<commit_before>describe('multi-stream', function test() {
  'use strict';

  var Primus = require('primus')
    , assume = require('assume')
    , plugin = require('../')
    , http = require('http')
    , port = 1024
    , primus;

  beforeEach(function (done) {
    var server = http.createServer();
    primus = new Primus(server, { transformer: 'websockets' });

    port++;
    server.listen(port, done);
  });

  afterEach(function (done) {
    primus.destroy(done);
  });

  it('is compatible as a server-side plugin', function () {
    primus.use('multi-stream', plugin);
    primus.save(__dirname+ '/primus.js');
  });

  it('is compatible as a client-side plugin', function () {
    primus.use('multi-stream', plugin);

    var Socket = primus.Socket;
  });

  it('exposes the substream function', function (done) {
    primus.use('substream', plugin);

    primus.on('connection', function (spark) {
      assume(spark.substream).to.be.a('function');
      spark.end();
    });

    var Socket = primus.Socket
      , socket = new Socket('http://localhost:'+ port);

    assume(socket.substream).to.be.a('function');
    socket.on('end', done);
  });

  describe('communication', function () {
    beforeEach(function () {
      primus.use('substream', plugin);
    });

    it('can communicate over a substream', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo');

        foo.on('data', function (data) {
          assume(data).to.equal('foo');
          spark.end();

          done();
        });
      });

      var Socket = primus.Socket
        , socket = new Socket('http://localhost:'+ port);

      socket.on('open', function () {
        socket.substream('foo').write('foo');
      });
    });

    it('proxies the close events', function (done) {
      var ends = 0;

      primus.on('connection', function (spark) {
        var foo = spark.substream('foo');

        foo.once('end', function () {
          ends++;
        });

        spark.once('end', function () {
          ends++;

          process.nextTick(function () {
            assume(ends).to.equal(4);

            done();
          });
        });
      });

      var Socket = primus.Socket
        , socket = new Socket('http://localhost:'+ port);

      socket.on('open', function () {
        var foo = socket.substream('foo');

        foo.once('end', function () {
          ends++;
        });

        setTimeout(function () {
          socket.end();
        }, 10);
      });

      socket.once('end', function () {
        ends++;
      });
    });

    it('also receives data on the client side', function (done) {
      primus.on('connection', function (spark) {
        spark.substream('foo').write('foo');
      });

      var Socket = primus.Socket
        , socket = new Socket('http://localhost:'+ port);

      socket.on('open', function () {
        socket.substream('foo').on('data', function (msg) {
          assume(msg).to.equal('foo');
          socket.end();
          done();
        });
      });
    });

    it('doesnt confuse multiple streams', function (done) {
      primus.on('connection', function (spark) {
        ['bar', 'baz', 'foo'].forEach(function (name) {
          var stream = spark.substream('/'+ name)
            , send = 0;

          stream.on('data', function (data) {
            assume(data).to.equal(name);
          });

          (function write() {
            if (send === 10) return;

            setTimeout(function () {
              stream.write(name);

              send++; write();
            }, 10);
          })();
        });
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , count = 0;

      socket.on('open', function () {
        ['bar', 'baz', 'foo'].forEach(function (name) {
          var stream = socket.substream('/'+ name);

          stream.on('data', function (data) {
            assume(data).to.equal(name);
            stream.write(data);

            count++;

            if (count === 30) {
              socket.end();
              done();
            }
          });
        });
      });
    });

    it('only emits the events once', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo')
          , counts = 0;

        foo.on('data', function (msg) {
          assume(msg).to.equal('Hello Server');
          globalcounts++;
          counts++;

          assume(counts).to.equal(1);

          if (globalcounts > 1) setTimeout(function () {
            done();
            done = function () {};
          }, 100);
        });
      });

      var Socket = primus.Socket
        , globalcounts = 0;

      [1, 2].forEach(function () {
        var socket = new Socket('http://localhost:'+ port +'/')
          , foo = socket.substream('foo');

        foo.write('Hello Server');
      });
    });

    it('proxies readyState', function (done) {
      primus.on('connection', function (spark) {
        setTimeout(function () {
          assume(foo.readyState).to.equal(socket.readyState);
          done();

        }, 10);
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , foo = socket.substream('foo');

      assume(foo.readyState).to.equal(socket.readyState);
    });

    it('returns the same substream instance when calling with same name', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo')
          , bar = spark.substream('foo');

        assume(foo).to.equal(bar);
        done();
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , foo = socket.substream('foo')
        , bar = socket.substream('foo');

      assume(foo).to.equal(bar);
    });

    it('adds substreams as special streams property', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo');

        assume(foo).to.equal(spark.streams.foo);
        done();
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , foo = socket.substream('foo');

      assume(foo).to.equal(socket.streams.foo);
    });

    it('closes the substream when its ended on the client', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo');
        foo.write('bar');

        foo.on('end', function end() {
          spark.end();
          done();
        });
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , foo = socket.substream('foo');

      foo.on('data', function (msg) {
        if ('bar' === msg) foo.end();
      });
    });

    it('closes the substream when its ended on the server', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo');

        foo.on('data', function (msg) {
          if ('bar' === msg) foo.end();
        });
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , foo = socket.substream('foo');

      foo.write('bar');

      foo.on('end', function end() {
        socket.end();
        done();
      });
    });
  });
});
<commit_msg>[fix] make sure we clean up after our selfs<commit_after>describe('multi-stream', function test() {
  'use strict';

  var Primus = require('primus')
    , assume = require('assume')
    , plugin = require('../')
    , http = require('http')
    , port = 1024
    , primus;

  beforeEach(function (done) {
    var server = http.createServer();
    primus = new Primus(server, { transformer: 'websockets' });

    port++;
    server.listen(port, done);
  });

  afterEach(function (done) {
    primus.destroy(done);
  });

  it('is compatible as a server-side plugin', function () {
    primus.use('multi-stream', plugin);
    primus.save(__dirname+ '/primus.js');
  });

  it('is compatible as a client-side plugin', function () {
    primus.use('multi-stream', plugin);

    var Socket = primus.Socket;
  });

  it('exposes the substream function', function (done) {
    primus.use('substream', plugin);

    primus.on('connection', function (spark) {
      assume(spark.substream).to.be.a('function');
      spark.end();
    });

    var Socket = primus.Socket
      , socket = new Socket('http://localhost:'+ port);

    assume(socket.substream).to.be.a('function');
    socket.on('end', done);
  });

  describe('communication', function () {
    beforeEach(function () {
      primus.use('substream', plugin);
    });

    it('can communicate over a substream', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo');

        foo.on('data', function (data) {
          assume(data).to.equal('foo');
          spark.end();

          done();
        });
      });

      var Socket = primus.Socket
        , socket = new Socket('http://localhost:'+ port);

      socket.on('open', function () {
        socket.substream('foo').write('foo');
      });
    });

    it('proxies the close events', function (done) {
      var ends = 0;

      primus.on('connection', function (spark) {
        var foo = spark.substream('foo');

        foo.once('end', function () {
          ends++;
        });

        spark.once('end', function () {
          ends++;

          process.nextTick(function () {
            assume(ends).to.equal(4);

            done();
          });
        });
      });

      var Socket = primus.Socket
        , socket = new Socket('http://localhost:'+ port);

      socket.on('open', function () {
        var foo = socket.substream('foo');

        foo.once('end', function () {
          ends++;
        });

        setTimeout(function () {
          socket.end();
        }, 10);
      });

      socket.once('end', function () {
        ends++;
      });
    });

    it('also receives data on the client side', function (done) {
      primus.on('connection', function (spark) {
        spark.substream('foo').write('foo');
      });

      var Socket = primus.Socket
        , socket = new Socket('http://localhost:'+ port);

      socket.on('open', function () {
        socket.substream('foo').on('data', function (msg) {
          assume(msg).to.equal('foo');
          socket.end();
          done();
        });
      });
    });

    it('doesnt confuse multiple streams', function (done) {
      primus.on('connection', function (spark) {
        ['bar', 'baz', 'foo'].forEach(function (name) {
          var stream = spark.substream('/'+ name)
            , send = 0;

          stream.on('data', function (data) {
            assume(data).to.equal(name);
          });

          (function write() {
            if (send === 10) return;

            setTimeout(function () {
              stream.write(name);

              send++; write();
            }, 10);
          })();
        });
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , count = 0;

      socket.on('open', function () {
        ['bar', 'baz', 'foo'].forEach(function (name) {
          var stream = socket.substream('/'+ name);

          stream.on('data', function (data) {
            assume(data).to.equal(name);
            stream.write(data);

            count++;

            if (count === 30) {
              socket.end();
              done();
            }
          });
        });
      });
    });

    it('only emits the events once', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo')
          , counts = 0;

        foo.on('data', function (msg) {
          assume(msg).to.equal('Hello Server');
          globalcounts++;
          counts++;

          assume(counts).to.equal(1);

          if (globalcounts > 1) setTimeout(function () {
            done();
            done = function () {};
          }, 100);
        });
      });

      var Socket = primus.Socket
        , globalcounts = 0;

      [1, 2].forEach(function () {
        var socket = new Socket('http://localhost:'+ port +'/')
          , foo = socket.substream('foo');

        foo.write('Hello Server');
      });
    });

    it('proxies readyState', function (done) {
      primus.on('connection', function (spark) {
        setTimeout(function () {
          assume(foo.readyState).to.equal(socket.readyState);
          done();

        }, 10);
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , foo = socket.substream('foo');

      assume(foo.readyState).to.equal(socket.readyState);
    });

    it('returns the same substream instance when calling with same name', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo')
          , bar = spark.substream('foo');

        assume(foo).to.equal(bar);
        done();
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , foo = socket.substream('foo')
        , bar = socket.substream('foo');

      assume(foo).to.equal(bar);
    });

    it('adds substreams as special streams property', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo');

        assume(foo).to.equal(spark.streams.foo);
        done();
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , foo = socket.substream('foo');

      assume(foo).to.equal(socket.streams.foo);
    });

    it('closes the substream when its ended on the client', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo');
        foo.write('bar');

        foo.on('end', function end() {
          spark.end();
          done();
        });
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , foo = socket.substream('foo');

      foo.on('data', function (msg) {
        if ('bar' === msg) foo.end();
      });
    });

    it('closes the substream when its ended on the server', function (done) {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo');

        foo.on('data', function (msg) {
          if ('bar' === msg) foo.end();
        });
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , foo = socket.substream('foo');

      foo.write('bar');

      foo.on('end', function end() {
        socket.end();
        done();
      });
    });

    it('removes substreams from the streams object on end', function () {
      primus.on('connection', function (spark) {
        var foo = spark.substream('foo');

        foo.on('data', function (msg) {
          if ('bar' === msg) foo.end();
        });

        foo.on('end', function () {
          assume(spark.streams.foo).to.be.undefined();
        });
      });

      var socket = new primus.Socket('http://localhost:'+ port)
        , foo = socket.substream('foo');

      foo.write('bar');

      foo.on('end', function end() {
        socket.end();
        assume(socket.streams.foo).to.be.undefined();
        done();
      });
    });
  });
});
<|endoftext|>


<commit_before>/**
 * WordPress dependencies
 */
import { activatePlugin, deactivatePlugin, visitAdminPage } from '@wordpress/e2e-test-utils';

/**
 * Internal dependencies
 */
import {
	setAuthToken,
	setClientConfig,
	setSearchConsoleProperty,
	setSiteVerification,
} from '../utils';

describe( 'Plugin Reset', () => {
	beforeAll( async () => {
		await activatePlugin( 'e2e-tests-proxy-credentials-plugin' );
		await setClientConfig();
		await setAuthToken();
		await setSiteVerification();
		await setSearchConsoleProperty();
	} );

	beforeEach( async () => {
		await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' );
		await expect( page ).toMatchElement( '.googlesitekit-page-header__title', { text: 'Settings' } );

		await page.waitForSelector( 'button.mdc-tab' );

		// Click on Admin Settings Tab.
		await expect( page ).toClick( 'button.mdc-tab', { text: 'Admin Settings' } );
		await page.waitForSelector( '.googlesitekit-settings-module__footer' );
	} );

	afterAll( async () => {
		await deactivatePlugin( 'e2e-tests-proxy-credentials-plugin' );
	} );

	it( 'displays a confirmation dialog when clicking the "Reset Site Kit" link', async () => {
		await expect( page ).toClick( 'button.googlesitekit-cta-link', { text: 'Reset Site Kit' } );
		await page.waitForSelector( '.mdc-dialog--open .mdc-button' );

		await expect( page ).toMatchElement( '.mdc-dialog--open .mdc-button', { text: 'Reset' } );
	} );

	it( 'dismisses the reset confirmation dialog when clicking "Cancel"', async () => {
		await expect( page ).toClick( 'button.googlesitekit-cta-link', { text: 'Reset Site Kit' } );
		await page.waitForSelector( '.mdc-dialog--open button' );

		await expect( page ).toClick( '.mdc-dialog--open button', { text: 'Cancel' } );
	} );

	it( 'disconnects Site Kit by clicking the "Reset" button in the confirmation dialog', async () => {
		await page.waitForSelector( 'button.googlesitekit-cta-link' );
		await expect( page ).toClick( 'button.googlesitekit-cta-link', { text: 'Reset Site Kit' } );
		await page.waitForSelector( '.mdc-dialog--open .mdc-button' );

		await Promise.all( [
			page.waitForNavigation(),
			expect( page ).toClick( '.mdc-dialog--open .mdc-button', { text: 'Reset' } ),
		] );

		// Ensure we're on the first step.
		await expect( page ).toMatchElement( '.googlesitekit-wizard-progress-step__number--inprogress', { text: '1' } );
	} );
} );
<commit_msg>Confirm after reset we're sent to the setup page.<commit_after>/**
 * WordPress dependencies
 */
import { activatePlugin, deactivatePlugin, visitAdminPage } from '@wordpress/e2e-test-utils';

/**
 * Internal dependencies
 */
import {
	setAuthToken,
	setClientConfig,
	setSearchConsoleProperty,
	setSiteVerification,
} from '../utils';

describe( 'Plugin Reset', () => {
	beforeAll( async () => {
		await activatePlugin( 'e2e-tests-proxy-credentials-plugin' );
		await setClientConfig();
		await setAuthToken();
		await setSiteVerification();
		await setSearchConsoleProperty();
	} );

	beforeEach( async () => {
		await visitAdminPage( 'admin.php', 'page=googlesitekit-settings' );
		await expect( page ).toMatchElement( '.googlesitekit-page-header__title', { text: 'Settings' } );

		await page.waitForSelector( 'button.mdc-tab' );

		// Click on Admin Settings Tab.
		await expect( page ).toClick( 'button.mdc-tab', { text: 'Admin Settings' } );
		await page.waitForSelector( '.googlesitekit-settings-module__footer' );
	} );

	afterAll( async () => {
		await deactivatePlugin( 'e2e-tests-proxy-credentials-plugin' );
	} );

	it( 'displays a confirmation dialog when clicking the "Reset Site Kit" link', async () => {
		await expect( page ).toClick( 'button.googlesitekit-cta-link', { text: 'Reset Site Kit' } );
		await page.waitForSelector( '.mdc-dialog--open .mdc-button' );

		await expect( page ).toMatchElement( '.mdc-dialog--open .mdc-button', { text: 'Reset' } );
	} );

	it( 'dismisses the reset confirmation dialog when clicking "Cancel"', async () => {
		await expect( page ).toClick( 'button.googlesitekit-cta-link', { text: 'Reset Site Kit' } );
		await page.waitForSelector( '.mdc-dialog--open button' );

		await expect( page ).toClick( '.mdc-dialog--open button', { text: 'Cancel' } );
	} );

	it( 'disconnects Site Kit by clicking the "Reset" button in the confirmation dialog', async () => {
		await page.waitForSelector( 'button.googlesitekit-cta-link' );
		await expect( page ).toClick( 'button.googlesitekit-cta-link', { text: 'Reset Site Kit' } );
		await page.waitForSelector( '.mdc-dialog--open .mdc-button' );

		await Promise.all( [
			page.waitForNavigation(),
			expect( page ).toClick( '.mdc-dialog--open .mdc-button', { text: 'Reset' } ),
		] );

		// Ensure we're on the setup page
		await expect( page ).toMatchElement( '.googlesitekit-start-setup', { text: 'Start setup' } );
	} );
} );
<|endoftext|>


<commit_before>/*jslint node: true, nomen: true, white: true, unparam: true*/
/*!
 * Sitegear3
 * Copyright(c) 2014 Ben New, Sitegear.org
 * MIT Licensed
 */

(function (_, path, connect, express, redis, mergeDescriptors, utils, defaults) {
	"use strict";

	// Expose the application factory method and its "public methods"
	module.exports = function () {
		var app = express();
		app._express_init = app.init;
		app.init = function (settings) {
			app._express_init();
			app.settings = _.merge({}, app.settings, defaults, settings);
			app.controllers = utils.loadPathAsGetters(path.join(__dirname, 'controllers'));
			app.redis = redis.createClient();
			app.redis.on('error', function (err) {
				console.log('Error from redis: ' + err);
			});
			return app;
		};
		app.setupRoutes = function () {
			app.get('/', app.controllers.default().page());
			app.get('/about', app.controllers.default().page());
			app.get('/about/board', app.controllers.default().page());
			app.get('/contact', app.controllers.default().page());
//			app.post('/contact', app.controllers.forms().form('contact'));
			app.get('/contact/thankyou', app.controllers.default().page());
			return app;
		};
		app.start = function () {
			// TODO Configurable http / https
			app.listen(app.settings.server.port);
			return app;
		};
		return app;
	};

	// Auto-load middleware with getters.
	utils.loadPathAsGetters(module.exports, path.join(__dirname, 'middleware'));

	// Merge middleware from connect into the exported namespace (this is copied from express.js).
	mergeDescriptors(module.exports, connect.middleware);

}(require('lodash'), require('path'), require('connect'), require('express'), require('redis'), require('merge-descriptors'), require('./utils'), require('./defaults.json')));
<commit_msg>Use express router, with statically-defined routes for now. Create default page controller, which renders the page specified by the URL.<commit_after>/*jslint node: true, nomen: true, white: true, unparam: true*/
/*!
 * Sitegear3
 * Copyright(c) 2014 Ben New, Sitegear.org
 * MIT Licensed
 */

(function (_, path, connect, express, redis, mergeDescriptors, utils, defaults) {
	"use strict";

	// Expose the application factory method and its "public methods"
	module.exports = function () {
		var app = express();
		app._express_init = app.init;
		app.init = function (settings) {
			app._express_init();
			app.settings = _.merge({}, app.settings, defaults, settings);
			app.controllers = utils.loadPathAsGetters(path.join(__dirname, 'controllers'));
			app.redis = redis.createClient();
			app.redis.on('error', function (err) {
				console.log('Error from redis: ' + err);
			});
			return app;
		};
		app.setupRoutes = function () {
			app.get('/', app.controllers.default(app).page());
			app.get('/about', app.controllers.default(app).page());
			app.get('/about/board', app.controllers.default(app).page());
			app.get('/contact', app.controllers.default(app).page());
//			app.post('/contact', app.controllers.forms().form('contact'));
			app.get('/contact/thankyou', app.controllers.default(app).page());
			return app;
		};
		app.start = function () {
			// TODO Configurable http / https
			app.listen(app.settings.server.port);
			return app;
		};
		app.dispose = function () {
			// TODO Stop the http listener
			app.redis.end();
		};
		return app;
	};

	// Auto-load middleware with getters.
	utils.loadPathAsGetters(module.exports, path.join(__dirname, 'middleware'));

	// Merge middleware from connect into the exported namespace (this is copied from express.js).
	mergeDescriptors(module.exports, connect.middleware);

}(require('lodash'), require('path'), require('connect'), require('express'), require('redis'), require('merge-descriptors'), require('./utils'), require('./defaults.json')));
<|endoftext|>


<commit_before>'use strict';

const Promise = require('bluebird'),
  moment = require('moment'),
  log = require('intel').getLogger('sitespeedio'),
  intel = require('intel'),
  os = require('os'),
  process = require('process'),
  logging = require('./core/logging'),
  toArray = require('./support/util').toArray,
  pullAll = require('lodash.pullall'),
  union = require('lodash.union'),
  messageMaker = require('./support/messageMaker'),
  filterRegistry = require('./support/filterRegistry'),
  statsHelpers = require('./support/statsHelpers'),
  packageInfo = require('../package');

const QueueHandler = require('./core/queueHandler'),
  resultsStorage = require('./core/resultsStorage'),
  loader = require('./core/pluginLoader'),
  urlSource = require('./core/url-source');

const budgetResult = {
  working: {},
  failing: {}
};

function hasFunctionFilter(functionName) {
  return obj => typeof obj[functionName] === 'function';
}

function runOptionalFunction(objects, fN) {
  // NOTE: note slicing due to https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
  let args = new Array(arguments.length - 2);
  for (let i = 2; i < arguments.length; i++) {
    args[i - 2] = arguments[i];
  }
  return Promise.resolve(objects)
    .filter(hasFunctionFilter(fN))
    .map(plugin => Promise.resolve(plugin[fN].apply(plugin, args)));
}

module.exports = {
  run(options) {
    const url = options.urls[0];
    const timestamp = moment();

    if (options.utc) {
      timestamp.utc();
    }

    const { storageManager, resultUrls } = resultsStorage(
      url,
      timestamp,
      options.outputFolder,
      options.resultBaseURL
    );

    return storageManager
      .createDirectory('logs')
      .then(logDir => {
        logging.configure(options, logDir);
      })
      .then(() => {
        if (log.isEnabledFor(log.VERBOSE)) {
          Promise.longStackTraces();
        }
        log.info(
          'Versions OS: %s nodejs: %s sitespeed.io: %s browsertime: %s coach: %s',
          os.platform() + ' ' + os.release(),
          process.version,
          packageInfo.version,
          packageInfo.dependencies.browsertime,
          packageInfo.dependencies.webcoach
        );
        log.verbose('Config options %s', JSON.stringify(options));
      })
      .then(() => {
        return loader.parsePluginNames(options);
      })
      .then(pluginNames => {
        const plugins = options.plugins;
        if (plugins) {
          if (plugins.disable) {
            log.warn(
              '--plugins.disable is deprecated, use plugins.remove instead.'
            );
            plugins.remove = plugins.disable;
          }
          if (plugins.load) {
            log.warn('--plugins.load is deprecated, use plugins.add instead.');
            plugins.add = plugins.load;
          }

          pullAll(pluginNames, toArray(plugins.remove));
          pluginNames = union(pluginNames, toArray(plugins.add));

          if (plugins.list) {
            log.info(
              'The following plugins are enabled: %s',
              pluginNames.join(', ')
            );
          }
        }
        return pluginNames;
      })
      .then(pluginNames => {
        return loader.loadPlugins(pluginNames).then(plugins => {
          let urlSources = [urlSource];
          const allPlugins = urlSources.concat(plugins),
            queueHandler = new QueueHandler(plugins, options);

          const context = {
            storageManager,
            resultUrls,
            timestamp,
            budget: budgetResult,
            name: url,
            log,
            intel,
            messageMaker,
            statsHelpers,
            filterRegistry
          };
          return runOptionalFunction(allPlugins, 'open', context, options)
            .then(() => queueHandler.run(urlSources))
            .tap(errors =>
              runOptionalFunction(allPlugins, 'close', options, errors)
            );
        });
      })
      .then(errors => {
        log.info('Finished analysing %s', url);
        if (resultUrls.hasBaseUrl()) {
          log.info('Find the result at %s', resultUrls.reportSummaryUrl());
        }

        if (options.summary && options.summary.out) {
          console.log(options.summary.out); // eslint-disable-line no-console
        }
        return {
          errors,
          budgetResult
        };
      })
      .catch(err => {
        log.error(err);
        throw err;
      });
  }
};
<commit_msg>log the options readable<commit_after>'use strict';

const Promise = require('bluebird'),
  moment = require('moment'),
  log = require('intel').getLogger('sitespeedio'),
  intel = require('intel'),
  os = require('os'),
  process = require('process'),
  logging = require('./core/logging'),
  toArray = require('./support/util').toArray,
  pullAll = require('lodash.pullall'),
  union = require('lodash.union'),
  messageMaker = require('./support/messageMaker'),
  filterRegistry = require('./support/filterRegistry'),
  statsHelpers = require('./support/statsHelpers'),
  packageInfo = require('../package');

const QueueHandler = require('./core/queueHandler'),
  resultsStorage = require('./core/resultsStorage'),
  loader = require('./core/pluginLoader'),
  urlSource = require('./core/url-source');

const budgetResult = {
  working: {},
  failing: {}
};

function hasFunctionFilter(functionName) {
  return obj => typeof obj[functionName] === 'function';
}

function runOptionalFunction(objects, fN) {
  // NOTE: note slicing due to https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
  let args = new Array(arguments.length - 2);
  for (let i = 2; i < arguments.length; i++) {
    args[i - 2] = arguments[i];
  }
  return Promise.resolve(objects)
    .filter(hasFunctionFilter(fN))
    .map(plugin => Promise.resolve(plugin[fN].apply(plugin, args)));
}

module.exports = {
  run(options) {
    const url = options.urls[0];
    const timestamp = moment();

    if (options.utc) {
      timestamp.utc();
    }

    const { storageManager, resultUrls } = resultsStorage(
      url,
      timestamp,
      options.outputFolder,
      options.resultBaseURL
    );

    return storageManager
      .createDirectory('logs')
      .then(logDir => {
        logging.configure(options, logDir);
      })
      .then(() => {
        if (log.isEnabledFor(log.VERBOSE)) {
          Promise.longStackTraces();
        }
        log.info(
          'Versions OS: %s nodejs: %s sitespeed.io: %s browsertime: %s coach: %s',
          os.platform() + ' ' + os.release(),
          process.version,
          packageInfo.version,
          packageInfo.dependencies.browsertime,
          packageInfo.dependencies.webcoach
        );
        log.verbose('Config options: %:2j', options);
      })
      .then(() => {
        return loader.parsePluginNames(options);
      })
      .then(pluginNames => {
        const plugins = options.plugins;
        if (plugins) {
          if (plugins.disable) {
            log.warn(
              '--plugins.disable is deprecated, use plugins.remove instead.'
            );
            plugins.remove = plugins.disable;
          }
          if (plugins.load) {
            log.warn('--plugins.load is deprecated, use plugins.add instead.');
            plugins.add = plugins.load;
          }

          pullAll(pluginNames, toArray(plugins.remove));
          pluginNames = union(pluginNames, toArray(plugins.add));

          if (plugins.list) {
            log.info(
              'The following plugins are enabled: %s',
              pluginNames.join(', ')
            );
          }
        }
        return pluginNames;
      })
      .then(pluginNames => {
        return loader.loadPlugins(pluginNames).then(plugins => {
          let urlSources = [urlSource];
          const allPlugins = urlSources.concat(plugins),
            queueHandler = new QueueHandler(plugins, options);

          const context = {
            storageManager,
            resultUrls,
            timestamp,
            budget: budgetResult,
            name: url,
            log,
            intel,
            messageMaker,
            statsHelpers,
            filterRegistry
          };
          return runOptionalFunction(allPlugins, 'open', context, options)
            .then(() => queueHandler.run(urlSources))
            .tap(errors =>
              runOptionalFunction(allPlugins, 'close', options, errors)
            );
        });
      })
      .then(errors => {
        log.info('Finished analysing %s', url);
        if (resultUrls.hasBaseUrl()) {
          log.info('Find the result at %s', resultUrls.reportSummaryUrl());
        }

        if (options.summary && options.summary.out) {
          console.log(options.summary.out); // eslint-disable-line no-console
        }
        return {
          errors,
          budgetResult
        };
      })
      .catch(err => {
        log.error(err);
        throw err;
      });
  }
};
<|endoftext|>


<commit_before>'use strict';

const Promise = require('bluebird'),
  moment = require('moment'),
  log = require('intel'),
  os = require('os'),
  process = require('process'),
  logging = require('../lib/support/logging'),
  difference = require('lodash.difference'),
  merge = require('lodash.merge'),
  pullAll = require('lodash.pullall'),
  DataCollection = require('./support/dataCollection'),
  browsertimeConfig = require('./plugins/browsertime').config,
  webpagetestConfig = require('./plugins/webpagetest').config,
  packageInfo = require('../package');

const QueueHandler = require('./support/queueHandler'),
  StorageManager = require('./support/storageManager'),
  loader = require('./support/pluginLoader'),
  urlSource = require('./support/url-source');

const budgetResult = {
  working: {},
  failing: {}
};

function hasFunctionFilter(functionName) {
  return ((obj) => (typeof obj[functionName] === 'function'));
}

function allInArray(sampleArray, referenceArray) {
  return difference(sampleArray, referenceArray).length === 0;
}

function runOptionalFunction(objects, fN) {
  // NOTE: note slicing due to https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
  let args = new Array(arguments.length - 2);
  for (let i = 2; i < arguments.length; i++) {
    args[i - 2] = arguments[i];
  }
  return Promise.resolve(objects)
    .filter(hasFunctionFilter(fN))
    .map((plugin) => Promise.resolve(plugin[fN].apply(plugin, args)));
}

module.exports = {
  run(options) {
    const url = options.urls[0];
    const timestamp = moment();

    if (options.utc) {
      timestamp.utc();
    }

    const storageManager = new StorageManager(url, timestamp, options);
    const dataCollection = new DataCollection();

    return storageManager.createDataDir('logs').then((logDir) => {
      logging.configure(options, logDir);
    }).then(() => {
      if (log.isEnabledFor(log.VERBOSE)) {
        Promise.longStackTraces();
      }
      log.info('Versions OS: %s nodejs: %s sitespeed.io: %s browsertime: %s coach: %s', os.platform() + ' ' + os.release(), process.version, packageInfo.version, packageInfo.dependencies.browsertime, packageInfo.dependencies.webcoach);
    }).then(() => {
      return loader.parsePluginNames(options)
    }).
    then((pluginNames) => {
        // remoce the disabled plugins
        let disabledPlugins = options.plugins && options.plugins.disable ? options.plugins.disable : [];
        pullAll(pluginNames, Array.isArray(disabledPlugins) ? disabledPlugins : [disabledPlugins]);

        // add extra plugins
        let addedPlugins = options.plugins && options.plugins.load ? options.plugins.load : [];
        pluginNames = pluginNames.concat(addedPlugins);

        if (options.plugins && options.plugins.list) {
          log.info('The following plugins is enabled: %s', pluginNames);
        }
        // if we run without cli, we still want the default options
        // in options to use it in output
        if (allInArray(['browsertime'], pluginNames)) {
          options.browsertime = merge({}, browsertimeConfig, options.browsertime);
        }
        if (allInArray(['webpagetest'], pluginNames)) {
          options.webpagetest = merge({}, webpagetestConfig, options.webpagetest);
        }
        if (allInArray(['browsertime', 'coach'], pluginNames)) {
          options.browsertime = merge({}, options.browsertime, {
            coach: true
          });
        }
        if (allInArray(['browsertime', 'screenshot'], pluginNames)) {
          options.browsertime = merge({}, options.browsertime, {
            screenshot: true
          });
        }
        return pluginNames;
      })
      .then((pluginNames) => {

        return loader.loadPlugins(pluginNames)
          .then((plugins) => {

            let urlSources = [urlSource];

            const allPlugins = urlSources.concat(plugins),
              queueHandler = new QueueHandler(plugins, options);

            return runOptionalFunction(allPlugins, 'open', {
                storageManager,
                dataCollection,
                timestamp,
                budget: budgetResult
              }, options)
              .then(() => runOptionalFunction(allPlugins, 'postOpen', options))
              .then(() => queueHandler.run(urlSources))
              .tap((errors) => runOptionalFunction(allPlugins, 'close', options, errors));
          })
      })
      .then((errors) => {
        log.info('Finished analysing %s', url);
        if (options.summary && options.summary.out) {
          console.log(options.summary.out); // eslint-disable-line no-console
        }
        return {
          errors,
          budgetResult
        };
      })
      .catch((err) => {
        log.error(err);
        throw err;
      })
  }
}
<commit_msg>pass the configured log in the context<commit_after>'use strict';

const Promise = require('bluebird'),
  moment = require('moment'),
  log = require('intel'),
  os = require('os'),
  process = require('process'),
  logging = require('../lib/support/logging'),
  difference = require('lodash.difference'),
  merge = require('lodash.merge'),
  pullAll = require('lodash.pullall'),
  DataCollection = require('./support/dataCollection'),
  browsertimeConfig = require('./plugins/browsertime').config,
  webpagetestConfig = require('./plugins/webpagetest').config,
  packageInfo = require('../package');

const QueueHandler = require('./support/queueHandler'),
  StorageManager = require('./support/storageManager'),
  loader = require('./support/pluginLoader'),
  urlSource = require('./support/url-source');

const budgetResult = {
  working: {},
  failing: {}
};

function hasFunctionFilter(functionName) {
  return ((obj) => (typeof obj[functionName] === 'function'));
}

function allInArray(sampleArray, referenceArray) {
  return difference(sampleArray, referenceArray).length === 0;
}

function runOptionalFunction(objects, fN) {
  // NOTE: note slicing due to https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments
  let args = new Array(arguments.length - 2);
  for (let i = 2; i < arguments.length; i++) {
    args[i - 2] = arguments[i];
  }
  return Promise.resolve(objects)
    .filter(hasFunctionFilter(fN))
    .map((plugin) => Promise.resolve(plugin[fN].apply(plugin, args)));
}

module.exports = {
  run(options) {
    const url = options.urls[0];
    const timestamp = moment();

    if (options.utc) {
      timestamp.utc();
    }

    const storageManager = new StorageManager(url, timestamp, options);
    const dataCollection = new DataCollection();

    return storageManager.createDataDir('logs').then((logDir) => {
      logging.configure(options, logDir);
    }).then(() => {
      if (log.isEnabledFor(log.VERBOSE)) {
        Promise.longStackTraces();
      }
      log.info('Versions OS: %s nodejs: %s sitespeed.io: %s browsertime: %s coach: %s', os.platform() + ' ' + os.release(), process.version, packageInfo.version, packageInfo.dependencies.browsertime, packageInfo.dependencies.webcoach);
    }).then(() => {
      return loader.parsePluginNames(options)
    }).
    then((pluginNames) => {
        // remoce the disabled plugins
        let disabledPlugins = options.plugins && options.plugins.disable ? options.plugins.disable : [];
        pullAll(pluginNames, Array.isArray(disabledPlugins) ? disabledPlugins : [disabledPlugins]);

        // add extra plugins
        let addedPlugins = options.plugins && options.plugins.load ? options.plugins.load : [];
        pluginNames = pluginNames.concat(addedPlugins);

        if (options.plugins && options.plugins.list) {
          log.info('The following plugins is enabled: %s', pluginNames);
        }
        // if we run without cli, we still want the default options
        // in options to use it in output
        if (allInArray(['browsertime'], pluginNames)) {
          options.browsertime = merge({}, browsertimeConfig, options.browsertime);
        }
        if (allInArray(['webpagetest'], pluginNames)) {
          options.webpagetest = merge({}, webpagetestConfig, options.webpagetest);
        }
        if (allInArray(['browsertime', 'coach'], pluginNames)) {
          options.browsertime = merge({}, options.browsertime, {
            coach: true
          });
        }
        if (allInArray(['browsertime', 'screenshot'], pluginNames)) {
          options.browsertime = merge({}, options.browsertime, {
            screenshot: true
          });
        }
        return pluginNames;
      })
      .then((pluginNames) => {

        return loader.loadPlugins(pluginNames)
          .then((plugins) => {

            let urlSources = [urlSource];

            const allPlugins = urlSources.concat(plugins),
              queueHandler = new QueueHandler(plugins, options);

            return runOptionalFunction(allPlugins, 'open', {
                storageManager,
                dataCollection,
                timestamp,
                budget: budgetResult,
                log
              }, options)
              .then(() => runOptionalFunction(allPlugins, 'postOpen', options))
              .then(() => queueHandler.run(urlSources))
              .tap((errors) => runOptionalFunction(allPlugins, 'close', options, errors));
          })
      })
      .then((errors) => {
        log.info('Finished analysing %s', url);
        if (options.summary && options.summary.out) {
          console.log(options.summary.out); // eslint-disable-line no-console
        }
        return {
          errors,
          budgetResult
        };
      })
      .catch((err) => {
        log.error(err);
        throw err;
      })
  }
}
<|endoftext|>


<commit_before>module.exports = ST;
var Ship       = require('./ship.js')
var Asteroid   = require('./asteroid.js')
var Laser      = require('./laser.js')
var Shield     = require('./shield.js')
var Mine       = require('./mine.js')

function ST (canvas, context, game) {
    this.canvas    = canvas;
    this.context   = context;
    this.game      = game;
    this.ship      = new Ship(this.canvas.width/2, this.canvas.height/2, 10, 10, context, this);
    this.asteroids = [];
    this.lasers    = [];
    this.shields   = [];
    this.mines     = [];
    this.initialAsteroids(game.numberOfAsteroids);
};

ST.prototype.drawAll = function () {
    this.detectShipCollision();
    this.detectSides();
    this.ship.moveShip().draw();
    this.drawAsteroids();
    this.drawLasers();
    this.drawMines();
    this.drawShield(this.ship);
    this.game.updateScore();
    this.game.updateLives();
    this.ship.flames();
    this.ship.death();
};

ST.prototype.initialAsteroids = function (numberOfAsteroids) {
    for (var i = 0; i < numberOfAsteroids; i++) {
        this.asteroids.push(new Asteroid(getRandom(0,this.canvas.width),getRandom(0,this.canvas.width),getRandom(20,50),getRandom(20,50),this.context,this.game.asteroidVelocity));
    }
};

ST.prototype.drawAsteroids = function () {
    if (this.asteroids.length === 0) {
        this.game.levelUp();
    } else {
        this.asteroids.forEach(function (asteroid) {
            asteroid.move().draw();
        })
    }
};

ST.prototype.drawLasers = function () {
    var spaceTime = this;
    if (this.lasers.length > 0) {
        this.lasers.forEach(function (laser) {
            laser.draw();
            spaceTime.detectLaserCollision(laser);
        })
    }
};

ST.prototype.drawMines = function () {
    var spaceTime = this;
    if (this.mines.length > 0) {
        this.mines.forEach(function (mine) {
            mine.draw();
            spaceTime.detectLaserCollision(mine);
        })
    }
};

ST.prototype.drawShield = function (ship) {
    var spaceTime = this;
    if (this.shields.length > 0) {
        this.shields.forEach(function (shield) {
            shield.draw(ship);
            spaceTime.detectShieldCollision(shield);
        })
    }
};

ST.prototype.fireLaser = function () {
    this.lasers.push(new Laser(this.ship, this.context));
};

ST.prototype.activeShield = function () {
    this.shields.push(new Shield(this.ship, this.context));
};

ST.prototype.layMine = function () {
    this.mines.push(new Mine(this.ship, this.context));
};

ST.prototype.detectLaserCollision = function (laser) {
    var spaceTime = this;
    this.asteroids.forEach( function (asteroid) {
        if (asteroidCollidesWith(laser, asteroid)) {
            asteroid.hit_count += 1;
            if(asteroid.hit_count === 3) {
                spaceTime.asteroids = spaceTime.asteroids.filter(function (a) {
                    return a !== asteroid;
                });
                if (asteroid.width > 30) {
                    spaceTime.asteroids.push(new Asteroid(asteroid.x, asteroid.y, asteroid.width / 2, asteroid.height / 2, spaceTime.context, spaceTime.game.asteroidVelocity));
                    spaceTime.asteroids.push(new Asteroid(asteroid.x + asteroid.width / 2, asteroid.y + asteroid.height / 2, asteroid.width / 2, asteroid.height / 2, spaceTime.context, spaceTime.game.asteroidVelocity));
                }
            }
            spaceTime.lasers = spaceTime.lasers.filter(function (l) {
                return l !== laser;
            });
            spaceTime.game.scorePoints(asteroid);
        }
    });
};

ST.prototype.detectShieldCollision = function (shield) {
    var spaceTime = this;
    this.asteroids.forEach( function (asteroid) {
        if (shieldCollidesWith(shield, asteroid)) {
            spaceTime.asteroids = spaceTime.asteroids.filter(function (a) {
                return a !== asteroid;
            });
            spaceTime.shields = spaceTime.shields.filter(function (s) {
                return s !== shield;
            });
            spaceTime.game.scorePoints(asteroid);
        }
    });
};

ST.prototype.detectShipCollision = function () {
    var ship = this.ship;
    var spaceTime = this;

    this.asteroids.forEach( function (asteroid) {
        if (asteroidCollidesWith(ship, asteroid)) {
            spaceTime.asteroids = spaceTime.asteroids.filter(function (a) {
                return a !== asteroid;
            });
            spaceTime.ship.dead = true;
            spaceTime.game.die();
            setTimeout(function() {
                spaceTime.ship.dead = false;
                ship.x = spaceTime.canvas.width/2;
                ship.y = spaceTime.canvas.height/2;
                ship.velocity = 0;
            }, 300);

        }
    });
};

ST.prototype.detectSides = function () {
    var spaceTime = this;
    var ship = this.ship;

    this.asteroids.forEach( function (asteroid) {
        if(asteroid.x > spaceTime.canvas.width) {
            asteroid.x -= spaceTime.canvas.width;
        }
        else if(asteroid.x < 0) {
            asteroid.x += spaceTime.canvas.width;
        }
        else if(asteroid.y > spaceTime.canvas.height) {
            asteroid.y -= spaceTime.canvas.height;
        }
        else if(asteroid.y < 0) {
            asteroid.y += spaceTime.canvas.height;
        }
    });

    if(ship.x + ship.width > this.canvas.width) {
        ship.x -= this.canvas.width;
    }
    else if(ship.x - ship.width < 0) {
        ship.x += this.canvas.width;
    }
    else if(ship.y > this.canvas.height) {
        ship.y -= this.canvas.height;
    }
    else if(ship.y < 0) {
        ship.y += this.canvas.height;
    }
};

function asteroidCollidesWith (object, asteroid) {
    if(object.y <= asteroid.y + asteroid.height && object.y >= asteroid.y) {
        if(object.x <= asteroid.x + asteroid.width && object.x >= asteroid.x){
            return true
        }
    }
}

function shieldCollidesWith (object, asteroid) {
    var distX = Math.abs(object.x - (asteroid.x + asteroid.width/2));
    var distY = Math.abs(object.y - (asteroid.y + asteroid.height/2));

    if (distX > (asteroid.width/2 + object.radius)) { return false; }
    if (distY > (asteroid.height/2 + object.radius)) { return false; }

    if (distX <= (asteroid.width/2)) { return true; }
    if (distY <= (asteroid.height/2)) { return true; }
}

function getRandom(min,max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}<commit_msg>Set scope as 'this' in 'forEach' methods<commit_after>module.exports = ST;
var Ship       = require('./ship.js')
var Asteroid   = require('./asteroid.js')
var Laser      = require('./laser.js')
var Shield     = require('./shield.js')
var Mine       = require('./mine.js')

function ST (canvas, context, game) {
    this.canvas    = canvas;
    this.context   = context;
    this.game      = game;
    this.ship      = new Ship(this.canvas.width/2, this.canvas.height/2, 10, 10, context, this);
    this.asteroids = [];
    this.lasers    = [];
    this.shields   = [];
    this.mines     = [];
    this.initialAsteroids(game.numberOfAsteroids);
};

ST.prototype.drawAll = function () {
    this.detectShipCollision();
    this.detectSides();
    this.ship.moveShip().draw();
    this.drawAsteroids();
    this.drawLasers();
    this.drawMines();
    this.drawShield(this.ship);
    this.game.updateScore();
    this.game.updateLives();
    this.ship.flames();
    this.ship.death();
};

ST.prototype.initialAsteroids = function (numberOfAsteroids) {
    for (var i = 0; i < numberOfAsteroids; i++) {
        this.asteroids.push(new Asteroid(getRandom(0,this.canvas.width),getRandom(0,this.canvas.width),getRandom(20,50),getRandom(20,50),this.context,this.game.asteroidVelocity));
    }
};

ST.prototype.drawAsteroids = function () {
    if (this.asteroids.length === 0) {
        this.game.levelUp();
    } else {
        this.asteroids.forEach(function (asteroid) {
            asteroid.move().draw();
        })
    }
};

ST.prototype.drawLasers = function () {
    var spaceTime = this;
    if (this.lasers.length > 0) {
        this.lasers.forEach(function (laser) {
            laser.draw();
            spaceTime.detectLaserCollision(laser);
        })
    }
};

ST.prototype.drawMines = function () {
    var spaceTime = this;
    if (this.mines.length > 0) {
        this.mines.forEach(function (mine) {
            mine.draw();
            spaceTime.detectLaserCollision(mine);
        })
    }
};

ST.prototype.drawShield = function (ship) {
    var spaceTime = this;
    if (this.shields.length > 0) {
        this.shields.forEach(function (shield) {
            shield.draw(ship);
            spaceTime.detectShieldCollision(shield);
        })
    }
};

ST.prototype.fireLaser = function () {
    this.lasers.push(new Laser(this.ship, this.context));
};

ST.prototype.activeShield = function () {
    this.shields.push(new Shield(this.ship, this.context));
};

ST.prototype.layMine = function () {
    this.mines.push(new Mine(this.ship, this.context));
};

ST.prototype.detectLaserCollision = function (laser) {
    this.asteroids.forEach( function (asteroid) {
        if (asteroidCollidesWith(laser, asteroid)) {
            asteroid.hit_count += 1;
            if(asteroid.hit_count === 3) {
                this.asteroids = this.asteroids.filter(function (a) {
                    return a !== asteroid;
                });
                if (asteroid.width > 30) {
                    this.asteroids.push(new Asteroid(asteroid.x, asteroid.y, asteroid.width / 2, asteroid.height / 2, this.context, this.game.asteroidVelocity));
                    this.asteroids.push(new Asteroid(asteroid.x + asteroid.width / 2, asteroid.y + asteroid.height / 2, asteroid.width / 2, asteroid.height / 2, this.context, this.game.asteroidVelocity));
                }
            }
            this.lasers = this.lasers.filter(function (l) {
                return l !== laser;
            });
            this.game.scorePoints(asteroid);
        }
    }, this);
};

ST.prototype.detectShieldCollision = function (shield) {
    this.asteroids.forEach( function (asteroid) {
        if (shieldCollidesWith(shield, asteroid)) {
            this.asteroids = this.asteroids.filter(function (a) {
                return a !== asteroid;
            });
            this.shields = this.shields.filter(function (s) {
                return s !== shield;
            });
            this.game.scorePoints(asteroid);
        }
    }, this);
};

ST.prototype.detectShipCollision = function () {
    var ship = this.ship;
    var spaceTime = this;

    this.asteroids.forEach( function (asteroid) {
        if (asteroidCollidesWith(ship, asteroid)) {
            spaceTime.asteroids = spaceTime.asteroids.filter(function (a) {
                return a !== asteroid;
            });
            spaceTime.ship.dead = true;
            spaceTime.game.die();
            setTimeout(function() {
                spaceTime.ship.dead = false;
                ship.x = spaceTime.canvas.width/2;
                ship.y = spaceTime.canvas.height/2;
                ship.velocity = 0;
            }, 300);

        }
    });
};

ST.prototype.detectSides = function () {
    this.asteroids.forEach( function (asteroid) {
        if(asteroid.x > this.canvas.width) {
            asteroid.x -= this.canvas.width;
        }
        else if(asteroid.x < 0) {
            asteroid.x += this.canvas.width;
        }
        else if(asteroid.y > this.canvas.height) {
            asteroid.y -= this.canvas.height;
        }
        else if(asteroid.y < 0) {
            asteroid.y += this.canvas.height;
        }
    }, this);

    var ship = this.ship;

    if(ship.x + ship.width > this.canvas.width) {
        ship.x -= this.canvas.width;
    }
    else if(ship.x - ship.width < 0) {
        ship.x += this.canvas.width;
    }
    else if(ship.y > this.canvas.height) {
        ship.y -= this.canvas.height;
    }
    else if(ship.y < 0) {
        ship.y += this.canvas.height;
    }
};

function asteroidCollidesWith (object, asteroid) {
    if(object.y <= asteroid.y + asteroid.height && object.y >= asteroid.y) {
        if(object.x <= asteroid.x + asteroid.width && object.x >= asteroid.x){
            return true
        }
    }
}

function shieldCollidesWith (object, asteroid) {
    var distX = Math.abs(object.x - (asteroid.x + asteroid.width/2));
    var distY = Math.abs(object.y - (asteroid.y + asteroid.height/2));

    if (distX > (asteroid.width/2 + object.radius)) { return false; }
    if (distY > (asteroid.height/2 + object.radius)) { return false; }

    if (distX <= (asteroid.width/2)) { return true; }
    if (distY <= (asteroid.height/2)) { return true; }
}

function getRandom(min,max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
}<|endoftext|>


<commit_before>'use strict';

var helpers = require('../../helpers/integration');
var harness = helpers.harness(__filename);
var it = harness.it;
var db = harness.locals.db;

if (helpers.unmocked) {
  it('should insert a bunch of items', helpers.insertThree);

  var feed1;

  it('should be able to get the changes feed', function(assert) {
    var i = 3;

    feed1 = db.follow({since: 3});

    feed1.on('change', function(change) {
      assert.ok(change, 'change existed');
      assert.equal(change.seq, i + 1, 'seq is set correctly');
      ++i;
      if (i === 4) {
        console.log(change, i);
        assert.end();
      }
    });

    feed1.follow();

    setTimeout(function() {
      db.insert({'bar': 'baz'}, 'barbaz');
    }, 100);
  });

  it('should see changes since `seq:3`', function(assert) {
    var feed = db.follow({since: 3}, function(error, change) {
      assert.equal(error, null, 'should not have errors');
      assert.ok(change, 'change existed');
      feed.die();
      feed1.die();
      setImmediate(assert.end);
    });
  });
}
<commit_msg>No setImmediate in 0.8<commit_after>'use strict';

var helpers = require('../../helpers/integration');
var harness = helpers.harness(__filename);
var it = harness.it;
var db = harness.locals.db;

if (helpers.unmocked) {
  it('should insert a bunch of items', helpers.insertThree);

  var feed1;

  it('should be able to get the changes feed', function(assert) {
    var i = 3;

    feed1 = db.follow({since: 3});

    feed1.on('change', function(change) {
      assert.ok(change, 'change existed');
      assert.equal(change.seq, i + 1, 'seq is set correctly');
      ++i;
      if (i === 4) {
        console.log(change, i);
        assert.end();
      }
    });

    feed1.follow();

    setTimeout(function() {
      db.insert({'bar': 'baz'}, 'barbaz');
    }, 100);
  });

  it('should see changes since `seq:3`', function(assert) {
    var feed = db.follow({since: 3}, function(error, change) {
      assert.equal(error, null, 'should not have errors');
      assert.ok(change, 'change existed');
      feed.die();
      feed1.die();
      process.nextTick(assert.end);
    });
  });
}
<|endoftext|>


<commit_before>/* eslint no-underscore-dangle: 0 */
var debug = require('debug')('twiser-streaming');
var _ = require('lodash');

var Tweet = require('./tweet');

// Streaming
// =========
//
// When you ask to stream tweets from specific URL, new tab is opened with this URL.
// Every 15 seconds Stream Cycle is run to iterate over all streaming tabs, and fetch
// all tweets from these. Then check if particular tweet is likely new, and call
// streaming callback with this tweet. Important - there is no guarantee you will
// particular tweet only once, so if you code requeres never to process same tweet
// again, you need to implement some sort of storage of seen tweets in your code.
//

module.exports = {
    currentStreams: {},
    streamingInterval: false,

    // **Streaming**
    //
    // This method allows to stream tweets from `streamable` pages.
    // `Streamable` pages include: logged in home page, Discover page and Search results page.
    //
    // Currently only callback can be specified in `options`:
    //
    //       client.stream('https://twitter.com/search?f=realtime&q=js&src=typd', {
    //         cb: function(tweet) { // This callback will be called with new tweet
    //           console.log(tweet.user.id);
    //         }
    //       });
    //
    // Here is example of tweet object:
    //
    //         {
    //             "id_str": "567646576014008320",
    //             "id": "567646576014008320",
    //             "created_at": "2015-02-17T11:27:44.000Z",
    //             "text": "Java vs. Node.js: An epic battle for developer mind share http://ift.tt/1Az9Z4l  ===== http://androidanalytic.com ",
    //             "html": "Java vs. Node.js: An epic battle for developer mind share http://ift.tt/1Az9Z4l  ===== http://androidanalytic.com ",
    //             "retweeted": false,
    //             "is_reply": false,
    //             "user_mentions": [""],
    //             "user": {
    //                 "id_str": "2780229181",
    //                 "id": "2780229181",
    //                 "name": "Android Analytics",
    //                 "screen_name": "AndroidAnalytic",
    //                 "lang": "en"
    //             }
    //         }
    //
    stream: function(url, options) {
        debug('Streaming %s', url);

        var client = this;
        var id = url;

        if (url === '#direct') {
            url = 'https://twitter.com/direct_messages/';
        }

        if (! options) {
            options = {};
        }

        // We always require cb
        if (! options.cb) {
            options.cb = function(tweet, stream) {
                console.log('Tweet: %j. Stream: %s', tweet, stream.url);
            };
        }

        // If streaming record with this URL already exists, just add additional callback into cb array
        if (this.currentStreams[ id ]) {
            debug('Stream for %s already exists. Adding callback.');
            this.currentStreams[ id ].cb.push( options.cb );
            this.resumeStream();
            return this;
        }

        this.api.newWindowWithId(url, id, '', function(err, res) {
            if (err || !res) {
                return;
            }

            var windowHandleId = res.value;

            debug("Opened new window %s for url %s", windowHandleId, url);

            // Before streaming from this page, remove current tweets from it,
            // so only new ones are streamed.
            if (options.onlyNew) {
                this.waitFor('#content-main-heading')
                    .execute('$("li.stream-item").remove();');
            }

            var cb = options.cb;
            delete options.cb;

            var stream = _.extend({
                id  : windowHandleId,
                cb  : [ cb ],
                url : url
            }, options);

            client.currentStreams[ id ] = stream;

            client.resumeStream();
        });
    },

    // **Stream Direct Messages**
    //
    // Special case of streaming.
    streamDirectMessages: function(options) {
        return this.stream('#direct', options);
    },

    // This function used internally.
    //
    // This function run on each streaming cycle. Scans all streaming tabs, and runs callback for each
    // `new-ish` tweet.
    _streamCycle: function() {
        var client = this;

        Object.keys(this.currentStreams).forEach(function(id) {
            var stream = this.currentStreams[id];
            var url = stream.url;

            this.api
                .call(function() {
                    debug('Checking window %s for url %s', stream.id, url);
                })
                .window(stream.id);

            if (id === '#direct') {
            }
            else {
                this.api
                     .getTweets(function(err, tweets) {
                        if (err) {
                            return;
                        }

                        debug('found %d tweets', tweets.length);

                        tweets.reverse().forEach(function(item) {
                            var tweet = new Tweet(item);
                            stream.cb.forEach(function(cb) {
                                cb.call(client, tweet, stream);
                            });
                        });
                    })
                    .execute('$("li.stream-item").remove();');
            }
        }.bind(this));
    },

    // **stopStreaming**
    //
    // Stops streaming for particular URL. It will find tab where this URL is opened,
    // close this tab and also remove reference to it from array of URL to scan
    // on each Stream Cycle.
    stopStreaming: function(url) {
        var stream = this.currentStreams[url];

        if (! stream) {
            debug('Stream for ' + url + ' is not present.');
            return;
        }

        debug('Stopping stream for url %s', url);

        this.api.window(stream.id)
                .window(); // Close window

        delete this.currentStreams[url];

        if (Object.keys(this.currentStreams).length < 1) {
            this.pauseStream();
        }
    },

    // **stopStreamingAll**
    //
    // This will iterate over all URLs and stop streaming for each one.
    stopStreamingAll: function() {
        Object.keys( this.currentStreams ).forEach(function(url) {
            this.stopStreaming(url);
        }.bind(this));

        this.pauseStream();
    },

    // **Pause streaming**
    //
    // If you need to react on tweet, update account or do something else, you need to pause streaming.
    // Calling `.pauseStream` will switch focus to `main` tab, so no streaming tabs affected.
    //
    pauseStream: function() {
        if (this.streamingInterval) {
            debug('Pausing streaming');
            this.streamingInterval = clearInterval(this.streamingInterval);
            this.api.window(this.mainWindowId);
        }
    },

    // **Resume streaming**
    //
    // Once you are ready to continue streaming (finished replying to a tweet for example), call `.resumeStream()`.
    //
    resumeStream: function() {
        if (! this.streamingInterval) {
            debug('Resuming streaming.');
            this._streamCycle();
            this.streamingInterval = setInterval(this._streamCycle.bind(this), 15000);
        }
    }
};
<commit_msg>Check first if $ available before using. Prevent some types of unhandled exceptions.<commit_after>/* eslint no-underscore-dangle: 0 */
var debug = require('debug')('twiser-streaming');
var _ = require('lodash');

var Tweet = require('./tweet');

// Streaming
// =========
//
// When you ask to stream tweets from specific URL, new tab is opened with this URL.
// Every 15 seconds Stream Cycle is run to iterate over all streaming tabs, and fetch
// all tweets from these. Then check if particular tweet is likely new, and call
// streaming callback with this tweet. Important - there is no guarantee you will
// particular tweet only once, so if you code requeres never to process same tweet
// again, you need to implement some sort of storage of seen tweets in your code.
//

module.exports = {
    currentStreams: {},
    streamingInterval: false,

    // **Streaming**
    //
    // This method allows to stream tweets from `streamable` pages.
    // `Streamable` pages include: logged in home page, Discover page and Search results page.
    //
    // Currently only callback can be specified in `options`:
    //
    //       client.stream('https://twitter.com/search?f=realtime&q=js&src=typd', {
    //         cb: function(tweet) { // This callback will be called with new tweet
    //           console.log(tweet.user.id);
    //         }
    //       });
    //
    // Here is example of tweet object:
    //
    //         {
    //             "id_str": "567646576014008320",
    //             "id": "567646576014008320",
    //             "created_at": "2015-02-17T11:27:44.000Z",
    //             "text": "Java vs. Node.js: An epic battle for developer mind share http://ift.tt/1Az9Z4l  ===== http://androidanalytic.com ",
    //             "html": "Java vs. Node.js: An epic battle for developer mind share http://ift.tt/1Az9Z4l  ===== http://androidanalytic.com ",
    //             "retweeted": false,
    //             "is_reply": false,
    //             "user_mentions": [""],
    //             "user": {
    //                 "id_str": "2780229181",
    //                 "id": "2780229181",
    //                 "name": "Android Analytics",
    //                 "screen_name": "AndroidAnalytic",
    //                 "lang": "en"
    //             }
    //         }
    //
    stream: function(url, options) {
        debug('Streaming %s', url);

        var client = this;
        var id = url;

        if (url === '#direct') {
            url = 'https://twitter.com/direct_messages/';
        }

        if (! options) {
            options = {};
        }

        // We always require cb
        if (! options.cb) {
            options.cb = function(tweet, stream) {
                console.log('Tweet: %j. Stream: %s', tweet, stream.url);
            };
        }

        // If streaming record with this URL already exists, just add additional callback into cb array
        if (this.currentStreams[ id ]) {
            debug('Stream for %s already exists. Adding callback.');
            this.currentStreams[ id ].cb.push( options.cb );
            this.resumeStream();
            return this;
        }

        this.api.newWindowWithId(url, id, '', function(err, res) {
            if (err || !res) {
                return;
            }

            var windowHandleId = res.value;

            debug("Opened new window %s for url %s", windowHandleId, url);

            // Before streaming from this page, remove current tweets from it,
            // so only new ones are streamed.
            if (options.onlyNew) {
                this.waitFor('#content-main-heading')
                    .execute('if (window.$) $("li.stream-item").remove();');
            }

            var cb = options.cb;
            delete options.cb;

            var stream = _.extend({
                id  : windowHandleId,
                cb  : [ cb ],
                url : url
            }, options);

            client.currentStreams[ id ] = stream;

            client.resumeStream();
        });
    },

    // **Stream Direct Messages**
    //
    // Special case of streaming.
    streamDirectMessages: function(options) {
        return this.stream('#direct', options);
    },

    // This function used internally.
    //
    // This function run on each streaming cycle. Scans all streaming tabs, and runs callback for each
    // `new-ish` tweet.
    _streamCycle: function() {
        var client = this;

        Object.keys(this.currentStreams).forEach(function(id) {
            var stream = this.currentStreams[id];
            var url = stream.url;

            this.api
                .call(function() {
                    debug('Checking window %s for url %s', stream.id, url);
                })
                .window(stream.id);

            if (id === '#direct') {
            }
            else {
                this.api
                     .getTweets(function(err, tweets) {
                        if (err) {
                            return;
                        }

                        debug('found %d tweets', tweets.length);

                        tweets.reverse().forEach(function(item) {
                            var tweet = new Tweet(item);
                            stream.cb.forEach(function(cb) {
                                cb.call(client, tweet, stream);
                            });
                        });
                    })
                    .execute('if (window.$) $("li.stream-item").remove();');
            }
        }.bind(this));
    },

    // **stopStreaming**
    //
    // Stops streaming for particular URL. It will find tab where this URL is opened,
    // close this tab and also remove reference to it from array of URL to scan
    // on each Stream Cycle.
    stopStreaming: function(url) {
        var stream = this.currentStreams[url];

        if (! stream) {
            debug('Stream for ' + url + ' is not present.');
            return;
        }

        debug('Stopping stream for url %s', url);

        this.api.window(stream.id)
                .window(); // Close window

        delete this.currentStreams[url];

        if (Object.keys(this.currentStreams).length < 1) {
            this.pauseStream();
        }
    },

    // **stopStreamingAll**
    //
    // This will iterate over all URLs and stop streaming for each one.
    stopStreamingAll: function() {
        Object.keys( this.currentStreams ).forEach(function(url) {
            this.stopStreaming(url);
        }.bind(this));

        this.pauseStream();
    },

    // **Pause streaming**
    //
    // If you need to react on tweet, update account or do something else, you need to pause streaming.
    // Calling `.pauseStream` will switch focus to `main` tab, so no streaming tabs affected.
    //
    pauseStream: function() {
        if (this.streamingInterval) {
            debug('Pausing streaming');
            this.streamingInterval = clearInterval(this.streamingInterval);
            this.api.window(this.mainWindowId);
        }
    },

    // **Resume streaming**
    //
    // Once you are ready to continue streaming (finished replying to a tweet for example), call `.resumeStream()`.
    //
    resumeStream: function() {
        if (! this.streamingInterval) {
            debug('Resuming streaming.');
            this._streamCycle();
            this.streamingInterval = setInterval(this._streamCycle.bind(this), 15000);
        }
    }
};
<|endoftext|>


<commit_before>'use babel';

export default class TestView {

  constructor(serializedState) {
    // Create root element
    this.element = document.createElement('div');
    this.element.classList.add('test');

    // Create message element
    const message = document.createElement('div');
    message.textContent = 'The Test package is Alive! It\'s ALIVE!';
    message.classList.add('message');
    this.element.appendChild(message);
  }

  // Returns an object that can be retrieved when package is activated
  serialize() {}

  // Tear down any state and detach
  destroy() {
    this.element.remove();
  }

  getElement() {
    return this.element;
  }

}
<commit_msg>asdfasdf<commit_after>'use babel';

export default class TestView {

  constructor(serializedState) {
    this.element = document.createElement('div');
    this.element.classList.add('test');

    // Create message element
    const message = document.createElement('div');
    message.textContent = 'The Test package is Alive! It\'s ALIVE!';
    message.classList.add('message');
    this.element.appendChild(message);
  }

  serialize() {}

  destroy() {
    this.element.remove();
  }

  getElement() {
    return this.element;
  }

  foo () {

  }

}
<|endoftext|>


<commit_before>'use strict';
var chumblRequest = require("./chumbl-request.js");
var queryBuilder = require('./query-builder');
module.exports = {
    getTimestores: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores", options);
        options.verb = "get";
        options.errorIfNoResult = true;
        chumblRequest(options, callback);
    },
    getTimestore: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}", options);
        options.verb = "get";
        options.errorIfNoResult = true;
        chumblRequest(options, callback);
    },
    addTimestore: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores", options);
        options.verb = "post";
        options.data = options.timestore || options.data;
        chumblRequest(options, callback);
    },
    updateTimestore: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}", options);
        options.verb = "put";
        options.data = options.timestore || options.data;
        chumblRequest(options, callback);
    },
    queryEntities: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/entities/{targetDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    },
    aggregateEntities: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/aggregate/{targetDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    },
    countEntities: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/count/{targetDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    },
    getAllValuesForTimestore: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/metrics/{targetDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    },
    getValues: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/entities/{entityId}/metrics/{targetDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    },
    setValues: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/entities/{entityId}/metrics/{targetDate}", options);
        options.data = options.values || options.data;
        options.verb = "post";
        chumblRequest(options, callback);
    },
    getTimeline: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/entities/{entityId}/timeline/{startDate}/{endDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    }
};<commit_msg>adding delete method.<commit_after>'use strict';
var chumblRequest = require("./chumbl-request.js");
var queryBuilder = require('./query-builder');
module.exports = {
    getTimestores: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores", options);
        options.verb = "get";
        options.errorIfNoResult = true;
        chumblRequest(options, callback);
    },
    getTimestore: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}", options);
        options.verb = "get";
        options.errorIfNoResult = true;
        chumblRequest(options, callback);
    },
    addTimestore: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores", options);
        options.verb = "post";
        options.data = options.timestore || options.data;
        chumblRequest(options, callback);
    },
    updateTimestore: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}", options);
        options.verb = "put";
        options.data = options.timestore || options.data;
        chumblRequest(options, callback);
    },
    deleteTimestore: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}", options);
        options.verb = "delete";
        options.data = options.timestore || options.data;
        chumblRequest(options, callback);
    },
    queryEntities: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/entities/{targetDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    },
    aggregateEntities: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/aggregate/{targetDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    },
    countEntities: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/count/{targetDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    },
    getAllValuesForTimestore: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/metrics/{targetDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    },
    getValues: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/entities/{entityId}/metrics/{targetDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    },
    setValues: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/entities/{entityId}/metrics/{targetDate}", options);
        options.data = options.values || options.data;
        options.verb = "post";
        chumblRequest(options, callback);
    },
    getTimeline: function (options, callback) {
        options.url = queryBuilder("/{chumblr}/timestores/{timestoreId}/entities/{entityId}/timeline/{startDate}/{endDate}", options);
        options.verb = "get";
        chumblRequest(options, callback);
    }
};<|endoftext|>


<commit_before>(function() {
    'use strict';

    angular
        .module('yapp.authentication')
        .controller('SignOut', SignOut);

    SignOut.$inject = ["$scope", "$rootScope", "StateRouter"];
    function SignOut($scope, $rootScope, StateRouter) {
        $scope.doSignOut = doSignOut;

        ////////////////////

        function doSignOut() {
            $rootScope.yUser = null;
            StateRouter.goAndForget("home");
        }
    }

})();<commit_msg>Sign out removes access token from local storage.<commit_after>(function() {
    'use strict';

    angular
        .module('yapp.authentication')
        .controller('SignOut', SignOut);

    SignOut.$inject = ["$scope", "$rootScope", "StateRouter"];
    function SignOut($scope, $rootScope, StateRouter) {
        $scope.doSignOut = doSignOut;

        ////////////////////

        function doSignOut() {
            $rootScope.yUser = null;
            window.localStorage.removeItem("access_token");
            StateRouter.goAndForget("home");
        }
    }

})();<|endoftext|>


<commit_before>let bitcoin = require('bitcoinjs-lib')
let debug = require('debug')('blockchain')
let parallel = require('run-parallel')
let types = require('./types')

function Blockchain (emitter, db, rpc) {
  this.emitter = emitter
  this.db = db
  this.rpc = rpc
}

Blockchain.prototype.connect = function (blockId, height, callback) {
  this.rpc('getblock', [blockId, false], (err, blockHex) => {
    if (err) return callback(err)

    let blockBuffer = Buffer.from(blockHex, 'hex')
    let block = bitcoin.Block.fromBuffer(blockBuffer)
    let atomic = this.db.atomic()

    block.transactions.forEach((tx) => {
      let txId = tx.getId()

      tx.ins.forEach(({ hash, index: vout }, vin) => {
        if (bitcoin.Transaction.isCoinbaseHash(hash)) return

        let prevTxId = hash.reverse().toString('hex')

        atomic.put(types.spentIndex, { txId: prevTxId, vout }, { txId, vin })

        this.emitter.emit('spent', `${prevTxId}:${vout}`, txId)
      })

      tx.outs.forEach(({ script, value }, vout) => {
        let scId = bitcoin.crypto.sha256(script).toString('hex')

        atomic.put(types.scIndex, { scId, height, txId, vout }, null)
        atomic.put(types.txoIndex, { txId, vout }, { value })

        this.emitter.emit('script', scId, txId)
      })

      let txBuffer = tx.toBuffer() // TODO: maybe we can slice this in fromBuffer
      this.emitter.emit('transaction', txId, txBuffer)
      atomic.put(types.txIndex, { txId }, { height })
    })

    this.emitter.emit('block', blockId, blockBuffer, height)
    debug(`Putting ${blockId} @ ${height} - ${block.transactions.length} transactions`)
    atomic.put(types.tip, {}, blockId).write(callback)
  })
}

Blockchain.prototype.disconnect = function (blockId, callback) {
  parallel({
    blockHeader: (f) => this.rpc('getblockheader', [blockId, true], f),
    blockHex: (f) => this.rpc('getblock', [blockId, false], f)
  }, (err, result) => {
    if (err) return callback(err)

    let { height } = result.blockHeader
    let blockBuffer = Buffer.from(result.blockHex, 'hex')
    let block = bitcoin.Block.fromBuffer(blockBuffer)
    let atomic = this.db.atomic()

    block.transactions.forEach((tx) => {
      let txId = tx.getId()

      tx.ins.forEach(({ hash, index: vout }) => {
        if (bitcoin.Transaction.isCoinbaseHash(hash)) return

        let prevTxId = hash.reverse().toString('hex')

        atomic.del(types.spentIndex, { txId: prevTxId, vout })
      })

      tx.outs.forEach(({ script }, vout) => {
        let scId = bitcoin.crypto.sha256(script).toString('hex')

        atomic.del(types.scIndex, { scId, height, txId, vout })
        atomic.del(types.txoIndex, { txId, vout })
      })

      atomic.del(types.txIndex, { txId }, { height })
    })

    // TODO: add helper to bitcoinjs-lib?
    let previousBlockId = Buffer.from(block.prevHash).reverse().toString('hex')
    debug(`Deleting ${blockId} @ ${height} - ${block.transactions.length} transactions`)
    atomic.put(types.tip, {}, previousBlockId).write(callback)
  })
}

// QUERIES
Blockchain.prototype.blockByTransaction = function (txId, callback) {
  this.db.get(types.txIndex, { txId }, (err, height) => {
    if (err && err.notFound) return callback()
    if (err) return callback(err)

    this.rpc('getblockhash', [height], callback)
  })
}

let ZERO64 = '0000000000000000000000000000000000000000000000000000000000000000'
Blockchain.prototype.knownScript = function (scId, callback) {
  let result = false

  this.db.iterator(types.scIndex, {
    gte: { scId, height: 0, txId: ZERO64, vout: 0 },
    lt: { scId, height: 0xffffffff, txId: ZERO64, vout: 0 },
    limit: 1
  }, () => {
    result = true
  }, (err) => callback(err, result))
}

Blockchain.prototype.tip = function (callback) {
  this.db.get(types.tip, {}, (err, blockId) => {
    if (err && err.notFound) return callback()
    callback(err, blockId)
  })
}

Blockchain.prototype.txosByScript = function (scId, height, callback) {
  let resultMap = {}

  this.db.iterator(types.scIndex, {
    gte: { scId, height, txId: ZERO64, vout: 0 },
    lt: { scId, height: 0xffffffff, txId: ZERO64, vout: 0 }
  }, ({ txId, vout, height }) => {
    resultMap[`${txId}:${vout}`] = { txId, vout, scId, height }
  }, (err) => callback(err, resultMap))
}

Blockchain.prototype.spentFromTxo = function (txo, callback) {
  this.db.get(types.spentIndex, txo, (err, result) => {
    if (err && err.notFound) return callback()
    if (err) return callback(err)

    callback(null, result)
  })
}

Blockchain.prototype.transactionsByScript = function (scId, height, callback) {
  this.txosByScript(scId, height, (err, txosMap) => {
    if (err) return callback(err)

    let taskMap = {}
    for (let txoKey in txosMap) {
      let txo = txosMap[txoKey]

      taskMap[txoKey] = (next) => this.spentFromTxo(txo, next)
    }

    parallel(taskMap, (err, spentMap) => {
      if (err) return callback(err)

      let txIds = {}

      for (let x in spentMap) {
        let spent = spentMap[x]
        if (!spent) continue

        txIds[spent.txId] = true
      }

      for (let x in txosMap) {
        let { txId } = txosMap[x]
        txIds[txId] = true
      }

      callback(null, txIds)
    })
  })
}

module.exports = Blockchain
<commit_msg>blockchain: row returned, not just height<commit_after>let bitcoin = require('bitcoinjs-lib')
let debug = require('debug')('blockchain')
let parallel = require('run-parallel')
let types = require('./types')

function Blockchain (emitter, db, rpc) {
  this.emitter = emitter
  this.db = db
  this.rpc = rpc
}

Blockchain.prototype.connect = function (blockId, height, callback) {
  this.rpc('getblock', [blockId, false], (err, blockHex) => {
    if (err) return callback(err)

    let blockBuffer = Buffer.from(blockHex, 'hex')
    let block = bitcoin.Block.fromBuffer(blockBuffer)
    let atomic = this.db.atomic()

    block.transactions.forEach((tx) => {
      let txId = tx.getId()

      tx.ins.forEach(({ hash, index: vout }, vin) => {
        if (bitcoin.Transaction.isCoinbaseHash(hash)) return

        let prevTxId = hash.reverse().toString('hex')

        atomic.put(types.spentIndex, { txId: prevTxId, vout }, { txId, vin })

        this.emitter.emit('spent', `${prevTxId}:${vout}`, txId)
      })

      tx.outs.forEach(({ script, value }, vout) => {
        let scId = bitcoin.crypto.sha256(script).toString('hex')

        atomic.put(types.scIndex, { scId, height, txId, vout }, null)
        atomic.put(types.txoIndex, { txId, vout }, { value })

        this.emitter.emit('script', scId, txId)
      })

      let txBuffer = tx.toBuffer() // TODO: maybe we can slice this in fromBuffer
      this.emitter.emit('transaction', txId, txBuffer)
      atomic.put(types.txIndex, { txId }, { height })
    })

    this.emitter.emit('block', blockId, blockBuffer, height)
    debug(`Putting ${blockId} @ ${height} - ${block.transactions.length} transactions`)
    atomic.put(types.tip, {}, blockId).write(callback)
  })
}

Blockchain.prototype.disconnect = function (blockId, callback) {
  parallel({
    blockHeader: (f) => this.rpc('getblockheader', [blockId, true], f),
    blockHex: (f) => this.rpc('getblock', [blockId, false], f)
  }, (err, result) => {
    if (err) return callback(err)

    let { height } = result.blockHeader
    let blockBuffer = Buffer.from(result.blockHex, 'hex')
    let block = bitcoin.Block.fromBuffer(blockBuffer)
    let atomic = this.db.atomic()

    block.transactions.forEach((tx) => {
      let txId = tx.getId()

      tx.ins.forEach(({ hash, index: vout }) => {
        if (bitcoin.Transaction.isCoinbaseHash(hash)) return

        let prevTxId = hash.reverse().toString('hex')

        atomic.del(types.spentIndex, { txId: prevTxId, vout })
      })

      tx.outs.forEach(({ script }, vout) => {
        let scId = bitcoin.crypto.sha256(script).toString('hex')

        atomic.del(types.scIndex, { scId, height, txId, vout })
        atomic.del(types.txoIndex, { txId, vout })
      })

      atomic.del(types.txIndex, { txId }, { height })
    })

    // TODO: add helper to bitcoinjs-lib?
    let previousBlockId = Buffer.from(block.prevHash).reverse().toString('hex')
    debug(`Deleting ${blockId} @ ${height} - ${block.transactions.length} transactions`)
    atomic.put(types.tip, {}, previousBlockId).write(callback)
  })
}

// QUERIES
Blockchain.prototype.blockByTransaction = function (txId, callback) {
  this.db.get(types.txIndex, { txId }, (err, row) => {
    if (err && err.notFound) return callback()
    if (err) return callback(err)

    this.rpc('getblockhash', [row.height], callback)
  })
}

let ZERO64 = '0000000000000000000000000000000000000000000000000000000000000000'
Blockchain.prototype.knownScript = function (scId, callback) {
  let result = false

  this.db.iterator(types.scIndex, {
    gte: { scId, height: 0, txId: ZERO64, vout: 0 },
    lt: { scId, height: 0xffffffff, txId: ZERO64, vout: 0 },
    limit: 1
  }, () => {
    result = true
  }, (err) => callback(err, result))
}

Blockchain.prototype.tip = function (callback) {
  this.db.get(types.tip, {}, (err, blockId) => {
    if (err && err.notFound) return callback()
    callback(err, blockId)
  })
}

Blockchain.prototype.txosByScript = function (scId, height, callback) {
  let resultMap = {}

  this.db.iterator(types.scIndex, {
    gte: { scId, height, txId: ZERO64, vout: 0 },
    lt: { scId, height: 0xffffffff, txId: ZERO64, vout: 0 }
  }, ({ txId, vout, height }) => {
    resultMap[`${txId}:${vout}`] = { txId, vout, scId, height }
  }, (err) => callback(err, resultMap))
}

Blockchain.prototype.spentFromTxo = function (txo, callback) {
  this.db.get(types.spentIndex, txo, (err, result) => {
    if (err && err.notFound) return callback()
    if (err) return callback(err)

    callback(null, result)
  })
}

Blockchain.prototype.transactionsByScript = function (scId, height, callback) {
  this.txosByScript(scId, height, (err, txosMap) => {
    if (err) return callback(err)

    let taskMap = {}
    for (let txoKey in txosMap) {
      let txo = txosMap[txoKey]

      taskMap[txoKey] = (next) => this.spentFromTxo(txo, next)
    }

    parallel(taskMap, (err, spentMap) => {
      if (err) return callback(err)

      let txIds = {}

      for (let x in spentMap) {
        let spent = spentMap[x]
        if (!spent) continue

        txIds[spent.txId] = true
      }

      for (let x in txosMap) {
        let { txId } = txosMap[x]
        txIds[txId] = true
      }

      callback(null, txIds)
    })
  })
}

module.exports = Blockchain
<|endoftext|>


<commit_before>/*
 * Code style test
 */

/**
 * Module dependencies
 */
var helper = require('./helper');

/**
 * Lint own code
 *
 * @param test
 */
exports.MakeLint = function (test) {
  helper.testConsoleOutput(
    'make',
    ['lint'],
    {
      stdout: './node_modules/.bin/nodelint ./lib/ ./test/\n',
      stderr: '0 errors\n',
      exitCode: 0
    },
    test
  );
};
<commit_msg>Fix 'make test' for quiet make<commit_after>/*
 * Code style test
 */

/**
 * Module dependencies
 */
var helper = require('./helper');

/**
 * Lint own code
 *
 * @param test
 */
exports.MakeLint = function (test) {
  helper.testConsoleOutput(
    './node_modules/.bin/nodelint',
    ['./lib/', './test/'],
    {
      stdout: '',
      stderr: '0 errors\n',
      exitCode: 0
    },
    test
  );
};
<|endoftext|>