<commit_before>(function(d){var f={$eq:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]===a}},$gt:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]>a}},$gte:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]>=a}},$lt:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]<a}},$lte:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]<=a}},$ne:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]!==a}},$in:function(c,a){return function(b){return b.hasOwnProperty(c)&&
-1<a.indexOf(b[c])}},$nin:function(c,a){return function(b){return b.hasOwnProperty(c)&&-1===a.indexOf(b[c])}},$exists:function(c,a){return function(b){return b.hasOwnProperty(c)===a}},$all:function(c,a){return function(b){return b.hasOwnProperty(c)&&a.every(function(a){return-1<b[c].indexOf(a)})}},$size:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c].length===a}},$elemMatch:function(c,a){var b=m(c,a);return function(a){return a.hasOwnProperty(c)&&a[c].some(function(a){var h={};h[c]=
a;return b.every(function(b){return b(h)})})}},$not:function(c,a){var b=m(c,a);return function(a){return!a.hasOwnProperty(c)||b.every(function(b){return!b(a)})}}},l={$and:function(c,a){var b=a.map(u).reduce(d.concat);return function(a){return b.every(function(b){return b(a)})}},$or:function(c,a){var b=a.map(u);return function(a){return b.some(function(b){return b.every(function(b){return b(a)})})}},$nor:function(c,a){var b=this.$and(c,a);return function(a){return!b(a)}}},n={$inc:function(c,a){return g(a,
function(b,c){c.hasOwnProperty(b)&&(c[b]+=a[b])})},$mul:function(c,a){return g(a,function(b,c){c.hasOwnProperty(b)&&(c[b]*=a[b])})},$rename:function(c,a){return g(a,function(b,c){var e=c[b];delete c[b];c[a[b]]=e})},$set:function(c,a){return g(a,function(b,c){c[b]=a[b]})},$unset:function(c,a){return g(a,function(b,a){delete a[b]})},$min:function(c,a){return g(a,function(b,c){c[b]=Math.min(c[b],a[b])})},$max:function(c,a){return g(a,function(b,c){c[b]=Math.max(c[b],a[b])})},$addToSet:function(c,a){return g(a,
function(b,c){d.checkIsArrayField(c,b)?-1===c[b].indexOf(a[b])&&c[b].push(a[b]):c[b]=[a[b]]})},$pop:function(c,a){return g(a,function(b,c){d.checkIsArrayField(c,b);1===a[b]?c[b].pop():-1===a[b]&&c[b].shift()})},$push:function(c,a){return g(a,function(b,c){d.checkIsArrayField(c,b)?c[b].push(a[b]):c[b]=[a[b]]})},$pullAll:function(c,a){return g(a,function(b,c){d.checkIsArrayField(c,b);var e=a[b];c[b]=c[b].filter(function(b){return-1===e.indexOf(b)})})},$pull:function(c,a){return g(a,function(b,c){d.checkIsArrayField(c,
b);var e=a[b];if(d.isPlainValue(e))c[b]=c[b].filter(function(b){return b!==e});else{var k=m(b,e);c[b]=c[b].filter(function(a){var c={};c[b]=a;return!k.some(function(b){return b(c)})})}})},$slice:function(c,a){return g(a,function(b,c){d.checkIsArrayField(c,b);var e=a[b];if(d.isPlainValue(e))c[b]=d.sliceArray(c[b],e);else{var k=Object.keys(e);c[b]=c[b].map(function(b){return k.reduce(function(b,a){b[a]=d.sliceArray(b[a],e[a]);return b},b)})}})},$sort:function(c,a){return g(a,function(b,c){d.checkIsArrayField(c,
b);var e=a[b];if(d.isPlainValue(e))c[b]=c[b].sort(function(b,a){return d.valueComparator(b,a,e)});else{var k=c[b].slice();c[b]=Object.keys(e).reduce(function(b,a){var c=e[a];return k.sort(function(b,h){return d.valueComparator(b[a],h[a],c)})},c[b])}})}},v=Object.keys(f),w=Object.keys(l),x=Object.keys(n),u=function(c){return Object.keys(c).map(function(a){return m(a,c[a])}).reduce(d.concat)},m=function(c,a){return Object.keys(a).map(function(b){return p({key:c,type:b,value:a[b]})})},q=function(c,a){a=
a||Object.keys(c);return function(b){return a.every(function(a){return b.hasOwnProperty(a)&&b[a]===c[a]})}},y=function(c,a){a=a||Object.keys(c);return function(b){a.forEach(function(a){b.hasOwnProperty(a)&&(b[a]=c[a])})}},g=function(c,a){var b=Object.keys(c);return function(c){b.forEach(function(b){a(b,c)})}},z=function(c,a){var b=-1,h=-1,d=-1;a.indexedKeys.forEach(function(a,c){a.unique?b=c:"number"===typeof a.value?h=c:a.plain&&(d=c)});return-1<b?a.indexedKeys[b]:-1<h?a.indexedKeys[h]:a.indexedKeys[d]},
A=function(c){return c.queryOperators.advanced.map(function(a){return a.operators.map(function(b){return p({type:b,key:a.key,value:a.value[b]})})}).reduce(d.concat)},B=function(c){return c.updateOperators.advanced.map(function(a){return p({type:a.key,key:null,value:a.value})})},r=function(c){var a=A(c);return function(b){return a.every(function(a){return a(b)})}},C=function(c){var a=B(c);return function(b){a.forEach(function(a){a(b)})}},t=function(c){return c.queryOperators.plain.map(function(a){return a.key})},
D={primaryKey:function(c,a,b){var d=a.primaryKey.value;b=b.where(a.primaryKey.key).equals(d);0<a.queryOperators.plain.length&&(c=q(c,t(a)),b.and(c));0<a.queryOperators.advanced.length&&(a=r(a),b.and(a));return b},indexedProp:function(c,a,b){var d=z(c,a);b=d&&d.plain?b.where(d.key).equals(d.value):b.toCollection();0<a.queryOperators.plain.length&&(c=q(c,t(a)),b.and(c));0<a.queryOperators.advanced.length&&(a=r(a),b.and(a));return b},fullScan:function(c,a,b){b=b.toCollection();0<a.queryOperators.plain.length&&
(c=q(c,t(a)),b.and(c));0<a.queryOperators.advanced.length&&(a=r(a),b.and(a));return b}},E=function(c,a){var b=0<a.updateOperators.plain.length,d=0<a.updateOperators.advanced.length;if(b&&d)return function(){};if(b)return y(c,a.keys);if(d)return C(a)},p=function(c){var a;-1<v.indexOf(c.type)?a=f:-1<w.indexOf(c.type)?a=l:-1<x.indexOf(c.type)&&(a=n);return a[c.type](c.key,c.value)},F=function(c,a){return function(b,a){var e=c[a],k=d.isPlainValue(e),f=-1<w.indexOf(a);k?b.plain.push({key:a,value:e,plain:k}):
f?(f={},f[a]=e,b.advanced.push({key:a,value:f,plain:k,operators:[a]})):b.advanced.push({key:a,value:e,plain:k,operators:Object.keys(e).filter(function(a){return-1<v.indexOf(a)})});return b}},G=function(c,a){return function(a,h){var e=c[h],f=d.isPlainValue(e);f?a.plain.push({key:h,value:e,plain:f}):a.advanced.push({key:h,value:e,plain:f});return a}},H=function(c,a,b){return b.indexes.filter(function(b){return-1<a.indexOf(b.keyPath)}).map(function(a){var b=a.keyPath;return{key:b,value:c[b],unique:a.unique,
plain:d.isPlainValue(c[b])}})};Dexie.addons.push(function(c){Dexie.prototype.collection=function(a){return c.table(a)};c.Table.prototype.count=function(a){return(d.isEmptyValue(a)?this.toCollection():this.find(a)).count()};c.Table.prototype.find=function(a){if(d.isEmptyValue(a))return this.toCollection();var b;b=this.schema;var c=Object.keys(a),e=c.reduce(F(a,c),{plain:[],advanced:[]}),f=b.primKey.keyPath,g=a[f],l=typeof g;b={keys:c,queryOperators:e,primaryKey:"number"===l||"string"===l?{key:f,value:g}:
{key:!1},indexedKeys:H(a,c,b)};b={queryAnalysis:b,execute:D[b.primaryKey.key?"primaryKey":0<b.indexedKeys.length?"indexedProp":"fullScan"]};return b.execute(a,b.queryAnalysis,this)};c.Table.prototype.findOne=function(a){return this.find(a).first()};c.Table.prototype.insert=function(a){return this.add(a)};c.Table.prototype.remove=function(a){return this.find(a)["delete"]()};c.Table.prototype.drop=function(){return this.toCollection()["delete"]()};c.WriteableTable.prototype.update=function(a,b){var c=
d.isEmptyValue(a)?this.toCollection():this.find(a),e;e=Object.keys(b);e={keys:e,updateOperators:e.reduce(G(b,e),{plain:[],advanced:[]})};e=E(b,e);return c.modify(e)}})})({isEmptyValue:function(d){return!("object"===typeof d&&null!==d&&d)||0===Object.keys(d).length},isPlainValue:function(d){d=typeof d;return"number"===d||"string"===d||"boolean"===d},checkIsArrayField:function(d,f){var l=d.hasOwnProperty(f),n=Array.isArray(d[f]);if(l&&!n)throw Error("You can't use array update operator on non-array field");
return l},concat:function(d,f){return d.concat(f)},sliceArray:function(d,f){return 0<=f?d.slice(0,f):d.slice(f)},valueComparator:function(d,f,l){return 1===l?d>f:d<f}});
<commit_msg>Update dist<commit_after>(function(f,e){var k={$eq:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]===a}},$gt:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]>a}},$gte:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]>=a}},$lt:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]<a}},$lte:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]<=a}},$ne:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c]!==a}},$in:function(c,a){return function(b){return b.hasOwnProperty(c)&&
-1<a.indexOf(b[c])}},$nin:function(c,a){return function(b){return b.hasOwnProperty(c)&&-1===a.indexOf(b[c])}},$exists:function(c,a){return function(b){return b.hasOwnProperty(c)===a}},$all:function(c,a){return function(b){return b.hasOwnProperty(c)&&a.every(function(a){return-1<b[c].indexOf(a)})}},$size:function(c,a){return function(b){return b.hasOwnProperty(c)&&b[c].length===a}},$elemMatch:function(c,a){var b=m(c,a);return function(a){return a.hasOwnProperty(c)&&a[c].some(function(a){var d={};d[c]=
a;return b.every(function(b){return b(d)})})}},$not:function(c,a){var b=m(c,a);return function(a){return!a.hasOwnProperty(c)||b.every(function(b){return!b(a)})}}},n={$and:function(c,a){var b=a.map(u).reduce(e.concat);return function(a){return b.every(function(b){return b(a)})}},$or:function(c,a){var b=a.map(u);return function(a){return b.some(function(b){return b.every(function(b){return b(a)})})}},$nor:function(c,a){var b=this.$and(c,a);return function(a){return!b(a)}}},v={$inc:function(c,a){return g(a,
function(b,d){d.hasOwnProperty(b)&&(d[b]+=a[b])})},$mul:function(c,a){return g(a,function(b,d){d.hasOwnProperty(b)&&(d[b]*=a[b])})},$rename:function(c,a){return g(a,function(b,d){var c=d[b];delete d[b];d[a[b]]=c})},$set:function(c,a){return g(a,function(b,d){d[b]=a[b]})},$unset:function(c,a){return g(a,function(b,a){delete a[b]})},$min:function(c,a){return g(a,function(b,d){d[b]=Math.min(d[b],a[b])})},$max:function(c,a){return g(a,function(b,d){d[b]=Math.max(d[b],a[b])})},$addToSet:function(c,a){return g(a,
function(b,d){e.checkIsArrayField(d,b)?-1===d[b].indexOf(a[b])&&d[b].push(a[b]):d[b]=[a[b]]})},$pop:function(c,a){return g(a,function(b,d){e.checkIsArrayField(d,b);1===a[b]?d[b].pop():-1===a[b]&&d[b].shift()})},$push:function(c,a){return g(a,function(b,d){e.checkIsArrayField(d,b)?d[b].push(a[b]):d[b]=[a[b]]})},$pullAll:function(c,a){return g(a,function(b,d){e.checkIsArrayField(d,b);var c=a[b];d[b]=d[b].filter(function(b){return-1===c.indexOf(b)})})},$pull:function(c,a){return g(a,function(b,d){e.checkIsArrayField(d,
b);var c=a[b];if(e.isPlainValue(c))d[b]=d[b].filter(function(b){return b!==c});else{var l=m(b,c);d[b]=d[b].filter(function(a){var c={};c[b]=a;return!l.some(function(b){return b(c)})})}})},$slice:function(c,a){return g(a,function(b,c){e.checkIsArrayField(c,b);var h=a[b];if(e.isPlainValue(h))c[b]=e.sliceArray(c[b],h);else{var l=Object.keys(h);c[b]=c[b].map(function(b){return l.reduce(function(b,a){b[a]=e.sliceArray(b[a],h[a]);return b},b)})}})},$sort:function(c,a){return g(a,function(b,c){e.checkIsArrayField(c,
b);var h=a[b];if(e.isPlainValue(h))c[b]=c[b].sort(function(b,a){return e.valueComparator(b,a,h)});else{var l=c[b].slice();c[b]=Object.keys(h).reduce(function(b,a){var c=h[a];return l.sort(function(b,d){return e.valueComparator(b[a],d[a],c)})},c[b])}})}},w=Object.keys(k),x=Object.keys(n),y=Object.keys(v),u=function(c){return Object.keys(c).map(function(a){return m(a,c[a])}).reduce(e.concat)},m=function(c,a){return Object.keys(a).map(function(b){return p({key:c,type:b,value:a[b]})})},q=function(c,a){a=
a||Object.keys(c);return function(b){return a.every(function(a){return b.hasOwnProperty(a)&&b[a]===c[a]})}},z=function(c,a){a=a||Object.keys(c);return function(b){a.forEach(function(a){b.hasOwnProperty(a)&&(b[a]=c[a])})}},g=function(c,a){var b=Object.keys(c);return function(c){b.forEach(function(b){a(b,c)})}},A=function(c,a){var b=-1,d=-1,e=-1;a.indexedKeys.forEach(function(a,c){a.unique?b=c:"number"===typeof a.value?d=c:a.plain&&(e=c)});return-1<b?a.indexedKeys[b]:-1<d?a.indexedKeys[d]:a.indexedKeys[e]},
B=function(c){return c.queryOperators.advanced.map(function(a){return a.operators.map(function(b){return p({type:b,key:a.key,value:a.value[b]})})}).reduce(e.concat)},C=function(c){return c.updateOperators.advanced.map(function(a){return p({type:a.key,key:null,value:a.value})})},r=function(c){var a=B(c);return function(b){return a.every(function(a){return a(b)})}},D=function(c){var a=C(c);return function(b){a.forEach(function(a){a(b)})}},t=function(c){return c.queryOperators.plain.map(function(a){return a.key})},
E={primaryKey:function(c,a,b){var d=a.primaryKey.value;b=b.where(a.primaryKey.key).equals(d);0<a.queryOperators.plain.length&&(c=q(c,t(a)),b.and(c));0<a.queryOperators.advanced.length&&(a=r(a),b.and(a));return b},indexedProp:function(c,a,b){var d=A(c,a);b=d&&d.plain?b.where(d.key).equals(d.value):b.toCollection();0<a.queryOperators.plain.length&&(c=q(c,t(a)),b.and(c));0<a.queryOperators.advanced.length&&(a=r(a),b.and(a));return b},fullScan:function(c,a,b){b=b.toCollection();0<a.queryOperators.plain.length&&
(c=q(c,t(a)),b.and(c));0<a.queryOperators.advanced.length&&(a=r(a),b.and(a));return b}},F=function(c,a){var b=0<a.updateOperators.plain.length,d=0<a.updateOperators.advanced.length;if(b&&d)return function(){};if(b)return z(c,a.keys);if(d)return D(a)},p=function(c){var a;-1<w.indexOf(c.type)?a=k:-1<x.indexOf(c.type)?a=n:-1<y.indexOf(c.type)&&(a=v);return a[c.type](c.key,c.value)},G=function(c,a){return function(b,a){var h=c[a],f=e.isPlainValue(h),g=-1<x.indexOf(a);f?b.plain.push({key:a,value:h,plain:f}):
g?(g={},g[a]=h,b.advanced.push({key:a,value:g,plain:f,operators:[a]})):b.advanced.push({key:a,value:h,plain:f,operators:Object.keys(h).filter(function(b){return-1<w.indexOf(b)})});return b}},H=function(c,a){return function(b,a){var f=c[a],l=e.isPlainValue(f);l?b.plain.push({key:a,value:f,plain:l}):b.advanced.push({key:a,value:f,plain:l});return b}},I=function(c,a,b){return b.indexes.filter(function(b){return-1<a.indexOf(b.keyPath)}).map(function(b){var a=b.keyPath;return{key:a,value:c[a],unique:b.unique,
plain:e.isPlainValue(c[a])}})};f(function(c){c.addons.push(function(a){c.prototype.collection=function(b){return a.table(b)};a.Table.prototype.count=function(b){return(e.isEmptyValue(b)?this.toCollection():this.find(b)).count()};a.Table.prototype.find=function(b){if(e.isEmptyValue(b))return this.toCollection();var a;a=this.schema;var c=Object.keys(b),f=c.reduce(G(b,c),{plain:[],advanced:[]}),g=a.primKey.keyPath,k=b[g],m=typeof k;a={keys:c,queryOperators:f,primaryKey:"number"===m||"string"===m?{key:g,
value:k}:{key:!1},indexedKeys:I(b,c,a)};a={queryAnalysis:a,execute:E[a.primaryKey.key?"primaryKey":0<a.indexedKeys.length?"indexedProp":"fullScan"]};return a.execute(b,a.queryAnalysis,this)};a.Table.prototype.findOne=function(a){return this.find(a).first()};a.Table.prototype.insert=function(a){return this.add(a)};a.Table.prototype.remove=function(a){return this.find(a)["delete"]()};a.Table.prototype.drop=function(){return this.toCollection()["delete"]()};a.WriteableTable.prototype.update=function(a,
c){var f=e.isEmptyValue(a)?this.toCollection():this.find(a),g;g=Object.keys(c);g={keys:g,updateOperators:g.reduce(H(c,g),{plain:[],advanced:[]})};g=F(c,g);return f.modify(g)}})})})(function(f){"function"===typeof define&&define.amd?define(["Dexie"],function(e){f(e)}):"undefined"!==typeof global&&"undefined"!==typeof module&&module.exports?module.exports=function(e){f(e)}:f(Dexie)},{isEmptyValue:function(f){return!("object"===typeof f&&null!==f&&f)||0===Object.keys(f).length},isPlainValue:function(f){f=
typeof f;return"number"===f||"string"===f||"boolean"===f},checkIsArrayField:function(f,e){var k=f.hasOwnProperty(e),n=Array.isArray(f[e]);if(k&&!n)throw Error("You can't use array update operator on non-array field");return k},concat:function(f,e){return f.concat(e)},sliceArray:function(f,e){return 0<=e?f.slice(0,e):f.slice(e)},valueComparator:function(f,e,k){return 1===k?f>e:f<e}});
<|endoftext|>


<commit_before>function HTMLActuator() {
  this.tileContainer    = document.querySelector(".tile-container");
  this.scoreContainer   = document.querySelector(".score-container");
  this.bestContainer    = document.querySelector(".best-container");
  this.messageContainer = document.querySelector(".game-message");
  this.sharingContainer = document.querySelector(".score-sharing");

  this.score = 0;
}

HTMLActuator.prototype.actuate = function (grid, metadata) {
  var self = this;

  window.requestAnimationFrame(function () {
    self.clearContainer(self.tileContainer);

    grid.cells.forEach(function (column) {
      column.forEach(function (cell) {
        if (cell) {
          self.addTile(cell);
        }
      });
    });

    self.updateScore(metadata.score);
    self.updateBestScore(metadata.bestScore);

    if (metadata.terminated) {
      if (metadata.over) {
        self.message(false); // You lose
      } else if (metadata.won) {
        self.message(true); // You win!
      }
    }

  });
};

// Continues the game (both restart and keep playing)
HTMLActuator.prototype.continue = function () {
  if (typeof ga !== "undefined") {
    ga("send", "event", "game", "restart");
  }

  this.clearMessage();
};

HTMLActuator.prototype.clearContainer = function (container) {
  while (container.firstChild) {
    container.removeChild(container.firstChild);
  }
};

HTMLActuator.prototype.addTile = function (tile) {
  var text = new Array();
  text[0] = "SUBSPECIES"
  text[1] = "SPECIES"
  text[2] = "GENUS"
  text[3] = "FAMILY"
  text[4] = "ORDER"
  text[5] = "CLASS"
  text[6] = "PHYLUM"
  text[7] = "KINGDOM"
  text[8] = "DOMAIN"
  text[9] = "LIFE"
  text[10] = "42"
  text[11] = "42"
  var self = this;
  var text2 = function (n) { var r = 0; while (n > 1) r++, n >>= 1; return r; }

  var wrapper   = document.createElement("div");
  var inner     = document.createElement("div");
  var position  = tile.previousPosition || { x: tile.x, y: tile.y };
  var positionClass = this.positionClass(position);

  // We can't use classlist because it somehow glitches when replacing classes
  var classes = ["tile", "tile-" + tile.value, positionClass];

  if (tile.value > 2048) classes.push("tile-super");

  this.applyClasses(wrapper, classes);

  inner.classList.add("tile-inner");
  inner.textContent = text[text2(tile.value)];

  if (tile.previousPosition) {
    // Make sure that the tile gets rendered in the previous position first
    window.requestAnimationFrame(function () {
      classes[2] = self.positionClass({ x: tile.x, y: tile.y });
      self.applyClasses(wrapper, classes); // Update the position
    });
  } else if (tile.mergedFrom) {
    classes.push("tile-merged");
    this.applyClasses(wrapper, classes);

    // Render the tiles that merged
    tile.mergedFrom.forEach(function (merged) {
      self.addTile(merged);
    });
  } else {
    classes.push("tile-new");
    this.applyClasses(wrapper, classes);
  }

  // Add the inner part of the tile to the wrapper
  wrapper.appendChild(inner);

  // Put the tile on the board
  this.tileContainer.appendChild(wrapper);
};

HTMLActuator.prototype.applyClasses = function (element, classes) {
  element.setAttribute("class", classes.join(" "));
};

HTMLActuator.prototype.normalizePosition = function (position) {
  return { x: position.x + 1, y: position.y + 1 };
};

HTMLActuator.prototype.positionClass = function (position) {
  position = this.normalizePosition(position);
  return "tile-position-" + position.x + "-" + position.y;
};

HTMLActuator.prototype.updateScore = function (score) {
  this.clearContainer(this.scoreContainer);

  var difference = score - this.score;
  this.score = score;

  this.scoreContainer.textContent = this.score;

  if (difference > 0) {
    var addition = document.createElement("div");
    addition.classList.add("score-addition");
    addition.textContent = "+" + difference;

    this.scoreContainer.appendChild(addition);
  }
};

HTMLActuator.prototype.updateBestScore = function (bestScore) {
  this.bestContainer.textContent = bestScore;
};

HTMLActuator.prototype.message = function (won) {
  var mytxt=new Array(9);
  mytxt[0]="";
  mytxt[1]="！";
  mytxt[2]="！";
  mytxt[3]="……";
  mytxt[4]="！";
  mytxt[5]="……";
  mytxt[6]="，！";
  mytxt[7]="……";
  mytxt[8]=" = =";

  var text3 = function (m) { var r = 0; while (m > 1) r++, m >>= 1; return r; }
  var type    = won ? "game-won" : "game-over";
  var message = won ? "Congratulations! You have reached the top of biological classification." : mytxt[text3(maxscore)-2];

  if (typeof ga !== "undefined") {
    ga("send", "event", "game", "end", type, this.score);
  }

  this.messageContainer.classList.add(type);
  this.messageContainer.getElementsByTagName("p")[0].textContent = message;

  this.clearContainer(this.sharingContainer);
  this.sharingContainer.appendChild(this.scoreTweetButton());
  twttr.widgets.load();
};

HTMLActuator.prototype.clearMessage = function () {
  // IE only takes one value to remove at a time.
  this.messageContainer.classList.remove("game-won");
  this.messageContainer.classList.remove("game-over");
};

HTMLActuator.prototype.scoreTweetButton = function () {
  var tweet = document.createElement("a");
  tweet.classList.add("twitter-share-button");
  tweet.setAttribute("href", "https://twitter.com/share");
  tweet.setAttribute("data-via", "gabrielecirulli");
  tweet.setAttribute("data-url", "http://git.io/2048");
  tweet.setAttribute("data-counturl", "http://gabrielecirulli.github.io/2048/");
  tweet.textContent = "Tweet";

  var text = "I scored " + this.score + " points at life, a game where you " +
             "join ranks of biological classifications to score high! #life_class_game";
  tweet.setAttribute("data-text", text);

  return tweet;
};
<commit_msg>Changed all names into Chinese. 简洁。<commit_after>function HTMLActuator() {
  this.tileContainer    = document.querySelector(".tile-container");
  this.scoreContainer   = document.querySelector(".score-container");
  this.bestContainer    = document.querySelector(".best-container");
  this.messageContainer = document.querySelector(".game-message");
  this.sharingContainer = document.querySelector(".score-sharing");

  this.score = 0;
}

HTMLActuator.prototype.actuate = function (grid, metadata) {
  var self = this;

  window.requestAnimationFrame(function () {
    self.clearContainer(self.tileContainer);

    grid.cells.forEach(function (column) {
      column.forEach(function (cell) {
        if (cell) {
          self.addTile(cell);
        }
      });
    });

    self.updateScore(metadata.score);
    self.updateBestScore(metadata.bestScore);

    if (metadata.terminated) {
      if (metadata.over) {
        self.message(false); // You lose
      } else if (metadata.won) {
        self.message(true); // You win!
      }
    }

  });
};

// Continues the game (both restart and keep playing)
HTMLActuator.prototype.continue = function () {
  if (typeof ga !== "undefined") {
    ga("send", "event", "game", "restart");
  }

  this.clearMessage();
};

HTMLActuator.prototype.clearContainer = function (container) {
  while (container.firstChild) {
    container.removeChild(container.firstChild);
  }
};

HTMLActuator.prototype.addTile = function (tile) {
  var text = new Array();
  text[0] = "亚种"
  text[1] = "种"
  text[2] = "属"
  text[3] = "科"
  text[4] = "目"
  text[5] = "纲"
  text[6] = "门"
  text[7] = "界"
  text[8] = "域"
  text[9] = "生"
  text[10] = "42"
  text[11] = "42"
  var self = this;
  var text2 = function (n) { var r = 0; while (n > 1) r++, n >>= 1; return r; }

  var wrapper   = document.createElement("div");
  var inner     = document.createElement("div");
  var position  = tile.previousPosition || { x: tile.x, y: tile.y };
  var positionClass = this.positionClass(position);

  // We can't use classlist because it somehow glitches when replacing classes
  var classes = ["tile", "tile-" + tile.value, positionClass];

  if (tile.value > 2048) classes.push("tile-super");

  this.applyClasses(wrapper, classes);

  inner.classList.add("tile-inner");
  inner.textContent = text[text2(tile.value)];

  if (tile.previousPosition) {
    // Make sure that the tile gets rendered in the previous position first
    window.requestAnimationFrame(function () {
      classes[2] = self.positionClass({ x: tile.x, y: tile.y });
      self.applyClasses(wrapper, classes); // Update the position
    });
  } else if (tile.mergedFrom) {
    classes.push("tile-merged");
    this.applyClasses(wrapper, classes);

    // Render the tiles that merged
    tile.mergedFrom.forEach(function (merged) {
      self.addTile(merged);
    });
  } else {
    classes.push("tile-new");
    this.applyClasses(wrapper, classes);
  }

  // Add the inner part of the tile to the wrapper
  wrapper.appendChild(inner);

  // Put the tile on the board
  this.tileContainer.appendChild(wrapper);
};

HTMLActuator.prototype.applyClasses = function (element, classes) {
  element.setAttribute("class", classes.join(" "));
};

HTMLActuator.prototype.normalizePosition = function (position) {
  return { x: position.x + 1, y: position.y + 1 };
};

HTMLActuator.prototype.positionClass = function (position) {
  position = this.normalizePosition(position);
  return "tile-position-" + position.x + "-" + position.y;
};

HTMLActuator.prototype.updateScore = function (score) {
  this.clearContainer(this.scoreContainer);

  var difference = score - this.score;
  this.score = score;

  this.scoreContainer.textContent = this.score;

  if (difference > 0) {
    var addition = document.createElement("div");
    addition.classList.add("score-addition");
    addition.textContent = "+" + difference;

    this.scoreContainer.appendChild(addition);
  }
};

HTMLActuator.prototype.updateBestScore = function (bestScore) {
  this.bestContainer.textContent = bestScore;
};

HTMLActuator.prototype.message = function (won) {
  var mytxt=new Array(9);
  mytxt[0]="";
  mytxt[1]="！";
  mytxt[2]="！";
  mytxt[3]="……";
  mytxt[4]="！";
  mytxt[5]="……";
  mytxt[6]="，！";
  mytxt[7]="……";
  mytxt[8]=" = =";

  var text3 = function (m) { var r = 0; while (m > 1) r++, m >>= 1; return r; }
  var type    = won ? "game-won" : "game-over";
  var message = won ? "Congratulations! You have reached the top of biological classification." : mytxt[text3(maxscore)-2];

  if (typeof ga !== "undefined") {
    ga("send", "event", "game", "end", type, this.score);
  }

  this.messageContainer.classList.add(type);
  this.messageContainer.getElementsByTagName("p")[0].textContent = message;

  this.clearContainer(this.sharingContainer);
  this.sharingContainer.appendChild(this.scoreTweetButton());
  twttr.widgets.load();
};

HTMLActuator.prototype.clearMessage = function () {
  // IE only takes one value to remove at a time.
  this.messageContainer.classList.remove("game-won");
  this.messageContainer.classList.remove("game-over");
};

HTMLActuator.prototype.scoreTweetButton = function () {
  var tweet = document.createElement("a");
  tweet.classList.add("twitter-share-button");
  tweet.setAttribute("href", "https://twitter.com/share");
  tweet.setAttribute("data-via", "gabrielecirulli");
  tweet.setAttribute("data-url", "http://git.io/2048");
  tweet.setAttribute("data-counturl", "http://gabrielecirulli.github.io/2048/");
  tweet.textContent = "Tweet";

  var text = "I scored " + this.score + " points at life, a game where you " +
             "join ranks of biological classifications to score high! #life_class_game";
  tweet.setAttribute("data-text", text);

  return tweet;
};
<|endoftext|>


<commit_before>var connect = require('connect');
var server = connect.createServer();

server.use(connect.static(__dirname));
server.use('/lib', connect.static(__dirname + '/../lib'));
server.use(require('browserify')({
  require: [__dirname + '/../lib/eval.js',
            __dirname + '/../lib/lambda.js',
            __dirname + '/../lib/macro.js',
            __dirname + '/../lib/primitives.js',
            __dirname + '/../lib/print.js',
            'util',
            'underscore',
            'pegjs'],
  //filter: require('uglify-js')
}));

server.listen(9797);
console.log('Listening on 9797...');
<commit_msg>Connect to 127.0.0.1 only.<commit_after>var connect = require('connect');
var server = connect.createServer();

server.use(connect.static(__dirname));
server.use('/lib', connect.static(__dirname + '/../lib'));
server.use(require('browserify')({
  require: [__dirname + '/../lib/eval.js',
            __dirname + '/../lib/lambda.js',
            __dirname + '/../lib/macro.js',
            __dirname + '/../lib/primitives.js',
            __dirname + '/../lib/print.js',
            'util',
            'underscore',
            'pegjs'],
  //filter: require('uglify-js')
}));

server.listen(9797, '127.0.0.1');
console.log('Listening on 127.0.0.1:9797...');
<|endoftext|>


<commit_before>'use strict';

const request = require('request');
const core = require('./../core/core.js');

/**
 * CREDENTIALS
 **/
const VALIDATION_TOKEN = process.env.FACEBOOK_VALIDATION_TOKEN;
const PAGE_ACCESS_TOKEN = process.env.FACEBOOK_PAGE_ACCESS_TOKEN;

/*
* Fonction appelé par Facbook pour checker le serveur
*/
function webhook(req, res) {
    return req.query['hub.mode'] === 'subscribe' && req.query['hub.verify_token'] === VALIDATION_TOKEN;
}

/*
* Fonction appelé par les routes lors de la reception d'un message
*/
function receivedMessage(req, res) {
    var data = req.body;
    if (data.object === 'page') {
        //Message reçu de Facebook
        data.entry.forEach(function(entry) {
            var pageID = entry.id;
            var timeOfEvent = entry.time;
            entry.messaging.forEach(function(event) {
                if (event.message) {
                    console.log("Event received : ", JSON.stringify(event));
                    extractMessage(event);
                }
            });
        });
    } else {
        //Pour tester via CURL
        extractMessage(req.body);
    }
}
/*
* Fonction qui permet de traiter un message reçu
*/
function extractMessage(event) {
    var senderID = event.sender.id;
    request({
        uri: 'https://graph.facebook.com/' + senderID,
        qs: { access_token: PAGE_ACCESS_TOKEN },
        headers: { 'Content-Type': 'application/json' },
        method: 'GET'
    }, function (error, response, body) {
        if (!error && response.statusCode == 200) {
            var recipientID = event.recipient.id;
            var timeOfMessage = event.timestamp;
            var message = event.message;

            console.log(JSON.stringify(message));

            var messageText = message.text;
            var messageAttachments = message.attachments;

            try {
                body = JSON.parse(body);
            } catch (err){
            }
            var message = {
                channel: "Facebook",
                senderID: senderID,
                timestamp: timeOfMessage,
                text: messageText,
                first_name: body.first_name,
                last_name: body.last_name
            };
            /*
            *   Coordonnées
            */
            if(messageAttachments != undefined && messageAttachments[0].payload != undefined && messageAttachments[0].payload.coordinates != undefined) {
                message["location"] = messageAttachments[0].payload.coordinates;
            }
            beginWriting(message.senderID);
            core.receivedMessage(message);
        } else {
            console.error("Unable to get name of user.");
            console.error(error);
        }
    });
}

/*
* Fonction appelé par le core pour envoyer un message sur la channel Facebook
*/
function sendMessage(message) {
    switch(message.type) {
        case "text":
            sendTextMessage(message);
        break;
        case "quickreply":
            sendQuickReplyMessage(message);
            break;
        case "location":
            sendLocationMessage(message);
            break;
        case "template":
            sendTemplateMessage(message);
            break;
        break;
    }
}

/*
* Fonction appelé par le core pour envoyer des messages sur la channel Facebook
*/
function sendMessages(messages) {
    for(var i=0;i<messages.length;i++) {
        sendMessage(messages[i]);
    }
}

/*
* Fonction qui envoie un message de type text
*/
function sendTextMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                text: message.text
            }
        };
        callSendAPI(messageData);
    }
}

/*
* Fonction qui envoie un message de type quickreply
*/
function sendQuickReplyMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                text: message.text,
                quick_replies: []
            }
        };
        for(var i=0;i<message.choices.length;i++) {
            var quickreply = {
                content_type: "text",
                title: message.choices[i],
                payload: message.choices[i]
            };
            messageData.message.quick_replies.push(quickreply);
        }
        callSendAPI(messageData);
    }
}

/*
* Fonction qui envoie un message de type location
*/
function sendLocationMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                text: message.text,
                quick_replies: [
                    {
                        "content_type":"location",
                    }
                ]
            }
        };
        callSendAPI(messageData);
    }
}

/*
* Fonction qui envoie un message audio/file/image/video
*/
function sendFileMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                attachment:{
                    type: message.type,
                    payload: {
                        url: message.text
                    }
                }
            }
        };
        callSendAPI(messageData);
    }
}

/*
* Fonction qui envoie un message audio/file/image/video
*/
function sendTemplateMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.attachment != undefined) {
        var elements = [
            {
                title: message.attachment[0].name,
                image_url: message.attachment[0].icon,
                subtitle: message.attachment[0].vicinity + " - " + message.attachment[0].rating + "/5",
                default_action: {
                    type: "web_url",
                    url: "https://peterssendreceiveapp.ngrok.io/view?item=100",
                    messenger_extensions: true,
                    webview_height_ratio: "tall",
                    fallback_url: "https://peterssendreceiveapp.ngrok.io/"
                },
                buttons: [
                    {
                        title: "Y-Aller",
                        type: "web_url",
                        url: "",
                        messenger_extensions: true,
                        webview_height_ratio: "tall"
                    },{
                        title: "Détails",
                        type: "web_url",
                        url: message.attachment[0].details_url,
                        messenger_extensions: true,
                        webview_height_ratio: "tall"
                    }
                ]
            },
            {
                title: message.attachment[1].name,
                image_url: message.attachment[1].icon,
                subtitle: message.attachment[1].vicinity + " - " + message.attachment[1].rating + "/5",
                default_action: {
                    type: "web_url",
                    url: "https://peterssendreceiveapp.ngrok.io/view?item=100",
                    messenger_extensions: true,
                    webview_height_ratio: "tall",
                    fallback_url: "https://peterssendreceiveapp.ngrok.io/"
                },
                buttons: [
                    {
                        title: "Y-Aller",
                        type: "web_url",
                        url: "",
                        messenger_extensions: true,
                        webview_height_ratio: "tall"
                    }, {
                        title: "Détails",
                        type: "web_url",
                        url: message.attachment[1].details_url,
                        messenger_extensions: true,
                        webview_height_ratio: "tall"
                    }
                ]
            }
        ];
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                attachment:{
                    type: message.type,
                    payload: {
                        template_type: "list",
                        top_element_style: "compact",
                        elements: elements

                    }
                }
            }
        };
        callSendAPI(messageData);
    }
}

/*
* Fonction qui appel l'API messages de Facebook
*/
function callSendAPI(messageData) {
    console.log("Messages sended via API : ", JSON.stringify(messageData));
    finishWriting(messageData.recipient.id, function() {
            request({
            uri: 'https://graph.facebook.com/v2.6/me/messages',
            qs: { access_token: PAGE_ACCESS_TOKEN },
            method: 'POST',
            json: messageData
        }, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                var recipientId = body.recipient_id;
                var messageId = body.message_id;

                console.log("Successfully sent generic message with id %s to recipient %s",
                    messageId, recipientId);
            } else {
                console.error("Unable to send message.");
                console.error(error);
                console.error(response);
            }
        });
    });
}

function beginWriting(id) {
    request({
        uri: 'https://graph.facebook.com/v2.6/me/messages',
        qs: { access_token: PAGE_ACCESS_TOKEN },
        method: 'POST',
        json: {recipient:{id: id}, sender_action:"typing_on"}
    }, function (error, response, body) {
        if (!error && response.statusCode == 200) {

        } else {
            console.error("Unable to send message.");
            console.error(error);
        }
    });
}

function finishWriting(id, callback) {
    request({
        uri: 'https://graph.facebook.com/v2.6/me/messages',
        qs: { access_token: PAGE_ACCESS_TOKEN },
        method: 'POST',
        json: {recipient:{id: id}, sender_action:"typing_off"}
    }, function (error, response, body) {
        if (!error && response.statusCode == 200) {
            callback();
        } else {
            console.error("Unable to send message.");
            console.error(error);
        }
    });
}

exports.webhook = webhook
exports.receivedMessage = receivedMessage
exports.sendMessage = sendMessage
exports.sendMessages = sendMessages<commit_msg>Fix bug button template facebook<commit_after>'use strict';

const request = require('request');
const core = require('./../core/core.js');

/**
 * CREDENTIALS
 **/
const VALIDATION_TOKEN = process.env.FACEBOOK_VALIDATION_TOKEN;
const PAGE_ACCESS_TOKEN = process.env.FACEBOOK_PAGE_ACCESS_TOKEN;

/*
* Fonction appelé par Facbook pour checker le serveur
*/
function webhook(req, res) {
    return req.query['hub.mode'] === 'subscribe' && req.query['hub.verify_token'] === VALIDATION_TOKEN;
}

/*
* Fonction appelé par les routes lors de la reception d'un message
*/
function receivedMessage(req, res) {
    var data = req.body;
    if (data.object === 'page') {
        //Message reçu de Facebook
        data.entry.forEach(function(entry) {
            var pageID = entry.id;
            var timeOfEvent = entry.time;
            entry.messaging.forEach(function(event) {
                if (event.message) {
                    console.log("Event received : ", JSON.stringify(event));
                    extractMessage(event);
                }
            });
        });
    } else {
        //Pour tester via CURL
        extractMessage(req.body);
    }
}
/*
* Fonction qui permet de traiter un message reçu
*/
function extractMessage(event) {
    var senderID = event.sender.id;
    request({
        uri: 'https://graph.facebook.com/' + senderID,
        qs: { access_token: PAGE_ACCESS_TOKEN },
        headers: { 'Content-Type': 'application/json' },
        method: 'GET'
    }, function (error, response, body) {
        if (!error && response.statusCode == 200) {
            var recipientID = event.recipient.id;
            var timeOfMessage = event.timestamp;
            var message = event.message;

            console.log(JSON.stringify(message));

            var messageText = message.text;
            var messageAttachments = message.attachments;

            try {
                body = JSON.parse(body);
            } catch (err){
            }
            var message = {
                channel: "Facebook",
                senderID: senderID,
                timestamp: timeOfMessage,
                text: messageText,
                first_name: body.first_name,
                last_name: body.last_name
            };
            /*
            *   Coordonnées
            */
            if(messageAttachments != undefined && messageAttachments[0].payload != undefined && messageAttachments[0].payload.coordinates != undefined) {
                message["location"] = messageAttachments[0].payload.coordinates;
            }
            beginWriting(message.senderID);
            core.receivedMessage(message);
        } else {
            console.error("Unable to get name of user.");
            console.error(error);
        }
    });
}

/*
* Fonction appelé par le core pour envoyer un message sur la channel Facebook
*/
function sendMessage(message) {
    switch(message.type) {
        case "text":
            sendTextMessage(message);
        break;
        case "quickreply":
            sendQuickReplyMessage(message);
            break;
        case "location":
            sendLocationMessage(message);
            break;
        case "template":
            sendTemplateMessage(message);
            break;
        break;
    }
}

/*
* Fonction appelé par le core pour envoyer des messages sur la channel Facebook
*/
function sendMessages(messages) {
    for(var i=0;i<messages.length;i++) {
        sendMessage(messages[i]);
    }
}

/*
* Fonction qui envoie un message de type text
*/
function sendTextMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                text: message.text
            }
        };
        callSendAPI(messageData);
    }
}

/*
* Fonction qui envoie un message de type quickreply
*/
function sendQuickReplyMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                text: message.text,
                quick_replies: []
            }
        };
        for(var i=0;i<message.choices.length;i++) {
            var quickreply = {
                content_type: "text",
                title: message.choices[i],
                payload: message.choices[i]
            };
            messageData.message.quick_replies.push(quickreply);
        }
        callSendAPI(messageData);
    }
}

/*
* Fonction qui envoie un message de type location
*/
function sendLocationMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                text: message.text,
                quick_replies: [
                    {
                        "content_type":"location",
                    }
                ]
            }
        };
        callSendAPI(messageData);
    }
}

/*
* Fonction qui envoie un message audio/file/image/video
*/
function sendFileMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.text != undefined) {
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                attachment:{
                    type: message.type,
                    payload: {
                        url: message.text
                    }
                }
            }
        };
        callSendAPI(messageData);
    }
}

/*
* Fonction qui envoie un message audio/file/image/video
*/
function sendTemplateMessage(message) {
    console.log("Messages sended : ", JSON.stringify(message));
    if(message.senderID != undefined && message.attachment != undefined) {
        var elements = [
            {
                title: message.attachment[0].name,
                image_url: message.attachment[0].icon,
                subtitle: message.attachment[0].vicinity + " - " + message.attachment[0].rating + "/5",
                default_action: {
                    type: "web_url",
                    url: message.attachment[0].details_url,
                    messenger_extensions: true,
                    webview_height_ratio: "tall"
                },
                buttons: [
                    {
                        title: "Y-Aller",
                        type: "web_url",
                        url: "",
                        messenger_extensions: true,
                        webview_height_ratio: "tall"
                    }
                ]
            },
            {
                title: message.attachment[1].name,
                image_url: message.attachment[1].icon,
                subtitle: message.attachment[1].vicinity + " - " + message.attachment[1].rating + "/5",
                default_action: {
                    type: "web_url",
                    url: message.attachment[1].details_url,
                    messenger_extensions: true,
                    webview_height_ratio: "tall"
                },
                buttons: [
                    {
                        title: "Y-Aller",
                        type: "web_url",
                        url: "",
                        messenger_extensions: true,
                        webview_height_ratio: "tall"
                    }
                ]
            }
        ];
        var messageData = {
            recipient: {
                id: message.senderID
            },
            message: {
                attachment:{
                    type: message.type,
                    payload: {
                        template_type: "list",
                        top_element_style: "compact",
                        elements: elements

                    }
                }
            }
        };
        callSendAPI(messageData);
    }
}

/*
* Fonction qui appel l'API messages de Facebook
*/
function callSendAPI(messageData) {
    console.log("Messages sended via API : ", JSON.stringify(messageData));
    finishWriting(messageData.recipient.id, function() {
            request({
            uri: 'https://graph.facebook.com/v2.6/me/messages',
            qs: { access_token: PAGE_ACCESS_TOKEN },
            method: 'POST',
            json: messageData
        }, function (error, response, body) {
            if (!error && response.statusCode == 200) {
                var recipientId = body.recipient_id;
                var messageId = body.message_id;

                console.log("Successfully sent generic message with id %s to recipient %s",
                    messageId, recipientId);
            } else {
                console.error("Unable to send message.");
                console.error(error);
                console.error(response);
            }
        });
    });
}

function beginWriting(id) {
    request({
        uri: 'https://graph.facebook.com/v2.6/me/messages',
        qs: { access_token: PAGE_ACCESS_TOKEN },
        method: 'POST',
        json: {recipient:{id: id}, sender_action:"typing_on"}
    }, function (error, response, body) {
        if (!error && response.statusCode == 200) {

        } else {
            console.error("Unable to send message.");
            console.error(error);
        }
    });
}

function finishWriting(id, callback) {
    request({
        uri: 'https://graph.facebook.com/v2.6/me/messages',
        qs: { access_token: PAGE_ACCESS_TOKEN },
        method: 'POST',
        json: {recipient:{id: id}, sender_action:"typing_off"}
    }, function (error, response, body) {
        if (!error && response.statusCode == 200) {
            callback();
        } else {
            console.error("Unable to send message.");
            console.error(error);
        }
    });
}

exports.webhook = webhook
exports.receivedMessage = receivedMessage
exports.sendMessage = sendMessage
exports.sendMessages = sendMessages<|endoftext|>


<commit_before>/**
 * Created by tim on 30.10.16.
 */

/**
 * intercept http errors and redirect to login page
 */
loginModule
    .factory('loginErrorInterceptor', ['$q', '$injector', '$rootScope', function ($q, $injector, $rootScope) {
        return {

            /*        'response': function (response) {
             console.log("intercept");
             console.log(response.status);
             return response;
             },*/
            'responseError': function (response) {
                console.log("intercept ERROR");
                //console.log(response);
                if (response.status === 401) {
                    s = $injector.get('$state');
                    if (!s.includes('loginState')) {
                        s.go('loginState');
                    }
                    var deferred = $q.defer();
                    return deferred.promise;
                } else {
                    $rootScope.$broadcast('FlashMessage', {
                        "type": "warning",
                        "text": "http error: " + response.status + " " + response.data
                    });
                }
                return $q.reject(response);
            }

        };
    }]);<commit_msg>don't intercept login errors<commit_after>/**
 * Created by tim on 30.10.16.
 */

/**
 * intercept http errors and redirect to login page
 */
loginModule
    .factory('loginErrorInterceptor', ['$q', '$injector', '$rootScope', function ($q, $injector, $rootScope) {
        return {

            /*        'response': function (response) {
             console.log("intercept");
             console.log(response.status);
             return response;
             },*/
            'responseError': function (response) {
                console.log("intercept ERROR");
                //console.log(response);
                if (response.status === 401) {
                    s = $injector.get('$state');
                    if (!s.includes('loginState')) {
                        s.go('loginState');
                        var deferred = $q.defer();
                        return deferred.promise;
                    }
                } else {
                    $rootScope.$broadcast('FlashMessage', {
                        "type": "warning",
                        "text": "http error: " + response.status + " " + response.data
                    });
                }
                return $q.reject(response);
            }

        };
    }]);<|endoftext|>


<commit_before>(function(){
  var GradRatesChart = D3BarChart.extend();

  GradRatesChart.prototype.get_layers = function(){
    // set up a layer for each series
    var self = this;
    var layers = self.plot.selectAll("g.layer")
      .data(this._data)
      .enter().append("g")
        .attr("class", "layer")
        .style("fill", function(d, i) { return self.options.color(i); });
    // shift grouped bars so they're adjacent to each other
    layers
      .attr("transform", function(d, i) {
        var offset = 20 - 10 * i;
        return "translate(" + offset + ",0)";
      });
    return layers;
  };

  GradRatesChart.prototype.get_bar_width = function(){
    var len_series = this._data.length; // m, i, rows
    var len_x = this._data[0].length;   // n, j, cols
    var bar_width = this.options.plot_box.w / len_x;  // bar_width is an outer width
    bar_width = bar_width - 20 - 10;
    return bar_width;
  };

  // y-axis shows percentage
  GradRatesChart.prototype.get_y_domain = function(){
    return [0, 100];
  };

  // BEGIN
  var $section = $('#gradrates');
  var $source = $section.find('table');
  var data = $source.tabulate().reverse();
  var colors = ['#99c', '#639', '#306'].reverse();

  var chart = new GradRatesChart(
        $('
').appendTo($section)[0],
        data,
        {
          'color': d3.scale.ordinal().range(colors),
          'tooltip': function(){
            var d = this.__data__;
            return d.series + " bachelor's graduation rate
" +
              d3.format(",.2f")(this.__data__.y) + "%";
          }
        });

})();
<commit_msg>Convert data to array before reverse<commit_after>(function(){
  var GradRatesChart = D3BarChart.extend();

  GradRatesChart.prototype.get_layers = function(){
    // set up a layer for each series
    var self = this;
    var layers = self.plot.selectAll("g.layer")
      .data(this._data)
      .enter().append("g")
        .attr("class", "layer")
        .style("fill", function(d, i) { return self.options.color(i); });
    // shift grouped bars so they're adjacent to each other
    layers
      .attr("transform", function(d, i) {
        var offset = 20 - 10 * i;
        return "translate(" + offset + ",0)";
      });
    return layers;
  };

  GradRatesChart.prototype.get_bar_width = function(){
    var len_series = this._data.length; // m, i, rows
    var len_x = this._data[0].length;   // n, j, cols
    var bar_width = this.options.plot_box.w / len_x;  // bar_width is an outer width
    bar_width = bar_width - 20 - 10;
    return bar_width;
  };

  // y-axis shows percentage
  GradRatesChart.prototype.get_y_domain = function(){
    return [0, 100];
  };

  // BEGIN
  var $section = $('#gradrates');
  var $source = $section.find('table');
  var data = $source.tabulate().toArray().reverse();
  var colors = ['#99c', '#639', '#306'].reverse();

  var chart = new GradRatesChart(
        $('
').appendTo($section)[0],
        data,
        {
          'color': d3.scale.ordinal().range(colors),
          'tooltip': function(){
            var d = this.__data__;
            return d.series + " bachelor's graduation rate
" +
              d3.format(",.2f")(this.__data__.y) + "%";
          }
        });

})();
<|endoftext|>


<commit_before>'use strict';

// MODULES //

var resolve = require( 'path' ).resolve;
var exec = require( 'child_process' ).exec;
var tape = require( 'tape' );
var IS_BROWSER = require( '@stdlib/assert/is-browser' );
var IS_WINDOWS = require( '@stdlib/assert/is-windows' );
var readFileSync = require( '@stdlib/fs/read-file' ).sync;

// VARIABLES //

var fpath = resolve( __dirname, '..', 'bin', 'cli' );
var opts = {
	'skip': IS_BROWSER || IS_WINDOWS
};

// FIXTURES //

var PKG_VERSION = require('./../package.json' ).version;

// TESTS //

tape( 'command-line interface', function test( t ) {
	t.ok( true, __filename );
	t.end();
});

tape( 'when invoked with a `--help` flag, the command-line interface prints the help text to `stderr`', opts, function test( t ) {
	var expected;
	var cmd;

	expected = readFileSync( resolve( __dirname, '..', 'bin', 'usage.txt' ), {
		'encoding': 'utf8'
	});
	cmd = [
		process.execPath,
		fpath,
		'--help'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), expected+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `-h` flag, the command-line interface prints the help text to `stderr`', opts, function test( t ) {
	var expected;
	var cmd;

	expected = readFileSync( resolve( __dirname, '..', 'bin', 'usage.txt' ), {
		'encoding': 'utf8'
	});
	cmd = [
		process.execPath,
		fpath,
		'-h'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), expected+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `--version` flag, the command-line interface prints the version to `stderr`', opts, function test( t ) {
	var cmd = [
		process.execPath,
		fpath,
		'--version'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), PKG_VERSION+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `-V` flag, the command-line interface prints the version to `stderr`', opts, function test( t ) {
	var cmd = [
		process.execPath,
		fpath,
		'-V'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), PKG_VERSION+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'the function returns an HTML string for rendering an SVG equation in GitHub Markdown', opts, function test( t ) {
	var expected;
	var cmd;

	cmd = [
		process.execPath,
		fpath,
		'--class \'equation\'',
		'--align \'center\'',
		'--raw \'y = mx + b\'',
		'--label \'eq:line\'',
		'--src \'https://cdn.rawgit.com/math-io/repo/branch/docs/img/eqn.svg\'',
		'--alt \'Equation for a line.\''
	];
	expected = '
\n    \n
\n
\n';

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), expected, 'expected value' );
			t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' );
		}
		t.end();
	}
});
<commit_msg>Fix description<commit_after>'use strict';

// MODULES //

var resolve = require( 'path' ).resolve;
var exec = require( 'child_process' ).exec;
var tape = require( 'tape' );
var IS_BROWSER = require( '@stdlib/assert/is-browser' );
var IS_WINDOWS = require( '@stdlib/assert/is-windows' );
var readFileSync = require( '@stdlib/fs/read-file' ).sync;

// VARIABLES //

var fpath = resolve( __dirname, '..', 'bin', 'cli' );
var opts = {
	'skip': IS_BROWSER || IS_WINDOWS
};

// FIXTURES //

var PKG_VERSION = require('./../package.json' ).version;

// TESTS //

tape( 'command-line interface', function test( t ) {
	t.ok( true, __filename );
	t.end();
});

tape( 'when invoked with a `--help` flag, the command-line interface prints the help text to `stderr`', opts, function test( t ) {
	var expected;
	var cmd;

	expected = readFileSync( resolve( __dirname, '..', 'bin', 'usage.txt' ), {
		'encoding': 'utf8'
	});
	cmd = [
		process.execPath,
		fpath,
		'--help'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), expected+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `-h` flag, the command-line interface prints the help text to `stderr`', opts, function test( t ) {
	var expected;
	var cmd;

	expected = readFileSync( resolve( __dirname, '..', 'bin', 'usage.txt' ), {
		'encoding': 'utf8'
	});
	cmd = [
		process.execPath,
		fpath,
		'-h'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), expected+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `--version` flag, the command-line interface prints the version to `stderr`', opts, function test( t ) {
	var cmd = [
		process.execPath,
		fpath,
		'--version'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), PKG_VERSION+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'when invoked with a `-V` flag, the command-line interface prints the version to `stderr`', opts, function test( t ) {
	var cmd = [
		process.execPath,
		fpath,
		'-V'
	];

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), '', 'does not print to `stdout`' );
			t.strictEqual( stderr.toString(), PKG_VERSION+'\n', 'expected value' );
		}
		t.end();
	}
});

tape( 'the command-line interface generates an HTML string for rendering an SVG equation in GitHub Markdown', opts, function test( t ) {
	var expected;
	var cmd;

	cmd = [
		process.execPath,
		fpath,
		'--class \'equation\'',
		'--align \'center\'',
		'--raw \'y = mx + b\'',
		'--label \'eq:line\'',
		'--src \'https://cdn.rawgit.com/math-io/repo/branch/docs/img/eqn.svg\'',
		'--alt \'Equation for a line.\''
	];
	expected = '
\n    \n
\n
\n';

	exec( cmd.join( ' ' ), done );

	function done( error, stdout, stderr ) {
		if ( error ) {
			t.fail( error.message );
		} else {
			t.strictEqual( stdout.toString(), expected, 'expected value' );
			t.strictEqual( stderr.toString(), '', 'does not print to `stderr`' );
		}
		t.end();
	}
});
<|endoftext|>


<commit_before>/*
 * Stately.js: A JavaScript based finite-state machine (FSM) engine.
 *
 * Copyright (c) 2012 Florian Schäfer (florian.schaefer@gmail.com)
 * Released under MIT license.
 *
 * Version: 0.9.8
 *
 */
(function (root, factory) {
    if (typeof exports === 'object') {
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {
        define(factory);
    } else {
        root.Stately = factory();
    }
})(this, function () {

    var
        //helper to identify options type
        toString = Object.prototype.toString,

        //custom exception for invalid states
        InvalidStateError = (function () {

            //custom event constructor
            function InvalidStateError(message) {

                //set error name
                this.name = 'InvalidStateError';

                //the error message
                this.message = message;
            }

            //inherit from error object
            InvalidStateError.prototype = new Error();

            //set custom error constructor
            InvalidStateError.prototype.constructor = InvalidStateError;

            //return custom event
            return InvalidStateError;
        })();

    //constructor
    function Stately(statesObject) {

        //if statesObject is a function
        if (typeof statesObject === 'function') {

            //avaluate it
            statesObject = statesObject();
        }

        //if no valid statesObject provided
        if (toString.call(statesObject) !== '[object Object]') {

            //bail out
            throw new InvalidStateError('Stately.js: Invalid states object: `' + statesObject + '`.');
        }

        var
            //current state of the machine
            currentState,

            //storage for notification callbacks
            notificationStore = [],

            //notify callbacks about a transition
            notify = function () {

                //make copy of notification storage
                var notifications = notificationStore.slice();

                //walk over stored callbacks
                for (var i = 0, l = notifications.length; i < l; i++) {

                    //and notify them
                    notifications[i].apply(this, arguments);
                }
            },

            //storage for machine states
            stateStore = {

                //evaluates the current state
                getMachineState: function getMachineState() {

                    //return current state as string
                    return currentState.name;
                },

                //function to transition into another state
                setMachineState: function setMachineState(nextState /*, eventName */) {

                    var
                        //event that triggered the transition
                        eventName = arguments[1],

                        //before state hook
                        onBeforeState,

                        //enter state hook
                        onEnterState,

                        //leave state hook
                        onLeaveState,

                        //store last machine state
                        lastState = currentState;

                    //if state machine cannot handle returned state
                    if (!nextState || !nextState.name || !stateStore[nextState.name]) {

                        //throw invalid state exception
                        throw new InvalidStateError('Stately.js: Transitioned into invalid state: `' + setMachineState.caller + '`.');
                    }

                    //transition into next state
                    currentState = nextState;

                    //retrieve enter state hook
                    onBeforeState = stateMachine['onbefore' + currentState.name];

                    //if a hook is attached
                    if (onBeforeState && typeof onBeforeState === 'function') {

                        //apply it
                        onBeforeState.call(stateStore, eventName, lastState.name, nextState.name);
                    }

                    //retrieve enter state hook
                    onEnterState = stateMachine['onenter' + currentState.name] || stateMachine['on' + currentState.name];

                    //if a hook is attached
                    if (onEnterState && typeof onEnterState === 'function') {

                        //apply it
                        onEnterState.call(stateStore, eventName, lastState.name, nextState.name);
                    }

                    //retrieve leave state hook
                    onLeaveState = stateMachine['onleave' + currentState.name];

                    //if a hook is attached
                    if (onLeaveState && typeof onLeaveState === 'function') {

                        //apply it
                        onLeaveState.call(stateStore, eventName, lastState.name, nextState.name);
                    }

                    //notify notification callbacks about transition
                    notify.call(stateStore, eventName, lastState.name, nextState.name);

                    //return the state store
                    return this;
                },

                //function returns the possible events in current state
                getMachineEvents: function getMachineEvents() {

                    //storage for the events in current state
                    var events = [];

                    //walk over the events of the current state
                    for (property in currentState) {

                        //ensure to only walk over own properties
                        if (currentState.hasOwnProperty(property)) {

                            //if it is an event function
                            if (typeof currentState[property] === 'function') {

                                //store it in events storage
                                events.push(property);
                            }
                        }
                    }

                    //return the possible events
                    return events;
                }

            },

            //the state machine
            stateMachine = {

                //copy function to public state machine object
                getMachineState: stateStore.getMachineState,

                //copy function to public state machine object
                getMachineEvents: stateStore.getMachineEvents,

                //store a new notification callback
                bind: function bind(callback) {

                    //if we have a new notification callback
                    if (callback) {

                        //store it in notification storage
                        notificationStore.push(callback);
                    }

                    //return the state machine
                    return this;
                },

                //remove a notification callback from storage
                unbind: function unbind(callback) {

                    //if no callback is given
                    if (!callback) {

                        //reset notification storage
                        notificationStore = [];

                    } else {

                        //walk over stored callbacks
                        for (var i = 0, l = notificationStore.length; i < l; i++) {

                            //if callback is found in notification storage
                            if (notificationStore[i] === callback) {

                                //remove it
                                notificationStore.splice(i, 1);
                            }
                        }
                    }

                    //return the state machine
                    return this;
                }
            },

            //event decorator factory function
            transition = function transition(stateName, eventName, nextEvent) {

                //the decorator
                return function event() {

                    var
                        //before event hook
                        onBeforeEvent,

                        //after event hook
                        onAfterEvent,

                        //new state machine changed into
                        nextState,

                        //return the state machine if no event returns something
                        eventValue = stateMachine;

                    //if attached event handler doesn't handle this event
                    if (stateStore[stateName] !== currentState) {

                        //try other events in chain
                        if (nextEvent) {

                            //let next event function handle this event
                            eventValue = nextEvent.apply(stateStore, arguments);
                        }

                        //or return value of action
                        return eventValue;
                    }

                    //retrieve before event hook
                    onBeforeEvent = stateMachine['onbefore' + eventName];

                    //if a hook is attached
                    if (onBeforeEvent && typeof onBeforeEvent === 'function') {

                        //apply it
                        onBeforeEvent.call(stateStore, eventName, currentState.name, currentState.name);
                    }

                    //run action
                    eventValue = stateStore[stateName][eventName].apply(stateStore, arguments);

                    //check return value of action
                    if (typeof eventValue === 'undefined') {

                        //nothing returned, stay in current state
                        nextState = currentState;

                        //return state machine
                        eventValue = stateMachine;

                    } else if (toString.call(eventValue) === '[object Object]') {

                        //if state store object is returned ('this' in action function) stay in current state
                        nextState = (eventValue === stateStore ? currentState : eventValue);

                        //return state machine
                        eventValue = stateMachine;

                    } else if (toString.call(eventValue) === '[object Array]' && eventValue.length >= 1) {

                        //else first element is next state
                        nextState = eventValue[0];

                        //second element is return value
                        eventValue = eventValue[1];
                    }

                    //retrieve after event hook
                    onAfterEvent = stateMachine['onafter' + eventName] || stateMachine['on' + eventName];

                    //if a hook is attached
                    if (onAfterEvent && typeof onAfterEvent === 'function') {

                        //apply it
                        onAfterEvent.call(stateStore, eventName, currentState.name, nextState.name);
                    }

                    //transition into next state
                    stateStore.setMachineState(nextState, eventName);

                    //return desired value
                    return eventValue;
                };
            };

        //walk over states object
        for (var stateName in statesObject) {

            //check own properties
            if (statesObject.hasOwnProperty(stateName)) {

                //store states in storage
                stateStore[stateName] = statesObject[stateName];

                //walk over events
                for (var eventName in stateStore[stateName]) {

                    //check for own property
                    if (stateStore[stateName].hasOwnProperty(eventName)) {

                        //if type is a string, assume it is a state
                        if (typeof stateStore[stateName][eventName] === 'string') {

                            //decorate it
                            stateStore[stateName][eventName] = (function (stateName) {

                                //with a function
                                return function event() {

                                    //returning the given state
                                    return this[stateName];
                                };

                            })(stateStore[stateName][eventName]);
                        }

                        //if type function
                        if (typeof stateStore[stateName][eventName] === 'function') {

                            //assign decorated events to state machine
                            stateMachine[eventName] = transition(stateName, eventName, stateMachine[eventName]);
                        }
                    }
                }

                //attach states name to object in storage
                stateStore[stateName].name = stateName;

                //initial state is the first passed in state
                if (!currentState) {

                    //make initial state the current state
                    currentState = stateStore[stateName];
                }
            }
        }

        //if there is no initial state
        if (!currentState) {

            //throw invalid state exception
            throw new InvalidStateError('Stately.js: Invalid initial state.');
        }

        //return the new state machine
        return stateMachine;
    }

    //a factory for new machines
    Stately.machine = function machine(statesObject) {
        return new Stately(statesObject);
    };

    //InvalidStateError exception
    Stately.InvalidStateError = InvalidStateError;

    //export Stately object
    return Stately;

});
<commit_msg>Update Stately.js<commit_after>/*
 * Stately.js: A JavaScript based finite-state machine (FSM) engine.
 *
 * Copyright (c) 2012 Florian Schäfer (florian.schaefer@gmail.com)
 * Released under MIT license.
 *
 * Version: 0.9.8
 *
 */
(function (root, factory) {
    if (typeof exports === 'object') {
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {
        define(factory);
    } else {
        root.Stately = factory();
    }
})(this, function () {

    var
        //helper to identify options type
        toString = Object.prototype.toString,

        //custom exception for invalid states
        InvalidStateError = (function () {

            //custom event constructor
            function InvalidStateError(message) {

                //set error name
                this.name = 'InvalidStateError';

                //the error message
                this.message = message;
            }

            //inherit from error object
            InvalidStateError.prototype = new Error();

            //set custom error constructor
            InvalidStateError.prototype.constructor = InvalidStateError;

            //return custom event
            return InvalidStateError;
        })();

    //constructor
    function Stately(statesObject) {

        //if statesObject is a function
        if (typeof statesObject === 'function') {

            //avaluate it
            statesObject = statesObject();
        }

        //if no valid statesObject provided
        if (toString.call(statesObject) !== '[object Object]') {

            //bail out
            throw new InvalidStateError('Stately.js: Invalid states object: `' + statesObject + '`.');
        }

        var
            //current state of the machine
            currentState,

            //storage for notification callbacks
            notificationStore = [],

            //notify callbacks about a transition
            notify = function () {

                //make copy of notification storage
                var notifications = notificationStore.slice();

                //walk over stored callbacks
                for (var i = 0, l = notifications.length; i < l; i++) {

                    //and notify them
                    notifications[i].apply(this, arguments);
                }
            },

            //storage for machine states
            stateStore = {

                //evaluates the current state
                getMachineState: function getMachineState() {

                    //return current state as string
                    return currentState.name;
                },

                //function to transition into another state
                setMachineState: function setMachineState(nextState /*, eventName */) {

                    var
                        //event that triggered the transition
                        eventName = arguments[1],

                        //before state hook
                        onBeforeState,

                        //enter state hook
                        onEnterState,

                        //leave state hook
                        onLeaveState,

                        //store last machine state
                        lastState = currentState;

                    //if state machine cannot handle returned state
                    if (!nextState || !nextState.name || !stateStore[nextState.name]) {

                        //throw invalid state exception
                        throw new InvalidStateError('Stately.js: Transitioned into invalid state: `' + setMachineState.caller + '`.');
                    }

                    //transition into next state
                    currentState = nextState;

                    //retrieve enter state hook
                    onBeforeState = stateMachine['onbefore' + currentState.name];

                    //if a hook is attached
                    if (onBeforeState && typeof onBeforeState === 'function') {

                        //apply it
                        onBeforeState.call(stateStore, eventName, lastState.name, nextState.name);
                    }

                    //retrieve enter state hook
                    onEnterState = stateMachine['onenter' + currentState.name] || stateMachine['on' + currentState.name];

                    //if a hook is attached
                    if (onEnterState && typeof onEnterState === 'function') {

                        //apply it
                        onEnterState.call(stateStore, eventName, lastState.name, nextState.name);
                    }

                    //retrieve leave state hook
                    onLeaveState = stateMachine['onleave' + currentState.name];

                    //if a hook is attached
                    if (onLeaveState && typeof onLeaveState === 'function') {

                        //apply it
                        onLeaveState.call(stateStore, eventName, lastState.name, nextState.name);
                    }

                    //notify notification callbacks about transition
                    notify.call(stateStore, eventName, lastState.name, nextState.name);

                    //return the state store
                    return this;
                },

                //function returns the possible events in current state
                getMachineEvents: function getMachineEvents() {

                    //storage for the events in current state
                    var events = [];

                    //walk over the events of the current state
                    for (var property in currentState) {

                        //ensure to only walk over own properties
                        if (currentState.hasOwnProperty(property)) {

                            //if it is an event function
                            if (typeof currentState[property] === 'function') {

                                //store it in events storage
                                events.push(property);
                            }
                        }
                    }

                    //return the possible events
                    return events;
                }

            },

            //the state machine
            stateMachine = {

                //copy function to public state machine object
                getMachineState: stateStore.getMachineState,

                //copy function to public state machine object
                getMachineEvents: stateStore.getMachineEvents,

                //store a new notification callback
                bind: function bind(callback) {

                    //if we have a new notification callback
                    if (callback) {

                        //store it in notification storage
                        notificationStore.push(callback);
                    }

                    //return the state machine
                    return this;
                },

                //remove a notification callback from storage
                unbind: function unbind(callback) {

                    //if no callback is given
                    if (!callback) {

                        //reset notification storage
                        notificationStore = [];

                    } else {

                        //walk over stored callbacks
                        for (var i = 0, l = notificationStore.length; i < l; i++) {

                            //if callback is found in notification storage
                            if (notificationStore[i] === callback) {

                                //remove it
                                notificationStore.splice(i, 1);
                            }
                        }
                    }

                    //return the state machine
                    return this;
                }
            },

            //event decorator factory function
            transition = function transition(stateName, eventName, nextEvent) {

                //the decorator
                return function event() {

                    var
                        //before event hook
                        onBeforeEvent,

                        //after event hook
                        onAfterEvent,

                        //new state machine changed into
                        nextState,

                        //return the state machine if no event returns something
                        eventValue = stateMachine;

                    //if attached event handler doesn't handle this event
                    if (stateStore[stateName] !== currentState) {

                        //try other events in chain
                        if (nextEvent) {

                            //let next event function handle this event
                            eventValue = nextEvent.apply(stateStore, arguments);
                        }

                        //or return value of action
                        return eventValue;
                    }

                    //retrieve before event hook
                    onBeforeEvent = stateMachine['onbefore' + eventName];

                    //if a hook is attached
                    if (onBeforeEvent && typeof onBeforeEvent === 'function') {

                        //apply it
                        onBeforeEvent.call(stateStore, eventName, currentState.name, currentState.name);
                    }

                    //run action
                    eventValue = stateStore[stateName][eventName].apply(stateStore, arguments);

                    //check return value of action
                    if (typeof eventValue === 'undefined') {

                        //nothing returned, stay in current state
                        nextState = currentState;

                        //return state machine
                        eventValue = stateMachine;

                    } else if (toString.call(eventValue) === '[object Object]') {

                        //if state store object is returned ('this' in action function) stay in current state
                        nextState = (eventValue === stateStore ? currentState : eventValue);

                        //return state machine
                        eventValue = stateMachine;

                    } else if (toString.call(eventValue) === '[object Array]' && eventValue.length >= 1) {

                        //else first element is next state
                        nextState = eventValue[0];

                        //second element is return value
                        eventValue = eventValue[1];
                    }

                    //retrieve after event hook
                    onAfterEvent = stateMachine['onafter' + eventName] || stateMachine['on' + eventName];

                    //if a hook is attached
                    if (onAfterEvent && typeof onAfterEvent === 'function') {

                        //apply it
                        onAfterEvent.call(stateStore, eventName, currentState.name, nextState.name);
                    }

                    //transition into next state
                    stateStore.setMachineState(nextState, eventName);

                    //return desired value
                    return eventValue;
                };
            };

        //walk over states object
        for (var stateName in statesObject) {

            //check own properties
            if (statesObject.hasOwnProperty(stateName)) {

                //store states in storage
                stateStore[stateName] = statesObject[stateName];

                //walk over events
                for (var eventName in stateStore[stateName]) {

                    //check for own property
                    if (stateStore[stateName].hasOwnProperty(eventName)) {

                        //if type is a string, assume it is a state
                        if (typeof stateStore[stateName][eventName] === 'string') {

                            //decorate it
                            stateStore[stateName][eventName] = (function (stateName) {

                                //with a function
                                return function event() {

                                    //returning the given state
                                    return this[stateName];
                                };

                            })(stateStore[stateName][eventName]);
                        }

                        //if type function
                        if (typeof stateStore[stateName][eventName] === 'function') {

                            //assign decorated events to state machine
                            stateMachine[eventName] = transition(stateName, eventName, stateMachine[eventName]);
                        }
                    }
                }

                //attach states name to object in storage
                stateStore[stateName].name = stateName;

                //initial state is the first passed in state
                if (!currentState) {

                    //make initial state the current state
                    currentState = stateStore[stateName];
                }
            }
        }

        //if there is no initial state
        if (!currentState) {

            //throw invalid state exception
            throw new InvalidStateError('Stately.js: Invalid initial state.');
        }

        //return the new state machine
        return stateMachine;
    }

    //a factory for new machines
    Stately.machine = function machine(statesObject) {
        return new Stately(statesObject);
    };

    //InvalidStateError exception
    Stately.InvalidStateError = InvalidStateError;

    //export Stately object
    return Stately;

});
<|endoftext|>