text:
package library

import (
	"errors"

	"github.com/jasoncapehart/go-sgd"          //sgd
	"github.com/nytlabs/gojee"                 // jee
	"github.com/nytlabs/streamtools/st/blocks" // blocks
	"github.com/nytlabs/streamtools/st/util"
)

type Learn struct {
	blocks.Block
	queryrule chan blocks.MsgChan
	inrule    blocks.MsgChan
	inpoll    blocks.MsgChan
	in        blocks.MsgChan
	out       blocks.MsgChan
	quit      blocks.MsgChan
}

// a bit of boilerplate for streamtools
func NewLearn() blocks.BlockInterface {
	return &Learn{}
}

func (b *Learn) Setup() {
	b.Kind = "Stats"
	b.Desc = "applies stochastic gradient descent to learn the relationship between features and response"
	b.in = b.InRoute("in")
	b.inrule = b.InRoute("rule")
	b.inpoll = b.InRoute("poll")
	b.queryrule = b.QueryRoute("rule")
	b.quit = b.Quit()
	b.out = b.Broadcast()
}

func (b *Learn) Run() {

	dataChan := make(chan sgd.Obs)
	paramChan := make(chan sgd.Params)
	stateChan := make(chan chan []float64)
	kernelQuitChan := make(chan bool)

	lossfuncs := map[string]sgd.LossFunc{
		"linear":   sgd.GradLinearLoss,
		"logistic": sgd.GradLogisticLoss,
	}
	stepfuncs := map[string]sgd.StepFunc{
		"inverse":  sgd.EtaInverse,
		"constant": sgd.EtaConstant,
		"bottou":   sgd.EtaBottou,
	}
	kernelStarted := false

	var responsePath, lossfuncString, stepfuncString string
	var featurePaths []string
	var θ_0 []float64
	var featureTrees []*jee.TokenTree
	var responseTree *jee.TokenTree
	var err error

	for {
	Loop:
		select {
		case rule := <-b.inrule:
			if kernelStarted {
				// if we already have a rule, then we've already started a
				// kernel, which we should now quit.
				kernelQuitChan <- true
			}

			featurePaths, err = util.ParseArrayString(rule, "FeaturePaths")
			if err != nil {
				b.Error(err)
				continue
			}
			featureTrees = make([]*jee.TokenTree, len(featurePaths))
			for i, path := range featurePaths {
				token, err := jee.Lexer(path)
				if err != nil {
					b.Error(err)
					break
				}
				tree, err := jee.Parser(token)
				if err != nil {
					b.Error(err)
					break
				}
				featureTrees[i] = tree
			}
			responsePath, err = util.ParseString(rule, "ResponsePath")
			if err != nil {
				b.Error(err)
				break
			}
			token, err := jee.Lexer(responsePath)
			if err != nil {
				b.Error(err)
				break
			}
			responseTree, err = jee.Parser(token)
			if err != nil {
				b.Error(err)
				break
			}
			lossfuncString, err = util.ParseString(rule, "Lossfunc")
			if err != nil {
				b.Error(err)
				break
			}
			stepfuncString, err = util.ParseString(rule, "Stepfunc")
			if err != nil {
				b.Error(err)
				break
			}
			grad, ok := lossfuncs[lossfuncString]
			if !ok {
				b.Error(errors.New("Unknown loss function: " + lossfuncString))
			}
			step, ok := stepfuncs[stepfuncString]
			if !ok {
				b.Error(errors.New("Unknown step function: " + stepfuncString))
			}
			θ_0, err = util.ParseArrayFloat(rule, "InitialState")
			if err != nil {
				b.Error(err)
				break
			}
			go sgd.SgdKernel(dataChan, paramChan, stateChan, kernelQuitChan, grad, step, θ_0)
			kernelStarted = true

		case <-b.quit:
			kernelQuitChan <- true
			return
		case msg := <-b.in:
			if featureTrees == nil {
				continue
			}
			if responseTree == nil {
				continue
			}
			x := make([]float64, len(featureTrees))
			for i, tree := range featureTrees {
				feature, err := jee.Eval(tree, msg)
				if err != nil {
					b.Error(err)
					break Loop
				}
				fi, ok := feature.(float64)
				if !ok {
					b.Error(errors.New("features must be float64"))
					break Loop
				}
				x[i] = fi
			}
			responseI, err := jee.Eval(responseTree, msg)
			if err != nil {
				b.Error(err)
				break
			}
			y, ok := responseI.(float64)
			if !ok {
				b.Error(errors.New("response must be float64"))
				break
			}
			d := sgd.Obs{
				X: x,
				Y: y,
			}
			dataChan <- d
		case <-b.inpoll:
			var params []interface{}
			var model []float64
			if kernelStarted {
				kernelMsgChan := make(chan []float64)
				stateChan <- kernelMsgChan
				model = <-kernelMsgChan
				params = make([]interface{}, len(model))
				for i, p := range model {
					params[i] = p
				}
			}
			b.out <- map[string]interface{}{
				"params": params,
			}
		case c := <-b.queryrule:
			c <- map[string]interface{}{
				"Lossfunc":     lossfuncString,
				"Stepfunc":     stepfuncString,
				"FeaturePaths": featurePaths,
				"ResponsePath": responsePath,
				"InitialState": θ_0,
			}
		}
	}
}


text:
using base::SharedMemory;
using base::SharedMemoryHandle;

namespace {
// Gets the address of the data from shared memory.
void* GetAddress(SharedMemory* shared_memory,
                 uint32 shm_size,
                 uint32 shm_data_offset,
                 uint32 shm_data_size) {
  // Memory bounds have already been validated, so there
  // is just DCHECKS here.
  DCHECK(shared_memory);
  DCHECK(shared_memory->memory());
  DCHECK_LE(shm_data_offset + shm_data_size, shm_size);
  return static_cast<int8*>(shared_memory->memory()) + shm_data_offset;
}
} // namespace

namespace gfx {

#if !defined(OS_ANDROID)
scoped_ptr<AsyncPixelTransferDelegate>
    AsyncPixelTransferDelegate::Create(gfx::GLContext* context) {
  return AsyncPixelTransferDelegateStub::Create(context);
}
#endif

scoped_ptr<AsyncPixelTransferDelegate>
      AsyncPixelTransferDelegateStub::Create(gfx::GLContext* context) {
  return make_scoped_ptr(
      static_cast<AsyncPixelTransferDelegate*>(
          new AsyncPixelTransferDelegateStub()));
}

AsyncTransferStateStub::AsyncTransferStateStub(GLuint texture_id) {
  static const AsyncTexImage2DParams zero_params = {0, 0, 0, 0, 0, 0, 0, 0};
  late_bind_define_params_ = zero_params;
  needs_late_bind_ = false;
}

AsyncTransferStateStub::~AsyncTransferStateStub() {
}

bool AsyncTransferStateStub::TransferIsInProgress() {
  return false;
}

void AsyncTransferStateStub::BindTransfer(AsyncTexImage2DParams* out_params) {
  DCHECK(out_params);
  DCHECK(needs_late_bind_);
  *out_params = late_bind_define_params_;
  needs_late_bind_ = false;
}

AsyncPixelTransferDelegateStub::AsyncPixelTransferDelegateStub()
    : texture_upload_count_(0) {
}

AsyncPixelTransferDelegateStub::~AsyncPixelTransferDelegateStub() {
}

AsyncPixelTransferState*
    AsyncPixelTransferDelegateStub::CreateRawPixelTransferState(
        GLuint texture_id) {
  return static_cast<AsyncPixelTransferState*>(
      new AsyncTransferStateStub(texture_id));
}

void AsyncPixelTransferDelegateStub::AsyncNotifyCompletion(
    const base::Closure& task) {
  task.Run();
}

void AsyncPixelTransferDelegateStub::AsyncTexImage2D(
    AsyncPixelTransferState* transfer_state,
    const AsyncTexImage2DParams& tex_params,
    const AsyncMemoryParams& mem_params) {
  // Save the define params to return later during deferred
  // binding of the transfer texture.
  DCHECK(transfer_state);
  AsyncTransferStateStub* state =
      static_cast<AsyncTransferStateStub*>(transfer_state);
  // We don't actually need a late bind since this stub does
  // everything synchronously, but this tries to be similar
  // as an async implementation.
  state->needs_late_bind_ = true;
  state->late_bind_define_params_ = tex_params;
  void* data = GetAddress(mem_params.shared_memory,
                          mem_params.shm_size,
                          mem_params.shm_data_offset,
                          mem_params.shm_data_size);
  glTexImage2D(
      tex_params.target,
      tex_params.level,
      tex_params.internal_format,
      tex_params.width,
      tex_params.height,
      tex_params.border,
      tex_params.format,
      tex_params.type,
      data);
}

void AsyncPixelTransferDelegateStub::AsyncTexSubImage2D(
    AsyncPixelTransferState* transfer_state,
    const AsyncTexSubImage2DParams& tex_params,
    const AsyncMemoryParams& mem_params) {
  void* data = GetAddress(mem_params.shared_memory,
                          mem_params.shm_size,
                          mem_params.shm_data_offset,
                          mem_params.shm_data_size);
  DCHECK(transfer_state);
  AsyncTransferStateStub* state =
      static_cast<AsyncTransferStateStub*>(transfer_state);
  DCHECK(!state->needs_late_bind_);
  base::TimeTicks begin_time(base::TimeTicks::HighResNow());
  glTexSubImage2D(
      tex_params.target,
      tex_params.level,
      tex_params.xoffset,
      tex_params.yoffset,
      tex_params.width,
      tex_params.height,
      tex_params.format,
      tex_params.type,
      data);
  texture_upload_count_++;
  total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time;
}

uint32 AsyncPixelTransferDelegateStub::GetTextureUploadCount() {
  return texture_upload_count_;
}

base::TimeDelta AsyncPixelTransferDelegateStub::GetTotalTextureUploadTime() {
  return total_texture_upload_time_;
}

}  // namespace gfx

redpajama_set_name: RedPajamaGithub


text:
using System;
using CoreGraphics;
using CoreAnimation;
using Foundation;
using UIKit;

namespace CollectionViewTransition {

	public class APLCollectionViewCell : UICollectionViewCell {

		public static readonly NSString Key = new NSString ("APLCollectionViewCell");

		[Export ("initWithFrame:")]
		public APLCollectionViewCell (CGRect frame) : base (frame)
		{
			BackgroundColor = UIColor.Cyan;
			ImageView = new UIImageView (Bounds);
			ImageView.AutoresizingMask = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth;
			ImageView.ContentMode = UIViewContentMode.ScaleAspectFill;
			ImageView.Layer.BorderWidth = 3.0f;
			ImageView.ClipsToBounds = true;
			ImageView.Layer.BorderColor = UIColor.White.CGColor;
			ImageView.Layer.EdgeAntialiasingMask = CAEdgeAntialiasingMask.LeftEdge | CAEdgeAntialiasingMask.RightEdge | CAEdgeAntialiasingMask.BottomEdge | CAEdgeAntialiasingMask.TopEdge;
			ContentView.AddSubview (ImageView);
		}

		public UIImageView ImageView { get; private set; }
	}
}


text:
using System;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;

namespace ThreadPost
{
    public static partial class SynchronizationContextAsyncExtensions
    {
        public static ValueTask PostAsync(this SynchronizationContext context, Action func)
        {
            var t = ActionValueTaskSource.Rent(func);
            context.Post(x => Unsafe.As<object, ActionValueTaskSource>(ref x).Invoke(), t);
            return new ValueTask(t, t.Version);
        }

        private class ActionValueTaskSource : ManualResetValueTaskSource<object>
        {
            private ObjectPool<ActionValueTaskSource> Pool;
            private Action State;

            public override object GetResult(short token)
            {
                var r = base.GetResult(token);
                Pool.Return(this);
                Pool = null;
                return r;
            }

            public void Invoke()
            {
                var func = State;
                State = default;

                try
                {
                    func();
                    SetResult(null);
                }
                catch (Exception ex)
                {
                    SetException(ex);
                }
            }

            private static readonly ObjectPool<ActionValueTaskSource> _pool = new ObjectPool<ActionValueTaskSource>(() => new ActionValueTaskSource());

            public static ActionValueTaskSource Rent(Action func)
            {
                var r = _pool.Rent();
                r.Pool = _pool;
                r.State = func;
                r.Reset();
                return r;
            }
        }
    }
}


text: g++ Source/main.cpp -std=c++11 -Wall -o main.exe


text:
var annotate = require('annotate');
var is = require('is-js');
var randint = require('./randint');
    function choose(m) {
        return m[randint(0, m.length - 1)];
    }

    module.exports = annotate('choose', 'Chooses an item randomly.')
        .on(is.array, choose);


text:
package org.jconverter.typesolver;

import java.lang.reflect.Type;
import java.util.List;
import java.util.function.Function;

import org.jcategory.ChainOfResponsibilityExhaustedException;
import org.jcategory.strategy.ChainOfResponsibility;

public class TypeSolverChain<T> extends ChainOfResponsibility<TypeSolver<T>, Type> /*implements TypeSolver<T>*/ {

	public TypeSolverChain(List<TypeSolver<T>> responsibilityChain) {
		super(responsibilityChain, UnrecognizedObjectException.class);
	}

	@Override
	public Type apply(Function<TypeSolver<T>, Type> evaluator) {
		try {
			return super.apply(evaluator);
		} catch(ChainOfResponsibilityExhaustedException e) {
			throw new UnrecognizedObjectException(e);
		}
	}

//	@Override
//	public Type inferType(T object) {
//		return apply(new TypeSolverChainEvaluator<T>(object));
//	}

}


text:
<?php
/**
 * PHPInSimMod - Connections Module
 * @package PRISM
 * @subpackage Connections
*/

require_once(ROOTPATH . '/modules/prism_sectionhandler.php');

define('CONNTYPE_HOST',            0);            # object is connected directly to a host
define('CONNTYPE_RELAY',        1);            # object is connected to host via relay

define('KEEPALIVE_TIME',        29);        # the time in seconds of write inactivity, after which we'll send a ping
define('HOST_TIMEOUT',             90);        # the time in seconds of silence after we will disconnect from a host
define('HOST_RECONN_TIMEOUT',    3);
define('HOST_RECONN_TRIES',        5);

define('CONN_TIMEOUT',            10);        # host long may a connection attempt last

define('CONN_NOTCONNECTED',        0);            # not connected to the host
define('CONN_CONNECTING',        1);            # in the process of connecting to the host
define('CONN_CONNECTED',        2);            # connected to a host
define('CONN_VERIFIED',            3);            # it has been verified that we have a working insim connection

define('SOCKTYPE_BEST',            0);
define('SOCKTYPE_TCP',            1);
define('SOCKTYPE_UDP',            2);

define('STREAM_READ_BYTES',        8192);
define('STREAM_WRITE_BYTES',    1400);

/**
 * HostHandler public functions :
 * ->initialise()                                    # (re)loads the config files and (re)connects to the host(s)
 * ->sendPacket($packetClass, $hostId = NULL)        # send a packet to either the last incoming host, or to $hostID
 * ->getHostsInfo()                                    # retrieve an array of information about all the hosts
 * ->getHostById(string $hostId)                    # get a host object by its hostID
 * ->getHostsByIp(string $ip)                        # get all hosts with a certain IP
**/
class HostHandler extends SectionHandler
{
    private $connvars        = array();
    private $hosts            = array();            # Stores references to the hosts we're connected to

    public $state            = array();

    public $curHostID        = NULL;                # Contains the current HostID we are talking to.

    public function &getCurrentHost()
    {
        return $this->curHostID;
    }

    public function __construct()
    {
        $this->iniFile = 'hosts.ini';
    }

    public function initialise()
    {
        global $PRISM;

        if ($this->loadIniFile($this->connvars))
        {
            foreach ($this->connvars as $hostID => $v)
            {
                if (!is_array($v))
                {
                    console('Section error in '.$this->iniFile.' file!');
                    return FALSE;
                }
            }
            if ($PRISM->config->cvars['debugMode'] & PRISM_DEBUG_CORE)
                console('Loaded '.$this->iniFile);
        }
        else
        {
            # We ask the client to manually input the connection details here.
            require_once(ROOTPATH . '/modules/prism_interactive.php');
            Interactive::queryHosts($this->connvars);

            # Then build a connections.ini file based on these details provided.
            if ($this->createIniFile('InSim Connection Hosts', $this->connvars))
                console('Generated config/'.$this->iniFile);
        }

        // Cleanup any existing connections (in case of re-initialise)
        $this->hosts = array();

        // Populate $this->hosts array from the connections.ini variables we've just read
        $this->populateHostsFromVars();

        return true;
    }

    private function populateHostsFromVars()
    {
        global $PRISM;

        $udpPortBuf = array();        // Duplicate udpPort (NLP/MCI or OutGauge port) value check array.

        foreach ($this->connvars as $hostID => $v)
        {
            if (isset($v['useRelay']) && $v['useRelay'] > 0)
            {
                // This is a Relay connection
                $hostName        = isset($v['hostname']) ? substr($v['hostname'], 0, 31) : '';
                $adminPass        = isset($v['adminPass']) ? substr($v['adminPass'], 0, 15) : '';
                $specPass        = isset($v['specPass']) ? substr($v['specPass'], 0, 15) : '';
                $prefix            = isset($v['prefix']) ? substr($v['prefix'], 0, 1) : '';

                // Some value checking - guess we should output some user notices here too if things go wrong.
                if ($hostName == '')
                    continue;

                $icVars = array (
                    'connType'        => CONNTYPE_RELAY,
                    'socketType'    => SOCKTYPE_TCP,
                    'id'             => $hostID,
                    'ip'            => $PRISM->config->cvars['relayIP'],
                    'port'            => $PRISM->config->cvars['relayPort'],
                    'hostName'        => $hostName,
                    'adminPass'        => $adminPass,
                    'specPass'        => $specPass,
                    'prefix'        => $prefix,
                    'pps'            => $PRISM->config->cvars['relayPPS'],
                );
                $ic = new InsimConnection($icVars);

                $this->hosts[$hostID] = $ic;
            }
            else
            {
                // This is a direct to host connection
                $ip                = isset($v['ip']) ? $v['ip'] : '';
                $port            = isset($v['port']) ? (int) $v['port'] : 0;
                $udpPort        = isset($v['udpPort']) ? (int) $v['udpPort'] : 0;
                $outgaugePort   = isset($v['outgaugePort']) ? (int) $v['outgaugePort'] : 0;
                $flags            = isset($v['flags']) ? (int) $v['flags'] : 72;
                $pps            = isset($v['pps']) ? (int) $v['pps'] : 3;
                $adminPass        = isset($v['password']) ? substr($v['password'], 0, 15) : '';
                $socketType        = isset($v['socketType']) ? (int) $v['socketType'] : SOCKTYPE_TCP;
                $prefix            = isset($v['prefix']) ? substr($v['prefix'], 0, 1) : '';

                // Some value checking
                if ($port < 1 || $port > 65535)
                {
                    console('Invalid port '.$port.' for '.$hostID);
                    console('Host '.$hostID.' will be excluded.');
                    continue;
                }
                if ($udpPort < 0 || $udpPort > 65535)
                {
                    console('Invalid UDP port '.$udpPort.' for '.$hostID);
                    console('Falling back to TCP.');
                    $udpPort = 0;
                }
                if ($outgaugePort < 0 || $outgaugePort > 65535)
                {
                    console('Invalid OutGauge port '.$outgaugePort.' for '.$hostID);
                    console('Outgauge will not work for host '.$hostID.'.');
                    $outgaugePort = 0;
                }
                if ($pps < 1 || $pps > 100)
                {
                    console('Invalid pps '.$pps.' for '.$hostID);
                    console('Host '.$hostID.' will be excluded.');
                    continue;
                }
                if ($socketType != SOCKTYPE_TCP && $socketType != SOCKTYPE_UDP)
                {
                    console('Invalid socket type set for '.$ip.':'.$port);
                    console('Host '.$hostID.' will be excluded.');
                    continue;
                }

                // Create new ic object
                $icVars = array (
                    'connType'        => CONNTYPE_HOST,
                    'socketType'    => $socketType,
                    'id'            => $hostID,
                    'ip'            => $ip,
                    'port'            => $port,
                    'udpPort'        => $udpPort,
                    'outgaugePort'    => $outgaugePort,
                    'flags'            => $flags,
                    'pps'            => $pps,
                    'adminPass'        => $adminPass,
                    'prefix'        => $prefix,
                );
                $ic = new InsimConnection($icVars);

                if ($ic->getUdpPort() > 0)
                {
                    if (in_array($ic->getUdpPort(), $udpPortBuf))
                    {
                        console('Duplicate udpPort value found! Every host must have its own unique udpPort. Not using additional port for this host.');
                        $ic->setUdpPort(0);
                    }
                    else
                    {
                        $udpPortBuf[] = $ic->getUdpPort();
                        if (!$ic->createMCISocket())
                        {
                            console('Host '.$hostID.' will be excluded.');
                            continue;
                        }
                    }
                }

                if ($ic->getOutgaugePort() > 0)
                {
                    if (in_array($ic->getOutgaugePort(), $udpPortBuf))
                    {
                        console('Duplicate outgaugePort value found! Every host must have its own unique outgaugePort. Not listening for OutGauge packets from host '.$hostID.'.');
                        $ic->setOutgaugePort(0);
                    }
                    else
                    {
                        $udpPortBuf[] = $ic->getOutgaugePort();
                        if (!$ic->createOutgaugeSocket())
                        {
                            console('Not listening for OutGauge packets from host '.$hostID.'.');
                            $ic->setOutgaugePort(0);
                        }
                    }
                }

                $this->hosts[$hostID] = $ic;
            }
        }
    }

    public function getSelectableSockets(array &$sockReads, array &$sockWrites)
    {
        foreach ($this->hosts as $hostID => $host)
        {
            if ($host->getConnStatus() >= CONN_CONNECTED)
            {
                    $sockReads[] = $host->getSocket();

                    // If the host is lagged, we must check to see when we can write again
                    if ($host->getSendQLen() > 0)
                        $sockWrites[] = $host->getSocket();
            }
            else if ($host->getConnStatus() == CONN_CONNECTING)
            {
                $sockWrites[] = $host->getSocket();
            }
            else
            {
                // Should we try to connect?
                if ($host->getMustConnect() > -1 && $host->getMustConnect() < time())
                {
                    if ($host->connect()) {
                        if ($host->getSocketType() == SOCKTYPE_TCP)
                            $sockWrites[] = $this->hosts[$hostID]->getSocket();
                        else
                            $sockReads[] = $this->hosts[$hostID]->getSocket();
                    }
                }
            }

            // Treat secondary socketMCI separately. This socket is always open.
            if ($host->getUdpPort() > 0 && is_resource($host->getSocketMCI()))
                $sockReads[] = $host->getSocketMCI();

            // Treat socketOutgauge separately. This socket is always open.
            if ($host->getOutgaugePort() > 0 && is_resource($host->getSocketOutgauge()))
                $sockReads[] = $host->getSocketOutgauge();
        }
    }

    public function checkTraffic(array &$sockReads, array &$sockWrites)
    {
        global $PRISM;

        $activity = 0;

        // Host traffic
        foreach($this->hosts as $hostID => $host)
        {
            // Finalise a tcp connection?
            if ($host->getConnStatus() == CONN_CONNECTING &&
                in_array($host->getSocket(), $sockWrites))
            {
                $activity++;

                // Check if remote replied negatively
                # Error suppressed, because of the underlying CRT (C Run Time) producing an error on Windows.
                $r = array($host->getSocket());
                $w = $e = array();
                $nr = @stream_select($r, $w, $e, 0);
                if ($nr > 0)
                {
                    // Experimentation showed that if something happened on this socket at this point,
                    // it is always an indication that the connection failed. We close this socket now.
                    $host->close();
                }
                else
                {
                    // The socket has become available for writing
                    $host->connectFinish();
                }
                unset($nr, $r, $w, $e);
            }

            // Recover a lagged host?
            if ($host->getConnStatus() >= CONN_CONNECTED &&
                $host->getSendQLen() > 0 &&
                in_array($host->getSocket(), $sockWrites))
            {
                $activity++;

                // Flush the sendQ and handle possible overload again
                $host->flushSendQ();
            }

            // Did the host send us something?
            if (in_array($host->getSocket(), $sockReads))
            {
                $activity++;
                $data = $packet = '';

                // Incoming traffic from a host
                $peerInfo = '';
                $data = $host->read($peerInfo);

                if (!$data)
                {
                    $host->close();
                }
                else
                {
                    if ($host->getSocketType() == SOCKTYPE_UDP)
                    {
                        // Check that this insim packet came from the IP we connected to
                        // UDP packet can be sent straight to packet parser
                        if ($host->getConnectIP().':'.$host->getPort() == $peerInfo)
                            $this->handlePacket($data, $hostID);
                    }
                    else
                    {
                        // TCP Stream requires buffering
                        $host->appendToBuffer($data);
                        while (true) {
                            //console('findloop');
                            $packet = $host->findNextPacket();
                            if (!$packet)
                                break;

                            // Handle the packet here
                            $this->handlePacket($packet, $hostID);
                        }
                    }
                }
            }

            // Did the host send us something on our separate udp port (if we have that active to begin with)?
            if ($host->getUdpPort() > 0 && in_array($host->getSocketMCI(), $sockReads))
            {
                $activity++;

                $peerInfo = '';
                $data = $host->readMCI($peerInfo);
                $exp = explode(':', $peerInfo);
                console('received '.strlen($data).' bytes on second socket');

                // Only process the packet if it came from the host's IP.
                if ($host->getConnectIP() == $exp[0])
                    $this->handlePacket($data, $hostID);
            }

            // Did the host send us something on our outgauge socket? (if we have that active to begin with)
            if ($host->getOutgaugePort() > 0 && in_array($host->getSocketOutgauge(), $sockReads))
            {
                $activity++;

                $peerInfo = '';
                $data = $host->readOutgauge($peerInfo);
                $exp = explode(':', $peerInfo);
                //console('received '.strlen($data).' bytes on outgauge socket');

                // Only process the packet if it came from the host's IP.
                if ($host->getConnectIP() == $exp[0])
                {
                    //echo "outgauge packet...\n";
                    $this->handleOutgaugePacket($data, $hostID);
                }
            }
        }

        return $activity;
    }

    public function maintenance()
    {
        // InSim Connection maintenance
        $c = 0;
        $d = 0;
        foreach($this->hosts as $hostID => $host)
        {
            $c++;
            if ($host->getConnStatus() == CONN_NOTCONNECTED)
            {
                if ($host->getMustConnect() == -1)
                    $d++;
                continue;
            }
            else if ($host->getConnStatus() == CONN_CONNECTING)
            {
                // Check to see if a connection attempt is going to time out.
                if ($host->getConnTime() < time() - CONN_TIMEOUT)
                {
                    console('Connection attempt to '.$host->getIP().':'.$host->getPort().' timed out');
                    $host->close();
                }
                continue;
            }

            // Does the connection appear to be dead? (LFS host not sending anything for more than HOST_TIMEOUT seconds
            if ($host->getLastReadTime() < time () - HOST_TIMEOUT)
            {
                console('Host '.$host->getIP().':'.$host->getPort().' timed out');
                $host->close();
            }

            // Do we need to keep the connection alive with a ping?
            if ($host->getLastWriteTime() < time () - KEEPALIVE_TIME)
            {
                $ISP = new IS_TINY();
                $ISP->SubT = TINY_NONE;
                $host->writePacket($ISP);
            }
        }

        // Are all hosts dead?
        if ($c == $d)
        {
            console('We cannot seem to successfully connect to any hosts. Exiting');
            return false;
        }
        return true;
    }

    private function handlePacket(&$rawPacket, &$hostID)
    {
        global $PRISM, $TYPEs, $TINY, $SMALL;

        // Check packet size
        if ((strlen($rawPacket) % 4) > 0)
        {
            // Packet size is not a multiple of 4
            console('WARNING : packet with invalid size ('.strlen($rawPacket).') from '.$hostID);

            // Let's clear the buffer to be sure, because remaining data cannot be trusted at this point.
            $this->hosts[$hostID]->clearBuffer();

            // Do we want to do anything else at this point?
            // Count errors? Disconnect host?
            // My preference would go towards counting the amount of times this error occurs and hang up after perhaps 3 errors.

            return;
        }

        $this->curHostId = $hostID; # To make sure we always know what host we are talking to, making the sendPacket function useful everywhere.

        # Parse Packet Header
        $pH = unpack('CSize/CType/CReqI/CSubT', $rawPacket);
        if (isset($TYPEs[$pH['Type']]))
        {
            if ($PRISM->config->cvars['debugMode'] & (PRISM_DEBUG_CORE + PRISM_DEBUG_MODULES))
            {
                switch ($pH['Type'])
                {
                    case ISP_TINY:
                        console("< ${TINY[$pH['SubT']]} Packet from {$hostID}.");
                    break;
                    case ISP_SMALL:
                        console("< ${SMALL[$pH['SubT']]} Packet from {$hostID}.");
                    break;
                    default:
                        console("< ${TYPEs[$pH['Type']]} Packet from {$hostID}.");
                }
            }
            $packet = new $TYPEs[$pH['Type']]($rawPacket);
            $this->inspectPacket($packet, $hostID);
        }
        else
        {
            console("Unknown Type Byte of ${pH['Type']}, with reported size of ${pH['Size']} Bytes and actual size of " . strlen($rawPacket) . ' Bytes.');
        }
    }

    private function handleOutgaugePacket(&$rawPacket, $hostID)
    {
        # Check packet size (without and with optional ID)
        $packetLen = strlen($rawPacket);

        if ($packetLen != OutGaugePack::LENGTH AND $packetLen != OutGaugePack::LENGTH + 4) {
            return console("WARNING : outgauge packet of invalid size ({$packetLen})");
        }

        # Parse packet
        $packet = new OutGaugePack($rawPacket);

        # Pass to outguage processor
        $this->inspectPacket($packet, $hostID);
    }

    // inspectPacket is used to act upon certain packets like error messages
    // We need these packets for proper basic PRISM connection functionality
    //
    private function inspectPacket(Struct &$packet, &$hostID)
    {
        global $PRISM;

        $this->curHostID = $hostID;
        switch($packet->Type)
        {
            case ISP_VER :
                // When receiving ISP_VER we can conclude that we now have a working insim connection.
                if ($this->hosts[$hostID]->getConnStatus() != CONN_VERIFIED) {
                    // Because we can receive more than one ISP_VER, we only set this the first time
                    $this->hosts[$hostID]->setConnStatus(CONN_VERIFIED);
                    $this->hosts[$hostID]->setConnTime(time());
                    $this->hosts[$hostID]->setConnTries(0);
                    // Here we setup the state for the connection.
                    $this->state[$hostID] = new StateHandler($packet);
                }
                $PRISM->plugins->dispatchPacket($packet, $hostID);
                break;

            case IRP_ERR :
                switch($packet->ErrNo)
                {
                    case IR_ERR_PACKET :
                        console('Invalid packet sent by client (wrong structure / length)');
                        break;

                    case IR_ERR_PACKET2 :
                        console('Invalid packet sent by client (packet was not allowed to be forwarded to host)');
                        break;

                    case IR_ERR_HOSTNAME :
                        console('Wrong hostname given by client');
                        break;

                    case IR_ERR_ADMIN :
                        console('Wrong admin pass given by client');
                        break;

                    case IR_ERR_SPEC :
                        console('Wrong spec pass given by client');
                        break;

                    case IR_ERR_NOSPEC :
                        console('Spectator pass required, but none given');
                        break;

                    default :
                        console('Unknown error received from relay ('.$packet->ErrNo.')');
                        break;
                }

                // Because of the error we close the connection to the relay.
                $this->hosts[$hostID]->close(true);
                break;

            case ISP_PLL :
            case ISP_CNL :
            case ISP_CPR :
                $PRISM->plugins->dispatchPacket($packet, $hostID);
                $this->state[$hostID]->dispatchPacket($packet);
                break;

            default:
                $this->state[$hostID]->dispatchPacket($packet);
                $PRISM->plugins->dispatchPacket($packet, $hostID);
                break;
        }
    }

    public function sendPacket(Struct $packetClass, $hostId = NULL)
    {
        if ($hostId === NULL)
            $hostId = $this->curHostID;

        $host = $this->hosts[$hostId];

        if($host == null){
            trigger_error('Attempted to check on invalid host.', E_USER_WARNING);
            return FALSE;
        }

        if ($host->isRelay())
        {
            if (!$host->isAdmin() &&
                (
                    ($packetClass instanceof IS_TINY && $packetClass->SubT == TINY_VTC)
                    || $packetClass instanceof IS_MST
                    || $packetClass instanceof IS_MSX
                    || $packetClass instanceof IS_MSL
                    || $packetClass instanceof IS_MTC
                    || $packetClass instanceof IS_SCH
                    || $packetClass instanceof IS_BFN
                    || $packetClass instanceof IS_BTN
                )
            )
            {
                trigger_error('Attempted to send invalid packet to relay host, packet not allowed to be forwarded without admin privileges.', E_USER_WARNING);
                return FALSE;
            }
            else if (
                $packetClass instanceof IS_TINY
                && ($packetClass->SubT == TINY_NLP
                || $packetClass->SubT == TINY_MCI
                || $packetClass->SubT == TINY_RIP)
            )
            {
                trigger_error('Attempted to send invalid packet to relay host, packet request makes no sense in this context.', E_USER_WARNING);
                return FALSE;
            }
        }else{
            if (($host->getFlags() & ISF_LOCAL) && $packetClass instanceof IS_MTC){
                trigger_error('Attempted to send invalid packet to single player host.', E_USER_WARNING);
                return FALSE;
            }
        }

        global $PRISM, $TYPEs, $TINY, $SMALL;
        if ($PRISM->config->cvars['debugMode'] & (PRISM_DEBUG_CORE + PRISM_DEBUG_MODULES))
        {
            switch ($packetClass->Type)
            {
                case ISP_TINY:
                    console("> ${TINY[$packetClass->SubT]} Packet to {$hostId}.");
                break;
                case ISP_SMALL:
                    console("> ${SMALL[$packetClass->SubT]} Packet to {$hostId}.");
                break;
                default:
                    console("> ${TYPEs[$packetClass->Type]} Packet to {$hostId}.");
            }
        }

        return $host->writePacket($packetClass);
    }

    public function &getHostsInfo()
    {
        $info = array();
        foreach ($this->hosts as $hostID => $host)
        {
            $info[] = array(
                'id'            => $hostID,
                'ip'            => $host->getIP(),
                'port'            => $host->getPort(),
                'useRelay'        => $host->isRelay(),
                'hostname'        => $host->getHostname(),
                'udpPort'        => $host->getUdpPort(),
                'flags'            => $host->getFlags(),
                'isAdmin'        => $host->isAdmin(),
                'connStatus'    => $host->getConnStatus(),
                'socketType'    => $host->getSocketType(),
            );
        }
        return $info;
    }

    public function getHostById($hostId = NULL)
    {
        if ($hostId == NULL)
            $hostId = $this->getCurrentHost();

        if (isset($this->hosts[$hostId]))
            return $this->hosts[$hostId];

        return NULL;
    }

    public function getHostsByIp($ip)
    {
        $hosts = array();
        foreach ($this->hosts as $hostID => $host)
        {
            if ($ip == $host->getIP())
                $hosts[$hostID] = $host;
        }
        return (count($hosts)) ? $hosts : null;
    }

    public function getStateById($hostId = NULL)
    {
        if ($hostId == NULL)
            $hostId = $this->getCurrentHost();

        if (isset($this->state[$hostId]))
            return $this->state[$hostId];

        return NULL;
    }
}

class InsimConnection
{
    private $connType;
    private $socketType;

    private $socket;
    private $socketMCI;                        # secondary, udp socket to listen on, if udpPort > 0
                                            # note that this follows the exact theory of how insim deals with tcp and udp sockets
                                            # see InSim.txt in LFS distributions for more info
    private $socketOutgauge;                # separate udp socket to listen on for outgauge packets, if outgaugePort > 0

    private $connStatus        = CONN_NOTCONNECTED;

    // Counters and timers
    private $mustConnect    = 0;
    private $connTries        = 0;
    private $connTime        = 0;
    private $lastReadTime    = 0;
    private $lastWriteTime    = 0;

    // TCP stream buffer
    private $streamBuf        = '';
    private $streamBufLen    = 0;

    // send queue used in emergency cases (if host appears lagged or overflown with packets)
    private $sendQ            = '';
    private $sendQLen        = 0;
    private $sendWindow        = STREAM_WRITE_BYTES;    // dynamic window size

    // connection & host info
    private $id                = '';            # the section id from the ini file
    private $ip                = '';            # ip or hostname to connect to
    private $connectIP        = '';            # the actual ip used to connect
    private $port            = 0;            # the port
    private $flags            = 72;            # Defaults to ISF_MSO_COLS (8) & ISF_CON (64) options on.
    private $udpPort        = 0;            # the secondary udp port to listen on for NLP/MCI packets, in case the main port is tcp
    private $outgaugePort    = 0;            # the outgauge udp port to listen on
    private $adminPass        = '';            # adminpass for both relay and direct usage
    private $specPass        = '';            # specpass for relay usage
    private $pps            = 3;
    private $hostName        = '';            # the hostname. Can be populated by user in case of relay.

    public function __construct(array &$icVars)
    {
    global $PRISM;

        $this->connType        = ($icVars['connType'] == CONNTYPE_RELAY) ? CONNTYPE_RELAY : CONNTYPE_HOST;
        $this->socketType    = ($icVars['socketType'] == SOCKTYPE_UDP) ? SOCKTYPE_UDP : SOCKTYPE_TCP;
        $this->id            = $icVars['id'];
        $this->ip            = $icVars['ip'];
        $this->port            = $icVars['port'];
        $this->flags        = $icVars['flags'];
        $this->pps            = $icVars['pps'];
        $this->adminPass    = $icVars['adminPass'];
        $this->prefix        = ($icVars['prefix'] == '') ? $PRISM->config->cvars['prefix'] : $icVars['prefix'];

        $this->udpPort        = isset($icVars['udpPort']) ? $icVars['udpPort'] : 0;
        $this->outgaugePort    = isset($icVars['outgaugePort']) ? $icVars['outgaugePort'] : 0;
        $this->hostName        = isset($icVars['hostName']) ? $icVars['hostName'] : '';
        $this->specPass        = isset($icVars['specPass']) ? $icVars['specPass'] : '';
    }

    public function __destruct()
    {
        $this->close(TRUE);
        if ($this->socketMCI)
            fclose($this->socketMCI);
        if ($this->socketOutgauge)
            fclose($this->socketOutgauge);
    }

    public function &getSocket()
    {
        return $this->socket;
    }

    public function &getSocketMCI()
    {
        return $this->socketMCI;
    }

    public function &getSocketOutgauge()
    {
        return $this->socketOutgauge;
    }

    public function &getSocketType()
    {
        return $this->socketType;
    }

    public function &getConnStatus()
    {
        return $this->connStatus;
    }

    public function setConnStatus($connStatus)
    {
        $this->connStatus = $connStatus;
    }

    public function &getMustConnect()
    {
        return $this->mustConnect;
    }

    public function setConnTries($connTries)
    {
        $this->connTries = $connTries;
    }

    public function setConnTime($connTime)
    {
        $this->connTime = $connTime;
    }

    public function &getConnTime()
    {
        return $this->connTime;
    }

    public function &getLastReadTime()
    {
        return $this->lastReadTime;
    }

    public function &getLastWriteTime()
    {
        return $this->lastWriteTime;
    }

    public function &getConnectIP()
    {
        return $this->connectIP;
    }

    public function &getIP()
    {
        return $this->ip;
    }

    public function &getPort()
    {
        return $this->port;
    }

    public function &getUdpPort()
    {
        return $this->udpPort;
    }

    public function &getOutgaugePort()
    {
        return $this->outgaugePort;
    }

    public function &getFlags()
    {
        return $this->flags;
    }

    public function &getPPS()
    {
        return $this->pps;
    }

    public function isAdmin()
    {
        return ($this->adminPass != '') ? TRUE : FALSE;
    }

    public function isRelay()
    {
        return ($this->connType == CONNTYPE_RELAY) ? TRUE : FALSE;
    }

    public function &getHostname()
    {
        return $this->hostName;
    }

    public function setUdpPort($udpPort)
    {
        // Set the new value
        $this->udpPort = $udpPort;

        // Should we reinit the udp listening socket?
        $this->closeMCISocket();
        $this->createMCISocket();
    }

    public function setOutgaugePort($outgaugePort)
    {
        // Set the new value
        $this->outgaugePort = $outgaugePort;

        // Should we reinit the udp listening socket?
        $this->closeOutgaugeSocket();
        $this->createOutgaugeSocket();
    }

    public function &getSendQLen()
    {
        return $this->sendQLen;
    }

    public function connect()
    {
        // If we're already connected, then we'll assume this is a forced reconnect, so we'll close
        $this->close(FALSE, TRUE);

        // Figure out the proper IP address. We do this every time we connect in case of dynamic IP addresses.
        $this->connectIP = getIP($this->ip);
        if (!$this->connectIP)
        {
            console('Cannot connect to host, Invalid IP : '.$this->ip.':'.$this->port);
            $this->socket        = NULL;
            $this->connStatus    = CONN_NOTCONNECTED;
            $this->mustConnect    = -1;                    // Something completely failed - we will no longer try this connection
            return FALSE;
        }

        if ($this->socketType == SOCKTYPE_UDP)
            $this->connectUDP();
        else
            $this->connectTCP();

        return true;
    }

    public function connectUDP()
    {
        // Create UDP socket
        $this->socket = @stream_socket_client('udp://'.$this->connectIP.':'.$this->port, $sockErrNo, $sockErrStr);
        if ($this->socket === FALSE || $sockErrNo)
        {
            console ('Error opening UDP socket for '.$this->connectIP.':'.$this->port.' : '.$sockErrStr);
            $this->socket        = NULL;
            $this->connStatus    = CONN_NOTCONNECTED;
            $this->mustConnect    = -1;                    // Something completely failed - we will no longer try this connection
            return FALSE;
        }

        // We set the connection time here, so we can track how long we're trying to connect
        $this->connTime = time();

        console('Connecting to '.$this->ip.':'.$this->port.' ... #'.($this->connTries + 1));
        $this->connectFinish();
        $this->lastReadTime = time() - HOST_TIMEOUT + 10;

        return TRUE;
    }

    public function connectTCP()
    {
        // If we're already connected, then we'll assume this is a forced reconnect, so we'll close
        $this->close(FALSE, TRUE);

        // Here we create the socket and initiate the connection. This is done asynchronously.
        $this->socket = @stream_socket_client('tcp://'.$this->connectIP.':'.$this->port,
                                                $sockErrNo,
                                                $sockErrStr,
                                                CONN_TIMEOUT,
                                                STREAM_CLIENT_CONNECT | STREAM_CLIENT_ASYNC_CONNECT);
        if ($this->socket === FALSE || $sockErrNo)
        {
            console ('Error opening TCP socket for '.$this->connectIP.':'.$this->port.' : '.$sockErrStr);
            $this->socket        = NULL;
            $this->connStatus    = CONN_NOTCONNECTED;
            $this->mustConnect    = -1;                    // Something completely failed - we will no longer try this connection
            return FALSE;
        }

        // Set socket status to 'SYN sent'
        $this->connStatus = CONN_CONNECTING;
        // We set the connection time here, so we can track how long we're trying to connect
        $this->connTime = time();

        stream_set_blocking($this->socket, 0);

        console('Connecting to '.$this->ip.':'.$this->port.' ... #'.($this->connTries + 1));

        return TRUE;
    }

    public function connectFinish()
    {
        // Here we finalise the connection cycle. Send an init packet to start the insim stream and while at it, detect if the socket is real.
        $this->connStatus    = CONN_CONNECTED;

        if ($this->connType == CONNTYPE_HOST)
        {
            // Send IS_ISI packet
            $ISP            = new IS_ISI();
            $ISP->ReqI        = TRUE;
            $ISP->UDPPort    = (isset($this->udpPort) && $this->udpPort > 0) ? $this->udpPort : 0;
            $ISP->Flags        = (isset($this->flags)) ? $this->flags : ISF_MSO_COLS & ISF_CON;
            $ISP->Prefix    = (isset($this->prefix)) ? ord($this->prefix) : ord('!');
            $ISP->Interval    = round(1000 / $this->pps);
            $ISP->Admin        = $this->adminPass;
            $ISP->IName        = 'PRISM v' . PHPInSimMod::VERSION;
            $this->writePacket($ISP);
        }
        else if ($this->connType == CONNTYPE_RELAY)
        {
            // Send IR_SEL packet
            $SEL            = new IR_SEL();
            $SEL->ReqI        = TRUE;
            $SEL->HName        = $this->hostName;
            $SEL->Admin        = $this->adminPass;
            $SEL->Spec        = $this->specPass;
            $this->writePacket($SEL);
        }
        else
        {
            // I'm not sure what we connected to. Shouldn't be possible. Permanently close.
            $this->close(TRUE);
        }

        console('Connected to '.$this->ip.':'.$this->port);
    }

    public function createMCISocket()
    {
        $this->closeMCISocket();
        if ($this->udpPort == 0)
            return TRUE;

        $this->socketMCI = @stream_socket_server('udp://0.0.0.0:'.$this->udpPort, $errNo, $errStr, STREAM_SERVER_BIND);
        if (!$this->socketMCI || $errNo > 0)
        {
            console ('Error opening additional UDP socket to listen on : '.$errStr);
            $this->socketMCI    = NULL;
            $this->udpPort        = 0;
            return FALSE;
        }

        console('Listening for NLP/MCI on secondary UDP port '.$this->udpPort);

        return TRUE;
    }

    private function closeMCISocket()
    {
        if (is_resource($this->socketMCI))
            fclose($this->socketMCI);
        $this->socketMCI = NULL;
    }

    public function createOutgaugeSocket()
    {
        $this->closeOutgaugeSocket();
        if ($this->outgaugePort == 0)
            return TRUE;

        $this->socketOutgauge = @stream_socket_server('udp://0.0.0.0:'.$this->outgaugePort, $errNo, $errStr, STREAM_SERVER_BIND);
        if (!$this->socketOutgauge || $errNo > 0)
        {
            console ('Error opening OutGauge UDP socket to listen on : '.$errStr);
            $this->socketOutgauge    = NULL;
            $this->outgaugePort        = 0;
            return FALSE;
        }

        console('Listening for OutGauge packets on UDP port '.$this->outgaugePort);

        return TRUE;
    }

    private function closeOutgaugeSocket()
    {
        if (is_resource($this->socketOutgauge))
            fclose($this->socketOutgauge);
        $this->socketOutgauge = NULL;
    }

    // $permanentClose    - set to TRUE to close this connection once and for all.
    // $quick            - set to TRUE to bypass the reconnection mechanism. If TRUE this disconnect would not count towards the reconnection counter.
    //
    public function close($permanentClose = FALSE, $quick = FALSE)
    {
        if (is_resource($this->socket))
        {
            if ($this->connStatus == CONN_VERIFIED && $this->connType == CONNTYPE_HOST)
            {
                // Send goodbye packet to host
                $ISP        = new IS_TINY();
                $ISP->SubT    = TINY_CLOSE;
                $this->writePacket($ISP);
            }

            fclose($this->socket);
            console('Closed connection to '.$this->ip.':'.$this->port);
        }

        // (re)set some variables.
        $this->socket            = NULL;
        $this->connStatus        = CONN_NOTCONNECTED;
        $this->lastReadTime        = 0;
        $this->lastWriteTime    = 0;
        $this->clearBuffer();
        $this->sendQReset();

        if ($quick)
            return;

        if (!$permanentClose)
        {
            if (++$this->connTries < HOST_RECONN_TRIES)
                $this->mustConnect = time() + HOST_RECONN_TIMEOUT;
            else
            {
                console('Cannot seem to connect to '.$this->ip.':'.$this->port.' - giving up ...');
                $this->mustConnect = -1;
            }
        }
        else
            $this->mustConnect = -1;
    }

    public function writePacket(Struct &$packet)
    {
        if ($this->socketType    == SOCKTYPE_UDP)
            return $this->writeUDP($packet->pack());
        else
            return $this->writeTCP($packet->pack());
    }

    public function writeUDP($data)
    {
        $this->lastWriteTime = time();
        if (($bytes = @fwrite($this->socket, $data)) === FALSE)
            console('UDP: Error sending packet through socket.');
        return $bytes;
    }

    public function writeTCP($data, $sendQPacket = FALSE)
    {
        $bytes = 0;

        if ($this->connStatus < CONN_CONNECTED)
            return $bytes;

        if ($sendQPacket == TRUE)
        {
            // This packet came from the sendQ. We just try to send this and don't bother too much about error checking.
            // That's done from the sendQ flushing code.
            if (($bytes = @fwrite($this->socket, $data)) === FALSE)
                console('TCP: Error sending packet through socket.');
        }
        else
        {
            if ($this->sendQLen == 0)
            {
                // It's Ok to send packet
                if (($bytes = @fwrite($this->socket, $data)) === FALSE)
                    console('TCP: Error sending packet through socket.');
                $this->lastWriteTime = time();

                if (!$bytes || $bytes != strlen($data))
                {
                    $this->addPacketToSendQ (substr($data, $bytes));
                }
            }
            else
            {
                // Host is lagged
                $this->addPacketToSendQ ($data);
            }
        }

        return $bytes;
    }

    private function addPacketToSendQ($data)
    {
        $this->sendQ .= $data;
        $this->sendQLen += strlen($data);
    }

    public function flushSendQ()
    {
        // Send chunk of data
        $bytes = $this->writeTCP(substr($this->sendQ, 0, $this->sendWindow), TRUE);

        // Dynamic window sizing
        if ($bytes == $this->sendWindow)
            $this->sendWindow += STREAM_WRITE_BYTES;
        else
        {
            $this->sendWindow -= STREAM_WRITE_BYTES;
            if ($this->sendWindow < STREAM_WRITE_BYTES)
                $this->sendWindow = STREAM_WRITE_BYTES;
        }

        // Update the sendQ
        $this->sendQ = substr($this->sendQ, $bytes);
        $this->sendQLen -= $bytes;

        // Cleanup / reset timers
        if ($this->sendQLen == 0)
        {
            // All done flushing - reset queue variables
            $this->sendQReset();
        }

        if ($bytes > 0)
            $this->lastWriteTime    = time();
        //console('Bytes sent : '.$bytes.' - Bytes left : '.$this->sendQLen.' - '.$this->ip);
    }

    private function sendQReset()
    {
        $this->sendQ            = '';
        $this->sendQLen            = 0;
        $this->lastActivity        = time();
    }

    public function read(&$peerInfo)
    {
        $this->lastReadTime = time();
        if ($this->socketType == SOCKTYPE_TCP)
            return fread($this->socket, STREAM_READ_BYTES); #stream_socket_recvfrom was crashing with TCP packets

        return stream_socket_recvfrom($this->socket, STREAM_READ_BYTES, 0, $peerInfo);
    }

    public function readMCI(&$peerInfo)
    {
        $this->lastReadTime = time();
        return stream_socket_recvfrom($this->socketMCI, STREAM_READ_BYTES, 0, $peerInfo);
    }

    public function readOutgauge(&$peerInfo)
    {
        $this->lastReadTime = time();
        return stream_socket_recvfrom($this->socketOutgauge, STREAM_READ_BYTES, 0, $peerInfo);
    }

    public function appendToBuffer(&$data)
    {
        $this->streamBuf    .= $data;
        $this->streamBufLen    = strlen ($this->streamBuf);
    }

    public function clearBuffer()
    {
        $this->streamBuf    = '';
        $this->streamBufLen    = 0;
    }

    public function findNextPacket()
    {
        if ($this->streamBufLen == 0)
            return FALSE;

        $sizebyte = ord($this->streamBuf[0]);
        if ($sizebyte == 0)
        {
            return FALSE;
        }
        else if ($this->streamBufLen < $sizebyte)
        {
            //console('Split packet ...');
            return FALSE;
        }

        // We should have a whole packet in the buffer now
        $packet                    = substr($this->streamBuf, 0, $sizebyte);
        $packetType                = ord($packet[1]);

        // Cleanup streamBuffer
        $this->streamBuf        = substr($this->streamBuf, $sizebyte);
        $this->streamBufLen        = strlen($this->streamBuf);

        return $packet;
    }
}

?>


text:
<?php

namespace FOS\MessageBundle\SpamDetection;

use FOS\MessageBundle\FormModel\NewThreadMessage;

class NoopSpamDetector implements SpamDetectorInterface
{
    /**
     * Tells whether or not a new message looks like spam
     *
     * @param NewThreadMessage $message
     * @return boolean true if it is spam, false otherwise
     */
    public function isSpam(NewThreadMessage $message)
    {
        return false;
    }
}


text:
package cn.felord.wepay.ali.sdk.api.domain;

import cn.felord.wepay.ali.sdk.api.AlipayObject;
import cn.felord.wepay.ali.sdk.api.internal.mapping.ApiField;

/**
 * 教育缴费学校信息录入接口
 *
 * @author auto create
 * @version $Id: $Id
 */
public class AlipayEcoEduKtSchoolinfoModifyModel extends AlipayObject {

	private static final long serialVersionUID = 1154744342286347473L;

	/**
	 * 银行卡编号。适配集团到卡模式的学校接入
	 */
	@ApiField("bankcard_no")
	private String bankcardNo;

	/**
	 * 市的国家编码
	 */
	@ApiField("city_code")
	private String cityCode;

	/**
	 * 城市名称
	 */
	@ApiField("city_name")
	private String cityName;

	/**
	 * 区县的国家编码
	 */
	@ApiField("district_code")
	private String districtCode;

	/**
	 * 区县名称
	 */
	@ApiField("district_name")
	private String districtName;

	/**
	 * 商家名称
	 */
	@ApiField("isv_name")
	private String isvName;

	/**
	 * 商家编码,ISV_NO
	 */
	@ApiField("isv_no")
	private String isvNo;

	/**
	 * 此链接是为了保持教育缴费平台与ISV
商户支付状态一致性。用户支付成功后,会异步回调此链接,回调时,会带入支付的相关参数,ISV商户可以根据返回的参数更新账单状态。支付宝异步通知说明
	 */
	@ApiField("isv_notify_url")
	private String isvNotifyUrl;

	/**
	 * Isv支付宝pid,商家在支付宝的唯一标识
	 */
	@ApiField("isv_phone")
	private String isvPhone;

	/**
	 * Isv支付宝pid,用于支付返佣
	 */
	@ApiField("isv_pid")
	private String isvPid;

	/**
	 * 省的国家编码
	 */
	@ApiField("province_code")
	private String provinceCode;

	/**
	 * 省名称
	 */
	@ApiField("province_name")
	private String provinceName;

	/**
	 * 学校的图像,一般为学校的标识,该字段为图片的链接地址,只支持png或jpg图片格式,图片高度为108,宽度为108 ,不大于20k
	 */
	@ApiField("school_icon")
	private String schoolIcon;

	/**
	 * 如果学校图像数据填写,则此字段不能为空。目前只支持png和jpg两种格式
	 */
	@ApiField("school_icon_type")
	private String schoolIconType;

	/**
	 * 学校名称
	 */
	@ApiField("school_name")
	private String schoolName;

	/**
	 * 学校支付宝pid,用于授权
	 */
	@ApiField("school_pid")
	private String schoolPid;

	/**
	 * 学校的国家标准编码
	 */
	@ApiField("school_stdcode")
	private String schoolStdcode;

	/**
	 * 学校的类型:托幼小初高。1、托, 2、幼,  3、小,  4、初,  5、高。如果学校兼有多种属性,可以写为:初高中为45 , 小初为34
	 */
	@ApiField("school_type")
	private String schoolType;

	/**
	 *
Getter for the field bankcardNo.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getBankcardNo() {
		return this.bankcardNo;
	}
	/**
	 *
Setter for the field bankcardNo.

	 *
	 * @param bankcardNo a {@link java.lang.String} object.
	 */
	public void setBankcardNo(String bankcardNo) {
		this.bankcardNo = bankcardNo;
	}

	/**
	 *
Getter for the field cityCode.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getCityCode() {
		return this.cityCode;
	}
	/**
	 *
Setter for the field cityCode.

	 *
	 * @param cityCode a {@link java.lang.String} object.
	 */
	public void setCityCode(String cityCode) {
		this.cityCode = cityCode;
	}

	/**
	 *
Getter for the field cityName.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getCityName() {
		return this.cityName;
	}
	/**
	 *
Setter for the field cityName.

	 *
	 * @param cityName a {@link java.lang.String} object.
	 */
	public void setCityName(String cityName) {
		this.cityName = cityName;
	}

	/**
	 *
Getter for the field districtCode.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getDistrictCode() {
		return this.districtCode;
	}
	/**
	 *
Setter for the field districtCode.

	 *
	 * @param districtCode a {@link java.lang.String} object.
	 */
	public void setDistrictCode(String districtCode) {
		this.districtCode = districtCode;
	}

	/**
	 *
Getter for the field districtName.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getDistrictName() {
		return this.districtName;
	}
	/**
	 *
Setter for the field districtName.

	 *
	 * @param districtName a {@link java.lang.String} object.
	 */
	public void setDistrictName(String districtName) {
		this.districtName = districtName;
	}

	/**
	 *
Getter for the field isvName.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getIsvName() {
		return this.isvName;
	}
	/**
	 *
Setter for the field isvName.

	 *
	 * @param isvName a {@link java.lang.String} object.
	 */
	public void setIsvName(String isvName) {
		this.isvName = isvName;
	}

	/**
	 *
Getter for the field isvNo.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getIsvNo() {
		return this.isvNo;
	}
	/**
	 *
Setter for the field isvNo.

	 *
	 * @param isvNo a {@link java.lang.String} object.
	 */
	public void setIsvNo(String isvNo) {
		this.isvNo = isvNo;
	}

	/**
	 *
Getter for the field isvNotifyUrl.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getIsvNotifyUrl() {
		return this.isvNotifyUrl;
	}
	/**
	 *
Setter for the field isvNotifyUrl.

	 *
	 * @param isvNotifyUrl a {@link java.lang.String} object.
	 */
	public void setIsvNotifyUrl(String isvNotifyUrl) {
		this.isvNotifyUrl = isvNotifyUrl;
	}

	/**
	 *
Getter for the field isvPhone.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getIsvPhone() {
		return this.isvPhone;
	}
	/**
	 *
Setter for the field isvPhone.

	 *
	 * @param isvPhone a {@link java.lang.String} object.
	 */
	public void setIsvPhone(String isvPhone) {
		this.isvPhone = isvPhone;
	}

	/**
	 *
Getter for the field isvPid.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getIsvPid() {
		return this.isvPid;
	}
	/**
	 *
Setter for the field isvPid.

	 *
	 * @param isvPid a {@link java.lang.String} object.
	 */
	public void setIsvPid(String isvPid) {
		this.isvPid = isvPid;
	}

	/**
	 *
Getter for the field provinceCode.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getProvinceCode() {
		return this.provinceCode;
	}
	/**
	 *
Setter for the field provinceCode.

	 *
	 * @param provinceCode a {@link java.lang.String} object.
	 */
	public void setProvinceCode(String provinceCode) {
		this.provinceCode = provinceCode;
	}

	/**
	 *
Getter for the field provinceName.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getProvinceName() {
		return this.provinceName;
	}
	/**
	 *
Setter for the field provinceName.

	 *
	 * @param provinceName a {@link java.lang.String} object.
	 */
	public void setProvinceName(String provinceName) {
		this.provinceName = provinceName;
	}

	/**
	 *
Getter for the field schoolIcon.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getSchoolIcon() {
		return this.schoolIcon;
	}
	/**
	 *
Setter for the field schoolIcon.

	 *
	 * @param schoolIcon a {@link java.lang.String} object.
	 */
	public void setSchoolIcon(String schoolIcon) {
		this.schoolIcon = schoolIcon;
	}

	/**
	 *
Getter for the field schoolIconType.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getSchoolIconType() {
		return this.schoolIconType;
	}
	/**
	 *
Setter for the field schoolIconType.

	 *
	 * @param schoolIconType a {@link java.lang.String} object.
	 */
	public void setSchoolIconType(String schoolIconType) {
		this.schoolIconType = schoolIconType;
	}

	/**
	 *
Getter for the field schoolName.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getSchoolName() {
		return this.schoolName;
	}
	/**
	 *
Setter for the field schoolName.

	 *
	 * @param schoolName a {@link java.lang.String} object.
	 */
	public void setSchoolName(String schoolName) {
		this.schoolName = schoolName;
	}

	/**
	 *
Getter for the field schoolPid.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getSchoolPid() {
		return this.schoolPid;
	}
	/**
	 *
Setter for the field schoolPid.

	 *
	 * @param schoolPid a {@link java.lang.String} object.
	 */
	public void setSchoolPid(String schoolPid) {
		this.schoolPid = schoolPid;
	}

	/**
	 *
Getter for the field schoolStdcode.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getSchoolStdcode() {
		return this.schoolStdcode;
	}
	/**
	 *
Setter for the field schoolStdcode.

	 *
	 * @param schoolStdcode a {@link java.lang.String} object.
	 */
	public void setSchoolStdcode(String schoolStdcode) {
		this.schoolStdcode = schoolStdcode;
	}

	/**
	 *
Getter for the field schoolType.

	 *
	 * @return a {@link java.lang.String} object.
	 */
	public String getSchoolType() {
		return this.schoolType;
	}
	/**
	 *
Setter for the field schoolType.

	 *
	 * @param schoolType a {@link java.lang.String} object.
	 */
	public void setSchoolType(String schoolType) {
		this.schoolType = schoolType;
	}

}


text:
- Design Google docs.
- Design a collaborative code editor like Coderpad/Codepile.
- Design a collaborative markdown editor.

## Requirements Gathering

- What is the intended platform?
  - Web
- What features are required?
  - Creating a document
  - Editing a document
  - Sharing a document
- Bonus features
  - Document revisions and reverting
  - Searching
  - Commenting
  - Chatting
  - Executing code (in the case of code editor)
- What is in a document?
  - Text
  - Images
- Which metrics should we optimize for?
  - Loading time
  - Synchronization
  - Throughput

## Core Components

- Front end
  - WebSockets/long polling for real-time communication between front end and back end.
- Back end services behind a reverse proxy.
  - Reverse proxy will proxy the requests to the right server.
  - Split into a few services for different purposes.
  - The benefit of this is that each service can use different languages that best suits its purpose.
- API servers for non-collaborative features and endpoints.
  - Ruby/Rails/Django for the server that deals with CRUD operations on data models where performance is not that crucial.
- WebSocket servers for handling document edits and publishing updates to listeners.
  - Possibly Node/Golang for WebSocket server which will need high performance as updates are frequent.
- Task queue to persist document updates to the database.
- ELB in front of back end servers.
- MySQL database.
- S3 and CDN for images.

## Data Modeling

- What kind of database to use?
  - Data is quite structured. Would go with SQL.
- Design the necessary tables, its columns and its relations.
  - `users`
    - `id`
    - `name`
  - `document`
    - `id`
    - `owner_id`
  - `permissions`
    - `id`
    - `name`
  - `document_permissions`
    - `id`
    - `document_id`
    - `user_id`

## Collaborative Editing - Client

- Upon loading of the page and document, the client should connect to the WebSocket server over the WebSocket protocol `ws://`.
- Upon connection, perform a time sync with the server, possibly via Network Time Protocol (NTP).
- The most straightforward way is to send the whole updated document content to the back end, and all users currently viewing the document will receive the updated document. However, there are a few problems with this approach:
  - Race condition. If two users editing the document at the same time, the last one to edit will overwrite the changes by the previous user. One workaround is to lock the document when a user is currently editing it, but that will not make it real-time collaborative.
  - A large payload (the whole document) is being sent to servers and published to users on each change, and the user is likely to already have most of the content. A lot of redundant data being sent.
- A feasible approach would be to use operational transforms and send just the action deltas to the back end. The back end publishes the action deltas to the listeners. What is considered an action delta?
  - (a) Changing a character/word, (b) inserting a character/word/image, (c) deleting a character/word.
  - With this approach, the payload will contain only small amount of data, such as (a) type of change, (b) character/word, (c) position in document: line/column, (d) timestamp. Why is the timestamp needed? Read on to find out.
- Updates can also be throttled and batched, to avoid flooding the web server with requests. For example, if a user inserts a

## Back End

The back end is split into a few portions: WebSocket server for receiving and broadcasting document updates, CRUD server for reading and writing non-document-related data, and a task queue for persistence of the document.

## WebSocket Server

- Languages and frameworks that support async requests and non-blocking I/O will be suitable for the collaborative editor server. Node and Golang comes to my mind.
- However, the WebSocket server is not stateless, so is it not that straightforward to scale horizontally. One approach would be for a Load Balancer to use Redis to maintain a map of the client to the WebSocket server instance IP, such that subsequent requests from the same client will be routed to the same server.
- Each document corresponds to a room (more of namespace). Users can subscribe to the events happening within a room.
- When a action delta is being received, blast it out to the listeners within the room and add it to the task queue.

## CRUD Server

- Provides APIs for reading and writing non-document-related data, such as users, permissions.

## Task Queue + Worker Service

- Worker service retrieves messages from the task queue and writes the updated documents to the database in an async fashion.
- Batch the actions together and perform one larger write that consists of multiple actions. For example, instead of persisting to the database once per addition of a word, combine these additions and write them into the database at once.
- Publish the save completion event to the WebSocket server to be published to the listeners, informing that the latest version of the document is being saved.
- Benefit of using a task queue is that as the amount of tasks in the queue goes up, we can scale up the number of worker services to clear the backlog of work faster.

## Document Persistence

TODO

###### References

- http://blog.gainlo.co/index.php/2016/03/22/system-design-interview-question-how-to-design-google-docs/


text:
package irc

import (
	"testing"
)

func TestUserHandlerNames(t *testing.T) {
	state := make(chan state, 1)
	handler := func() handler { return newUserHandler(state, "nick") }
	testHandler(t, "userHandler-NAMES", state, handler, []handlerTest{
		{
			desc: "names successful",
			in:   []message{cmdNames.withParams("#channel")},
			wantNicks: map[string]mockConnection{
				"nick": mockConnection{
					messages: []message{
						replyNamReply,
						replyNamReply,
						replyNamReply,
						replyNamReply,
						replyEndOfNames,
					},
				},
			},
			state: newMockState().
				withChannel("#channel", "", "").
				withUser("nick", "#channel").
				withUser("foo", "#channel").
				withUser("bar", "#channel").
				// User baz should be listed even though they are invisible because
				// they share a channel with the user that is requesting names.
				withUser("baz", "#channel").
				withUserMode("baz", "i"),
		},
		{
			desc: "names all",
			in:   []message{cmdNames.withParams()},
			wantNicks: map[string]mockConnection{
				"nick": mockConnection{
					messages: []message{
						replyNamReply,
						replyEndOfNames,
						replyNamReply,
						replyEndOfNames,
					},
				},
			},
			state: newMockState().
				withChannel("#foo", "", "").
				withChannel("#bar", "", "").
				withUser("nick").
				withUser("foo", "#foo").
				withUser("bar", "#bar").
				// User baz should not be listed because their are invisible.
				withUser("baz", "#bar").
				withUserMode("baz", "i"),
		},
		{
			desc: "names all private",
			in:   []message{cmdNames.withParams()},
			wantNicks: map[string]mockConnection{
				"nick": mockConnection{
					messages: []message{},
				},
			},
			state: newMockState().
				withChannel("#foo", "p", "").
				withUser("nick").
				withUser("foo", "#foo"),
		},
		{
			desc: "names successful private",
			in:   []message{cmdNames.withParams("#channel")},
			wantNicks: map[string]mockConnection{
				"nick": mockConnection{
					messages: []message{
						replyNamReply,
						replyNamReply,
						replyNamReply,
						replyEndOfNames,
					},
				},
			},
			state: newMockState().
				withChannel("#channel", "p", "").
				withUser("nick", "#channel").
				withUser("foo", "#channel").
				withUser("bar", "#channel"),
		},
		{
			desc: "names fails private",
			in:   []message{cmdNames.withParams("#channel")},
			wantNicks: map[string]mockConnection{
				"nick": mockConnection{
					messages: []message{},
				},
			},
			state: newMockState().
				withChannel("#channel", "p", "").
				withUser("nick").
				withUser("foo", "#channel").
				withUser("bar", "#channel"),
		},
		{
			desc: "names all secret",
			in:   []message{cmdNames.withParams()},
			wantNicks: map[string]mockConnection{
				"nick": mockConnection{
					messages: []message{},
				},
			},
			state: newMockState().
				withChannel("#foo", "s", "").
				withUser("nick").
				withUser("foo", "#foo"),
		},
		{
			desc: "names successful secret",
			in:   []message{cmdNames.withParams("#channel")},
			wantNicks: map[string]mockConnection{
				"nick": mockConnection{
					messages: []message{
						replyNamReply,
						replyNamReply,
						replyNamReply,
						replyEndOfNames,
					},
				},
			},
			state: newMockState().
				withChannel("#channel", "s", "").
				withUser("nick", "#channel").
				withUser("foo", "#channel").
				withUser("bar", "#channel"),
		},
		{
			desc: "names fails secret",
			in:   []message{cmdNames.withParams("#channel")},
			wantNicks: map[string]mockConnection{
				"nick": mockConnection{
					messages: []message{},
				},
			},
			state: newMockState().
				withChannel("#channel", "s", "").
				withUser("nick").
				withUser("foo", "#channel").
				withUser("bar", "#channel"),
		},
	})
}


text:
app.controller('article.list', ['$scope', 'Restangular', '$routeParams', '$log',
    function ($scope, Restangular, $routeParams, $log) {

    $log = $log.getInstance('article.list');

    $scope.currentPage = 1;
    if($routeParams.page) {
        $scope.currentPage = $routeParams.page;
    }

    $log.debug('Page ' + $scope.currentPage );

    Restangular.all("articles").getList({'page': $scope.currentPage}).then(function(articles) {
        $scope.articles = articles;
        $scope.totalItems = articles.meta.total;
        $scope.itemsPerPage = articles.meta.perPage;
    });

    $scope.setPage = function (pageNumber) {
        $scope.currentPage = pageNumber;
        $log.debug('Change to  ' + pageNumber );
    };

    $scope.pageChanged = function() {
        $log.debug('Page changed to: ' + $scope.currentPage);
        Restangular.all("articles").getList({
            'page': $scope.currentPage
        }).then(function(articles) {
            $scope.articles = articles;
        });
    };
}]);

app.controller('article.uncategorize', ['$scope', 'Restangular', '$routeParams', '$log',
    function ($scope, Restangular, $routeParams, $log) {

    $log = $log.getInstance('article.uncategorize');

    $scope.currentPage = 1;
    if($routeParams.page) {
        $scope.currentPage = $routeParams.page;
    }

    $log.debug('Page ' + $scope.currentPage );

    Restangular.all("articles").noCategory({'page': $scope.currentPage}).then(function(articles) {
        $scope.articles = articles;
        $scope.totalItems = articles.meta.total;
        $scope.itemsPerPage = articles.meta.perPage;
    });

    $scope.setPage = function (pageNumber) {
        $scope.currentPage = pageNumber;
        $log.debug('Change to  ' + pageNumber );
    };

    $scope.pageChanged = function() {
        $log.debug('Page changed to: ' + $scope.currentPage);
        Restangular.all("articles").noCategory({
            'page': $scope.currentPage
        }).then(function(articles) {
            $scope.articles = articles;
        });
    };
}]);

app.controller('article.get', ['$rootScope', '$scope', 'Restangular', '$routeParams', '$log', 'math', 'apiUrl',
    function ($rootScope, $scope, Restangular, $routeParams, $log, math, apiUrl) {
    $log = $log.getInstance('article.get');

    $log.debug('Get article #' + $routeParams.id );

    $scope.currentPage = 1;
    if($routeParams.page) {
        $scope.currentPage = $routeParams.page;
    }

    $scope.errors = {};
    $scope.alert = '';

    var updateNotes = function (page) {
        $scope.article.getList('notes', {
            'page' : $scope.currentPage
        }).then(function(notes) {
            $scope.article.notes = notes;
            $scope.totalItems = notes.meta.total;
            $scope.itemsPerPage = notes.meta.perPage;
        });
    };

    $scope.setPage = function (pageNumber) {
        $scope.currentPage = pageNumber;
        $log.debug('Change to  ' + pageNumber );
    };

    $scope.pageChanged = function() {
        $log.debug('Page changed to: ' + $scope.currentPage);
        updateNotes($scope.currentPage);
    };

    $scope.submitForm = function() {
        $log.debug($scope.note.body);
        Restangular.all('notes').post({
            'article_id': $scope.article.id,
            'user_id': $scope.authentification.id,
            'body': $scope.note.body
        }).then(function(result) {
            if(result.success === undefined || !result.success) {
                if(result.body) {
                    $scope.errors.body = result.body[0];
                }
            } else {
                updateNotes($scope.currentPage);
                $scope.note.body = '';
                $scope.alert = "Note added";
            }
        });
    }

    Restangular.one("articles", $routeParams.id).get().then(function(article) {
        $scope.article = article;
        updateNotes($scope.currentPage);
    });

    $scope.changeQuantity = function(currentYield) {
        var ratio = math.getRatio($scope.yieldInitial, currentYield);

        for(var i = 0; i < $scope.quantities.length; i++) {
            if($scope.quantities[i]) {
                $scope.quantities[i].text(math.toString(math.closestFraction(math.applyRation($scope.quantitiesInitial[i], ratio))));
            }
        }
        $scope.currentYield = $scope.yieldInitial * ratio;
        $scope.yield.text($scope.currentYield);
    }

    $scope.parse = function() {
        var domArticle = $('.recipe-body');
        $scope.yield = $('strong:eq(0)', domArticle);
        console.log($scope.yield);
        if(!$scope.yield) {
            $('#yieldChanger').remove();

            return;
        }
        $scope.yieldInitial = math.getValue($scope.yield.text());
        if(!$scope.yieldInitial) {
            $('#yieldChanger').remove();

            return;
        }
        $scope.currentYield = $scope.yieldInitial;
        $scope.quantities = $('em', domArticle);
        $scope.quantitiesInitial = new Array();
        for(var i = 0; i < $scope.quantities.length; i++) {
            $scope.quantities[i] = $($scope.quantities[i]);

            var parsedValue = math.getValue($scope.quantities[i].text());
            if(parsedValue) {
                $scope.quantitiesInitial[i] = math.getValue($scope.quantities[i].text());
            } else {
                delete $scope.quantities[i];
            }
        }
    }

    $scope.yields = _.range(1, 15);
    $scope.currentYield = 1;
    $scope.downloadUrl = apiUrl + 'articles/export/' + $routeParams.id + "?auth_token=" + $rootScope.authentification.token;
}]);

app.controller('article.delete', ['$scope', 'Restangular', '$routeParams', '$log', '$location', function ($scope, Restangular, $routeParams, $log, $location) {
    $log = $log.getInstance('article.delete');

    $log.debug('Delete article #' + $routeParams.id );

    Restangular.one("articles", $routeParams.id).get().then(function(article) {
        $scope.article = article;
    });

    $scope.submitForm = function() {
        $scope.article.remove();
        $location.path('recipes');
    };
}]);

app.controller('article.edit', ['$scope', 'Restangular', '$routeParams', '$log', '$location', function ($scope, Restangular, $routeParams, $log, $location) {
    $log = $log.getInstance('article.edit');

    $log.debug('Edit article #' + $routeParams.id );

    Restangular.one("articles", $routeParams.id).get().then(function(article) {
        $scope.article = article;
        $log.debug(article );
    });

    $scope.submitForm = function() {
        $scope.article.put().then(function(result){
            if(result.success === undefined || !result.success) {
                if(result.title) {
                    $scope.errors.title = result.title[0];
                }
                if(result.body) {
                    $scope.errors.body = result.body[0];
                }
                if(result.image) {
                    $scope.errors.image = result.image[0];
                }
                if(result.category_id) {
                    $scope.errors.category_id = result.category_id[0];
                }
                $log.debug('Validation errors' + $scope.errors);
            } else {
                $log.debug('Edit of #' + $routeParams.id + ' OK ');
            }
        });
    };

    $scope.errors = {};
}]);

app.controller('article.search', ['$rootScope', '$scope', 'Restangular', '$routeParams', '$log', '$location',
    function ($rootScope, $scope, Restangular, $routeParams, $log, $location) {

    $log = $log.getInstance('article.search');

    var page = 1;
    if($routeParams.page) {
        page = $routeParams.page;
    }
    $log.debug('Page ' + page );

    var query = $location.search().query;

    Restangular.all("articles").search({
        'query': query
    }).then(function(articles) {
        $scope.articles = articles;
    });
}]);

app.controller('article.add', ['$rootScope', '$scope', 'Restangular', '$routeParams', '$log', '$location',
    function ($rootScope, $scope, Restangular, $routeParams, $log, $location) {

    $log = $log.getInstance('article.add');

    $log.debug('Add article');

    $scope.urlExtract = function() {
        if(this.formScope.article.url.indexOf('://') === -1) {
            this.formScope.article.url = 'http://' + this.formScope.article.url
        }

        if(!this.formScope.article.title && !this.formScope.article.body) {
            Restangular.all('articles').extract({
                'url': this.formScope.article.url,
                'markdown': true
            }).then(function(data) {
                $scope.article.title = data.title;
                $scope.article.body = data.body;
            });
        }
    }

    $scope.setFormScope= function(scope){
        this.formScope = scope;
    }

    $scope.submitForm = function() {
        this.formScope.article.author_id = $rootScope.authentification.id;
        Restangular.all('articles').post(this.formScope.article).then(function(result){
            if(result.success === undefined || !result.success) {
                if(result.title) {
                    $scope.errors.title = result.title[0];
                }
                if(result.body) {
                    $scope.errors.body = result.body[0];
                }
                if(result.category_id) {
                    $scope.errors.category_id = result.category_id[0];
                }
                $log.debug('Validation errors' + $scope.errors);
            } else {
                $log.debug('Post added ! #' + result.id);
                $location.path("/recipes/" + result.id);
            }
        });
    };

    $scope.errors = {};
}]);


text:
<!DOCTYPE html><title>ZLib test</title>
<meta name="viewport" content="width=device-width, user-scalable=no">
<meta charset="utf-8">


text:
package net.dongliu.vcdiff.vc;

import net.dongliu.vcdiff.io.ByteArrayStream;
import net.dongliu.vcdiff.io.FixedByteArrayStream;
import net.dongliu.vcdiff.io.RandomAccessStream;
import net.dongliu.vcdiff.utils.IOUtils;

import java.io.IOException;
import java.util.Arrays;

/**
 * Cache used for encoding/decoding addresses.
 * Used to efficiently encode the addresses of COPY instructions
 *
 * @author dongliu
 */
public class AddressCache {

    private static final int defaultNearSize = 4;
    private static final int defaultSameSize = 3;

    private int nearSize;

    private int sameSize;

    /**
     * A "near" cache is an array with "s_near" slots, each containing an
     * address used for encoding addresses nearby to previously encoded
     * addresses
     */
    private int[] near;

    private int nextNearSlot;

    /**
     * The same cache maintains a hash table of recent addresses used for
     * repeated encoding of the exact same address
     */
    private int[] same;

    private RandomAccessStream addressStream;

    public AddressCache() {
        this(defaultNearSize, defaultSameSize);
    }

    public AddressCache(int nearSize, int sameSize) {
        this.nearSize = nearSize;
        this.sameSize = sameSize;
        near = new int[nearSize];
        same = new int[sameSize * 256];
    }

    public void reset(byte[] addresses) {
        nextNearSlot = 0;
        Arrays.fill(near, 0);
        Arrays.fill(same, 0);

        addressStream = new FixedByteArrayStream(addresses, true);
    }

    /**
     * @param here the current location in the target data
     * @param mode
     * @return
     * @throws IOException
     */
    public int decodeAddress(int here, short mode) throws IOException {
        int address;

        if (mode == Vcdiff.VCD_SELF_MODE) {
            // The address was encoded by itself as an integer
            address = IOUtils.readVarIntBE(addressStream);
        } else if (mode == Vcdiff.VCD_HERE_MODE) {
            // The address was encoded as the integer value "here - addr"
            address = here - IOUtils.readVarIntBE(addressStream);
        } else if (mode <= nearSize + 1) {
            // Near modes: The "near modes" are in the range [2,nearSize+1]
            // The address was encoded  as the integer value "addr - near[m-2]"
            address = near[mode - 2] + IOUtils.readVarIntBE(addressStream);
        } else if (mode <= nearSize + sameSize + 1) {
            // Same modes: are in the range [nearSize+2,nearSize+sameSize+1].
            // The address was encoded as a single byte b such that "addr == same[(mode - (s_near+2))*256 + b]".
            int m = mode - (nearSize + 2);
            address = same[(m * 256) + IOUtils.readByte(addressStream)];
        } else {
            // should never reach here.
            throw new RuntimeException("Should never reach here");
        }

        update(address);
        return address;
    }

    /**
     * update caches each time a COPY instruction is processed by the encoder or decoder.
     *
     * @param address
     */
    private void update(int address) {
        if (nearSize > 0) {
            near[nextNearSlot] = address;
            nextNearSlot = (nextNearSlot + 1) % nearSize;
        }
        if (sameSize > 0) {
            same[address % (sameSize * 256)] = address;
        }
    }

    public static short defaultLastMode() {
        return Vcdiff.VCD_FIRST_NEAR_MODE + defaultNearSize + defaultSameSize - 1;
    }

    /**
     * encode address
     *
     * @param address
     * @param hereAddress
     * @param encodedAddress the encode address. because java cannot pass reference, we use a wrapper
     * @return the mode
     */
    public short encodeAddress(int address, int hereAddress, int[] encodedAddress) {
        assert address >= 0;
        assert address < hereAddress;
        // Try using the SAME cache.  This method, if available, always
        // results in the smallest encoding and takes priority over other modes.
        if (sameSize > 0) {
            int sameCachePos = address % (sameSize * 256);
            if (same[sameCachePos] == address) {
                // This is the only mode for which an single byte will be written
                // to the address stream instead of a variable-length integer.
                update(address);
                encodedAddress[0] = sameCachePos % 256;
                return (short) (firstSameMode() + (sameCachePos / 256));  // SAME mode
            }
        }

        // Try SELF mode
        short bestMode = Vcdiff.VCD_SELF_MODE;
        int bestEncodedAddress = address;

        // Try HERE mode
        int hereEncodedAddress = hereAddress - address;
        if (hereEncodedAddress < bestEncodedAddress) {
            bestMode = Vcdiff.VCD_HERE_MODE;
            bestEncodedAddress = hereEncodedAddress;
        }

        // Try using the NEAR cache
        for (int i = 0; i < nearSize; ++i) {
            int nearEncodedAddress = address - near[i];
            if ((nearEncodedAddress >= 0) &&
                    (nearEncodedAddress < bestEncodedAddress)) {
                bestMode = (short) (firstNearMode() + i);
                bestEncodedAddress = nearEncodedAddress;
            }
        }

        update(address);
        encodedAddress[0] = bestEncodedAddress;
        return bestMode;
    }

    private short firstNearMode() {
        return Vcdiff.VCD_FIRST_NEAR_MODE;
    }

    private short firstSameMode() {
        return (short) (Vcdiff.VCD_FIRST_NEAR_MODE + nearSize);
    }

    public boolean writeAddressAsVarIntForMode(short mode) {
        return !IsSameMode(mode);
    }

    public boolean IsSameMode(short mode) {
        return (mode >= firstSameMode()) && (mode <= LastMode());
    }

    public short LastMode() {
        return (short) (firstSameMode() + sameSize - 1);
    }
}


text:
enum { LOGOP_INVALID = 0, LOGOP_AND = 1, LOGOP_OR, MATCHOP_EQ, MATCHOP_NE, MATCHOP_RXEQ, MATCHOP_RXNE, MATCHOP_LT, MATCHOP_GT, MATCHOP_LE, MATCHOP_GE, MATCHOP_CONTAINS, MATCHOP_CONTAINSNOT, MATCHOP_BETWEEN };

struct expression {
	expression(const std::string& n, const std::string& lit, int o);
	expression(int o = LOGOP_INVALID);
	~expression();

	std::string name;
	std::string literal;
	int op;
	expression * l, * r;
	expression * parent;
	regex_t * regex;
};

class FilterParser {
	public:
		FilterParser();
		FilterParser(const FilterParser& p);
		~FilterParser();
		void add_logop(int op);
		void add_matchexpr(char * name, int op, char * lit);
		void open_block();
		void close_block();

		bool parse_string(const std::string& str);
		void cleanup();

		inline expression * get_root() { return root; }
		FilterParser& operator=(FilterParser& p);

		const std::wstring& get_error() { return errmsg; }

	private:
		void print_tree_r(expression * e, unsigned int depth);
		void cleanup_r(expression * e);

		expression * root;
		expression * curpos;
		bool next_must_descend_right;
		std::string strexpr;
		std::wstring errmsg;
};

#endif


text:
package eu.verdelhan.ta4j.indicators.helpers;

import static eu.verdelhan.ta4j.TATestsUtils.assertDecimalEquals;
import eu.verdelhan.ta4j.Tick;
import eu.verdelhan.ta4j.mocks.MockTick;
import eu.verdelhan.ta4j.mocks.MockTimeSeries;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;

public class DirectionalMovementDownIndicatorTest {

    @Test
    public void zeroDirectionalMovement() {
        MockTick yesterdayTick = new MockTick(0, 0, 10, 2);
        MockTick todayTick = new MockTick(0, 0, 6, 6);
        List<Tick> ticks = new ArrayList<Tick>();
        ticks.add(yesterdayTick);
        ticks.add(todayTick);
        MockTimeSeries series = new MockTimeSeries(ticks);
        DirectionalMovementDownIndicator down = new DirectionalMovementDownIndicator(series);
        assertDecimalEquals(down.getValue(1), 0);
    }

    @Test
    public void zeroDirectionalMovement2() {
        MockTick yesterdayTick = new MockTick(0, 0, 6, 12);
        MockTick todayTick = new MockTick(0, 0, 12, 6);
        List<Tick> ticks = new ArrayList<Tick>();
        ticks.add(yesterdayTick);
        ticks.add(todayTick);
        MockTimeSeries series = new MockTimeSeries(ticks);
        DirectionalMovementDownIndicator down = new DirectionalMovementDownIndicator(series);
        assertDecimalEquals(down.getValue(1), 0);
    }

    @Test
    public void zeroDirectionalMovement3() {
        MockTick yesterdayTick = new MockTick(0, 0, 6, 6);
        MockTick todayTick = new MockTick(0, 0, 12, 4);
        List<Tick> ticks = new ArrayList<Tick>();
        ticks.add(yesterdayTick);
        ticks.add(todayTick);
        MockTimeSeries series = new MockTimeSeries(ticks);
        DirectionalMovementDownIndicator down = new DirectionalMovementDownIndicator(series);
        assertDecimalEquals(down.getValue(1), 0);
    }

    @Test
    public void positiveDirectionalMovement() {
        MockTick yesterdayTick = new MockTick(0, 0, 6, 20);
        MockTick todayTick = new MockTick(0, 0, 12, 4);
        List<Tick> ticks = new ArrayList<Tick>();
        ticks.add(yesterdayTick);
        ticks.add(todayTick);
        MockTimeSeries series = new MockTimeSeries(ticks);
        DirectionalMovementDownIndicator down = new DirectionalMovementDownIndicator(series);
        assertDecimalEquals(down.getValue(1), 16);
    }
}