text:
package com.cleveroad.slidingtutorial;

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;

/**
 * Indicator view.
 */
@SuppressWarnings("unused")
public final class TutorialPageIndicator extends View implements TutorialImpl.IndicatorPageListener {

    private static final float ANGLE_360 = 360f;

    static final int NO_VALUE = -1;
    static final int NO_COLOR = 1;
    @ColorInt
    static final int DEFAULT_ELEMENT_COLOR = Color.LTGRAY;
    @ColorInt
    static final int DEFAULT_SELECTED_ELEMENT_COLOR = Color.WHITE;

    private final RectF mClipBounds = new RectF();
    private final RectF mElementBounds = new RectF();
    private float mScrolledOffset;
    private int mSelectedPosition;
    private float mIndicatorElementSpacing;
    private float mIndicatorElementSize;
    private final Paint mIndicatorSelectedPaint = new Paint();
    private final Paint mIndicatorPaint = new Paint();
    private Renderer mRenderer;
    private int mPagesCount;
    private boolean mIsInfiniteScroll;

    public TutorialPageIndicator(Context context) {
        this(context, null);
    }

    public TutorialPageIndicator(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TutorialPageIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initDefaultSizes(context);

    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public TutorialPageIndicator(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        initDefaultSizes(context);
    }

    private void initDefaultSizes(@NonNull Context context) {
        mIndicatorElementSize = context.getResources().getDimension(R.dimen.st_indicator_size_default);
        mIndicatorElementSpacing = context.getResources().getDimension(R.dimen.st_indicator_spacing_default);
    }

    void initWith(@NonNull IndicatorOptions indicatorOptions, int pagesCount) {
        mIndicatorPaint.setAntiAlias(true);
        int elementColor;
        if (indicatorOptions.getElementColor() != NO_COLOR) {
            elementColor = indicatorOptions.getElementColor();
        } else {
            elementColor = TutorialPageIndicator.DEFAULT_ELEMENT_COLOR;
        }
        mIndicatorPaint.setColor(elementColor);

        mIndicatorSelectedPaint.setAntiAlias(true);
        int selectedElementColor;
        if (indicatorOptions.getSelectedElementColor() != NO_COLOR) {
            selectedElementColor = indicatorOptions.getSelectedElementColor();
        } else {
            selectedElementColor = TutorialPageIndicator.DEFAULT_SELECTED_ELEMENT_COLOR;
        }
        mIndicatorSelectedPaint.setColor(selectedElementColor);

        if (indicatorOptions.getElementSize() != NO_VALUE) {
            mIndicatorElementSize = indicatorOptions.getElementSize();
        }

        if (indicatorOptions.getElementSpacing() != NO_VALUE) {
            mIndicatorElementSpacing = indicatorOptions.getElementSpacing();
        }

        if (indicatorOptions.getRenderer() != null) {
            mRenderer = indicatorOptions.getRenderer();
        } else {
            mRenderer = Renderer.Factory.newCircleRenderer();
        }

        mPagesCount = pagesCount;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int halfSize = (int) (mIndicatorElementSize / 2f);
        int properHeight = (int) (mIndicatorElementSize + halfSize + mIndicatorElementSpacing * 2);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        if (heightMode == MeasureSpec.AT_MOST) {
            height = Math.min(height, properHeight);
        } else {
            height = properHeight;
        }
        setMeasuredDimension(width, height);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (changed) {
            updateClipBounds();
        }
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int count = mPagesCount;
        if (count == 0) {
            return;
        }
        float cx = canvas.getWidth() >> 1;
        float cy = canvas.getHeight() >> 1;
        int totalCount = 2 * count - 1;
        int halfCount = totalCount / 2;
        float itemWithOffset = mIndicatorElementSize + mIndicatorElementSpacing;
        float halfItemWithOffset = mIndicatorElementSize / 2 + mIndicatorElementSpacing;
        float halfSize = mIndicatorElementSize / 2f;
        float halfSpacing = mIndicatorElementSpacing / 2f;
        float startX = cx - halfCount * (mIndicatorElementSize + mIndicatorElementSpacing);
        float top = cy - halfSize;
        float bottom = cy + halfSize;
        // if we have odd elements - need to set indicators in center
        if (totalCount % 2 != 0) {
            startX -= halfSize + halfSpacing;
        }

        int i;
        for (i = 0; i < totalCount; i++) {
            // skip empty spaces
            if (i % 2 != 0) {
                continue;
            }
            float left = startX + (mIndicatorElementSize + mIndicatorElementSpacing) * i;
            float right = left + mIndicatorElementSize;
            mElementBounds.set(left, top, right, bottom);
            mRenderer.draw(canvas, mElementBounds, mIndicatorPaint, false);
        }

        // multiply on 2 because there are spaces between elements
        float activeItemOffset = (mSelectedPosition + mScrolledOffset) * 2;
        float left = startX + (mIndicatorElementSize + mIndicatorElementSpacing) * activeItemOffset;
        float right = left + mIndicatorElementSize;
        mElementBounds.set(left, top, right, bottom);
        canvas.clipRect(mClipBounds);
        canvas.save();
        canvas.rotate(ANGLE_360 * mScrolledOffset, mElementBounds.centerX(), mElementBounds.centerY());
        mRenderer.draw(canvas, mElementBounds, mIndicatorSelectedPaint, true);
        canvas.restore();

        if (mIsInfiniteScroll && mSelectedPosition == mPagesCount - 1) { // isInfinite && isEnd
            activeItemOffset = (1f - mScrolledOffset) * 2;
            left = mClipBounds.left - itemWithOffset * activeItemOffset + halfItemWithOffset;
            right = left + mIndicatorElementSize;
            mElementBounds.set(left, top, right, bottom);
            canvas.save();
            canvas.rotate(ANGLE_360 * mScrolledOffset, mElementBounds.centerX(), mElementBounds.centerY());
            mRenderer.draw(canvas, mElementBounds, mIndicatorSelectedPaint, true);
            canvas.restore();
        }
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, boolean isInfiniteScroll) {
        //Log.e("ViewPagerIndicator", "onPageScrolled: " + position);
        mSelectedPosition = position;
        mScrolledOffset = positionOffset;
        mIsInfiniteScroll = isInfiniteScroll;
        invalidate();
    }

    void setPagesCount(int pagesCount) {
        mPagesCount = pagesCount;
        updateClipBounds();
    }

    void updateClipBounds() {
        float cx = getWidth() >> 1;
        float cy = getHeight() >> 1;
        int totalCount = 2 * mPagesCount - 1;
        int halfCount = totalCount / 2;
        float halfSize = mIndicatorElementSize / 2f;
        float halfSpacing = mIndicatorElementSpacing / 2f;
        float startX = cx - halfCount * (mIndicatorElementSize + mIndicatorElementSpacing);
        float top = cy - halfSize - halfSpacing;
        float bottom = cy + halfSize + halfSpacing;
        // if we have odd elements - need to set indicators in center
        if (totalCount % 2 != 0) {
            startX -= halfSize + halfSpacing;
        }
        float itemWithOffset = mIndicatorElementSize + mIndicatorElementSpacing;
        float halfItemWithOffset = mIndicatorElementSize / 2f + mIndicatorElementSpacing;
        float left = startX - halfItemWithOffset;
        // multiply on 2 because we have offset at startX by 'halfItemWithOffset'
        float right = left + itemWithOffset * (totalCount - 1) + mIndicatorElementSize + halfItemWithOffset * 2;
        mClipBounds.set(left, top - halfSize, right, bottom + halfSize);
    }
}


text:
@implementation ToolTipMenu

@synthesize bridge = _bridge;

RCT_EXPORT_MODULE()

- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}

RCT_EXPORT_METHOD(show:(nonnull NSNumber *)reactTag
                  items: (NSArray *)items
                  arrowDirection: (NSString *)arrowDirection)
{
    UIView *view = [self.bridge.uiManager viewForReactTag:reactTag];
    NSArray *buttons = items;
    NSMutableArray *menuItems = [NSMutableArray array];
    for (NSString *buttonText in buttons) {
        NSString *sel = [NSString stringWithFormat:@"magic_%@", buttonText];
        [menuItems addObject:[[UIMenuItem alloc]
                              initWithTitle:buttonText
                              action:NSSelectorFromString(sel)]];
    }
    [view becomeFirstResponder];
    UIMenuController *menuCont = [UIMenuController sharedMenuController];
    [menuCont setTargetRect:view.frame inView:view.superview];

    [[NSNotificationCenter defaultCenter] addObserver:view selector:@selector(didHideMenu:) name:UIMenuControllerDidHideMenuNotification object:nil];

    if([arrowDirection isEqualToString: @"up"]){
      menuCont.arrowDirection = UIMenuControllerArrowUp;
    } else if ([arrowDirection isEqualToString: @"right"]){
      menuCont.arrowDirection = UIMenuControllerArrowRight;
    } else if ([arrowDirection isEqualToString: @"left"]) {
      menuCont.arrowDirection = UIMenuControllerArrowLeft;
    } else if ([arrowDirection isEqualToString: @"down"]) {
      menuCont.arrowDirection = UIMenuControllerArrowDown;
    } else {
      menuCont.arrowDirection = UIMenuControllerArrowDefault;
    }
    menuCont.menuItems = menuItems;
    [menuCont setMenuVisible:YES animated:YES];
}

RCT_EXPORT_METHOD(hide){
    UIMenuController *menuCont = [UIMenuController sharedMenuController];
    [menuCont setMenuVisible:NO animated:NO];
}

@end

redpajama_set_name: RedPajamaGithub


text:
package com.amazonaws.services.route53domains.model.transform;

import java.math.*;

import javax.annotation.Generated;

import com.amazonaws.services.route53domains.model.*;
import com.amazonaws.transform.SimpleTypeJsonUnmarshallers.*;
import com.amazonaws.transform.*;

import com.fasterxml.jackson.core.JsonToken;
import static com.fasterxml.jackson.core.JsonToken.*;

/**
 * DisableDomainTransferLockResult JSON Unmarshaller
 */
@Generated("com.amazonaws:aws-java-sdk-code-generator")
public class DisableDomainTransferLockResultJsonUnmarshaller implements Unmarshaller<DisableDomainTransferLockResult, JsonUnmarshallerContext> {

    public DisableDomainTransferLockResult unmarshall(JsonUnmarshallerContext context) throws Exception {
        DisableDomainTransferLockResult disableDomainTransferLockResult = new DisableDomainTransferLockResult();

        int originalDepth = context.getCurrentDepth();
        String currentParentElement = context.getCurrentParentElement();
        int targetDepth = originalDepth + 1;

        JsonToken token = context.getCurrentToken();
        if (token == null)
            token = context.nextToken();
        if (token == VALUE_NULL) {
            return disableDomainTransferLockResult;
        }

        while (true) {
            if (token == null)
                break;

            if (token == FIELD_NAME || token == START_OBJECT) {
                if (context.testExpression("OperationId", targetDepth)) {
                    context.nextToken();
                    disableDomainTransferLockResult.setOperationId(context.getUnmarshaller(String.class).unmarshall(context));
                }
            } else if (token == END_ARRAY || token == END_OBJECT) {
                if (context.getLastParsedParentElement() == null || context.getLastParsedParentElement().equals(currentParentElement)) {
                    if (context.getCurrentDepth() <= originalDepth)
                        break;
                }
            }
            token = context.nextToken();
        }

        return disableDomainTransferLockResult;
    }

    private static DisableDomainTransferLockResultJsonUnmarshaller instance;

    public static DisableDomainTransferLockResultJsonUnmarshaller getInstance() {
        if (instance == null)
            instance = new DisableDomainTransferLockResultJsonUnmarshaller();
        return instance;
    }
}


text:
package listing08

import (
	"net/http"
	"testing"
)

const checkMark = "\u2713"
const ballotX = "\u2717"

// TestDownload validates the http Get function can download
// content and handles different status conditions properly.
func TestDownload(t *testing.T) {
	var urls = []struct {
		url        string
		statusCode int
	}{
		{
			"http://www.goinggo.net/feeds/posts/default?alt=rss",
			http.StatusOK,
		},
		{
			"http://rss.cnn.com/rss/cnn_topstbadurl.rss",
			http.StatusNotFound,
		},
	}

	t.Log("Given the need to test downloading different content.")
	{
		for _, u := range urls {
			t.Logf("\tWhen checking \"%s\" for status code \"%d\"",
				u.url, u.statusCode)
			{
				resp, err := http.Get(u.url)
				if err != nil {
					t.Fatal("\t\tShould be able to Get the url.",
						ballotX, err)
				}
				t.Log("\t\tShould be able to Get the url.",
					checkMark)

				defer resp.Body.Close()

				if resp.StatusCode == u.statusCode {
					t.Logf("\t\tShould have a \"%d\" status. %v",
						u.statusCode, checkMark)
				} else {
					t.Errorf("\t\tShould have a \"%d\" status. %v %v",
						u.statusCode, ballotX, resp.StatusCode)
				}
			}
		}
	}
}


text:
package org.protorabbit.stats;

import java.util.Collection;

public interface IStat {
    public static enum types {
        VIEW,
        JSON
    };

    public long getTimestamp();
    public void setTimestamp( long timestamp );
    public Enum<?> getType();
    public void setType( IStat.types type );
    public String getRemoteClient();
    public void setRemoteClient( String remoteClient );
    public String getHost();
    public void setHost( String host );
    public String getRequestURI();
    public void setRequestURI ( String uri );
    public String getPathInfo();
    public void setPathInfo( String pathInfo );
    public String getPath();
    public void setPath( String path );
    public Long getContentLength();
    public void setContentLength( Long contentLength );
    public Long getProcessTime();
    public void setProcessTime( Long processTime );
    public void setContentType( String contentType );
    public String getContentType();
    public boolean hasErrors();
    public Collection<String> getErrors();
    public void setErrors( Collection<String> errors );
    public void setIsPoller( boolean pollerstat );
    public boolean isPoller();
}


text:
<!DOCTYPE html>

	<meta charset="utf-8">
	<title>Meu Horóscopo</title>
	<link href='http://fonts.googleapis.com/css?family=Pacifico' rel='stylesheet' type='text/css'>
	<link href='http://fonts.googleapis.com/css?family=Merienda+One' rel='stylesheet' type='text/css'>
	<link rel="stylesheet" type="text/css" href="style.css">

Meu Astral

Pré-Definições

				Signos de País:
				<select id='comboPais' onchange="signosCarregarPais(this.value)"></select>

				Signo:
				<select id='comboSigno'></select>

				Previsor:
				<select id='comboPrevisores' onchange="defCarregarDuracao(this.value)"></select>

				Tempo de Previsão:
				<select id='comboDuracao'></select>

			<button id="guardar" onclick="guardar()">Guardar</button>

			Voltar a Horóscopo


text:
package gitindex

import (
	"bytes"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sort"

	git "github.com/go-git/go-git/v5"
	"github.com/go-git/go-git/v5/config"
)

// CloneRepo clones one repository, adding the given config
// settings. It returns the bare repo directory. The `name` argument
// determines where the repo is stored relative to `destDir`. Returns
// the directory of the repository.
func CloneRepo(destDir, name, cloneURL string, settings map[string]string) (string, error) {
	parent := filepath.Join(destDir, filepath.Dir(name))
	if err := os.MkdirAll(parent, 0o755); err != nil {
		return "", err
	}

	repoDest := filepath.Join(parent, filepath.Base(name)+".git")
	if _, err := os.Lstat(repoDest); err == nil {
		return "", nil
	}

	var keys []string
	for k := range settings {
		keys = append(keys, k)
	}
	sort.Strings(keys)

	var config []string
	for _, k := range keys {
		if settings[k] != "" {
			config = append(config, "--config", k+"="+settings[k])
		}
	}

	cmd := exec.Command(
		"git", "clone", "--bare", "--verbose", "--progress",
	)
	cmd.Args = append(cmd.Args, config...)
	cmd.Args = append(cmd.Args, cloneURL, repoDest)

	// Prevent prompting
	cmd.Stdin = &bytes.Buffer{}
	log.Println("running:", cmd.Args)
	if err := cmd.Run(); err != nil {
		return "", err
	}

	if err := setFetch(repoDest, "origin", "+refs/heads/*:refs/heads/*"); err != nil {
		log.Printf("addFetch: %v", err)
	}
	return repoDest, nil
}

func setFetch(repoDir, remote, refspec string) error {
	repo, err := git.PlainOpen(repoDir)
	if err != nil {
		return err
	}

	cfg, err := repo.Config()
	if err != nil {
		return err
	}

	rm := cfg.Remotes[remote]
	if rm != nil {
		rm.Fetch = []config.RefSpec{config.RefSpec(refspec)}
	}
	if err := repo.Storer.SetConfig(cfg); err != nil {
		return err
	}

	return nil
}


text:
@interface nationalityViewController : BaseViewController
@property (nonatomic, copy) NSString *sess_ID;

@end


text:
<!doctype html>

	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<title>SwitchButton | My project title</title>
	<meta name="description" content="">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<link rel="stylesheet" href="../assets/css/main.css">

						Search
						<input id="tsd-search-field" type="text" />

Preparing search index...

The search index is not available

					My project title

						Options

								All

Public

Public/Protected

All

							<input type="checkbox" id="tsd-filter-inherited" checked />
							Inherited
							<input type="checkbox" id="tsd-filter-externals" checked />
							Externals
							<input type="checkbox" id="tsd-filter-only-exported" />
							Only exported

					Menu

					Globals

					"module/actuator/switch"

					SwitchButton

Interface SwitchButton

Hierarchy

						SwitchButton

Implemented by

MockSwitch

RestSwitch

Index

Methods

blink

off

on

Methods

blink

blink(): any

Defined in module/actuator/switch.ts:6

Metodo que cambia el estado del interruptor de on a off automaticamente tras un pocos segundos

Returns any

off

off(): any

Defined in module/actuator/switch.ts:16

Método que apaga el interruptor

Returns any

on

on(): any

Defined in module/actuator/switch.ts:11

Método que enciende el interruptor

Returns any

						Globals

						"factory/<wbr>Accessory<wbr>Factory"

						"factory/<wbr>Actuator<wbr>Factory"

						"factory/<wbr>Sensor<wbr>Factory"

						"main"

						"module/accesory/<wbr>Accessory"

						"module/accesory/impl/<wbr>Garage<wbr>Accesory"

						"module/accesory/impl/<wbr>Light<wbr>Accessory"

						"module/accesory/impl/<wbr>Sensor<wbr>Accessory"

						"module/accesory/impl/<wbr>Thermostat<wbr>Accessory"

						"module/actuator/impl/<wbr>Mock<wbr>Switch"

						"module/actuator/impl/<wbr>Rest<wbr>Switch"

						"module/actuator/switch"

						"module/sensor/impl/<wbr>Mock<wbr>Sensor"

						"module/sensor/impl/<wbr>Rest<wbr>Sensor"

						"module/sensor/read"

						"util/<wbr>Notification<wbr>Sender"

						"util/<wbr>Rest<wbr>Util"

						Switch<wbr>Button

								blink

								off

								on

Legend

Module

Object literal

Variable

Function

Function with type parameter

Index signature

Type alias

Enumeration

Enumeration member

Property

Method

Interface

Interface with type parameter

Constructor

Property

Method

Index signature

Class

Class with type parameter

Constructor

Property

Method

Accessor

Index signature

Inherited constructor

Inherited property

Inherited method

Inherited accessor

Protected property

Protected method

Protected accessor

Private property

Private method

Private accessor

Static property

Static method

Generated using TypeDoc


text:
package org.anodyneos.xpImpl.runtime;

import java.beans.Beans;
import java.io.IOException;

import javax.servlet.jsp.el.ELException;

import org.anodyneos.xp.XpContext;
import org.anodyneos.xp.XpException;

/**
 * @author jvas
 */
public class XPTagNewBeanHelper {

    private XPTagNewBeanHelper() {
        super();
    }

    public static void newBean(XpContext xpContext, String var, String scope, String className) throws XpException, ELException {

        try {
            Object obj = Beans.instantiate(Thread.currentThread().getContextClassLoader(), className);
            xpContext.setAttribute(var, obj);
        } catch (ClassNotFoundException e) {
            throw new XpException(e);
        } catch (IOException e) {
            throw new XpException(e);
        }
    }

}


text:
\chapter{Current State of Online \LaTeX Editors and the Imposed Requirements on them}
This chapter is aimed at the elicitation of the status quo of other collaborative editors and users' expectations towards them.

First and foremost other existing solutions will be reviewed and then the requirements to a online \LaTeX editor elicited. Finally the elicited requirements and research findings are analysed.

\section{Review of Existing Online \LaTeX Editors}
\label{sec:existing-solutions}
There are two existing solutions, both open source software and can be freely downloaded and installed. They target the same problem as this work, which is providing a collaborative real-time online editor for \LaTeX documents, that is as the same time suitable for self-hosting.

The first solution, \name{FlyLatex}, is a one-man-project developed by Daniel Alabi and started in 2012, to counter the lack of collaborative real-time \LaTeX environments. It matured until mid 2013, since where there were fewer updates although the project is still being actively developed \cite{website:flylatex-commits}.

The second solution, \name{ShareLaTex}, originated from a project called \name{ScribTex}, which was the first iteration of an online \LaTeX editor, though not a collaborative one, and published in 2008. \name{ShareLaTex} is the redevelopment and -implementation of that basic concept \cite{website:scribtex} \cite{website:sharelatex}.

Being run as a website that is free to use for up to two project members but sells subscriptions plans for projects with more members, its code base was published as open source in mid-February 2014, parallel to the draft of this work \cite{website:sharelatex-oss}.

However, the website continues to be still run as a freemium model, meaning that the basic functionalities are free to use but more extensive features are only available when paying for them.

The architecture and implementation details of each solution will be illuminated hereafter and the findings presented in a nutshell at the end.

\subsection{FlyLatex}
\label{subsec:flylatex}
FlyLatex is developed in Node.js, a lightweight, server-side platform for network applications, built on Google Chrome's JavaScript. It is intended to help implementing data-intensive, fast, scalable applications for real-time applications with its event-driven, non-blocking I/O model \cite{website:node-js}. Moreover, the built-in asynchronous I/O library for file, socket and HTTP communication allows Node.js to act as a stand-alone web server.

Node.js was originally written and initially released on May 27th, 2009 by Ryan Lienhart Dahl. The most recent stable release, as of May 2014, is version 0.10.28.

Node.js' key feature is its performance and concurrency, which works the following way: It uses a cross-platform library that is provided by all major operating systems and abstracts system calls for asynchronous (non-blocking) input/output. Node.js is single-threaded and tells the operating system that it should be notified upon new connections. Right after that, it immediately goes to sleep and when a new connection is made, a callback is executed and the actual work then performed by Node.js.

This results in non-blocking processes, as no function in Node.js is performing input/output operations directly. That way, there are no dead-locks. In addition, it is more memory-efficient in contrast to most other programming languages concurrency models. They usually allocate memory for each new thread and connection, while in Node.js each connection allocates only a small heap.

In short, Node.js excels for thousands of concurrent connections. This is due to the fact that web servers spent a lot ot their time waiting for network or disc access, which is not CPU intensive, and Node.js performs especially well in this area. Thinking in \nameref{subsec:cloud-service-models}, it can be seen as \nameref{subsubsec:paas}, as it also provides a platform to run applications on and shares the suitablity for short-living processes.

But to return to FlyLatex: Being built on the well-illustrated Node.js and written in JavaScript, it makes use of various other technologies such as the \name{ACE Editor}, an embeddable code editor written in JavaScript, that supports syntax highlighting for over 110 languages, code completion and themes among other things \cite{website:ace-editor}. It was developed by Cloud9 for their online IDE and is published as open source on GitHub \cite{website:ace-github}.

To provide collaborative editing, FlyLatex integrates \name{ShareJS}, an operational transform (compare chapter \ref{subsubsec:operational-transform}) library for browsers and Node.js, that adds support for concurrent live editing \cite{website:sharejs}. It was written by Joseph Gentle in 2011, an ex-engineer of Google Wave, which was one of the first major products that featured collaborative editing. But it was closed by Google in 2012, due to the lack of popular demand, and is now an Incubator Project of Apache \cite{website:googlewave-status} \cite{website:apache-wave}. ShareJS is also hosted on GitHub \cite{website:sharejs-github}.

To display Portable Document Files, a viewer called \name{PDF.js} is integrated into FlyLatex. First being started by the Mozilla Foundation as an HTML5 technology experiment that explored building a precise and efficient renderer without native code assistance, it is now officially used in the Firefox browser as default plugin.

Its major features are a search function, jump to page, zooming, fullscreen view, printing and bookmark support, save as file. Among the extensive features is also the localisation for various languages.

For data storage, FlyLatex relies on \name{MongoDB}, a document-oriented NoSQL database \cite{website:mongo-db}.

FlyLatex is hosted on GitHub \cite{website:flylatex-github}.

After an overview of the technical aspects, the functionalities and implementation will now be discussed. The following features are the ones that FlyLatex describes itself with \cite{website:flylatex-github}:

\begin{itemize}
	\item{Real-time collaboration}
	\item{Real-time status updates on priveleges of documents}
	\item{Online compilation of \LaTeX to \fileformat{PDF}}
	\item{Online \LaTeX debugging}
	\item{Manipulation of compiled \fileformat{PDF}s}
	\item{Sharing of \fileformat{PDF}s}
	\item{Option to use images or additional packages like .sty files}
\end{itemize}

Another point is missing on this list though. FlyLatex can be self-hosted on one's own Node.js server and only requires some configuration for the connection to a running MongoDB instance. This is of major importance, as one must not hand over control of sensitive data and confidential documents to other cloud providers. At the same time, information security is also maximised.

After deploying FlyLatex on Node.js and accessing the webpage in the browser, the landing page shows a login as well as the possibility to sign-up for the service. On successful login, the main page compromises of a simple document management and very basic message center where notifications of changes in documents can be seen. The exisiting documents are listed with their rights (read/write) and can be deleted or shared. New documents can be created as well.

When sharing documents, the field uses auto-complete on the exisiting users, making it easier to find each individual person. This person then receives a notification, accessible in the message center, and the user is able to either accept or decline the access to the document.

But the core part of FlyLatex is the document editing. The editor comes with syntax highlighting and is displayed full-page. If users edit the document collaboratively, text changes are immediately applied and displayed in other users' browsers that are also working on this document, meaning there is hardly any delay. Although changes are auto-saved they are not persisted in the database, effectively resulting in loss of data when internal server errors occur or it is shutdown, it was just written to volatile memory. Changes are only persisted when explicitly clicking the document's save button.

\pagebreak

To be able to compile documents, the \fileformat{PDF} view must be activated. It provides a button to compile the document, download the \fileformat{PDF} and view the compilation log. The latter is displayed as a small overlay and can be browsed by going back and forth to each log extract. The result of the compilation, the successfully created \fileformat{PDF}, is shown in a preview right next to the editor.

\begin{figure}[H]
	\centering
		\includegraphics[width=\textwidth]{images/flylatex.png}
	\caption{FlyLatex' document editing and compilation view}
\end{figure}

If there are errors during the compilation, a notification is displayed and the log can be consulted to figure out the cause. When a document was not compiled for the first time, the last successfully compiled \fileformat{PDF} is still shown and the preview not updated.

The actual compilation is achieved by calling the console to execute the transformation of the \LaTeX document. That is why FlyLatex is expecting PDFLatex to be installed, as it is the utilised engine and hard-wired in the source code:

\begin{lstlisting}[language=JavaScript, frame=none, numbers=none, caption=Latex Compilation in FlyLatex]
exec("pdflatex -interaction=nonstopmode "+ inputPath +" > /dev/null 2>&1",
afterCompile);
\end{lstlisting}

The \parameter{nonstopmode} specifies that the compilation will not be stopped by PDFLatex upon errors, while \parametertype{/dev/null 2>\&1} is redirecting the outputs of the console, resulting in all standard output to be repressed (signifies the compilation log) and only errors being displayed on the console.

Finally, \parameter{afterCompile} is the name of the callback function that will be executed after successful execution of the command. The actual source code of it will not be listed, but this function reads in the \fileformat{PDF} file and makes it accessible under a unique Uniform Resource Identifier (\abk{URI}{Uniform Resource Identifier}), then reads the log as well and sends both to its own REST services. Finally, it presents the log and file to the user by showing both on the webpage.

Analysing all these information, there are several downsides to this approach:

The handling of documents is rather complicated. To change between documents, one has to go back to the main page and then select a different document to open it.

A document is a stand-alone file, there is no possibility to structure it by seperating it into more \LaTeX files or include others. That way, bibliography management is not supported as well.

The log is only accessible in a small overlay dialog and when trying to skip to the end, the next page button must be clicked several times.

That shared documents have first be accepted or declined in the somewhat hidden message center also adds to the perception of a lacking user experience.

The parallel view of the document and the compiled \fileformat{PDF} is a good approach, but missing controls for zoom. Therefore a detailed examination of the output is not possible for the user, who is left with a rather vague impression about the rightfulness of the created \fileformat{PDF} file.

In conclusion, the bare collaborative document editing and document sharing is working excellent, but advanced functions such as multi-file documents, import, bibliography management and extensive \LaTeX support and tools are missing, preventing a pleasent user experience.

\subsection{ShareLaTex}
\label{subsec:sharelatex}
First and foremost, ShareLaTex cannot be equivalently compared to FlyLatex, as the former is the result of a capital-backed, longstanding project with full-time commitment of its developers. So thinking of ShareLaTeX, the sale of subscriptions makes it actually rather a business model than an open-source project \cite{website:sharelatex-team} \cite{website:sharelatex-subscriptions}. The latter is especially true as FlyLatex used to be the solely available open source online editor, with ShareLaTex being freely available only since shortly, February 2014.

The decision to go open source is justified by the developers in the following way \cite{website:sharelatex-oss}:

\begin{quotation}
As a small team, we're constantly receiving feature requests that we'd love to implement but don't have the time. We've also had a lot of offers from willing volunteers who we've had to turn away because we didn't have a framework for people to contribute. I hope that by open-sourcing ShareLaTeX we can empower our brilliant community to help improve ShareLaTeX in the ways that you want, without having to wait for the two of us to work down our todo list. \\

A lot of people have asked to host ShareLaTeX internally due to company guidelines or data privacy concerns. We don't have the resources to support licensed installs at the moment, but we also hate having to say no. With an open-source version of ShareLaTeX, now anyone who wants to run it locally can.
\end{quotation}

ShareLaTex is hosted on GitHub and consists of several subprojects and services: For the web interface, application of updates on documents, \name{Common LaTeX Service Interface} (\abk{CLSI}{Common LaTeX Service Interface}) for the compilation of \LaTeX documents, \abk{CRUD}{Create, Read, Update and Delete} operations (create, read, update, delete) operations and tracking and storing updates for documents \cite{website:sharelatex-github}.

It mostly relies on the same established technologies as FlyLatex (compare chapter \ref{subsec:flylatex}), such as Node.js, MongoDB, AceEdtior and PDF.js.

Having said this, it makes use of one additional technology, \name{Redis}, a key-value-store used as data structure server. It is used to perform atomic operations on various data types such as Strings, Hashes, Lists, Sets and Sorted Sets, which are kept as in-memory datasets. Such operations would for instance be: appending to a String, pushing to a List, computing Set intersection, union, difference and so on \cite{website:redis}.

Before running ShareLaTex on Node.js, it must be assured that the Redis and MongoDB services are running, a suitable \LaTeX environment is installed and also a specific version of the \name{latexmk} package.

The \name{latexmk} package can be used in two ways. On the one hand, to detect the correct order and amount of times to compile a document. For example when there is a bibliography and a nomenclature, the execution order would be \method{pdflatex bibtex pdflatex makeindex pdflatex} as the document has to be first compiled. Then the citation references would be set by \method{bibtex}, added to the document in the second compilation step and finally the same would apply for the nomenclature with the last two commands.

On the other hand, \name{latexmk} is even more powerful as it can be used to watch \TeX files for changes and run the necessary commands to re-compile the \fileformat{PDF} automatically.

ShareLaTex comes with several matured functionalities. In addition to the basic CRUD operations, it also supports the inclusion of other files or  even structuring a project with subdirectories. There are various ways to share documents, either with specific users - for which their e-mail has to be entered - or by URI. If the latter is chosen, projects can be made either publicly readable or editable, providing also access to users outside of the platform. Besides, exisiting projects can be download and new projects imported as ZIP file.

There are also specific project settings, as for the spellchecking language of documents, setting the main document and which compiler (PDFLaTeX, LuaTeX, XeLaTeX) to use, whereas some features are exclusively available to the website. Such as the newly introducted integration of DropBox, templates, the help and a \LaTeX tutorial.

\pagebreak

But the centrepiece is the document editing view, which also combines the preview of the compilated \fileformat{PDF} and raw compilation log. There are, from left to right, a foldout sidebar with icons for the code, history, sharing and settings of the document, the project file tree where files can be added, renamed, deleted, the editor containing the document's \LaTeX code and the mentioned preview for \fileformat{PDF} and log.

\begin{figure}[h!]
	\centering
		\includegraphics[width=\textwidth]{images/sharelatex-editing.png}
	\caption{ShareLaTex' document editing and compilation view}
	\label{sharelatex-editing-view}
\end{figure}

As ShareLaTex makes use of the same most commonly used and proven library \name{ShareJS} to enable collaborative editing, changes in documents can be seen instantly in other browsers. If a document is edited by several individuals, each user's current cursor position is shown in a different colour to make it clearly recognisable on which part of the document he is presently working. Changes are instantaneously persisted in the database, code completion is provided by the editor.

When there are errors during compilation, they are automatically extracted from the log and presented in summary, with description and cause. As a matter of course the raw log output can be viewed was well.

\begin{figure}[h!]
	\centering
		\includegraphics[width=0.66\textwidth]{images/sharelatex-error.png}
	\caption{ShareLaTex' summarises errors with description and cause}
\end{figure}

Document compilation is quick and the preview has, unlike FlyLatex, also zoom buttons to take a closer look at the \fileformat{PDF}. The split view of document code and \fileformat{PDF} can be switched to a single view, where either the editor or preview is shown on the entire screen. The sidebar and project file tree remain displayed though.

A rather sophisticated feature is the possibility to click either on parts of the document to see the corresponding code passages or the other way around, where for any code passage the according output in the \fileformat{PDF} is highlighted in a pale yellow tone (as can be seen on the upper right in figure \ref{sharelatex-editing-view}).

If document changes shall be tracked, there is a history where changes are depicted in a timeline. Each modification is shown with time and the user causing it on a sidebar on the right. When clicking on one of these entries, the document's version as of that point in time is displayed in the editor. User's changes are represented in a different color, actually showing a diff of the document. This is quite helpful to spot changes immediately. With this functionality comes also the option to restore the document back to its state of that given point. All in all, this is equivalent to a basic revision control system.

\begin{figure}[h!]
	\centering
		\includegraphics[width=\textwidth]{images/sharelatex-history.png}
	\caption{ShareLaTex' document history view}
\end{figure}

Finally, there are even user settings where the preferred editor theme, font size, key binding can be adjusted, autocompletion switched on or off as well as the user's data and password reset.

The implementation of the compilation is quite similiar to FlyLateX', the process is spawned directly from the command line. Because of the more complex architecture and distributed code base of ShareLaTeX, the actual source code will only be shown in excerpts and for the compilation engine \name{PDFLaTeX}.

\pagebreak

\begin{lstlisting}[language=JavaScript, frame=none, numbers=none, caption=Latex Compilation in ShareLaTeX]
_latexmkBaseCommand: ["latexmk", "-cd", "-f", "-jobname=output", "-auxdir=$COMPILE_DIR", "-outdir=$COMPILE_DIR"]:
return LatexRunner._latexmkBaseCommand.concat(["-pdf", "-e", "$pdflatex='pdflatex -synctex=1 -interaction=batchmode %O %S'", Path.join("$COMPILE_DIR", mainFile)]);
[...]
}).call(this);
\end{lstlisting}

Again, the \parameter{nonstopmode} is used to make the compilation not hold upon errors, as well as a callback function is executed on completion. The major differences are the use of \name{latexmk} (as mentioned earlier a package for automatic document (re-)compilation) and the parametrisation of the compilation engine (here \name{PDFLaTeX}).

Evaluating ShareLaTex' implementation and features, the collaborative nature of its service is ubiquitously noticeable in several functionalities such as the history. It is one of ShareLaTex' strong points, together with document editing, hierarchical structuring, sharing and performance. But there are also weaknesses regarding the support of bibliography and \LaTeX functions, although the latter is partly implemented by the editor's code completion. Nevertheless, ShareLaTex provides a good user experience with all necessary basic functions and even rather useful additional features.

\subsection{Findings}
Analysing the findings for both existing solutions, \nameref{subsec:flylatex} and \nameref{subsec:sharelatex}, there are several similiarities because of their use of the almost same technologies.

Both are based on Node.js, which performs and scales very well as lightweight, server-side platform for network applications. It is well-suited as the creation of diffs and application of patches on texts is not very CPU intensive, although the \LaTeX to \fileformat{PDF} compilation is, to a certain amount.

They also share their approach of document compilation: First the command is executed on the console and then a callback function used to process the output further.

Collaborative editing works like a charm on ShareLaTeX and FlyLatex by using ShareJS, there are no noticeable delays and document changes are always applied in the correct way.

Regarding all functions beyond the basics, ShareLaTeX excels FlyLatex in the user experience and the provisioning of useful tools by far. This is obviously the result of long dedication to the project and capital-backed development, while FlyLatex must be seen as what it is: a spare time project of a single developer.

Having been closed-source for most of it's development lifespan, ShareLaTex was a late competitor to the race but is now the leading open-source \LaTeX editor for people or organisations who are dedicated to keep their private data in their own hands.

However, as can be seen in the next section, neither of the solutions fulfills all requirements for such a collaborative online \LaTeX editor. And above all else, they would also not satisfy the need for an application that utilises the exisiting infrastucture (compare chapter \ref{sec:scope-and-aim} and chapter \ref{sec:approach-and-decision}) of the Institute of Telematics.

\section{Technical Constraints and Software Requirements}
For the development of a cloud-based \LaTeX editor, there are some technical constraints, predefined by the Institute of Telematics' computing resources, as well as software requirements - be it implicit requirements declared in advance to this work or the one's defined in the preliminary stages by inquiry of the future users.

In the following sections, both contraints and requirements are evaluated to work out the implications for the outcome of this work. First off, the computing resources, topology and technology of the Institute of Telematics' Cloud Computing Lab are treated, then followed by the elaboration of functional and implicit requirements in the next section.

\subsection{Technical Constraints}
\label{subsec:technical-constraints}
The technical contraints consist of various factors such as computing resources, so existing hardware, its arrangement, network topology and ultimately its configuration, especially the systems' architectures, operating systems and middlewares.

These are the variables that will be looked at throughout the following subsections, although it must be noted that only the parts closely related to this work will be reviewed in detail.

\subsubsection{Computing Resources}
\label{subsubsec:computing-resources}
The Cloud Lab's infrastructure is made up of a heterogenous array of computers and servers, ranging from older AMD64 or Intel Core 2 Duo with 2GB of RAM to the new generation of Intel Core i7 with 8GB RAM and therefore reflecting the variances in Cloud Computing systems in a realistic way.

The topology can be roughly divided into four parts: There are the firewall and the \abk{DNS}{Domain Name System} servers, ensuring network communication and protection of the affiliated systems and then workstations for employees and students. Its most central part though are the different clouds to test a diversity of different infrastructures.

For such purposes, there are two main clouds, one is based on OpenStack, the other one on Eucalyptus, and then there are two test clouds where more recent versions or new developments in the Cloud Computing landscape can be installed and examined \cite{website:openstack} \cite{website:eucalyptus}. \\
All the mentioned components of the lab can be seen in the network topology below.

\begin{figure}[H]
	\centering
		\includegraphics[width=\textwidth]{images/itm-topology.pdf}
	\caption{The topology of the University of L\"ubeck's Institute of Telematics' Cloud Computing Lab}
\end{figure}

Subsequently, only the OpenStack cloud and its characteristics will be regarded as it is the most suitable cloud, which will be explained alongside the depiction of its architecture. For further information on the comparision of different open source Clouds compare the preceding bachelor thesis of Thomas Moritz \cite{thomas2013cloud}.

It should be pointed out that details on the actual configuration are omitted, as this work takes a fully configured and working system as starting point, which is the case with the ITM Cloud Computing Lab.

\subsubsection{OpenStack}
\label{subsubsec:openstack}

OpenStack began in 2010 as mutual project of the NASA and Rackspace Hosting and is now established as non-profit foundation, with many major tech companies like Microsoft, IBM, Oracle or Red Hat being contributers and members of the project. It consists of the components:

\begin{itemize}
	\item{\name{Horizon} serves as a dashboard, a web front-end to manage and control the Cloud and its services}
	\item{\name{Nova} is executing the virtual machines}
	\item{\name{Swift} persists objects and is a highly scalable system where user and instances can store data}
	\item{\name{Glance} manages images and snapshots of virtual machines}
	\item{\name{Keystone} is used for authentification and rights management}
	\item{\name{Quantum} controls the routing and network}
	\item{\name{Cinder} is a block storage that provides logic volumes}
\end{itemize}

The interdependency and relation between these components can be seen in the following graph.

\begin{figure}[h!]
	\centering
		\includegraphics[width=0.9\textwidth]{images/openstack-architecture.png}
	\caption{The architecture and component relations of OpenStack \cite{website:wikimedia-openstack-conceptual}}
\end{figure}

As this is a bit abstract to grasp, there is also a more simplyfied version showing how {OpenStack} provides the basis to build applications on top of it.

\begin{figure}[H]
	\centering
		\includegraphics[width=\textwidth]{images/openstack-software-diagram.pdf}
	\caption{Simplyfied OpenStack software diagram \cite{website:openstack-sw-diagram}}
\end{figure}

OpenStack is acting as IaaS and implements simple and massively scaleable cloud services that can be used to provide public or private clouds (compare \nameref{subsec:cloud-deployment-models}, chapter \ref{subsec:cloud-deployment-models}). As can be seen from the graphics, such services include the creation of pools for compute, storage and network resources, which can then be used to virtualise one's server hardware. This happens in a way, that the virtualisation layer abstracts the resource management and specifics of the existing hardware, making both of no concern to the consumer.

The advantages are apparent: While OpenStack is simple to integrate with any hardware, easy to manage and monitor, secure and an industry-wide standard, the systems build on OpenStack are also very elastic, highly available and realiable.

\subsection{Software Requirements}
\label{subsec:software-requirements}
In a software project, requirements engineering, namely the formulation, collection, documentation and maintenance of software requirements, is certainly the most vital part, being not much different for this work.

There are two main stakeholders, first the users and secondly the operators. While most requirements originate from the users, there were also some requirements couched by the operators. This is potentially leading to conflicts of interest and will be described later, but first all requirements are listed. They are documented as they arised, starting with implicit requirements and followed by the functional ones.

\subsubsection{Implicit Requirements}
\label{subsubsec:implicit-requirements}
There are a number of implicit requirements that were already partially discussed in section \ref{sec:scope-and-aim}, \nameref{sec:scope-and-aim}. These are basic conditions that were defined prior to this work with the supervisor.

To begin with, the application is supposed to run as SaaS. Secondly, it is vital that different users can not only edit documents together but also simultaneously, making the collaborative aspect of the application its most important feature.

When desired, the current \TeX document has to be compiled and the result shown to the user. Document changes shall be backed by the usage of a version control system that ensures all document revisions are stored and can be restored.

Lastly, access should solely be granted to users of the Institute of Telematics, who will use their exisiting \name{Lightweight Directory Access Protocol} (\abk{LDAP}{Lightweight Directory Access Protocol}) accounts for authentification.

\subsubsection{Functional Requirements}
\label{subsubsec:functional-requirements}
While all these implicit requirements are primarily shaping the architecture of the system, the actual features are defined by functional requirements which are compiled of the later users' requests and needs.

To gather these data, a questionnaire with a list of possible features was prepared. Each functionality could be ranked on a scale from 1, \textit{not so important}, to 10, \textit{very important} and additional remarks or feature requests be made.

There was a total of 21 questions and a response from 18 individuals, with the highest rating being a 8.7 and the lowest a 4.2. The arithmetic mean was 6.8 and the median 7.0.

Based on their values, these functionalities were prioritised and divided into three majors groups: \textit{high priority}, \textit{medium priority} and \textit{low priority}. The size of each group was arranged after the arithmetic mean, respectively median, so that the group of highest prioritisation has five functionalities and a arithmetic mean and median of 8.1.

\begin{table}[H]
	\begin{center}
		\footnotesize
		\setlength\extrarowheight{5pt}
		\rowcolors{1}{}{lightgray}
		\begin{tabular}{ p{11cm} cp{1.5cm} }
		  	\textbf{Functionality} 	  														& \textbf{Rating} \\
			\hline
			Undo/Redo of edits																& 8.7 \\
			Support of bibliography/BibTeX management										& 8.3 \\
			Viewable log of the compilation													& 8.3 \\
			Automatic background save while editing (e.g. every five minutes)				& 8.1 \\
			Tabs for multiple opened documents and parallel editing							& 8.0 \\
		\end{tabular}
		\caption{Functionalities with high priority}
		\label{tab:high-priority}
	\end{center}
\end{table}

While the group with medium priority has the same arithmetic mean and median as the overall results of 6.8 and 7.0, consisting of six priorities.

\begin{table}[H]
	\begin{center}
		\footnotesize
		\setlength\extrarowheight{5pt}
		\rowcolors{1}{}{lightgray}
		\begin{tabular}{ p{11cm} cp{1.5cm} }
		  	\textbf{Functionality} 	  														& \textbf{Rating} \\
			\hline
			Download of single files/the whole project										& 7.8 \\
			Full-text search over all documents												& 7.6 \\
			Import function for existing \LaTeX projects									& 7.3 \\
			Code completion similiar to an IDE												& 7.1 \\
			Notifications on changes made by other users or their activities				& 7.1 \\
			Download of single files/the whole project										& 7.0 \\
		\end{tabular}
		\caption{Functionalities with medium priority}
		\label{tab:medium-priority}
	\end{center}
\end{table}

All other proposed functionalities form the group of lowest prioritisation, including ten features. This group has an arithmetic mean of 5.5 and median of 5.7.

\begin{table}[H]
	\begin{center}
		\footnotesize
		\setlength\extrarowheight{5pt}
		\rowcolors{1}{}{lightgray}
		\begin{tabular}{ p{11cm} cp{1.5cm} }
		  	\textbf{Functionality} 	  														& \textbf{Rating} \\
			\hline
			Rights management for documents (not accessible for others, share with user)	& 6.5 \\
			Preview of the document as parallel view of \LaTeX and \fileformat{PDF}			& 6.5 \\
			Existing logins can be used (authentification by LDAP)							& 6.1 \\
			Toolbar for the most common commands (bold text, section, figure et cetera)		& 6.1 \\
 			Capability to print documents													& 6.1 \\
			Personalised settings of editor appearance (font size, theme and so on)			& 6.0 \\
			Collection of formulas, extended commands, symbol tables						& 5.7 \\
			Bookmarks/markers can be set in documents				 						& 5.3 \\
			\LaTeX templates to follow the ITM conventions									& 5.0 \\
			Syntax highlighting for other languages except \LaTeX							& 4.2 \\
		\end{tabular}
		\caption{Functionalities with low priority}
		\label{tab:low-priority}
	\end{center}
\end{table}

These functional requirements defined by the users are accompanied by the requests and needs of the other stakeholders, the operators:

When using \LaTeX engines for the compilation of documents, they are executed via command line. Granting access for a process or application to the command line is always a security risk, so instead of direct interaction with the shell, an alternative should be achieved by all means.

\section{Analysis of the Elicited Requirements and Research Findings}
The \nameref{sec:existing-solutions} and the functional requirements (compare chapter \ref{subsec:software-requirements} et seqq) for such a  collaborative editor gave diverse insights of established systems and users' expectations towards them.

To make these components or aspects more accessible, they are divided into different groups regarding such an editor, before contemplating their implications for the development of a collaborative online \LaTeX editor.

\begin{description}
	\item[Architecture] \hfill \\
		The editor must be developed as Software as a Service.
	\item[Editor] \hfill \\
		Collaborative, simultaneous editing is an implicit requirement and therefore a must. \\
		Undo/Redo of edits, automatic saving while editing, tabs for multiple opened documents, code completion, syntax highlighting for other languages except \LaTeX are functional requirements.
	\item[Handling of LaTeX files] \hfill \\
		Compilation of \LaTeX files and showing the output to the user is an implicit requirement and therefore a must. \\
		A viewable log of the compilation, support of a bibliography, an import function for existing \LaTeX files, download of single files/the whole project are functional requirements.
	\item[Sharing] \hfill \\
		Rights management for documents and notifications on changes made by other users are functional requirements.
	\item[Personalisation] \hfill \\
		Authentification by existing LDAP accounts is an implicit requirement and therefore a must. \\
		Personalised settings of editor appearance (font size, theme and so on) and \LaTeX \linebreak templates to follow the ITM conventions are functional requirements.
	\item[User Experience] \hfill \\
		Tracking document changes with a version control system is an implicit requirement and therefore a must. \\
		A full-text search over all documents, preview of the document as parallel view of \linebreak \LaTeX and \fileformat{PDF}, capability to print documents, toolbar for the most common commands, collection of formulas and extended commands, bookmarks in documents are functional requirements.
\end{description}

To develop the application as \nameref{subsubsec:saas} limits the architectural choices, as does the fact that \nameref{subsubsec:openstack} is used in the ITM Cloud Computing Lab. To mention it again, both existing solutions are developed on \name{Node.js}.

In addition to it, \nameref{subsec:sharelatex} and \nameref{subsec:flylatex} equal themselves in two other integral parts. For the editor, \name{ACE Editor} is used, to compute and apply the right \nameref{subsubsec:operational-transform} steps, \name{ShareJS}. Both the editor and the collaboration library are too complex to develop them from scratch, so it is inevitable to make use of frameworks or libraries or embed existing applications.

The handling of \LaTeX files must be accomplished in a transparent way that seems intuitive to the user. It must be possible for him to work in an accustomed manner, for instance including other \LaTeX files, images and bibliography, while also providing functionalities to import data to and export data from the application.

As major enabler of collaboration, sharing functionality bases on document rights as well as the detailed illustration of changes performed on the document.

Personalisation can only occur when user accounts are integrated into the application and it encompasses of settings for editor theme, font size and so forth, but also document templates.

The analysing of \nameref{subsec:sharelatex} and \nameref{subsec:flylatex} emphasised the importance of functionalities and user interfaces that assist users and encourage them to take advantage of the broad range of auxiliary tools that are being provided. It must be said that both were lacking in this area, \nameref{subsec:flylatex} even more than \nameref{subsec:sharelatex}, but also the latter did not provide \LaTeX specific toolbars and menus.


text:
suite("AppRouter",function() {
})


text:
import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  Image,
  ListView,
  Dimensions,
  Platform,
  View,
  NavigatorIOS,
  TouchableOpacity
} from 'react-native';

import FundPurchaseView from './FundPurchaseView';
import FundRedeemView from './FundRedeemView';

let {height,width} = Dimensions.get('window');
let HostApi =
// 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg';
'http://172.16.101.202/';

class MineView extends Component{
  constructor(props){
    super(props);
  }
  _GoToFundPurchaseView(){
    // this.props.tabbarHidden(true);
    this.props.navigator.push({
      leftButtonIcon:require('../Images/nav_back.png'),
      onLeftButtonPress:()=>{
        this.props.tabbarHidden(false);
        this.props.navigator.pop();
      },
      component:FundPurchaseView,
      title:'基金申购',
      // barTintColor: '#996699',
      translucent:true,
      passProps:{
        text:'这是从帖子界面获取到的文本',
        tabbarHidden:this.props.tabbarHidden,
      },
    })
  }

  _GoToFundRedeemView(){
    this.props.tabbarHidden(true);
    this.props.navigator.push({
      leftButtonIcon:require('../Images/nav_back.png'),
      onLeftButtonPress:()=>{
        this.props.tabbarHidden(false);
        this.props.navigator.pop();
      },
      component:FundRedeemView,
      title:'基金赎回',
      // barTintColor: '#996699',
      translucent:true,
      passProps:{
        text:'这是从帖子界面获取到的文本',
        tabbarHidden:this.props.tabbarHidden,
      },
    })
  }

  render(){
    return (
      <View style = {styles.container}>
        <TouchableOpacity
          onPress = {()=>this._GoToFundPurchaseView()}>
          <Text style = {styles.userName}>申购</Text>
        </TouchableOpacity>
        <TouchableOpacity
          onPress = {()=>this._GoToFundRedeemView()}>
          <Text style = {styles.userName}>赎回</Text>
        </TouchableOpacity>
      </View>
    )
  }
}

export default class Mine extends Component {
  constructor(props){
    super(props);
  }

  render() {
    let defaultComponent = MineView;
    let tabbarHidden = this.props.tabbarHidden;
    return (
      <NavigatorIOS
        ref = 'nav'
        initialRoute = {{
          component:defaultComponent,
          title:'财富管家',
          passProps:{tabbarHidden},
          translucent:true,
        }}
        style = {{flex:1}}
        ></NavigatorIOS>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    //子元素沿主轴的对齐方式
    justifyContent: 'center',
    //子元素沿着次轴的对齐方式
    // alignItems: 'center',
    backgroundColor: '#FFFFFF',
    overflow:'hidden',
    paddingTop:Platform.OS === 'android'?0:20,
  },
  userName: {
    fontSize: 20,
    textAlign: 'center',
    backgroundColor:'red',
    marginHorizontal:10,
    marginBottom: 5,
  },
});

// AppRegistry.registerComponent('Demo4', () => Demo4);


text:
import { createReadStream } from 'fs';
import { ExifImage, TYPE_NO_EXIF_SEGMENT, Exif, ExifError } from 'exif';
import * as marked from 'marked';
import * as slug from 'slug';
import * as debug from 'debug';
import nodeIptc = require('node-iptc');
import getImageSize = require('probe-image-size');
import * as utf8 from 'utf8';
import { pReadFile, sortAlphabetically } from './util';
import {
  GPS,
  LatLng,
  Dimensions,
  Orientation,
  Meta,
  PhotoMeta,
  Tag,
} from './definitions/global';

const ORIENTATION_SQUARE = 'square';
const ORIENTATION_LANDSCAPE = 'landscape';
const ORIENTATION_PORTRAIT = 'portrait';
const NO_EXIF_SEGMENT: TYPE_NO_EXIF_SEGMENT = 'NO_EXIF_SEGMENT';

const log = debug('phox:getimage-meta');

const isError = (err: ExifError) => err && err.code !== NO_EXIF_SEGMENT;

const hasNoExifData = (err: ExifError) => err && err.code === NO_EXIF_SEGMENT;

const toTagData = (tag: string): Tag => ({
  slug: slug(tag),
  title: tag,
});

const decodeUtf8 = (str: string) => utf8.decode(utf8.encode(str));

const getExifData = async (filePath: string): Promise<Meta> =>
  new Promise((resolve, reject) => {
    const args = { image: filePath };
    const extractor: ExifImage = new ExifImage(
      args,
      (err: any, data?: Exif) => {
        if (isError(err)) {
          reject({});
          return;
        }
        const exif = hasNoExifData(err) ? extractor.exifData : data;
        resolve(exif);
      }
    );
  });

const getIptcData = async (filePath: string): Promise<Meta> => {
  try {
    const data = await pReadFile(filePath);
    return nodeIptc(data) || {};
  } catch (e) {
    return {};
  }
};

const getDimensions = async (filePath: string): Promise<Dimensions> => {
  const input = createReadStream(filePath);
  let orientation: Orientation;
  let size;
  try {
    size = await getImageSize(input);
    const { width, height } = size;
    if (width === height) {
      orientation = ORIENTATION_SQUARE;
    }
    if (width > height) {
      orientation = ORIENTATION_LANDSCAPE;
    } else {
      orientation = ORIENTATION_PORTRAIT;
    }
  } catch (e) {} // tslint:disable-line:no-empty
  input.destroy();
  return {
    width: size.width,
    height: size.height,
    orientation,
  };
};

const getCreationDateFromString = (date: string): string => {
  const year = date.slice(0, 4);
  const month = date.slice(4, 6);
  const day = date.slice(6);
  return new Date(`${year}-${month}-${day}`).toISOString();
};

const coordToDecimal = (gps: GPS): LatLng => {
  const latArr = gps.GPSLatitude;
  const lngArr = gps.GPSLongitude;
  if (!latArr || !lngArr) {
    return {};
  }
  const latRef = gps.GPSLatitudeRef || 'N';
  const lngRef = gps.GPSLongitudeRef || 'W';
  const lat =
    (latArr[0] + latArr[1] / 60 + latArr[2] / 3600) * (latRef === 'N' ? 1 : -1);
  const lng =
    (lngArr[0] + lngArr[1] / 60 + lngArr[2] / 3600) * (lngRef === 'W' ? -1 : 1);
  return { lat, lng };
};

const getDetailsFromMeta = (
  exif: Meta,
  iptc: Meta,
  dimensions: Dimensions
): PhotoMeta => ({
  ...dimensions,
  title: decodeUtf8(iptc.object_name || ''),
  tags: (iptc.keywords || [])
    .map(decodeUtf8)
    .filter(Boolean)
    .sort(sortAlphabetically)
    .map(toTagData),
  description: marked(decodeUtf8(iptc.caption || '')),
  createdAt: iptc.date_created
    ? getCreationDateFromString(iptc.date_created)
    : undefined,
  camera: exif.image.Model || '',
  lens: exif.exif.LensModel || '',
  iso: exif.exif.ISO ? Number(exif.exif.ISO) : undefined,
  aperture: exif.exif.FNumber ? exif.exif.FNumber.toFixed(1) : undefined,
  focalLength: exif.exif.FocalLength
    ? exif.exif.FocalLength.toFixed(1)
    : undefined,
  exposureTime: exif.exif.ExposureTime
    ? Number(exif.exif.ExposureTime)
    : undefined,
  flash: Boolean(exif.exif.Flash),
  gps: coordToDecimal(exif.gps),
});

export default async (filePath: string): Promise<PhotoMeta> => {
  log('Get image met for file "%s".', filePath);

  const [exif, iptc, dimensions] = await Promise.all([
    getExifData(filePath),
    getIptcData(filePath),
    getDimensions(filePath),
  ]);

  return getDetailsFromMeta(exif, iptc, dimensions);
};


text:
<!DOCTYPE html>

    <title>Bowling Calculator</title>

    <link rel="stylesheet" type="text/css" href="bowling.css" />

Bowling Sheet

            Frame {{$index+1}}

              <input focus="!frame.first && isCurrentFrame($index)" ng-disabled="isDisabledCell($index,'first')" maxlength="1" type="text" class="sheet-throw readable-text sheet-cell" ng-model="frame.first" />
              <input focus="!frame.second && frame.first && isCurrentFrame($index)" ng-disabled="isDisabledCell($index,'second')" maxlength="1" type="text" class="sheet-throw readable-text right sheet-cell" ng-model="frame.second" ng-class="{'sheet-disabled': isDisabledCell($index,'second')}" />
              <input focus="!frame.third && frame.second && isCurrentFrame($index)" ng-disabled="isDisabledCell($index,'third')" maxlength="1" type="text" class="sheet-throw readable-text right sheet-cell" ng-model="frame.third" ng-show="$index === 9" />

{{frame.total}}


text:
/**
 * URL: https://leetcode.com/explore/featured/card/november-leetcoding-challenge/564/week-1-november-1st-november-7th/3516/
 * */

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {number}
 */
var getDecimalValue = function (head) {
    let binaryString = "";
    let ptr = head;
    while (ptr != null) {
        binaryString += ptr.val;
        ptr = ptr.next;
    }
    return parseInt(binaryString, 2);
};


text:
#ifndef GPUANN_H_INCLUDED
#define GPUANN_H_INCLUDED

#include "NEAT_Network.h"

#include "NEAT_NetworkNode.h"
#include "NEAT_NetworkLink.h"
#include "NEAT_NetworkIndexedLink.h"

#include "NEAT_FastLayeredNetwork.h"

namespace NEAT
{
    /**
     *  The GPUANN class is designed to be faster at the cost
     *  of being less dynamic.  Adding/Removing links and nodes
     *  is not supported with this network.
     */
    template<class Type>
    class GPUANN : public Network<Type>
    {
        vector<NetworkLayer<Type> > layers;

    public:
        /**
         *  (Constructor) Create a Network with the inputed toplogy
         */
        NEAT_DLL_EXPORT GPUANN(
            const vector<NetworkLayer<Type> > &_layers
        );

        /**
         *  (Constructor) Empty Constructor
         */
        NEAT_DLL_EXPORT GPUANN();

        NEAT_DLL_EXPORT virtual ~GPUANN();

        //NetworkNode *getNode(const string name);

        inline int getLayerIndex(const string &layerName)
        {
            for(int a=0;a<(int)layers.size();a++)
            {
                if(layers[a].name==layerName)
                {
                    return a;
                }
            }

            throw CREATE_LOCATEDEXCEPTION_INFO("OOPS");
        }

        /**
         *  getValue: gets the value for a specified node
         */
        NEAT_DLL_EXPORT bool hasNode(const Node &nodeIndex);

        /**
         *  getValue: gets the value for a specified node
         */
        NEAT_DLL_EXPORT Type getValue(const Node &nodeIndex);

        /**
         *  setValue: sets the value for a specified node
         */
        NEAT_DLL_EXPORT void setValue(const Node &nodeIndex,Type newValue);

        /**
         *  getLink: gets the link weight between two specified nodes
         */
        NEAT_DLL_EXPORT Type getLink(const Node &fromNodeIndex,const Node &toNodeIndex);

        /**
         *  setLink: gets the link weight between two specified nodes
         */
        NEAT_DLL_EXPORT void setLink(const Node &fromNodeIndex,const Node &toNodeIndex,Type weight);

        /**
         * reinitialize: This resets the state of the network
         * to its initial state
         */
        NEAT_DLL_EXPORT void reinitialize();

        /**
         * update: This updates the network.
         * If the network has not been updated since construction or
         * reinitialize(), the network will be activated.  This means
         * it will update (1+ExtraActivationUpdates+iterations) times!
         * Otherwise, it will update (iterations) times.  If you do not
         * want the extra updates, call dummyActivation() before the first
         * update.
         */
        NEAT_DLL_EXPORT void update();

    protected:
    };

}

#endif // FASTNETWORK_H_INCLUDED


text:
package twilightforest.entity.ai;

import net.minecraft.entity.EntityCreature;
import net.minecraft.entity.ai.RandomPositionGenerator;
import net.minecraft.pathfinding.PathNavigate;
import net.minecraft.util.Vec3;

public class EntityAITFKidnapRider extends net.minecraft.entity.ai.EntityAIBase
{
  private EntityCreature theEntityCreature;
  private float speed;
  private double randPosX;
  private double randPosY;
  private double randPosZ;

  public EntityAITFKidnapRider(EntityCreature par1EntityCreature, float par2)
  {
    theEntityCreature = par1EntityCreature;
    speed = par2;
    func_75248_a(1);
  }

  public boolean func_75250_a()
  {
    if ((theEntityCreature.field_70153_n == null) || (theEntityCreature.func_70681_au().nextInt(5) > 0))
    {
      return false;
    }

    Vec3 var1 = RandomPositionGenerator.func_75463_a(theEntityCreature, 5, 4);

    if (var1 == null)
    {
      return false;
    }

    randPosX = field_72450_a;
    randPosY = field_72448_b;
    randPosZ = field_72449_c;
    return true;
  }

  public void func_75249_e()
  {
    theEntityCreature.func_70661_as().func_75492_a(randPosX, randPosY, randPosZ, speed);
  }

  public boolean func_75253_b()
  {
    return !theEntityCreature.func_70661_as().func_75500_f();
  }
}


text: require_relative 'rails/controller_helper'


text:
<?xml version="1.0" encoding="utf-8"?>
<!-- $Revision: 317663 $ -->

<refentry xml:id="function.gupnp-service-action-return-error" xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink">
 <refnamediv>
  <refname>gupnp_service_action_return_error</refname>
  <refpurpose>Return error code</refpurpose>
 </refnamediv>

 <refsect1 role="description">
  &reftitle.description;
  <methodsynopsis>
   <type>bool</type><methodname>gupnp_service_action_return_error</methodname>
   <methodparam><type>resource</type><parameter>action</parameter></methodparam>
   <methodparam><type>int</type><parameter>error_code</parameter></methodparam>
   <methodparam choice="opt"><type>string</type><parameter>error_description</parameter></methodparam>
  </methodsynopsis>
  <para>
   Return error code.
  </para>
 </refsect1>

 <refsect1 role="parameters">
  &reftitle.parameters;
  <para>
   <variablelist>
    <varlistentry>
     <term><parameter>action</parameter></term>
     <listitem>
      <para>
       A service action identifier.
      </para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term><parameter>error_code</parameter></term>
     <listitem>
      <para>
       The error code. Signal can be one of the following values or user defined:
       <variablelist>
        <varlistentry>
         <term><constant>GUPNP_CONTROL_ERROR_INVALID_ACTION</constant></term>
         <listitem>
          <simpara>
           The action name was invalid.
          </simpara>
         </listitem>
        </varlistentry>
        <varlistentry>
         <term><constant>GUPNP_CONTROL_ERROR_INVALID_ARGS</constant></term>
         <listitem>
          <simpara>
           The action arguments were invalid.
          </simpara>
         </listitem>
        </varlistentry>
        <varlistentry>
         <term><constant>GUPNP_CONTROL_ERROR_OUT_OF_SYNC</constant></term>
         <listitem>
          <simpara>
           Out of sync (deprecated).
          </simpara>
         </listitem>
        </varlistentry>
        <varlistentry>
         <term><constant>GUPNP_CONTROL_ERROR_ACTION_FAILED</constant></term>
         <listitem>
          <simpara>
           The action failed.
          </simpara>
         </listitem>
        </varlistentry>
       </variablelist>
      </para>
     </listitem>
    </varlistentry>
    <varlistentry>
     <term><parameter>error_description</parameter></term>
     <listitem>
      <para>
       The error description.
      </para>
     </listitem>
    </varlistentry>
   </variablelist>
  </para>
 </refsect1>

 <refsect1 role="returnvalues">
  &reftitle.returnvalues;
  <para>
   &return.success;
  </para>
 </refsect1>

 <refsect1 role="seealso">
  &reftitle.seealso;
  <para>
   <simplelist>
    <member><function>gupnp_service_action_return</function></member>
   </simplelist>
  </para>
 </refsect1>

</refentry>

<!-- Keep this comment at the end of the file
Local variables:
mode: sgml
sgml-omittag:t
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
indent-tabs-mode:nil
sgml-parent-document:nil
sgml-default-dtd-file:"~/.phpdoc/manual.ced"
sgml-exposed-tags:nil
sgml-local-catalogs:nil
sgml-local-ecat-files:nil
End:
vim600: syn=xml fen fdm=syntax fdl=2 si
vim: et tw=78 syn=sgml
vi: ts=1 sw=1
-->


text:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Rptpdf extends CI_Controller{
    //put your code here
     public function __construct()
    {
        parent::__construct();
        $this->load->helper('form');
        $this->load->library('fpdf');

        $logged_in = $this->session->userdata('logged_in');
        if(!$logged_in){
            header("location: ".base_url());
        }
    }

    public function index() {
        $this->load->model('rptpdf/data');
        $res['data'] = $this->data->select_data(7);
        $this->load->view('rptpdf/index',$res);
    }

}


text:
require 'application_system_test_case'

# Confirm behavior around updating fund-editable settings
class UpdatingConfigsTest < ApplicationSystemTestCase
  describe 'non-admin redirect' do
    [:data_volunteer, :cm].each do |role|
      it "should deny access as a #{role.to_s}" do
        user = create :user, role: role
        log_in_as user
        visit configs_path
        assert_equal current_path, authenticated_root_path
      end
    end
  end

  describe 'admin usage' do
    before do
      @patient = create :patient
      @user = create :user, role: :admin
      log_in_as @user
      visit configs_path
    end

    describe 'updating a config - insurance' do
      it 'should update and be available' do
        fill_in 'config_options_insurance', with: 'Yolo, Goat, Something'
        click_button 'Update options for Insurance'

        assert_equal 'Yolo, Goat, Something',
                     find('#config_options_insurance').value
        within :css, '#insurance_options_list' do
          assert has_content? 'Yolo'
          assert has_content? 'Goat'
          assert has_content? 'Something'
          assert has_content? 'No insurance'
          assert has_content? "Don't know"
          assert has_content? 'Other (add to notes)'
        end

        visit edit_patient_path(@patient)
        assert has_select? 'Patient insurance', options: ['', 'Yolo', 'Goat', 'Something',
                                                          'No insurance', "Don't know",
                                                          'Other (add to notes)']
      end
    end

    describe 'updating a config - practical support' do
      it 'should update and be available' do
        fill_in 'config_options_practical_support', with: 'Yolo, Goat, Something'
        click_button 'Update options for Practical support'

        assert_equal 'Yolo, Goat, Something',
                     find('#config_options_practical_support').value
        within :css, '#practical_support_options_list' do
          assert has_content? 'Yolo'
          assert has_content? 'Goat'
          assert has_content? 'Something'
          assert has_content? 'Travel to the region'
          assert has_content? 'Travel inside the region'
          assert has_content? "Lodging"
          assert has_content? 'Companion'
        end

        # Requires view implementation
        #visit edit_patient_path(@patient)
        #assert has_select? 'Patient insurance', options: ['', 'Yolo', 'Goat', 'Something',
                                                          #'No insurance', "Don't know",
                                                          #'Other (add to notes)']
      end
    end

    describe 'updating a config - external pledge' do
      it 'should update and be available' do
        fill_in 'config_options_external_pledge_source', with: 'Yolo, Goat, Something'
        click_button 'Update options for External pledge source'

        assert_equal 'Yolo, Goat, Something',
                     find('#config_options_external_pledge_source').value
        within :css, '#external_pledge_source_options_list' do
          assert has_content? 'Yolo'
          assert has_content? 'Goat'
          assert has_content? 'Something'
          assert has_content? 'Clinic discount'
          assert has_content? 'Other funds (see notes)'
        end

        visit edit_patient_path(@patient)
        click_link 'Abortion Information'
        assert has_select? 'Source', options: ['', 'Yolo', 'Goat', 'Something',
                                               'Clinic discount',
                                               'Other funds (see notes)']
      end
    end

    describe 'updating a config - Pledge limit help text' do
      it 'should update and be available' do
        fill_in 'config_options_pledge_limit_help_text',
                with: 'Pledge guidelines, 13 weeks $100'
        click_button 'Update options for Pledge limit help text'

        assert_equal 'Pledge guidelines, 13 weeks $100',
                     find('#config_options_pledge_limit_help_text').value
        within :css, '#pledge_limit_help_text_options_list' do
          assert has_content? 'Pledge guidelines'
          assert has_content? '13 weeks $100'
        end

        # Can't get this to work quite right
        # visit edit_patient_path @patient
        # click_link 'Abortion Information'
        # within :css, 'label[for=patient_fund_pledge]' do
        #   find('.tooltip-header-help').hover
        # end
        # assert has_text? 'Pledge guidelines'
        # assert has_text? '13 weeks $100'
      end
    end

    describe 'updating a config - referred by' do
      it 'should update and be available' do
        fill_in 'config_options_referred_by', with: 'Metallica'
        click_button 'Update options for Referred by'

        assert_equal 'Metallica',
                     find('#config_options_referred_by').value
        within :css, '#referred_by_options_list' do
          assert has_content? 'Clinic' # stock option
          assert has_content? 'Metallica' # custom option
        end
      end
    end

    describe 'updating a config - fax service' do
      it 'should update and be available in the footer' do
        fill_in 'config_options_fax_service', with: 'https://metallicarules.com'
        click_button 'Update options for Fax service'

        assert_equal 'https://metallicarules.com',
                     find('#config_options_fax_service').value
        within :css, '#app_footer' do
          assert has_content? 'https://metallicarules.com'
        end
      end
    end
  end
end


text:
$(function (){
	// Rich text
	var rich_text_areas = $('.rich_text_area');
	rich_text_areas.each(function(){
		var specificRichText = $(this)
		var parentElement = specificRichText.parent().parent().parent().parent();
		var helpBox = parentElement.find('.object-help');
		if (helpBox.html()) {
			helpBox.addClass('charcount');
		} else {
			var helpBoxExists = true
			var elem = parentElement.append("

");
			var helpBox = parentElement.find('.charcount');
			helpBox.hide();
		}
		var whiteSpace = /\s\s+/gm;
		var wordsRegex = /\s+/gi;
		var charCountElemText = helpBox.text();
		var maxChars = specificRichText.find('textarea').attr('maxlength');

		$(specificRichText.find('.richtext')).bind('hallomodified', function(event) {
			var text = event.currentTarget.innerText;
			var textNoWhitespace = text.replace(whiteSpace, ' ');
			var textWordCount = textNoWhitespace.trim().replace(wordsRegex, ' ').split(' ').length;
			var textCharCount = textNoWhitespace.length - 1;
			var backendCount = $(specificRichText).find('.richtext').html().length;
			if (charCountElemText.length > 1) {
				helpBox.css({opacity :1});
				helpBox.html(
					charCountElemText + '
' +
					"
" + textWordCount + " words" +
					"
" + backendCount + ' / ' + maxChars + ' characters');
				if (backendCount > maxChars) {
					$(helpBox.find('.count')).css({color: 'red'})
				} else if (backendCount + 20  > maxChars) {
					$(helpBox.find('.count')).css({color: 'orange'})
				}
			} else {
				helpBox.show();
				helpBox.html(
					textWordCount + " words" +
					"
" + backendCount + ' / ' + maxChars + ' characters');
				if (backendCount  > maxChars) {
					$(helpBox.find('.count')).css({color: 'red'})
				} else if (backendCount + 20  > maxChars) {
					$(helpBox.find('.count')).css({color: 'orange'})
				}
			}
		});
	})
	// Normal text fields
	var text_fields = $($('form').find('.field.char_field').not('.rich_text_area'));
	text_fields.each(function(){
		var specificTextBox = $(this)
		var parentElement = specificTextBox.parent().parent().parent().parent();
		var helpBox = parentElement.find('.object-help');
		if (helpBox.html()) {
			helpBox.addClass('charcount');
		} else {
			var helpBoxExists = true
			var elem = parentElement.append("

");
			var helpBox = parentElement.find('.charcount');
			helpBox.hide();
		}
		var whiteSpace = /\s\s+/gm;
		var wordsRegex = /\s+/gi;
		var charCountElemText = helpBox.text();
		var maxChars = specificTextBox.find('input').attr('maxlength');

		$(specificTextBox.find('input')).bind('input propertychange', function() {
			var text = this.value;
			var textNoWhitespace = text.replace(whiteSpace, ' ');
			var textCharCount = textNoWhitespace.length;
			if (textCharCount == 0) {
				var textWordCount = 0
			} else {
				var textWordCount = textNoWhitespace.trim().replace(wordsRegex, ' ').split(' ').length;
			}
			if (charCountElemText.length > 1) {
				helpBox.css({opacity :1});
				var helpBoxContent = (charCountElemText + '
' +
					"
" + textWordCount + " words" +
					"
" + textCharCount + ' / ' + maxChars + ' characters');

				helpBox.html(helpBoxContent);
				if (textCharCount > maxChars) {
					$(helpBox.find('.count')).css({color: 'red'})
				} else if (textCharCount + 20  > maxChars) {
					$(helpBox.find('.count')).css({color: 'orange'})
				}
			} else {
				helpBox.show();
				helpBox.html(
					textWordCount + " words" +
					"
" + textCharCount + ' / ' + maxChars + ' characters'
				);
				if (textCharCount > maxChars) {
					$(helpBox.find('.count')).css({color: 'red'})
				} else if (textCharCount + 20  > maxChars) {
					$(helpBox.find('.count')).css({color: 'orange'})
				}
			}
		});
	})

});


text:
  Louvières-en-Auge est
       un village
       situé dans le département de l'Orne en Basse-Normandie. Elle totalisait 84 habitants en 2008.

Si vous pensez demenager à Louvières-en-Auge, vous pourrez aisément trouver une maison à vendre.

À proximité de Louvières-en-Auge sont situées les communes de
Trun à 3 km, 1 322 habitants,
Guêprei localisée à 4 km, 142 habitants,
Les Moutiers-en-Auge située à 4 km, 122 habitants,
Ommoy située à 4 km, 117 habitants,
Montreuil-la-Cambe à 2 km, 83 habitants,
Fontaine-les-Bassets située à 2 km, 116 habitants,
 entre autres. De plus, Louvières-en-Auge est située à seulement quatorze km de Argentan.

Le nombre de logements, à Louvières-en-Auge, était réparti en 2011 en zero appartements et 53 maisons soit
 un marché plutôt équilibré.


text:
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->

<link rel="import" href="../polymer/polymer.html">

<!-- Taken from https://www.google.com/design/spec/style/color.html#color-ui-color-application -->

<style is="custom-style">

  :root {
    /*
     * You can use these generic variables in your elements for easy theming.
     * For example, if all your elements use `--primary-text-color` as its main
     * color, then switching from a light to a dark theme is just a matter of
     * changing the value of `--primary-text-color` in your application.
     */
    --primary-text-color: var(--light-theme-text-color);
    --primary-background-color: var(--light-theme-background-color);
    --secondary-text-color: var(--light-theme-secondary-color);
    --disabled-text-color: var(--light-theme-disabled-color);
    --divider-color: var(--light-theme-divider-color);
    --error-color: var(--paper-deep-orange-a700);

    /*
     * Primary and accent colors. Also see color.html for more colors.
     */
    --primary-color: #3f51b5;  /* --paper-indigo-500 */
    --light-primary-color: #c5cae9;  /* --paper-indigo-100 */
    --dark-primary-color: #303f9f;  /* --paper-indigo-700 */

    --accent-color: #ff4081;  /* --paper-pink-a200 */
    --light-accent-color: #ff80ab;  /* --paper-pink-a100 */
    --dark-accent-color: #f50057;  /* --paper-pink-a400 */

    /*
     * Material Design Light background theme
     */
    --light-theme-background-color: #ffffff;
    --light-theme-base-color: #000000;
    --light-theme-text-color: #212121;
    --light-theme-secondary-color: #737373;  /* for secondary text and icons */
    --light-theme-disabled-color: #9b9b9b;  /* disabled/hint text */
    --light-theme-divider-color: #dbdbdb;

    /*
     * Material Design Dark background theme
     */
    --dark-theme-background-color: #212121;
    --dark-theme-base-color: #ffffff;
    --dark-theme-text-color: #ffffff;
    --dark-theme-secondary-color: #bcbcbc;  /* for secondary text and icons */
    --dark-theme-disabled-color: #646464;  /* disabled/hint text */
    --dark-theme-divider-color: #3c3c3c;

    /*
     * Deprecated values because of their confusing names.
     */
    --text-primary-color: var(--dark-theme-text-color);
    --default-primary-color: var(--primary-color);

  }

</style>


text:
package org.kie.test.util;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
import org.junit.runners.model.TestTimedOutException;

public class TestStatusListener extends RunListener {

    private static BufferedWriter writer;
    static {
        try {
            writer = Files.newBufferedWriter(
                    Paths.get("./target/testStatusListener"
                                + "." + ManagementFactory.getRuntimeMXBean().getName().replaceAll("\\W+", "")
                                + "." + System.nanoTime()
                                + ".log"));
        } catch (IOException e) {
            new RuntimeException( "TestStatusListener unable to open writer for logging to file test status updates.", e );
        }
    }

    private static synchronized void write(String method, Description description) throws IOException {
        writer.write(method);
        writer.write("\t");
        writer.write(description.getClassName());
        writer.write(".");
        if ( description.getMethodName() != null ) { writer.write(description.getMethodName()); }
        writer.newLine();
        writer.flush();
    }

    private static synchronized void write(String method, Failure failure) throws IOException {
        writer.write(method);
        writer.write("\t");
        if ( failure.getMessage() != null ) { writer.write(failure.getMessage()); }
        writer.newLine();
        writer.flush();
    }

    private static synchronized void write(String method, Result result) throws IOException {
        writer.write(method);
        writer.write("\t");
        writer.write(result.toString());
        writer.newLine();
        writer.flush();
    }

    private static synchronized void writeThreadDump() throws IOException {
        ThreadMXBean threadMxBean = ManagementFactory.getThreadMXBean();
        for (ThreadInfo ti : threadMxBean.dumpAllThreads(true, true)) {
            writer.write( ti.toString() );
            if ( ti.getStackTrace().length > 8 ) { writer.write("full stacktrace:\n"); writer.write(fullStackTrace(ti)); writer.write("\n"); }
        }
        writer.newLine();
        writer.flush();
    }

    private static String fullStackTrace(ThreadInfo ti) {
        StringBuilder sb = new StringBuilder();
        Stream.of( ti.getStackTrace() )
            .forEach( ste -> {
                sb.append(" ");
                sb.append(ste.toString());
                sb.append("\n");
                Stream.of( ti.getLockedMonitors() )
                    .filter( m -> ste.equals(m.getLockedStackFrame()) )
                    .forEach( lm -> {
                        sb.append("  (locked: ");
                        sb.append(lm);
                        sb.append(" )\n");
                    });
            });
        return sb.toString();
    }

    @Override
    public void testRunStarted(Description description) throws Exception {
        write("testRunStarted", description);
    }

    @Override
    public void testRunFinished(Result result) throws Exception {
        write("testRunFinished", result);
    }

    @Override
    public void testStarted(Description description) throws Exception {
        write("testStarted", description);
    }

    @Override
    public void testFinished(Description description) throws Exception {
        write("testFinished", description);
    }

    @Override
    public void testFailure(Failure failure) throws Exception {
        if ( failure.getException() instanceof TestTimedOutException ) {
            writeThreadDump();
        }
        write("testFailure", failure);
    }

    @Override
    public void testAssumptionFailure(Failure failure) {
        try {
            write("testAssumptionFailure", failure);
        } catch (IOException e) {
            // can't do anything at this point to report it to log file
            e.printStackTrace();
        }
    }

    @Override
    public void testIgnored(Description description) throws Exception {
        write("testIgnored", description);
    }

}


text:
package com.amazonaws.services.ec2.model.transform;

import java.util.Map;
import java.util.Map.Entry;

import javax.xml.stream.events.XMLEvent;

import com.amazonaws.services.ec2.model.*;
import com.amazonaws.transform.Unmarshaller;
import com.amazonaws.transform.MapEntry;
import com.amazonaws.transform.StaxUnmarshallerContext;
import com.amazonaws.transform.SimpleTypeStaxUnmarshallers.*;

/**
 * NetworkAclEntry StAX Unmarshaller
 */
public class NetworkAclEntryStaxUnmarshaller implements
        Unmarshaller<NetworkAclEntry, StaxUnmarshallerContext> {

    public NetworkAclEntry unmarshall(StaxUnmarshallerContext context)
            throws Exception {
        NetworkAclEntry networkAclEntry = new NetworkAclEntry();
        int originalDepth = context.getCurrentDepth();
        int targetDepth = originalDepth + 1;

        if (context.isStartOfDocument())
            targetDepth += 1;

        while (true) {
            XMLEvent xmlEvent = context.nextEvent();
            if (xmlEvent.isEndDocument())
                return networkAclEntry;

            if (xmlEvent.isAttribute() || xmlEvent.isStartElement()) {

                if (context.testExpression("ruleNumber", targetDepth)) {
                    networkAclEntry.setRuleNumber(IntegerStaxUnmarshaller
                            .getInstance().unmarshall(context));
                    continue;
                }

                if (context.testExpression("protocol", targetDepth)) {
                    networkAclEntry.setProtocol(StringStaxUnmarshaller
                            .getInstance().unmarshall(context));
                    continue;
                }

                if (context.testExpression("ruleAction", targetDepth)) {
                    networkAclEntry.setRuleAction(StringStaxUnmarshaller
                            .getInstance().unmarshall(context));
                    continue;
                }

                if (context.testExpression("egress", targetDepth)) {
                    networkAclEntry.setEgress(BooleanStaxUnmarshaller
                            .getInstance().unmarshall(context));
                    continue;
                }

                if (context.testExpression("cidrBlock", targetDepth)) {
                    networkAclEntry.setCidrBlock(StringStaxUnmarshaller
                            .getInstance().unmarshall(context));
                    continue;
                }

                if (context.testExpression("icmpTypeCode", targetDepth)) {
                    networkAclEntry
                            .setIcmpTypeCode(IcmpTypeCodeStaxUnmarshaller
                                    .getInstance().unmarshall(context));
                    continue;
                }

                if (context.testExpression("portRange", targetDepth)) {
                    networkAclEntry.setPortRange(PortRangeStaxUnmarshaller
                            .getInstance().unmarshall(context));
                    continue;
                }
            } else if (xmlEvent.isEndElement()) {
                if (context.getCurrentDepth() < originalDepth) {
                    return networkAclEntry;
                }
            }
        }
    }

    private static NetworkAclEntryStaxUnmarshaller instance;

    public static NetworkAclEntryStaxUnmarshaller getInstance() {
        if (instance == null)
            instance = new NetworkAclEntryStaxUnmarshaller();
        return instance;
    }
}