<commit_before>// 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.

couchTests.reduce = function(debug) {
  var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
  db.deleteDb();
  db.createDb();
  if (debug) debugger;
  var numDocs = 500;
  var docs = makeDocs(1,numDocs + 1);
  db.bulkSave(docs);
  var summate = function(N) {return (N+1)*N/2;};

  var map = function (doc) {
      emit(doc.integer, doc.integer);
      emit(doc.integer, doc.integer);
  };
  var reduce = function (keys, values) { return sum(values); };
  var result = db.query(map, reduce);
  T(result.rows[0].value == 2*summate(numDocs));

  result = db.query(map, reduce, {startkey: 4, endkey: 4});
  T(result.rows[0].value == 8);

  result = db.query(map, reduce, {startkey: 4, endkey: 5});
  T(result.rows[0].value == 18);

  result = db.query(map, reduce, {startkey: 4, endkey: 6});
  T(result.rows[0].value == 30);

  result = db.query(map, reduce, {group:true, limit:3});
  T(result.rows[0].value == 2);
  T(result.rows[1].value == 4);
  T(result.rows[2].value == 6);

  for(var i=1; i<numDocs/2; i+=30) {
    result = db.query(map, reduce, {startkey: i, endkey: numDocs - i});
    T(result.rows[0].value == 2*(summate(numDocs-i) - summate(i-1)));
  }

  db.deleteDb();
  db.createDb();

  for(var i=1; i <= 5; i++) {

    for(var j=0; j < 10; j++) {
      // these docs are in the order of the keys collation, for clarity
      var docs = [];
      docs.push({keys:["a"]});
      docs.push({keys:["a"]});
      docs.push({keys:["a", "b"]});
      docs.push({keys:["a", "b"]});
      docs.push({keys:["a", "b", "c"]});
      docs.push({keys:["a", "b", "d"]});
      docs.push({keys:["a", "c", "d"]});
      docs.push({keys:["d"]});
      docs.push({keys:["d", "a"]});
      docs.push({keys:["d", "b"]});
      docs.push({keys:["d", "c"]});
      db.bulkSave(docs);
      T(db.info().doc_count == ((i - 1) * 10 * 11) + ((j + 1) * 11));
    }

    map = function (doc) { emit(doc.keys, 1); };
    reduce = function (keys, values) { return sum(values); };

    var results = db.query(map, reduce, {group:true});

    //group by exact key match
    T(equals(results.rows[0], {key:["a"],value:20*i}));
    T(equals(results.rows[1], {key:["a","b"],value:20*i}));
    T(equals(results.rows[2], {key:["a", "b", "c"],value:10*i}));
    T(equals(results.rows[3], {key:["a", "b", "d"],value:10*i}));

    // test to make sure group reduce and limit params provide valid json
    var results = db.query(map, reduce, {group: true, limit: 2});
    T(equals(results.rows[0], {key: ["a"], value: 20*i}));
    T(equals(results.rows.length, 2));

    //group by the first element in the key array
    var results = db.query(map, reduce, {group_level:1});
    T(equals(results.rows[0], {key:["a"],value:70*i}));
    T(equals(results.rows[1], {key:["d"],value:40*i}));

    //group by the first 2 elements in the key array
    var results = db.query(map, reduce, {group_level:2});
    T(equals(results.rows[0], {key:["a"],value:20*i}));
    T(equals(results.rows[1], {key:["a","b"],value:40*i}));
    T(equals(results.rows[2], {key:["a","c"],value:10*i}));
    T(equals(results.rows[3], {key:["d"],value:10*i}));
    T(equals(results.rows[4], {key:["d","a"],value:10*i}));
    T(equals(results.rows[5], {key:["d","b"],value:10*i}));
    T(equals(results.rows[6], {key:["d","c"],value:10*i}));

    // endkey test with inclusive_end=true
    var results = db.query(map, reduce, {group_level:2,endkey:["d"],inclusive_end:true});
    T(equals(results.rows[0], {key:["a"],value:20*i}));
    T(equals(results.rows[1], {key:["a","b"],value:40*i}));
    T(equals(results.rows[2], {key:["a","c"],value:10*i}));
    T(equals(results.rows[3], {key:["d"],value:10*i}));
    TEquals(4, results.rows.length);

    // endkey test with inclusive_end=false
    var results = db.query(map, reduce, {group_level:2,endkey:["d"],inclusive_end:false});
    T(equals(results.rows[0], {key:["a"],value:20*i}));
    T(equals(results.rows[1], {key:["a","b"],value:40*i}));
    T(equals(results.rows[2], {key:["a","c"],value:10*i}));
    TEquals(3, results.rows.length);
  }

  // now test out more complex reductions that need to use the combine option.

  db.deleteDb();
  db.createDb();

  var map = function (doc) { emit(doc.val, doc.val); };
  var reduceCombine = function (keys, values, rereduce) {
      // This computes the standard deviation of the mapped results
      var stdDeviation=0.0;
      var count=0;
      var total=0.0;
      var sqrTotal=0.0;

      if (!rereduce) {
        // This is the reduce phase, we are reducing over emitted values from
        // the map functions.
        for(var i in values) {
          total = total + values[i];
          sqrTotal = sqrTotal + (values[i] * values[i]);
        }
        count = values.length;
      }
      else {
        // This is the rereduce phase, we are re-reducing previosuly
        // reduced values.
        for(var i in values) {
          count = count + values[i].count;
          total = total + values[i].total;
          sqrTotal = sqrTotal + values[i].sqrTotal;
        }
      }

      var variance =  (sqrTotal - ((total * total)/count)) / count;
      stdDeviation = Math.sqrt(variance);

      // the reduce result. It contains enough information to be rereduced
      // with other reduce results.
      return {"stdDeviation":stdDeviation,"count":count,
          "total":total,"sqrTotal":sqrTotal};
    };

    // Save a bunch a docs.

  for(var i=0; i < 10; i++) {
    var docs = [];
    docs.push({val:10});
    docs.push({val:20});
    docs.push({val:30});
    docs.push({val:40});
    docs.push({val:50});
    docs.push({val:60});
    docs.push({val:70});
    docs.push({val:80});
    docs.push({val:90});
    docs.push({val:100});
    db.bulkSave(docs);
  }

  var results = db.query(map, reduceCombine);

  var difference = results.rows[0].value.stdDeviation - 28.722813232690143;
  // account for floating point rounding error
  T(Math.abs(difference) < 0.0000000001);

};
<commit_msg>Fix fold reduce with non-inclusive end key<commit_after>// 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.

couchTests.reduce = function(debug) {
  var db = new CouchDB("test_suite_db", {"X-Couch-Full-Commit":"false"});
  db.deleteDb();
  db.createDb();
  if (debug) debugger;
  var numDocs = 500;
  var docs = makeDocs(1,numDocs + 1);
  db.bulkSave(docs);
  var summate = function(N) {return (N+1)*N/2;};

  var map = function (doc) {
      emit(doc.integer, doc.integer);
      emit(doc.integer, doc.integer);
  };
  var reduce = function (keys, values) { return sum(values); };
  var result = db.query(map, reduce);
  T(result.rows[0].value == 2*summate(numDocs));

  result = db.query(map, reduce, {startkey: 4, endkey: 4});
  T(result.rows[0].value == 8);

  result = db.query(map, reduce, {startkey: 4, endkey: 5});
  T(result.rows[0].value == 18);

  result = db.query(map, reduce, {startkey: 4, endkey: 6});
  T(result.rows[0].value == 30);

  result = db.query(map, reduce, {group:true, limit:3});
  T(result.rows[0].value == 2);
  T(result.rows[1].value == 4);
  T(result.rows[2].value == 6);

  for(var i=1; i<numDocs/2; i+=30) {
    result = db.query(map, reduce, {startkey: i, endkey: numDocs - i});
    T(result.rows[0].value == 2*(summate(numDocs-i) - summate(i-1)));
  }

  db.deleteDb();
  db.createDb();

  for(var i=1; i <= 5; i++) {

    for(var j=0; j < 10; j++) {
      // these docs are in the order of the keys collation, for clarity
      var docs = [];
      docs.push({keys:["a"]});
      docs.push({keys:["a"]});
      docs.push({keys:["a", "b"]});
      docs.push({keys:["a", "b"]});
      docs.push({keys:["a", "b", "c"]});
      docs.push({keys:["a", "b", "d"]});
      docs.push({keys:["a", "c", "d"]});
      docs.push({keys:["d"]});
      docs.push({keys:["d", "a"]});
      docs.push({keys:["d", "b"]});
      docs.push({keys:["d", "c"]});
      db.bulkSave(docs);
      T(db.info().doc_count == ((i - 1) * 10 * 11) + ((j + 1) * 11));
    }

    map = function (doc) { emit(doc.keys, 1); };
    reduce = function (keys, values) { return sum(values); };

    var results = db.query(map, reduce, {group:true});

    //group by exact key match
    T(equals(results.rows[0], {key:["a"],value:20*i}));
    T(equals(results.rows[1], {key:["a","b"],value:20*i}));
    T(equals(results.rows[2], {key:["a", "b", "c"],value:10*i}));
    T(equals(results.rows[3], {key:["a", "b", "d"],value:10*i}));

    // test to make sure group reduce and limit params provide valid json
    var results = db.query(map, reduce, {group: true, limit: 2});
    T(equals(results.rows[0], {key: ["a"], value: 20*i}));
    T(equals(results.rows.length, 2));

    //group by the first element in the key array
    var results = db.query(map, reduce, {group_level:1});
    T(equals(results.rows[0], {key:["a"],value:70*i}));
    T(equals(results.rows[1], {key:["d"],value:40*i}));

    //group by the first 2 elements in the key array
    var results = db.query(map, reduce, {group_level:2});
    T(equals(results.rows[0], {key:["a"],value:20*i}));
    T(equals(results.rows[1], {key:["a","b"],value:40*i}));
    T(equals(results.rows[2], {key:["a","c"],value:10*i}));
    T(equals(results.rows[3], {key:["d"],value:10*i}));
    T(equals(results.rows[4], {key:["d","a"],value:10*i}));
    T(equals(results.rows[5], {key:["d","b"],value:10*i}));
    T(equals(results.rows[6], {key:["d","c"],value:10*i}));

    // endkey test with inclusive_end=true
    var results = db.query(map, reduce, {group_level:2,endkey:["d"],inclusive_end:true});
    T(equals(results.rows[0], {key:["a"],value:20*i}));
    T(equals(results.rows[1], {key:["a","b"],value:40*i}));
    T(equals(results.rows[2], {key:["a","c"],value:10*i}));
    T(equals(results.rows[3], {key:["d"],value:10*i}));
    TEquals(4, results.rows.length);

    // endkey test with inclusive_end=false
    var results = db.query(map, reduce, {group_level:2,endkey:["d"],inclusive_end:false});
    T(equals(results.rows[0], {key:["a"],value:20*i}));
    T(equals(results.rows[1], {key:["a","b"],value:40*i}));
    T(equals(results.rows[2], {key:["a","c"],value:10*i}));
    TEquals(3, results.rows.length);
  }

  // now test out more complex reductions that need to use the combine option.

  db.deleteDb();
  db.createDb();

  var map = function (doc) { emit(doc.val, doc.val); };
  var reduceCombine = function (keys, values, rereduce) {
      // This computes the standard deviation of the mapped results
      var stdDeviation=0.0;
      var count=0;
      var total=0.0;
      var sqrTotal=0.0;

      if (!rereduce) {
        // This is the reduce phase, we are reducing over emitted values from
        // the map functions.
        for(var i in values) {
          total = total + values[i];
          sqrTotal = sqrTotal + (values[i] * values[i]);
        }
        count = values.length;
      }
      else {
        // This is the rereduce phase, we are re-reducing previosuly
        // reduced values.
        for(var i in values) {
          count = count + values[i].count;
          total = total + values[i].total;
          sqrTotal = sqrTotal + values[i].sqrTotal;
        }
      }

      var variance =  (sqrTotal - ((total * total)/count)) / count;
      stdDeviation = Math.sqrt(variance);

      // the reduce result. It contains enough information to be rereduced
      // with other reduce results.
      return {"stdDeviation":stdDeviation,"count":count,
          "total":total,"sqrTotal":sqrTotal};
    };

    // Save a bunch a docs.

  for(var i=0; i < 10; i++) {
    var docs = [];
    docs.push({val:10});
    docs.push({val:20});
    docs.push({val:30});
    docs.push({val:40});
    docs.push({val:50});
    docs.push({val:60});
    docs.push({val:70});
    docs.push({val:80});
    docs.push({val:90});
    docs.push({val:100});
    db.bulkSave(docs);
  }

  var results = db.query(map, reduceCombine);

  var difference = results.rows[0].value.stdDeviation - 28.722813232690143;
  // account for floating point rounding error
  T(Math.abs(difference) < 0.0000000001);

  function testReducePagination() {
    var ddoc = {
      "_id": "_design/test",
      "language": "javascript",
      "views": {
        "view1": {
          "map": "function(doc) {" +
             "emit(doc.int, doc._id);" +
             "emit(doc.int + 1, doc._id);" +
             "emit(doc.int + 2, doc._id);" +
          "}",
          "reduce": "_count"
        }
      }
    };
    var result, docs = [];

    function randVal() {
        return Math.random() * 100000000;
    }

    db.deleteDb();
    db.createDb();

    for (var i = 0; i < 1123; i++) {
      docs.push({"_id": String(i), "int": i});
    }
    db.bulkSave(docs.concat([ddoc]));

    // ?group=false tests
    result = db.view('test/view1', {startkey: 400, endkey: 402, foobar: randVal()});
    TEquals(9, result.rows[0].value);
    result = db.view('test/view1', {startkey: 402, endkey: 400, descending: true,
      foobar: randVal()});
    TEquals(9, result.rows[0].value);

    result = db.view('test/view1', {startkey: 400, endkey: 402, inclusive_end: false,
      foobar: randVal()});
    TEquals(6, result.rows[0].value);
    result = db.view('test/view1', {startkey: 402, endkey: 400, inclusive_end: false,
      descending: true, foobar: randVal()});
    TEquals(6, result.rows[0].value);

    result = db.view('test/view1', {startkey: 400, endkey: 402, endkey_docid: "400",
      foobar: randVal()});
    TEquals(7, result.rows[0].value);
    result = db.view('test/view1', {startkey: 400, endkey: 402, endkey_docid: "400",
      inclusive_end: false, foobar: randVal()});
    TEquals(6, result.rows[0].value);

    result = db.view('test/view1', {startkey: 400, endkey: 402, endkey_docid: "401",
      foobar: randVal()});
    TEquals(8, result.rows[0].value);
    result = db.view('test/view1', {startkey: 400, endkey: 402, endkey_docid: "401",
      inclusive_end: false, foobar: randVal()});
    TEquals(7, result.rows[0].value);

    result = db.view('test/view1', {startkey: 400, endkey: 402, endkey_docid: "402",
      foobar: randVal()});
    TEquals(9, result.rows[0].value);
    result = db.view('test/view1', {startkey: 400, endkey: 402, endkey_docid: "402",
      inclusive_end: false, foobar: randVal()});
    TEquals(8, result.rows[0].value);

    result = db.view('test/view1', {startkey: 402, endkey: 400, endkey_docid: "398",
      descending: true, foobar: randVal()});
    TEquals(9, result.rows[0].value);
    result = db.view('test/view1', {startkey: 402, endkey: 400, endkey_docid: "398",
      descending: true, inclusive_end: false, foobar: randVal()}),
    TEquals(8, result.rows[0].value);

    result = db.view('test/view1', {startkey: 402, endkey: 400, endkey_docid: "399",
      descending: true, foobar: randVal()});
    TEquals(8, result.rows[0].value);
    result = db.view('test/view1', {startkey: 402, endkey: 400, endkey_docid: "399",
      descending: true, inclusive_end: false, foobar: randVal()}),
    TEquals(7, result.rows[0].value);

    result = db.view('test/view1', {startkey: 402, endkey: 400, endkey_docid: "400",
      descending: true, foobar: randVal()}),
    TEquals(7, result.rows[0].value);
    result = db.view('test/view1', {startkey: 402, endkey: 400, endkey_docid: "400",
      descending: true, inclusive_end: false, foobar: randVal()}),
    TEquals(6, result.rows[0].value);

    result = db.view('test/view1', {startkey: 402, startkey_docid: "400", endkey: 400,
      descending: true, foobar: randVal()});
    TEquals(7, result.rows[0].value);

    result = db.view('test/view1', {startkey: 402, startkey_docid: "401", endkey: 400,
      descending: true, inclusive_end: false, foobar: randVal()});
    TEquals(5, result.rows[0].value);

    // ?group=true tests
    result = db.view('test/view1', {group: true, startkey: 400, endkey: 402,
      foobar: randVal()});
    TEquals(3, result.rows.length);
    TEquals(400, result.rows[0].key);
    TEquals(3, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);
    TEquals(402, result.rows[2].key);
    TEquals(3, result.rows[2].value);

    result = db.view('test/view1', {group: true, startkey: 402, endkey: 400,
      descending: true, foobar: randVal()});
    TEquals(3, result.rows.length);
    TEquals(402, result.rows[0].key);
    TEquals(3, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);
    TEquals(400, result.rows[2].key);
    TEquals(3, result.rows[2].value);

    result = db.view('test/view1', {group: true, startkey: 400, endkey: 402,
      inclusive_end: false, foobar: randVal()});
    TEquals(2, result.rows.length);
    TEquals(400, result.rows[0].key);
    TEquals(3, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);

    result = db.view('test/view1', {group: true, startkey: 402, endkey: 400,
      descending: true, inclusive_end: false, foobar: randVal()});
    TEquals(2, result.rows.length);
    TEquals(402, result.rows[0].key);
    TEquals(3, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);

    result = db.view('test/view1', {group: true, startkey: 400, endkey: 402,
      endkey_docid: "401", foobar: randVal()});
    TEquals(3, result.rows.length);
    TEquals(400, result.rows[0].key);
    TEquals(3, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);
    TEquals(402, result.rows[2].key);
    TEquals(2, result.rows[2].value);

    result = db.view('test/view1', {group: true, startkey: 400, endkey: 402,
      endkey_docid: "400", foobar: randVal()});
    TEquals(3, result.rows.length);
    TEquals(400, result.rows[0].key);
    TEquals(3, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);
    TEquals(402, result.rows[2].key);
    TEquals(1, result.rows[2].value);

    result = db.view('test/view1', {group: true, startkey: 402, startkey_docid: "401",
      endkey: 400, descending: true, foobar: randVal()});
    TEquals(3, result.rows.length);
    TEquals(402, result.rows[0].key);
    TEquals(2, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);
    TEquals(400, result.rows[2].key);
    TEquals(3, result.rows[2].value);

    result = db.view('test/view1', {group: true, startkey: 402, startkey_docid: "400",
      endkey: 400, descending: true, foobar: randVal()});
    TEquals(3, result.rows.length);
    TEquals(402, result.rows[0].key);
    TEquals(1, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);
    TEquals(400, result.rows[2].key);
    TEquals(3, result.rows[2].value);

    result = db.view('test/view1', {group: true, startkey: 402, startkey_docid: "401",
      endkey: 400, descending: true, inclusive_end: false, foobar: randVal()});
    TEquals(2, result.rows.length);
    TEquals(402, result.rows[0].key);
    TEquals(2, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);

    result = db.view('test/view1', {group: true, startkey: 402, startkey_docid: "400",
      endkey: 400, descending: true, inclusive_end: false, foobar: randVal()});
    TEquals(2, result.rows.length);
    TEquals(402, result.rows[0].key);
    TEquals(1, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);

    result = db.view('test/view1', {group: true, startkey: 402, endkey: 400,
      endkey_docid: "398", descending: true, inclusive_end: true, foobar: randVal()});
    TEquals(3, result.rows.length);
    TEquals(402, result.rows[0].key);
    TEquals(3, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);
    TEquals(400, result.rows[2].key);
    TEquals(3, result.rows[2].value);

    result = db.view('test/view1', {group: true, startkey: 402, endkey: 400,
      endkey_docid: "399", descending: true, inclusive_end: true, foobar: randVal()});
    TEquals(3, result.rows.length);
    TEquals(402, result.rows[0].key);
    TEquals(3, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);
    TEquals(400, result.rows[2].key);
    TEquals(2, result.rows[2].value);

    result = db.view('test/view1', {group: true, startkey: 402, endkey: 400,
      endkey_docid: "399", descending: true, inclusive_end: false, foobar: randVal()});
    TEquals(3, result.rows.length);
    TEquals(402, result.rows[0].key);
    TEquals(3, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);
    TEquals(400, result.rows[2].key);
    TEquals(1, result.rows[2].value);

    result = db.view('test/view1', {group: true, startkey: 402, endkey: 400,
      endkey_docid: "400", descending: true, inclusive_end: false, foobar: randVal()});
    TEquals(2, result.rows.length);
    TEquals(402, result.rows[0].key);
    TEquals(3, result.rows[0].value);
    TEquals(401, result.rows[1].key);
    TEquals(3, result.rows[1].value);

    db.deleteDb();
  }

  testReducePagination();

};
<|endoftext|>


<commit_before>var webpack = require("webpack");
var webpackDevServer = require('webpack-dev-server');
var path = require('path');
var baseConfig = require('../config/webpack.config.dist');

var port = 8080;
var serverURI = `webpack-dev-server/client?http://localhost:${port}/`;

var browser = baseConfig();
browser.output.libraryTarget = "var";
browser.output.filename = "./dist/seng-boilerplate.js";
browser.output.path = path.join(__dirname, '../dist');
browser.entry = [serverURI, browser.entry];

browser.devtool = 'source-map';
browser.watch = true;
browser.progress = true;
browser.keepalive = true;

var compiler = webpack(browser);
var server = new webpackDevServer(compiler, {
	contentBase: "example/"
});

server.listen(port, function(err) {
	if (err) {
		console.log(err);
		return
	}
	console.log(`Listening at http://localhost:${port}\n`);
});
<commit_msg>Disable chunks in webpack-dev-server stats to minimize noise<commit_after>var webpack = require("webpack");
var webpackDevServer = require('webpack-dev-server');
var path = require('path');
var baseConfig = require('../config/webpack.config.dist');

var port = 8080;
var serverURI = `webpack-dev-server/client?http://localhost:${port}/`;

var browser = baseConfig();
browser.output.libraryTarget = "var";
browser.output.filename = "./dist/seng-boilerplate.js";
browser.output.path = path.join(__dirname, '../dist');
browser.entry = [serverURI, browser.entry];

browser.devtool = 'source-map';
browser.watch = true;
browser.progress = true;
browser.keepalive = true;

var compiler = webpack(browser);
var server = new webpackDevServer(compiler, {
	contentBase: "example/",
	stats: {
		colors: true,
		chunks: false
	}
});

server.listen(port, function(err) {
	if (err) {
		console.log(err);
		return
	}
	console.log(`Listening at http://localhost:${port}\n`);
});
<|endoftext|>


<commit_before>// TODO: Extract rendering logic to a Renderer object

function Simulation(driveA, driveB, arms, pen) {

	this.driveA = driveA;
	this.driveB = driveB;
	this.arms = arms;
	this.pen = pen;
	this.timeStep = 10;
	this.stepsPerFrame = 10;
	this.renderTools = false;
	this.fadeColor = "rgba(0,0,0,0.1)";
	this.fadeInterval = 6;

	var currentTime = 0;

	this.stepTime = function () {
		currentTime += (+this.timeStep);
		return currentTime;
	};
}

var drawBuffer = [];

Simulation.prototype.step = function() {
	try {
		var t = this.stepTime();

		driveA.step(t);
		driveB.step(t);
		arms.step(t);
		pen.step(t);

		drawBuffer.push({ x: pen.mountPoint.x, y: pen.mountPoint.y, style: pen.lineStyle });
	} catch (err) {
		console.warn(err);
	}
};

Simulation.prototype.draw = function(context) {
	if (drawBuffer.length <= 1) {
		return;
	}

	context.beginPath();

	context.lineTo(drawBuffer[0].x, drawBuffer[0].y);
	for (var i = 1; i < drawBuffer.length; i++) {
		var nextPoint = drawBuffer[i];
		context.strokeStyle = nextPoint.style;
		context.lineTo(nextPoint.x, nextPoint.y);
	}

	context.stroke();

	var lastPoint = drawBuffer[drawBuffer.length - 1];
	drawBuffer = [ lastPoint ];
};

Simulation.prototype.drawTools = function(context) {
	var width = context.canvas.width;
	var height = context.canvas.height;

	context.clearRect(0, 0, width, height);

	driveA.render(context);
	driveB.render(context);
	arms.render(context);
	pen.render(context);
};

Simulation.prototype.runSingleStep = function(drawingContext, toolsDrawingContext) {
	this.step();
	this.draw(drawingContext);
	if (this.renderTools) {
		this.drawTools(toolsDrawingContext);
	}
};

Simulation.prototype.runOnce = function(drawingContext, toolsDrawingContext) {
	for (var i = 0; i < this.stepsPerFrame; i++) {
		this.step();
	}

	this.draw(drawingContext);
	if (this.renderTools) {
		this.drawTools(toolsDrawingContext);
	}
};

var running = false;

Simulation.prototype.run = function(drawingContext, toolsDrawingContext) {
	running = true;
	var self = this;
	var frameCounter = 0;

	function runStep() {
		if (self.fadeInterval) {
			if (frameCounter++ >= self.fadeInterval) {
				frameCounter = 0;
				drawingContext.fillStyle = self.fadeColor;
				drawingContext.fillRect(0, 0, drawingArea.width, drawingArea.height);
			}
		} else {
			frameCounter = 0;
		}

		self.runOnce(drawingContext, toolsDrawingContext);

		if (running) {
			requestAnimationFrame(runStep);
		}
	}

	runStep();
};

Simulation.prototype.pause = function() {
	running = false;
};<commit_msg>Bug fixes<commit_after>// TODO: Extract rendering logic to a Renderer object

function Simulation(driveA, driveB, arms, pen) {

	this.driveA = driveA;
	this.driveB = driveB;
	this.arms = arms;
	this.pen = pen;
	this.timeStep = 10;
	this.stepsPerFrame = 10;
	this.renderTools = false;
	this.fadeColor = "rgba(0,0,0,0.1)";
	this.fadeInterval = 6;

	var currentTime = 0;

	this.stepTime = function () {
		currentTime += (+this.timeStep);
		return currentTime;
	};
}

var drawBuffer = [];

Simulation.prototype.step = function() {
	try {
		var t = this.stepTime();

		this.driveA.step(t);
		this.driveB.step(t);
		this.arms.step(t);
		this.pen.step(t);

		drawBuffer.push({ x: this.pen.mountPoint.x, y: this.pen.mountPoint.y, style: this.pen.lineStyle });
	} catch (err) {
		console.warn(err);
	}
};

Simulation.prototype.draw = function(context) {
	if (drawBuffer.length <= 1) {
		return;
	}

	context.beginPath();

	context.lineTo(drawBuffer[0].x, drawBuffer[0].y);
	for (var i = 1; i < drawBuffer.length; i++) {
		var nextPoint = drawBuffer[i];
		context.strokeStyle = nextPoint.style;
		context.lineTo(nextPoint.x, nextPoint.y);
	}

	context.stroke();

	var lastPoint = drawBuffer[drawBuffer.length - 1];
	drawBuffer = [ lastPoint ];
};

Simulation.prototype.drawTools = function(context) {
	var width = context.canvas.width;
	var height = context.canvas.height;

	context.clearRect(0, 0, width, height);

	this.driveA.render(context);
	this.driveB.render(context);
	this.arms.render(context);
	this.pen.render(context);
};

Simulation.prototype.runSingleStep = function(drawingContext, toolsDrawingContext) {
	this.step();
	this.draw(drawingContext);
	if (this.renderTools) {
		this.drawTools(toolsDrawingContext);
	}
};

Simulation.prototype.runOnce = function(drawingContext, toolsDrawingContext) {
	for (var i = 0; i < this.stepsPerFrame; i++) {
		this.step();
	}

	this.draw(drawingContext);
	if (this.renderTools) {
		this.drawTools(toolsDrawingContext);
	}
};

var running = false;

Simulation.prototype.run = function(drawingContext, toolsDrawingContext) {
	running = true;
	var self = this;
	var frameCounter = 0;

	function runStep() {
		if (self.fadeInterval) {
			if (frameCounter++ >= self.fadeInterval) {
				frameCounter = 0;
				drawingContext.fillStyle = self.fadeColor;
				drawingContext.fillRect(0, 0, drawingContext.canvas.width, drawingContext.canvas.height);
			}
		} else {
			frameCounter = 0;
		}

		self.runOnce(drawingContext, toolsDrawingContext);

		if (running) {
			requestAnimationFrame(runStep);
		}
	}

	runStep();
};

Simulation.prototype.pause = function() {
	running = false;
};<|endoftext|>


<commit_before>var appIds = [],
  appIds_discount = [],
  appIds_discount_detailed = [],
  XHRs = [],
  CHUNK_SIZE = 200,
  XHRsinProgress = false;

//usually triggered when Chrome makes an update check
// -triggered by requestUpdateCheck AND Chromes automatic update mechanism
chrome.runtime.onUpdateAvailable.addListener(function(details) {
  console.log("updating to version " + details.version);
  chrome.runtime.reload();
});
//Force update check when background script is loaded
// -at the moment on browser start
chrome.runtime.requestUpdateCheck(function(status) {
  console.info("requestUpdateCheck result: ", status);
});

var getAllApps = function(callback) {
  console.info("Performing requests.");

  $.ajax({
    url: "http://api.steampowered.com/ISteamApps/GetAppList/v2",
    type: "GET",
    accepts: "application/json",
    retryLimit: 3
  })
    .done(function(response) {
      $.each(response.applist.apps, function(index, value) {
        appIds.push(value.appid);
      });
      //console.log(response.applist.apps);
      console.log(appIds);
      if (callback !== 'undefined') callback();
    });
};

var getAppDetails = function(appIds, urlParams) {
  return $.ajax({
    url: "http://store.steampowered.com/api/appdetails/?appids=" + appIds.toString() + urlParams,
    type: "GET",
    accepts: "application/json",
    statusCode: {
      200: function(data, textStatus, jqXHR) {
        $.each(data, function(key, value) {
          if (value.success === true && !$.isArray(value.data)) {
            if (urlParams.indexOf("filters=price_overview") > -1) {
              if (value.data.price_overview.discount_percent !== 0) {
                appIds_discount.push(key);
              }
            } else {
              appIds_discount_detailed.push({
                appid: value.data.steam_appid.toString(),
                type: value.data.type,
                name: value.data.name,
                price_overview: value.data.price_overview,
                categories: value.data.categories,
                genres: value.data.genres,
                platforms: value.data.platforms,
                metacritic: value.data.metacritic,
                recommendations: value.data.recommendations, //optional
                controller_support: value.data.controller_support
              });
            }
          }
        });
        if (urlParams.indexOf("filters=price_overview") > -1) {
          console.log(appIds_discount, appIds_discount.length);
        } else {
          console.log(appIds_discount_detailed, appIds_discount_detailed.length);
        }
      },
      500: function(jqXHR, textStatus, errorThrown) {
        /*console.warn("RETRYING REQUEST");
        setTimeout(function() {
          getAppDetails(appIds);
        }, 5000);*/
      }
    }
  });
};

var processAppDetails = function() {
  var chunkCount = Math.floor(appIds.length / CHUNK_SIZE),
    appIds_chunk = 0;

  var benchmark_begin,
    benchmark_end,
    benchmark = 0;

  benchmark_begin = Date.now();

  for (var i = 0; i <= chunkCount; i++) {
    appIds_chunk = makeChunk(appIds);
    XHRs.push(getAppDetails(appIds_chunk, "&cc=DE&l=english&filters=price_overview"));
  }
  //not needed because i <= chunkCount
  //XHRs.push(getAppDetails(appIds, "&cc=EE&l=english&filters=price_overview"));

  var defer = $.when.apply($, XHRs);
  defer.done(function() {
    benchmark_end = Date.now();
    console.log((benchmark_end - benchmark_begin) / 1000);
    //TODO ready to continue :)
    var todayUTC = new Date(new Date().toUTCString().substr(0, 25));
    if (todayUTC.getHours() < 17) {
      //1 day back
      todayUTC.setDate(todayUTC.getDate() - 1);
    }
    todayUTC.setHours(17, 1, 0, 0);
    //graceperiod so storage sets
    setTimeout(function() {
      chrome.storage.local.set({
        //Remember last poll to steam api
        'lastAppListPoll': todayUTC.toString(),
        'discounted_apps': appIds_discount
      }, function() {
        console.info('commited in storage');
        //empty Ajax array
        XHRs = [];
        chrome.storage.local.getBytesInUse(['discounted_apps'], function(res) {
          console.log(res);
        });
        processDiscountedAppDetails();
      });
    }, 1000);
  });
};

function makeChunk(sourceArray) {
  return sourceArray.splice(0, CHUNK_SIZE);
}

var processDiscountedAppDetails = function() {
  //CHUNK_SIZE set lower to ensure success
  CHUNK_SIZE = 50;
  var chunkCount = Math.floor(appIds_discount.length / CHUNK_SIZE),
    appIds_chunk = 0;

  for (var i = 0; i <= chunkCount; i++) {
    appIds_chunk = makeChunk(appIds_discount);
    XHRs.push(getAppDetails(appIds_chunk, "&cc=DE&l=english"));
  }
  //XHRs.push(getAppDetails(appIds_discount, "&cc=DE&l=english"));
  var defer = $.when.apply($, XHRs);
  defer.done(function() {
    //graceperiod so storage sets
    setTimeout(function() {
      chrome.storage.local.set({
        'discounted_apps_detailed': appIds_discount_detailed
      }, function() {
        console.info('commited in storage');
        chrome.storage.local.getBytesInUse(['discounted_apps_detailed'], function(res) {
          console.log("Bytes in Use discounted_apps_detailed " + res);
        });
        //empty Ajax array
        XHRs = [];
        //stop badge animation
        XHRsinProgress = false;
        displayProgressInBadge_End();
      });
    }, 1000);
  });
};

function displayProgressInBadge() {

  chrome.browserAction.getBadgeText({}, function(result) {
    var newBadgeText = '';

    if ((result === '.  ' || result === '.. ' || result === '...') && XHRsinProgress) {
      if (result === '.  ') {
        newBadgeText = '.. ';
      } else if (result === '.. ') {
        newBadgeText = '...';
      } else if (result === '...') {
        newBadgeText = '.  ';
      }
    } else {
      return false;
    }
    chrome.browserAction.setBadgeText({
      text: newBadgeText
    });
    setTimeout(displayProgressInBadge, 500);
  });
}

function displayProgressInBadge_Start() {
  chrome.browserAction.setBadgeBackgroundColor({
    color: "#3366CC"
  });
  chrome.browserAction.setBadgeText({
    text: '.  '
  });

  displayProgressInBadge();
}

function displayProgressInBadge_End() {
  chrome.browserAction.setBadgeText({
    text: 'Ok'
  });
  setTimeout(function() {
    chrome.browserAction.setBadgeText({
      text: ''
    });
  }, 2000);
}
//Immediate initialization function called on browser start, i.e. when bg script is initialized
(function() {
  console.info('init');

  chrome.storage.local.get(['lastAppListPoll'], function(items) {
    if (items.lastAppListPoll) {
      //Steam update time set to 17:01 UTC
      var storedDate = new Date(items.lastAppListPoll),
        today = new Date(new Date().toUTCString().substr(0, 25)),
        diff = today - storedDate;

      console.log("storedDate(UTC): ", storedDate);
      console.log("today(UTC): ", today);
      console.log(diff, "today gt storedDate: ", today > storedDate, "today lt storedDate: ", today < storedDate);
      var dayDiff = Math.floor(diff / (1000 * 60 * 60 * 24));

      /*console.warn("DEBUG - OVERWRITING dayDiff");
      dayDiff = 5;*/
      if (dayDiff > 0) {
        XHRsinProgress = true;
        displayProgressInBadge_Start();

        getAllApps(processAppDetails);
      } else {
        console.info("Less than one day has passed since last update.");
      }
    } else {
      XHRsinProgress = true;
      displayProgressInBadge_Start();
      //no date in storage found
      console.info("No lastAppListPoll parameter found in storage.");
      getAllApps(processAppDetails);
    }
  });
})();
<commit_msg>* comments<commit_after>var appIds = [],
  appIds_discount = [],
  appIds_discount_detailed = [],
  XHRs = [],
  CHUNK_SIZE = 200,
  XHRsinProgress = false;

//usually triggered when Chrome makes an update check
// -triggered by requestUpdateCheck AND Chromes automatic update mechanism
chrome.runtime.onUpdateAvailable.addListener(function(details) {
  console.log("updating to version " + details.version);
  //UNLOADS POPUP
  chrome.runtime.reload();
});
//Force update check when background script is loaded
// -at the moment on browser start
chrome.runtime.requestUpdateCheck(function(status) {
  console.info("requestUpdateCheck result: ", status);
});

var getAllApps = function(callback) {
  console.info("Performing requests.");

  $.ajax({
    url: "http://api.steampowered.com/ISteamApps/GetAppList/v2",
    type: "GET",
    accepts: "application/json",
    retryLimit: 3
  })
    .done(function(response) {
      $.each(response.applist.apps, function(index, value) {
        appIds.push(value.appid);
      });
      //console.log(response.applist.apps);
      console.log(appIds);
      if (callback !== 'undefined') callback();
    });
};

var getAppDetails = function(appIds, urlParams) {
  return $.ajax({
    url: "http://store.steampowered.com/api/appdetails/?appids=" + appIds.toString() + urlParams,
    type: "GET",
    accepts: "application/json",
    statusCode: {
      200: function(data, textStatus, jqXHR) {
        $.each(data, function(key, value) {
          if (value.success === true && !$.isArray(value.data)) {
            if (urlParams.indexOf("filters=price_overview") > -1) {
              if (value.data.price_overview.discount_percent !== 0) {
                appIds_discount.push(key);
              }
            } else {
              appIds_discount_detailed.push({
                appid: value.data.steam_appid.toString(),
                type: value.data.type,
                name: value.data.name,
                price_overview: value.data.price_overview,
                categories: value.data.categories,
                genres: value.data.genres,
                platforms: value.data.platforms,
                metacritic: value.data.metacritic,
                recommendations: value.data.recommendations, //optional
                controller_support: value.data.controller_support
              });
            }
          }
        });
        if (urlParams.indexOf("filters=price_overview") > -1) {
          console.log(appIds_discount, appIds_discount.length);
        } else {
          console.log(appIds_discount_detailed, appIds_discount_detailed.length);
        }
      },
      500: function(jqXHR, textStatus, errorThrown) {
        /*console.warn("RETRYING REQUEST");
        setTimeout(function() {
          getAppDetails(appIds);
        }, 5000);*/
      }
    }
  });
};

var processAppDetails = function() {
  var chunkCount = Math.floor(appIds.length / CHUNK_SIZE),
    appIds_chunk = 0;

  var benchmark_begin,
    benchmark_end,
    benchmark = 0;

  benchmark_begin = Date.now();

  for (var i = 0; i <= chunkCount; i++) {
    appIds_chunk = makeChunk(appIds);
    XHRs.push(getAppDetails(appIds_chunk, "&cc=DE&l=english&filters=price_overview"));
  }
  //not needed because i <= chunkCount
  //XHRs.push(getAppDetails(appIds, "&cc=EE&l=english&filters=price_overview"));

  var defer = $.when.apply($, XHRs);
  defer.done(function() {
    benchmark_end = Date.now();
    console.log((benchmark_end - benchmark_begin) / 1000);
    //TODO ready to continue :)
    var todayUTC = new Date(new Date().toUTCString().substr(0, 25));
    if (todayUTC.getHours() < 17) {
      //1 day back
      todayUTC.setDate(todayUTC.getDate() - 1);
    }
    todayUTC.setHours(17, 1, 0, 0);
    //graceperiod so storage sets
    setTimeout(function() {
      chrome.storage.local.set({
        //Remember last poll to steam api
        'lastAppListPoll': todayUTC.toString(),
        'discounted_apps': appIds_discount
      }, function() {
        console.info('commited in storage');
        //empty Ajax array
        XHRs = [];
        chrome.storage.local.getBytesInUse(['discounted_apps'], function(res) {
          console.log(res);
        });
        processDiscountedAppDetails();
      });
    }, 1000);
  });
};

function makeChunk(sourceArray) {
  return sourceArray.splice(0, CHUNK_SIZE);
}

var processDiscountedAppDetails = function() {
  //CHUNK_SIZE set lower to ensure success
  CHUNK_SIZE = 50;
  var chunkCount = Math.floor(appIds_discount.length / CHUNK_SIZE),
    appIds_chunk = 0;

  for (var i = 0; i <= chunkCount; i++) {
    appIds_chunk = makeChunk(appIds_discount);
    XHRs.push(getAppDetails(appIds_chunk, "&cc=DE&l=english"));
  }
  //XHRs.push(getAppDetails(appIds_discount, "&cc=DE&l=english"));
  var defer = $.when.apply($, XHRs);
  defer.done(function() {
    //graceperiod so storage sets
    setTimeout(function() {
      chrome.storage.local.set({
        'discounted_apps_detailed': appIds_discount_detailed
      }, function() {
        console.info('commited in storage');
        chrome.storage.local.getBytesInUse(['discounted_apps_detailed'], function(res) {
          console.log("Bytes in Use discounted_apps_detailed " + res);
        });
        //empty Ajax array
        XHRs = [];
        //stop badge animation
        XHRsinProgress = false;
        displayProgressInBadge_End();
      });
    }, 1000);
  });
};

function displayProgressInBadge() {

  chrome.browserAction.getBadgeText({}, function(result) {
    var newBadgeText = '';

    if ((result === '.  ' || result === '.. ' || result === '...') && XHRsinProgress) {
      if (result === '.  ') {
        newBadgeText = '.. ';
      } else if (result === '.. ') {
        newBadgeText = '...';
      } else if (result === '...') {
        newBadgeText = '.  ';
      }
    } else {
      return false;
    }
    chrome.browserAction.setBadgeText({
      text: newBadgeText
    });
    setTimeout(displayProgressInBadge, 500);
  });
}

function displayProgressInBadge_Start() {
  chrome.browserAction.setBadgeBackgroundColor({
    color: "#3366CC"
  });
  chrome.browserAction.setBadgeText({
    text: '.  '
  });

  displayProgressInBadge();
}

function displayProgressInBadge_End() {
  chrome.browserAction.setBadgeText({
    text: 'Ok'
  });
  setTimeout(function() {
    chrome.browserAction.setBadgeText({
      text: ''
    });
  }, 2000);
}
//Immediate initialization function called on browser start, i.e. when bg script is initialized
(function() {
  console.info('init');

  chrome.storage.local.get(['lastAppListPoll'], function(items) {
    if (items.lastAppListPoll) {
      //Steam update time set to 17:01 UTC
      var storedDate = new Date(items.lastAppListPoll),
        today = new Date(new Date().toUTCString().substr(0, 25)),
        diff = today - storedDate;

      console.log("storedDate(UTC): ", storedDate);
      console.log("today(UTC): ", today);
      console.log(diff, "today gt storedDate: ", today > storedDate, "today lt storedDate: ", today < storedDate);
      var dayDiff = Math.floor(diff / (1000 * 60 * 60 * 24));

      /*console.warn("DEBUG - OVERWRITING dayDiff");
      dayDiff = 5;*/
      if (dayDiff > 0) {
        XHRsinProgress = true;
        displayProgressInBadge_Start();

        getAllApps(processAppDetails);
      } else {
        console.info("Less than one day has passed since last update.");
      }
    } else {
      XHRsinProgress = true;
      displayProgressInBadge_Start();
      //no date in storage found
      console.info("No lastAppListPoll parameter found in storage.");
      getAllApps(processAppDetails);
    }
  });
})();
<|endoftext|>


<commit_before>$(function() {

    $("input,textarea").jqBootstrapValidation({
        preventSubmit: true,
        submitError: function($form, event, errors) {
        },
        submitSuccess: function($form, event) {
            var reader = new FileReader();
            var firstHackathon, resumeData;
            $("#Field7").is(':checked') ? firstHackathon = true : firstHackathon = false;
            reader.readAsDataURL(($("#Field6"))[0].files[0]);

            reader.onload = loaded;

            function loaded(evt) {
                var resumeData = evt.target.result;
                var data = {"firstName": $('#Field1').val(), "lastName": $('#Field2').val(), "email": $('#Field3').val(), "phone": $('#Field4').val(), "suggestions": $('#Field5').val(), "resume": resumeData, "dietary": $('#Field8').val(), "first": firstHackathon};
                $.ajax({
                    url:    "http://108.24.150.90/LehighHacks/register.php",
                    type:   "POST",
                    data:   {
                        data: data
                    },
                    success: function(data) {
                        $('#success').empty();
                        if(data.indexOf("user-exists") > -1){
                            $('#success').append('
Hey, '+$('#Field1').val()+'! Looks like we already have that email registered!
').hide().fadeIn(750);
                        }
                        if(data.indexOf("added-user") > -1){
                            $('#success').append('
Thanks for registering, '+$('#Field1').val()+'!
').hide().fadeIn(750);
                            $('#submitButton').prop("disabled",true);
                        }
                    },
                    error: function(data) {
                        $('#success').append('
Sorry, '+$('#Field1').val()+', but it looks like we are having trouble right now. Try again later!
').hide().fadeIn(750);
                    }
                });
            }
        },
        filter: function() {
            return $(this).is(":visible");
        },
    });

    $("a[data-toggle=\"tab\"]").click(function(e) {
        e.preventDefault();
        $(this).tab("show");
    });
});

$('#name').focus(function() {
    $('#success').html('');
});<commit_msg>form update<commit_after>$(function() {

    $("input,textarea").jqBootstrapValidation({
        preventSubmit: true,
        submitError: function($form, event, errors) {
        },
        submitSuccess: function($form, event) {
            var reader = new FileReader();
            var firstHackathon, resumeData;
            $("#Field7").is(':checked') ? firstHackathon = true : firstHackathon = false;
            reader.readAsDataURL(($("#Field6"))[0].files[0]);

            reader.onload = loaded;

            function loaded(evt) {
                var resumeData = evt.target.result;
                var data = {"firstName": $('#Field1').val(), "lastName": $('#Field2').val(), "email": $('#Field3').val(), "phone": $('#Field4').val().replace("-", ""), "suggestions": $('#Field5').val(), "resume": resumeData, "dietary": $('#Field8').val(), "first": firstHackathon};
                $.ajax({
                    url:    "http://108.24.150.90/LehighHacks/register.php",
                    type:   "POST",
                    data:   {
                        data: data
                    },
                    success: function(data) {
                        $('#success').empty();
                        if(data.indexOf("user-exists") > -1){
                            $('#success').append('
Hey, '+$('#Field1').val()+'! Looks like we already have that email registered!
').hide().fadeIn(750);
                        }
                        if(data.indexOf("added-user") > -1){
                            $('#success').append('
Thanks for registering, '+$('#Field1').val()+'!
').hide().fadeIn(750);
                            $('#submitButton').prop("disabled",true);
                        }
                    },
                    error: function(data) {
                        $('#success').append('
Sorry, '+$('#Field1').val()+', but it looks like we are having trouble right now. Try again later!
').hide().fadeIn(750);
                    }
                });
            }
        },
        filter: function() {
            return $(this).is(":visible");
        },
    });

    $("a[data-toggle=\"tab\"]").click(function(e) {
        e.preventDefault();
        $(this).tab("show");
    });
});

$('#name').focus(function() {
    $('#success').html('');
});<|endoftext|>


<commit_before>const assert = require('assert');
const chai = require('chai');
const chaiHttp = require('chai-http');
const config = require('config');
const reqPromise = require('request-promise');
const sinon = require('sinon');

const app = require('../../src/messenger/app');

chai.use(chaiHttp);

describe('app', () => {
  const messenger = new app.Messenger(config);

  beforeEach(() => {
    sinon.stub(messenger, 'send');
  });

  afterEach(() => {
    // TODO investigate making the suite mock `reqPromise.post` instead of `send`
    messenger.send.restore && messenger.send.restore();
  });

  describe('doLogin', function () {
    this.timeout(100);
    it('emits login event', () => {
      messenger.once('login', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'narf');
      });

      messenger.doLogin('narf');

      assert.equal(messenger.send.callCount, 1);
    });
  });

  describe('onAuth', function () {
    this.timeout(100);
    const baseEvent = {
      sender: {id: 'senderId'},
      recipient: {id: 'recipientId'},
      timestamp: 0,
      optin: {ref: ''}
    };

    it('emits auth event', () => {
      messenger.once('auth', (payload) => {
        assert.ok(payload.event);
        assert.ok(payload.session);
        assert.equal(payload.senderId, 'senderId');
        assert.equal(payload.optinRef, 'narf');
      });
      const event = Object.assign({}, baseEvent, {
        optin: {
          ref: 'narf'
        }
      });

      messenger.onAuth(event, {});

      assert.equal(messenger.send.callCount, 0);
    });
  });

  describe('onLink', function () {
    this.timeout(100);
    const baseEvent = {
      sender: {id: 'senderId'},
      recipient: {id: 'recipientId'},
      timestamp: 0,
      facebook: {id: ''}
    };

    it('emits link event', () => {
      messenger.once('link', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
        assert.equal(payload.fbData.id, 'narf');
      });
      const event = Object.assign({}, baseEvent, {
        facebook: {
          id: 'narf'
        }
      });

      messenger.onLink(event);
    });
  });

  describe('onMessage message router', function () {
    this.timeout(100);
    const baseEvent = {
      sender: {id: 'senderId'},
      recipient: {id: 'recipientId'},
      timestamp: 0,
      message: {}
    };

    it('emits "message" event', () => {
      messenger.once('message', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
        assert.deepEqual(payload.message, {foo: 'bar'});
      });
      const event = Object.assign({}, baseEvent, {
        message: {foo: 'bar'}
      });

      messenger.onMessage(event);
    });

    it('emits "text" event', () => {
      const event = Object.assign({}, baseEvent, {
        message: {
          text: 'message text'
        }
      });
      const fakeSession = {};
      messenger.once('message.text', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
        assert.equal(payload.text, 'message text');
      });

      messenger.onMessage(event, fakeSession);
    });

    it('emits "quick reply" event', () => {
      const messageText = 'Browse other looks';
      const quickReplyPayload = 'looks';
      messenger.once('message.quickReply', (quickReply) => {
        assert.ok(quickReply.event);
        assert.equal(quickReply.senderId, 'senderId');
        assert.equal(quickReply.payload, quickReplyPayload);
      });
      const event = Object.assign({}, baseEvent, {
        message: {
          quick_reply: { payload: quickReplyPayload },
          text: messageText
        }
      });

      messenger.onMessage(event);
    });

    it('emits "image" event', () => {
      messenger.once('message.image', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
        assert.equal(payload.url, 'http://i.imgur.com/w1F7dae.jpg');
      });
      const event = Object.assign({}, baseEvent, {
        message: {
          attachments: [
            {
              type: 'image',
              payload: {
                url: 'http://i.imgur.com/w1F7dae.jpg'
              }
            }
          ]
        }
      });

      messenger.onMessage(event);
    });

    it('emits "sticker" event', () => {
      messenger.once('message.sticker', () => {});
      const event = Object.assign({}, baseEvent, {
        message: {
          sticker_id: 201013950048539,
          attachments: [
            {
              type: 'image',
              payload: {
                url: 'https://scontent.xx.fbcdn.net/t39.1997-6/p100x100/851576_201013953381872_1273966384_n.png?_nc_ad=z-m',
                sticker_id: 201013950048539
              }
            }
          ]
        }
      });

      messenger.onMessage(event);
    });

    it('emits "thumbsup" event', () => {
      messenger.once('message.thumbsup', (payload) => {
        assert.equal(payload.senderId, 'senderId');
      });
      const event = Object.assign({}, baseEvent, {
        message: {
          sticker_id: 369239263222822,
          attachments: [
            {
              type: 'image',
              payload: {
                url: 'https://scontent.xx.fbcdn.net/t39.1997-6/851557_369239266556155_759568595_n.png?_nc_ad=z-m',
                sticker_id: 369239263222822
              }
            }
          ]
        }
      });

      messenger.onMessage(event);
    });
  });

  describe('onPostback', function () {
    this.timeout(100);
    const baseEvent = {
      sender: {id: 'senderId'},
      recipient: {id: 'recipientId'},
      timestamp: 0,
      postback: {payload: ''}
    };

    it('emits postback event', () => {
      messenger.once('postback', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
        assert.equal(payload.payload, 'narf');
      });
      const event = Object.assign({}, baseEvent, {
        postback: {
          payload: 'narf'
        }
      });

      messenger.onPostback(event);
    });
  });

  describe('send', function () {
    let postStub;

    beforeEach(() => {
      postStub = sinon.stub(reqPromise, 'post').returns(Promise.resolve({}));
    });

    afterEach(() => {
      postStub.restore();
    });

    it('passed sender id and message', () => {
      messenger.send.restore();

      return messenger.send('senderId', {foo: 'bar'})
        .then(() => {
          assert.equal(reqPromise.post.args[0][0].json.recipient.id, 'senderId');
          assert.deepEqual(reqPromise.post.args[0][0].json.message, {foo: 'bar'});
        });
    });
  });

  describe('staticContent', function () {
    it('provides a homepage', (done) => {
      chai.request(messenger.app)
        .get('/')
        .end(function (err, res) {
          assert.equal(res.statusCode, 200);
          done();
        });
    });

    xit('provides a Send to Messenger button', (done) => {
      chai.request(messenger.app)
        .get('/send-to-messenger')
        .end(function (err, res) {
          assert.equal(res.statusCode, 200);
          assert.ok(res.text.includes('fb-send-to-messenger'));
          done();
        });
    });

    xit('provides a Message Us button', (done) => {
      chai.request(messenger.app)
        .get('/send-to-messenger')
        .end(function (err, res) {
          assert.equal(res.statusCode, 200);
          assert.ok(res.text.includes('fb-messengermessageus'));
          done();
        });
    });

    it('provides a departures healthcheck', (done) => {
      chai.request(messenger.app)
        .get('/ping')
        .end(function (err, res) {
          assert.equal(res.statusCode, 200);
          done();
        });
    });

  });

  describe('routeEachMessage session', () => {
    const baseMessage = {
      sender: {id: 'teehee'}
    };
    let messenger;

    beforeEach(() => {
      messenger = new app.Messenger(config);
      sinon.stub(messenger, 'getPublicProfile').returns({then: (resolve) => resolve({})});
    });

    afterEach(() => {
      messenger.getPublicProfile.restore();
    });

    it('counts every message received', () =>
      messenger.routeEachMessage(baseMessage)
        .then(() => messenger.routeEachMessage(baseMessage))
        .then((session) => {
          assert.equal(session.count, 2);
        })
    );

    it('sets lastSeen', () =>
      messenger.routeEachMessage(baseMessage)
        .then((session) => {
          assert.equal(typeof session.lastSeen, 'number');
        })
    );

    it('sets source for auth messages', () => {
      const authMessage = Object.assign({optin: 'foo'}, baseMessage);
      return messenger.routeEachMessage(authMessage)
        .then(() => app.__internals__.cache.get(baseMessage.sender.id))
        .then((session) => {
          assert.equal(session.source, 'web');
        });
    });

    describe('return user', () => {
      let originalValue;

      before(() => {
        originalValue = app.__internals__.SESSION_TIMEOUT_MS;
        app.__internals__.SESSION_TIMEOUT_MS = 0;
      });

      after(() => {
        app.__internals__.SESSION_TIMEOUT_MS = originalValue;
      });

      it('sets source for return user', () =>
        messenger.routeEachMessage(baseMessage)
          .then((session) => {
            session.source = 'foo';
            return messenger.routeEachMessage(baseMessage);
          })
          .then((session) => {
            assert.equal(session.source, 'return');
          })
      );
    });

    it('does not set source for user still in session', () =>
      messenger.routeEachMessage(baseMessage)
        .then((session) => {
          session.source = 'foo this should not change';
          return app.__internals__.cache.set(baseMessage.sender.id, session);
        })
        .then(() => {
          return messenger.routeEachMessage(baseMessage);
        })
        .then((session) => {
          assert.equal(session.source, 'foo this should not change');
        })
    );
  });
});
<commit_msg>Optionally check for & emit greetings in the SDK (#18)<commit_after>const assert = require('assert');
const chai = require('chai');
const chaiHttp = require('chai-http');
const config = require('config');
const reqPromise = require('request-promise');
const sinon = require('sinon');

const app = require('../../src/messenger/app');

chai.use(chaiHttp);

describe('app', () => {
  const messenger = new app.Messenger(config);

  beforeEach(() => {
    sinon.stub(messenger, 'send');
  });

  afterEach(() => {
    // TODO investigate making the suite mock `reqPromise.post` instead of `send`
    messenger.send.restore && messenger.send.restore();
  });

  describe('doLogin', function () {
    this.timeout(100);
    it('emits login event', () => {
      messenger.once('login', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'narf');
      });

      messenger.doLogin('narf');

      assert.equal(messenger.send.callCount, 1);
    });
  });

  describe('onAuth', function () {
    this.timeout(100);
    const baseEvent = {
      sender: {id: 'senderId'},
      recipient: {id: 'recipientId'},
      timestamp: 0,
      optin: {ref: ''}
    };

    it('emits auth event', () => {
      messenger.once('auth', (payload) => {
        assert.ok(payload.event);
        assert.ok(payload.session);
        assert.equal(payload.senderId, 'senderId');
        assert.equal(payload.optinRef, 'narf');
      });
      const event = Object.assign({}, baseEvent, {
        optin: {
          ref: 'narf'
        }
      });

      messenger.onAuth(event, {});

      assert.equal(messenger.send.callCount, 0);
    });
  });

  describe('onLink', function () {
    this.timeout(100);
    const baseEvent = {
      sender: {id: 'senderId'},
      recipient: {id: 'recipientId'},
      timestamp: 0,
      facebook: {id: ''}
    };

    it('emits link event', () => {
      messenger.once('link', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
        assert.equal(payload.fbData.id, 'narf');
      });
      const event = Object.assign({}, baseEvent, {
        facebook: {
          id: 'narf'
        }
      });

      messenger.onLink(event);
    });
  });

  describe('onMessage message router', function () {
    this.timeout(100);
    const baseEvent = {
      sender: {id: 'senderId'},
      recipient: {id: 'recipientId'},
      timestamp: 0,
      message: {}
    };

    it('emits "message" event', () => {
      messenger.once('message', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
        assert.deepEqual(payload.message, {foo: 'bar'});
      });
      const event = Object.assign({}, baseEvent, {
        message: {foo: 'bar'}
      });

      messenger.onMessage(event);
    });

    it('emits "text" event', () => {
      const event = Object.assign({}, baseEvent, {
        message: {
          text: 'message text'
        }
      });
      const fakeSession = {};
      messenger.once('message.text', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
        assert.equal(payload.text, 'message text');
      });

      messenger.onMessage(event, fakeSession);
    });

    it('emits "quick reply" event', () => {
      const messageText = 'Browse other looks';
      const quickReplyPayload = 'looks';
      messenger.once('message.quickReply', (quickReply) => {
        assert.ok(quickReply.event);
        assert.equal(quickReply.senderId, 'senderId');
        assert.equal(quickReply.payload, quickReplyPayload);
      });
      const event = Object.assign({}, baseEvent, {
        message: {
          quick_reply: { payload: quickReplyPayload },
          text: messageText
        }
      });

      messenger.onMessage(event);
    });

    it('emits "image" event', () => {
      messenger.once('message.image', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
        assert.equal(payload.url, 'http://i.imgur.com/w1F7dae.jpg');
      });
      const event = Object.assign({}, baseEvent, {
        message: {
          attachments: [
            {
              type: 'image',
              payload: {
                url: 'http://i.imgur.com/w1F7dae.jpg'
              }
            }
          ]
        }
      });

      messenger.onMessage(event);
    });

    it('emits "sticker" event', () => {
      messenger.once('message.sticker', () => {});
      const event = Object.assign({}, baseEvent, {
        message: {
          sticker_id: 201013950048539,
          attachments: [
            {
              type: 'image',
              payload: {
                url: 'https://scontent.xx.fbcdn.net/t39.1997-6/p100x100/851576_201013953381872_1273966384_n.png?_nc_ad=z-m',
                sticker_id: 201013950048539
              }
            }
          ]
        }
      });

      messenger.onMessage(event);
    });

    it('emits "thumbsup" event', () => {
      messenger.once('message.thumbsup', (payload) => {
        assert.equal(payload.senderId, 'senderId');
      });
      const event = Object.assign({}, baseEvent, {
        message: {
          sticker_id: 369239263222822,
          attachments: [
            {
              type: 'image',
              payload: {
                url: 'https://scontent.xx.fbcdn.net/t39.1997-6/851557_369239266556155_759568595_n.png?_nc_ad=z-m',
                sticker_id: 369239263222822
              }
            }
          ]
        }
      });

      messenger.onMessage(event);
    });

    it('emits "greeting" event', () => {
      const text = "hello, is it me you're looking for?";
      const event = Object.assign({}, baseEvent, { message: { text: text } });
      messenger.once('text.greeting', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
      });

      messenger.once('message.text', (payload) => {
        assert.fail('message.text', 'message.greeting', 'incorrect event emitted');
      });

      messenger.onMessage(event, {});
    });

    it('emits "text" event for greeting when emitGreetings is disabled', () => {
      const myMessenger = new app.Messenger(config, {emitGreetings: false});
      sinon.stub(myMessenger, 'send');

      const text = "hello, is it me you're looking for?";
      const event = Object.assign({}, baseEvent, {
        message: { text: text }
      });
      myMessenger.once('message.greeting', (payload) => {
        assert.fail('message.text', 'message.greeting', 'incorrect event emitted');
      });

      myMessenger.once('message.text', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
      });

      myMessenger.onMessage(event, {});
    });

  });

  describe('onPostback', function () {
    this.timeout(100);
    const baseEvent = {
      sender: {id: 'senderId'},
      recipient: {id: 'recipientId'},
      timestamp: 0,
      postback: {payload: ''}
    };

    it('emits postback event', () => {
      messenger.once('postback', (payload) => {
        assert.ok(payload.event);
        assert.equal(payload.senderId, 'senderId');
        assert.equal(payload.payload, 'narf');
      });
      const event = Object.assign({}, baseEvent, {
        postback: {
          payload: 'narf'
        }
      });

      messenger.onPostback(event);
    });
  });

  describe('send', function () {
    let postStub;

    beforeEach(() => {
      postStub = sinon.stub(reqPromise, 'post').returns(Promise.resolve({}));
    });

    afterEach(() => {
      postStub.restore();
    });

    it('passed sender id and message', () => {
      messenger.send.restore();

      return messenger.send('senderId', {foo: 'bar'})
        .then(() => {
          assert.equal(reqPromise.post.args[0][0].json.recipient.id, 'senderId');
          assert.deepEqual(reqPromise.post.args[0][0].json.message, {foo: 'bar'});
        });
    });
  });

  describe('staticContent', function () {
    it('provides a homepage', (done) => {
      chai.request(messenger.app)
        .get('/')
        .end(function (err, res) {
          assert.equal(res.statusCode, 200);
          done();
        });
    });

    xit('provides a Send to Messenger button', (done) => {
      chai.request(messenger.app)
        .get('/send-to-messenger')
        .end(function (err, res) {
          assert.equal(res.statusCode, 200);
          assert.ok(res.text.includes('fb-send-to-messenger'));
          done();
        });
    });

    xit('provides a Message Us button', (done) => {
      chai.request(messenger.app)
        .get('/send-to-messenger')
        .end(function (err, res) {
          assert.equal(res.statusCode, 200);
          assert.ok(res.text.includes('fb-messengermessageus'));
          done();
        });
    });

    it('provides a departures healthcheck', (done) => {
      chai.request(messenger.app)
        .get('/ping')
        .end(function (err, res) {
          assert.equal(res.statusCode, 200);
          done();
        });
    });

  });

  describe('routeEachMessage session', () => {
    const baseMessage = {
      sender: {id: 'teehee'}
    };
    let messenger;

    beforeEach(() => {
      messenger = new app.Messenger(config);
      sinon.stub(messenger, 'getPublicProfile').returns({then: (resolve) => resolve({})});
    });

    afterEach(() => {
      messenger.getPublicProfile.restore();
    });

    it('counts every message received', () =>
      messenger.routeEachMessage(baseMessage)
        .then(() => messenger.routeEachMessage(baseMessage))
        .then((session) => {
          assert.equal(session.count, 2);
        })
    );

    it('sets lastSeen', () =>
      messenger.routeEachMessage(baseMessage)
        .then((session) => {
          assert.equal(typeof session.lastSeen, 'number');
        })
    );

    it('sets source for auth messages', () => {
      const authMessage = Object.assign({optin: 'foo'}, baseMessage);
      return messenger.routeEachMessage(authMessage)
        .then(() => app.__internals__.cache.get(baseMessage.sender.id))
        .then((session) => {
          assert.equal(session.source, 'web');
        });
    });

    describe('return user', () => {
      let originalValue;

      before(() => {
        originalValue = app.__internals__.SESSION_TIMEOUT_MS;
        app.__internals__.SESSION_TIMEOUT_MS = 0;
      });

      after(() => {
        app.__internals__.SESSION_TIMEOUT_MS = originalValue;
      });

      it('sets source for return user', () =>
        messenger.routeEachMessage(baseMessage)
          .then((session) => {
            session.source = 'foo';
            return messenger.routeEachMessage(baseMessage);
          })
          .then((session) => {
            assert.equal(session.source, 'return');
          })
      );
    });

    it('does not set source for user still in session', () =>
      messenger.routeEachMessage(baseMessage)
        .then((session) => {
          session.source = 'foo this should not change';
          return app.__internals__.cache.set(baseMessage.sender.id, session);
        })
        .then(() => {
          return messenger.routeEachMessage(baseMessage);
        })
        .then((session) => {
          assert.equal(session.source, 'foo this should not change');
        })
    );
  });
});
<|endoftext|>


<commit_before>define(function() {
  /**
   * A game board
   *
   * @param container
   * @param width
   * @param height
   * @constructor
   */
  function GameBoard(container, width, height) {
    this.container = container;
    this.map = [];
    this.listeners = {};

    for (var i = 0; i < height; i++) {
      var row = [];
      for (var j = 0; j < width; j++) {
        row.push(new GameTile(0));
      }
      this.map.push(row);
    }

    container.innerHTML = '';
    this.map.forEach(function(row) {
      var rowEl = document.createElement('div');
      rowEl.className = 'row';
      row.forEach(function(gameTile) {
        rowEl.appendChild(gameTile.render().el);
      });

      container.appendChild(rowEl);
    });

    function _mouseMove(e) {
      var x = e.pageX,
        y = e.pageY;

      var el = document.elementFromPoint(x, y);

      if (el.tile) {
        el.tile.setHeight(el.tile.getHeight() + 5);
      }
    }

    container.addEventListener('mousedown', function(e) {
      container.addEventListener('mousemove', _mouseMove);
    });

    container.addEventListener('mouseup', function(e) {
      container.removeEventListener('mousemove', _mouseMove);
    });
  }

  /**
   * Bind a handler to the given event by name
   *
   * @param name    The name of the event
   * @param handler A Function to be called when the event is triggered
   */
  GameBoard.prototype.on = function(name, handler) {
    if (!this.listeners[name]) {
      this.listeners[name] = [];
    }

    this.listeners[name].push(handler);
  };

  /**
   * Trigger an event by name
   *
   * @param name The name of the event
   * @param args Any data to pass to the object
   */
  GameBoard.prototype.trigger = function(name, args) {
    if (!this.listeners[name]) {
      return;
    }

    this.listeners[name].slice(0).forEach(function(handler) {
      handler(args);
    });
  };

  GameBoard.prototype.getHeight = function() {
    return this.map.length;
  };

  GameBoard.prototype.getWidth = function() {
    return this.map[0].length;
  };

  GameBoard.prototype.getTile = function(x, y) {
    if (this.map[y] && this.map[y][x]) {
      return this.map[y][x];
    }

    return null;
  };

  /**
   * Start the game
   *
   * Ticks update game logic like positions, scores, etc.
   * Rendering draws the current state to the viewport
   */
  GameBoard.prototype.run = function() {
    var loops = 0, skipTicks = 1000 / 10,
      maxFrameSkip = 10,
      nextGameTick = (new Date).getTime();

    var self = this;
    var _tick = function() {
      loops = 0;

      while ((new Date).getTime() > nextGameTick && loops < maxFrameSkip) {
        self.trigger('tick');
        nextGameTick += skipTicks;
        loops++;
      }

      self.trigger('render');
    };

    setInterval(_tick, 0);
  };

  /**
   * A tile on the game board
   *
   * @param height
   * @constructor
   */
  function GameTile(height) {
    function _makeTile(gameTile) {
      var el = document.createElement('div');
      el.className = 'tile';
      el.tile      = gameTile;

      return el;
    }

    var _height;
    this.setHeight = function(height) {
      if (height < 0) {
        height = 0;
      }

      _height = height;

      var redHex = (height == 0 ? 253 : 253 - _height).toString(16);
      var greenHex = (height == 0 ? 245 : 245 - _height).toString(16);
      var blueHex = (height == 0 ? 239 : 239 - _height).toString(16);
      this.el.style.backgroundColor = "#" + redHex + greenHex + blueHex;
    };
    this.getHeight = function() {
      return _height;
    };

    this.el = _makeTile(this);
    this.setHeight(height);
  }

  GameTile.prototype.render = function() {
    // does nothing for now

    return this;
  };

  return {
    GameBoard: GameBoard,
    GameTile:  GameTile
  };
});<commit_msg>No longer repaint when nothing changes<commit_after>define(function() {
  /**
   * A game board
   *
   * @param container
   * @param width
   * @param height
   * @constructor
   */
  function GameBoard(container, width, height) {
    this.container = container;
    this.map = [];
    this.listeners = {};

    for (var i = 0; i < height; i++) {
      var row = [];
      for (var j = 0; j < width; j++) {
        row.push(new GameTile(0));
      }
      this.map.push(row);
    }

    container.innerHTML = '';
    this.map.forEach(function(row) {
      var rowEl = document.createElement('div');
      rowEl.className = 'row';
      row.forEach(function(gameTile) {
        rowEl.appendChild(gameTile.render().el);
      });

      container.appendChild(rowEl);
    });

    function _mouseMove(e) {
      var x = e.pageX,
        y = e.pageY;

      var el = document.elementFromPoint(x, y);

      if (el.tile) {
        el.tile.setHeight(el.tile.getHeight() + 5);
      }
    }

    container.addEventListener('mousedown', function(e) {
      container.addEventListener('mousemove', _mouseMove);
    });

    container.addEventListener('mouseup', function(e) {
      container.removeEventListener('mousemove', _mouseMove);
    });
  }

  /**
   * Bind a handler to the given event by name
   *
   * @param name    The name of the event
   * @param handler A Function to be called when the event is triggered
   */
  GameBoard.prototype.on = function(name, handler) {
    if (!this.listeners[name]) {
      this.listeners[name] = [];
    }

    this.listeners[name].push(handler);
  };

  /**
   * Trigger an event by name
   *
   * @param name The name of the event
   * @param args Any data to pass to the object
   */
  GameBoard.prototype.trigger = function(name, args) {
    if (!this.listeners[name]) {
      return;
    }

    this.listeners[name].slice(0).forEach(function(handler) {
      handler(args);
    });
  };

  GameBoard.prototype.getHeight = function() {
    return this.map.length;
  };

  GameBoard.prototype.getWidth = function() {
    return this.map[0].length;
  };

  GameBoard.prototype.getTile = function(x, y) {
    if (this.map[y] && this.map[y][x]) {
      return this.map[y][x];
    }

    return null;
  };

  /**
   * Start the game
   *
   * Ticks update game logic like positions, scores, etc.
   * Rendering draws the current state to the viewport
   */
  GameBoard.prototype.run = function() {
    var loops = 0, skipTicks = 1000 / 10,
      maxFrameSkip = 10,
      nextGameTick = (new Date).getTime();

    var self = this;
    var _tick = function() {
      loops = 0;

      while ((new Date).getTime() > nextGameTick && loops < maxFrameSkip) {
        self.trigger('tick');
        nextGameTick += skipTicks;
        loops++;
      }

      if (loops > 0) {
        self.trigger('render');
      }
    };

    setInterval(_tick, 0);
  };

  /**
   * A tile on the game board
   *
   * @param height
   * @constructor
   */
  function GameTile(height) {
    function _makeTile(gameTile) {
      var el = document.createElement('div');
      el.className = 'tile';
      el.tile      = gameTile;

      return el;
    }

    var _height;
    this.setHeight = function(height) {
      if (height < 0) {
        height = 0;
      }

      _height = height;

      var redHex = (height == 0 ? 253 : 253 - _height).toString(16);
      var greenHex = (height == 0 ? 245 : 245 - _height).toString(16);
      var blueHex = (height == 0 ? 239 : 239 - _height).toString(16);
      this.el.style.backgroundColor = "#" + redHex + greenHex + blueHex;
    };
    this.getHeight = function() {
      return _height;
    };

    this.el = _makeTile(this);
    this.setHeight(height);
  }

  GameTile.prototype.render = function() {
    // does nothing for now

    return this;
  };

  return {
    GameBoard: GameBoard,
    GameTile:  GameTile
  };
});<|endoftext|>


<commit_before>var request = reqwest;

var BookCreateForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();

    var title       = this.refs.title.getDOMNode().value.trim();
    var description = this.refs.description.getDOMNode().value.trim();
    var color       = this.refs.color.getDOMNode().value.trim();

    var self = this;
    request({
      url: '/api/books',
      type: 'json',
      method: 'post',
      data: {title: title, description: description, color: color},
      success: function (book) {
        self.props.onBookSubmit(book);
      }
    })

    this.refs.title.getDOMNode().value = '';
    this.refs.description.getDOMNode().value = '';
    this.refs.color.getDOMNode().value = '';
  },

  render: function() {
    return (
      <form onSubmit={this.handleSubmit}>

Create book

Title:* <input type="text" ref="title" />

Description:* <input type="text" ref="description" />

Color:* <input type="text" ref="color" />

        <input type="submit" value="Create" />
      </form>
    );
  }
});

var BookListing = React.createClass({
  render: function() {
    var bookNodes = this.props.data.map(function (book) {
      return (

{book.title}

{book.description}

      );
    });
    return (

        {bookNodes}

    );
  }
});

var BookIndex = React.createClass({
  getInitialState: function() {
    return {data: []};
  },

  componentDidMount: function() {
    request({
      url: '/api/books',
      type: 'json',
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
    })
  },

  handleBookSubmit: function(book) {
    var updatedData = this.state.data.concat([book]);
    this.setState({data: updatedData});
  },

  render: function() {
    return (

Book Listing

        <BookListing data={this.state.data} />
        <BookCreateForm onBookSubmit={this.handleBookSubmit} />

    );
  }
});

React.render(
  <BookIndex />,
  document.getElementById('main')
);
<commit_msg>BookIndex should handle all store operations<commit_after>var request = reqwest;

var BookCreateForm = React.createClass({
  handleSubmit: function(e) {
    e.preventDefault();

    var title       = this.refs.title.getDOMNode().value.trim();
    var description = this.refs.description.getDOMNode().value.trim();
    var color       = this.refs.color.getDOMNode().value.trim();

    this.props.onBookSubmit({title: title, description: description, color: color});

    this.refs.title.getDOMNode().value = '';
    this.refs.description.getDOMNode().value = '';
    this.refs.color.getDOMNode().value = '';
  },

  render: function() {
    return (
      <form onSubmit={this.handleSubmit}>

Create book

Title:* <input type="text" ref="title" />

Description:* <input type="text" ref="description" />

Color:* <input type="text" ref="color" />

        <input type="submit" value="Create" />
      </form>
    );
  }
});

var BookListing = React.createClass({
  render: function() {
    var bookNodes = this.props.data.map(function (book) {
      return (

{book.title}

{book.description}

      );
    });
    return (

        {bookNodes}

    );
  }
});

var BookIndex = React.createClass({
  getInitialState: function() {
    return {data: []};
  },

  componentDidMount: function() {
    request({
      url: '/api/books',
      type: 'json',
      success: function(data) {
        this.setState({data: data});
      }.bind(this),
    })
  },

  handleBookSubmit: function(book) {
    var self = this;
    request({
      url:    '/api/books',
      type:   'json',
      method: 'post',
      data:    book,
      success: function (book) {
        var updatedData = self.state.data.concat([book]);
        self.setState({data: updatedData});
      }
    });
  },

  render: function() {
    return (

Book Listing

        <BookListing data={this.state.data} />
        <BookCreateForm onBookSubmit={this.handleBookSubmit} />

    );
  }
});

React.render(
  <BookIndex />,
  document.getElementById('main')
);
<|endoftext|>


<commit_before>
var $ = require("./jquery-or-zepto");
var Backbone = require("backbone");
var _ = require("underscore");
var moment = require("moment");

var Rickshaw = require("./vendor/rickshaw");

var GraphView = Backbone.View.extend({

  constructor: function() {
    Backbone.View.prototype.constructor.apply(this, arguments);
    this.listenTo(this.collection, "add", this.render);
  },

  render: function() {

    var data = [];
    var count = 0;
    this.collection.each(function(m) {
      count += 1;
      data.push({
        x: m.get("seen").getTime(),
        y: count
      });
    });

    if (!data.length) {
      this.$el.html("no data!");
      return;
    }

    this.$el.empty();

    var graph = new Rickshaw.Graph( {
      element: this.el,
      width: $(window).width() - 50,
      height: 500,
      renderer: 'line',
      series: [
        {
          color: "blue",
          data: data,
          name: 'Cars'
        }
      ]
    } );

    var yAxis = new Rickshaw.Graph.Axis.Y({
        graph: graph
    });

    var xAxis = new Rickshaw.Graph.Axis.X({
        graph: graph,
        tickFormat: function(data) {
          return moment.unix(data/1000).format("hh:mm:ss a");
        }
    });

    graph.render();
    yAxis.render();
    xAxis.render();
  },

  remove: function() {
    Backbone.View.prototype.remove.apply(this, arguments);
    $(window).off("resize", this._rerender);
  }

});

module.exports = GraphView;
<commit_msg>Update graph size on resize<commit_after>
var $ = require("./jquery-or-zepto");
var Backbone = require("backbone");
var _ = require("underscore");
var moment = require("moment");

var Rickshaw = require("./vendor/rickshaw");

var GraphView = Backbone.View.extend({

  constructor: function() {
    Backbone.View.prototype.constructor.apply(this, arguments);
    this.listenTo(this.collection, "add", this.render);

    this._rerender = _.debounce(this.render.bind(this) , 250);
    $(window).on("resize", this._rerender);
  },

  render: function() {

    var data = [];
    var count = 0;
    this.collection.each(function(m) {
      count += 1;
      data.push({
        x: m.get("seen").getTime(),
        y: count
      });
    });

    if (!data.length) {
      this.$el.html("no data!");
      return;
    }

    this.$el.empty();

    var graph = new Rickshaw.Graph( {
      element: this.el,
      width: $(window).width() - 50,
      height: 500,
      renderer: 'line',
      series: [
        {
          color: "blue",
          data: data,
          name: 'Cars'
        }
      ]
    } );

    var yAxis = new Rickshaw.Graph.Axis.Y({
        graph: graph
    });

    var xAxis = new Rickshaw.Graph.Axis.X({
        graph: graph,
        tickFormat: function(data) {
          return moment.unix(data/1000).format("hh:mm:ss a");
        }
    });

    graph.render();
    yAxis.render();
    xAxis.render();
  },

  remove: function() {
    Backbone.View.prototype.remove.apply(this, arguments);
    $(window).off("resize", this._rerender);
  }

});

module.exports = GraphView;
<|endoftext|>


<commit_before>/*
 * Author:        Pierre-Henry Soria <ph7software@gmail.com>
 * Copyright:     (c) 2012-2016, Pierre-Henry Soria. All Rights Reserved.
 * License:       GNU General Public License; See PH7.LICENSE.txt and PH7.COPYRIGHT.txt in the root directory.
 */

/*
 * ATTENTION!
 * Please remplace "ph7cms" by your username by registering on: http://www.geonames.org/login
 * After, you will need to enable the Free Web Services here: http://www.geonames.org/manageaccount
 */
var sGeonamesUsername = 'ph7cms'; // Remplace "ph7cms" by your username!

function autocompleteCityInit()
{
    // Set the variables
    var sCountry = $('#str_country').val();
    var sUrlSlug = (typeof sCountry != 'undefined' ? '?country=' + sCountry : '');

    $('#str_city').autocomplete(
    {
        source: function(oRequest, oResponse)
        {
            $.ajax(
            {
                url: 'http://ws.geonames.org/searchJSON' + sUrlSlug + '&username=' + sGeonamesUsername,
                dataType: 'jsonp',
                data:
                {
                    featureClass: 'P',
                    style: 'full',
                    maxRows: 12,
                    name_startsWith: oRequest.term
                },
                success: function(oData)
                {
                    // Check if "geonames" exists. When the API returns an error message, it won't return "geonames"
                    if (!oData.geonames)
                    {
                        if (oData.status.message) {
                            console.error(oData.status.message); // Display the error message from the API into the browser's log
                        }
                    }
                    else
                    {
                        oResponse($.map(oData.geonames, function(oItem)
                        {
                            $('#str_city').click(function()
                            {
                                $('#str_state').val((oItem.adminName1 ? oItem.adminName1 : ''));
                                $('#str_zip_code').val(oItem.postalcode);
                            });

                            return {
                                label: oItem.name + (oItem.adminName1 ? ', ' + oItem.adminName1 : '') + (sCountry ? '' : ', ' + oItem.countryName),
                                value: oItem.name
                            }
                        }));
                    }
                }
            })
        }
    })
}

$(document).ready(function()
{
    autocompleteCityInit();
});<commit_msg>Other improvements<commit_after>/*
 * Author:        Pierre-Henry Soria <ph7software@gmail.com>
 * Copyright:     (c) 2012-2016, Pierre-Henry Soria. All Rights Reserved.
 * License:       GNU General Public License; See PH7.LICENSE.txt and PH7.COPYRIGHT.txt in the root directory.
 */

/*
 * ATTENTION!
 * Please remplace "ph7cms" by your username by registering on: http://www.geonames.org/login
 * After, you will need to enable the Free Web Services here: http://www.geonames.org/manageaccount
 */
$(document).ready(function() {
    autocompleteCityInit('ph7cms'); // Remplace "ph7cms" by your username!
});

function autocompleteCityInit(sGeonamesUsername)
{
    // Set "country" API parameter
    var sUrlSlug = '';
    $('#str_city').click(function() {
        sUrlSlug = '&country=' + $('#str_country').val();
    });

    $('#str_city').autocomplete(
    {
        source: function(oRequest, oResponse)
        {
            $.ajax(
            {
                url: 'http://ws.geonames.org/searchJSON?username=' + sGeonamesUsername + sUrlSlug,
                dataType: 'jsonp',
                data:
                {
                    featureClass: 'P',
                    style: 'full',
                    maxRows: 12,
                    name_startsWith: oRequest.term
                },
                success: function(oData)
                {
                    // Check if "geonames" exists. When the API returns an error message, it won't return "geonames"
                    if (!oData.geonames)
                    {
                        if (oData.status.message) {
                            console.error(oData.status.message); // Display the error message from the API into the browser's log
                        }
                    }
                    else
                    {
                        oResponse($.map(oData.geonames, function(oItem)
                        {
                            $('#str_city').mousemove(function()
                            {
                                $('#str_state').val((oItem.adminName1 ? oItem.adminName1 : ''));
                                $('#str_zip_code').val(oItem.postalcode);
                            });

                            return {
                                label: oItem.name + (oItem.adminName1 ? ', ' + oItem.adminName1 : '') + (sUrlSlug.trim() ? '' : ', ' + oItem.countryName),
                                value: oItem.name
                            }
                        }));
                    }
                }
            })
        }
    })
}<|endoftext|>