text:
namespace juce
{
namespace dsp
{

//==============================================================================
template <typename SampleType>
Phaser<SampleType>::Phaser()
{
    auto oscFunction = [] (SampleType x) { return std::sin (x); };
    osc.initialise (oscFunction);

    for (auto n = 0; n < numStages; ++n)
    {
        filters.add (new FirstOrderTPTFilter<SampleType>());
        filters[n]->setType (FirstOrderTPTFilterType::allpass);
    }

    dryWet.setMixingRule (DryWetMixingRule::linear);
}

template <typename SampleType>
void Phaser<SampleType>::setRate (SampleType newRateHz)
{
    jassert (isPositiveAndBelow (newRateHz, static_cast<SampleType> (100.0)));

    rate = newRateHz;
    update();
}

template <typename SampleType>
void Phaser<SampleType>::setDepth (SampleType newDepth)
{
    jassert (isPositiveAndNotGreaterThan (newDepth, static_cast<SampleType> (1.0)));

    depth = newDepth;
    update();
}

template <typename SampleType>
void Phaser<SampleType>::setCentreFrequency (SampleType newCentreHz)
{
    jassert (isPositiveAndBelow (newCentreHz, static_cast<SampleType> (sampleRate * 0.5)));

    centreFrequency = newCentreHz;
    normCentreFrequency = mapFromLog10 (centreFrequency, static_cast<SampleType> (20.0), static_cast<SampleType> (jmin (20000.0, 0.49 * sampleRate)));
}

template <typename SampleType>
void Phaser<SampleType>::setFeedback (SampleType newFeedback)
{
    jassert (newFeedback >= static_cast<SampleType> (-1.0) && newFeedback <= static_cast<SampleType> (1.0));

    feedback = newFeedback;
    update();
}

template <typename SampleType>
void Phaser<SampleType>::setMix (SampleType newMix)
{
    jassert (isPositiveAndNotGreaterThan (newMix, static_cast<SampleType> (1.0)));

    mix = newMix;
    update();
}

//==============================================================================
template <typename SampleType>
void Phaser<SampleType>::prepare (const ProcessSpec& spec)
{
    jassert (spec.sampleRate > 0);
    jassert (spec.numChannels > 0);

    sampleRate = spec.sampleRate;

    for (auto n = 0; n < numStages; ++n)
        filters[n]->prepare (spec);

    dryWet.prepare (spec);
    feedbackVolume.resize (spec.numChannels);
    lastOutput.resize (spec.numChannels);

    auto specDown = spec;
    specDown.sampleRate /= (double) maxUpdateCounter;
    specDown.maximumBlockSize = specDown.maximumBlockSize / (uint32) maxUpdateCounter + 1;

    osc.prepare (specDown);
    bufferFrequency.setSize (1, (int) specDown.maximumBlockSize, false, false, true);

    update();
    reset();
}

template <typename SampleType>
void Phaser<SampleType>::reset()
{
    std::fill (lastOutput.begin(), lastOutput.end(), static_cast<SampleType> (0));

    for (auto n = 0; n < numStages; ++n)
        filters[n]->reset();

    osc.reset();
    dryWet.reset();

    oscVolume.reset (sampleRate / (double) maxUpdateCounter, 0.05);

    for (auto& vol : feedbackVolume)
        vol.reset (sampleRate, 0.05);

    updateCounter = 0;
}

template <typename SampleType>
void Phaser<SampleType>::update()
{
    osc.setFrequency (rate);
    oscVolume.setTargetValue (depth * (SampleType) 0.5);
    dryWet.setWetMixProportion (mix);

    for (auto& vol : feedbackVolume)
        vol.setTargetValue (feedback);
}

//==============================================================================
template class Phaser<float>;
template class Phaser<double>;

} // namespace dsp
} // namespace juce


text:
package com.twitter.finagle.memcached.integration

import com.twitter.conversions.DurationOps._
import com.twitter.finagle._
import com.twitter.finagle.liveness.FailureAccrualFactory
import com.twitter.finagle.memcached.Client
import com.twitter.finagle.memcached.integration.external.TestMemcachedServer
import com.twitter.finagle.partitioning.param
import com.twitter.finagle.service.TimeoutFilter
import com.twitter.finagle.stats.InMemoryStatsReceiver
import com.twitter.finagle.tracing.Annotation
import com.twitter.finagle.tracing.BufferingTracer
import com.twitter.finagle.tracing.Record
import com.twitter.finagle.tracing.TraceId
import com.twitter.finagle.{param => ctfparam}
import com.twitter.hashing.KeyHasher
import com.twitter.io.Buf
import com.twitter.util._
import java.net.InetAddress
import java.net.InetSocketAddress

class MemcachedPartitioningClientTest extends MemcachedTest {

  protected def createClient(dest: Name, clientName: String): Client = {
    Memcached.client.newRichClient(dest, clientName)
  }

  protected[this] val redistributesKey: Seq[String] =
    Seq("test_client", "partitioner", "redistributes")
  protected[this] val leavesKey: Seq[String] = Seq(clientName, "partitioner", "leaves")
  protected[this] val revivalsKey: Seq[String] = Seq(clientName, "partitioner", "revivals")
  protected[this] val ejectionsKey: Seq[String] = Seq(clientName, "partitioner", "ejections")

  test("re-hash when a bad host is ejected") {
    val sr = new InMemoryStatsReceiver
    val client = Memcached.client
      .configured(param.KeyHasher(KeyHasher.FNV1_32))
      .configured(TimeoutFilter.Param(10000.milliseconds))
      .configured(param.EjectFailedHost(true))
      .configured(FailureAccrualFactory.Param(1, () => 10.minutes))
      .configured(ctfparam.Stats(sr))
      .newRichClient(Name.bound(servers.map { s => Address(s.address) }: _*), clientName)
    testRehashUponEject(client, sr)
    client.close()
  }

  test("host comes back into ring after being ejected") {
    testRingReEntryAfterEjection((timer, cacheServer, statsReceiver) =>
      Memcached.client
        .configured(param.KeyHasher(KeyHasher.FNV1_32))
        .configured(TimeoutFilter.Param(10000.milliseconds))
        .configured(FailureAccrualFactory.Param(1, () => 10.minutes))
        .configured(param.EjectFailedHost(true))
        .configured(ctfparam.Timer(timer))
        .configured(ctfparam.Stats(statsReceiver))
        .newRichClient(
          Name.bound(Address(cacheServer.boundAddress.asInstanceOf[InetSocketAddress])),
          clientName))
  }

  test("Add and remove nodes") {
    val addrs = servers.map { s => Address(s.address) }

    // Start with 3 backends
    val mutableAddrs: ReadWriteVar[Addr] = new ReadWriteVar(Addr.Bound(addrs.toSet.drop(2)))

    val sr = new InMemoryStatsReceiver

    val client = Memcached.client
      .configured(param.KeyHasher(KeyHasher.FNV1_32))
      .configured(TimeoutFilter.Param(10000.milliseconds))
      .configured(FailureAccrualFactory.Param(1, () => 10.minutes))
      .configured(param.EjectFailedHost(true))
      .connectionsPerEndpoint(NumConnections)
      .withStatsReceiver(sr)
      .newRichClient(Name.Bound.singleton(mutableAddrs), clientName)
    testAddAndRemoveNodes(addrs, mutableAddrs, sr)
    client.close()
  }

  test("FailureAccrualFactoryException has remote address") {
    val client = Memcached.client
      .configured(param.KeyHasher(KeyHasher.FNV1_32))
      .configured(TimeoutFilter.Param(10000.milliseconds))
      .configured(FailureAccrualFactory.Param(1, 10.minutes))
      .configured(param.EjectFailedHost(false))
      .connectionsPerEndpoint(1)
      .newRichClient(Name.bound(Address("localhost", 1234)), clientName)
    testFailureAccrualFactoryExceptionHasRemoteAddress(client)
    client.close()
  }

  test("traces fanout requests") {
    // we use an eventually block to retry the request if we didn't get partitioned to different shards
    eventually {
      val tracer = new BufferingTracer()

      // the servers created in MemcachedTest have inconsistent addresses, which means sharding
      // will be inconsistent across runs. To combat this, we'll start our own servers and rerun the
      // tests if we partition to the same shard.
      val serverOpts =
        for (_ <- 1 to NumServers)
          yield TestMemcachedServer.start(
            Some(new InetSocketAddress(InetAddress.getLoopbackAddress, 0)))
      val servers: Seq[TestMemcachedServer] = serverOpts.flatten

      val client = Memcached.client
        .configured(param.KeyHasher(KeyHasher.FNV1_32))
        .connectionsPerEndpoint(1)
        .withTracer(tracer)
        .newRichClient(Name.bound(servers.map { s => Address(s.address) }: _*), clientName)

      awaitResult(client.set("foo", Buf.Utf8("bar")))
      awaitResult(client.set("baz", Buf.Utf8("boing")))
      awaitResult(
        client.gets(Seq("foo", "baz"))
      ).flatMap {
        case (key, (Buf.Utf8(value1), Buf.Utf8(value2))) =>
          Map((key, (value1, value2)))
      }

      client.close()
      servers.foreach(_.stop())

      val gets: Seq[TraceId] = tracer.iterator.toList collect {
        case Record(id, _, Annotation.Rpc("Gets"), _) => id
      }

      // Moving the MemcachedTracingFilter means that partitioned requests should result in two gets spans
      assert(gets.length == 2)
      // However the FanoutProxy should ensure that the requests are stored in peers, not the same tid.
      gets.tail.foreach { get =>
        assert(get._parentId == gets.head._parentId)
        assert(get.spanId != gets.head.spanId)
      }
    }
  }

  test("data read/write consistency between old and new clients") {
    testCompatibility()
  }
}

redpajama_set_name: RedPajamaGithub


text:
I bet you can't beat the computer!

### To play

Download and install [Leiningen](http://leiningen.org/)

```
git clone git@github.com:beccanelson/clojure-tic-tac-toe.git
cd clojure-tic-tac-toe
```

#### To play with default settings:

`lein run`

#### To play with a 4x4 board:

`lein run 4x4`

### Run the specs:

`lein spec`


text:
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [4.8.0](https://github.com/neovim/node-client/compare/v4.7.0...v4.8.0) (2020-01-12)

### Features

* **attach:** allow custom logger for attach neovim proc ([#138](https://github.com/neovim/node-client/issues/138)) ([d9bc2ef](https://github.com/neovim/node-client/commit/d9bc2efe30cd4c0de3691e953cace04d02e7855f))

# [4.7.0](https://github.com/neovim/node-client/compare/v4.6.0...v4.7.0) (2019-12-30)

### Features

* **transport:** bump up msgpack to latest official ([#136](https://github.com/neovim/node-client/issues/136)) ([669e1d9](https://github.com/neovim/node-client/commit/669e1d9591138dc315092c52b819f118ece66749))


text:
from django.contrib import admin
from .models import Records
# Register your models here.

admin.site.register(Records)


text:
function down {
	base_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
	docker-compose -f $base_dir/../harbor/docker-compose*.yml down
}

#Start Harbor
function up {
	base_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
	$base_dir/start_harbor.sh
}

#Configure Harbor
function configure {
	base_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
	$base_dir/config.sh
}

function getRegistryVersion {
	registry_version=""
	base_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
	registry_version=$(sed -n -e 's|.*library/registry:||p' $base_dir/../harbor/docker-compose.yml)
	if [ -z registry_version ]
	then
		registry_version="latest"
	fi
}

#Garbage collectoin
function gc {
	echo "======================= $(date)====================="

	getRegistryVersion

	docker run --name gc --rm --volume /data/registry:/storage \
		--volume $base_dir/../harbor/common/config/registry/:/etc/registry/ \
		registry:$registry_version garbage-collect /etc/registry/config.yml

	echo "===================================================="
}

#Add rules to iptables
function addIptableRules {
	iptables -A INPUT -p tcp --dport 5480 -j ACCEPT -w || true
	#iptables -A INPUT -p tcp --dport 5488 -j ACCEPT
	#iptables -A INPUT -p tcp --dport 5489 -j ACCEPT
}

#Install docker-compose
function installDockerCompose {
	base_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
	$base_dir/../deps/docker-compose-1.7.1/install.sh
}

#Load images
function load {
	basedir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
	docker load -i $basedir/../harbor/harbor*.tgz
}

#Configure SSH
function configSSH {
	value=$(ovfenv -k permit_root_login)
	if [ "$value" = "true" ]
	then
		v=yes
	else
		v=no
	fi
	echo "ssh: permit root login - $v"
	sed -i -r s%"^PermitRootLogin .*"%"PermitRootLogin $v"% /etc/ssh/sshd_config

	if [ ! -f /etc/ssh/ssh_host_rsa_key ] \
		|| [ ! -f /etc/ssh/ssh_host_ecdsa_key ] \
		|| [ ! -f /etc/ssh/ssh_host_ed25519_key ]
	then
		ssh-keygen -A
	fi

	systemctl restart sshd
}

#Configure attr in harbor.cfg
function configureHarborCfg {
	cfg_key=$1
	cfg_value=$2

	basedir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
	cfg_file=$basedir/../harbor/harbor.cfg

	if [ -n "$cfg_key" ]
	then
		cfg_value=$(echo "$cfg_value" | sed -r -e 's%[\/&%]%\\&%g')
		sed -i -r "s%#?$cfg_key\s*=\s*.*%$cfg_key = $cfg_value%" $cfg_file
	fi
}

function pushPhoton {
	set +e

	getRegistryVersion

	docker run -d --name photon_pusher -v /data/registry:/var/lib/registry -p 5000:5000 registry:$registry_version
	docker tag photon:1.0 127.0.0.1:5000/library/photon:1.0
	sleep 5
	docker push 127.0.0.1:5000/library/photon:1.0
	docker rm -f photon_pusher
	set -e
}


text:
/* Task Description */
/*
	Create a function constructor for Person. Each Person must have:
	*	properties `firstname`, `lastname` and `age`
		*	firstname and lastname must always be strings between 3 and 20 characters, containing only Latin letters
		*	age must always be a number in the range 0 150
			*	the setter of age can receive a convertible-to-number value
		*	if any of the above is not met, throw Error
	*	property `fullname`
		*	the getter returns a string in the format 'FIRST_NAME LAST_NAME'
		*	the setter receives a string in the format 'FIRST_NAME LAST_NAME'
			*	it must parse it and set `firstname` and `lastname`
	*	method `introduce()` that returns a string in the format 'Hello! My name is FULL_NAME and I am AGE-years-old'
	*	all methods and properties must be attached to the prototype of the Person
	*	all methods and property setters must return this, if they are not supposed to return other value
		*	enables method-chaining
*/
function solve(){

    var Person = (function () {
        function Person(firstName, lastName, inputAge) {
            this.firstname = firstName;
            this.lastname = lastName;
            this.age = inputAge
        }

        function validateAge(value) {
            var age = parseInt(value);

            if (age < 0 || age > 150 || isNaN(age)) {
                throw new Error('Age must be number between 0 and 150')
            }
        }

        function validateName(value) {
            if (!(value.length > 2 && value.length < 21)) {
                throw new Error('Name length must be between 3 and 20 characters');
            }
            for (var i = 0; i < value.length; i += 1) {
                if (!((value.charCodeAt(i) >= 65 && value.charCodeAt(i) <= 90) || (value.charCodeAt(i) >= 97 && value.charCodeAt(i) <= 122))) {
                    throw new Error('Name can contain only Latin letters');
                }
            }
        }

        Object.defineProperty(Person.prototype, 'firstname', {
            get: function () {
                return this._firstname;
            },
            set: function (value) {
                validateName(value);

                this._firstname = value;
                return this;
            }
        });

        Object.defineProperty(Person.prototype, 'lastname', {
            get: function () {
                return this._lastname;
            },
            set: function (value) {
                validateName(value);
                this._lastname = value;
                return this;
            }
        });

        Object.defineProperty(Person.prototype, 'age', {
            get: function () {
                return this._age;
            },
            set: function (value) {
                validateAge(value);

                this._age = parseInt(value);
                return this;
            }
        });

        Object.defineProperty(Person.prototype, 'fullname', {
            get: function () {
                return this._firstname + ' ' + this._lastname;
            },
            set: function (value) {
                var names = value.split(' ');
                validateName(names[0]);
                validateName(names[1]);

                this._firstname = names[0];
                this._lastname = names[1];

                return this;
            }
        });

        Person.prototype.introduce = function () {
            return 'Hello! My name is ' + this.fullname + ' and I am ' + this.age + '-years-old';
        };

        return Person;
    }());

    var Student = (function (parent) {
        function Student(firstName, lastName, inputAge, inputGrade) {
            parent.call(this, firstName, lastName, inputAge);
            this.grade = inputGrade;
        }

        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        Student.prototype = Object.create(Person.prototype);//TODO -the best solution
        Student.prototype.constructor = Student;
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

        function validateGrade(value) {
            if (value < 2 || value > 6) {
                throw new Error('Grade is invalid');
            }
        }

        Object.defineProperty(Student.prototype, 'grade', {
            get: function () {
                return this._grade;
            },
            set: function (value) {
                validateGrade(value);

                this._grade = value;
                return this;
            }
        });

        Student.prototype.introduce = function(){
            var baseResult = Person.prototype.introduce.call(this);
            return baseResult + ' and my grade is: ' + this.grade;
        };

        return Student;
    }(Person));

    return {
        Person: Person,
        Student: Student
    };

}
var solver = solve();

var eva =  new solver.Person('Eva', 'Ova', '19');
console.log(eva);//{ _firstname: 'Eva', _lastname: 'Ova', _age: 19 }
console.log(eva.introduce());//Hello! My name is Eva Ova and I am 19-years-old
var student = new solver.Student('Oho', 'Boho', 20, 6);
console.log(student);//{ _firstname: 'Oho', _lastname: 'Boho', _age: 20, _grade: 6 }
console.log(student.introduce());//Hello! My name is Oho Boho and I am 20-years-old and my grade is: 6

//module.exports = solve;


text:
using AppCampus.Domain.Interfaces.Components;
using AppCampus.SignboardApi.Models.ResponseModels;
using System;
using System.Reflection;
using System.Web.Http;

namespace AppCampus.SignboardApi.Controllers
{
    [RoutePrefix("signboardapi/v1/widgetcontent/images")]
    public class ImagesController : ApiController
    {
        public IImageComponent ImageComponent { get; set; }

        public ILoggingComponent LoggingComponennt { get; set; }

        public ImagesController(IImageComponent imageComponent, ILoggingComponent loggingComponent)
        {
            ImageComponent = imageComponent;
            LoggingComponennt = loggingComponent;
        }

        [Route("{imageId:Guid}")]
        public IHttpActionResult GetImage(Guid imageId)
        {
            if (!ImageComponent.IsValidImageId(imageId))
            {
                LoggingComponennt.LogWarning(MethodBase.GetCurrentMethod(), "Image with Id " + imageId + " is an invalid image.");
                return NotFound();
            }

            var responseModel = ImageResponseModel.From(ImageComponent.GetImageFromId(imageId));
            return Ok(responseModel);
        }
    }
}


text:
module Succession {
    describe("Title", function () {
        it("builds a clever title name", function () {
            var province1 = new Province([], "Landia");
            var province2 = new Province([], "Orni");
            var province3 = new Province([], "Tesme");

            var lord1 = new Title("Lord", "Lord", "Lord", [province1]);
            expect(lord1.name_title).toEqual("Lord of Landia");

            var lord2 = new Title("Lord", "Lord", "Lord", [province2]);
            expect(lord2.name_title).toEqual("Lord of Orni");

            var overlord = new Title("Overlord", "Overlord", "Overlord", [], [lord1, lord2]);
            expect(overlord.name_title).toEqual("Overlord of Landia");

            var mixlord = new Title("Mixlord", "Mixlord", "Mixlord", [province3], [lord1, lord2]);
            expect(mixlord.name_title).toEqual("Mixlord of Tesme");

            var emperor = new Title("Emperor", "Emperor", "Emperor", [], []);
            expect(emperor.name_title).toEqual("Emperor of Nothing");
        });

        it("builds a ruler name", function () {
            var province1 = new Province([], "Landia");
            var duchy = new Title("Duchy", "Duke", "Duchess", [province1]);
            expect(duchy.name_title).toEqual("Duchy of Landia");
            expect(duchy.name_owner).toEqual("Duke of Landia");

            var female = new Character(province1, null, false);
            duchy.setOwner(female);
            expect(duchy.name_title).toEqual("Duchy of Landia");
            expect(duchy.name_owner).toEqual("Duchess of Landia");

            var male = new Character(province1, null, true);
            duchy.setOwner(male);
            expect(duchy.name_title).toEqual("Duchy of Landia");
            expect(duchy.name_owner).toEqual("Duke of Landia");
        });

        it("updates successors list", function () {
            var title = new Title("Title", "Titlerer", "Titleress");
            expect(title.successors).toEqual([]);

            var char1 = new Character();
            var char2 = new Character();
            var char3 = new Character();
            title.setOwner(char1);

            title.updateSuccessors([char2, char3]);
            expect(title.successors).toEqual([]);

            title.succession.addStrategy((owner, pretendants, propose) => pretendants.forEach(propose));
            title.updateSuccessors([char2, char3]);
            expect(title.successors).toEqual([char2, char3]);
        });
    });
}


text:
"use strict";

module.exports = require("./is-implemented")()
	? Array.prototype.slice : require("./shim");


text:
package model;

import java.util.Collection;
import java.util.HashMap;
import java.util.Random;

/**
 * Groups all sessions and methods relevant to all sessions.
 *
 */
public class ServerSessions {

	static HashMap<Integer, GameSession> sessions = new HashMap<Integer, GameSession>();
	static int lastIndex = 0; // Index of the last session created.

	/**
	 * Adds a new user to a session.
	 * @param username	User's name
	 * @param userIP	User's IP address
	 * @param userID	User's ID
	 * @param sessionID	The ID of the session to witch the user will connect to.
	 * @return
	 * @throws SessionFullException 	If the number of users reach maxPlayers in this session
	 * @throws InvalidURLException 		If any String parameters is empty (password is opional)
	 */
	public static void joinSession(String username, String userIP, int userID, int sessionID)
	throws SessionFullException, InvalidURLException {
		if(sessions.get(sessionID).isFull()){
			throw new SessionFullException();
		}
		if(userIP == null || username == null){
			throw new InvalidURLException();
		}
		sessions.get(sessionID).join(username, Integer.valueOf(userID), userIP);
	}

	public static HashMap<Integer, GameSession> getSessions() {
		return sessions;
	}

	/**
	 * Adds a new session. Calls compareNames(name) to prevent same name sessions.
	 * @param name		Session name
	 * @param max		Max number of players allowed
	 * @param userid	ID of the owner user
	 * @param isPrivate	Whether this session is password protected
	 * @param password	Password used if the session is private
	 * @throws InvalidURLException	If any String parameters is empty (password is opional)
	 */
	public static void newSession(String name, int max, int userid,
			boolean isPrivate, String password) throws InvalidURLException {
		if(name.equals(""))
			throw new InvalidURLException();

		int index = 1 + lastIndex++;
		sessions.put(index, new GameSession(index,
				compareNames(name), max, userid, isPrivate, password)).run();

	}

	/**
	 * Virtually prevents two sessions from having the same name
	 * by adding a random integer to the original name if the name
	 * is already being used.
	 * @param name
	 * @return
	 */
	public static String compareNames(String name){
		Collection<GameSession> gamesessions = sessions.values();
		for (GameSession s : gamesessions) {
			if(s.getName().equals(name)){
				return name + "_" + (new Random()).nextInt(100);
			}
		}
		return name;
	}

}


text:
package com.github.frankfarrell.snowball.service;

import com.github.frankfarrell.snowball.exceptions.AlreadyExistsException;
import com.github.frankfarrell.snowball.exceptions.NotFoundException;
import com.github.frankfarrell.snowball.model.QueuedWorkOrder;
import com.github.frankfarrell.snowball.model.WorkOrder;
import com.github.frankfarrell.snowball.model.WorkOrderClass;
import com.github.frankfarrell.snowball.service.WorkOrderQueue;
import io.swagger.models.auth.In;
import org.redisson.RedissonClient;
import org.redisson.client.protocol.ScoredEntry;
import org.redisson.core.RLock;
import org.redisson.core.RReadWriteLock;
import org.redisson.core.RScoredSortedSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;

import java.time.Clock;
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAmount;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * Created by Frank on 16/02/2016.
 *
 * Distributed Priority queue backed by Redis.
 * Using Redisson distributed collections.
 *
 * Implementation:
 * Uses 4 redis ScoredSortedSets (one per WorkOrderType)
 * Scores the WorkOrders by Seconds since the EPOCH, GMT
 * Set property means that only one instance of Id can be stored in queue
 *
 * Possible Future Extensions: Allows for Time To live on set entries
 */
public class DistributedWorkOrderQueue implements WorkOrderQueue {

    private final Logger log = LoggerFactory.getLogger(this.getClass());

    private RScoredSortedSet<Long> normalQueue;
    private RScoredSortedSet<Long> priorityQueue;
    private RScoredSortedSet<Long> vipQueue;
    private RScoredSortedSet<Long> managementQueue;

    private final OffsetDateTime EPOCH = OffsetDateTime.ofInstant(Instant.EPOCH, ZoneId.of("UTC"));

    private final RedissonClient redisson;

    protected Clock clock;

    private static final String MANAGEMENT_QUEUE_NAME = "management";
    private static final String VIP_QUEUE_NAME = "vip";
    private static final String PRIORITY_QUEUE_NAME = "priority";
    private static final String NORMAL_QUEUE_NAME = "normal";

    @Autowired
    public DistributedWorkOrderQueue(RedissonClient redisson,Clock clock) {
        this.redisson = redisson;
        this.clock = clock;

        normalQueue = redisson.getScoredSortedSet(NORMAL_QUEUE_NAME);
        priorityQueue =  redisson.getScoredSortedSet(PRIORITY_QUEUE_NAME);
        vipQueue = redisson.getScoredSortedSet(VIP_QUEUE_NAME);
        managementQueue =  redisson.getScoredSortedSet(MANAGEMENT_QUEUE_NAME);
    }

    @Override
    public List<QueuedWorkOrder> getAllWorkOrders() {

        /*
        Get all queues.
        Map through priority function
        Sort All
         */
        log.info("Enter getAllWorkOrders");

        final OffsetDateTime now = getCurrentTime();

        List<ScoredEntry<Long>> managementWorkOrders = new ArrayList<>();

        managementWorkOrders.addAll(getAllInQueue(managementQueue));

        //First get Management Queue,
        List<QueuedWorkOrder> allOrders = IntStream.range(0, managementWorkOrders.size())
                .mapToObj(index ->{
                    ScoredEntry<Long> order = managementWorkOrders.get(index);
                    return new QueuedWorkOrder(order.getValue(),
                            EPOCH.plus(order.getScore().longValue(), ChronoUnit.SECONDS),
                            EPOCH.until(now, ChronoUnit.SECONDS) - order.getScore().longValue(),
                            index,
                            WorkOrderClass.MANAGEMENT_OVERRIDE);
                }).collect(Collectors.toList());

        //Group the rest together.
        //This might not be the optimal solution
        List<ScoredEntry<Long>> nonManagementWorkOrders = new ArrayList<>();
        nonManagementWorkOrders.addAll(getAllInQueue(vipQueue));
        nonManagementWorkOrders.addAll(getAllInQueue(priorityQueue));
        nonManagementWorkOrders.addAll(getAllInQueue(normalQueue));

        //Sort them according to priority function score
        List<ScoredEntry<DurationValueStruct>> otherWorkOrders = nonManagementWorkOrders.stream()
                .map(entry -> {
                    Double durationInQueue = getDurationInQueue(entry.getScore()).doubleValue();
                    Double priorityScore = getPriorityFunctionForClass(getWorkOrderClass(entry.getValue())).apply(durationInQueue);
                    return new ScoredEntry<DurationValueStruct>(priorityScore, new DurationValueStruct(entry.getValue(), durationInQueue, entry.getScore()));
                })
                .sorted((x,y)-> {
                    if(x.getScore() > y.getScore()){
                        return -1;
                    }
                    if(y.getScore() >x.getScore()){
                        return 1;
                    }
                    else return 0;
                })
                .collect(Collectors.toList());

        //Map in the index
        //Map to QueuedWorkOrder -> Duration
        List<QueuedWorkOrder> nonManagementOrders = IntStream.range(managementWorkOrders.size(), nonManagementWorkOrders.size() + managementWorkOrders.size())
                .mapToObj(index ->{
                    DurationValueStruct order = otherWorkOrders.get(index - managementWorkOrders.size()).getValue();
                    return new QueuedWorkOrder(
                            order.getValue(),
                            EPOCH.plus(order.getOriginalScore().longValue(), ChronoUnit.SECONDS),
                            order.getDurationInQueue().longValue(),
                            index,
                            getWorkOrderClass(order.getValue()));
                }).collect(Collectors.toList());

        allOrders.addAll(nonManagementOrders);

        log.info("Exit getAllWorkOrders with {} work order", allOrders.size());

        return allOrders;
    }

    @Override
    public QueuedWorkOrder getWorkOrder(Long id) {

        log.info("Enter getWorkOrder for id : {}", id);

        final RScoredSortedSet<Long> queue = getQueueForId(id);

        if(queue.contains(id)){
            OffsetDateTime timestamp = getOriginalTimestamp(queue.getScore(id));

            long durationInQueue =  timestamp.until(getCurrentTime(), ChronoUnit.SECONDS);

            //Calculates position in queue for now
            long positionInQueue = getPositionForId(id);
            WorkOrderClass workOrderClass = getWorkOrderClass(id);

            QueuedWorkOrder workOrderResult = new QueuedWorkOrder(id, timestamp, durationInQueue, positionInQueue, workOrderClass);
            log.info("Exit getWorkOrder for id : {}, result : {}", id, workOrderResult);

            return workOrderResult;
        }
        else{
            log.info("Exit getWorkOrder for id : {}, no result found", id);
            throw new NotFoundException("id", id);
        }
    }

    /*
    Async call to remove work order from queue
    */
    @Override
    @Async(value = "queueWriteTaskExecutor")
    public Future<Boolean> removeWorkOrder(Long id) {

        log.info("Enter removeWorkOrder for id : {}", id);

        final RScoredSortedSet<Long> queue = getQueueForId(id);
        Boolean result = queue.remove(id);

        log.info("Exit removeWorkOrder for id : {}, ", id);
        return new AsyncResult<>(result);
    }

    /*
    Async call to pop top priority order from queue
    */
    @Override
    @Async(value = "queueWriteTaskExecutor")
    public Future<Optional<QueuedWorkOrder>> popWorkOrder() {

        /*
        Get top from each queue
        Pick one that is first according to sorting
         */
        log.info("Enter popWorkOrder");

        if(managementQueue.size()>0){

            Collection<ScoredEntry<Long>> asCollection = managementQueue.entryRange(0, 0);
            ArrayList<ScoredEntry<Long>> asList = new ArrayList<>();
            asList.addAll(asCollection);
            ScoredEntry<Long> managementOrder = asList.get(0);
            QueuedWorkOrder orderToPop = new QueuedWorkOrder(
                    managementOrder.getValue(),
                    getOriginalTimestamp(managementOrder.getScore()),
                    getDurationInQueue(managementOrder.getScore()),
                    0,
                    WorkOrderClass.MANAGEMENT_OVERRIDE
                    );

            managementQueue.removeRangeByRank(0,0);
            log.info("Exit popWorkOrder with {}", orderToPop);
            return new AsyncResult<Optional<QueuedWorkOrder>>(Optional.of(orderToPop));
        }
        else{
            //Iterate over the three other WorkOrder Classes.
            //Rank by Type and Sort by Rank
            //Pick First
            Optional<QueuedWorkOrder> topRankedValue = Arrays.asList(
                            WorkOrderClass.VIP,
                            WorkOrderClass.PRIORITY,
                            WorkOrderClass.NOMRAL
                    )
                    .stream()
                    .map(orderClass ->{
                        RScoredSortedSet<Long> queue = getQueueForClass(orderClass);
                        ArrayList<ScoredEntry<Long>> asList = new ArrayList<>();
                        asList.addAll(queue.entryRange(0, 0));
                        if(asList.size()>0){

                            ScoredEntry<Long> value = asList.get(0);
                            Long durationInQueue = getDurationInQueue(value.getScore());
                            Double rank = getPriorityFunctionForClass(orderClass).apply(durationInQueue.doubleValue());
                            QueuedWorkOrder workOrder = new QueuedWorkOrder(
                                    value.getValue(),
                                    getOriginalTimestamp(value.getScore()),
                                    durationInQueue,
                                    0,
                                    orderClass);

                            workOrder.setRank(rank);
                            //Pass down rank, id, timestamp, duration in queue
                            return workOrder;
                        }
                        else{
                            return null;
                        }
                    })
                    .filter(value -> value != null)
                    //Sort ascending to return top ranking
                    .sorted(((x,y)-> {
                        if(x.getRank() > y.getRank()){
                            return -1;
                        }
                        if(y.getRank() >x.getRank()){
                            return 1;
                        }
                        else return 0;
                    }))
                    .findFirst();

            if(topRankedValue.isPresent()){
                log.info("Exit popWorkOrder with {}", topRankedValue.get());
                getQueueForClass(topRankedValue.get().getWorkOrderClass()).removeRangeByRank(0,0);
            }
            else{
                log.info("Exit popWorkOrder with no work order");
            }
            return new AsyncResult<Optional<QueuedWorkOrder>>(topRankedValue);

        }
    }

    /*
    Async call to push work order into queue
    For queue to operate without non-stop queue size growth, pop frequency must be greater or equal than average than push frequency.
    */
    @Override
    @Async(value = "queuePushTaskExecutor")
    public Future<QueuedWorkOrder> pushWorkOrder(WorkOrder workOrder) {

        log.info("Enter pushWorkOrder for id : {}", workOrder.getId());
        final RScoredSortedSet<Long> queue = getQueueForClass(getWorkOrderClass(workOrder.getId()));

        if(queue.contains(workOrder.getId())){
            log.info("Exit pushWorkOrder for id : {}, order for id already exists", workOrder.getId());
            throw new AlreadyExistsException("id", workOrder.getId());
        }
        else{
            queue.add(EPOCH.until(workOrder.getTimeStamp(), ChronoUnit.SECONDS), workOrder.getId());

            QueuedWorkOrder enqueuedWorkOrder = new QueuedWorkOrder(workOrder.getId(), workOrder.getTimeStamp(), 0, getPositionForId(workOrder.getId()), getWorkOrderClass(workOrder.getId()));

            log.info("Exit pushWorkOrder for id : {}, queued value : {}", workOrder.getId(), enqueuedWorkOrder);

            return new AsyncResult<>(enqueuedWorkOrder);
        }
    }

    private Collection<ScoredEntry<Long>> getAllInQueue(RScoredSortedSet<Long> queue){
        return queue.entryRange(Double.MIN_VALUE, true, Double.MAX_VALUE, true);
    }

    private OffsetDateTime getCurrentTime(){
        return OffsetDateTime.now(clock);
    }

    private RScoredSortedSet<Long> getQueueForId(long id){
        if(id%3 == 0 && id%5 == 0){
            return managementQueue;
        }
        else if(id%5 == 0){
            return vipQueue;
        }
        else if(id%3 == 0 ){
            return priorityQueue;
        }
        else{
            return normalQueue;
        }
    }

    private RScoredSortedSet<Long> getQueueForClass(WorkOrderClass orderClass){
        switch(orderClass) {
            case MANAGEMENT_OVERRIDE:
                return managementQueue;
            case VIP:
                return vipQueue;
            case PRIORITY:
                return priorityQueue;
            case NOMRAL:
                return normalQueue;
            default:
                throw new IllegalStateException();
        }
    }

    private WorkOrderClass getWorkOrderClass(long id){
        if(id%3 == 0 && id%5 == 0){
            return WorkOrderClass.MANAGEMENT_OVERRIDE;
        }
        else if( id%5 == 0){
            return WorkOrderClass.VIP;
        }
        else if (id%3 == 0 ){
            return WorkOrderClass.PRIORITY;
        }
        else{
            return WorkOrderClass.NOMRAL;
        }
    }

    private Long getDurationInQueue(Double score){
        return EPOCH.until(getCurrentTime(), ChronoUnit.SECONDS) - score.longValue();
    }

    private OffsetDateTime getOriginalTimestamp(Double score){
        return EPOCH.plus(score.longValue(), ChronoUnit.SECONDS);
    }

    /*
    For a given id it gives the position of the WorkOrder .
    This is not effiecient for multiple calls, but is effcient for one call
    */
    private Long getPositionForId(Long id){

        //This is seconds since epoch on insert
        final Double rangeScore =  getQueueForId(id).getScore(id);

        //This can happen if Value has not been persisted in Redis yet?
        //At least, we can take a guess that new value will be near back of queue
        //Should be fixed, concurrency issue
        if(rangeScore == null){
            return Long.MAX_VALUE;
        }

        final OffsetDateTime now = getCurrentTime();

        //How many seconds now after EPOCH, minus score
        final Double durationInQueue = getDurationInQueue(rangeScore).doubleValue();

        if (getWorkOrderClass(id).equals(WorkOrderClass.MANAGEMENT_OVERRIDE)) {
            return getQueueSizeInRange(WorkOrderClass.MANAGEMENT_OVERRIDE ,WorkOrderClass.MANAGEMENT_OVERRIDE, durationInQueue, now) -1;
        }
        else{
            final Long managementQueueSize = new Long(managementQueue.size());
            final Long vipQueueSizeForRange = getQueueSizeInRange(getWorkOrderClass(id), WorkOrderClass.VIP, durationInQueue, now);
            final Long priorityQueueSizeForRange = getQueueSizeInRange(getWorkOrderClass(id), WorkOrderClass.PRIORITY, durationInQueue, now);
            final Long normalQueueSizeForRange = getQueueSizeInRange(getWorkOrderClass(id), WorkOrderClass.NOMRAL, durationInQueue, now);

            //How many items are ahead of this in the Queue, minus 1 offset
            return managementQueueSize + vipQueueSizeForRange + priorityQueueSizeForRange + normalQueueSizeForRange -1;
        }
    }

    /*
    NB This is an approximate method that gives a very accurate indication of the position of a given item in the queue

    Calculate queue entries higher than given duration.
    Get the time from EPOCH until that time
    => Score in ScoredSortedSet
     */
    protected Long getQueueSizeInRange(WorkOrderClass orderClassOfValue, WorkOrderClass orderClassCompared, Double durationInQueue, OffsetDateTime now){

        //Caculate priority function for current value
        //Calculate inverse priority value other queues would need to achieve to out rank/equal that
        Double durationAsProductOfPrioirityFunction = getInversePriorityFunctionForClass(orderClassCompared)
                .apply(getPriorityFunctionForClass(orderClassOfValue).apply(durationInQueue));

        OffsetDateTime startTime = now.minus(durationAsProductOfPrioirityFunction.longValue(), ChronoUnit.SECONDS);

        Long startScoreForClass = EPOCH.until(startTime, ChronoUnit.SECONDS);

        return new Long(getQueueForClass(orderClassCompared)
                .valueRange(0, true, startScoreForClass, true)
                .size());
    }

    /*
    This is used to find values that would be ahead of a given value in the queue
    So, if we have a value in normal queue 10 seconds,
    we want to get  all values in Normal between 0 - 10 seconds
    and all values in Prioirity between 0 - inverse(10*log(10))seconds
    and all values in VIP between 0- inverse(2*10*log(10)) seconds
    Use Lambert W function for inverse of nlogn
    */
    protected Function<Double, Double> getInversePriorityFunctionForClass(WorkOrderClass orderClass){
        switch(orderClass) {
            case MANAGEMENT_OVERRIDE:
                return value -> value; //This is only for case of comparing management with management
            case VIP:
                // https://en.wikipedia.org/wiki/Lambert_W_function#Example_4
                return value -> Math.max(4, Math.exp(lambertWFunction(value/2)));
            case PRIORITY:
                return value -> Math.max(3, Math.exp(lambertWFunction(value)));
            case NOMRAL:
                return value -> value;
            default:
                throw new IllegalStateException();
        }
    }

    protected Function<Double, Double> getPriorityFunctionForClass(WorkOrderClass orderClass){
        switch(orderClass) {
            case MANAGEMENT_OVERRIDE:
                return value -> value;
            case VIP:
                return value -> Math.max(4, 2*value* Math.log(value));
            case PRIORITY:
                return value ->Math.max(3, value* Math.log(value));
            case NOMRAL:
                return value -> value;
            default:
                throw new IllegalStateException();
        }
    }

    /*
    Struct Class for Queue Value and Duration in Queue
    Eg so we don't do work we have to throw away
     */
    private class DurationValueStruct{

        private final Long value;
        private final Double durationInQueue;
        private final Double originalScore;

        public DurationValueStruct(Long value, Double durationInQueue, Double originalScore) {
            this.value = value;
            this.durationInQueue = durationInQueue;
            this.originalScore = originalScore;
        }

        public Long getValue() {
            return value;
        }

        public Double getDurationInQueue() {
            return durationInQueue;
        }

        public Double getOriginalScore() {
            return originalScore;
        }
    }

    /*
    From https://gist.github.com/cab1729/1318030
     */
    public static double lambertWFunction(double z)
    {
        double S = 0.0;
        for (int n=1; n <= 100; n++)
        {
            double Se = S * StrictMath.pow(StrictMath.E, S);
            double S1e = (S+1) * StrictMath.pow(StrictMath.E, S);

            if (1E-12 > StrictMath.abs((z-Se)/S1e))
            {
                return S;
            }
            S -= (Se-z) / (S1e - (S+2) * (Se-z) / (2*S+2));
        }
        return S;
    }

    /*
    Hook to Clock for unit testing
    Needed because Clock is immutable
     */
    protected void setClock(Clock clock) {
        this.clock = clock;
    }

}


text:
from .api import list_slices, list_artboards, list_pages
from .api import slices, artboards, pages
from .api import preview
from .api import is_sketchfile


text:
/* Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.flowable.test.cmmn.converter;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.List;

import org.flowable.cmmn.model.CmmnDiEdge;
import org.flowable.cmmn.model.CmmnModel;
import org.flowable.cmmn.model.GraphicInfo;
import org.flowable.cmmn.model.PlanItem;
import org.flowable.cmmn.model.Stage;
import org.flowable.test.cmmn.converter.util.CmmnXmlConverterTest;

/**
 * @author Tijs Rademakers
 */
public class SimpleDiCmmnXmlConverterTest {

    @CmmnXmlConverterTest("org/flowable/test/cmmn/converter/simpledi.cmmn")
    public void validateModel(CmmnModel cmmnModel) {
        Stage planModel = cmmnModel.getPrimaryCase().getPlanModel();
        assertThat(planModel.getPlanItems()).hasSize(2);

        PlanItem planItem = cmmnModel.findPlanItem("planItem1");
        assertThat(planItem).isNotNull();
        assertThat(planItem.getDefinitionRef()).isEqualTo("task1");

        planItem = cmmnModel.findPlanItem("planItem2");
        assertThat(planItem).isNotNull();
        assertThat(planItem.getDefinitionRef()).isEqualTo("task2");

        GraphicInfo graphicInfo = cmmnModel.getGraphicInfo("myPlanModel");
        assertThat(graphicInfo).isNotNull();
        assertThat(graphicInfo.getX()).isEqualTo(1.0);
        assertThat(graphicInfo.getY()).isEqualTo(19.0);
        assertThat(graphicInfo.getWidth()).isEqualTo(400.0);
        assertThat(graphicInfo.getHeight()).isEqualTo(300.0);

        graphicInfo = cmmnModel.getGraphicInfo("planItem1");
        assertThat(graphicInfo).isNotNull();
        assertThat(graphicInfo.getX()).isEqualTo(70.0);
        assertThat(graphicInfo.getY()).isEqualTo(65.0);
        assertThat(graphicInfo.getWidth()).isEqualTo(80.0);
        assertThat(graphicInfo.getHeight()).isEqualTo(60.0);

        graphicInfo = cmmnModel.getGraphicInfo("planItem2");
        assertThat(graphicInfo).isNotNull();
        assertThat(graphicInfo.getX()).isEqualTo(250.0);
        assertThat(graphicInfo.getY()).isEqualTo(100.0);
        assertThat(graphicInfo.getWidth()).isEqualTo(80.0);
        assertThat(graphicInfo.getHeight()).isEqualTo(60.0);

        graphicInfo = cmmnModel.getGraphicInfo("criterion1");
        assertThat(graphicInfo).isNotNull();
        assertThat(graphicInfo.getX()).isEqualTo(268.0);
        assertThat(graphicInfo.getY()).isEqualTo(216.0);
        assertThat(graphicInfo.getWidth()).isEqualTo(20.0);
        assertThat(graphicInfo.getHeight()).isEqualTo(28.0);

        List<GraphicInfo> waypoints = cmmnModel.getFlowLocationGraphicInfo("CMMNEdge_onPart1");
        assertThat(waypoints).hasSize(4);
        assertThat(waypoints.get(0).getX()).isEqualTo(170.0);
        assertThat(waypoints.get(0).getY()).isEqualTo(95.0);
        assertThat(waypoints.get(1).getX()).isEqualTo(220.0);
        assertThat(waypoints.get(1).getY()).isEqualTo(95.0);
        assertThat(waypoints.get(2).getX()).isEqualTo(220.0);
        assertThat(waypoints.get(2).getY()).isEqualTo(130.0);
        assertThat(waypoints.get(3).getX()).isEqualTo(250.0);
        assertThat(waypoints.get(3).getY()).isEqualTo(130.0);

        CmmnDiEdge edgeInfo = cmmnModel.getEdgeInfo("CMMNEdge_onPart1");
        assertThat(edgeInfo.getSourceDockerInfo().getX()).isEqualTo(50.0);
        assertThat(edgeInfo.getSourceDockerInfo().getY()).isEqualTo(10.0);
        assertThat(edgeInfo.getTargetDockerInfo().getX()).isEqualTo(50.0);
        assertThat(edgeInfo.getTargetDockerInfo().getY()).isEqualTo(40.0);
    }

}


text:
<!DOCTYPE html>
<html>
  <head>
    <title>Try to click me!</title>
    <link rel="stylesheet" type="text/css" href="css/style.css">
  </head>
  <body>
      <script src='js/main.js'></script>
  </body>
</html>


text:
package com.android.systemui;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.media.AudioAttributes;
import android.os.Vibrator;
import android.util.Log;
import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;

import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.ExpandableView;
import com.android.systemui.statusbar.FlingAnimationUtils;
import com.android.systemui.statusbar.policy.ScrollAdapter;

public class ExpandHelper implements Gefingerpoken {
    public interface Callback {
        ExpandableView getChildAtRawPosition(float x, float y);
        ExpandableView getChildAtPosition(float x, float y);
        boolean canChildBeExpanded(View v);
        void setUserExpandedChild(View v, boolean userExpanded);
        void setUserLockedChild(View v, boolean userLocked);
        void expansionStateChanged(boolean isExpanding);
    }

    private static final String TAG = "ExpandHelper";
    protected static final boolean DEBUG = false;
    protected static final boolean DEBUG_SCALE = false;
    private static final float EXPAND_DURATION = 0.3f;

    // Set to false to disable focus-based gestures (spread-finger vertical pull).
    private static final boolean USE_DRAG = true;
    // Set to false to disable scale-based gestures (both horizontal and vertical).
    private static final boolean USE_SPAN = true;
    // Both gestures types may be active at the same time.
    // At least one gesture type should be active.
    // A variant of the screwdriver gesture will emerge from either gesture type.

    // amount of overstretch for maximum brightness expressed in U
    // 2f: maximum brightness is stretching a 1U to 3U, or a 4U to 6U
    private static final float STRETCH_INTERVAL = 2f;

    @SuppressWarnings("unused")
    private Context mContext;

    private boolean mExpanding;
    private static final int NONE    = 0;
    private static final int BLINDS  = 1<<0;
    private static final int PULL    = 1<<1;
    private static final int STRETCH = 1<<2;
    private int mExpansionStyle = NONE;
    private boolean mWatchingForPull;
    private boolean mHasPopped;
    private View mEventSource;
    private float mOldHeight;
    private float mNaturalHeight;
    private float mInitialTouchFocusY;
    private float mInitialTouchY;
    private float mInitialTouchSpan;
    private float mLastFocusY;
    private float mLastSpanY;
    private int mTouchSlop;
    private float mLastMotionY;
    private float mPullGestureMinXSpan;
    private Callback mCallback;
    private ScaleGestureDetector mSGD;
    private ViewScaler mScaler;
    private ObjectAnimator mScaleAnimation;
    private boolean mEnabled = true;
    private ExpandableView mResizedView;
    private float mCurrentHeight;

    private int mSmallSize;
    private int mLargeSize;
    private float mMaximumStretch;
    private boolean mOnlyMovements;

    private int mGravity;

    private ScrollAdapter mScrollAdapter;
    private FlingAnimationUtils mFlingAnimationUtils;
    private VelocityTracker mVelocityTracker;

    private OnScaleGestureListener mScaleGestureListener
            = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            if (DEBUG_SCALE) Log.v(TAG, "onscalebegin()");

            if (!mOnlyMovements) {
                startExpanding(mResizedView, STRETCH);
            }
            return mExpanding;
        }

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            if (DEBUG_SCALE) Log.v(TAG, "onscale() on " + mResizedView);
            return true;
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
        }
    };

    private class ViewScaler {
        ExpandableView mView;

        public ViewScaler() {}
        public void setView(ExpandableView v) {
            mView = v;
        }
        public void setHeight(float h) {
            if (DEBUG_SCALE) Log.v(TAG, "SetHeight: setting to " + h);
            mView.setContentHeight((int) h);
            mCurrentHeight = h;
        }
        public float getHeight() {
            return mView.getContentHeight();
        }
        public int getNaturalHeight(int maximum) {
            return Math.min(maximum, mView.getMaxContentHeight());
        }
    }

    /**
     * Handle expansion gestures to expand and contract children of the callback.
     *
     * @param context application context
     * @param callback the container that holds the items to be manipulated
     * @param small the smallest allowable size for the manuipulated items.
     * @param large the largest allowable size for the manuipulated items.
     */
    public ExpandHelper(Context context, Callback callback, int small, int large) {
        mSmallSize = small;
        mMaximumStretch = mSmallSize * STRETCH_INTERVAL;
        mLargeSize = large;
        mContext = context;
        mCallback = callback;
        mScaler = new ViewScaler();
        mGravity = Gravity.TOP;
        mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f);
        mPullGestureMinXSpan = mContext.getResources().getDimension(R.dimen.pull_span_min);

        final ViewConfiguration configuration = ViewConfiguration.get(mContext);
        mTouchSlop = configuration.getScaledTouchSlop();

        mSGD = new ScaleGestureDetector(context, mScaleGestureListener);
        mFlingAnimationUtils = new FlingAnimationUtils(context, EXPAND_DURATION);
    }

    private void updateExpansion() {
        if (DEBUG_SCALE) Log.v(TAG, "updateExpansion()");
        // are we scaling or dragging?
        float span = mSGD.getCurrentSpan() - mInitialTouchSpan;
        span *= USE_SPAN ? 1f : 0f;
        float drag = mSGD.getFocusY() - mInitialTouchFocusY;
        drag *= USE_DRAG ? 1f : 0f;
        drag *= mGravity == Gravity.BOTTOM ? -1f : 1f;
        float pull = Math.abs(drag) + Math.abs(span) + 1f;
        float hand = drag * Math.abs(drag) / pull + span * Math.abs(span) / pull;
        float target = hand + mOldHeight;
        float newHeight = clamp(target);
        mScaler.setHeight(newHeight);
        mLastFocusY = mSGD.getFocusY();
        mLastSpanY = mSGD.getCurrentSpan();
    }

    private float clamp(float target) {
        float out = target;
        out = out < mSmallSize ? mSmallSize : (out > mLargeSize ? mLargeSize : out);
        out = out > mNaturalHeight ? mNaturalHeight : out;
        return out;
    }

    private ExpandableView findView(float x, float y) {
        ExpandableView v;
        if (mEventSource != null) {
            int[] location = new int[2];
            mEventSource.getLocationOnScreen(location);
            x += location[0];
            y += location[1];
            v = mCallback.getChildAtRawPosition(x, y);
        } else {
            v = mCallback.getChildAtPosition(x, y);
        }
        return v;
    }

    private boolean isInside(View v, float x, float y) {
        if (DEBUG) Log.d(TAG, "isinside (" + x + ", " + y + ")");

        if (v == null) {
            if (DEBUG) Log.d(TAG, "isinside null subject");
            return false;
        }
        if (mEventSource != null) {
            int[] location = new int[2];
            mEventSource.getLocationOnScreen(location);
            x += location[0];
            y += location[1];
            if (DEBUG) Log.d(TAG, "  to global (" + x + ", " + y + ")");
        }
        int[] location = new int[2];
        v.getLocationOnScreen(location);
        x -= location[0];
        y -= location[1];
        if (DEBUG) Log.d(TAG, "  to local (" + x + ", " + y + ")");
        if (DEBUG) Log.d(TAG, "  inside (" + v.getWidth() + ", " + v.getHeight() + ")");
        boolean inside = (x > 0f && y > 0f && x < v.getWidth() & y < v.getHeight());
        return inside;
    }

    public void setEventSource(View eventSource) {
        mEventSource = eventSource;
    }

    public void setGravity(int gravity) {
        mGravity = gravity;
    }

    public void setScrollAdapter(ScrollAdapter adapter) {
        mScrollAdapter = adapter;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (!isEnabled()) {
            return false;
        }
        trackVelocity(ev);
        final int action = ev.getAction();
        if (DEBUG_SCALE) Log.d(TAG, "intercept: act=" + MotionEvent.actionToString(action) +
                         " expanding=" + mExpanding +
                         (0 != (mExpansionStyle & BLINDS) ? " (blinds)" : "") +
                         (0 != (mExpansionStyle & PULL) ? " (pull)" : "") +
                         (0 != (mExpansionStyle & STRETCH) ? " (stretch)" : ""));
        // check for a spread-finger vertical pull gesture
        mSGD.onTouchEvent(ev);
        final int x = (int) mSGD.getFocusX();
        final int y = (int) mSGD.getFocusY();

        mInitialTouchFocusY = y;
        mInitialTouchSpan = mSGD.getCurrentSpan();
        mLastFocusY = mInitialTouchFocusY;
        mLastSpanY = mInitialTouchSpan;
        if (DEBUG_SCALE) Log.d(TAG, "set initial span: " + mInitialTouchSpan);

        if (mExpanding) {
            mLastMotionY = ev.getRawY();
            maybeRecycleVelocityTracker(ev);
            return true;
        } else {
            if ((action == MotionEvent.ACTION_MOVE) && 0 != (mExpansionStyle & BLINDS)) {
                // we've begun Venetian blinds style expansion
                return true;
            }
            switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_MOVE: {
                final float xspan = mSGD.getCurrentSpanX();
                if (xspan > mPullGestureMinXSpan &&
                        xspan > mSGD.getCurrentSpanY() && !mExpanding) {
                    // detect a vertical pulling gesture with fingers somewhat separated
                    if (DEBUG_SCALE) Log.v(TAG, "got pull gesture (xspan=" + xspan + "px)");
                    startExpanding(mResizedView, PULL);
                    mWatchingForPull = false;
                }
                if (mWatchingForPull) {
                    final float yDiff = ev.getRawY() - mInitialTouchY;
                    if (yDiff > mTouchSlop) {
                        if (DEBUG) Log.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
                        mWatchingForPull = false;
                        if (mResizedView != null && !isFullyExpanded(mResizedView)) {
                            if (startExpanding(mResizedView, BLINDS)) {
                                mLastMotionY = ev.getRawY();
                                mInitialTouchY = ev.getRawY();
                                mHasPopped = false;
                            }
                        }
                    }
                }
                break;
            }

            case MotionEvent.ACTION_DOWN:
                mWatchingForPull = mScrollAdapter != null &&
                        isInside(mScrollAdapter.getHostView(), x, y)
                        && mScrollAdapter.isScrolledToTop();
                mResizedView = findView(x, y);
                if (mResizedView != null && !mCallback.canChildBeExpanded(mResizedView)) {
                    mResizedView = null;
                    mWatchingForPull = false;
                }
                mInitialTouchY = ev.getY();
                break;

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                if (DEBUG) Log.d(TAG, "up/cancel");
                finishExpanding(false, getCurrentVelocity());
                clearView();
                break;
            }
            mLastMotionY = ev.getRawY();
            maybeRecycleVelocityTracker(ev);
            return mExpanding;
        }
    }

    private void trackVelocity(MotionEvent event) {
        int action = event.getActionMasked();
        switch(action) {
            case MotionEvent.ACTION_DOWN:
                if (mVelocityTracker == null) {
                    mVelocityTracker = VelocityTracker.obtain();
                } else {
                    mVelocityTracker.clear();
                }
                mVelocityTracker.addMovement(event);
                break;
            case MotionEvent.ACTION_MOVE:
                if (mVelocityTracker == null) {
                    mVelocityTracker = VelocityTracker.obtain();
                }
                mVelocityTracker.addMovement(event);
                break;
            default:
                break;
        }
    }

    private void maybeRecycleVelocityTracker(MotionEvent event) {
        if (mVelocityTracker != null && (event.getActionMasked() == MotionEvent.ACTION_CANCEL
                || event.getActionMasked() == MotionEvent.ACTION_UP)) {
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }

    private float getCurrentVelocity() {
        if (mVelocityTracker != null) {
            mVelocityTracker.computeCurrentVelocity(1000);
            return mVelocityTracker.getYVelocity();
        } else {
            return 0f;
        }
    }

    public void setEnabled(boolean enable) {
        mEnabled = enable;
    }

    private boolean isEnabled() {
        return mEnabled;
    }

    private boolean isFullyExpanded(ExpandableView underFocus) {
        return underFocus.areChildrenExpanded() || underFocus.getIntrinsicHeight()
                - underFocus.getBottomDecorHeight() == underFocus.getMaxContentHeight();
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (!isEnabled()) {
            return false;
        }
        trackVelocity(ev);
        final int action = ev.getActionMasked();
        if (DEBUG_SCALE) Log.d(TAG, "touch: act=" + MotionEvent.actionToString(action) +
                " expanding=" + mExpanding +
                (0 != (mExpansionStyle & BLINDS) ? " (blinds)" : "") +
                (0 != (mExpansionStyle & PULL) ? " (pull)" : "") +
                (0 != (mExpansionStyle & STRETCH) ? " (stretch)" : ""));

        mSGD.onTouchEvent(ev);
        final int x = (int) mSGD.getFocusX();
        final int y = (int) mSGD.getFocusY();

        if (mOnlyMovements) {
            mLastMotionY = ev.getRawY();
            return false;
        }
        switch (action) {
            case MotionEvent.ACTION_DOWN:
                mWatchingForPull = mScrollAdapter != null &&
                        isInside(mScrollAdapter.getHostView(), x, y);
                mResizedView = findView(x, y);
                mInitialTouchY = ev.getY();
                break;
            case MotionEvent.ACTION_MOVE: {
                if (mWatchingForPull) {
                    final float yDiff = ev.getRawY() - mInitialTouchY;
                    if (yDiff > mTouchSlop) {
                        if (DEBUG) Log.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
                        mWatchingForPull = false;
                        if (mResizedView != null && !isFullyExpanded(mResizedView)) {
                            if (startExpanding(mResizedView, BLINDS)) {
                                mInitialTouchY = ev.getRawY();
                                mLastMotionY = ev.getRawY();
                                mHasPopped = false;
                            }
                        }
                    }
                }
                if (mExpanding && 0 != (mExpansionStyle & BLINDS)) {
                    final float rawHeight = ev.getRawY() - mLastMotionY + mCurrentHeight;
                    final float newHeight = clamp(rawHeight);
                    boolean isFinished = false;
                    boolean expanded = false;
                    if (rawHeight > mNaturalHeight) {
                        isFinished = true;
                        expanded = true;
                    }
                    if (rawHeight < mSmallSize) {
                        isFinished = true;
                        expanded = false;
                    }

                    if (!mHasPopped) {
                        if (mEventSource != null) {
                            mEventSource.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
                        }
                        mHasPopped = true;
                    }

                    mScaler.setHeight(newHeight);
                    mLastMotionY = ev.getRawY();
                    if (isFinished) {
                        mCallback.setUserExpandedChild(mResizedView, expanded);
                        mCallback.expansionStateChanged(false);
                        return false;
                    } else {
                        mCallback.expansionStateChanged(true);
                    }
                    return true;
                }

                if (mExpanding) {

                    // Gestural expansion is running
                    updateExpansion();
                    mLastMotionY = ev.getRawY();
                    return true;
                }

                break;
            }

            case MotionEvent.ACTION_POINTER_UP:
            case MotionEvent.ACTION_POINTER_DOWN:
                if (DEBUG) Log.d(TAG, "pointer change");
                mInitialTouchY += mSGD.getFocusY() - mLastFocusY;
                mInitialTouchSpan += mSGD.getCurrentSpan() - mLastSpanY;
                break;

            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if (DEBUG) Log.d(TAG, "up/cancel");
                finishExpanding(false, getCurrentVelocity());
                clearView();
                break;
        }
        mLastMotionY = ev.getRawY();
        maybeRecycleVelocityTracker(ev);
        return mResizedView != null;
    }

    /**
     * @return True if the view is expandable, false otherwise.
     */
    private boolean startExpanding(ExpandableView v, int expandType) {
        if (!(v instanceof ExpandableNotificationRow)) {
            return false;
        }
        mExpansionStyle = expandType;
        if (mExpanding && v == mResizedView) {
            return true;
        }
        mExpanding = true;
        mCallback.expansionStateChanged(true);
        if (DEBUG) Log.d(TAG, "scale type " + expandType + " beginning on view: " + v);
        mCallback.setUserLockedChild(v, true);
        mScaler.setView(v);
        mOldHeight = mScaler.getHeight();
        mCurrentHeight = mOldHeight;
        if (mCallback.canChildBeExpanded(v)) {
            if (DEBUG) Log.d(TAG, "working on an expandable child");
            mNaturalHeight = mScaler.getNaturalHeight(mLargeSize);
        } else {
            if (DEBUG) Log.d(TAG, "working on a non-expandable child");
            mNaturalHeight = mOldHeight;
        }
        if (DEBUG) Log.d(TAG, "got mOldHeight: " + mOldHeight +
                    " mNaturalHeight: " + mNaturalHeight);
        return true;
    }

    private void finishExpanding(boolean force, float velocity) {
        if (!mExpanding) return;

        if (DEBUG) Log.d(TAG, "scale in finishing on view: " + mResizedView);

        float currentHeight = mScaler.getHeight();
        float targetHeight = mSmallSize;
        float h = mScaler.getHeight();
        final boolean wasClosed = (mOldHeight == mSmallSize);
        if (wasClosed) {
            targetHeight = (force || currentHeight > mSmallSize) ? mNaturalHeight : mSmallSize;
        } else {
            targetHeight = (force || currentHeight < mNaturalHeight) ? mSmallSize : mNaturalHeight;
        }
        if (mScaleAnimation.isRunning()) {
            mScaleAnimation.cancel();
        }
        mCallback.setUserExpandedChild(mResizedView, targetHeight == mNaturalHeight);
        mCallback.expansionStateChanged(false);
        if (targetHeight != currentHeight) {
            mScaleAnimation.setFloatValues(targetHeight);
            mScaleAnimation.setupStartValues();
            final View scaledView = mResizedView;
            mScaleAnimation.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    mCallback.setUserLockedChild(scaledView, false);
                    mScaleAnimation.removeListener(this);
                }
            });
            mFlingAnimationUtils.apply(mScaleAnimation, currentHeight, targetHeight, velocity);
            mScaleAnimation.start();
        } else {
            mCallback.setUserLockedChild(mResizedView, false);
        }

        mExpanding = false;
        mExpansionStyle = NONE;

        if (DEBUG) Log.d(TAG, "wasClosed is: " + wasClosed);
        if (DEBUG) Log.d(TAG, "currentHeight is: " + currentHeight);
        if (DEBUG) Log.d(TAG, "mSmallSize is: " + mSmallSize);
        if (DEBUG) Log.d(TAG, "targetHeight is: " + targetHeight);
        if (DEBUG) Log.d(TAG, "scale was finished on view: " + mResizedView);
    }

    private void clearView() {
        mResizedView = null;
    }

    /**
     * Use this to abort any pending expansions in progress.
     */
    public void cancel() {
        finishExpanding(true, 0f /* velocity */);
        clearView();

        // reset the gesture detector
        mSGD = new ScaleGestureDetector(mContext, mScaleGestureListener);
    }

    /**
     * Change the expansion mode to only observe movements and don't perform any resizing.
     * This is needed when the expanding is finished and the scroller kicks in,
     * performing an overscroll motion. We only want to shrink it again when we are not
     * overscrolled.
     *
     * @param onlyMovements Should only movements be observed?
     */
    public void onlyObserveMovements(boolean onlyMovements) {
        mOnlyMovements = onlyMovements;
    }
}


text:
package interview;

import org.junit.Test;

import java.util.HashSet;
import java.util.Set;

import static junit.framework.Assert.assertEquals;

public class RendererTest {
  @Test
  public void testClassic() throws Exception {
    Renderer renderer = new Classic();
    test(renderer);
  }

  @Test
  public void testOptimizedClassic() throws Exception {
    Renderer renderer = new OptimizedClassic();
    test(renderer);
  }

  @Test
  public void testOptimizedClassicWithCodePoints() throws Exception {
    Renderer renderer = new OptimizedClassicWithCodePoints();
    testMultibyte(renderer);
  }

  @Test
  public void testBinaryTree() throws Exception {
    Renderer renderer = new BinaryTree();
    test(renderer);
  }

  @Test
  public void testInsertionSort() throws Exception {
    Renderer renderer = new InsertionSort();
    test(renderer);
  }

  @Test
  public void testBinarySearchSort() throws Exception {
    Renderer renderer = new BinarySearchSort();
    test(renderer);
  }

  @Test
  public void testTree() throws Exception {
    Renderer renderer = new Tree();
    test(renderer);
  }

  @Test
  public void testStringReplacement() throws Exception {
    Renderer renderer = new StringReplacement();
    test(renderer);
  }

  @Test
  public void testStringBuilderReplace() throws Exception {
    Renderer renderer = new StringBuilderReplace();
    test(renderer);
  }

  @Test
  public void testLinearNodes() throws Exception {
    Renderer renderer = new LinkedListEntities();
    test(renderer);
  }

  private void test(Renderer renderer) {
    String text = "Attend to hear 6 stellar #mobile #startups at #OF12 Entrepreneur Idol show 2day,  " +
            "http://t.co/HtzEMgAC @TiEcon @sv_entrepreneur @500!";
    assertEquals(text, renderer.render(text, new HashSet<>()).toString());

    String result = "Attend to hear 6 stellar <#mobile> <#startups> at <#OF12> Entrepreneur Idol show 2day,  " +
            "<http://t.co/HtzEMgAC> <@TiEcon> <@sv_entrepreneur> <@500>!";
    Set<Entity> entities = getEntities();
    assertEquals(result, renderer.render(text, entities).toString());
  }

  private void testMultibyte(Renderer renderer) {
    String text = "Attend \uD840\uDC00\uD840\uDC00 hear 6 stellar #mobile #startups at #OF12 Entrepreneur Idol show 2day,  " +
            "http://t.co/HtzEMgAC @TiEcon @sv_entrepreneur @500!";
    assertEquals(text, renderer.render(text, new HashSet<>()).toString());

    String result = "Attend \uD840\uDC00\uD840\uDC00 hear 6 stellar <#mobile> <#startups> at <#OF12> Entrepreneur Idol show 2day,  " +
            "<http://t.co/HtzEMgAC> <@TiEcon> <@sv_entrepreneur> <@500>!";
    Set<Entity> entities = getEntities();
    assertEquals(result, renderer.render(text, entities).toString());
  }

  private Set<Entity> getEntities() {
    return new HashSet<Entity>() {{
        add(new Entity(25, 32, "<#mobile>"));
        add(new Entity(33, 42, "<#startups>"));
        add(new Entity(46, 51, "<#OF12>"));
        add(new Entity(82, 102, "<http://t.co/HtzEMgAC>"));
        add(new Entity(103, 110, "<@TiEcon>"));
        add(new Entity(111, 127, "<@sv_entrepreneur>"));
        add(new Entity(128, 132, "<@500>"));
      }};
  }
}


text:
<?php

namespace OpenSkool\AdminBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * GrupoEtapaPlanEstudios
 *
 * @ORM\Table(name="grupo_etapa_plan_estudios")
 * @ORM\Entity(repositoryClass="OpenSkool\AdminBundle\Entity\Repository\GrupoEtapaPlanEstudiosRepository")
 */
class GrupoEtapaPlanEstudios
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="OpenSkool\AdminBundle\Entity\Grupo", cascade={"persist"})
     */
    private $grupo;

    /**
     * @ORM\ManyToOne(targetEntity="OpenSkool\AdminBundle\Entity\EtapaPlanEstudios", cascade={"persist"})
     */
    private $etapaPlanEstudios;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * Set grupo
     *
     * @param \OpenSkool\AdminBundle\Entity\Grupo $grupo
     * @return GrupoEtapaPlanEstudios
     */
    public function setGrupo(\OpenSkool\AdminBundle\Entity\Grupo $grupo = null)
    {
        $this->grupo = $grupo;

        return $this;
    }

    /**
     * Get grupo
     *
     * @return \OpenSkool\AdminBundle\Entity\Grupo
     */
    public function getGrupo()
    {
        return $this->grupo;
    }

    /**
     * Set etapaPlanEstudios
     *
     * @param \OpenSkool\AdminBundle\Entity\EtapaPlanEstudios $etapaPlanEstudios
     * @return GrupoEtapaPlanEstudios
     */
    public function setEtapaPlanEstudios(\OpenSkool\AdminBundle\Entity\EtapaPlanEstudios $etapaPlanEstudios = null)
    {
        $this->etapaPlanEstudios = $etapaPlanEstudios;

        return $this;
    }

    /**
     * Get etapaPlanEstudios
     *
     * @return \OpenSkool\AdminBundle\Entity\EtapaPlanEstudios
     */
    public function getEtapaPlanEstudios()
    {
        return $this->etapaPlanEstudios;
    }
}


text:
[![Build Status](https://travis-ci.org/smallmiro/nbasearc-spring-boot-starter.svg?branch=master)](https://travis-ci.org/smallmiro/nbasearc-spring-boot-starter)
[![Coverage Status](https://coveralls.io/repos/github/smallmiro/nbasearc-spring-boot-starter/badge.svg?branch=master)](https://coveralls.io/github/smallmiro/nbasearc-spring-boot-starter?branch=master)
[![Apache 2](http://img.shields.io/badge/license-Apache%202-red.svg)](http://www.apache.org/licenses/LICENSE-2.0)
[![Maven Central](https://img.shields.io/badge/Maven%20Central-v1.0-blue.svg)](http://search.maven.org/#artifactdetails%7Ccom.github.smallmiro%7Cnbasearc-spring-boot-starter%7C1.0%7Cjar)

# overview
* nbase-arc를 spring-boot에서 사용하기 편하도록 아래 내용을 추가했습니다.
 * spring-boot-autoconfigure
 * spring-boot-starter

# 변경 내역
* XML/ configuration 선언 없이 `spring.properties`의 선언 만으로 사용 가능
* 필요시 기존 방법대로 선언해서 사용 가능

## 기존 사용방법
* maven
```xml
<dependencies>
    <dependency>
        <groupId>com.navercorp</groupId>
        <artifactId>nbase-arc-java-client</artifactId>
        <version>1.4.6</version>
    </dependency>
</dependencies>
```

* XML 설정
```xml
<bean id="gatewayConfig" class="com.navercorp.redis.cluster.gateway.GatewayConfig">
  <property name="zkAddress" value="zookeeper-address"/>
  <property name="clusterName" value="cluster-name"/>
</bean>

<bean id="redisClusterConnectionFactory" class="com.navercorp.redis.cluster.spring.RedisClusterConnectionFactory" destroy-method="destroy">
    <property name="config" ref="gatewayConfig"/>
</bean>

<bean id="redisTemplate" class="com.navercorp.redis.cluster.spring.StringRedisClusterTemplate">
    <property name="connectionFactory" ref="redisClusterConnectionFactory"/>
</bean>
```

## 변경된 사용 방법
* maven
 * dependency 추가
```xml
<dependencies>
    <dependency>
        <groupId>com.github.smallmiro</groupId>
        <artifactId>nbasearc-spring-boot-starter</artifactId>
        <version>1.0.1</version>
    </dependency>
</dependencies>
```

* spring-properties
```
nbase.arc.gateway.zkAddress=# user nbase-arc address #
nbase.arc.gateway.clusterName=# user cluster name #
nbase.arc.gateway.timeoutMillisec=3000
nbase.arc.gateway.healthCheckUsed=true
nbase.arc.gateway.healthCheckThreadSize=3
nbase.arc.gateway.healthCheckPeriodSeconds=10
nbase.arc.gateway.gatewaySelectorMethod=round-robin

nbase.arc.pool.initialSize=1
nbase.arc.pool.maxActive=4
nbase.arc.pool.maxIdle=2
nbase.arc.pool.minIdle=2
nbase.arc.pool.maxWait=2
```
* 예제 소스
```java
@Autowired
private StringRedisClusterTemplate redisTemplate;

@RequestMapping(value = "/get", method = RequestMethod.GET)
@ResponseBody
public Map<String, String> get() {
    String sample = redisTemplate.opsForValue().get(KEY);
    Map<String, String> re = new HashMap<String, String>();
    re.put("retrun", sample);
    return re;
}
```

# 예제 프로젝트
* nbasearc-spring-boot-sample
* IntegrationTest 작성 예제
```java
@Test
public void getHello() throws Exception {
    String testValue = "SAMPLE";
    Map<String, Object> in = new HashMap<String, Object>();
    in.put("insert",testValue);

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    HttpEntity<String> requestUpdate = new HttpEntity<String>(mapper.writeValueAsString(in), headers);

    ResponseEntity<Void> response1 = template.exchange(hostName + "/put", HttpMethod.PUT, requestUpdate, Void.class);
    assertThat(response1.getStatusCode(), equalTo(HttpStatus.OK));

    ResponseEntity<String> response2 = template.getForEntity(hostName + "/get", String.class);
    String body = response2.getBody();
    Map<String, Object> re = mapper.readValue(body, new TypeReference<Map<String, Object>>() {
    });
    assertThat((String) re.get("retrun"), equalTo(testValue));

}
```
# Related Projects
* nbase-arc : https://github.com/naver/nbase-arc

# Licensed
```

Copyright 2010-2015 the original author or authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

```


text:
<?php

// autoload_files.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    $vendorDir . '/symfony/intl/Resources/stubs/functions.php',
    $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
    $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
    $vendorDir . '/danielstjules/stringy/src/Create.php',
    $vendorDir . '/illuminate/support/helpers.php',
);


text:
#pragma once

#include "Layer.h"
#include "paddle/math/Matrix.h"
#include <vector>

namespace paddle {

/**
 * @brief Basic parent layer of pooling
 * Pools the input within regions
 */
class PoolLayer : public Layer {
protected:
  size_t channels_, sizeX_, stride_, outputX_, imgSize_;
  int start_, confPadding_;

  size_t sizeY_;
  size_t imgSizeY_;
  size_t strideY_;
  size_t outputY_;
  int confPaddingY_;

  std::string poolType_;

public:
  explicit PoolLayer(const LayerConfig& config) : Layer(config) {}

  /**
   * @brief create pooling layer by pool_type
   */
  static Layer* create(const LayerConfig& config);

  virtual bool init(const LayerMap& layerMap, const ParameterMap& parameterMap);
};

}  // namespace paddle


text:
title: Capability One
keywords: capability
tags: [capability]
sidebar: capability_one_sidebar
permalink: capability_one.html
summary: "Details of the functionality available in capability pack one."
---

[<i class="fa fa-arrow-left" aria-hidden="true"/> Back to {{site.site_title}} - Getting Started.](index.html)

{% include todo.html content="This capability pack is published as a **work in progress** version and as such is subject to change." %}

Details of the capability pack one.