text:
'use strict';
var mongoConfig = require(process.cwd() + '/config').mongodb;
var mongoose = require('mongoose');
var Account = require('./models/account');
var User = require('./models/user');

var host = mongoConfig.host;
var port = mongoConfig.port;
var db = mongoConfig.database;
mongoose.connect(`mongodb://${host}:${port}/${db}`);

var registerAdmin = (callback) => {
  Account.register(new Account({
      username: 'admin'
    }),
    'admin', (err) => {
      if (err) {
        throw err;
      }
      console.log('Admin user registered');
      callback();
    });
};

var createAdminProfile = () => {
  User.create({
    username: 'admin',
    firstName: 'Admin',
    lastName: 'Admin',
    role: 'admin',
    email: 'admin@admin.com',
    gropus: []
  }, (err) => {
    if (err) {
      throw err;
    }
    console.log('Admin user profile created');
    mongoose.disconnect(() => process.exit(0));
  });
};

var removeAdmin = () => {
  Account.remove({
    username: 'admin'
  }, (err) => {
    if (err) {
      throw err;
    }
    registerAdmin(createAdminProfile);
  });
};

User.remove({
  username: 'admin'
}, (err) => {
  if (err) {
    throw err;
  }
  removeAdmin();
});


text:
using System.Collections.Generic;

namespace IdentityAdmin.Core.Client
{
    public class ClientDetail : ClientSummary
    {
        public IEnumerable<PropertyValue> Properties { get; set; }
        public ICollection<ClientClaimValue> Claims { get; set; }
        public ICollection<ClientSecretValue> ClientSecrets { get; set; }
        public ICollection<ClientIdPRestrictionValue> IdentityProviderRestrictions { get; set; }
        public ICollection<ClientPostLogoutRedirectUriValue> PostLogoutRedirectUris { get; set; }
        public ICollection<ClientRedirectUriValue> RedirectUris { get; set; }
        public ICollection<ClientCorsOriginValue> AllowedCorsOrigins { get; set; }
        public ICollection<ClientCustomGrantTypeValue> AllowedCustomGrantTypes { get; set; }
        public ICollection<ClientScopeValue> AllowedScopes { get; set; }
    }
}

redpajama_set_name: RedPajamaGithub


text:
package com.ericmguimaraes.gaso.model;

import com.google.firebase.database.DatabaseError;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by adrianodias on 4/29/17.
 */

public class FuzzyConsumption implements Serializable {

    private static final float ALLOWANCE = 50f;
    private int verylow = 0;
    private int low = 0;
    private int average = 0;
    private int high = 0;
    private int veryhigh = 0;

    public void incrementVeryLow() {
        verylow++;
    }
    public void incrementLow() {
        low++;
    }
    public void incrementAverage() {
        average++;
    }
    public void incrementHigh() {
        high++;
    }
    public void incrementVeryHigh() {
        veryhigh++;
    }

    public int getVerylow() {
        return verylow;
    }

    public int getLow() {
        return low;
    }

    public int getAverage() {
        return average;
    }

    public int getHigh() {
        return high;
    }

    public int getVeryhigh() {
        return veryhigh;
    }

    public void setVerylow(int verylow) {
        this.verylow = verylow;
    }

    public void setLow(int low) {
        this.low = low;
    }

    public void setAverage(int average) {
        this.average = average;
    }

    public void setHigh(int high) {
        this.high = high;
    }

    public void setVeryhigh(int veryhigh) {
        this.veryhigh = veryhigh;
    }

    public void incrementComsuption(String str) {
        if (str.equals("muito_baixo")) {
            incrementVeryLow();
        } else if (str.equals("baixo")) {
            incrementLow();
        } else if (str.equals("medio")) {
            incrementAverage();
        } else if (str.equals("alto")) {
            incrementHigh();
        } else if (str.equals("muito_alto")) {
            incrementVeryHigh();
        }
    }

    private List<Integer> getValuesOfComsumptions() {
        List<Integer> c = new ArrayList<>();
        c.add(verylow);
        c.add(low);
        c.add(average);
        c.add(high);
        c.add(veryhigh);
        return c;
    }

    private List<String> getNamesOfComsumptions() {
        List<String> c = new ArrayList<>();
        c.add("muito_baixo");
        c.add("baixo");
        c.add("medio");
        c.add("alto");
        c.add("muito_alto");
        return c;
    }

    public String mostFrequentConsumptionName() {
        int max = 0;
        int indexOfMax = 0;
        List<Integer> comsumptions = getValuesOfComsumptions();
        for (Integer comsumption : comsumptions) {
            if (comsumption > max) {
                max = comsumption;
                indexOfMax = comsumptions.indexOf(comsumption);
            }
        }
        return getNamesOfComsumptions().get(indexOfMax);
    }

    public int getTotal() {
        int total = verylow+low+average+high+veryhigh;
        return total;
    }

    public float getPercentage(int value){
        if(getTotal()==0)
            return 0;
        return ((float) value/getTotal()*100);
    }

    public boolean isSimilar(FuzzyConsumption consumption) {
        if(Math.abs(getPercentage(verylow)-consumption.getPercentage(consumption.verylow))>ALLOWANCE)
            return false;
        if(Math.abs(getPercentage(low)-consumption.getPercentage(consumption.low))>ALLOWANCE)
            return false;
        if(Math.abs(getPercentage(average)-consumption.getPercentage(consumption.average))>ALLOWANCE)
            return false;
        if(Math.abs(getPercentage(high)-consumption.getPercentage(consumption.high))>ALLOWANCE)
            return false;
        if(Math.abs(getPercentage(veryhigh)-consumption.getPercentage(consumption.veryhigh))>ALLOWANCE)
            return false;
        return true;
    }

    public interface FuzzyConsumptionListener {
        void onConsumptionFound(FuzzyConsumption consumption);

        void onCancelled(DatabaseError databaseError);
    }
}


text:
ACCEPTED

#### According to
Index Fungorum

#### Published in
null

#### Original name
Lecidea cinereoatra var. cinereoatra

### Remarks
null


text:
<?php

namespace Sylius\Behat\Page\Admin\CustomerGroup;

use Sylius\Behat\Page\Admin\Crud\UpdatePageInterface as BaseUpdatePageInterface;

/**
 * @author Grzegorz Sadowski <grzegorz.sadowski@lakion.com>
 */
interface UpdatePageInterface extends BaseUpdatePageInterface
{
    /**
     * @param string $name
     */
    public function nameIt($name);
}


text:
var zmq = require('../')
  , should = require('should');

var pub = zmq.socket('pub')
  , sub = zmq.socket('sub');

var n = 0;

sub.subscribe('');
sub.on('message', function(msg){
  msg.should.be.an.instanceof(Buffer);
  switch (n++) {
    case 0:
      msg.toString().should.equal('foo');
      break;
    case 1:
      msg.toString().should.equal('bar');
      break;
    case 2:
      msg.toString().should.equal('baz');
      sub.close();
      pub.close();
      break;
  }
});

sub.bind('inproc://stuff', function(){
  pub.connect('inproc://stuff');
  pub.send('foo');
  pub.send('bar');
  pub.send('baz');
});


text:
require 'spec_helper'

module Tracker
  module Application
    describe LoadStoryStory do
      let(:parent_story_id) { Tracker.pg[:stories].insert(title: 'Parent Story') }
      let(:child_story_id) { Tracker.pg[:stories].insert(title: 'Child Story') }

      subject(:result) do
        LoadStoryStory.perform(
          parent_story_id: parent_story_id,
          child_story_id: child_story_id
        )
      end

      context 'when the story story does not exist' do
        it 'is empty and does not blow up' do
          expect(result.story_story).to be_nil
        end
      end

      context 'when the story story exists' do
        let!(:story_story_id) do
          Tracker.pg[:story_stories].insert(
            parent_story_id: parent_story_id,
            child_story_id: child_story_id
          )
        end

        it 'loads the story story' do
          expect(result.story_story).to eq(
            id: story_story_id,
            parent_story_id: parent_story_id,
            child_story_id: child_story_id
          )
        end
      end
    end
  end
end


text:
void free_content(CT ct);
void free_ctinfo(CT);
void free_encoding(CT, int);
void freects_done(int) NORETURN;

extern CT *cts;


text:
package cern.accsoft.steering.util.meas.data.yasp;

import java.util.Collection;

import cern.accsoft.steering.util.meas.data.DataValue;

public interface MeasuredData<T extends DataValue> {

	/**
	 * returns the monitor value for a given key
	 *
	 * @param key
	 * @return the {@link MonitorValue}
	 */
	T getMonitorValue(String key);

	/**
	 * @return all available monitorValues
	 */
	Collection<T> getMonitorValues();
}


text:
(function(root, definition) {
    if (typeof define === 'function' && define.amd) {
        define([], definition);
    } else if (typeof exports === 'object') {
        module.exports = definition();
    } else {
        root.tokenize_equation = definition();
    }
})(this, function() {
    function is_identifier(token) {
        return token.match(/^[A-Za-z_][A-Za-z0-9_]*$/);
    }

    function is_alphanumeric(token) {
        return token.match(/^[A-Za-z0-9_\.]$/);
    }

    function is_numeric(token) {
        return token.match(/^[0-9]*\.?[0-9]+$/);
    }

    function is_operator(token) {
        return token.match(/^[+\-*\/%\^]$/);
    }

    function tokenize(equation, label) {
        var tokens = [];
        var buffer = '';
        var type = 'equation';
        var parentheses = 0;

        function append(token) {
            if (typeof token === 'string' && !is_identifier(token)
                    && !is_numeric(token) && !is_operator(token)) {
                throw new Error('Invalid Token: ' + token);
            }
            token = typeof token === 'string'
                && is_numeric(token) ? +token : token;
            if (!label || token instanceof Array) {
                tokens = tokens.concat(token);
            } else {
                tokens.push({ value: token, type: type });
            }
        }

        equation.split('').forEach(function(character) {
            if (character.trim().length) {
                var _type = 'equation';
                if (is_alphanumeric(character)) {
                    _type = 'operand';
                } else if (is_operator(character)) {
                    _type = 'operator';
                }

                if ((_type !== type || _type === 'operator') && !parentheses) {
                    if (buffer) {
                        append(buffer);
                        buffer = '';
                    }
                    type = _type;
                }

                buffer += character;
            } else if (buffer && !parentheses) {
                append(buffer);
                buffer = '';
            }

            if (character === '(') {
                parentheses++;
            } else if (character === ')') {
                if (!parentheses) {
                    throw new Error('Parenthesis Mismatched.');
                } else if (!--parentheses) {
                    buffer = buffer.substring(1, buffer.length - 1);
                    var value = tokenize(buffer, label);
                    value.unshift(label ? { value: '(', type: 'group' } : '(');
                    value.push(label ? { value: ')', type: 'group' } : ')');
                    append(value);
                    buffer = '';
                }
            }
        });

        if (parentheses) {
            throw new Error('Parenthesis Mismatched.');
        } else if (buffer) {
            append(buffer);
            buffer = '';
        }

        return tokens;
    }

    return tokenize;
});


text:
HORIZ_MARGIN     = 8
BIG_HORIZ_MARGIN = HORIZ_MARGIN * 3
VERTICAL_MARGIN  = 8
TITLE_HEIGHT     = 33
TITLE_BOTTOM     = VERTICAL_MARGIN + TITLE_HEIGHT

# HACK: IOS7 + MMDrawerController seems to let you draw behind he nav bar. Use this to move everything down
if Device.ios_version < '7.0'
  TOP_BELOW_MM_NAV = 0
else
  TOP_BELOW_MM_NAV = 65
end


text:
{\rtf1\ansi\ansicpg1252\cocoartf1343\cocoasubrtf140
{\fonttbl\f0\froman\fcharset0 Times-Roman;\f1\fnil\fcharset0 HelveticaNeue;}
{\colortbl;\red255\green255\blue255;\red0\green0\blue0;\red0\green0\blue233;\red179\green179\blue179;
}
{\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}
{\list\listtemplateid2\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid101\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid2}
{\list\listtemplateid3\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid201\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid3}
{\list\listtemplateid4\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid301\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid4}
{\list\listtemplateid5\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid401\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid5}
{\list\listtemplateid6\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid501\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid6}
{\list\listtemplateid7\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid601\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid7}
{\list\listtemplateid8\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid701\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid8}}
{\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}{\listoverride\listid2\listoverridecount0\ls2}{\listoverride\listid3\listoverridecount0\ls3}{\listoverride\listid4\listoverridecount0\ls4}{\listoverride\listid5\listoverridecount0\ls5}{\listoverride\listid6\listoverridecount0\ls6}{\listoverride\listid7\listoverridecount0\ls7}{\listoverride\listid8\listoverridecount0\ls8}}
{\info
{\title Agency - Start Bootstrap Theme}}\vieww18520\viewh18080\viewkind0
\deftab720
\pard\pardeftab720

\f0\fs24 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\pard\tx220\tx720\pardeftab720\li720\fi-720
\ls1\ilvl0\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\pard\tx220\tx720\pardeftab720\li720\fi-720
\ls1\ilvl0\cf3 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\ul \outl0\strokewidth0 \strokec3 Services\cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2  \
\ls1\ilvl0\cf3 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\ul \outl0\strokewidth0 \strokec3 Portfolio\cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2  \
\ls1\ilvl0\cf3 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\ul \outl0\strokewidth0 \strokec3 About\cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2  \
\ls1\ilvl0\cf3 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\ul \outl0\strokewidth0 \strokec3 Team\cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2  \
\ls1\ilvl0\cf3 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\ul \outl0\strokewidth0 \strokec3 Contact\cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2  \
\pard\pardeftab720
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Welcome To Our Studio!\
It's Nice To Meet You\
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 Tell Me More\cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2  \
\pard\pardeftab720\sa298

\b\fs36 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Services\
\pard\pardeftab720\sa280

\fs28 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet consectetur.\
\pard\pardeftab720\sa319

\fs24 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 E-Commerce\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima maxime quam architecto quo inventore harum ex magni, dicta impedit.\
\pard\pardeftab720\sa319

\b \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Responsive Design\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima maxime quam architecto quo inventore harum ex magni, dicta impedit.\
\pard\pardeftab720\sa319

\b \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Web Security\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Minima maxime quam architecto quo inventore harum ex magni, dicta impedit.\
\pard\pardeftab720\sa298

\b\fs36 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Portfolio\
\pard\pardeftab720\sa280

\fs28 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet consectetur.\
\pard\pardeftab720

\b0\fs24 \cf3 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec3 \
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \
\pard\pardeftab720\sa319

\b \cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2 Round Icons\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Graphic Design\
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec3 \
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \
\pard\pardeftab720\sa319

\b \cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2 Startup Framework\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Website Design\
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec3 \
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \
\pard\pardeftab720\sa319

\b \cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2 Treehouse\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Website Design\
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec3 \
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \
\pard\pardeftab720\sa319

\b \cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2 Golden\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Website Design\
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec3 \
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \
\pard\pardeftab720\sa319

\b \cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2 Escape\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Website Design\
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec3 \
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \
\pard\pardeftab720\sa319

\b \cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2 Dreams\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Website Design\
\pard\pardeftab720\sa298

\b\fs36 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 About\
\pard\pardeftab720\sa280

\fs28 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet consectetur.\
\pard\tx220\tx720\pardeftab720\li720\fi-720
\ls2\ilvl0
\b0\fs24 \cf2 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0  \uc0\u8232
\b \expnd0\expndtw0\kerning0
\outl0\strokewidth0 2009-2011\uc0\u8232 Our Humble Beginnings\u8232
\b0 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \uc0\u8232 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sunt ut voluptatum eius sapiente, totam reiciendis temporibus qui quibusdam, recusandae sit vero unde, sed, incidunt et ea quo dolore laudantium consectetur!\u8232 \u8232 \u8232 \
\ls2\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2  \uc0\u8232
\b \expnd0\expndtw0\kerning0
\outl0\strokewidth0 March 2011\uc0\u8232 An Agency is Born\u8232
\b0 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \uc0\u8232 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sunt ut voluptatum eius sapiente, totam reiciendis temporibus qui quibusdam, recusandae sit vero unde, sed, incidunt et ea quo dolore laudantium consectetur!\u8232 \u8232 \u8232 \
\ls2\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2  \uc0\u8232
\b \expnd0\expndtw0\kerning0
\outl0\strokewidth0 December 2012\uc0\u8232 Transition to Full Service\u8232
\b0 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \uc0\u8232 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sunt ut voluptatum eius sapiente, totam reiciendis temporibus qui quibusdam, recusandae sit vero unde, sed, incidunt et ea quo dolore laudantium consectetur!\u8232 \u8232 \u8232 \
\ls2\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2  \uc0\u8232
\b \expnd0\expndtw0\kerning0
\outl0\strokewidth0 July 2014\uc0\u8232 Phase Two Expansion\u8232
\b0 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \uc0\u8232 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Sunt ut voluptatum eius sapiente, totam reiciendis temporibus qui quibusdam, recusandae sit vero unde, sed, incidunt et ea quo dolore laudantium consectetur!\u8232 \u8232 \u8232 \
\pard\tx220\tx720\pardeftab720\li720\fi-720\sa319
\ls2\ilvl0
\b \cf2 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 Be Part \uc0\u8232 Of Our \u8232 Story!\u8232
\b0 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \uc0\u8232 \
\pard\pardeftab720\sa298

\b\fs36 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Our Team\
\pard\pardeftab720\sa280

\fs28 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet consectetur.\
\pard\pardeftab720

\b0\fs24 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\pard\pardeftab720\sa319

\b \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Danika Landers\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Partner and User Experience Designer\
\pard\tx220\tx720\pardeftab720\li720\fi-720
\ls3\ilvl0\cf2 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\ls3\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\ls3\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\pard\pardeftab720
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\pard\pardeftab720\sa319

\b \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Ruth No Wong\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Partner and User Interface Designer\
\pard\tx220\tx720\pardeftab720\li720\fi-720
\ls4\ilvl0\cf2 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\ls4\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\ls4\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\pard\pardeftab720
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\pard\pardeftab720\sa319

\b \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Diana Pertersen\
\pard\pardeftab720\sa240

\b0 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lead Developer\
\pard\tx220\tx720\pardeftab720\li720\fi-720
\ls5\ilvl0\cf2 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\ls5\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\ls5\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\pard\pardeftab720\sa240
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aut eaque, laboriosam veritatis, quos non quis ad perspiciatis, totam corporis ea, alias ut unde.\
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec3 \pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0  \cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2 \
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec3 \pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0  \cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2 \
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec3 \pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0  \cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2 \
\pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec3 \pard\pardeftab720
\cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0  \cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2 \
\pard\pardeftab720\sa298

\b\fs36 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Contact Us\
\pard\pardeftab720\sa280

\fs28 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet consectetur.\
\pard\pardeftab720\sa240

\b0\fs24 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\
\
\
\pard\pardeftab720
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\
\pard\pardeftab720

\f1\fs22 \cf2 \cb4 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Send Message
\f0\fs24 \cb1 \expnd0\expndtw0\kerning0
\outl0\strokewidth0  \
Copyright \'a9 Your Website 2014 \
\pard\tx220\tx720\pardeftab720\li720\fi-720
\ls6\ilvl0\cf2 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\ls6\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\ls6\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 \
\pard\tx220\tx720\pardeftab720\li720\fi-720
\ls7\ilvl0\cf3 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\ul \outl0\strokewidth0 \strokec3 Privacy Policy\cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2  \
\ls7\ilvl0\cf3 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\ul \outl0\strokewidth0 \strokec3 Terms of Use\cf2 \expnd0\expndtw0\kerning0
\ulnone \outl0\strokewidth0 \strokec2  \
\pard\pardeftab720
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\pard\pardeftab720\sa298

\b\fs36 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Project Name\
\pard\pardeftab720\sa240

\b0\fs24 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet consectetur.\
\pard\pardeftab720
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\pard\pardeftab720\sa240
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Use this area to describe your project. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Est blanditiis dolorem culpa incidunt minus dignissimos deserunt repellat aperiam quasi sunt officia expedita beatae cupiditate, maiores repudiandae, nostrum, reiciendis facere nemo!\
\pard\pardeftab720\sa240

\b \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Want these icons in this portfolio item sample?
\b0 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 You can download 60 of them for free, courtesy of {\field{\*\fldinst{HYPERLINK "https://getdpd.com/cart/hoplink/18076?referrer=bvbo4kax5k8ogc"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 RoundIcons.com}}, or you can purchase the 1500 icon set {\field{\*\fldinst{HYPERLINK "https://getdpd.com/cart/hoplink/18076?referrer=bvbo4kax5k8ogc"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 here}}.\
\pard\tx220\tx720\pardeftab720\li720\fi-720
\ls8\ilvl0\cf2 \kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 Date: July 2014\
\ls8\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 Client: Round Icons\
\ls8\ilvl0\kerning1\expnd0\expndtw0 \outl0\strokewidth0 {\listtext	\'95	}\expnd0\expndtw0\kerning0
\outl0\strokewidth0 \strokec2 Category: Graphic Design\
\pard\pardeftab720

\f1\fs22 \cf2 \cb4 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Close Project
\f0\fs24 \cb1 \expnd0\expndtw0\kerning0
\outl0\strokewidth0  \
\
\pard\pardeftab720\sa298

\b\fs36 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Project Heading\
\pard\pardeftab720\sa240

\b0\fs24 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet consectetur.\
\pard\pardeftab720
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\pard\pardeftab720\sa240
{\field{\*\fldinst{HYPERLINK "http://designmodo.com/startup/?u=787"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 Startup Framework}}\expnd0\expndtw0\kerning0
\outl0\strokewidth0  is a website builder for professionals. Startup Framework contains components and complex blocks (PSD+HTML Bootstrap themes and templates) which can easily be integrated into almost any design. All of these components are made in the same style, and can easily be integrated into projects, allowing you to create hundreds of solutions for your future projects.\
You can preview Startup Framework {\field{\*\fldinst{HYPERLINK "http://designmodo.com/startup/?u=787"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 here}}.\
\pard\pardeftab720

\f1\fs22 \cf2 \cb4 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Close Project
\f0\fs24 \cb1 \expnd0\expndtw0\kerning0
\outl0\strokewidth0  \
\
\pard\pardeftab720\sa298

\b\fs36 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Project Name\
\pard\pardeftab720\sa240

\b0\fs24 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet consectetur.\
\pard\pardeftab720
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\pard\pardeftab720\sa240
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Treehouse is a free PSD web template built by {\field{\*\fldinst{HYPERLINK "https://www.behance.net/MathavanJaya"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 Mathavan Jaya}}. This is bright and spacious design perfect for people or startup companies looking to showcase their apps or other projects.\
You can download the PSD template in this portfolio sample item at {\field{\*\fldinst{HYPERLINK "http://freebiesxpress.com/gallery/treehouse-free-psd-web-template/"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 FreebiesXpress.com}}.\
\pard\pardeftab720

\f1\fs22 \cf2 \cb4 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Close Project
\f0\fs24 \cb1 \expnd0\expndtw0\kerning0
\outl0\strokewidth0  \
\
\pard\pardeftab720\sa298

\b\fs36 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Project Name\
\pard\pardeftab720\sa240

\b0\fs24 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet consectetur.\
\pard\pardeftab720
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\pard\pardeftab720\sa240
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Start Bootstrap's Agency theme is based on Golden, a free PSD website template built by {\field{\*\fldinst{HYPERLINK "https://www.behance.net/MathavanJaya"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 Mathavan Jaya}}. Golden is a modern and clean one page web template that was made exclusively for Best PSD Freebies. This template has a great portfolio, timeline, and meet your team sections that can be easily modified to fit your needs.\
You can download the PSD template in this portfolio sample item at {\field{\*\fldinst{HYPERLINK "http://freebiesxpress.com/gallery/golden-free-one-page-web-template/"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 FreebiesXpress.com}}.\
\pard\pardeftab720

\f1\fs22 \cf2 \cb4 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Close Project
\f0\fs24 \cb1 \expnd0\expndtw0\kerning0
\outl0\strokewidth0  \
\
\pard\pardeftab720\sa298

\b\fs36 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Project Name\
\pard\pardeftab720\sa240

\b0\fs24 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet consectetur.\
\pard\pardeftab720
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\pard\pardeftab720\sa240
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Escape is a free PSD web template built by {\field{\*\fldinst{HYPERLINK "https://www.behance.net/MathavanJaya"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 Mathavan Jaya}}. Escape is a one page web template that was designed with agencies in mind. This template is ideal for those looking for a simple one page solution to describe your business and offer your services.\
You can download the PSD template in this portfolio sample item at {\field{\*\fldinst{HYPERLINK "http://freebiesxpress.com/gallery/escape-one-page-psd-web-template/"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 FreebiesXpress.com}}.\
\pard\pardeftab720

\f1\fs22 \cf2 \cb4 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Close Project
\f0\fs24 \cb1 \expnd0\expndtw0\kerning0
\outl0\strokewidth0  \
\
\pard\pardeftab720\sa298

\b\fs36 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Project Name\
\pard\pardeftab720\sa240

\b0\fs24 \cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Lorem ipsum dolor sit amet consectetur.\
\pard\pardeftab720
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 \
\pard\pardeftab720\sa240
\cf2 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Dreams is a free PSD web template built by {\field{\*\fldinst{HYPERLINK "https://www.behance.net/MathavanJaya"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 Mathavan Jaya}}. Dreams is a modern one page web template designed for almost any purpose. It\'92s a beautiful template that\'92s designed with the Bootstrap framework in mind.\
You can download the PSD template in this portfolio sample item at {\field{\*\fldinst{HYPERLINK "http://freebiesxpress.com/gallery/dreams-free-one-page-web-template/"}}{\fldrslt \cf3 \expnd0\expndtw0\kerning0
\ul \ulc3 \outl0\strokewidth0 \strokec3 FreebiesXpress.com}}.\
\pard\pardeftab720

\f1\fs22 \cf2 \cb4 \expnd0\expndtw0\kerning0
\outl0\strokewidth0 Close Project
\f0\fs24 \cb1 \expnd0\expndtw0\kerning0
\outl0\strokewidth0  \
}


text:
FROM alpine:3.7

RUN adduser -D server

COPY ./bin/server /home/server/server

RUN chown -R server /home/server && \
    chmod o+x /home/server/server

USER server
ENTRYPOINT /home/server/server


text:
<?php

/**
 * Slim Framework (https://slimframework.com)
 *
 * @license https://github.com/slimphp/Slim-Http/blob/master/LICENSE.md (MIT License)
 */

declare(strict_types=1);

namespace Slim\Http;

use Psr\Http\Message\UriInterface;

class Uri implements UriInterface
{
    protected UriInterface $uri;

    /**
     * @param UriInterface $uri
     */
    final public function __construct(UriInterface $uri)
    {
        $this->uri = $uri;
    }

    /**
     * Disable magic setter to ensure immutability
     * @param mixed $name
     * @param mixed $value
     * @return void
     */
    public function __set($name, $value)
    {
    }

    /**
     * {@inheritdoc}
     */
    public function getAuthority(): string
    {
        return $this->uri->getAuthority();
    }

    /**
     * {@inheritdoc}
     */
    public function getFragment(): string
    {
        return $this->uri->getFragment();
    }

    /**
     * {@inheritdoc}
     */
    public function getHost(): string
    {
        return $this->uri->getHost();
    }

    /**
     * {@inheritdoc}
     */
    public function getPath(): string
    {
        return $this->uri->getPath();
    }

    /**
     * {@inheritdoc}
     */
    public function getPort(): ?int
    {
        return $this->uri->getPort();
    }

    /**
     * {@inheritdoc}
     */
    public function getQuery(): string
    {
        return $this->uri->getQuery();
    }

    /**
     * {@inheritdoc}
     */
    public function getScheme(): string
    {
        return $this->uri->getScheme();
    }

    /**
     * {@inheritdoc}
     */
    public function getUserInfo(): string
    {
        return $this->uri->getUserInfo();
    }

    /**
     * {@inheritdoc}
     */
    public function withFragment($fragment)
    {
        $uri = $this->uri->withFragment($fragment);
        return new static($uri);
    }

    /**
     * {@inheritdoc}
     */
    public function withHost($host)
    {
        $uri = $this->uri->withHost($host);
        return new static($uri);
    }

    /**
     * {@inheritdoc}
     */
    public function withPath($path)
    {
        $uri = $this->uri->withPath($path);
        return new static($uri);
    }

    /**
     * {@inheritdoc}
     */
    public function withPort($port)
    {
        $uri = $this->uri->withPort($port);
        return new static($uri);
    }

    /**
     * {@inheritdoc}
     */
    public function withQuery($query)
    {
        $uri = $this->uri->withQuery($query);
        return new static($uri);
    }

    /**
     * {@inheritdoc}
     */
    public function withScheme($scheme)
    {
        $uri = $this->uri->withScheme($scheme);
        return new static($uri);
    }

    /**
     * {@inheritdoc}
     */
    public function withUserInfo($user, $password = null)
    {
        $uri = $this->uri->withUserInfo($user, $password);
        return new static($uri);
    }

    /**
     * {@inheritdoc}
     */
    public function __toString(): string
    {
        return $this->uri->__toString();
    }

    /**
     * Return the fully qualified base URL.
     *
     * Note that this method never includes a trailing slash
     *
     * This method is not part of PSR-7.
     *
     * @return string
     */
    public function getBaseUrl(): string
    {
        $scheme = $this->uri->getScheme();
        $authority = $this->uri->getAuthority();
        return ($scheme !== '' ? $scheme . ':' : '') . ($authority !== '' ? '//' . $authority : '');
    }
}


text:
'use strict';

let gulp = require('gulp')
    , eslint = require('gulp-eslint')
    , rename = require('gulp-rename')
    , uglify = require('gulp-uglify')
    , replace = require('gulp-replace')
    , sourcemaps = require('gulp-sourcemaps')
    , karma = require('karma').Server
    , source = require('vinyl-source-stream')
    , buffer = require('vinyl-buffer')
    , rollup = require('rollup-stream')
    , buble = require('rollup-plugin-buble');

process.chdir(__dirname);

let bundle = (format) => {
    return rollup({
        entry: 'lib/quilk-frontend-router.js'
        , format: format
        , moduleName: 'QuilkFrontendRouter'
        , plugins: [ buble() ]
        , sourceMap: true
        , useStrict: false
    })
        .pipe(source('quilk-frontend-router.js', './lib'))
        .pipe(buffer())
        .pipe(replace(
            /@@VERSION@@/g
            , require('./package.json').version
        ));
};

gulp.task('cjs', () => {
    return bundle('cjs')
        .pipe(sourcemaps.init({
            loadMaps: true
        }))
        .pipe(rename((path) => {
            path.basename = 'index';
        }))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('./'));
});

gulp.task('js', [ 'cjs' ], () => {
    return bundle('umd')
        .pipe(sourcemaps.init({
            loadMaps: true
        }))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('dist'));
});

gulp.task('jsmin', [ 'js' ], () => {
    return gulp.src('dist/quilk-frontend-router.js')
        .pipe(sourcemaps.init({
            loadMaps: true
        }))
        .pipe(uglify({
            mangle: true
        }))
        .pipe(rename((path) => {
            path.basename += '.min';
        }))
        .pipe(sourcemaps.write('.'))
        .pipe(gulp.dest('dist'));
});

gulp.task('build', [
    'jsmin'
]);

gulp.task('default', [
    'build'
]);


text:
import datetime
from flask_mongoengine import MongoEngine

db = MongoEngine()

class User(db.Document):
    name = db.StringField(max_length=50, required=True)
    password = db.StringField()
    email = db.StringField()
    avatar = db.StringField()
    signature = db.StringField()
    created_at = db.DateTimeField(default=datetime.datetime.now, required=True)

class Diary(db.Document):
    title = db.StringField(required=True)
    old_id = db.IntField()
    content = db.StringField()
    summary = db.StringField()
    html = db.StringField()
    category = db.StringField(default=u'未分类')
    author = db.ReferenceField(User)
    tags = db.SortedListField(db.StringField())
    comments = db.SortedListField(db.EmbeddedDocumentField('CommentEm'))
    publish_time = db.DateTimeField(default=datetime.datetime.now, required=True)
    update_time = db.DateTimeField(default=datetime.datetime.now, required=True)

    meta = {'allow_inheritance': True}

class Photo(db.Document):
    url = db.StringField(required=True)
    title = db.StringField(required=True)
    album_name = db.StringField(default=u'未分类')
    description = db.StringField()
    publish_time = db.DateTimeField(default=datetime.datetime.now, required=True)

class Tag(db.Document):
    name = db.StringField(max_length=120, required=True)
    diaries = db.SortedListField(db.ReferenceField(Diary))
    publish_time = db.DateTimeField(default=datetime.datetime.now, required=True)

class Category(db.Document):
    name = db.StringField(max_length=120, required=True)
    diaries = db.SortedListField(db.ReferenceField(Diary))
    publish_time = db.DateTimeField(default=datetime.datetime.now, required=True)

class Comment(db.Document):
    content = db.StringField(required=True)
    author = db.StringField(max_length=120, required=True)
    email = db.EmailField()
    diary = db.ReferenceField(Diary)
    publish_time = db.DateTimeField(default=datetime.datetime.now, required=True)

class Page(db.Document):
    url = db.StringField(required=True, unique=True)
    title = db.StringField(required=True)
    content = db.StringField()
    summary = db.StringField()
    html = db.StringField()
    author = db.ReferenceField(User)
    comments = db.SortedListField(db.EmbeddedDocumentField('CommentEm'))
    publish_time = db.DateTimeField(default=datetime.datetime.now, required=True)
    update_time = db.DateTimeField(default=datetime.datetime.now, required=True)

    meta = {'allow_inheritance': True}

class StaticPage(Page):
    pass

class CommentEm(db.EmbeddedDocument):
    content = db.StringField(required=True)
    author = db.StringField(max_length=120, required=True)
    email = db.EmailField()
    publish_time = db.DateTimeField(default=datetime.datetime.now, required=True)


text:
package org.apache.spark.sql.execution.columnar

import java.nio.{ByteBuffer, ByteOrder}

import org.apache.spark.sql.catalyst.InternalRow

private[columnar] trait NullableColumnAccessor extends ColumnAccessor {
  private var nullsBuffer: ByteBuffer = _
  private var nullCount: Int = _
  private var seenNulls: Int = 0

  private var nextNullIndex: Int = _
  private var pos: Int = 0

  abstract override protected def initialize(): Unit = {
    nullsBuffer = underlyingBuffer.duplicate().order(ByteOrder.nativeOrder())
    nullCount = ByteBufferHelper.getInt(nullsBuffer)
    nextNullIndex = if (nullCount > 0) ByteBufferHelper.getInt(nullsBuffer) else -1
    pos = 0

    underlyingBuffer.position(underlyingBuffer.position() + 4 + nullCount * 4)
    super.initialize()
  }

  abstract override def extractTo(row: InternalRow, ordinal: Int): Unit = {
    if (pos == nextNullIndex) {
      seenNulls += 1

      if (seenNulls < nullCount) {
        nextNullIndex = ByteBufferHelper.getInt(nullsBuffer)
      }

      row.setNullAt(ordinal)
    } else {
      super.extractTo(row, ordinal)
    }

    pos += 1
  }

  abstract override def hasNext: Boolean = seenNulls < nullCount || super.hasNext
}


text:
<?php
/**
 * YiiChatWidget
 *
 *	Please refer to README about details.
 *
 *
 * @uses CWidget
 * @version 1.0
 * @author Christian Salazar <christiansalazarh@gmail.com>
 * @license FREE BSD
 */
class YiiChatWidget extends CWidget {

	public	$chat_id;	// chat main identificator
	public	$identity;	// ID, can be: Yii::app()->user->id
	public	$selector;	// jQuery selector (holder)

	public	$sendButtonText='Kirim';
	public	$onError;
	public	$onSuccess;
	public  $defaultController='/admin';
	public	$minPostLen=2;
	public	$maxPostLen=5000;
	public  $model; // a model instance, it must implements IYiiChat
	public  $timerMs = 5000;
	public  $data;	// public data passed to the model instance

	public	$myOwnPostCssStyle;		// css style names
	public	$othersPostCssStyle;	//

	private $_action;
	private $_baseUrl;

	public function init(){
		parent::init();
		$this->_prepareAssets();
		if($this->onError==null || $this->onError=='')
			$this->onError = new CJavaScriptExpression("function(err, txt){}");
		if(!($this->onError instanceof CJavaScriptExpression))
			throw new Exception("onError must be a CJavaScriptExpression");
		if($this->onSuccess==null || $this->onSuccess=='')
			$this->onSuccess = new CJavaScriptExpression("function(code, txt, post_id){}");
		if(!($this->onSuccess instanceof CJavaScriptExpression))
			throw new Exception("onSuccess must be a CJavaScriptExpression");
	}

	public function run(){
		$_interfaceName='IYiiChat';
		if($_impl = class_implements($this->model))
			if(!isset($_impl[$_interfaceName]))
				throw new Exception("The model instance passed by "
					."argument to this widget must implements IYiiChat interface");
		// this 'dummy' argument is required to provide urlmanager support...
		$this->_action = array($this->defaultController.'/yiichat','dummy'=>'@');
		$options = CJavaScript::encode(array(
			'selector'=>$this->selector,
			'chat_id'=>$this->chat_id,
			'identity'=>$this->identity,
			'sendButtonText'=>$this->sendButtonText,
			'onError'=>$this->onError,
			'onSuccess'=>$this->onSuccess,
			'minPostLen'=>$this->minPostLen,
			'maxPostLen'=>$this->maxPostLen,
			'action'=>CHtml::normalizeUrl($this->_action),
			'timerMs'=>$this->timerMs,
			'myOwnPostCssStyle'=>$this->myOwnPostCssStyle,
			'othersPostCssStyle'=>$this->othersPostCssStyle,
		));
		$s = Yii::app()->session;
		$s[$this->chat_id.'_model'] = $this->model;
		$s[$this->chat_id.'_data'] = $this->data;
		$var_id = rand(1000,9999);
		Yii::app()->getClientScript()->registerScript("yii_chat_script_".$var_id
		,"	var chat_{$var_id} = new YiiChat({$options});
			chat_{$var_id}.run();
		");
	}// end run()

	public function _prepareAssets(){
		$localAssetsDir = dirname(__FILE__) . '/assets';
		$this->_baseUrl = Yii::app()->getAssetManager()->publish(
				$localAssetsDir);
        $cs = Yii::app()->getClientScript();
        $cs->registerCoreScript('jquery');
		foreach(scandir($localAssetsDir) as $f){
			$_f = strtolower($f);
			if(strstr($_f,".swp"))
				continue;
			if(strstr($_f,".js"))
				$cs->registerScriptFile($this->_baseUrl."/".$_f);
			if(strstr($_f,".css"))
				$cs->registerCssFile($this->_baseUrl."/".$_f);
		}
	}

	public function runAction($action, $data){
		$chat_id = $this->_getPost('chat_id',null);
		$identity = $this->_getPost('identity',null);
		$text = $this->_getPost('text');
		$s = Yii::app()->session;
		$model = $s[$chat_id.'_model'];
		$data = $s[$chat_id.'_data'];
		if(($action == 'sendpost') && $identity && $chat_id){
			header("Content-type: application/json");
			if($post = $model->yiichat_post($chat_id, $identity, $text, $data)){
				if(!isset($post['chat_id']))
					$post['chat_id']=$chat_id;
				if(!isset($post['identity']))
					$post['identity']=$identity;
				if(!isset($post['post_identity']))
					$post['post_identity']=$identity; // must be the same
				echo CJSON::encode($post);
			}else{
				echo CJSON::encode("REJECTED");
			}
		}
		if(($action == 'init') && $identity && $chat_id){
			$posts = $model->yiichat_list_posts($chat_id, $identity, -1, $data);
			if($posts==null)
				$posts = array();
			$data = array('chat_id'=>$chat_id, 'identity'=>$identity,
				'posts'=>$posts);
			header("Content-type: application/json");
			echo CJSON::encode($data);
		}
		if(($action == 'timer') && $identity && $chat_id){
			$posts = $model->yiichat_list_posts(
					$chat_id, $identity, $this->_getPost('last_id'), $data);
			if($posts==null)
				$posts = array();
			$data = array('chat_id'=>$chat_id, 'identity'=>$identity,
				'posts'=>$posts);
			header("Content-type: application/json");
			echo CJSON::encode($data);
		}
	}

	private function _getPost($attr, $def=''){
		if(isset($_POST[$attr])){
			$value = trim($_POST[$attr]);
			if(($value == 'undefined') || ($value == null) || ($value==''))
				return $def;
			return $value;
		}
		else{
			return $def;
		}
	}
}


text:
/*
*
*/
#pragma once
#ifndef _CLEARSKY_CLEARSKY_IMOUSE_LISTENER_H_
#define _CLEARSKY_CLEARSKY_IMOUSE_LISTENER_H_

#include "core/utils.h"

namespace clearsky
{
	class Window;

	class CLEARSKY_API MouseEvent
	{
		public:
			Window *window;
			int x;
			int y;
			int xAbs;
			int yAbs;
	};

	class CLEARSKY_API MouseMoveEvent : public MouseEvent
	{
		public:
			double deltaX;
			double deltaY;
	};

	class CLEARSKY_API MouseKeyEvent : public MouseEvent
	{
		public:
			int	keyCode;
			bool down;
	};

	class CLEARSKY_API IMouseListener
	{
		public:
			virtual void mouseMove(MouseMoveEvent mouseEvent){};
			virtual void mouseKey(MouseKeyEvent mouseEvent){};
			virtual void mouseOver(MouseEvent mouseEvent){};
			virtual void mouseClicked(MouseKeyEvent mouseEvent){};
			virtual void mouseEnter(MouseEvent mouseEvent){};
			virtual void mouseLeave(MouseEvent mouseEvent){};

		private:
	};
}

#endif


text:
      <button class="link-cmd ui-btn accessory" ng-click="toggleManagerLoadBalancer()" class="btn-toggle-loadbalancer">Load Balancer</button>

        <sl-manager-load-balancer></sl-manager-load-balancer>

      {{ appContext.name }}

        {{ appContext.version }}

    <form class="ui-form has-table" name="form" novalidate ng-submit="save(form)">

            Service

            Strong PM

            Port

            App Status

            Count

            PIDs

            {{host.app.name}}

            <sl-manager-host-name></sl-manager-host-name>

              <sl-manager-host-port></sl-manager-host-port>

              <sl-manager-status></sl-manager-status>

              <sl-manager-process-count></sl-manager-process-count>

              <sl-manager-process-list></sl-manager-process-list>

            (X)

            <ng-form name="currentPMHostForm">

                <input type="text"
                       ng-model="currentPM.host"
                       class="ui-input"
                       name="host"
                       typeahead-focus-first="false"
                       sl-common-select-on-click
                       typeahead-on-select="onPMServerSelectAutoCompleted($item, 'currentPM')"
                       typeahead="server as server.host + ' : ' + server.port for server in hosts"
                       ng-minlength="8"
                       ng-focus="itemFocus($event)"
                       ng-blur="itemBlur($event)"
                       placeholder="host"
                       required>
                Please enter host

            </ng-form>

            <ng-form name="currentPMPortForm">

                <input
                  class="ui-input skinny"
                  type="text"
                  name="port"
                  ng-model="currentPM.port"
                  placeholder="(eg: 8701)"
                  ng-focus="itemFocus($event)"
                  ng-blur="itemBlur($event)">

            </ng-form>

                {{ currentPM.status || 'Activate' }}

              <button title="state of host"
                      class="status-icon"
                      ng-click="savePM()">

              </button>

            (X)

            <button
              class="ui-btn accessory"
              ng-click="initAddNewPMHost()"
              tooltip="{{addHostTooltipText}}"
              ng-class="{ disabled: isAddHostButtonDisabled }">

              Add PM Host
            </button>

    </form>


text:
namespace mate {

template<>
struct Converter<content::WebContents*> {
  static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
                     content::WebContents** out) {
    atom::api::WebContents* contents;
    if (!Converter<atom::api::WebContents*>::FromV8(isolate, val, &contents))
      return false;
    *out = contents->web_contents();
    return true;
  }
};

template<>
struct Converter<atom::WebViewManager::WebViewInfo> {
  static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
                     atom::WebViewManager::WebViewInfo* out) {
    Dictionary options;
    if (!ConvertFromV8(isolate, val, &options))
      return false;

    GURL preload_url;
    if (!options.Get("preloadUrl", &preload_url))
      return false;

    if (!preload_url.is_empty() &&
        !net::FileURLToFilePath(preload_url, &(out->preload_script)))
      return false;

    return options.Get("nodeIntegration", &(out->node_integration)) &&
           options.Get("plugins", &(out->plugins)) &&
           options.Get("disableWebSecurity", &(out->disable_web_security));
  }
};

}  // namespace mate

namespace {

atom::WebViewManager* GetWebViewManager(content::WebContents* web_contents) {
  auto context = web_contents->GetBrowserContext();
  if (context) {
    auto manager = context->GetGuestManager();
    return static_cast<atom::WebViewManager*>(manager);
  } else {
    return nullptr;
  }
}

void AddGuest(int guest_instance_id,
              int element_instance_id,
              content::WebContents* embedder,
              content::WebContents* guest_web_contents,
              atom::WebViewManager::WebViewInfo info) {
  auto manager = GetWebViewManager(embedder);
  if (manager) {
    info.guest_instance_id = guest_instance_id;
    info.embedder = embedder;
    manager->AddGuest(guest_instance_id, element_instance_id, embedder,
                      guest_web_contents, info);
  }
}

void RemoveGuest(content::WebContents* embedder, int guest_instance_id) {
  auto manager = GetWebViewManager(embedder);
  if (manager)
    manager->RemoveGuest(guest_instance_id);
}

void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
                v8::Handle<v8::Context> context, void* priv) {
  mate::Dictionary dict(context->GetIsolate(), exports);
  dict.SetMethod("addGuest", &AddGuest);
  dict.SetMethod("removeGuest", &RemoveGuest);
}

}  // namespace

NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_web_view_manager, Initialize)


text:
package com.jeeplus.weixin.fastweixin.api.response;

import com.jeeplus.weixin.fastweixin.api.entity.InterfaceSummaryHour;

import java.util.List;

/**
 * @author peiyu
 */
public class GetInterfaceSummaryHourResponse extends BaseResponse {

    private List<InterfaceSummaryHour> list;

    public List<InterfaceSummaryHour> getList() {
        return list;
    }

    public void setList(List<InterfaceSummaryHour> list) {
        this.list = list;
    }
}


text:
package test.simpleserviceandevent;

import org.capcaval.c3.component.ComponentEventSubscribe;
import org.capcaval.c3.componentmanager.ComponentManager;

import test.simpleserviceandevent.hellomachine.HelloMachineEvent;
import test.simpleserviceandevent.hellomachine.HelloMachineServices;
import test.simpleserviceandevent.hellomachine.impl.HelloMachineImpl;

public class HelloMachineMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {

		ComponentManager cm = ComponentManager.componentManager;

		cm.registerComponent(HelloMachineImpl.class);

		cm.startApplication();

		ComponentEventSubscribe<HelloMachineEvent> tces = cm.getComponentEventSubscribe(HelloMachineEvent.class);

		tces.subscribe(new HelloMachineEvent() {

			@Override
			public void notifyHelloMessageChanged(String updatedmessage) {
				System.out.println("Message updated : " + updatedmessage);
			}
		});

		HelloMachineServices hms = cm.getComponentService(HelloMachineServices.class);

		String name = hms.getNameToSalute();

		System.out.println("Default name : " + name);

		hms.setNameToSalute("world");

		cm.stopApplication();
	}

}


text:
Changelog
=========

0.7.6 (2015-08-01)
------------------

- Fixed DRY_RUN message print by using print_msg that handles PY2 and PY3 strings
- Added -F/--files-only option to 115 down
- Fixed files_only parse error
- Fixed unexpected kwargs for get_tasks
- Fixed Task against added 'url' attr

0.7.5 (2015-07-02)
------------------

- Added environs to make a "workaround" that deals with issue #27
- Fixed Task.is_directory to include 'BEING TRANSFERRED' exception

0.7.4 (2015-06-20)
------------------

- Fixed getting download URL error due to another API change (#23)

0.7.3 (2015-06-16)
------------------

- Fixed previous broken release that does not contain CLI command 115

0.7.2 (2015-06-16)
------------------

- Fixed getting download URL error due to API change (#23)

0.7.1 (2015-06-15)
------------------

- Fixed argparse's required subparser behavior in Python 2.7 (http://bugs.python.org/issue9253)

0.7.0 (2015-06-14)
------------------

- Added public methods: move, edit, mkdir (#13, #19)
- Added Pro API support for getting download URL (#21)
- Added ``receiver_directory``
- Added logging utility and debugging hooks (#22)
- Combined 115down and 115up into a single 115 commands
- Supported Python 3.4 by removing ``__del__``

0.6.0 (2015-05-17)
------------------

- Deprecated ``auto_logout`` argument
- Added cookies support to CLI commands

0.5.1 (2015-04-20)
------------------

- 115down: fixed sub-entry range parser to ordered list

0.5.0 (2015-04-12)
------------------

- 115down: supported both keeping directory structure and flattening
- Fixed ``Task`` to not inherit ``Directory``

0.4.2 (2015-04-03)
------------------

- Fixed broken upload due to source page change (``_parse_src_js_var``)

0.4.1 (2015-04-03)
------------------

- 115down: added range support for argument ``sub_num`` (#14)
- 115down: added size display for file and task entries

0.4.0 (2015-03-23)
------------------

- Added persistent session (cookies) feature
- Added search API
- Added CLI commands: 115down and 115up
- Fixed #10

0.3.1 (2015-02-03)
------------------

- Fixed broken release 0.3.0 due to a missing dependency

0.3.0 (2015-02-03)
------------------

- Used external package "homura" to replace downloader utility
- Merge #8: added add_task_url API

0.2.4 (2014-10-09)
------------------

- Fixed #5: add isatty() so progress refreshes less frequently on non-tty
- Fixed parse_src_js_var

0.2.3 (2014-09-23)
------------------

- Fixed #2: ``show_progress`` argument
- Added resume download feature

0.2.2 (2014-09-20)
------------------

- Added system dependencies to documentation

0.2.1 (2014-09-20)
------------------

- Fixed ``Task.status_human`` error

0.2.0 (2014-09-20)
------------------

- Added download feature to the API and ``download`` method to ``u115.File``
- Added elaborate exceptions
- Added ``auto_logout`` optional argument to ``u115.API.__init__``
- Updated Task status info

0.1.1 (2014-09-11)
------------------

- Fixed broken sdist release of v0.1.0.

0.1.0 (2014-09-11)
------------------

- Initial release.


text:
namespace ash {
namespace {

class TestHighlighterObserver : public HighlighterController::Observer {
 public:
  TestHighlighterObserver() = default;

  TestHighlighterObserver(const TestHighlighterObserver&) = delete;
  TestHighlighterObserver& operator=(const TestHighlighterObserver&) = delete;

  ~TestHighlighterObserver() override = default;

  // HighlighterController::Observer:
  void OnHighlighterEnabledChanged(HighlighterEnabledState state) override {
    switch (state) {
      case HighlighterEnabledState::kEnabled:
        ++enabled_count_;
        break;
      case HighlighterEnabledState::kDisabledByUser:
        ++disabled_by_user_count_;
        break;
      case HighlighterEnabledState::kDisabledBySessionAbort:
        ++disabled_by_session_abort_;
        break;
      case HighlighterEnabledState::kDisabledBySessionComplete:
        ++disabled_by_session_complete_;
        break;
    }
  }

  void OnHighlighterSelectionRecognized(const gfx::Rect& rect) override {
    last_recognized_rect_ = rect;
  }

  int enabled_count_ = 0;
  int disabled_by_user_count_ = 0;
  int disabled_by_session_abort_ = 0;
  int disabled_by_session_complete_ = 0;
  gfx::Rect last_recognized_rect_;
};

class HighlighterControllerTest : public AssistantAshTestBase {
 public:
  HighlighterControllerTest() = default;

  HighlighterControllerTest(const HighlighterControllerTest&) = delete;
  HighlighterControllerTest& operator=(const HighlighterControllerTest&) =
      delete;

  ~HighlighterControllerTest() override = default;

  void SetUp() override {
    AssistantAshTestBase::SetUp();
    controller_ = Shell::Get()->highlighter_controller();
    controller_test_api_ =
        std::make_unique<HighlighterControllerTestApi>(controller_);

    palette_tool_delegate_ = std::make_unique<MockPaletteToolDelegate>();
    tool_ = std::make_unique<MetalayerMode>(palette_tool_delegate_.get());
  }

  void TearDown() override {
    tool_.reset();
    // This needs to be called first to reset the controller state before the
    // shell instance gets torn down.
    controller_test_api_.reset();
    AssistantAshTestBase::TearDown();
  }

  void UpdateDisplayAndWaitForCompositingEnded(
      const std::string& display_specs) {
    UpdateDisplay(display_specs);
    ui::DrawWaiterForTest::WaitForCompositingEnded(
        Shell::GetPrimaryRootWindow()->GetHost()->compositor());
  }

 protected:
  void TraceRect(const gfx::Rect& rect) {
    ui::test::EventGenerator* event_generator = GetEventGenerator();
    event_generator->MoveTouch(gfx::Point(rect.x(), rect.y()));
    event_generator->PressTouch();
    event_generator->MoveTouch(gfx::Point(rect.right(), rect.y()));
    event_generator->MoveTouch(gfx::Point(rect.right(), rect.bottom()));
    event_generator->MoveTouch(gfx::Point(rect.x(), rect.bottom()));
    event_generator->MoveTouch(gfx::Point(rect.x(), rect.y()));
    event_generator->ReleaseTouch();

    // The the events above will trigger a frame, so wait until a new
    // CompositorFrame is generated before terminating.
    ui::DrawWaiterForTest::WaitForCompositingEnded(
        Shell::GetPrimaryRootWindow()->GetHost()->compositor());
  }

  std::unique_ptr<HighlighterControllerTestApi> controller_test_api_;
  std::unique_ptr<MockPaletteToolDelegate> palette_tool_delegate_;
  std::unique_ptr<PaletteTool> tool_;

  HighlighterController* controller_ = nullptr;  // Not owned.
};

}  // namespace

// Test to ensure the class responsible for drawing the highlighter pointer
// receives points from stylus movements as expected.
TEST_F(HighlighterControllerTest, HighlighterRenderer) {
  ash::stylus_utils::SetHasStylusInputForTesting();

  // The highlighter pointer mode only works with stylus.
  ui::test::EventGenerator* event_generator = GetEventGenerator();
  event_generator->EnterPenPointerMode();

  // When disabled the highlighter pointer should not be showing.
  event_generator->MoveTouch(gfx::Point(1, 1));
  EXPECT_FALSE(controller_test_api_->IsShowingHighlighter());

  // Verify that by enabling the mode, the highlighter pointer should still not
  // be showing.
  controller_test_api_->SetEnabled(true);
  EXPECT_FALSE(controller_test_api_->IsShowingHighlighter());

  // Verify moving the stylus 4 times will not display the highlighter pointer.
  event_generator->MoveTouch(gfx::Point(2, 2));
  event_generator->MoveTouch(gfx::Point(3, 3));
  event_generator->MoveTouch(gfx::Point(4, 4));
  event_generator->MoveTouch(gfx::Point(5, 5));
  EXPECT_FALSE(controller_test_api_->IsShowingHighlighter());

  // Verify pressing the stylus will show the highlighter pointer and add a
  // point but will not activate fading out.
  event_generator->PressTouch();
  EXPECT_TRUE(controller_test_api_->IsShowingHighlighter());
  EXPECT_FALSE(controller_test_api_->IsFadingAway());
  EXPECT_EQ(1, controller_test_api_->points().GetNumberOfPoints());

  // Verify dragging the stylus 2 times will add 2 more points.
  event_generator->MoveTouch(gfx::Point(6, 6));
  event_generator->MoveTouch(gfx::Point(7, 7));
  EXPECT_EQ(3, controller_test_api_->points().GetNumberOfPoints());

  // Verify releasing the stylus still shows the highlighter pointer, which is
  // fading away.
  event_generator->ReleaseTouch();
  EXPECT_TRUE(controller_test_api_->IsShowingHighlighter());
  EXPECT_TRUE(controller_test_api_->IsFadingAway());

  // Verify that disabling the mode right after the gesture completion does not
  // hide the highlighter pointer immediately but lets it play out the
  // animation.
  controller_test_api_->SetEnabled(false);
  EXPECT_TRUE(controller_test_api_->IsShowingHighlighter());
  EXPECT_TRUE(controller_test_api_->IsFadingAway());

  // Verify that disabling the mode mid-gesture hides the highlighter pointer
  // immediately.
  controller_test_api_->DestroyPointerView();
  controller_test_api_->SetEnabled(true);
  event_generator->PressTouch();
  event_generator->MoveTouch(gfx::Point(6, 6));
  EXPECT_TRUE(controller_test_api_->IsShowingHighlighter());
  controller_test_api_->SetEnabled(false);
  EXPECT_FALSE(controller_test_api_->IsShowingHighlighter());

  // Verify that the highlighter pointer does not add points while disabled.
  event_generator->PressTouch();
  event_generator->MoveTouch(gfx::Point(8, 8));
  event_generator->ReleaseTouch();
  event_generator->MoveTouch(gfx::Point(9, 9));
  EXPECT_FALSE(controller_test_api_->IsShowingHighlighter());

  // Verify that the highlighter pointer does not get shown if points are not
  // coming from the stylus, even when enabled.
  event_generator->ExitPenPointerMode();
  controller_test_api_->SetEnabled(true);
  event_generator->PressTouch();
  event_generator->MoveTouch(gfx::Point(10, 10));
  event_generator->MoveTouch(gfx::Point(11, 11));
  EXPECT_FALSE(controller_test_api_->IsShowingHighlighter());
  event_generator->ReleaseTouch();
}

// Test to ensure the class responsible for drawing the highlighter pointer
// handles prediction as expected when it receives points from stylus movements.
TEST_F(HighlighterControllerTest, HighlighterPrediction) {
  controller_test_api_->SetEnabled(true);
  // The highlighter pointer mode only works with stylus.
  ui::test::EventGenerator* event_generator = GetEventGenerator();
  event_generator->EnterPenPointerMode();
  event_generator->PressTouch();
  EXPECT_TRUE(controller_test_api_->IsShowingHighlighter());

  EXPECT_EQ(1, controller_test_api_->points().GetNumberOfPoints());
  // Initial press event shouldn't generate any predicted points as there's no
  // history to use for prediction.
  EXPECT_EQ(0, controller_test_api_->predicted_points().GetNumberOfPoints());

  // Verify dragging the stylus 3 times will add some predicted points.
  event_generator->MoveTouch(gfx::Point(10, 10));
  event_generator->MoveTouch(gfx::Point(20, 20));
  event_generator->MoveTouch(gfx::Point(30, 30));
  EXPECT_NE(0, controller_test_api_->predicted_points().GetNumberOfPoints());
  // Verify predicted points are in the right direction.
  for (const auto& point : controller_test_api_->predicted_points().points()) {
    EXPECT_LT(30, point.location.x());
    EXPECT_LT(30, point.location.y());
  }
}

// Test that stylus gestures are correctly recognized by HighlighterController.
TEST_F(HighlighterControllerTest, HighlighterGestures) {
  controller_test_api_->SetEnabled(true);
  ui::test::EventGenerator* event_generator = GetEventGenerator();
  event_generator->EnterPenPointerMode();

  TestHighlighterObserver observer;
  controller_->AddObserver(&observer);

  // A non-horizontal stroke is not recognized
  controller_test_api_->ResetSelection();
  event_generator->MoveTouch(gfx::Point(100, 100));
  event_generator->PressTouch();
  event_generator->MoveTouch(gfx::Point(200, 200));
  event_generator->ReleaseTouch();
  EXPECT_FALSE(controller_test_api_->HandleSelectionCalled());

  // An almost horizontal stroke is recognized
  controller_test_api_->ResetSelection();
  event_generator->MoveTouch(gfx::Point(100, 100));
  event_generator->PressTouch();
  event_generator->MoveTouch(gfx::Point(300, 102));
  event_generator->ReleaseTouch();
  EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());

  // Horizontal stroke selection rectangle should:
  //   have the same horizontal center line as the stroke bounding box,
  //   be 4dp wider than the stroke bounding box,
  //   be exactly 14dp high.
  gfx::Rect expected_rect(98, 94, 204, 14);
  EXPECT_EQ(expected_rect, controller_test_api_->selection());
  EXPECT_EQ(expected_rect, observer.last_recognized_rect_);

  // An insufficiently closed C-like shape is not recognized
  controller_test_api_->ResetSelection();
  event_generator->MoveTouch(gfx::Point(100, 0));
  event_generator->PressTouch();
  event_generator->MoveTouch(gfx::Point(0, 0));
  event_generator->MoveTouch(gfx::Point(0, 100));
  event_generator->MoveTouch(gfx::Point(100, 100));
  event_generator->ReleaseTouch();
  EXPECT_FALSE(controller_test_api_->HandleSelectionCalled());

  // An almost closed G-like shape is recognized
  controller_test_api_->ResetSelection();
  event_generator->MoveTouch(gfx::Point(200, 0));
  event_generator->PressTouch();
  event_generator->MoveTouch(gfx::Point(0, 0));
  event_generator->MoveTouch(gfx::Point(0, 100));
  event_generator->MoveTouch(gfx::Point(200, 100));
  event_generator->MoveTouch(gfx::Point(200, 20));
  event_generator->ReleaseTouch();
  EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
  expected_rect = gfx::Rect(0, 0, 200, 100);
  EXPECT_EQ(expected_rect, controller_test_api_->selection());
  EXPECT_EQ(expected_rect, observer.last_recognized_rect_);

  // A closed diamond shape is recognized
  controller_test_api_->ResetSelection();
  event_generator->MoveTouch(gfx::Point(100, 50));
  event_generator->PressTouch();
  event_generator->MoveTouch(gfx::Point(200, 150));
  event_generator->MoveTouch(gfx::Point(100, 250));
  event_generator->MoveTouch(gfx::Point(0, 150));
  event_generator->MoveTouch(gfx::Point(100, 50));
  event_generator->ReleaseTouch();
  EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
  expected_rect = gfx::Rect(0, 50, 200, 200);
  EXPECT_EQ(expected_rect, controller_test_api_->selection());
  EXPECT_EQ(expected_rect, observer.last_recognized_rect_);

  controller_->RemoveObserver(&observer);
}

TEST_F(HighlighterControllerTest, HighlighterGesturesScaled) {
  controller_test_api_->SetEnabled(true);
  ui::test::EventGenerator* event_generator = GetEventGenerator();
  event_generator->EnterPenPointerMode();

  const gfx::Rect original_px(200, 100, 400, 300);

  constexpr float display_scales[] = {1.f, 1.5f, 2.0f};
  constexpr float ui_scales[] = {0.5f,  0.67f, 1.0f,  1.25f,
                                 1.33f, 1.5f,  1.67f, 2.0f};

  for (size_t i = 0; i < sizeof(display_scales) / sizeof(float); ++i) {
    const float display_scale = display_scales[i];
    for (size_t j = 0; j < sizeof(ui_scales) / sizeof(float); ++j) {
      const float ui_scale = ui_scales[j];

      std::string display_spec =
          base::StringPrintf("1500x1000*%.2f@%.2f", display_scale, ui_scale);
      SCOPED_TRACE(display_spec);
      UpdateDisplayAndWaitForCompositingEnded(display_spec);

      controller_test_api_->ResetSelection();
      TraceRect(original_px);
      EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());

      const float combined_scale = display_scale * ui_scale;

      const gfx::Rect selection_dp = controller_test_api_->selection();
      const gfx::Rect selection_px = gfx::ToEnclosingRect(
          gfx::ScaleRect(gfx::RectF(selection_dp), combined_scale));
      EXPECT_TRUE(selection_px.Contains(original_px));

      gfx::Rect inflated_px(original_px);
      // Allow for rounding errors within 1dp.
      const int error_margin = static_cast<int>(std::ceil(combined_scale));
      inflated_px.Inset(-error_margin, -error_margin);
      EXPECT_TRUE(inflated_px.Contains(selection_px));
    }
  }
}

// Test that stylus gesture recognition correctly handles display rotation
TEST_F(HighlighterControllerTest, HighlighterGesturesRotated) {
  controller_test_api_->SetEnabled(true);
  ui::test::EventGenerator* event_generator = GetEventGenerator();
  event_generator->EnterPenPointerMode();

  const gfx::Rect trace(200, 100, 400, 300);

  // No rotation
  UpdateDisplayAndWaitForCompositingEnded("1500x1000");
  controller_test_api_->ResetSelection();
  TraceRect(trace);
  EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
  EXPECT_EQ("200,100 400x300", controller_test_api_->selection().ToString());

  // Rotate to 90 degrees
  UpdateDisplayAndWaitForCompositingEnded("1500x1000/r");
  controller_test_api_->ResetSelection();
  TraceRect(trace);
  EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
  EXPECT_EQ("100,900 300x400", controller_test_api_->selection().ToString());

  // Rotate to 180 degrees
  UpdateDisplayAndWaitForCompositingEnded("1500x1000/u");
  controller_test_api_->ResetSelection();
  TraceRect(trace);
  EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
  EXPECT_EQ("900,600 400x300", controller_test_api_->selection().ToString());

  // Rotate to 270 degrees
  UpdateDisplayAndWaitForCompositingEnded("1500x1000/l");
  controller_test_api_->ResetSelection();
  TraceRect(trace);
  EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
  EXPECT_EQ("600,200 300x400", controller_test_api_->selection().ToString());
}

// Test that a stroke interrupted close to the screen edge is treated as
// contiguous.
TEST_F(HighlighterControllerTest, InterruptedStroke) {
  controller_test_api_->SetEnabled(true);
  ui::test::EventGenerator* event_generator = GetEventGenerator();
  event_generator->EnterPenPointerMode();

  UpdateDisplayAndWaitForCompositingEnded("1500x1000");

  // An interrupted stroke close to the screen edge should be recognized as a
  // contiguous stroke.
  controller_test_api_->ResetSelection();
  event_generator->MoveTouch(gfx::Point(300, 100));
  event_generator->PressTouch();
  event_generator->MoveTouch(gfx::Point(0, 100));
  event_generator->ReleaseTouch();
  EXPECT_TRUE(controller_test_api_->IsWaitingToResumeStroke());
  EXPECT_FALSE(controller_test_api_->HandleSelectionCalled());
  EXPECT_FALSE(controller_test_api_->IsFadingAway());

  event_generator->MoveTouch(gfx::Point(0, 200));
  event_generator->PressTouch();
  event_generator->MoveTouch(gfx::Point(300, 200));
  event_generator->ReleaseTouch();
  EXPECT_FALSE(controller_test_api_->IsWaitingToResumeStroke());
  EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
  EXPECT_EQ("0,100 300x100", controller_test_api_->selection().ToString());

  // Repeat the same gesture, but simulate a timeout after the gap. This should
  // force the gesture completion.
  controller_test_api_->ResetSelection();
  event_generator->MoveTouch(gfx::Point(300, 100));
  event_generator->PressTouch();
  event_generator->MoveTouch(gfx::Point(0, 100));
  event_generator->ReleaseTouch();
  EXPECT_TRUE(controller_test_api_->IsWaitingToResumeStroke());
  EXPECT_FALSE(controller_test_api_->HandleSelectionCalled());
  EXPECT_FALSE(controller_test_api_->IsFadingAway());

  controller_test_api_->SimulateInterruptedStrokeTimeout();
  EXPECT_FALSE(controller_test_api_->IsWaitingToResumeStroke());
  EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
  EXPECT_TRUE(controller_test_api_->IsFadingAway());
}

// Test that the selection is never crossing the screen bounds.
TEST_F(HighlighterControllerTest, SelectionInsideScreen) {
  controller_test_api_->SetEnabled(true);
  ui::test::EventGenerator* event_generator = GetEventGenerator();
  event_generator->EnterPenPointerMode();

  constexpr float display_scales[] = {1.f, 1.5f, 2.0f};

  for (size_t i = 0; i < sizeof(display_scales) / sizeof(float); ++i) {
    // 2nd display is for offscreen test.
    std::string display_spec = base::StringPrintf(
        "1000x999*%.2f,500x1000*%.2f", display_scales[i], display_scales[i]);
    SCOPED_TRACE(display_spec);
    UpdateDisplayAndWaitForCompositingEnded(display_spec);

    const gfx::Rect screen(0, 0, 1000, 999);

    // Rectangle completely offscreen.
    controller_test_api_->ResetSelection();
    TraceRect(gfx::Rect(-100, -100, 10, 10));
    controller_test_api_->SimulateInterruptedStrokeTimeout();
    EXPECT_FALSE(controller_test_api_->HandleSelectionCalled());

    // Rectangle crossing the left edge.
    controller_test_api_->ResetSelection();
    TraceRect(gfx::Rect(-100, 100, 200, 200));
    controller_test_api_->SimulateInterruptedStrokeTimeout();
    EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));

    // Rectangle crossing the top edge.
    controller_test_api_->ResetSelection();
    TraceRect(gfx::Rect(100, -100, 200, 200));
    controller_test_api_->SimulateInterruptedStrokeTimeout();
    EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));

    // Rectangle crossing the right edge.
    controller_test_api_->ResetSelection();
    TraceRect(gfx::Rect(900, 100, 200, 200));
    controller_test_api_->SimulateInterruptedStrokeTimeout();
    EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));

    // Rectangle crossing the bottom edge.
    controller_test_api_->ResetSelection();
    TraceRect(gfx::Rect(100, 900, 200, 200));
    controller_test_api_->SimulateInterruptedStrokeTimeout();
    EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));

    // Vertical stroke completely offscreen.
    controller_test_api_->ResetSelection();
    event_generator->MoveTouch(gfx::Point(1100, 100));
    event_generator->PressTouch();
    event_generator->MoveTouch(gfx::Point(1100, 500));
    event_generator->ReleaseTouch();
    controller_test_api_->SimulateInterruptedStrokeTimeout();
    EXPECT_FALSE(controller_test_api_->HandleSelectionCalled());

    // Horizontal stroke along the top edge of the screen.
    controller_test_api_->ResetSelection();
    event_generator->MoveTouch(gfx::Point(0, 0));
    event_generator->PressTouch();
    event_generator->MoveTouch(gfx::Point(1000, 0));
    event_generator->ReleaseTouch();
    controller_test_api_->SimulateInterruptedStrokeTimeout();
    EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));

    // Horizontal stroke along the bottom edge of the screen.
    controller_test_api_->ResetSelection();
    event_generator->MoveTouch(gfx::Point(0, 999));
    event_generator->PressTouch();
    event_generator->MoveTouch(gfx::Point(1000, 999));
    event_generator->ReleaseTouch();
    controller_test_api_->SimulateInterruptedStrokeTimeout();
    EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
    EXPECT_TRUE(screen.Contains(controller_test_api_->selection()));
  }
}

// Test that a detached client does not receive notifications.
TEST_F(HighlighterControllerTest, DetachedClient) {
  controller_test_api_->SetEnabled(true);
  ui::test::EventGenerator* event_generator = GetEventGenerator();
  event_generator->EnterPenPointerMode();

  UpdateDisplayAndWaitForCompositingEnded("1500x1000");
  const gfx::Rect trace(200, 100, 400, 300);

  // Detach the client, no notifications should reach it.
  controller_test_api_->DetachClient();

  controller_test_api_->ResetEnabledState();
  controller_test_api_->SetEnabled(false);
  EXPECT_FALSE(controller_test_api_->HandleEnabledStateChangedCalled());
  controller_test_api_->SetEnabled(true);
  EXPECT_FALSE(controller_test_api_->HandleEnabledStateChangedCalled());

  controller_test_api_->ResetSelection();
  TraceRect(trace);
  EXPECT_FALSE(controller_test_api_->HandleSelectionCalled());

  // Attach the client again, notifications should be delivered normally.
  controller_test_api_->AttachClient();

  controller_test_api_->ResetEnabledState();
  controller_test_api_->SetEnabled(false);
  EXPECT_TRUE(controller_test_api_->HandleEnabledStateChangedCalled());
  controller_test_api_->SetEnabled(true);
  EXPECT_TRUE(controller_test_api_->HandleEnabledStateChangedCalled());

  controller_test_api_->ResetSelection();
  TraceRect(trace);
  EXPECT_TRUE(controller_test_api_->HandleSelectionCalled());
}

// Test enabling/disabling metalayer mode by selecting/deselecting on palette
// tool and calling UpdateEnabledState notify observers properly.
TEST_F(HighlighterControllerTest, UpdateEnabledState) {
  TestHighlighterObserver observer;
  controller_->AddObserver(&observer);

  // Assert initial state.
  ASSERT_EQ(0, observer.enabled_count_);
  ASSERT_EQ(0, observer.disabled_by_user_count_);
  ASSERT_EQ(0, observer.disabled_by_session_abort_);
  ASSERT_EQ(0, observer.disabled_by_session_complete_);

  // Test enabling.
  tool_->OnEnable();
  EXPECT_EQ(1, observer.enabled_count_);
  EXPECT_EQ(0, observer.disabled_by_user_count_);
  EXPECT_EQ(0, observer.disabled_by_session_abort_);
  EXPECT_EQ(0, observer.disabled_by_session_complete_);

  // Test disabling by user.
  tool_->OnDisable();
  EXPECT_EQ(1, observer.enabled_count_);
  EXPECT_EQ(1, observer.disabled_by_user_count_);
  EXPECT_EQ(0, observer.disabled_by_session_abort_);
  EXPECT_EQ(0, observer.disabled_by_session_complete_);

  // Test disabling by session abort.
  tool_->OnEnable();
  EXPECT_EQ(2, observer.enabled_count_);
  EXPECT_EQ(1, observer.disabled_by_user_count_);
  EXPECT_EQ(0, observer.disabled_by_session_abort_);
  EXPECT_EQ(0, observer.disabled_by_session_complete_);
  controller_->UpdateEnabledState(
      HighlighterEnabledState::kDisabledBySessionAbort);
  EXPECT_EQ(2, observer.enabled_count_);
  EXPECT_EQ(1, observer.disabled_by_user_count_);
  EXPECT_EQ(1, observer.disabled_by_session_abort_);
  EXPECT_EQ(0, observer.disabled_by_session_complete_);

  // Test disabling by session complete.
  tool_->OnEnable();
  EXPECT_EQ(3, observer.enabled_count_);
  EXPECT_EQ(1, observer.disabled_by_user_count_);
  EXPECT_EQ(1, observer.disabled_by_session_abort_);
  EXPECT_EQ(0, observer.disabled_by_session_complete_);
  controller_->UpdateEnabledState(
      HighlighterEnabledState::kDisabledBySessionComplete);
  EXPECT_EQ(3, observer.enabled_count_);
  EXPECT_EQ(1, observer.disabled_by_user_count_);
  EXPECT_EQ(1, observer.disabled_by_session_abort_);
  EXPECT_EQ(1, observer.disabled_by_session_complete_);

  controller_->RemoveObserver(&observer);
}

// Test aborting a metalayer session and notifying observers properly.
TEST_F(HighlighterControllerTest, AbortSession) {
  TestHighlighterObserver observer;
  controller_->AddObserver(&observer);

  // Assert initial state.
  ASSERT_EQ(0, observer.enabled_count_);
  ASSERT_EQ(0, observer.disabled_by_user_count_);
  ASSERT_EQ(0, observer.disabled_by_session_abort_);
  ASSERT_EQ(0, observer.disabled_by_session_complete_);

  // Start metalayer session.
  tool_->OnEnable();
  EXPECT_EQ(1, observer.enabled_count_);
  EXPECT_EQ(0, observer.disabled_by_user_count_);
  EXPECT_EQ(0, observer.disabled_by_session_abort_);
  EXPECT_EQ(0, observer.disabled_by_session_complete_);

  // Abort metalayer session.
  controller_->AbortSession();
  EXPECT_EQ(1, observer.enabled_count_);
  EXPECT_EQ(0, observer.disabled_by_user_count_);
  EXPECT_EQ(1, observer.disabled_by_session_abort_);
  EXPECT_EQ(0, observer.disabled_by_session_complete_);

  // Assert no-op when aborting an aborted session.
  controller_->AbortSession();
  EXPECT_EQ(1, observer.enabled_count_);
  EXPECT_EQ(0, observer.disabled_by_user_count_);
  EXPECT_EQ(1, observer.disabled_by_session_abort_);
  EXPECT_EQ(0, observer.disabled_by_session_complete_);

  // Assert no-op when aborting a completed session.
  tool_->OnEnable();
  EXPECT_EQ(2, observer.enabled_count_);
  EXPECT_EQ(0, observer.disabled_by_user_count_);
  EXPECT_EQ(1, observer.disabled_by_session_abort_);
  EXPECT_EQ(0, observer.disabled_by_session_complete_);
  controller_->UpdateEnabledState(
      HighlighterEnabledState::kDisabledBySessionComplete);
  EXPECT_EQ(2, observer.enabled_count_);
  EXPECT_EQ(0, observer.disabled_by_user_count_);
  EXPECT_EQ(1, observer.disabled_by_session_abort_);
  EXPECT_EQ(1, observer.disabled_by_session_complete_);
  controller_->AbortSession();
  EXPECT_EQ(2, observer.enabled_count_);
  EXPECT_EQ(0, observer.disabled_by_user_count_);
  EXPECT_EQ(1, observer.disabled_by_session_abort_);
  EXPECT_EQ(1, observer.disabled_by_session_complete_);

  // Assert no-op when aborting a disabled session.
  tool_->OnEnable();
  EXPECT_EQ(3, observer.enabled_count_);
  EXPECT_EQ(0, observer.disabled_by_user_count_);
  EXPECT_EQ(1, observer.disabled_by_session_abort_);
  EXPECT_EQ(1, observer.disabled_by_session_complete_);
  tool_->OnDisable();
  EXPECT_EQ(3, observer.enabled_count_);
  EXPECT_EQ(1, observer.disabled_by_user_count_);
  EXPECT_EQ(1, observer.disabled_by_session_abort_);
  EXPECT_EQ(1, observer.disabled_by_session_complete_);
  controller_->AbortSession();
  EXPECT_EQ(3, observer.enabled_count_);
  EXPECT_EQ(1, observer.disabled_by_user_count_);
  EXPECT_EQ(1, observer.disabled_by_session_abort_);
  EXPECT_EQ(1, observer.disabled_by_session_complete_);
}

}  // namespace ash


text:
using LinearAlgebra

mutable struct TridiagonalOperator
  diagonal::Vector{Float64}
  lowerDiagonal::Vector{Float64}
  upperDiagonal::Vector{Float64}
  temp::Vector{Float64}
  n::Int
end

TridiagonalOperator(n::Int) = TridiagonalOperator(zeros(n), zeros(n - 1), zeros(n - 1), zeros(n), n)
TridiagonalOperator() = TridiagonalOperator(Vector{Float64}(), Vector{Float64}(), Vector{Float64}(), Vector{Float64}(), 0)
TridiagIdentity(n::Int) = TridiagonalOperator(ones(n), zeros(n - 1), zeros(n - 1), zeros(n), n)

function set_first_row!(L::TridiagonalOperator, valB::Float64, valC::Float64)
  L.diagonal[1] = valB
  L.upperDiagonal[1] = valC

  return L
end

function set_mid_row!(L::TridiagonalOperator, i::Int, valA::Float64, valB::Float64, valC::Float64)
  i >= 2 && i <= L.n - 1 || error("out of range for Tridiagonal System: set mid row")

  L.lowerDiagonal[i - 1] = valA
  L.diagonal[i] = valB
  L.upperDiagonal[i] = valC

  return L
end

function set_last_row!(L::TridiagonalOperator, valA::Float64, valB::Float64)
  L.lowerDiagonal[L.n - 1] = valA
  L.diagonal[L.n] = valB

  return L
end

function solve_for(L::TridiagonalOperator, rhs::Vector{Float64})
  # create tridiagonal
  tri = Tridiagonal(L.lowerDiagonal, L.diagonal, L.upperDiagonal)

  # lu factorization
  Alu = lu(tri)

  return Alu \ rhs
end

function solve_for!(L::TridiagonalOperator, rhs::Vector{Float64}, result::Vector{Float64})
  bet = L.diagonal[1]
  result[1] = rhs[1] / bet

  @inbounds @simd for j = 2:L.n
    L.temp[j] = L.upperDiagonal[j - 1] / bet
    bet = L.diagonal[j] - L.lowerDiagonal[j - 1] * L.temp[j]
    result[j] = (rhs[j] - L.lowerDiagonal[j - 1] * result[j - 1]) / bet
  end

  @inbounds @simd for j = L.n-1:-1:2
    result[j] -= (L.temp[j + 1] * result[j + 1])
    # println(result[j])
  end
  # println(result)
  # error("DIE")
  result[1] -= L.temp[2] * result[2]
  return L, result
end

function apply_to(L::TridiagonalOperator, v::Vector{Float64})
  L.n == length(v) || error("v of incorrect length")

  res = L.diagonal .* v

  res[1] = L.upperDiagonal[1] * v[2]
  @simd for j = 2:L.n - 1
    @inbounds res[j] += L.lowerDiagonal[j-1] * v[j-1] + L.upperDiagonal[j] * v[j+1]
  end

  res[end] += L.lowerDiagonal[end-1] * v[end-1]

  return res
end

# basic operators
import Base.+, Base.-, Base.*, Base./, Base.copy

function -(D::TridiagonalOperator)
  low = -D.lowerDiagonal
  mid = -D.diagonal
  high = -D.upperDiagonal

  return TridiagonalOperator(mid, low, high, D.temp, D.n)
end

function +(D1::TridiagonalOperator, D2::TridiagonalOperator)
  D1.n == D2.n || error("Dimension mismatch")
  low = D1.lowerDiagonal + D2.lowerDiagonal
  mid = D1.diagonal + D2.diagonal
  high = D1.upperDiagonal + D2.upperDiagonal

  return TridiagonalOperator(mid, low, high, D1.temp, D1.n)
end

function -(D1::TridiagonalOperator, D2::TridiagonalOperator)
  D1.n == D2.n || error("Dimension mismatch")
  low = D1.lowerDiagonal - D2.lowerDiagonal
  mid = D1.diagonal - D2.diagonal
  high = D1.upperDiagonal - D2.upperDiagonal

  return TridiagonalOperator(mid, low, high, D1.temp, D1.n)
end

function *(a::Number, D::TridiagonalOperator)
  low = D.lowerDiagonal * a
  mid = D.diagonal * a
  high = D.upperDiagonal * a

  return TridiagonalOperator(mid, low, high, D.temp, D.n)
end

function *(D::TridiagonalOperator, a::Number)
  low = D.lowerDiagonal * a
  mid = D.diagonal * a
  high = D.upperDiagonal * a

  return TridiagonalOperator(mid, low, high, D.temp, D.n)
end

function /(D::TridiagonalOperator, a::Number)
  low = D.lowerDiagonal / a
  mid = D.diagonal / a
  high = D.upperDiagonal / a

  return TridiagonalOperator(mid, low, high, D.temp, D.n)
end

copy(L::TridiagonalOperator) = TridiagonalOperator(L.diagonal, L.lowerDiagonal, L.upperDiagonal, L.temp, L.n)