<commit_before>
$.extend($.easing,
{
    def: 'easeOutQuad',
    easeInOutExpo: function (x, t, b, c, d) {
        if (t==0) return b;
        if (t==d) return b+c;
        if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
        return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
    }
});

(function( $ ) {

    var settings;
    var disableScrollFn = false;
    var navItems;
    var navs = {}, sections = {};

    $.fn.navScroller = function(options) {
        settings = $.extend({
            scrollToOffset: 170,
            scrollSpeed: 800,
            activateParentNode: true,
        }, options );
        navItems = this;

        //attatch click listeners
    	navItems.on('click', function(event){
    		event.preventDefault();
            var navID = $(this).attr("href").substring(1);
            disableScrollFn = true;
            activateNav(navID);
            populateDestinations(); //recalculate these!
        	$('html,body').animate({scrollTop: sections[navID] - settings.scrollToOffset},
                settings.scrollSpeed, "easeInOutExpo", function(){
                    disableScrollFn = false;
                }
            );
    	});

        //populate lookup of clicable elements and destination sections
        populateDestinations(); //should also be run on browser resize, btw

        // setup scroll listener
        $(document).scroll(function(){
            if (disableScrollFn) { return; }
            var page_height = $(window).height();
            var pos = $(this).scrollTop();
            for (i in sections) {
                if ((pos + settings.scrollToOffset >= sections[i]) && sections[i] < pos + page_height){
                    activateNav(i);
                }
            }
        });
    };

    function populateDestinations() {
        navItems.each(function(){
            var scrollID = $(this).attr('href').substring(1);
            navs[scrollID] = (settings.activateParentNode)? this.parentNode : this;
            sections[scrollID] = $(document.getElementById(scrollID)).offset().top;
        });
    }

    function activateNav(navID) {
        for (nav in navs) { $(navs[nav]).removeClass('active'); }
        $(navs[navID]).addClass('active');
    }
})( jQuery );

$(document).ready(function (){

    $('nav li a').navScroller();

    //section divider icon click gently scrolls to reveal the section
	$(".sectiondivider").on('click', function(event) {
    	$('html,body').animate({scrollTop: $(event.target.parentNode).offset().top - 50}, 400, "linear");
	});

    //links going to other sections nicely scroll
	$(".container a").each(function(){
        if ($(this).attr("href").charAt(0) == '#'){
            $(this).on('click', function(event) {
        		event.preventDefault();
                var target = $(event.target).closest("a");
                var targetHight =  $(target.attr("href")).offset().top
            	$('html,body').animate({scrollTop: targetHight - 170}, 800, "easeInOutExpo");
            });
        }
	});

});

<commit_msg>Cambio al comportamiento de los anchors para que la ubicacion se refleje en la URL del browser y poder agregarla a bookmarks<commit_after>
$.extend($.easing,
{
    def: 'easeOutQuad',
    easeInOutExpo: function (x, t, b, c, d) {
        if (t==0) return b;
        if (t==d) return b+c;
        if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
        return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
    }
});

(function( $ ) {

    var settings;
    var disableScrollFn = false;
    var navItems;
    var navs = {}, sections = {};

    $.fn.navScroller = function(options) {
        settings = $.extend({
            scrollToOffset: 170,
            scrollSpeed: 800,
            activateParentNode: true,
        }, options );
        navItems = this;

        //attatch click listeners
    	navItems.on('click', function(event){
    		//event.preventDefault();
            var navID = $(this).attr("href").substring(1);
            disableScrollFn = true;
            activateNav(navID);
            populateDestinations(); //recalculate these!
        	$('html,body').animate({scrollTop: sections[navID] - settings.scrollToOffset},
                settings.scrollSpeed, "easeInOutExpo", function(){
                    disableScrollFn = false;
                }
            );

    	});

        //populate lookup of clicable elements and destination sections
        populateDestinations(); //should also be run on browser resize, btw

        // setup scroll listener
        $(document).scroll(function(){
            if (disableScrollFn) { return; }
            var page_height = $(window).height();
            var pos = $(this).scrollTop();
            for (i in sections) {
                if ((pos + settings.scrollToOffset >= sections[i]) && sections[i] < pos + page_height){
                    activateNav(i);
                }
            }
        });
    };

    function populateDestinations() {
        navItems.each(function(){
            var scrollID = $(this).attr('href').substring(1);
            navs[scrollID] = (settings.activateParentNode)? this.parentNode : this;
            sections[scrollID] = $(document.getElementById(scrollID)).offset().top;
        });
    }

    function activateNav(navID) {
        for (nav in navs) { $(navs[nav]).removeClass('active'); }
        $(navs[navID]).addClass('active');
    }
})( jQuery );

$(document).ready(function (){

    $('nav li a').navScroller();

    //section divider icon click gently scrolls to reveal the section
	$(".sectiondivider").on('click', function(event) {
    	$('html,body').animate({scrollTop: $(event.target.parentNode).offset().top - 50}, 400, "linear");
	});

    //links going to other sections nicely scroll
	$(".container a").each(function(){
        if ($(this).attr("href").charAt(0) == '#'){
            $(this).on('click', function(event) {
        		//event.preventDefault();
                var target = $(event.target).closest("a");
                var targetHight =  $(target.attr("href")).offset().top
            	$('html,body').animate({scrollTop: targetHight - 170}, 800, "easeInOutExpo");
            });
        }
	});

});

<|endoftext|>


<commit_before>var test = require("tape");
var _ = require( "lodash" );
var sinon = require("sinon");
var algoliaSearch = require( "algoliasearch" );

var Helper = require( "../../index" );

test( "Search should call the algolia client according to the number of refinements", function( t ){
  var testData = require( "./search.testData" );

  var client = algoliaSearch( "dsf", "dsfdf" );

  var mock = sinon.mock( client );
  mock.expects( "startQueriesBatch" ).once();
  mock.expects( "addQueryInBatch" ).exactly( 2 );
  mock.expects( "sendQueriesBatch" ).once().yields( null, testData.response );

  var helper = Helper( client, "test_hotels-node", {
    disjunctiveFacets : ["city"]
  });

  helper.addDisjunctiveRefine( "city", "Paris" );
  helper.addDisjunctiveRefine( "city", "New York" );

  helper.on( "result", function( data ) {
    t.ok( _.isEqual( data, testData.responseHelper ) , "should be equal" );
    t.ok( mock.verify(), "Mock constraints should be verified!" );
    t.end();
  } );

  helper.search( "" );
} );
<commit_msg>Update test with deepEqual tape api<commit_after>var test = require("tape");
var _ = require( "lodash" );
var sinon = require("sinon");
var algoliaSearch = require( "algoliasearch" );

var Helper = require( "../../index" );

test( "Search should call the algolia client according to the number of refinements", function( t ){
  var testData = require( "./search.testData" );

  var client = algoliaSearch( "dsf", "dsfdf" );

  var mock = sinon.mock( client );
  mock.expects( "startQueriesBatch" ).once();
  mock.expects( "addQueryInBatch" ).exactly( 2 );
  mock.expects( "sendQueriesBatch" ).once().yields( null, testData.response );

  var helper = Helper( client, "test_hotels-node", {
    disjunctiveFacets : ["city"]
  });

  helper.addDisjunctiveRefine( "city", "Paris" );
  helper.addDisjunctiveRefine( "city", "New York" );

  helper.on( "result", function( data ) {
    t.deepEqual( data, testData.responseHelper,  "should be equal" );
    t.ok( mock.verify(), "Mock constraints should be verified!" );
    t.end();
  } );

  helper.search( "" );
} );
<|endoftext|>


<commit_before>describe('scope', function(){
  var ripple = require('ripple');
  var assert = require('assert');
  var View = ripple('

');

  it('should get data from the parent scope', function(){
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    assert( child.get('foo') === 'bar' );
  })

  it('should watch for changes on the parent scope', function(done){
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(){
      done();
    })
    parent.set('foo', 'baz');
  })

  it('should watch for multiple changes on the parent scope', function(){
    var count = 0;
    var parent = new View();
    parent.set({
      'foo': 'bar',
      'raz': 'taz'
    });
    var child = new View({
      scope: parent
    });
    child.watch(['foo', 'raz'], function(){
      count++;
    })
    parent.set({
      'foo': 'baz',
      'raz': 'baz'
    });
    assert(count === 2);
  })

  it('should unwatch for changes on the parent scope', function () {
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(){
      assert(false, 'it should be remove this callback');
    })
    child.unwatch('foo');
    parent.set('foo', 'baz');
    assert(child.scopeWatchers.foo.length === 0);
  });

  it('should unwatch for multiple changes on the parent scope', function () {
    var count = 0;
    var parent = new View();
    parent.set({
      'foo': 'bar',
      'raz': 'taz'
    });
    var child = new View({
      scope: parent
    });
    child.watch(['foo', 'raz'], function(){
      count++;
    });
    child.unwatch(['foo', 'raz']);
    parent.set({
      'foo': 'baz',
      'raz': 'baz'
    });
    assert(count === 0);
  });

  it('should unwatch some changes on the parent scope', function () {
    var count = 0;
    var parent = new View();
    parent.set({
      'foo': 'bar',
      'raz': 'taz'
    });
    var child = new View({
      scope: parent
    });
    child.watch(['foo', 'raz'], function(){
      count++;
    });
    child.unwatch('foo');
    parent.set({
      'foo': 'baz',
      'raz': 'baz'
    });
    assert(count === 1);
  });

  it('should unwatch for changes on the parent scope if the child sets the value', function () {
    var count = 0;
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(value){
      assert(value === 'raz');
      count++;
    })
    child.set('foo', 'raz');
    parent.set('foo', 'baz');
    assert(count === 1);
  });

  it('should unwatch for changes on the parent scope if the child sets the value as an object', function () {
    var count = 0;
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(value){
      assert(value === 'raz');
      count++;
    })
    child.set({ 'foo': 'raz' });
    parent.set('foo', 'baz');
    assert(count === 1);
  });

  it('should unwatch for changes on the parent scope but still keep parent listeners', function (done) {
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    parent.watch('foo', function(){
      done();
    });
    child.set('foo', 'raz');
    parent.set('foo', 'baz');
  });

  it('should remove all the scope watchers when the child gets the value', function () {
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(){});
    child.set('foo', 'raz');
    assert(child.scopeWatchers['foo'] === undefined);
  });

  it('should remove all scope listeners when destroyed', function () {
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(){
      assert(false, 'this should be unbound');
    });
    child.destroy();
    parent.set('foo', 'baz');
  });

  it.only('should interpolate with properties from the parent scope', function () {
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    assert( child.interpolate('{{foo}}') === 'bar' );
  });

})<commit_msg>Remove .only<commit_after>describe('scope', function(){
  var ripple = require('ripple');
  var assert = require('assert');
  var View = ripple('

');

  it('should get data from the parent scope', function(){
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    assert( child.get('foo') === 'bar' );
  })

  it('should watch for changes on the parent scope', function(done){
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(){
      done();
    })
    parent.set('foo', 'baz');
  })

  it('should watch for multiple changes on the parent scope', function(){
    var count = 0;
    var parent = new View();
    parent.set({
      'foo': 'bar',
      'raz': 'taz'
    });
    var child = new View({
      scope: parent
    });
    child.watch(['foo', 'raz'], function(){
      count++;
    })
    parent.set({
      'foo': 'baz',
      'raz': 'baz'
    });
    assert(count === 2);
  })

  it('should unwatch for changes on the parent scope', function () {
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(){
      assert(false, 'it should be remove this callback');
    })
    child.unwatch('foo');
    parent.set('foo', 'baz');
    assert(child.scopeWatchers.foo.length === 0);
  });

  it('should unwatch for multiple changes on the parent scope', function () {
    var count = 0;
    var parent = new View();
    parent.set({
      'foo': 'bar',
      'raz': 'taz'
    });
    var child = new View({
      scope: parent
    });
    child.watch(['foo', 'raz'], function(){
      count++;
    });
    child.unwatch(['foo', 'raz']);
    parent.set({
      'foo': 'baz',
      'raz': 'baz'
    });
    assert(count === 0);
  });

  it('should unwatch some changes on the parent scope', function () {
    var count = 0;
    var parent = new View();
    parent.set({
      'foo': 'bar',
      'raz': 'taz'
    });
    var child = new View({
      scope: parent
    });
    child.watch(['foo', 'raz'], function(){
      count++;
    });
    child.unwatch('foo');
    parent.set({
      'foo': 'baz',
      'raz': 'baz'
    });
    assert(count === 1);
  });

  it('should unwatch for changes on the parent scope if the child sets the value', function () {
    var count = 0;
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(value){
      assert(value === 'raz');
      count++;
    })
    child.set('foo', 'raz');
    parent.set('foo', 'baz');
    assert(count === 1);
  });

  it('should unwatch for changes on the parent scope if the child sets the value as an object', function () {
    var count = 0;
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(value){
      assert(value === 'raz');
      count++;
    })
    child.set({ 'foo': 'raz' });
    parent.set('foo', 'baz');
    assert(count === 1);
  });

  it('should unwatch for changes on the parent scope but still keep parent listeners', function (done) {
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    parent.watch('foo', function(){
      done();
    });
    child.set('foo', 'raz');
    parent.set('foo', 'baz');
  });

  it('should remove all the scope watchers when the child gets the value', function () {
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(){});
    child.set('foo', 'raz');
    assert(child.scopeWatchers['foo'] === undefined);
  });

  it('should remove all scope listeners when destroyed', function () {
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    child.watch('foo', function(){
      assert(false, 'this should be unbound');
    });
    child.destroy();
    parent.set('foo', 'baz');
  });

  it('should interpolate with properties from the parent scope', function () {
    var parent = new View();
    parent.set('foo', 'bar');
    var child = new View({
      scope: parent
    });
    assert( child.interpolate('{{foo}}') === 'bar' );
  });

})<|endoftext|>


<commit_before>var _req = require("./req.js");
var querystring = require("querystring");

module.exports = function() {

    return {

        buy: function(data, cb) {

            if (arguments.length === 2) {

                _req("GET", "/prices/buy?" + querystring.stringify(data), cb);

            } else {

                var cb = data;

                _req("GET", "/prices/buy", cb);

            }

        },

        sell: function(data, cb) {

            if (arguments.length === 2) {

                _req("GET", "/prices/sell?" + querystring.stringify(data), cb);

            } else {

                var cb = data;

                _req("GET", "/prices/sell", cb);

            }

        },

        spot_rate: function(data, cb) {

            if (arguments.length === 2) {

                _req("GET", "/prices/spot_rate?" + querystring.stringify(data), cb);

            } else {

                var cb = data;

                _req("GET", "/prices/spot_rate", cb);

            }

        }

    };

};

<commit_msg>Renamed spot_rate to spotRate<commit_after>var _req = require("./req.js");
var querystring = require("querystring");

module.exports = function() {

    return {

        buy: function(data, cb) {

            if (arguments.length === 2) {

                _req("GET", "/prices/buy?" + querystring.stringify(data), cb);

            } else {

                var cb = data;

                _req("GET", "/prices/buy", cb);

            }

        },

        sell: function(data, cb) {

            if (arguments.length === 2) {

                _req("GET", "/prices/sell?" + querystring.stringify(data), cb);

            } else {

                var cb = data;

                _req("GET", "/prices/sell", cb);

            }

        },

        spotRate: function(data, cb) {

            if (arguments.length === 2) {

                _req("GET", "/prices/spot_rate?" + querystring.stringify(data), cb);

            } else {

                var cb = data;

                _req("GET", "/prices/spot_rate", cb);

            }

        }

    };

};

<|endoftext|>


<commit_before>const Signal = require('signals')
const Mat4 = require('pex-math/Mat4')

function Skin (opts) {
  this.type = 'Skin'
  this.entity = null
  this.joints = []
  this.changed = new Signal()
  this.set(opts)
}

Skin.prototype.init = function (entity) {
  this.entity = entity
}

Skin.prototype.set = function (opts) {
  Object.assign(this, opts)
  Object.keys(opts).forEach((prop) => this.changed.dispatch(prop))
}

Skin.prototype.update = function () {
  this.jointMatrices = this.joints.map((joint, index) => {
    var m = Mat4.create()
    Mat4.mult(m, joint.transform.modelMatrix)
    Mat4.mult(m, this.inverseBindMatrices[index])
    return m
  })
}

module.exports = function createSkin (opts) {
  return new Skin(opts)
}
<commit_msg>Fix pex-math casing in skin<commit_after>const Signal = require('signals')
const mat4 = require('pex-math/mat4')

function Skin (opts) {
  this.type = 'Skin'
  this.entity = null
  this.joints = []
  this.changed = new Signal()
  this.set(opts)
}

Skin.prototype.init = function (entity) {
  this.entity = entity
}

Skin.prototype.set = function (opts) {
  Object.assign(this, opts)
  Object.keys(opts).forEach((prop) => this.changed.dispatch(prop))
}

Skin.prototype.update = function () {
  this.jointMatrices = this.joints.map((joint, index) => {
    var m = mat4.create()
    mat4.mult(m, joint.transform.modelMatrix)
    mat4.mult(m, this.inverseBindMatrices[index])
    return m
  })
}

module.exports = function createSkin (opts) {
  return new Skin(opts)
}
<|endoftext|>


<commit_before>import assert from 'assert';
import { Store } from '../../store.js';

describe('store', () => {
	describe('get', () => {
		it('gets a specific key', () => {
			const store = new Store({
				foo: 'bar'
			});

			assert.equal(store.get('foo'), 'bar');
		});

		it('gets the entire state object', () => {
			const store = new Store({
				foo: 'bar'
			});

			assert.deepEqual(store.get(), { foo: 'bar' });
		});
	});

	describe('set', () => {
		it('sets state', () => {
			const store = new Store();

			store.set({
				foo: 'bar'
			});

			assert.equal(store.get('foo'), 'bar');
		});
	});

	describe('observe', () => {
		it('observes state', () => {
			let newFoo;
			let oldFoo;

			const store = new Store({
				foo: 'bar'
			});

			store.observe('foo', (n, o) => {
				newFoo = n;
				oldFoo = o;
			});

			assert.equal(newFoo, 'bar');
			assert.equal(oldFoo, undefined);

			store.set({
				foo: 'baz'
			});

			assert.equal(newFoo, 'baz');
			assert.equal(oldFoo, 'bar');
		});
	});

	describe('onchange', () => {
		it('fires a callback when state changes', () => {
			const store = new Store();

			let count = 0;
			let args;

			store.onchange((state, changed) => {
				count += 1;
				args = { state, changed };
			});

			store.set({ foo: 'bar' });

			assert.equal(count, 1);
			assert.deepEqual(args, {
				state: { foo: 'bar' },
				changed: { foo: true }
			});

			// this should be a noop
			store.set({ foo: 'bar' });
			assert.equal(count, 1);

			// this shouldn't
			store.set({ foo: 'baz' });

			assert.equal(count, 2);
			assert.deepEqual(args, {
				state: { foo: 'baz' },
				changed: { foo: true }
			});
		});
	});

	describe('computed', () => {
		it('computes a property based on data', () => {
			const store = new Store({
				foo: 1
			});

			store.compute('bar', ['foo'], foo => foo * 2);
			assert.equal(store.get('bar'), 2);

			const values = [];

			store.observe('bar', bar => {
				values.push(bar);
			});

			store.set({ foo: 2 });
			assert.deepEqual(values, [2, 4]);
		});

		it('computes a property based on another computed property', () => {
			const store = new Store({
				foo: 1
			});

			store.compute('bar', ['foo'], foo => foo * 2);
			store.compute('baz', ['bar'], bar => bar * 2);
			assert.equal(store.get('baz'), 4);

			const values = [];

			store.observe('baz', baz => {
				values.push(baz);
			});

			store.set({ foo: 2 });
			assert.deepEqual(values, [4, 8]);
		});

		it('prevents computed properties from being set', () => {
			const store = new Store({
				foo: 1
			});

			store.compute('bar', ['foo'], foo => foo * 2);

			assert.throws(() => {
				store.set({ bar: 'whatever' });
			}, /'bar' is a read-only property/);
		});

		it('allows multiple dependents to depend on the same computed property', () => {
			const store = new Store({
				a: 1
			});

			store.compute('b', ['a'], a => a * 2);
			store.compute('c', ['b'], b => b * 3);
			store.compute('d', ['b'], b => b * 4);

			assert.deepEqual(store.get(), { a: 1, b: 2, c: 6, d: 8 });

			// bit cheeky, testing a private property, but whatever
			assert.equal(store._sortedComputedProperties.length, 3);
		});

		it('prevents cyclical dependencies', () => {
			const store = new Store();

			assert.throws(() => {
				store.compute('a', ['b'], b => b + 1);
				store.compute('b', ['a'], a => a + 1);
			}, /Cyclical dependency detected — a computed property cannot indirectly depend on itself/);
		});
	});
});
<commit_msg>guard against introducing ES6+isms into store.js<commit_after>import fs from 'fs';
import assert from 'assert';
import MagicString from 'magic-string';
import { parse } from 'acorn';
import { Store } from '../../store.js';

describe('store', () => {
	it('is written in ES5', () => {
		const source = fs.readFileSync('store.js', 'utf-8');

		const ast = parse(source, {
			sourceType: 'module'
		});

		const magicString = new MagicString(source);
		ast.body.forEach(node => {
			if (/^(Im|Ex)port/.test(node.type)) magicString.remove(node.start, node.end);
		});

		parse(magicString.toString(), {
			ecmaVersion: 5
		});
	});

	describe('get', () => {
		it('gets a specific key', () => {
			const store = new Store({
				foo: 'bar'
			});

			assert.equal(store.get('foo'), 'bar');
		});

		it('gets the entire state object', () => {
			const store = new Store({
				foo: 'bar'
			});

			assert.deepEqual(store.get(), { foo: 'bar' });
		});
	});

	describe('set', () => {
		it('sets state', () => {
			const store = new Store();

			store.set({
				foo: 'bar'
			});

			assert.equal(store.get('foo'), 'bar');
		});
	});

	describe('observe', () => {
		it('observes state', () => {
			let newFoo;
			let oldFoo;

			const store = new Store({
				foo: 'bar'
			});

			store.observe('foo', (n, o) => {
				newFoo = n;
				oldFoo = o;
			});

			assert.equal(newFoo, 'bar');
			assert.equal(oldFoo, undefined);

			store.set({
				foo: 'baz'
			});

			assert.equal(newFoo, 'baz');
			assert.equal(oldFoo, 'bar');
		});
	});

	describe('onchange', () => {
		it('fires a callback when state changes', () => {
			const store = new Store();

			let count = 0;
			let args;

			store.onchange((state, changed) => {
				count += 1;
				args = { state, changed };
			});

			store.set({ foo: 'bar' });

			assert.equal(count, 1);
			assert.deepEqual(args, {
				state: { foo: 'bar' },
				changed: { foo: true }
			});

			// this should be a noop
			store.set({ foo: 'bar' });
			assert.equal(count, 1);

			// this shouldn't
			store.set({ foo: 'baz' });

			assert.equal(count, 2);
			assert.deepEqual(args, {
				state: { foo: 'baz' },
				changed: { foo: true }
			});
		});
	});

	describe('computed', () => {
		it('computes a property based on data', () => {
			const store = new Store({
				foo: 1
			});

			store.compute('bar', ['foo'], foo => foo * 2);
			assert.equal(store.get('bar'), 2);

			const values = [];

			store.observe('bar', bar => {
				values.push(bar);
			});

			store.set({ foo: 2 });
			assert.deepEqual(values, [2, 4]);
		});

		it('computes a property based on another computed property', () => {
			const store = new Store({
				foo: 1
			});

			store.compute('bar', ['foo'], foo => foo * 2);
			store.compute('baz', ['bar'], bar => bar * 2);
			assert.equal(store.get('baz'), 4);

			const values = [];

			store.observe('baz', baz => {
				values.push(baz);
			});

			store.set({ foo: 2 });
			assert.deepEqual(values, [4, 8]);
		});

		it('prevents computed properties from being set', () => {
			const store = new Store({
				foo: 1
			});

			store.compute('bar', ['foo'], foo => foo * 2);

			assert.throws(() => {
				store.set({ bar: 'whatever' });
			}, /'bar' is a read-only property/);
		});

		it('allows multiple dependents to depend on the same computed property', () => {
			const store = new Store({
				a: 1
			});

			store.compute('b', ['a'], a => a * 2);
			store.compute('c', ['b'], b => b * 3);
			store.compute('d', ['b'], b => b * 4);

			assert.deepEqual(store.get(), { a: 1, b: 2, c: 6, d: 8 });

			// bit cheeky, testing a private property, but whatever
			assert.equal(store._sortedComputedProperties.length, 3);
		});

		it('prevents cyclical dependencies', () => {
			const store = new Store();

			assert.throws(() => {
				store.compute('a', ['b'], b => b + 1);
				store.compute('b', ['a'], a => a + 1);
			}, /Cyclical dependency detected — a computed property cannot indirectly depend on itself/);
		});
	});
});
<|endoftext|>


<commit_before>var fs = require('fs')
var sia = require('../')
var SearchIndexSearcher = require('search-index-searcher')
var test = require('tape')
var JSONStream = require('JSONStream')
var indexer

test('init indexer', function (t) {
  t.plan(1)
  sia({
    indexPath: 'test/sandbox/streamTest'
  }, function (err, thisIndexer) {
    indexer = thisIndexer
    t.error(err)
  })
})

test('test stream file', function (t) {
  t.plan(11)
  const filePath = './node_modules/reuters-21578-json/data/fullFileStream/justTen.str'
  require('readline').createInterface({
    input: fs.createReadStream(filePath)
  })
    .on('line', function (line) {
      t.ok(true)
    })
    .on('close', function () {
      t.ok(true)
    })
})

test('stream file to search-index', { timeout: 6000000 }, function (t) {
  t.plan(1)
  const filePath = './node_modules/reuters-21578-json/data/fullFileStream/justTen.str'
  // const filePath = './data.json'
  fs.createReadStream(filePath)
    .pipe(indexer.feedFromFile())
    .on('data', function (data) {
      // nowt
    })
    .on('finish', function () {
      console.log('test completed')
      t.ok(true)
    })
})

test('close search-index-adder', function (t) {
  t.plan(1)
  indexer.close(function (err) {
    t.error(err)
  })
})

test('index should be searchable', function (t) {
  t.plan(11)
  var results = [ '9', '8', '7', '6', '5', '4', '3', '2', '10', '1' ]
  SearchIndexSearcher({
    indexPath: 'test/sandbox/streamTest'
  }, function (err, si) {
    t.error(err)
    si.search({
      query: [{
        AND: {'*': ['*']}
      }]
    }).on('data', function (data) {
      t.ok(data.document.id === results.shift())
    })
  })
})
<commit_msg>refactor(cleanup): removed unreferenced variable<commit_after>var fs = require('fs')
var sia = require('../')
var SearchIndexSearcher = require('search-index-searcher')
var test = require('tape')
var indexer

test('init indexer', function (t) {
  t.plan(1)
  sia({
    indexPath: 'test/sandbox/streamTest'
  }, function (err, thisIndexer) {
    indexer = thisIndexer
    t.error(err)
  })
})

test('test stream file', function (t) {
  t.plan(11)
  const filePath = './node_modules/reuters-21578-json/data/fullFileStream/justTen.str'
  require('readline').createInterface({
    input: fs.createReadStream(filePath)
  })
    .on('line', function (line) {
      t.ok(true)
    })
    .on('close', function () {
      t.ok(true)
    })
})

test('stream file to search-index', { timeout: 6000000 }, function (t) {
  t.plan(1)
  const filePath = './node_modules/reuters-21578-json/data/fullFileStream/justTen.str'
  // const filePath = './data.json'
  fs.createReadStream(filePath)
    .pipe(indexer.feedFromFile())
    .on('data', function (data) {
      // nowt
    })
    .on('finish', function () {
      console.log('test completed')
      t.ok(true)
    })
})

test('close search-index-adder', function (t) {
  t.plan(1)
  indexer.close(function (err) {
    t.error(err)
  })
})

test('index should be searchable', function (t) {
  t.plan(11)
  var results = [ '9', '8', '7', '6', '5', '4', '3', '2', '10', '1' ]
  SearchIndexSearcher({
    indexPath: 'test/sandbox/streamTest'
  }, function (err, si) {
    t.error(err)
    si.search({
      query: [{
        AND: {'*': ['*']}
      }]
    }).on('data', function (data) {
      t.ok(data.document.id === results.shift())
    })
  })
})
<|endoftext|>


<commit_before>var assert = require('assert'),
    base62 = require('base62');

suite('base62のテスト', function () {

  suite('decode関数のテスト', function () {

    test('"0"を渡して0が返ること', function () {
      assert.strictEqual(base62.decode('0'), 0);
    });

    test('"Z"を渡して61が返ること', function () {
      assert.strictEqual(base62.decode('Z'), 61);
    });

    test('"10"を渡して62が返ること', function () {
      assert.strictEqual(base62.decode('10'), 62);
    });

    test('"ZZ"を渡して3843が返ること', function () {
      assert.strictEqual(base62.decode('ZZ'), 3843);
    });

    test('"1000000"を渡して56800235584が返ること', function () {
      assert.strictEqual(base62.decode('1000000'), 56800235584);
    });

    test('"ZZZZZZZ"を渡して3521614606207が返ること', function () {
      assert.strictEqual(base62.decode('ZZZZZZZ'), 3521614606207);
    });

    test('"-0"を渡して0が返ること', function () {
      assert.strictEqual(base62.decode('-0'), 0);
    });

    test('"-Z"を渡して-61が返ること', function () {
      assert.strictEqual(base62.decode('-Z'), -61);
    });

    test('"-10"を渡して-62が返ること', function () {
      assert.strictEqual(base62.decode('-10'), -62);
    });

    test('"-ZZ"を渡して-3843が返ること', function () {
      assert.strictEqual(base62.decode('-ZZ'), -3843);
    });

    test('"-1000000"を渡して-56800235584が返ること', function () {
      assert.strictEqual(base62.decode('-1000000'), -56800235584);
    });

    test('"-ZZZZZZZ"を渡して-3521614606207が返ること', function () {
      assert.strictEqual(base62.decode('-ZZZZZZZ'), -3521614606207);
    });

    test('undefinedを渡してNaNが返ること', function () {
      assert.strictEqual(isNaN(base62.decode()), true);
    });

    test('空文字を渡してNaNが返ること', function () {
      assert.strictEqual(isNaN(base62.decode('')), true);
    });

    test('0を渡してNaNが返ること', function () {
      assert.strictEqual(isNaN(base62.decode(0)), true);
    });

    test('falseを渡してNaNが返ること', function () {
      assert.strictEqual(isNaN(base62.decode(false)), true);
    });

  });

  suite('encode関数のテスト', function () {

    test('0を渡して"0"が返ること', function () {
      assert.strictEqual(base62.encode(0), '0');
    });

    test('61を渡して"Z"が返ること', function () {
      assert.strictEqual(base62.encode(61), 'Z');
    });

    test('62を渡して"10"が返ること', function () {
      assert.strictEqual(base62.encode(62), '10');
    });

    test('3843を渡して"ZZ"が返ること', function () {
      assert.strictEqual(base62.encode(3843), 'ZZ');
    });

    test('56800235584を渡して"1000000"が返ること', function () {
      assert.strictEqual(base62.encode(56800235584), '1000000');
    });

    test('3521614606207を渡して"ZZZZZZZ"が返ること', function () {
      assert.strictEqual(base62.encode(3521614606207), 'ZZZZZZZ');
    });

    test('-0を渡して"0"が返ること', function () {
      assert.strictEqual(base62.encode(-0), '0');
    });

    test('-61を渡して"-Z"が返ること', function () {
      assert.strictEqual(base62.encode(-61), '-Z');
    });

    test('-62を渡して"-10"が返ること', function () {
      assert.strictEqual(base62.encode(-62), '-10');
    });

    test('-3843を渡して"-ZZ"が返ること', function () {
      assert.strictEqual(base62.encode(-3843), '-ZZ');
    });

    test('-56800235584を渡して"-1000000"が返ること', function () {
      assert.strictEqual(base62.encode(-56800235584), '-1000000');
    });

    test('-3521614606207を渡して"-ZZZZZZZ"が返ること', function () {
      assert.strictEqual(base62.encode(-3521614606207), '-ZZZZZZZ');
    });

    test('undefinedを渡して空文字が返ること', function () {
      assert.strictEqual(base62.encode(), '');
    });

    test('NaNを渡して空文字が返ること', function () {
      assert.strictEqual(base62.encode(NaN), '');
    });

    test('Infinityを渡して空文字が返ること', function () {
      assert.strictEqual(base62.encode(Infinity), '');
    });

    test('文字列を渡して空文字が返ること', function () {
      assert.strictEqual(base62.encode('base62'), '');
    });

    test('falseを渡して空文字が返ること', function () {
      assert.strictEqual(base62.encode(false), '');
    });

  });

});
<commit_msg>encode関数のテストに小数点の値についてのテストを追加<commit_after>var assert = require('assert'),
    base62 = require('base62');

suite('base62のテスト', function () {

  suite('decode関数のテスト', function () {

    test('"0"を渡して0が返ること', function () {
      assert.strictEqual(base62.decode('0'), 0);
    });

    test('"Z"を渡して61が返ること', function () {
      assert.strictEqual(base62.decode('Z'), 61);
    });

    test('"10"を渡して62が返ること', function () {
      assert.strictEqual(base62.decode('10'), 62);
    });

    test('"ZZ"を渡して3843が返ること', function () {
      assert.strictEqual(base62.decode('ZZ'), 3843);
    });

    test('"1000000"を渡して56800235584が返ること', function () {
      assert.strictEqual(base62.decode('1000000'), 56800235584);
    });

    test('"ZZZZZZZ"を渡して3521614606207が返ること', function () {
      assert.strictEqual(base62.decode('ZZZZZZZ'), 3521614606207);
    });

    test('"-0"を渡して0が返ること', function () {
      assert.strictEqual(base62.decode('-0'), 0);
    });

    test('"-Z"を渡して-61が返ること', function () {
      assert.strictEqual(base62.decode('-Z'), -61);
    });

    test('"-10"を渡して-62が返ること', function () {
      assert.strictEqual(base62.decode('-10'), -62);
    });

    test('"-ZZ"を渡して-3843が返ること', function () {
      assert.strictEqual(base62.decode('-ZZ'), -3843);
    });

    test('"-1000000"を渡して-56800235584が返ること', function () {
      assert.strictEqual(base62.decode('-1000000'), -56800235584);
    });

    test('"-ZZZZZZZ"を渡して-3521614606207が返ること', function () {
      assert.strictEqual(base62.decode('-ZZZZZZZ'), -3521614606207);
    });

    test('undefinedを渡してNaNが返ること', function () {
      assert.strictEqual(isNaN(base62.decode()), true);
    });

    test('空文字を渡してNaNが返ること', function () {
      assert.strictEqual(isNaN(base62.decode('')), true);
    });

    test('0を渡してNaNが返ること', function () {
      assert.strictEqual(isNaN(base62.decode(0)), true);
    });

    test('falseを渡してNaNが返ること', function () {
      assert.strictEqual(isNaN(base62.decode(false)), true);
    });

  });

  suite('encode関数のテスト', function () {

    test('0を渡して"0"が返ること', function () {
      assert.strictEqual(base62.encode(0), '0');
    });

    test('61を渡して"Z"が返ること', function () {
      assert.strictEqual(base62.encode(61), 'Z');
    });

    test('62を渡して"10"が返ること', function () {
      assert.strictEqual(base62.encode(62), '10');
    });

    test('3843を渡して"ZZ"が返ること', function () {
      assert.strictEqual(base62.encode(3843), 'ZZ');
    });

    test('56800235584を渡して"1000000"が返ること', function () {
      assert.strictEqual(base62.encode(56800235584), '1000000');
    });

    test('3521614606207を渡して"ZZZZZZZ"が返ること', function () {
      assert.strictEqual(base62.encode(3521614606207), 'ZZZZZZZ');
    });

    test('-0を渡して"0"が返ること', function () {
      assert.strictEqual(base62.encode(-0), '0');
    });

    test('-61を渡して"-Z"が返ること', function () {
      assert.strictEqual(base62.encode(-61), '-Z');
    });

    test('-62を渡して"-10"が返ること', function () {
      assert.strictEqual(base62.encode(-62), '-10');
    });

    test('-3843を渡して"-ZZ"が返ること', function () {
      assert.strictEqual(base62.encode(-3843), '-ZZ');
    });

    test('-56800235584を渡して"-1000000"が返ること', function () {
      assert.strictEqual(base62.encode(-56800235584), '-1000000');
    });

    test('-3521614606207を渡して"-ZZZZZZZ"が返ること', function () {
      assert.strictEqual(base62.encode(-3521614606207), '-ZZZZZZZ');
    });

    test('10.5を渡して"a"が返ること', function () {
      assert.strictEqual(base62.encode(10.5), 'a');
    });

    test('-10.5を渡して"-a"が返ること', function () {
      assert.strictEqual(base62.encode(-10.5), '-a');
    });

    test('undefinedを渡して空文字が返ること', function () {
      assert.strictEqual(base62.encode(), '');
    });

    test('NaNを渡して空文字が返ること', function () {
      assert.strictEqual(base62.encode(NaN), '');
    });

    test('Infinityを渡して空文字が返ること', function () {
      assert.strictEqual(base62.encode(Infinity), '');
    });

    test('文字列を渡して空文字が返ること', function () {
      assert.strictEqual(base62.encode('base62'), '');
    });

    test('falseを渡して空文字が返ること', function () {
      assert.strictEqual(base62.encode(false), '');
    });

  });

});
<|endoftext|>


<commit_before>'use strict';
const assert = require('chai').assert;
const fs = require('fs');
const cheerio = require("cheerio/lib/static.js");
const MealsController = require('../app/app');

describe('The sv page parer module', function(){
    it('formats the menuplan page of 2016-02-14 correctly',function () {
        let menuplanPath = __dirname + "\\menuplan2016-02-14.html";

        let mealsController = new MealsController.MealsController();

        let $ = cheerio.load(fs.readFileSync(menuplanPath));
        mealsController.formatMessage($,function (text) {
            console.warn("callback");
            console.warn(text);
        });
/*        mealsController.parse('file://__dirname\\test\Menuplan2016-02-14.html',function () {

        });*/
    });
});

<commit_msg>test: add formatting test for menuplan page of 14.12.2016<commit_after>'use strict';
const assert = require('assert');
const fs = require('fs');
const cheerio = require("cheerio/lib/static.js");
const MealsController = require('../app/app');

describe('The sv page parer module', function(){
    it('formats the menuplan page of 2016-02-14 correctly',function() {
        let markdownTextExpected = `*chefs choice: Knusprig gebratene Entenbrust*
an Balsamicojus
Ofen Kartoffeln
Grillgemüse
_CHF 18.90_

*dailys: Gemüseauflauf*
mit Basilikumsauce
und gebackenen Avocadoecken
_CHF 14.50_

*free choice: Sautierte Lammstreifen*
Thymiansauce, Kartoffelgratin, Schwarzwurzel mit Sultanienen,
Gemüseebly, Bouillongemüse,
sautiertes Kürbisgemüse
_100G 3.30_

*season market: Wrap mit Rindsstreifen*
Cocktailsauce, Rucola,
Tomaten, Eisbergsalat
an bunten Blattsalaten
_CHF 17.50_

*go4 pasta: Agnolotti Fondue*
Sauce Quattro Formaggi
und Gemüse Ragout
_CHF 14.90_

`;
        let menuplanPath = __dirname + "\\menuplan2016-02-14.html";
        let mealsController = new MealsController.MealsController();

        let $ = cheerio.load(fs.readFileSync(menuplanPath));
        let markdownTextActual = mealsController.formatMessage($);

        assert.equal(markdownTextActual, markdownTextExpected, "Page is formatted to the correct markdown");
    });
});

<|endoftext|>


<commit_before>/*!
 * Copyright 2014 mpowers
 *
 * 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.
 */
(function(window, undefined) {

	/*
	 * Pollster monitors feeds and notifies subscribers of updates. We expect to
	 * see a number of different strategies for achieving near-real-time
	 * results, and those should be drop in replacements for this interface.
	 */
	var pollster = window.pollster = {};

	/**
	 * Shared timer.
	 */
	var timer;

	/**
	 * Ordered queue of tasks to complete, highest priority at front.
	 */
	var queue = [];

	/**
	 * Shared callback list.
	 */
	var topicToSubscribers = {};

	/**
	 * Mapping of topic to corresponding task.
	 */
	var topicToTask = {};

	/**
	 * Keeps a copy of latest result for a given query.
	 * TODO: need to clear out the cache after a while
	 */
	var resultCache = {};

	/**
	 * Subscribe to have your notify(feedXml, query) method called each time new
	 * results are received for the specified query.
	 */
	pollster.subscribe = function(query, subscriber) {
		var topic = JSON.stringify(query);
		var subscribers = topicToSubscribers[topic];
		if (subscribers) {
			var existing = subscribers.indexOf(subscriber);
			if (existing === -1) {
				subscribers.push(subscriber);
			}
		} else {
			topicToSubscribers[topic] = [ subscriber ];
		}

		// if existing task
		var task = topicToTask[topic];
		if (task) {
			if (task.latestFeed) {
				// notify subscriber now of latest results
				subscriber.notify(task.latestFeed, query);
			} else {
				// trigger refetch asap
				task.noFetchBefore = 0;
			}
			// will get updated on already queued task
		} else {
			// otherwise: create new task
			task = {
				query : query,
				lastUpdate : 0,
				lastFetched : 0,
				noFetchBefore : 0
			};
			topicToTask[topic] = task;
			// execute now
			doTask(task);
			// doTask will insert task into queue
		}

	};

	pollster.unsubscribe = function(subscriber) {
		// scan the entire list and remove ourself
		for ( var i in topicToSubscribers) {
			for ( var j in topicToSubscribers[i]) {
				if (topicToSubscribers[i][j] === subscriber) {
					topicToSubscribers[i].splice(j, 1); // remove
					if (topicToSubscribers[i].length === 0) {
						delete topicToSubscribers[i];
					}
				}
			}
		}
	};

	var concurrentFetchCount = 0;

	pollster.getPendingCount = function() {
		return concurrentFetchCount;
	};

	pollster.incrementPendingCount = function() {
		concurrentFetchCount++;
		if (concurrentFetchCount > 2) {
			$("body").addClass("pending");
		}
	};

	pollster.decrementPendingCount = function() {
		concurrentFetchCount--;
		if (concurrentFetchCount === 0) {
			$("body").removeClass("pending");
		}
	};

	/**
	 * Executes the task's query and notifies subscribers. Return true if task
	 * completed successfully, or false if no query was executed.
	 */
	var doTask = function(task) {
		var topic = JSON.stringify(task.query);
		var subscribers = topicToSubscribers[topic];
		if (!subscribers || subscribers.length === 0) {
//			console.log("Deleting task: " + topic);
//			console.log(task);
//			delete topicToSubscribers[topic];
//			delete topicToTask[topic];
			return false; // task skipped
		}
		// console.log("doTask: " + task.toString());
		var query = shallowCopy(task.query);
		var feedId = query.feedId;

		if (task.latestEntryId) {
			// use latest entry update time
			query.after = task.latestEntryId;
		}

		// if first time executing task
		if (task.lastFetched === 0) {
			// fetch only latest few and requeue
			query.count = 4;
		}

		var self = this;
		pollster.incrementPendingCount();
		console.log("concurrentFetchCount: inc:" + pollster.getPendingCount());
		var stringifiedQuery = JSON.stringify(query);
		console.log("Sent:     " + pollster.getPendingCount() + " : " + stringifiedQuery);
		var currentTask = task;
		model.pull(query, function(feedData) {
			if (!feedData) {
				console.log("Not found: " + pollster.getPendingCount() + " : " + JSON.stringify(query));
			} else {
				//console.log("Received: " + pollster.getPendingCount() + " : " + JSON.stringify(query));

				// call each subscriber's notify function
				for ( var i in subscribers) {
					subscribers[i].notify(feedData, query);
				}

				// grab the latest result if any
				resultCache[stringifiedQuery] = feedData;
				var entries = feedData.children("entry");
				if (entries.length > 0) {
					currentTask.latestEntry = entries.first();
					currentTask.latestEntryId = model.entryIdFromEntryUrn(currentTask.latestEntry.children("id").text());
					currentTask.latestFeed = feedData;
					// remember latest feed *with entries*
				}

				// requeue this task
				var now = new Date().getTime();
				var updated;
				var diff;
				if (currentTask.latestEntry) {
					// use latest entry update if we can
					updated = Date.parse(currentTask.latestEntry.find("entry updated").first().text());
					if (!updated) {
						console.log("Error: could not parse entry date: " + Date.parse($(feedData).children("entry updated").text()));
					}
				} else {
					// fall back on feed's updated date
					updated = Date.parse(feedData.children("updated").text());
					if (!updated) {
						console.log("Error: could not parse feed date: " + feedData.children("updated").text());
					}
				}
				if (!updated) {
					console.log("       defaulting to one hour");
					diff = 60 * 60 * 1000; // default to 1 hour
					updated = now - diff;
				}
				diff = now - updated;
				if (diff < 1) {
					console.log("Error: feed was updated in the future: " + updated);
					diff = 60 * 60 * 1000; // default to 1 hour
				}

				if (currentTask.lastFetched === 0) {
					// first time fetch:
					// fetch again after 15 seconds to allow for relays to respond
					currentTask.noFetchBefore = now + 15 * 1000;
					console.log("rescheduled: " + currentTask.query.feedId + " : asap");
				} else {
					// fetch on a sliding delay
					diff = Math.max(6, Math.min(diff, Math.floor(Math.pow(diff / 60000, 1 / 3) * 20000)));
					currentTask.noFetchBefore = now + diff;
					// schedule fetch for cube root of the number of elapsed minutes
					console.log("rescheduled: " + currentTask.query.feedId + " : " + Math.floor((now - updated) / 1000) + "s : " + Math.floor(diff / 1000 / 60) + "m " + Math.floor((diff / 1000) % 60) + "s");
				}
				currentTask.lastUpdate = updated;
				currentTask.lastFetched = now;

				insertTaskIntoSortedQueue(currentTask);
			}
			pollster.decrementPendingCount();
			console.log("concurrentFetchCount: dec:" + pollster.getPendingCount());

		});
		return true; // task was handled
	};

	var insertTaskIntoSortedQueue = function(task) {
		// console.log("insertTaskIntoSortedQueue: ");
		// console.log(task);
		// could try binary search but suspect
		// reverse linear might be faster with js array:
		var time = task.nextFetch;
		var next;
		for (var i = queue.length - 1; i >= 0; i--) {
			next = queue[i].nextFetch;
			if (next === time) {
				// check for duplicate task
				if (JSON.stringify(queue[i].query) === JSON.stringify(task.query)) {
					console.log("Coalescing duplicate task");
					return; // done: exit
				}
			}
			if (next < time) {
				queue.splice(i + i, 0, task);
				return; // done: exit
			}
		}
		// insert at rear of queue
		queue.splice(0, 0, task);
	};

	/**
	 * Resumes polling.
	 */
	var start = function() {
		if (!timer) {
			timer = window.setInterval(function() {
				onTick();
			}, 250);
		}
	};

	/**
	 * Pauses polling.
	 */
	var stop = function() {
		window.clearInterval(timer);
	};

	/**
	 * Called with each tick of the timer to refetch any pending feeds on the
	 * queue.
	 */
	var onTick = function() {
		if (pollster.getPendingCount() < 5) {
			// console.log("onTick");
			var task;
			var time = new Date().getTime();
			for (var i = queue.length - 1; i >= 0; i--) {
				task = queue[i];
				if (task.noFetchBefore < time) {
					queue.splice(i, 1); // remove
					if (doTask(task)) {
						return; // done: exit
					}
				}
			}
		}
	};

	var shallowCopy = function(obj) {
		var result = {};
		for ( var i in obj) {
			result[i] = obj[i];
		}
		return result;
	};

	/**
	 * Called by model to notify us of a local change to a feed so we can
	 * refresh our subscribers if needed.
	 */
	model.subscribe(function(feedId) {
		var copy = [];
		var priority = [];
		var task;
		var i;
		for (i in queue) {
			task = queue[i];
			// catch plain and urn:feed case
			if (feedId.indexOf(task.query.feedId) != -1) {
				// fetch asap
				task.noFetchBefore = 0;
				task.lastUpdate = new Date().getTime();
				priority.push(task);
			} else {
				copy.push(task);
			}
		}
		for (i in priority) {
			copy.push(priority[i]);
		}
		queue = copy;
	});

	/**
	 * Start the timer.
	 */
	start();

})(window);
<commit_msg>Reducing the timer rate for performance. <commit_after>/*!
 * Copyright 2014 mpowers
 *
 * 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.
 */
(function(window, undefined) {

	/*
	 * Pollster monitors feeds and notifies subscribers of updates. We expect to
	 * see a number of different strategies for achieving near-real-time
	 * results, and those should be drop in replacements for this interface.
	 */
	var pollster = window.pollster = {};

	/**
	 * Shared timer.
	 */
	var timer;

	/**
	 * Ordered queue of tasks to complete, highest priority at front.
	 */
	var queue = [];

	/**
	 * Shared callback list.
	 */
	var topicToSubscribers = {};

	/**
	 * Mapping of topic to corresponding task.
	 */
	var topicToTask = {};

	/**
	 * Keeps a copy of latest result for a given query.
	 * TODO: need to clear out the cache after a while
	 */
	var resultCache = {};

	/**
	 * Subscribe to have your notify(feedXml, query) method called each time new
	 * results are received for the specified query.
	 */
	pollster.subscribe = function(query, subscriber) {
		var topic = JSON.stringify(query);
		var subscribers = topicToSubscribers[topic];
		if (subscribers) {
			var existing = subscribers.indexOf(subscriber);
			if (existing === -1) {
				subscribers.push(subscriber);
			}
		} else {
			topicToSubscribers[topic] = [ subscriber ];
		}

		// if existing task
		var task = topicToTask[topic];
		if (task) {
			if (task.latestFeed) {
				// notify subscriber now of latest results
				subscriber.notify(task.latestFeed, query);
			} else {
				// trigger refetch asap
				task.noFetchBefore = 0;
			}
			// will get updated on already queued task
		} else {
			// otherwise: create new task
			task = {
				query : query,
				lastUpdate : 0,
				lastFetched : 0,
				noFetchBefore : 0
			};
			topicToTask[topic] = task;
			// execute now
			doTask(task);
			// doTask will insert task into queue
		}

	};

	pollster.unsubscribe = function(subscriber) {
		// scan the entire list and remove ourself
		for ( var i in topicToSubscribers) {
			for ( var j in topicToSubscribers[i]) {
				if (topicToSubscribers[i][j] === subscriber) {
					topicToSubscribers[i].splice(j, 1); // remove
					if (topicToSubscribers[i].length === 0) {
						delete topicToSubscribers[i];
					}
				}
			}
		}
	};

	var concurrentFetchCount = 0;

	pollster.getPendingCount = function() {
		return concurrentFetchCount;
	};

	pollster.incrementPendingCount = function() {
		concurrentFetchCount++;
		if (concurrentFetchCount > 2) {
			$("body").addClass("pending");
		}
	};

	pollster.decrementPendingCount = function() {
		concurrentFetchCount--;
		if (concurrentFetchCount === 0) {
			$("body").removeClass("pending");
		}
	};

	/**
	 * Executes the task's query and notifies subscribers. Return true if task
	 * completed successfully, or false if no query was executed.
	 */
	var doTask = function(task) {
		var topic = JSON.stringify(task.query);
		var subscribers = topicToSubscribers[topic];
		if (!subscribers || subscribers.length === 0) {
//			console.log("Deleting task: " + topic);
//			console.log(task);
//			delete topicToSubscribers[topic];
//			delete topicToTask[topic];
			return false; // task skipped
		}
		// console.log("doTask: " + task.toString());
		var query = shallowCopy(task.query);
		var feedId = query.feedId;

		if (task.latestEntryId) {
			// use latest entry update time
			query.after = task.latestEntryId;
		}

		// if first time executing task
		if (task.lastFetched === 0) {
			// fetch only latest few and requeue
			query.count = 4;
		}

		var self = this;
		pollster.incrementPendingCount();
		console.log("concurrentFetchCount: inc:" + pollster.getPendingCount());
		var stringifiedQuery = JSON.stringify(query);
		console.log("Sent:     " + pollster.getPendingCount() + " : " + stringifiedQuery);
		var currentTask = task;
		model.pull(query, function(feedData) {
			if (!feedData) {
				console.log("Not found: " + pollster.getPendingCount() + " : " + JSON.stringify(query));
			} else {
				//console.log("Received: " + pollster.getPendingCount() + " : " + JSON.stringify(query));

				// call each subscriber's notify function
				for ( var i in subscribers) {
					subscribers[i].notify(feedData, query);
				}

				// grab the latest result if any
				resultCache[stringifiedQuery] = feedData;
				var entries = feedData.children("entry");
				if (entries.length > 0) {
					currentTask.latestEntry = entries.first();
					currentTask.latestEntryId = model.entryIdFromEntryUrn(currentTask.latestEntry.children("id").text());
					currentTask.latestFeed = feedData;
					// remember latest feed *with entries*
				}

				// requeue this task
				var now = new Date().getTime();
				var updated;
				var diff;
				if (currentTask.latestEntry) {
					// use latest entry update if we can
					updated = Date.parse(currentTask.latestEntry.find("entry updated").first().text());
					if (!updated) {
						console.log("Error: could not parse entry date: " + Date.parse($(feedData).children("entry updated").text()));
					}
				} else {
					// fall back on feed's updated date
					updated = Date.parse(feedData.children("updated").text());
					if (!updated) {
						console.log("Error: could not parse feed date: " + feedData.children("updated").text());
					}
				}
				if (!updated) {
					console.log("       defaulting to one hour");
					diff = 60 * 60 * 1000; // default to 1 hour
					updated = now - diff;
				}
				diff = now - updated;
				if (diff < 1) {
					console.log("Error: feed was updated in the future: " + updated);
					diff = 60 * 60 * 1000; // default to 1 hour
				}

				if (currentTask.lastFetched === 0) {
					// first time fetch:
					// fetch again after 15 seconds to allow for relays to respond
					currentTask.noFetchBefore = now + 15 * 1000;
					console.log("rescheduled: " + currentTask.query.feedId + " : asap");
				} else {
					// fetch on a sliding delay
					diff = Math.max(6, Math.min(diff, Math.floor(Math.pow(diff / 60000, 1 / 3) * 20000)));
					currentTask.noFetchBefore = now + diff;
					// schedule fetch for cube root of the number of elapsed minutes
					console.log("rescheduled: " + currentTask.query.feedId + " : " + Math.floor((now - updated) / 1000) + "s : " + Math.floor(diff / 1000 / 60) + "m " + Math.floor((diff / 1000) % 60) + "s");
				}
				currentTask.lastUpdate = updated;
				currentTask.lastFetched = now;

				insertTaskIntoSortedQueue(currentTask);
			}
			pollster.decrementPendingCount();
			console.log("concurrentFetchCount: dec:" + pollster.getPendingCount());

		});
		return true; // task was handled
	};

	var insertTaskIntoSortedQueue = function(task) {
		// console.log("insertTaskIntoSortedQueue: ");
		// console.log(task);
		// could try binary search but suspect
		// reverse linear might be faster with js array:
		var time = task.nextFetch;
		var next;
		for (var i = queue.length - 1; i >= 0; i--) {
			next = queue[i].nextFetch;
			if (next === time) {
				// check for duplicate task
				if (JSON.stringify(queue[i].query) === JSON.stringify(task.query)) {
					console.log("Coalescing duplicate task");
					return; // done: exit
				}
			}
			if (next < time) {
				queue.splice(i + i, 0, task);
				return; // done: exit
			}
		}
		// insert at rear of queue
		queue.splice(0, 0, task);
	};

	/**
	 * Resumes polling.
	 */
	var start = function() {
		if (!timer) {
			timer = window.setInterval(function() {
				onTick();
			}, 1000);
		}
	};

	/**
	 * Pauses polling.
	 */
	var stop = function() {
		window.clearInterval(timer);
	};

	/**
	 * Called with each tick of the timer to refetch any pending feeds on the
	 * queue.
	 */
	var onTick = function() {
		if (pollster.getPendingCount() < 5) {
			// console.log("onTick");
			var task;
			var time = new Date().getTime();
			for (var i = queue.length - 1; i >= 0; i--) {
				task = queue[i];
				if (task.noFetchBefore < time) {
					queue.splice(i, 1); // remove
					if (doTask(task)) {
						return; // done: exit
					}
				}
			}
		}
	};

	var shallowCopy = function(obj) {
		var result = {};
		for ( var i in obj) {
			result[i] = obj[i];
		}
		return result;
	};

	/**
	 * Called by model to notify us of a local change to a feed so we can
	 * refresh our subscribers if needed.
	 */
	model.subscribe(function(feedId) {
		var copy = [];
		var priority = [];
		var task;
		var i;
		for (i in queue) {
			task = queue[i];
			// catch plain and urn:feed case
			if (feedId.indexOf(task.query.feedId) != -1) {
				// fetch asap
				task.noFetchBefore = 0;
				task.lastUpdate = new Date().getTime();
				priority.push(task);
			} else {
				copy.push(task);
			}
		}
		for (i in priority) {
			copy.push(priority[i]);
		}
		queue = copy;
	});

	/**
	 * Start the timer.
	 */
	start();

})(window);
<|endoftext|>


<commit_before>var Promise         = require('bluebird')
  , _               = require('lodash')
  , Docker          = require('dockerode')
  , config          = require('config')
  , Worker          = require('../core/worker')
  ;

function DockerPool(){
  var docker_options = undefined;

  if (config.has('docker.host') && config.get('docker.host') != undefined) {
    docker_options = {
        protocol  : config.get('docker.protocol')
      , host      : config.get('docker.host')
      , port      : config.get('docker.port')
    };
  }

  this.docker = new Docker(docker_options);
};

DockerPool.prototype._next_id = 0;
DockerPool.prototype.workers = {};

DockerPool.prototype.create_worker = function(cb) {
  var id    = this._next_id ++
    , worker = new Worker({
          dir         : config.get('worker.dir')
        , id          : id
        , protocol    : 'http'
        , host        : config.get('docker.host')
        , port        : config.get('worker.port') + id
      })
    ;

  this.workers[id] = worker;

  cb && cb(undefined, worker);
};

DockerPool.prototype.prepare = function(id, cb) {
  var worker = _.isObject(id)? id : this.workers[id];

  Promise
    .resolve(worker)
    .bind(this)
    .then(function(worker){
      if (!worker) {
        throw new Error('unknown worker');
      }

      return worker;
    })
    .then(function(worker){
      return Promise
              .promisify(this.docker.createContainer, this.docker)({
                  Image     : 'a7medkamel/taskmill-core-dockerworker'
                , Cmd       : ['node', '/home/worker/index.js']
                , CpuShares : 128
                , Memory    : 16*1024*1024
                , ExposedPorts :{
                   '80/tcp': {}
                }
              })
              .then(function(res){
                worker.container = this.docker.getContainer(res.id);

                return worker;
              }.bind(this));
    })
    // .then(function(worker){
    //   worker.container.attach({stream: true, stdout: true, stderr: true, tty : false}, function (err, stream) {
    //     worker.container.modem.demuxStream(stream, process.stdout, process.stderr);
    //   });

    //   return worker;
    // })
    .nodeify(cb)
    ;
}

DockerPool.prototype.start = function(id, cb) {
  var worker = _.isObject(id)? id : this.workers[id];

   Promise
    .resolve(worker)
    .bind(this)
    .then(function(worker){
      if (!worker) {
        throw new Error('unknown worker');
      }

      return worker;
    })
    .then(function(worker){
      var dir   = worker.dir
        , port  = worker.port.toString()
        ;

      return Promise
              .promisify(worker.container.start, worker.container)({
                  'Binds':[
                      dir + ':/home/worker:ro'
                  ]
                , 'PortBindings':{ '80/tcp': [{ 'HostPort':  port }] }
              })
              .then(function(){
                return worker;
              });
    })
    .nodeify(cb)
    ;
}

DockerPool.prototype.kill_worker = function(id, cb) {
  // this.docker
  //       .getContainer(id)
  //       .remove({ force : true }, cb || function(){})
  //       ;
  throw new Error('not implemented');
};

DockerPool.prototype.kill_workers = function(cb) {
  Promise
    .promisify(this.docker.listContainers, this.docker)({ all : true })
    .bind(this)
    .each(function(item){
      var container = this.docker.getContainer(item.Id);

      return Promise.promisify(container.remove, container)({ force : true });
    })
    .nodeify(cb)
    ;
};

DockerPool.prototype.get_worker = function(cb) {
  return _.sample(this.workers);
};

DockerPool.prototype.size = function(cb) {
  return _.size(this.workers);
};

module.exports = DockerPool;<commit_msg>default to localhost when docker.host is undefined<commit_after>var Promise         = require('bluebird')
  , _               = require('lodash')
  , Docker          = require('dockerode')
  , config          = require('config')
  , Worker          = require('../core/worker')
  ;

function DockerPool(){
  var docker_options = undefined;

  if (config.has('docker.host') && config.get('docker.host') != undefined) {
    docker_options = {
        protocol  : config.get('docker.protocol')
      , host      : config.get('docker.host')
      , port      : config.get('docker.port')
    };
  }

  this.docker = new Docker(docker_options);
};

DockerPool.prototype._next_id = 0;
DockerPool.prototype.workers = {};

DockerPool.prototype.create_worker = function(cb) {
  var id    = this._next_id ++
    , worker = new Worker({
          dir         : config.get('worker.dir')
        , id          : id
        , protocol    : 'http'
        , host        : config.has('docker.host')? config.get('docker.host') : 'locahost'
        , port        : config.get('worker.port') + id
      })
    ;

  this.workers[id] = worker;

  cb && cb(undefined, worker);
};

DockerPool.prototype.prepare = function(id, cb) {
  var worker = _.isObject(id)? id : this.workers[id];

  Promise
    .resolve(worker)
    .bind(this)
    .then(function(worker){
      if (!worker) {
        throw new Error('unknown worker');
      }

      return worker;
    })
    .then(function(worker){
      return Promise
              .promisify(this.docker.createContainer, this.docker)({
                  Image     : 'a7medkamel/taskmill-core-dockerworker'
                , Cmd       : ['node', '/home/worker/index.js']
                , CpuShares : 128
                , Memory    : 16*1024*1024
                , ExposedPorts :{
                   '80/tcp': {}
                }
              })
              .then(function(res){
                worker.container = this.docker.getContainer(res.id);

                return worker;
              }.bind(this));
    })
    // .then(function(worker){
    //   worker.container.attach({stream: true, stdout: true, stderr: true, tty : false}, function (err, stream) {
    //     worker.container.modem.demuxStream(stream, process.stdout, process.stderr);
    //   });

    //   return worker;
    // })
    .nodeify(cb)
    ;
}

DockerPool.prototype.start = function(id, cb) {
  var worker = _.isObject(id)? id : this.workers[id];

   Promise
    .resolve(worker)
    .bind(this)
    .then(function(worker){
      if (!worker) {
        throw new Error('unknown worker');
      }

      return worker;
    })
    .then(function(worker){
      var dir   = worker.dir
        , port  = worker.port.toString()
        ;

      return Promise
              .promisify(worker.container.start, worker.container)({
                  'Binds':[
                      dir + ':/home/worker:ro'
                  ]
                , 'PortBindings':{ '80/tcp': [{ 'HostPort':  port }] }
              })
              .then(function(){
                return worker;
              });
    })
    .nodeify(cb)
    ;
}

DockerPool.prototype.kill_worker = function(id, cb) {
  // this.docker
  //       .getContainer(id)
  //       .remove({ force : true }, cb || function(){})
  //       ;
  throw new Error('not implemented');
};

DockerPool.prototype.kill_workers = function(cb) {
  Promise
    .promisify(this.docker.listContainers, this.docker)({ all : true })
    .bind(this)
    .each(function(item){
      var container = this.docker.getContainer(item.Id);

      return Promise.promisify(container.remove, container)({ force : true });
    })
    .nodeify(cb)
    ;
};

DockerPool.prototype.get_worker = function(cb) {
  return _.sample(this.workers);
};

DockerPool.prototype.size = function(cb) {
  return _.size(this.workers);
};

module.exports = DockerPool;<|endoftext|>


<commit_before>/**
 * @copyright Copyright (c) Sematext Group, Inc. - All Rights Reserved
 *
 * @licence SPM for Docker is free-to-use, proprietary software.
 * THIS IS PROPRIETARY SOURCE CODE OF Sematext Group, Inc. (Sematext)
 * This source code may not be copied, reverse engineered, or altered for any purpose.
 * This source code is to be used exclusively by users and customers of Sematext.
 * Please see the full license (found in LICENSE in this distribution) for details on its license and the licenses of its dependencies.
 */
'use strict'
var monitor = require('./dockerMonitor.js')
var Agent = require('spm-agent/lib/agent.js')
var SpmAgent = require('spm-agent')
var DockerEventForwarder = require('./dockerEventForwarder.js')
function dockerAgent () {
  var da = new Agent(
    {
      start: function (agent) {
        this.dockerListener = function (stats) {
          if (!stats) {
            return
          }
          var containerName = stats.dockerId
          if (stats.name) {
            containerName = containerName + '-' + stats.name
          }
          var metric = {
            ts: new Date().getTime(),
            type: 'container',
            filters: [stats.image, containerName],
            name: 'docker',
            value: stats.value
          }
          console.log(agent.formatLine(metric))
          agent.addMetrics(metric)
        }
        if (SpmAgent.Config.tokens.spm) {
          monitor(this.dockerListener)
        } else {
          console.log('SPM_TOKEN is missing, no metrics will be collected')
        }
      },
      stop: function () {
        // TODO: stop streaming docker stats, terminate timer
      },
      eventForwarder: new DockerEventForwarder()
    }
  )
  return da
}

module.exports = dockerAgent
<commit_msg>removed logging of metrics to console ->  spmlogs with info level<commit_after>/**
 * @copyright Copyright (c) Sematext Group, Inc. - All Rights Reserved
 *
 * @licence SPM for Docker is free-to-use, proprietary software.
 * THIS IS PROPRIETARY SOURCE CODE OF Sematext Group, Inc. (Sematext)
 * This source code may not be copied, reverse engineered, or altered for any purpose.
 * This source code is to be used exclusively by users and customers of Sematext.
 * Please see the full license (found in LICENSE in this distribution) for details on its license and the licenses of its dependencies.
 */
'use strict'
var monitor = require('./dockerMonitor.js')
var Agent = require('spm-agent/lib/agent.js')
var SpmAgent = require('spm-agent')
var DockerEventForwarder = require('./dockerEventForwarder.js')
function dockerAgent () {
  var da = new Agent(
    {
      start: function (agent) {
        this.dockerListener = function (stats) {
          if (!stats) {
            return
          }
          var containerName = stats.dockerId
          if (stats.name) {
            containerName = containerName + '-' + stats.name
          }
          var metric = {
            ts: new Date().getTime(),
            type: 'container',
            filters: [stats.image, containerName],
            name: 'docker',
            value: stats.value
          }
          SpmAgent.Logger.log('info', agent.formatLine(metric))
          agent.addMetrics(metric)
        }
        if (SpmAgent.Config.tokens.spm) {
          monitor(this.dockerListener)
        } else {
          console.log('SPM_TOKEN is missing, no metrics will be collected')
        }
      },
      stop: function () {
        // TODO: stop streaming docker stats, terminate timer
      },
      eventForwarder: new DockerEventForwarder()
    }
  )
  return da
}

module.exports = dockerAgent
<|endoftext|>


<commit_before>// Dependencies
const fs = require('fs');
const Eris = require('eris'); // https://abal.moe/Eris/docs/getting-started
const tumblrjs = require('tumblr.js'); // https://tumblr.github.io/tumblr.js/index.html
const Auth = require('./auth.json');
const Config = require('./config.json');
global.Promise = require('bluebird');

// Auth stuff
var bot = new Eris(Auth.bot_token, {
    getAllUsers: true,
    messageLimit: 0,
    maxShards: 1,
    disableEvents: {
        TYPING_START: true,
        MESSAGE_UPDATE: true,
        MESSAGE_DELETE: true,
        MESSAGE_DELETE_BULK: true,
        VOICE_STATE_UPDATE: true
    }
});
var tumblr = tumblrjs.createClient(Auth.tum_token);

// tumblr.blogPosts('').then(resp => {console.log(resp.posts[0]);}).catch(err => {console.log(err);});

// Global Vars, try keeping these few in number.
var blog;

// When bot starts set status "Playing with Luna"
// Don't judge me
bot.on("ready", () => {
	console.log(bot.user.username + " is awake! [" + bot.shards.size + "] S:" + bot.guilds.size + " U:" + bot.users.size);
	bot.editStatus("online",{"name":"with Luna"});
    tumblr.blogPosts(Config.blogName, { type: 'photo', limit: 10 })
        .then(resp => {blog = resp.posts;})
        .catch(err => {console.log(err);});
});

// Every 5 minute asynchronous
var tumblrRefresh = 5 * 60 * 1000
setInterval(()=>{
    tumblr.blogPosts(Config.blogName, { type: 'photo', limit: 10 })
        .then(resp => {blog = resp.posts;})
        .catch(err => {console.log(err);});
},tumblrRefresh);

// https://github.com/ddlr/WishBot/blob/chryssi/index.js <- reference this
bot.on("messageCreate", (msg) => {
	if( !bot.ready || msg.author.bot ) return;
	if(msg.content.includes(bot.user.mention)){
		bot.addMessageReaction(msg.channel.id, msg.id, "⚡");
		bot.createMessage(msg.channel.id, "Oh, hello!");
	}

    // SIMPLE IMPLEMENTATION FIRST BEFORE REAL IMPLEMENTATION
    if(msg.content.startsWith(Config.commandPrefix)){
        if(msg.content.substring(1).startsWith("tumblr")){
            var post = blog[0];
            bot.createMessage(msg.channel.id,{
                content:"Latest post on jykinturah-art.tumblr.com!",
                embed:{
                    title: post.blog_name,
                    description: post.summary,
                    image: {
                        url: post.photos[0].original_size.url
                    },
                    url: post.post_url
                }
            });
        }

        // **** ONLY IN DEV BRANCH PLEASE ****
        if(msg.content.substring(1).startsWith("dev ")){
            if (msg.author.id != Config.admin) bot.createMessage(msg.channel.id, "I cannot let you do that, " + msg.author.mention);
            else{
                var devCmd = msg.content.substring(5);
                if(devCmd.startsWith("tumblr")){
                    tumblr.blogPosts(devCmd.substring(7), { limit: 1 })
                        .then(resp => {
                            devPost = resp.posts[0];
                            var contentTitle = "Latest post on " + devPost.blog_name + ".tumblr.com";
                            bot.createMessage(msg.channel.id,{
                                content:contentTitle,
                                embed:{
                                    title: devPost.blog_name,
                                    description: devPost.summary,
                                    url: devPost.post_url
                                }
                            });
                        })
                        .catch(err => {
                            bot.createMessage(msg.channel.id, "Something went wrong!\n\`\`\`\n" + err + "\n\`\`\`");
                        });
                }
            }
        }
        // **** ONLY IN DEV BRANCH PLEASE ****
    }
});

bot.on("presenceUpdate", (usr) => {
    if(usr.id != Config.admin) return;
    if(usr.game == null) { bot.editStatus("online",{"name":"with Luna"}); }
    else{
        if(usr.game.name === "Adobe Photoshop") bot.editStatus("online",{"name":"with a tablet"});
        else if(usr.game.name === "with code") bot.editStatus("online",{"name":"find the bugs!"});
        else bot.editStatus("online",{"name":"with Jyky"});
    }
});

/*

## TODO ##

# Permissions #
Check by Guild (if moderation implemented)
Spam prevention

# Commands # https://github.com/abalabahaha/eris/blob/master/examples/basicCommands.js
Tumblr check (5min auto)
Tumblr check (cmd + rate limit)
Msg (check old bot)
Luna (reaction)
Poke
Uptime (native)
Say
Myid

# Optional #
Moderation tools

*/

bot.connect();<commit_msg>corrected embed in dev<commit_after>// Dependencies
const fs = require('fs');
const Eris = require('eris'); // https://abal.moe/Eris/docs/getting-started
const tumblrjs = require('tumblr.js'); // https://tumblr.github.io/tumblr.js/index.html
const Auth = require('./auth.json');
const Config = require('./config.json');
global.Promise = require('bluebird');

// Auth stuff
var bot = new Eris(Auth.bot_token, {
    getAllUsers: true,
    messageLimit: 0,
    maxShards: 1,
    disableEvents: {
        TYPING_START: true,
        MESSAGE_UPDATE: true,
        MESSAGE_DELETE: true,
        MESSAGE_DELETE_BULK: true,
        VOICE_STATE_UPDATE: true
    }
});
var tumblr = tumblrjs.createClient(Auth.tum_token);

// tumblr.blogPosts('').then(resp => {console.log(resp.posts[0]);}).catch(err => {console.log(err);});

// Global Vars, try keeping these few in number.
var blog;

// When bot starts set status "Playing with Luna"
// Don't judge me
bot.on("ready", () => {
	console.log(bot.user.username + " is awake! [" + bot.shards.size + "] S:" + bot.guilds.size + " U:" + bot.users.size);
	bot.editStatus("online",{"name":"with Luna"});
    tumblr.blogPosts(Config.blogName, { type: 'photo', limit: 10 })
        .then(resp => {blog = resp.posts;})
        .catch(err => {console.log(err);});
});

// Every 5 minute asynchronous
var tumblrRefresh = 5 * 60 * 1000
setInterval(()=>{
    tumblr.blogPosts(Config.blogName, { type: 'photo', limit: 10 })
        .then(resp => {blog = resp.posts;})
        .catch(err => {console.log(err);});
},tumblrRefresh);

// https://github.com/ddlr/WishBot/blob/chryssi/index.js <- reference this
bot.on("messageCreate", (msg) => {
	if( !bot.ready || msg.author.bot ) return;
	if(msg.content.includes(bot.user.mention)){
		bot.addMessageReaction(msg.channel.id, msg.id, "⚡");
		bot.createMessage(msg.channel.id, "Oh, hello!");
	}

    // SIMPLE IMPLEMENTATION FIRST BEFORE REAL IMPLEMENTATION
    if(msg.content.startsWith(Config.commandPrefix)){
        if(msg.content.substring(1).startsWith("tumblr")){
            var post = blog[0];
            var stri = "Latest post on " + post.blog_name + ".tumblr.com!";
            bot.createMessage(msg.channel.id,{
                content:stri,
                embed:{
                    title: post.blog_name,
                    description: post.summary,
                    image: {
                        url: post.photos[0].original_size.url
                    },
                    url: post.post_url
                }
            });
        }

        // **** ONLY IN DEV BRANCH PLEASE ****
        if(msg.content.substring(1).startsWith("dev ")){
            if (msg.author.id != Config.admin) bot.createMessage(msg.channel.id, "I cannot let you do that, " + msg.author.mention);
            else{
                var devCmd = msg.content.substring(5);
                if(devCmd.startsWith("tumblr")){
                    tumblr.blogPosts(devCmd.substring(7), { limit: 1 })
                        .then(resp => {
                            devPost = resp.posts[0];
                            var contentTitle = "Latest post on " + devPost.blog_name + ".tumblr.com";
                            bot.createMessage(msg.channel.id,{
                                content:contentTitle,
                                embed:{
                                    title: devPost.blog_name,
                                    description: devPost.summary,
                                    url: devPost.post_url
                                }
                            });
                        })
                        .catch(err => {
                            bot.createMessage(msg.channel.id, "Something went wrong!\n\`\`\`\n" + err + "\n\`\`\`");
                        });
                }
            }
        }
        // **** ONLY IN DEV BRANCH PLEASE ****
    }
});

bot.on("presenceUpdate", (usr) => {
    if(usr.id != Config.admin) return;
    if(usr.game == null) { bot.editStatus("online",{"name":"with Luna"}); }
    else{
        if(usr.game.name === "Adobe Photoshop") bot.editStatus("online",{"name":"with a tablet"});
        else if(usr.game.name === "with code") bot.editStatus("online",{"name":"find the bugs!"});
        else bot.editStatus("online",{"name":"with Jyky"});
    }
});

/*

## TODO ##

# Permissions #
Check by Guild (if moderation implemented)
Spam prevention

# Commands # https://github.com/abalabahaha/eris/blob/master/examples/basicCommands.js
Tumblr check (5min auto)
Tumblr check (cmd + rate limit)
Msg (check old bot)
Luna (reaction)
Poke
Uptime (native)
Say
Myid

# Optional #
Moderation tools

*/

bot.connect();<|endoftext|>


<commit_before>'use strict';
let path = require('path'),
  fs = require('fs'),
  filter = require('filter-files');

module.exports = function(filename) {

    const filterJsFiles = (file) => (path.extname(file) === '.js');
    const filterDirs = (file, dir) => (fs.statSync(path.resolve(dir, file)).isDirectory());
    const fileContentsByName = (scripts, file) => {
      let name = path.basename(file, '.js');
      scripts[name] = fs.readFileSync(file, 'utf8');
      return scripts;
    };

    let utilsSrc = fs.readFileSync(path.join(__dirname, 'util.js'));
    let calculateScoreSrc = fs.readFileSync(path.join(__dirname, 'calculateScore.js'));

    let categoryDirs = filter.sync(__dirname, filterDirs, false);

    let scriptsByCategory = categoryDirs.reduce((byCategory, categoryDir) => {
      let categoryName = path.basename(categoryDir);
      byCategory[categoryName] = filter.sync(categoryDir, filterJsFiles, false)
        .reduce(fileContentsByName, {});
      return byCategory;
    }, {});

    var pushResultsSrc = Object.keys(scriptsByCategory).map((categoryId) => {
      let scriptsById = scriptsByCategory[categoryId];
      let pushResultsSrc = Object.keys(scriptsById).map((scriptId) => {
        let script = scriptsById[scriptId];
        // catch errors and just add the string, good for finding errors for now
        return `try {${categoryId}Results["${scriptId}"] = ${script}} catch(err) {${categoryId}Results["${scriptId}"] = 'failure:' + err}`;

      }).join('\n');

      // info got some special treatment since it is not an advice
      // more just some intresting info
      let categoryResults = '';
      if (categoryId === 'info' || categoryId === 'timings') {
        categoryResults  = `results["${categoryId}"] = ${categoryId}Results;`;
      }
      else {
        categoryResults  =
        `results["${categoryId}"] = {};
        results["${categoryId}"].adviceList = ${categoryId}Results;`
      }

      return `
  var ${categoryId}Results = {};

  ${pushResultsSrc}

  ${categoryResults}

  `;
    }).join('\n');

    const combinedSrc = `(function() {
if (typeof window !== 'undefined') {
  ${utilsSrc}
  return (function(util) {
      var results = {};
      ${pushResultsSrc}

      ${calculateScoreSrc}

      return results;
    })(util);
  } else {
    console.error('Missing window or window document');
  }
  })();
`;

    fs.writeFileSync(filename, combinedSrc);
};
<commit_msg>include the version in the output #31<commit_after>'use strict';
let path = require('path'),
  fs = require('fs'),
  packageInfo = require('../../package'),
  filter = require('filter-files');

module.exports = function(filename) {

    const filterJsFiles = (file) => (path.extname(file) === '.js');
    const filterDirs = (file, dir) => (fs.statSync(path.resolve(dir, file)).isDirectory());
    const fileContentsByName = (scripts, file) => {
      let name = path.basename(file, '.js');
      scripts[name] = fs.readFileSync(file, 'utf8');
      return scripts;
    };

    let utilsSrc = fs.readFileSync(path.join(__dirname, 'util.js'));
    let calculateScoreSrc = fs.readFileSync(path.join(__dirname, 'calculateScore.js'));

    let categoryDirs = filter.sync(__dirname, filterDirs, false);

    let scriptsByCategory = categoryDirs.reduce((byCategory, categoryDir) => {
      let categoryName = path.basename(categoryDir);
      byCategory[categoryName] = filter.sync(categoryDir, filterJsFiles, false)
        .reduce(fileContentsByName, {});
      return byCategory;
    }, {});

    var pushResultsSrc = Object.keys(scriptsByCategory).map((categoryId) => {
      let scriptsById = scriptsByCategory[categoryId];
      let pushResultsSrc = Object.keys(scriptsById).map((scriptId) => {
        let script = scriptsById[scriptId];
        // catch errors and just add the string, good for finding errors for now
        return `try {${categoryId}Results["${scriptId}"] = ${script}} catch(err) {${categoryId}Results["${scriptId}"] = 'failure:' + err}`;

      }).join('\n');

      // info got some special treatment since it is not an advice
      // more just some intresting info
      let categoryResults = '';
      if (categoryId === 'info' || categoryId === 'timings') {
        categoryResults  = `results["${categoryId}"] = ${categoryId}Results;`;
      }
      else {
        categoryResults  =
        `results["${categoryId}"] = {};
        results["${categoryId}"].adviceList = ${categoryId}Results;`
      }

      return `
  var ${categoryId}Results = {};

  ${pushResultsSrc}

  ${categoryResults}

  `;
    }).join('\n');

    const combinedSrc = `(function() {
if (typeof window !== 'undefined') {
  ${utilsSrc}
  return (function(util) {
      var results = {};
      ${pushResultsSrc}

      ${calculateScoreSrc}
      results["version"] = "${packageInfo.version}";

      return results;
    })(util);
  } else {
    console.error('Missing window or window document');
  }
  })();
`;

    fs.writeFileSync(filename, combinedSrc);
};
<|endoftext|>