<commit_before>var stream = require('stream');
var util = require('util');

module.exports = ZXYStream;
util.inherits(ZXYStream, stream.Readable);

// Readable stream of line-delimited z/x/y coordinates
// contained within the MBTiles `tiles` table/view.
//
// The `batch` option exists to allow tests to check that
// multiple calls to `_read` are handled properly. IRL the
// default offset of 1000 should be reasonably efficient
// and not worth messing with.
function ZXYStream(source, options) {
    if (!source) throw new TypeError('MBTiles source required');

    options = options || {};

    if (options.batch !== undefined && typeof options.batch !== 'number')
        throw new TypeError('options.batch must be a positive integer');

    this.source = source;
    this.batch = options.batch || 1000;
    this.offset = 0;

    stream.Readable.call(this);
}

ZXYStream.prototype._read = function() {
    var stream = this;

    // Check for the existence of a map table that is indexed.
    if (!stream.table) {
        return this.source._db.get("select count(1) as count from sqlite_master where type = 'index' and tbl_name = 'map';", function(err, row) {
            if (err) return stream.emit('error', err);
            stream.table = row.count === 1 ? 'map' : 'tiles';
            return stream._read();
        });
    }

    this.source._db.all('SELECT zoom_level AS z, tile_column AS x, tile_row AS y FROM ' + this.table + ' LIMIT ' + this.batch + ' OFFSET ' + this.offset, function(err, rows) {
        if (err && err.code === 'SQLITE_ERROR' && /no such table/.test(err.message)) return stream.push(null);
        if (err) return stream.emit('error', err);
        if (!rows.length) return stream.push(null);
        stream.offset += stream.batch;
        var chunk = '';
        for (var i = 0; i < rows.length; i++) chunk += toLine(rows[i]);
        stream.push(chunk);
    });
};

function toLine(row) {
    // Flip Y coordinate because MBTiles files are TMS.
    var y = row.y = (1 << row.z) - 1 - row.y;
    return row.z + '/' + row.x + '/' + y + '\n';
}

<commit_msg>Query from `map` table with more than one index.<commit_after>var stream = require('stream');
var util = require('util');

module.exports = ZXYStream;
util.inherits(ZXYStream, stream.Readable);

// Readable stream of line-delimited z/x/y coordinates
// contained within the MBTiles `tiles` table/view.
//
// The `batch` option exists to allow tests to check that
// multiple calls to `_read` are handled properly. IRL the
// default offset of 1000 should be reasonably efficient
// and not worth messing with.
function ZXYStream(source, options) {
    if (!source) throw new TypeError('MBTiles source required');

    options = options || {};

    if (options.batch !== undefined && typeof options.batch !== 'number')
        throw new TypeError('options.batch must be a positive integer');

    this.source = source;
    this.batch = options.batch || 1000;
    this.offset = 0;

    stream.Readable.call(this);
}

ZXYStream.prototype._read = function() {
    var stream = this;

    // Check for the existence of a map table that is indexed.
    if (!stream.table) {
        return this.source._db.get("select count(1) as count from sqlite_master where type = 'index' and tbl_name = 'map';", function(err, row) {
            if (err) return stream.emit('error', err);
            stream.table = row.count >= 1 ? 'map' : 'tiles';
            return stream._read();
        });
    }

    this.source._db.all('SELECT zoom_level AS z, tile_column AS x, tile_row AS y FROM ' + this.table + ' LIMIT ' + this.batch + ' OFFSET ' + this.offset, function(err, rows) {
        if (err && err.code === 'SQLITE_ERROR' && /no such table/.test(err.message)) return stream.push(null);
        if (err) return stream.emit('error', err);
        if (!rows.length) return stream.push(null);
        stream.offset += stream.batch;
        var chunk = '';
        for (var i = 0; i < rows.length; i++) chunk += toLine(rows[i]);
        stream.push(chunk);
    });
};

function toLine(row) {
    // Flip Y coordinate because MBTiles files are TMS.
    var y = row.y = (1 << row.z) - 1 - row.y;
    return row.z + '/' + row.x + '/' + y + '\n';
}

<|endoftext|>


<commit_before>'use strict'

const assert = require('chai').assert
const uuid = require('uuid/v4')
const filtrate = require('../../src/utils/filtrate')

const name = (prefix) => prefix + uuid()

describe('filtrate()', function() {

	it('should return components', function() {

		const components = [
			{
				id: uuid(),
				name: name('a'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			},
			{
				id: uuid(),
				name: name('b'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			}
		]

		const result = filtrate(components, '')

		assert.deepEqual(result, components)

	})

	it('should return components filtered by name', function() {

		const components = [
			{
				id: uuid(),
				name: name('a'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			},
			{
				id: uuid(),
				name: name('b'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			}
		]

		const result = filtrate(components, components[1].name)

		assert.deepEqual(result, [ components[1] ])

	})

	it('should return components filtered by data', function() {

		const components = [
			{
				id: uuid(),
				name: name('a'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			},
			{
				id: uuid(),
				name: name('b'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			}
		]

		const result = filtrate(components, `view:${ components[1].data[0].data }`)

		assert.deepEqual(result, [ components[1] ])

	})

	it('should return components filtered by group', function() {

		const components = [
			{
				id: uuid(),
				name: name('a'),
				data: [
					{
						id: 'config',
						data: {
							group: uuid()
						}
					}
				]
			},
			{
				id: uuid(),
				name: name('b'),
				data: [
					{
						id: 'config',
						data: {
							group: uuid()
						}
					}
				]
			}
		]

		const result = filtrate(components, `group:${ components[1].data[0].data.group }`)

		assert.deepEqual(result, [ components[1] ])

	})

	it('should ignore unknown tabs', function() {

		const components = [
			{
				id: uuid(),
				name: name('a')
			}
		]

		const result = filtrate(components, `view:${ components[0].name }`)

		assert.strictEqual(result.length, 0)

	})

	it('should ignore custom parsed tabs', function() {

		const components = [
			{
				id: uuid(),
				name: name('a'),
				data: [
					{
						id: 'view',
						data: {}
					}
				]
			}
		]

		const result = filtrate(components, `view:$${ components[0].name }`)

		assert.strictEqual(result.length, 0)

	})

})<commit_msg>Test status filter<commit_after>'use strict'

const assert = require('chai').assert
const uuid = require('uuid/v4')
const filtrate = require('../../src/utils/filtrate')

const name = (prefix) => prefix + uuid()

describe('filtrate()', function() {

	it('should return components', function() {

		const components = [
			{
				id: uuid(),
				name: name('a'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			},
			{
				id: uuid(),
				name: name('b'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			}
		]

		const result = filtrate(components, '')

		assert.deepEqual(result, components)

	})

	it('should return components filtered by name', function() {

		const components = [
			{
				id: uuid(),
				name: name('a'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			},
			{
				id: uuid(),
				name: name('b'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			}
		]

		const result = filtrate(components, components[1].name)

		assert.deepEqual(result, [ components[1] ])

	})

	it('should return components filtered by data', function() {

		const components = [
			{
				id: uuid(),
				name: name('a'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			},
			{
				id: uuid(),
				name: name('b'),
				data: [
					{
						id: 'view',
						data: uuid()
					}
				]
			}
		]

		const result = filtrate(components, `view:${ components[1].data[0].data }`)

		assert.deepEqual(result, [ components[1] ])

	})

	it('should return components filtered by group', function() {

		const components = [
			{
				id: uuid(),
				name: name('a'),
				data: [
					{
						id: 'config',
						data: {
							group: uuid()
						}
					}
				]
			},
			{
				id: uuid(),
				name: name('b'),
				data: [
					{
						id: 'config',
						data: {
							group: uuid()
						}
					}
				]
			}
		]

		const result = filtrate(components, `group:${ components[1].data[0].data.group }`)

		assert.deepEqual(result, [ components[1] ])

	})

	it('should return components filtered by status', function() {

		const components = [
			{
				id: uuid(),
				name: name('a'),
				data: [
					{
						id: 'config',
						data: {
							status: uuid()
						}
					}
				]
			},
			{
				id: uuid(),
				name: name('b'),
				data: [
					{
						id: 'config',
						data: {
							status: uuid()
						}
					}
				]
			}
		]

		const result = filtrate(components, `status:${ components[1].data[0].data.status }`)

		assert.deepEqual(result, [ components[1] ])

	})

	it('should ignore unknown tabs', function() {

		const components = [
			{
				id: uuid(),
				name: name('a')
			}
		]

		const result = filtrate(components, `view:${ components[0].name }`)

		assert.strictEqual(result.length, 0)

	})

	it('should ignore custom parsed tabs', function() {

		const components = [
			{
				id: uuid(),
				name: name('a'),
				data: [
					{
						id: 'view',
						data: {}
					}
				]
			}
		]

		const result = filtrate(components, `view:$${ components[0].name }`)

		assert.strictEqual(result.length, 0)

	})

})<|endoftext|>


<commit_before>import mongoose from 'mongoose';
import Promise from 'bluebird';
import { getBooth } from './booth';
import { getPlaylists } from './playlists';

const ObjectId = mongoose.Types.ObjectId;

export const getState = function getState(id, uwave) {
  const Playlist = uwave.mongo.model('Playlist');
  const User = uwave.mongo.model('User');

  const playlists = getPlaylists(0, 50, id, uwave.mongo);
  const booth = getBooth(uwave)
    // set booth to null if nobody is playing
    .then(booth => booth.historyID ? booth : null);
  const user = User.findOne(ObjectId(id));
  const users = uwave.redis.lrange('users', 0, -1)
    .then(userIDs => User.find({'_id': { '$in': userIDs }}));
  const waitlist = uwave.redis.lrange('waitlist', 0, -1);

  return Promise.props({
    playlists,
    booth,
    user,
    users,
    waitlist
  });
};
<commit_msg>add waitlistLocked and activePlaylist to /now; resolves #27 and #28<commit_after>import mongoose from 'mongoose';
import Promise from 'bluebird';
import { getBooth } from './booth';
import { getPlaylists } from './playlists';

const ObjectId = mongoose.Types.ObjectId;

export const getState = function getState(id, uwave) {
  const Playlist = uwave.mongo.model('Playlist');
  const User = uwave.mongo.model('User');

  const playlists = getPlaylists(0, 50, id, uwave.mongo);
  const booth = getBooth(uwave)
    // set booth to null if nobody is playing
    .then(booth => booth.historyID ? booth : null);
  const user = User.findOne(ObjectId(id));
  const users = uwave.redis.lrange('users', 0, -1)
    .then(userIDs => User.find({'_id': { '$in': userIDs }}));
  const waitlist = uwave.redis.lrange('waitlist', 0, -1);
  const waitlistLocked = uwave.redis.get('waitlist:lock')
    .then(lock => lock ? true : false);
  const activePlaylist = uwave.redis.get(`playlist:${id}`);

  return Promise.props({
    playlists,
    booth,
    user,
    users,
    waitlist,
    waitlistLocked,
    activePlaylist
  });
};
<|endoftext|>


<commit_before>   //File Alert Box
    function CustomAlert() {
        this.render = function (dialog) {
          var winW = window.innerWidth;
          var winH = window.innerHeight;
          var dialogoverlay = document.getElementById('dialogoverlay');
          var dialogbox = document.getElementById('dialogbox');
          dialogoverlay.style.display = "block";
          dialogoverlay.style.height = winH + "px";
          dialogbox.style.left = (winW / 2) - (550 * .5) + "px";
          dialogbox.style.top = "100px";
          dialogbox.style.display = "block";
          document.getElementById('dialogboxhead').innerHTML = "Data Analyzer";
          document.getElementById('dialogboxbody').innerHTML = dialog + "<select><option onclick='Alert.ok()' value='Line'>Line Graph</option><option value='Bar'>Bar Graph</option><option value='scatter'>Scatter Plot</option></select>";
          document.getElementById('dialogboxfoot').innerHTML = "<button onclick='Alert2.cancel()'>Cancel</button><button onclick='Alert.ok()'>Submit</button>"
          document.getElementById('dialogbox').style.visibility = "visible";
          document.getElementById('dialogoverlay').style.visibility = "visible";
        }
        this.ok = function () {
          var e = document.getElementById('dialogboxbody').firstChild.nextSibling;
          type = e.options[e.selectedIndex].value.toLowerCase();
          if(type != "line" && type != "bar" && type!= "scatter"){
              alert("No graph type has been selected! Please select a type of graph.");
              return;
            }
          loadFile();
          if (type === "line") document.getElementById("lineRadioButton").checked = true;
          else if (type === "bar") document.getElementById("barRadioButton").checked = true;
          else if (type === "scatter") document.getElementById("scatterRadioButton").checked = true;
          document.getElementById('dialogbox').style.visibility = "hidden";
          document.getElementById('dialogoverlay').style.visibility = "hidden";
          document.getElementsByClassName('uploadBtn')[0].focus();
        }
        this.cancel= function(){
          document.getElementById('dialogbox').style.visibility = "hidden";
          document.getElementById('dialogoverlay').style.visibility = "hidden";
          document.getElementsByClassName('createBtn')[0].focus();
        }
    }
    //Second Alert Box
    function CustomAlert2() {
        this.render = function (dialog) {
            var winW = window.innerWidth;
            var winH = window.innerHeight;
            var dialogoverlay = document.getElementById('dialogoverlay');
            var dialogbox = document.getElementById('dialogbox');
            dialogoverlay.style.display = "block";
            dialogoverlay.style.height = winH + "px";
            dialogbox.style.left = (winW / 2) - (550 * .5) + "px";
            dialogbox.style.top = "100px";
            dialogbox.style.display = "block";
            document.getElementById('dialogboxhead').innerHTML = "Data Analyzer";
            document.getElementById('dialogboxbody').innerHTML = dialog + "<select><option onclick='Alert2.ok()' value='Line'>Line Graph</option><option value='Bar'>Bar Graph</option><option value='scatter'>Scatter Plot</option></select>
Choose number of rows: <input id='rows' type='text' value='0' aria-labelledby='Choose number of rows'/>
Choose number of columns: <input id='columns' type='text' value='0' aria-labelledby='Choose number of columns'/>";
            document.getElementById('dialogboxfoot').innerHTML = "<button onclick='Alert2.cancel()'>Cancel</button><button onclick=Alert2.reset()>Reset</button><button onclick='Alert2.ok()'>Submit</button>";
            document.getElementById('dialogbox').style.visibility = "visible";
            document.getElementById('dialogoverlay').style.visibility = "visible";
        }
        this.ok = function () {
            var e = document.getElementById('dialogboxbody').firstChild.nextSibling;
            type = e.options[e.selectedIndex].value.toLowerCase();
            if(type != "line" && type != "bar" && type!= "scatter"){
              alert("No graph type has been selected! Please select a type of graph.");
              return;
            }
            if(document.getElementById('rows').value * document.getElementById('columns').value >= 1000 ||document.getElementById('columns').value >= 1000 ||document.getElementById('rows').value >= 1000){
              if(!confirm("Large data set may cause browser instability, continue anyways?")){
                this.reset;
                return;
              }
            }
            createFile(document.getElementById('rows').value, document.getElementById('columns').value);
            if (type === "line") document.getElementById("lineRadioButton").checked = true;
            else if (type === "bar") document.getElementById("barRadioButton").checked = true;
            else if (type === "scatter") document.getElementById("scatterRadioButton").checked = true;
            document.getElementById('dialogbox').style.visibility = "hidden";
            document.getElementById('dialogoverlay').style.visibility = "hidden";
            document.getElementsByClassName('createBtn')[0].focus();
        }
        this.reset = function () {
            document.getElementById("rows").value=0;
            document.getElementById("columns").value=0;
        }
        this.cancel= function(){
          document.getElementById('dialogbox').style.visibility = "hidden";
          document.getElementById('dialogoverlay').style.visibility = "hidden";
          document.getElementsByClassName('createBtn')[0].focus();
        }
    }
var Alert = new CustomAlert();
var Alert2 = new CustomAlert2();

//Radio Button Chart/Graph Type Selection
var rType = function (rType) {
    var selType = document.getElementById("rTypeSel");
    if (selType.firstChild.nextSibling.checked) type = "line";
    else if (document.getElementById("barRadioButton").checked) {
        type = "bar";
    } else if (document.getElementById("scatterRadioButton").checked) {
        type = "scatter";
    }
        document.getElementById("colors").innerHTML="";
        changeType();

}
<commit_msg>Revert "Default Graph in Dialogue changed to Line Graph"<commit_after>   //File Alert Box
    function CustomAlert() {
        this.render = function (dialog) {
          var winW = window.innerWidth;
          var winH = window.innerHeight;
          var dialogoverlay = document.getElementById('dialogoverlay');
          var dialogbox = document.getElementById('dialogbox');
          dialogoverlay.style.display = "block";
          dialogoverlay.style.height = winH + "px";
          dialogbox.style.left = (winW / 2) - (550 * .5) + "px";
          dialogbox.style.top = "100px";
          dialogbox.style.display = "block";
          document.getElementById('dialogboxhead').innerHTML = "Data Analyzer";
          document.getElementById('dialogboxbody').innerHTML = dialog + "<select><option onclick='Alert.ok()' value='graphSelect'>select a type of graph</option><option value='Line'>Line Graph</option><option value='Bar'>Bar Graph</option><option value='scatter'>Scatter Plot</option></select>";
          document.getElementById('dialogboxfoot').innerHTML = "<button onclick='Alert2.cancel()'>Cancel</button><button onclick='Alert.ok()'>Submit</button>"
          document.getElementById('dialogbox').style.visibility = "visible";
          document.getElementById('dialogoverlay').style.visibility = "visible";
        }
        this.ok = function () {
          var e = document.getElementById('dialogboxbody').firstChild.nextSibling;
          type = e.options[e.selectedIndex].value.toLowerCase();
          if(type != "line" && type != "bar" && type!= "scatter"){
              alert("No graph type has been selected! Please select a type of graph.");
              return;
            }
          loadFile();
          if (type === "line") document.getElementById("lineRadioButton").checked = true;
          else if (type === "bar") document.getElementById("barRadioButton").checked = true;
          else if (type === "scatter") document.getElementById("scatterRadioButton").checked = true;
          document.getElementById('dialogbox').style.visibility = "hidden";
          document.getElementById('dialogoverlay').style.visibility = "hidden";
          document.getElementsByClassName('uploadBtn')[0].focus();
        }
        this.cancel= function(){
          document.getElementById('dialogbox').style.visibility = "hidden";
          document.getElementById('dialogoverlay').style.visibility = "hidden";
          document.getElementsByClassName('createBtn')[0].focus();
        }
    }
    //Second Alert Box
    function CustomAlert2() {
        this.render = function (dialog) {
            var winW = window.innerWidth;
            var winH = window.innerHeight;
            var dialogoverlay = document.getElementById('dialogoverlay');
            var dialogbox = document.getElementById('dialogbox');
            dialogoverlay.style.display = "block";
            dialogoverlay.style.height = winH + "px";
            dialogbox.style.left = (winW / 2) - (550 * .5) + "px";
            dialogbox.style.top = "100px";
            dialogbox.style.display = "block";
            document.getElementById('dialogboxhead').innerHTML = "Data Analyzer";
            document.getElementById('dialogboxbody').innerHTML = dialog + "<select><option onclick='Alert2.ok()' value='graphSelect'>select a type of graph</option><option value='Line'>Line Graph</option><option value='Bar'>Bar Graph</option><option value='scatter'>Scatter Plot</option></select>
Choose number of rows: <input id='rows' type='text' value='0' aria-labelledby='Choose number of rows'/>
Choose number of columns: <input id='columns' type='text' value='0' aria-labelledby='Choose number of columns'/>";
            document.getElementById('dialogboxfoot').innerHTML = "<button onclick='Alert2.cancel()'>Cancel</button><button onclick=Alert2.reset()>Reset</button><button onclick='Alert2.ok()'>Submit</button>";
            document.getElementById('dialogbox').style.visibility = "visible";
            document.getElementById('dialogoverlay').style.visibility = "visible";
        }
        this.ok = function () {
            var e = document.getElementById('dialogboxbody').firstChild.nextSibling;
            type = e.options[e.selectedIndex].value.toLowerCase();
            if(type != "line" && type != "bar" && type!= "scatter"){
              alert("No graph type has been selected! Please select a type of graph.");
              return;
            }
            if(document.getElementById('rows').value * document.getElementById('columns').value >= 1000 ||document.getElementById('columns').value >= 1000 ||document.getElementById('rows').value >= 1000){
              if(!confirm("Large data set may cause browser instability, continue anyways?")){
                this.reset;
                return;
              }
            }
            createFile(document.getElementById('rows').value, document.getElementById('columns').value);
            if (type === "line") document.getElementById("lineRadioButton").checked = true;
            else if (type === "bar") document.getElementById("barRadioButton").checked = true;
            else if (type === "scatter") document.getElementById("scatterRadioButton").checked = true;
            document.getElementById('dialogbox').style.visibility = "hidden";
            document.getElementById('dialogoverlay').style.visibility = "hidden";
            document.getElementsByClassName('createBtn')[0].focus();
        }
        this.reset = function () {
            document.getElementById("rows").value=0;
            document.getElementById("columns").value=0;
        }
        this.cancel= function(){
          document.getElementById('dialogbox').style.visibility = "hidden";
          document.getElementById('dialogoverlay').style.visibility = "hidden";
          document.getElementsByClassName('createBtn')[0].focus();
        }
    }
var Alert = new CustomAlert();
var Alert2 = new CustomAlert2();

//Radio Button Chart/Graph Type Selection
var rType = function (rType) {
    var selType = document.getElementById("rTypeSel");
    if (selType.firstChild.nextSibling.checked) type = "line";
    else if (document.getElementById("barRadioButton").checked) {
        type = "bar";
    } else if (document.getElementById("scatterRadioButton").checked) {
        type = "scatter";
    }
        document.getElementById("colors").innerHTML="";
        changeType();

}
<|endoftext|>


<commit_before>var test = require('tap').test,
    wolfram = require('../')

test('valid response', function(t) {
  var client = wolfram.createClient(process.env.WOLFRAM_APPID)

  t.test("integrate 2x", function(t) {
    client.query("integrate 2x", function(err, result) {
      t.notOk(err, "err should be null")
      t.type(result, "object")
      t.ok(result.length)
      t.equal(result.length, 2, "result length should be 2")
      t.equal(result[0].primary, true, "first pod should be primary")
      t.equal(result[0].subpods[0].value, ' integral 2 x dx = x^2+constant', 'result should be constant')
      t.ok(result[0].subpods[0].image, "result should have an image representation")
      t.end()
    })
  })

  t.test("1+1", function(t) {
    client.query("1+1", function(err, result) {
      t.notOk(err, "err should be null")
      t.type(result, "object")
      t.ok(result.length)
      t.equal(result.length, 6)
      t.equal(result[1].primary, true)
      t.equal(result[1].subpods[0].value, '2')
      t.end()
    })
  })
})
<commit_msg>Adds a test for the pod title property.<commit_after>var test = require('tap').test,
    wolfram = require('../')

test('valid response', function(t) {
  var client = wolfram.createClient(process.env.WOLFRAM_APPID)

  t.test("integrate 2x", function(t) {
    client.query("integrate 2x", function(err, result) {
      t.notOk(err, "err should be null")
      t.type(result, "object")
      t.ok(result.length)
      t.equal(result.length, 2, "result length should be 2")
      t.equal(result[0].primary, true, "first pod should be primary")
      t.equal(result[0].subpods[0].value, ' integral 2 x dx = x^2+constant', 'result should be constant')
      t.ok(result[0].subpods[0].image, "result should have an image representation")
      t.ok(result[0].title, "result should have a title of Indefinite integral")
      t.end()
    })
  })

  t.test("1+1", function(t) {
    client.query("1+1", function(err, result) {
      t.notOk(err, "err should be null")
      t.type(result, "object")
      t.ok(result.length)
      t.equal(result.length, 6)
      t.equal(result[1].primary, true)
      t.equal(result[1].subpods[0].value, '2')
      t.end()
    })
  })
})
<|endoftext|>


<commit_before>var NEIGHBOR_DISTANCE = 10;
var TURN_SENSITIVITY = 0.5;
var MAX_Y = 100;

var Boid = function(x, y, initialVelocity, initialHeading) {
  this.x = x;
  this.y = y;
  this.velocity = initialVelocity;
  this.heading = initialHeading;
};

Boid.prototype.step = function(dt) {
  this.x += dt * this.velocity * Math.cos(this.heading);
  this.y += dt * this.velocity * Math.sin(this.heading);
};

Boid.prototype.adjustHeading = function(flock, dt) {
  var neighborCount = 0;
  var neighborX = 0;
  var neighborY = 0;
  for(var i = 0; i < flock.length; i++) {
    var dx = this.x - flock[i].x;
    var dy = this.y - flock[i].y;

    if( (dx * dx + dy * dy) > NEIGHBOR_DISTANCE) {
      continue;
    }

    neighborX += dx;
    neighborY += dy;
  }

  var neighborHeading = Math.atan2(neighborY, neighborX);

  var timeSensitivity = TURN_SENSITIVITY * dt;
  this.heading = (1 - timeSensitivity) * this.heading + timeSensitivity * this.heading;

  if(this.y > MAX_Y) {
    this.heading = -MATH.PI / 2;
  }
};

var Flock = function(boidCount, xMin, xMax) {
  this.boids = [];
  for(var i = 0; i < boidCount; i++) {
    var x = Math.random() * (xMax - xMin) + xMax;
    var y = Math.random() * MAX_Y;
    var heading = Math.random() * Math.PI * 2;
    this.boids.push(new Boid(x, y, 10, heading));
  }
};

Flock.prototype.update = function(dt) {
  var i;

  for(i = 0; i < this.boids.length; i++) {
    this.boids[i].adjustHeading(this.boids, dt);
  }

  for(i = 0; i < this.boids.length; i++) {
    this.boids[i].step(dt);
  }
};
<commit_msg>Fixing another typo<commit_after>var NEIGHBOR_DISTANCE = 10;
var TURN_SENSITIVITY = 0.5;
var MAX_Y = 100;

var Boid = function(x, y, initialVelocity, initialHeading) {
  this.x = x;
  this.y = y;
  this.velocity = initialVelocity;
  this.heading = initialHeading;
};

Boid.prototype.step = function(dt) {
  this.x += dt * this.velocity * Math.cos(this.heading);
  this.y += dt * this.velocity * Math.sin(this.heading);
};

Boid.prototype.adjustHeading = function(flock, dt) {
  var neighborCount = 0;
  var neighborX = 0;
  var neighborY = 0;
  for(var i = 0; i < flock.length; i++) {
    var dx = this.x - flock[i].x;
    var dy = this.y - flock[i].y;

    if( (dx * dx + dy * dy) > NEIGHBOR_DISTANCE) {
      continue;
    }

    neighborX += dx;
    neighborY += dy;
  }

  var neighborHeading = Math.atan2(neighborY, neighborX);

  var timeSensitivity = TURN_SENSITIVITY * dt;
  this.heading = (1 - timeSensitivity) * this.heading + timeSensitivity * this.heading;

  if(this.y > MAX_Y) {
    this.heading = -Math.PI / 2;
  }
};

var Flock = function(boidCount, xMin, xMax) {
  this.boids = [];
  for(var i = 0; i < boidCount; i++) {
    var x = Math.random() * (xMax - xMin) + xMax;
    var y = Math.random() * MAX_Y;
    var heading = Math.random() * Math.PI * 2;
    this.boids.push(new Boid(x, y, 10, heading));
  }
};

Flock.prototype.update = function(dt) {
  var i;

  for(i = 0; i < this.boids.length; i++) {
    this.boids[i].adjustHeading(this.boids, dt);
  }

  for(i = 0; i < this.boids.length; i++) {
    this.boids[i].step(dt);
  }
};
<|endoftext|>


<commit_before>// ---   negate : (a -> Bool) -> a -> Bool
function negate(@p) { return function(@a) {return !p(a);};}
<commit_msg>javadoc bool<commit_after>/**
* negate : (a -> Bool) -> a -> Bool
*/
function negate(@p) { return function(@a) {return !p(a);};}
<|endoftext|>


<commit_before>var M = {};
M.loader = $('#ajax_wrap, #ajax_loader');
M.loadCount = 0;
M.loadCheck = function(){
	if ( this.loadCount > 0 ){
		this.loader.show();
	}
	else
	{
		this.loader.hide();
	}
}
M.init = function(){
	M.etsy.init();
	$('#etsy .more').tappable(function(){
		M.etsy.more();
	});

	M.write.get();
	$('#write .more').tappable(function(){
		M.write.get();
	});

	M.art.get();
	$('#art .more').tappable(function(){
		M.art.get();
	});

	$('.home').tappable(function(){
		M.nav.home();
	});

	if ( $('.mobNav').css('display') == 'block' ){
		if (History.getState().cleanUrl == "http://catandglove.com/"){
			router.navigate('/etsy');
		}
	}

	$('[show]:not(.prep)').addClass('prep').tappable(function(){
		var show = $(this).attr('show');
		router.navigate('/'+show);
		$('[show].act').removeClass('act');
		$('[show='+show+']').addClass('act');
	});
	router.checkRoutes(History.getState());
}

M.etsy = {};
M.etsy.items = {};
M.etsy.page = 0;
M.etsy.limit = 10;
M.etsy.isMore = true;
M.etsy.get = function(){
	if ( M.etsy.isMore ){
		limit = M.etsy.limit;
		var offset = M.etsy.page*limit;
		var url = 'http://openapi.etsy.com/v2/shops/catandglove/listings/active.js?callback=getData&api_key=3lrt6kdjs0ppzxvxj1ypo0m4&includes=Images&limit='+limit+'&order=date_desc&offset='+offset;
		M.loadCount++;
		M.loadCheck();
		$.ajax({
		url:url,
		dataType: 'jsonp'
		}).done(function(data){
			M.loadCount--;
			M.loadCheck();
			if (data.ok){
			M.etsy.page++;
			var count = 0;
				for (x in data.results)
				{
					count++;
					var result = data.results[x];
					if (M.etsy.items[result.listing_id] == undefined){
						M.etsy.items[result.listing_id] = result;
					}
				}
				if ( count < limit ) { M.etsy.isMore = false;}
				M.etsy.render();
			}
			else
			{

			}
		})
		.fail(function(){
		M.loadCount--;
		M.loadCheck();
		});
	}
}
M.etsy.getSingle = function(id){
	var url = 'http://openapi.etsy.com/v2/listings/'+id+'.js?callback=getData&api_key=3lrt6kdjs0ppzxvxj1ypo0m4&includes=Images';
	M.loadCount++;
	M.loadCheck();
	$.ajax({
	url:url,
	dataType: 'jsonp'
	}).done(function(data){
		M.loadCount--;
		M.loadCheck();
		if (data.ok){
			console.log(data);
			M.etsy.items[data.results[0]['listing_id']] = data.results[0];
			M.etsy.render();
			$('[eid='+id+']').addClass('activeItem');
			var data = M['etsy']['items'][id];
			M['etsy']['renderItem']( data );
			scrollTo(0, $('.activeItem').offset().top);
		}
	})
	.fail(function(){
	M.loadCount--;
	M.loadCheck();
	});
}
M.etsy.hideMoreButton = function (){
	$('#etsy .more').hide();
}
M.etsy.showMoreButton = function (){
	$('#etsy .more').show();
}
M.etsy.render = function(){
	var itemTemp = '

{{{title}}}

';
	var etsyHTML = [];

	for (x in M.etsy.items){
		var result = M.etsy.items[x];
		if (result.rendered == undefined){
			result.image = result.Images[0]['url_570xN'];
			etsyHTML.push(Mustache.render(itemTemp, result));
			M.etsy.items[x]['rendered'] = true;
		}
	}

	var loadHTML = function(){
		if (etsyHTML.length > 0)
		{
			var $item = $(etsyHTML.pop());
			$('#etsy .items').append($item);
			$item.hide().fadeIn(1000);
			setTimeout(loadHTML, 100);
		}
		else
		{
			$('.etsyItem:not(prepped)').addClass('prepped').tappable(function(){
				var eid = $(this).attr('eid');
				router.navigate('/etsy/'+eid);
			});
			if ( M.etsy.isMore ){
				M.etsy.showMoreButton();
			}
			else
			{
				M.etsy.hideMoreButton();
			}
		}
	}
	loadHTML();
}
M.etsy.renderItem = function (data) {
M.nav.makeActive($('#etsy'));
var tmpl = '

{{{description}}}
<button class="button">View on etsy</button>

Price - {{price}} {{currency_code}}

Style - {{style_string}}

{{{image_list}}}

';
data.style_string = '';
var eid = data.listing_id;
for (x in data.style)
{
	data.style_string += data.style[x] +', ';
}
if (data.style_string.length > 0)
{
	data.style_string= data.style_string.substr(0, data.style_string.length-2);
}
data.description = data.description.replace(/\n/g,"
");

data.image_list = '';
var a = 0;
for (x in data.Images ){
	if (a == 0){
		data.image_list+='

';
		a++;
	} else
	{
		data.image_list+='

';
	}
}

var res = Mustache.render(tmpl, data);
$('[eid='+eid+']').after(res);
scrollTo(0, $('[eid='+eid+']').offset().top);
window.s = new Swipe($('.gal')[0]);
var myPhotoSwipe = $(".gal a").photoSwipe({ enableMouseWheel: false , enableKeyboard: true });
}

M.restoreItems = function (){
 $('.itemDetails').remove();
 $('.activeItem').removeClass('activeItem');
}
M.etsy.init = M.etsy.get;
M.etsy.more = M.etsy.get;

function WP(category){
	this.category = category;
	this.items = {};
	this.page = 1;
	this.limit = 10;
	this.isMore = true;
	this.get = function(){
		if ( this.isMore ){
			var wp = this;
			url = '/press?json=get_category_posts&category_slug='+this.category+'&count='+this.limit+'&page='+this.page;
			M.loadCount++;
			M.loadCheck();
			$.get(url).
			done( function( data ){
				M.loadCount--;
				M.loadCheck();
				if ( data.status == 'ok' ){
					wp.page++;
					var count = 0;
					for ( x in data.posts ){
						count++;
						var result = data.posts[x];
						wp.items[result['slug']] = result;
					}
					if ( count < wp.limit ) { wp.isMore = false;}
				}
				wp.render();
			})
			.fail(function(){
			M.loadCount--;
			M.loadCheck();
			});
		}
	}
}

M.write = new WP('write');
M.write.showMoreButton = function(){
	$('#write .more').show();
};
M.write.hideMoreButton = function(){
	$('#write .more').hide();
};
M.write.render = function(){
	var itemTemp = '

{{{title}}}
{{{content}}}

';
	var writeHTML = [];

	for (x in this.items){
		var result = this.items[x];
		if (result.rendered == undefined){
			//result.image = result.Images[0]['url_570xN'];
			writeHTML.push(Mustache.render(itemTemp, result));
			this.items[x]['rendered'] = true;
		}
	}

	var loadHTML = function(){
		if (writeHTML.length > 0)
		{
			var $item = $(writeHTML.pop());
			$('#write .items').append($item);
			$item.hide().fadeIn(1000);
			setTimeout(loadHTML, 100);
		}
		else
		{
			$('.writeItem a img').each(function(){
			var image = $(this).html('img');
			var a = $(this).parent('a').before(image).remove();
			});

			if ( M.write.isMore ){
				M.write.showMoreButton();
			}
			else
			{
				M.write.hideMoreButton();
			}
		}
	}
	loadHTML();
}

M.art = new WP('art');
M.art.render = function(){

	var itemTemp = 	'

{{{title}}}

';
	var artHTML = [];

	for ( x in this.items ){
		var result = this.items[x];
		if ( result.rendered == undefined ){
			//result.image = result.Images[0]['url_570xN'];
			artHTML.push(Mustache.render(itemTemp, result));
			this.items[x]['rendered'] = true;
		}
	}

	var loadHTML = function(){
		if (artHTML.length > 0)
		{
			var $item = $(artHTML.pop());
			$('#art .items').append($item);
			$item.hide().fadeIn(1000);
			setTimeout(loadHTML, 100);
		}
		else
		{
			if ( M.art.isMore ){
				M.art.showMoreButton();
			}
			else
			{
				M.art.hideMoreButton();
			}
		}
	}
	loadHTML();
}
M.art.showMoreButton = function(){
	$('#art .more').show();
};
M.art.hideMoreButton = function(){
	$('#art .more').hide();
};

M.nav = {};

M.nav.home = function () {
	router.navigate('/');
}
M.nav.makeActive = function ($id){
	if ( !$id.hasClass('eight') ){
		var id = $id.attr('id');
		$('[show]').removeClass('act');
		$('[show='+id+']').addClass('act');
		$('.content>.eight').removeClass('eight').removeClass('offset-by-two').addClass('four');
		$('.hidden').removeClass('hidden');
		$('#etsy, #write, #art').addClass('hidden');
		$id.removeClass('hidden').removeClass('four').addClass('eight').addClass('offset-by-two');
	}
}
M.nav.removeActive = function($id){
$('#etsy, #write, #art').removeClass('hidden');
$('.content>.eight').removeClass('eight').removeClass('offset-by-two').addClass('four');
}
M.nav.pageByID = function(type, id){

	if ( M[type]['items'][id] != undefined )
	{
		$('[eid='+id+']').addClass('activeItem');
		var data = M[type]['items'][id];
		M[type]['renderItem']( data );
		scrollTo(0, $('.activeItem').offset().top);
	}
	else
	{
		M[type]['getSingle'](id);

	}
}

var router = new Router();
router.route('/', function(){
	M.restoreItems();
	M.nav.removeActive();
});
router.route('/etsy', function(){
	M.restoreItems();
	M.nav.makeActive($('#etsy'));
});
router.route('/etsy/:id', function(id){
	M.restoreItems();
	M.nav.pageByID('etsy', id);
});
router.route('/write', function(){
	M.restoreItems();
	M.nav.makeActive($('#write'));
});
router.route('/write/:id', function(id){
	M.restoreItems();
	M.nav.pageByID('write', id);
});
router.route('/art', function(){
	M.restoreItems();
	M.nav.makeActive($('#art'));
});
router.route('/art/:id', function(id){
	M.restoreItems();
	M.nav.pageByID('art', id);
});

<commit_msg>added getSingle to wp<commit_after>var M = {};
M.loader = $('#ajax_wrap, #ajax_loader');
M.loadCount = 0;
M.loadCheck = function(){
	if ( this.loadCount > 0 ){
		this.loader.show();
	}
	else
	{
		this.loader.hide();
	}
}
M.init = function(){
	M.etsy.init();
	$('#etsy .more').tappable(function(){
		M.etsy.more();
	});

	M.write.get();
	$('#write .more').tappable(function(){
		M.write.get();
	});

	M.art.get();
	$('#art .more').tappable(function(){
		M.art.get();
	});

	$('.home').tappable(function(){
		M.nav.home();
	});

	if ( $('.mobNav').css('display') == 'block' ){
		if (History.getState().cleanUrl == "http://catandglove.com/"){
			router.navigate('/etsy');
		}
	}

	$('[show]:not(.prep)').addClass('prep').tappable(function(){
		var show = $(this).attr('show');
		router.navigate('/'+show);
		$('[show].act').removeClass('act');
		$('[show='+show+']').addClass('act');
	});
	router.checkRoutes(History.getState());
}

M.etsy = {};
M.etsy.items = {};
M.etsy.page = 0;
M.etsy.limit = 10;
M.etsy.isMore = true;
M.etsy.get = function(){
	if ( M.etsy.isMore ){
		limit = M.etsy.limit;
		var offset = M.etsy.page*limit;
		var url = 'http://openapi.etsy.com/v2/shops/catandglove/listings/active.js?callback=getData&api_key=3lrt6kdjs0ppzxvxj1ypo0m4&includes=Images&limit='+limit+'&order=date_desc&offset='+offset;
		M.loadCount++;
		M.loadCheck();
		$.ajax({
		url:url,
		dataType: 'jsonp'
		}).done(function(data){
			M.loadCount--;
			M.loadCheck();
			if (data.ok){
			M.etsy.page++;
			var count = 0;
				for (x in data.results)
				{
					count++;
					var result = data.results[x];
					if (M.etsy.items[result.listing_id] == undefined){
						M.etsy.items[result.listing_id] = result;
					}
				}
				if ( count < limit ) { M.etsy.isMore = false;}
				M.etsy.render();
			}
			else
			{

			}
		})
		.fail(function(){
		M.loadCount--;
		M.loadCheck();
		});
	}
}
M.etsy.getSingle = function(id){
	var url = 'http://openapi.etsy.com/v2/listings/'+id+'.js?callback=getData&api_key=3lrt6kdjs0ppzxvxj1ypo0m4&includes=Images';
	M.loadCount++;
	M.loadCheck();
	$.ajax({
	url:url,
	dataType: 'jsonp'
	}).done(function(data){
		M.loadCount--;
		M.loadCheck();
		if (data.ok){
			console.log(data);
			M.etsy.items[data.results[0]['listing_id']] = data.results[0];
			M.etsy.render();
			$('[eid='+id+']').addClass('activeItem');
			var data = M['etsy']['items'][id];
			M['etsy']['renderItem']( data );
			scrollTo(0, $('.activeItem').offset().top);
		}
	})
	.fail(function(){
	M.loadCount--;
	M.loadCheck();
	});
}
M.etsy.hideMoreButton = function (){
	$('#etsy .more').hide();
}
M.etsy.showMoreButton = function (){
	$('#etsy .more').show();
}
M.etsy.render = function(){
	var itemTemp = '

{{{title}}}

';
	var etsyHTML = [];

	for (x in M.etsy.items){
		var result = M.etsy.items[x];
		if (result.rendered == undefined){
			result.image = result.Images[0]['url_570xN'];
			etsyHTML.push(Mustache.render(itemTemp, result));
			M.etsy.items[x]['rendered'] = true;
		}
	}

	var loadHTML = function(){
		if (etsyHTML.length > 0)
		{
			var $item = $(etsyHTML.pop());
			$('#etsy .items').append($item);
			$item.hide().fadeIn(1000);
			setTimeout(loadHTML, 100);
		}
		else
		{
			$('.etsyItem:not(prepped)').addClass('prepped').tappable(function(){
				var eid = $(this).attr('eid');
				router.navigate('/etsy/'+eid);
			});
			if ( M.etsy.isMore ){
				M.etsy.showMoreButton();
			}
			else
			{
				M.etsy.hideMoreButton();
			}
		}
	}
	loadHTML();
}
M.etsy.renderItem = function (data) {
M.nav.makeActive($('#etsy'));
var tmpl = '

{{{description}}}
<button class="button">View on etsy</button>

Price - {{price}} {{currency_code}}

Style - {{style_string}}

{{{image_list}}}

';
data.style_string = '';
var eid = data.listing_id;
for (x in data.style)
{
	data.style_string += data.style[x] +', ';
}
if (data.style_string.length > 0)
{
	data.style_string= data.style_string.substr(0, data.style_string.length-2);
}
data.description = data.description.replace(/\n/g,"
");

data.image_list = '';
var a = 0;
for (x in data.Images ){
	if (a == 0){
		data.image_list+='

';
		a++;
	} else
	{
		data.image_list+='

';
	}
}

var res = Mustache.render(tmpl, data);
$('[eid='+eid+']').after(res);
scrollTo(0, $('[eid='+eid+']').offset().top);
window.s = new Swipe($('.gal')[0]);
var myPhotoSwipe = $(".gal a").photoSwipe({ enableMouseWheel: false , enableKeyboard: true });
}

M.restoreItems = function (){
 $('.itemDetails').remove();
 $('.activeItem').removeClass('activeItem');
}
M.etsy.init = M.etsy.get;
M.etsy.more = M.etsy.get;

function WP(category){
	this.category = category;
	this.items = {};
	this.page = 1;
	this.limit = 10;
	this.isMore = true;
	this.get = function(){
		if ( this.isMore ){
			var wp = this;
			url = '/press?json=get_category_posts&category_slug='+this.category+'&count='+this.limit+'&page='+this.page;
			M.loadCount++;
			M.loadCheck();
			$.get(url).
			done( function( data ){
				M.loadCount--;
				M.loadCheck();
				if ( data.status == 'ok' ){
					wp.page++;
					var count = 0;
					for ( x in data.posts ){
						count++;
						var result = data.posts[x];
						wp.items[result['slug']] = result;
					}
					if ( count < wp.limit ) { wp.isMore = false;}
				}
				wp.render();
			})
			.fail(function(){
			M.loadCount--;
			M.loadCheck();
			});
		}
	};
	this.getSingle = function(id){
		var wp = this;
		var url = '/press?json=get_post&post_slug='+id+';
		M.loadCount++;
		M.loadCheck();
		$.ajax({
		url:url,
		dataType: 'json'
		}).done(function(data){
			M.loadCount--;
			M.loadCheck();
			if (data.ok){
				wp.items[data.results[0]['listing_id']] = data.results[0];
				wp.render();

				$('[eid='+id+']').addClass('activeItem');
				var data = wp['items'][id];
				M['etsy']['renderItem']( data );
				scrollTo(0, $('.activeItem').offset().top);
			}
		})
		.fail(function(){
		M.loadCount--;
		M.loadCheck();
		});
	};
}

M.write = new WP('write');
M.write.showMoreButton = function(){
	$('#write .more').show();
};
M.write.hideMoreButton = function(){
	$('#write .more').hide();
};
M.write.render = function(){
	var itemTemp = '

{{{title}}}
{{{content}}}

';
	var writeHTML = [];

	for (x in this.items){
		var result = this.items[x];
		if (result.rendered == undefined){
			//result.image = result.Images[0]['url_570xN'];
			writeHTML.push(Mustache.render(itemTemp, result));
			this.items[x]['rendered'] = true;
		}
	}

	var loadHTML = function(){
		if (writeHTML.length > 0)
		{
			var $item = $(writeHTML.pop());
			$('#write .items').append($item);
			$item.hide().fadeIn(1000);
			setTimeout(loadHTML, 100);
		}
		else
		{
			$('.writeItem a img').each(function(){
			var image = $(this).html('img');
			var a = $(this).parent('a').before(image).remove();
			});

			if ( M.write.isMore ){
				M.write.showMoreButton();
			}
			else
			{
				M.write.hideMoreButton();
			}
		}
	}
	loadHTML();
}

M.art = new WP('art');
M.art.render = function(){

	var itemTemp = 	'

{{{title}}}

';
	var artHTML = [];

	for ( x in this.items ){
		var result = this.items[x];
		if ( result.rendered == undefined ){
			//result.image = result.Images[0]['url_570xN'];
			artHTML.push(Mustache.render(itemTemp, result));
			this.items[x]['rendered'] = true;
		}
	}

	var loadHTML = function(){
		if (artHTML.length > 0)
		{
			var $item = $(artHTML.pop());
			$('#art .items').append($item);
			$item.hide().fadeIn(1000);
			setTimeout(loadHTML, 100);
		}
		else
		{
			if ( M.art.isMore ){
				M.art.showMoreButton();
			}
			else
			{
				M.art.hideMoreButton();
			}
		}
	}
	loadHTML();
}
M.art.showMoreButton = function(){
	$('#art .more').show();
};
M.art.hideMoreButton = function(){
	$('#art .more').hide();
};

M.nav = {};

M.nav.home = function () {
	router.navigate('/');
}
M.nav.makeActive = function ($id){
	if ( !$id.hasClass('eight') ){
		var id = $id.attr('id');
		$('[show]').removeClass('act');
		$('[show='+id+']').addClass('act');
		$('.content>.eight').removeClass('eight').removeClass('offset-by-two').addClass('four');
		$('.hidden').removeClass('hidden');
		$('#etsy, #write, #art').addClass('hidden');
		$id.removeClass('hidden').removeClass('four').addClass('eight').addClass('offset-by-two');
	}
}
M.nav.removeActive = function($id){
$('#etsy, #write, #art').removeClass('hidden');
$('.content>.eight').removeClass('eight').removeClass('offset-by-two').addClass('four');
}
M.nav.pageByID = function(type, id){

	if ( M[type]['items'][id] != undefined )
	{
		$('[eid='+id+']').addClass('activeItem');
		var data = M[type]['items'][id];
		M[type]['renderItem']( data );
		scrollTo(0, $('.activeItem').offset().top);
	}
	else
	{
		M[type]['getSingle'](id);

	}
}

var router = new Router();
router.route('/', function(){
	M.restoreItems();
	M.nav.removeActive();
});
router.route('/etsy', function(){
	M.restoreItems();
	M.nav.makeActive($('#etsy'));
});
router.route('/etsy/:id', function(id){
	M.restoreItems();
	M.nav.pageByID('etsy', id);
});
router.route('/write', function(){
	M.restoreItems();
	M.nav.makeActive($('#write'));
});
router.route('/write/:id', function(id){
	M.restoreItems();
	M.nav.pageByID('write', id);
});
router.route('/art', function(){
	M.restoreItems();
	M.nav.makeActive($('#art'));
});
router.route('/art/:id', function(id){
	M.restoreItems();
	M.nav.pageByID('art', id);
});

<|endoftext|>


<commit_before>/**
 * 提供变换扩展
 * @module zrender/mixin/Transformable
 * @author pissang (https://www.github.com/pissang)
 */
define(function (require) {

    'use strict';

    var matrix = require('../core/matrix');
    var vector = require('../core/vector');
    var mIdentity = matrix.identity;

    var mTranslate = matrix.translate;

    var EPSILON = 5e-5;

    function isAroundZero(val) {
        return val > -EPSILON && val < EPSILON;
    }
    function isNotAroundZero(val) {
        return val > EPSILON || val < -EPSILON;
    }

    /**
     * @alias module:zrender/mixin/Transformable
     * @constructor
     */
    var Transformable = function (opts) {
        // If there are no given position, rotation, scale
        if (! opts.position) {
            /**
             * 平移
             * @type {Array.<number>}
             * @default [0, 0]
             */
            this.position = [0, 0];
        }
        if (opts.rotation == null) {
            /**
             * 旋转
             * @type {Array.<number>}
             * @default 0
             */
            this.rotation = 0;
        }
        if (! opts.scale) {
            /**
             * 缩放
             * @type {Array.<number>}
             * @default [1, 1]
             */
            this.scale = [1, 1];
        }
        /**
         * 旋转和缩放的原点
         * @type {Array.<number>}
         * @default null
         */
        this.origin = this.origin || null;

        /**
         * 是否有坐标变换
         * @type {boolean}
         * @readOnly
         */
        this.needTransform = false;
    };

    Transformable.prototype = {

        constructor: Transformable,

        transform: null,

        needLocalTransform: function () {
            return isNotAroundZero(this.rotation)
                || isNotAroundZero(this.position[0])
                || isNotAroundZero(this.position[1])
                || isNotAroundZero(this.scale[0] - 1)
                || isNotAroundZero(this.scale[1] - 1);
        },

        /**
         * 判断是否需要有坐标变换，更新needTransform属性。
         * 如果有坐标变换, 则从position, rotation, scale以及父节点的transform计算出自身的transform矩阵
         */
        updateTransform: function () {

            var parent = this.parent;
            var parentHasTransform = parent && parent.needTransform;
            var needLocalTransform = this.needLocalTransform();
            this.needTransform = needLocalTransform || parentHasTransform;

            if (!this.needTransform) {
                return;
            }

            var m = this.transform || matrix.create();

            if (needLocalTransform) {
                this.getLocalTransform(m);
            }
            else {
                mIdentity(m);
            }

            // 应用父节点变换
            if (parentHasTransform) {
                if (needLocalTransform) {
                    matrix.mul(m, parent.transform, m);
                }
                else {
                    matrix.copy(m, parent.transform);
                }
            }
            // 保存这个变换矩阵
            this.transform = m;

            this.invTransform = this.invTransform || matrix.create();
            matrix.invert(this.invTransform, m);
        },

        getLocalTransform: function (m) {
            m = m || [];
            mIdentity(m);

            var origin = this.origin;
            if (origin && isAroundZero(origin[0]) && isAroundZero(origin[1])) {
                origin = null;
            }

            var scale = this.scale;
            var rotation = this.rotation;
            var position = this.position;
            if (origin) {
                mTranslate(m, m, origin);
            }
            matrix.scale(m, m, scale);
            if (rotation) {
                matrix.rotate(m, m, rotation);
            }
            if (origin) {
                origin[0] = -origin[0];
                origin[1] = -origin[1];
                mTranslate(m, m, origin);
                origin[0] = -origin[0];
                origin[1] = -origin[1];
            }

            if (isNotAroundZero(position[0]) || isNotAroundZero(position[1])) {
                mTranslate(m, m, position);
            }

            return m;
        },
        /**
         * 将自己的transform应用到context上
         * @param {Context2D} ctx
         */
        setTransform: function (ctx) {
            if (this.needTransform) {
                var m = this.transform;
                ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
            }
        },
        /**
         * 设置图形的朝向
         * @param  {Array.<number>|Float32Array} target
         * @method
         */
        lookAt: (function () {
            var v = vector.create();
            return function(target) {
                if (!this.transform) {
                    this.transform = matrix.create();
                }
                var m = this.transform;
                vector.sub(v, target, this.position);
                if (isAroundZero(v[0]) && isAroundZero(v[1])) {
                    return;
                }
                vector.normalize(v, v);
                var scale = this.scale;
                // Y Axis
                // TODO Scale origin ?
                m[2] = v[0] * scale[1];
                m[3] = v[1] * scale[1];
                // X Axis
                m[0] = v[1] * scale[0];
                m[1] = -v[0] * scale[0];
                // Position
                m[4] = this.position[0];
                m[5] = this.position[1];

                this.decomposeTransform();
            };
        })(),
        /**
         * 分解`transform`矩阵到`position`, `rotation`, `scale`
         */
        decomposeTransform: function () {
            if (!this.transform) {
                return;
            }
            var m = this.transform;
            var sx = m[0] * m[0] + m[1] * m[1];
            var position = this.position;
            var scale = this.scale;
            if (isNotAroundZero(sx - 1)) {
                sx = Math.sqrt(sx);
            }
            var sy = m[2] * m[2] + m[3] * m[3];
            if (isNotAroundZero(sy - 1)) {
                sy = Math.sqrt(sy);
            }
            position[0] = m[4];
            position[1] = m[5];
            scale[0] = sx;
            scale[1] = sy;
            this.rotation = Math.atan2(-m[1] / sy, m[0] / sx);
        },

        /**
         * 变换坐标位置到 shape 的局部坐标空间
         * @method
         * @param {number} x
         * @param {number} y
         * @return {Array.<number>}
         */
        transformCoordToLocal: function (x, y) {
            var v2 = [x, y];
            var invTransform = this.invTransform;
            if (this.needTransform && invTransform) {
                vector.applyTransform(v2, v2, invTransform);
            }
            return v2;
        },

        /**
         * 变换局部坐标位置到全局坐标空间
         * @method
         * @param {number} x
         * @param {number} y
         * @return {Array.<number>}
         */
        transformCoordToGlobal: function (x, y) {
            var v2 = [x, y];
            var transform = this.transform;
            if (this.needTransform && transform) {
                vector.applyTransform(v2, v2, transform);
            }
            return v2;
        }
    };

    return Transformable;
});
<commit_msg>Optimization in Transformable#updateTransform<commit_after>/**
 * 提供变换扩展
 * @module zrender/mixin/Transformable
 * @author pissang (https://www.github.com/pissang)
 */
define(function (require) {

    'use strict';

    var matrix = require('../core/matrix');
    var vector = require('../core/vector');
    var mIdentity = matrix.identity;

    var mTranslate = matrix.translate;

    var EPSILON = 5e-5;

    function isAroundZero(val) {
        return val > -EPSILON && val < EPSILON;
    }
    function isNotAroundZero(val) {
        return val > EPSILON || val < -EPSILON;
    }

    /**
     * @alias module:zrender/mixin/Transformable
     * @constructor
     */
    var Transformable = function (opts) {
        // If there are no given position, rotation, scale
        if (! opts.position) {
            /**
             * 平移
             * @type {Array.<number>}
             * @default [0, 0]
             */
            this.position = [0, 0];
        }
        if (opts.rotation == null) {
            /**
             * 旋转
             * @type {Array.<number>}
             * @default 0
             */
            this.rotation = 0;
        }
        if (! opts.scale) {
            /**
             * 缩放
             * @type {Array.<number>}
             * @default [1, 1]
             */
            this.scale = [1, 1];
        }
        /**
         * 旋转和缩放的原点
         * @type {Array.<number>}
         * @default null
         */
        this.origin = this.origin || null;

        /**
         * 是否有坐标变换
         * @type {boolean}
         * @readOnly
         */
        this.needTransform = false;
    };

    Transformable.prototype = {

        constructor: Transformable,

        transform: null,

        needLocalTransform: function () {
            return isNotAroundZero(this.rotation)
                || isNotAroundZero(this.position[0])
                || isNotAroundZero(this.position[1])
                || isNotAroundZero(this.scale[0] - 1)
                || isNotAroundZero(this.scale[1] - 1);
        },

        /**
         * 判断是否需要有坐标变换，更新needTransform属性。
         * 如果有坐标变换, 则从position, rotation, scale以及父节点的transform计算出自身的transform矩阵
         */
        updateTransform: function () {

            var parent = this.parent;
            var parentHasTransform = parent && parent.needTransform;
            var needLocalTransform = this.needLocalTransform();
            this.needTransform = needLocalTransform || parentHasTransform;

            if (!this.needTransform) {
                return;
            }

            var m = this.transform || matrix.create();

            if (needLocalTransform) {
                this.getLocalTransform(m);
            }
            else {
                mIdentity(m);
            }

            // 应用父节点变换
            if (parentHasTransform) {
                if (needLocalTransform) {
                    matrix.mul(m, parent.transform, m);
                }
                else {
                    matrix.copy(m, parent.transform);
                }
            }
            // 保存这个变换矩阵
            this.transform = m;

            this.invTransform = this.invTransform || matrix.create();
            matrix.invert(this.invTransform, m);
        },

        getLocalTransform: function (m) {
            m = m || [];
            mIdentity(m);

            var origin = this.origin;
            if (origin && isAroundZero(origin[0]) && isAroundZero(origin[1])) {
                origin = null;
            }

            var scale = this.scale;
            var rotation = this.rotation;
            var position = this.position;
            if (origin) {
                mTranslate(m, m, origin);
            }
            matrix.scale(m, m, scale);
            if (rotation) {
                matrix.rotate(m, m, rotation);
            }
            if (origin) {
                origin[0] = -origin[0];
                origin[1] = -origin[1];
                mTranslate(m, m, origin);
                origin[0] = -origin[0];
                origin[1] = -origin[1];
            }

            mTranslate(m, m, position);

            return m;
        },
        /**
         * 将自己的transform应用到context上
         * @param {Context2D} ctx
         */
        setTransform: function (ctx) {
            if (this.needTransform) {
                var m = this.transform;
                ctx.transform(m[0], m[1], m[2], m[3], m[4], m[5]);
            }
        },
        /**
         * 设置图形的朝向
         * @param  {Array.<number>|Float32Array} target
         * @method
         */
        lookAt: (function () {
            var v = vector.create();
            return function(target) {
                if (!this.transform) {
                    this.transform = matrix.create();
                }
                var m = this.transform;
                vector.sub(v, target, this.position);
                if (isAroundZero(v[0]) && isAroundZero(v[1])) {
                    return;
                }
                vector.normalize(v, v);
                var scale = this.scale;
                // Y Axis
                // TODO Scale origin ?
                m[2] = v[0] * scale[1];
                m[3] = v[1] * scale[1];
                // X Axis
                m[0] = v[1] * scale[0];
                m[1] = -v[0] * scale[0];
                // Position
                m[4] = this.position[0];
                m[5] = this.position[1];

                this.decomposeTransform();
            };
        })(),
        /**
         * 分解`transform`矩阵到`position`, `rotation`, `scale`
         */
        decomposeTransform: function () {
            if (!this.transform) {
                return;
            }
            var m = this.transform;
            var sx = m[0] * m[0] + m[1] * m[1];
            var position = this.position;
            var scale = this.scale;
            if (isNotAroundZero(sx - 1)) {
                sx = Math.sqrt(sx);
            }
            var sy = m[2] * m[2] + m[3] * m[3];
            if (isNotAroundZero(sy - 1)) {
                sy = Math.sqrt(sy);
            }
            position[0] = m[4];
            position[1] = m[5];
            scale[0] = sx;
            scale[1] = sy;
            this.rotation = Math.atan2(-m[1] / sy, m[0] / sx);
        },

        /**
         * 变换坐标位置到 shape 的局部坐标空间
         * @method
         * @param {number} x
         * @param {number} y
         * @return {Array.<number>}
         */
        transformCoordToLocal: function (x, y) {
            var v2 = [x, y];
            var invTransform = this.invTransform;
            if (this.needTransform && invTransform) {
                vector.applyTransform(v2, v2, invTransform);
            }
            return v2;
        },

        /**
         * 变换局部坐标位置到全局坐标空间
         * @method
         * @param {number} x
         * @param {number} y
         * @return {Array.<number>}
         */
        transformCoordToGlobal: function (x, y) {
            var v2 = [x, y];
            var transform = this.transform;
            if (this.needTransform && transform) {
                vector.applyTransform(v2, v2, transform);
            }
            return v2;
        }
    };

    return Transformable;
});
<|endoftext|>


<commit_before>// Node.js API.
var path = require('path')

// Control-flow utilities.
var delta = require('delta')
var cadence = require('cadence')

var Reactor = require('reactor')
var Runner = require('./runner')
var spawn = require('child_process').spawn

var Keyify = require('keyify')

var descendent = require('foremost')('descendent')

// Exceptions that you can catch by type.
var Interrupt = require('interrupt').createInterrupter('subordinate')

var Monitor = require('./monitor')

var Operation = require('operation')

function Listener (destructible, socketPath) {
    this._destructible = destructible
    this._destructible.markDestroyed(this)
    this.destroyed = false

    descendent.increment()
    destructible.completed.wait(descendent, 'decrement')

    descendent.on('olio:registered', this._registered.bind(this))
    descendent.on('olio:ready', this._ready.bind(this))

    this._socketPath = socketPath
    this._children = {}

    this._process = process
    this._process.env.OLIO_SUPERVISOR_PROCESS_ID = process.pid

    this.reactor = new Reactor(this, function (dispatcher) {
        dispatcher.dispatch('GET /', 'index')
    })
}

Listener.prototype.socket = function (request, socket) {
    var message = {
        module: 'olio',
        method: 'connect',
        to: {
            name: request.headers['x-olio-to-name'],
            index: +request.headers['x-olio-to-index']
        },
        from: {
            name: request.headers['x-olio-from-name'],
            index: +request.headers['x-olio-from-index']
        }
    }
    var path = this._children[message.to.name].paths[message.to.index]
    descendent.down(path, 'olio:message', message, socket)
}

Listener.prototype.index = cadence(function (async) {
    return [ 200, { 'content-type': 'text/plain' }, 'Olio Listener API\n' ]
})

Listener.prototype._created = function (count, name, argv, pids) {
    this._children[name] = {
        count: count,
        registered: 0,
        ready: 0,
        argv: argv,
        pids: pids,
        paths: []
    }
}

Listener.prototype._registered = function (message) {
    var child = this._children[message.cookie.name]
    child.registered++
    child.paths[message.cookie.index] = message.from
    if (child.registered != child.count) {
        return
    }
    for (var name in this._children) {
        var child = this._children[name]
        if (child.registered != child.count) {
            return
        }
    }
    for (var name in this._children) {
        child = this._children[name]
        child.paths.forEach(function (path, index) {
            // TODO Shouldn't count go down now with initialization?
            descendent.down(path, 'olio:message', {
                method: 'initialize',
                name: name,
                argv: child.argv,
                index: index
            })
        }, this)
        child.paths.forEach(function (path, index) {
            descendent.down(path, 'olio:message', {
                method: 'created',
                socketPath: this._socketPath,
                argv: child.argv,
                name: name,
                paths: child.paths,
                count: child.count
            })
        }, this)
    }
}

Listener.prototype._ready = function (message) {
    var child = this._children[message.cookie.name]
    if (++child.ready != child.count) {
        return
    }
    for (var name in this._children) {
        var sibling = this._children[name]
        if (name != message.cookie.name) {
            sibling.paths.forEach(function (path, index) {
                descendent.down(path, 'olio:message', {
                    method: 'created',
                    socketPath: this._socketPath,
                    name: message.cookie.name,
                    count: child.count,
                    argv: child.argv
                })
            }, this)
        }
    }
}

Listener.prototype.children = cadence(function (async, children) {
    async.forEach(function (body) {
        switch (body.method) {
        case 'serve':
            var child = spawn('node', [
                path.join(__dirname, 'serve.child.js'),
                '--name', body.parameters.name,
                '--workers', body.parameters.workers
            ].concat(body.argv), { stdio: [ 0, 1, 2, 'ipc' ] })
            descendent.addChild(child, null)
            this._created(+body.parameters.workers, body.parameters.name, body.argv, [ child.pid ])
            this._destructible.destruct.wait(child, 'kill')
            Monitor(Interrupt, this, child, this._destructible.monitor([ 'serve', body.argv ]))
            break
        case 'run':
            async(function () {
                this._destructible.monitor([ 'run', body.parameters.name ], Runner, {
                    process: process,
                    workers: body.parameters.workers,
                    name: body.parameters.name,
                    argv: body.argv
                }, async())
            }, function (runner) {
                this._created(+body.parameters.workers, body.parameters.name, body.argv, runner.pids)
            })
            break
        }
    })(children)
})

module.exports = function (destructible, socketPath, callback) {
    callback(null, new Listener(destructible, socketPath))
}
<commit_msg>Remove another unused `require`.<commit_after>// Node.js API.
var path = require('path')

// Control-flow utilities.
var delta = require('delta')
var cadence = require('cadence')

var Reactor = require('reactor')
var Runner = require('./runner')
var spawn = require('child_process').spawn

var descendent = require('foremost')('descendent')

// Exceptions that you can catch by type.
var Interrupt = require('interrupt').createInterrupter('subordinate')

var Monitor = require('./monitor')

var Operation = require('operation')

function Listener (destructible, socketPath) {
    this._destructible = destructible
    this._destructible.markDestroyed(this)
    this.destroyed = false

    descendent.increment()
    destructible.completed.wait(descendent, 'decrement')

    descendent.on('olio:registered', this._registered.bind(this))
    descendent.on('olio:ready', this._ready.bind(this))

    this._socketPath = socketPath
    this._children = {}

    this._process = process
    this._process.env.OLIO_SUPERVISOR_PROCESS_ID = process.pid

    this.reactor = new Reactor(this, function (dispatcher) {
        dispatcher.dispatch('GET /', 'index')
    })
}

Listener.prototype.socket = function (request, socket) {
    var message = {
        module: 'olio',
        method: 'connect',
        to: {
            name: request.headers['x-olio-to-name'],
            index: +request.headers['x-olio-to-index']
        },
        from: {
            name: request.headers['x-olio-from-name'],
            index: +request.headers['x-olio-from-index']
        }
    }
    var path = this._children[message.to.name].paths[message.to.index]
    descendent.down(path, 'olio:message', message, socket)
}

Listener.prototype.index = cadence(function (async) {
    return [ 200, { 'content-type': 'text/plain' }, 'Olio Listener API\n' ]
})

Listener.prototype._created = function (count, name, argv, pids) {
    this._children[name] = {
        count: count,
        registered: 0,
        ready: 0,
        argv: argv,
        pids: pids,
        paths: []
    }
}

Listener.prototype._registered = function (message) {
    var child = this._children[message.cookie.name]
    child.registered++
    child.paths[message.cookie.index] = message.from
    if (child.registered != child.count) {
        return
    }
    for (var name in this._children) {
        var child = this._children[name]
        if (child.registered != child.count) {
            return
        }
    }
    for (var name in this._children) {
        child = this._children[name]
        child.paths.forEach(function (path, index) {
            // TODO Shouldn't count go down now with initialization?
            descendent.down(path, 'olio:message', {
                method: 'initialize',
                name: name,
                argv: child.argv,
                index: index
            })
        }, this)
        child.paths.forEach(function (path, index) {
            descendent.down(path, 'olio:message', {
                method: 'created',
                socketPath: this._socketPath,
                argv: child.argv,
                name: name,
                paths: child.paths,
                count: child.count
            })
        }, this)
    }
}

Listener.prototype._ready = function (message) {
    var child = this._children[message.cookie.name]
    if (++child.ready != child.count) {
        return
    }
    for (var name in this._children) {
        var sibling = this._children[name]
        if (name != message.cookie.name) {
            sibling.paths.forEach(function (path, index) {
                descendent.down(path, 'olio:message', {
                    method: 'created',
                    socketPath: this._socketPath,
                    name: message.cookie.name,
                    count: child.count,
                    argv: child.argv
                })
            }, this)
        }
    }
}

Listener.prototype.children = cadence(function (async, children) {
    async.forEach(function (body) {
        switch (body.method) {
        case 'serve':
            var child = spawn('node', [
                path.join(__dirname, 'serve.child.js'),
                '--name', body.parameters.name,
                '--workers', body.parameters.workers
            ].concat(body.argv), { stdio: [ 0, 1, 2, 'ipc' ] })
            descendent.addChild(child, null)
            this._created(+body.parameters.workers, body.parameters.name, body.argv, [ child.pid ])
            this._destructible.destruct.wait(child, 'kill')
            Monitor(Interrupt, this, child, this._destructible.monitor([ 'serve', body.argv ]))
            break
        case 'run':
            async(function () {
                this._destructible.monitor([ 'run', body.parameters.name ], Runner, {
                    process: process,
                    workers: body.parameters.workers,
                    name: body.parameters.name,
                    argv: body.argv
                }, async())
            }, function (runner) {
                this._created(+body.parameters.workers, body.parameters.name, body.argv, runner.pids)
            })
            break
        }
    })(children)
})

module.exports = function (destructible, socketPath, callback) {
    callback(null, new Listener(destructible, socketPath))
}
<|endoftext|>


<commit_before>
;(function( FooFighter ){

"use strict";

function StartScreen ( gameState, group ) {
    this.gameState = gameState;
    this.game = gameState.game;
    this.group = group;
    this.styles = {
        title: {
            font: "72px KenPixel",
            fill: "#ffff00",
            align: "center"
        },
        start: {
            font: "32px KenPixel",
            fill: "#ffff00",
            align: "center"
        },
        gameOver: {
            font: "100px KenPixel",
            fill: "#ffff00",
            align: "center"
        }
    };
    this.refs = {};
    this.title = 'FooFighter.js';
    this.gameOver = 'Game Over';
    this.bindEvents();
}

var proto = StartScreen.prototype;

proto.bindEvents = function(){
    var vent = this.gameState.vent;

    // Need to keep a reference for the bound function
    // so we can unbind the handler later
    this.refs.checkStart = this.checkStart.bind(this);
    vent.on('update', this.refs.checkStart);

    vent.on('create', this.create.bind(this));
    vent.on('start', this.hideTitle.bind(this));
    vent.on('game-over', this.showGameOver.bind(this));
    return this;
};

proto.create = function(){
    var vent = this.gameState.vent;

    this.titleText = this.game.add.bitmapText(
        this.game.world.centerX, this.game.world.centerY - 300,
        this.title,
        this.styles.title
    );
    this.titleText.anchor = {
        x: 0.5,
        y: 0.5
    };
    this.group.add(this.titleText);

    this.startText = this.game.add.bitmapText(
        this.game.world.centerX, this.game.world.centerY - 200,
        'Press \'S\' To Start Game',
        this.styles.start
    );
    this.startText.anchor = {
        x: 0.5,
        y: 0.5
    };

    this.group.add(this.startText);
    return this;
};

proto.checkStart = function(){
    var kb = this.gameState.keyboard,
        vent = this.gameState.vent;

    if ( kb.isDown(83) ) {
        vent.emit('start');
        vent.off('update', this.refs.checkStart);
        this.gameState.hasStarted = true;
    }
};

proto.hideTitle = function(){
    this.startText.visible = false;
    this.titleText.visible = false;
};

proto.showGameOver = function(){
    var game = this.game,
        isUndefined = FooFighter.Util.isUndefined;

    if ( isUndefined(this.gameOverText) ) {
        this.gameOverText =this.game.add.bitmapText(
            this.game.world.centerX, this.game.world.centerY,
            this.gameOver,
            this.styles.title
        );
        this.gameOverText.anchor = {
            x: 0.5,
            y: 0.5
        };
    } else {
        this.gameOverText.visible = true;
    }
};

FooFighter.StartScreen = StartScreen;

})(FooFighter);
<commit_msg>add a hack for restarting gameplay after game over<commit_after>
;(function( FooFighter ){

'use strict';

function StartScreen ( gameState, group ) {
    this.gameState = gameState;
    this.game = gameState.game;
    this.group = group;
    this.styles = {
        title: {
            font: "72px KenPixel",
            fill: "#ffff00",
            align: "center"
        },
        start: {
            font: "32px KenPixel",
            fill: "#ffff00",
            align: "center"
        },
        gameOver: {
            font: "100px KenPixel",
            fill: "#ffff00",
            align: "center"
        },
        restart: {
            font: "32px KenPixel",
            fill: "#ffff00",
            align: "center"
        }
    };
    this.refs = {};
    this.title = 'FooFighter.js';
    this.gameOver = 'Game Over';
    this.restart = 'Press \'P\' to Play Again';
    this.bindEvents();
}

var proto = StartScreen.prototype;

proto.bindEvents = function(){
    var vent = this.gameState.vent;

    // Need to keep a reference for the bound function
    // so we can unbind the handler later
    this.refs.checkStart = this.checkStart.bind(this);
    vent.on('update', this.refs.checkStart);

    vent.on('create', this.create.bind(this));
    vent.on('start', this.toggleTitle.bind(this, false));
    vent.on('game-over', this.showGameOver.bind(this));
    return this;
};

proto.create = function(){
    var vent = this.gameState.vent;

    this.titleText = this.game.add.bitmapText(
        this.game.world.centerX, this.game.world.centerY - 300,
        this.title,
        this.styles.title
    );
    this.titleText.anchor = {
        x: 0.5,
        y: 0.5
    };
    this.group.add(this.titleText);

    this.startText = this.game.add.bitmapText(
        this.game.world.centerX, this.game.world.centerY - 200,
        'Press \'S\' To Start Game',
        this.styles.start
    );
    this.startText.anchor = {
        x: 0.5,
        y: 0.5
    };

    this.group.add(this.startText);
    return this;
};

proto.checkStart = function(){
    var kb = this.gameState.keyboard,
        vent = this.gameState.vent;

    if ( kb.isDown(83) ) {
        vent.emit('start');
        vent.off('update', this.refs.checkStart);
        this.gameState.hasStarted = true;
    }
};

proto.toggleTitle = function ( val ) {
    this.startText.visible = val;
    this.titleText.visible = val;
};

proto.toggleGameOver = function ( val ) {
    this.gameOverText.visible = val;
};

proto.showGameOver = function(){
    var game = this.game,
        vent = this.gameState.vent,
        isUndefined = FooFighter.Util.isUndefined;

    if ( isUndefined(this.gameOverText) ) {
        this.gameOverText = this.game.add.bitmapText(
            this.game.world.centerX, this.game.world.centerY - 100,
            this.gameOver,
            this.styles.gameOver
        );
        this.gameOverText.anchor = {
            x: 0.5,
            y: 0.5
        };
        this.restartText = this.game.add.bitmapText(
            this.game.world.centerX, this.game.world.centerY,
            this.restart,
            this.styles.restart
        );
        this.restartText.anchor = {
            x: 0.5,
            y: 0.5
        };
    } else {
        this.toggleGameOver(true);
    }

    this.refs.checkRestart = this.checkRestart.bind(this);
    vent.on('update', this.refs.checkRestart);
};

proto.checkRestart = function(){
    var kb = this.gameState.keyboard,
        vent = this.gameState.vent;

    if ( kb.isDown(80) ) {
        vent.off('update', this.refs.checkRestart);
        window.location.reload(false);
    }
};

FooFighter.StartScreen = StartScreen;

})(FooFighter);
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2016 Bilibili. All Rights Reserved.
 *
 * @author zheng qian <xqq@xqq.im>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import EventEmitter from 'events';
import Log from '../utils/logger.js';
import LoggingControl from '../utils/logging-control.js';
import TransmuxingController from './transmuxing-controller.js';
import TransmuxingEvents from './transmuxing-events.js';
import TransmuxingWorker from './transmuxing-worker.js';
import MediaInfo from './media-info.js';

class Transmuxer {

    constructor(mediaDataSource, config) {
        this.TAG = 'Transmuxer';
        this._emitter = new EventEmitter();

        if (config.enableWorker && typeof (Worker) !== 'undefined') {
            try {
                let work = require('webworkify');
                this._worker = work(TransmuxingWorker);
                this._workerDestroying = false;
                this._worker.addEventListener('message', this._onWorkerMessage.bind(this));
                this._worker.postMessage({cmd: 'init', param: [mediaDataSource, config]});
                this.e = {
                    onLoggingConfigChanged: this._onLoggingConfigChanged.bind(this)
                };
                LoggingControl.registerListener(this.e.onLoggingConfigChanged);
                this._worker.postMessage({cmd: 'logging_config', param: LoggingControl.getConfig()});
            } catch (error) {
                Log.e(this.TAG, 'Error while initialize transmuxing worker, fallback to inline transmuxing');
                this._worker = null;
                this._controller = new TransmuxingController(mediaDataSource, config);
            }
        } else {
            this._controller = new TransmuxingController(mediaDataSource, config);
        }

        if (this._controller) {
            let ctl = this._controller;
            ctl.on(TransmuxingEvents.IO_ERROR, this._onIOError.bind(this));
            ctl.on(TransmuxingEvents.DEMUX_ERROR, this._onDemuxError.bind(this));
            ctl.on(TransmuxingEvents.INIT_SEGMENT, this._onInitSegment.bind(this));
            ctl.on(TransmuxingEvents.MEDIA_SEGMENT, this._onMediaSegment.bind(this));
            ctl.on(TransmuxingEvents.LOADING_COMPLETE, this._onLoadingComplete.bind(this));
            ctl.on(TransmuxingEvents.RECOVERED_EARLY_EOF, this._onRecoveredEarlyEof.bind(this));
            ctl.on(TransmuxingEvents.MEDIA_INFO, this._onMediaInfo.bind(this));
            ctl.on(TransmuxingEvents.METADATA_ARRIVED, this._onMetaDataArrived.bind(this));
            ctl.on(TransmuxingEvents.SCRIPTDATA_ARRIVED, this._onScriptDataArrived.bind(this));
            ctl.on(TransmuxingEvents.STATISTICS_INFO, this._onStatisticsInfo.bind(this));
            ctl.on(TransmuxingEvents.RECOMMEND_SEEKPOINT, this._onRecommendSeekpoint.bind(this));
        }
    }

    destroy() {
        if (this._worker) {
            if (!this._workerDestroying) {
                this._workerDestroying = true;
                this._worker.postMessage({cmd: 'destroy'});
                LoggingControl.removeListener(this.e.onLoggingConfigChanged);
                this.e = null;
            }
        } else {
            this._controller.destroy();
            this._controller = null;
        }
        this._emitter.removeAllListeners();
        this._emitter = null;
    }

    on(event, listener) {
        this._emitter.addListener(event, listener);
    }

    off(event, listener) {
        this._emitter.removeListener(event, listener);
    }

    hasWorker() {
        return this._worker != null;
    }

    open() {
        if (this._worker) {
            this._worker.postMessage({cmd: 'start'});
        } else {
            this._controller.start();
        }
    }

    close() {
        if (this._worker) {
            this._worker.postMessage({cmd: 'stop'});
        } else {
            this._controller.stop();
        }
    }

    seek(milliseconds) {
        if (this._worker) {
            this._worker.postMessage({cmd: 'seek', param: milliseconds});
        } else {
            this._controller.seek(milliseconds);
        }
    }

    pause() {
        if (this._worker) {
            this._worker.postMessage({cmd: 'pause'});
        } else {
            this._controller.pause();
        }
    }

    resume() {
        if (this._worker) {
            this._worker.postMessage({cmd: 'resume'});
        } else {
            this._controller.resume();
        }
    }

    _onInitSegment(type, initSegment) {
        // do async invoke
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.INIT_SEGMENT, type, initSegment);
        });
    }

    _onMediaSegment(type, mediaSegment) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.MEDIA_SEGMENT, type, mediaSegment);
        });
    }

    _onLoadingComplete() {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.LOADING_COMPLETE);
        });
    }

    _onRecoveredEarlyEof() {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.RECOVERED_EARLY_EOF);
        });
    }

    _onMediaInfo(mediaInfo) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.MEDIA_INFO, mediaInfo);
        });
    }

    _onMetaDataArrived(metadata) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.METADATA_ARRIVED, metadata);
        });
    }

    _onScriptDataArrived(data) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.SCRIPTDATA_ARRIVED, data);
        });
    }

    _onStatisticsInfo(statisticsInfo) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.STATISTICS_INFO, statisticsInfo);
        });
    }

    _onIOError(type, info) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.IO_ERROR, type, info);
        });
    }

    _onDemuxError(type, info) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.DEMUX_ERROR, type, info);
        });
    }

    _onRecommendSeekpoint(milliseconds) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.RECOMMEND_SEEKPOINT, milliseconds);
        });
    }

    _onLoggingConfigChanged(config) {
        if (this._worker) {
            this._worker.postMessage({cmd: 'logging_config', param: config});
        }
    }

    _onWorkerMessage(e) {
        let message = e.data;
        let data = message.data;

        if (message.msg === 'destroyed' || this._workerDestroying) {
            this._workerDestroying = false;
            this._worker.terminate();
            this._worker = null;
            return;
        }

        switch (message.msg) {
            case TransmuxingEvents.INIT_SEGMENT:
            case TransmuxingEvents.MEDIA_SEGMENT:
                this._emitter.emit(message.msg, data.type, data.data);
                break;
            case TransmuxingEvents.LOADING_COMPLETE:
            case TransmuxingEvents.RECOVERED_EARLY_EOF:
                this._emitter.emit(message.msg);
                break;
            case TransmuxingEvents.MEDIA_INFO:
                Object.setPrototypeOf(data, MediaInfo.prototype);
                this._emitter.emit(message.msg, data);
                break;
            case TransmuxingEvents.METADATA_ARRIVED:
            case TransmuxingEvents.SCRIPTDATA_ARRIVED:
            case TransmuxingEvents.STATISTICS_INFO:
                this._emitter.emit(message.msg, data);
                break;
            case TransmuxingEvents.IO_ERROR:
            case TransmuxingEvents.DEMUX_ERROR:
                this._emitter.emit(message.msg, data.type, data.info);
                break;
            case TransmuxingEvents.RECOMMEND_SEEKPOINT:
                this._emitter.emit(message.msg, data);
                break;
            case 'logcat_callback':
                Log.emitter.emit('log', data.type, data.logcat);
                break;
            default:
                break;
        }
    }

}

export default Transmuxer;<commit_msg>transmuxer: Migrate to webworkify-webpack<commit_after>/*
 * Copyright (C) 2016 Bilibili. All Rights Reserved.
 *
 * @author zheng qian <xqq@xqq.im>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import EventEmitter from 'events';
import work from 'webworkify-webpack';
import Log from '../utils/logger.js';
import LoggingControl from '../utils/logging-control.js';
import TransmuxingController from './transmuxing-controller.js';
import TransmuxingEvents from './transmuxing-events.js';
import TransmuxingWorker from './transmuxing-worker.js';
import MediaInfo from './media-info.js';

class Transmuxer {

    constructor(mediaDataSource, config) {
        this.TAG = 'Transmuxer';
        this._emitter = new EventEmitter();

        if (config.enableWorker && typeof (Worker) !== 'undefined') {
            try {
                this._worker = work(require.resolve('./transmuxing-worker'));
                this._workerDestroying = false;
                this._worker.addEventListener('message', this._onWorkerMessage.bind(this));
                this._worker.postMessage({cmd: 'init', param: [mediaDataSource, config]});
                this.e = {
                    onLoggingConfigChanged: this._onLoggingConfigChanged.bind(this)
                };
                LoggingControl.registerListener(this.e.onLoggingConfigChanged);
                this._worker.postMessage({cmd: 'logging_config', param: LoggingControl.getConfig()});
            } catch (error) {
                Log.e(this.TAG, 'Error while initialize transmuxing worker, fallback to inline transmuxing');
                this._worker = null;
                this._controller = new TransmuxingController(mediaDataSource, config);
            }
        } else {
            this._controller = new TransmuxingController(mediaDataSource, config);
        }

        if (this._controller) {
            let ctl = this._controller;
            ctl.on(TransmuxingEvents.IO_ERROR, this._onIOError.bind(this));
            ctl.on(TransmuxingEvents.DEMUX_ERROR, this._onDemuxError.bind(this));
            ctl.on(TransmuxingEvents.INIT_SEGMENT, this._onInitSegment.bind(this));
            ctl.on(TransmuxingEvents.MEDIA_SEGMENT, this._onMediaSegment.bind(this));
            ctl.on(TransmuxingEvents.LOADING_COMPLETE, this._onLoadingComplete.bind(this));
            ctl.on(TransmuxingEvents.RECOVERED_EARLY_EOF, this._onRecoveredEarlyEof.bind(this));
            ctl.on(TransmuxingEvents.MEDIA_INFO, this._onMediaInfo.bind(this));
            ctl.on(TransmuxingEvents.METADATA_ARRIVED, this._onMetaDataArrived.bind(this));
            ctl.on(TransmuxingEvents.SCRIPTDATA_ARRIVED, this._onScriptDataArrived.bind(this));
            ctl.on(TransmuxingEvents.STATISTICS_INFO, this._onStatisticsInfo.bind(this));
            ctl.on(TransmuxingEvents.RECOMMEND_SEEKPOINT, this._onRecommendSeekpoint.bind(this));
        }
    }

    destroy() {
        if (this._worker) {
            if (!this._workerDestroying) {
                this._workerDestroying = true;
                this._worker.postMessage({cmd: 'destroy'});
                LoggingControl.removeListener(this.e.onLoggingConfigChanged);
                this.e = null;
            }
        } else {
            this._controller.destroy();
            this._controller = null;
        }
        this._emitter.removeAllListeners();
        this._emitter = null;
    }

    on(event, listener) {
        this._emitter.addListener(event, listener);
    }

    off(event, listener) {
        this._emitter.removeListener(event, listener);
    }

    hasWorker() {
        return this._worker != null;
    }

    open() {
        if (this._worker) {
            this._worker.postMessage({cmd: 'start'});
        } else {
            this._controller.start();
        }
    }

    close() {
        if (this._worker) {
            this._worker.postMessage({cmd: 'stop'});
        } else {
            this._controller.stop();
        }
    }

    seek(milliseconds) {
        if (this._worker) {
            this._worker.postMessage({cmd: 'seek', param: milliseconds});
        } else {
            this._controller.seek(milliseconds);
        }
    }

    pause() {
        if (this._worker) {
            this._worker.postMessage({cmd: 'pause'});
        } else {
            this._controller.pause();
        }
    }

    resume() {
        if (this._worker) {
            this._worker.postMessage({cmd: 'resume'});
        } else {
            this._controller.resume();
        }
    }

    _onInitSegment(type, initSegment) {
        // do async invoke
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.INIT_SEGMENT, type, initSegment);
        });
    }

    _onMediaSegment(type, mediaSegment) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.MEDIA_SEGMENT, type, mediaSegment);
        });
    }

    _onLoadingComplete() {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.LOADING_COMPLETE);
        });
    }

    _onRecoveredEarlyEof() {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.RECOVERED_EARLY_EOF);
        });
    }

    _onMediaInfo(mediaInfo) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.MEDIA_INFO, mediaInfo);
        });
    }

    _onMetaDataArrived(metadata) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.METADATA_ARRIVED, metadata);
        });
    }

    _onScriptDataArrived(data) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.SCRIPTDATA_ARRIVED, data);
        });
    }

    _onStatisticsInfo(statisticsInfo) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.STATISTICS_INFO, statisticsInfo);
        });
    }

    _onIOError(type, info) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.IO_ERROR, type, info);
        });
    }

    _onDemuxError(type, info) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.DEMUX_ERROR, type, info);
        });
    }

    _onRecommendSeekpoint(milliseconds) {
        Promise.resolve().then(() => {
            this._emitter.emit(TransmuxingEvents.RECOMMEND_SEEKPOINT, milliseconds);
        });
    }

    _onLoggingConfigChanged(config) {
        if (this._worker) {
            this._worker.postMessage({cmd: 'logging_config', param: config});
        }
    }

    _onWorkerMessage(e) {
        let message = e.data;
        let data = message.data;

        if (message.msg === 'destroyed' || this._workerDestroying) {
            this._workerDestroying = false;
            this._worker.terminate();
            this._worker = null;
            return;
        }

        switch (message.msg) {
            case TransmuxingEvents.INIT_SEGMENT:
            case TransmuxingEvents.MEDIA_SEGMENT:
                this._emitter.emit(message.msg, data.type, data.data);
                break;
            case TransmuxingEvents.LOADING_COMPLETE:
            case TransmuxingEvents.RECOVERED_EARLY_EOF:
                this._emitter.emit(message.msg);
                break;
            case TransmuxingEvents.MEDIA_INFO:
                Object.setPrototypeOf(data, MediaInfo.prototype);
                this._emitter.emit(message.msg, data);
                break;
            case TransmuxingEvents.METADATA_ARRIVED:
            case TransmuxingEvents.SCRIPTDATA_ARRIVED:
            case TransmuxingEvents.STATISTICS_INFO:
                this._emitter.emit(message.msg, data);
                break;
            case TransmuxingEvents.IO_ERROR:
            case TransmuxingEvents.DEMUX_ERROR:
                this._emitter.emit(message.msg, data.type, data.info);
                break;
            case TransmuxingEvents.RECOMMEND_SEEKPOINT:
                this._emitter.emit(message.msg, data);
                break;
            case 'logcat_callback':
                Log.emitter.emit('log', data.type, data.logcat);
                break;
            default:
                break;
        }
    }

}

export default Transmuxer;<|endoftext|>