<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.stats = function(debug) {
  if (debug) debugger;

  var open_databases_tests = {
    'should increment the number of open databases when creating a db': function(name) {
       var db = new CouchDB("test_suite_db");
       db.deleteDb();
       var open_databases = requestStatsTest("couchdb", "open_databases").current;
       db.createDb();

       var new_open_databases = requestStatsTest("couchdb", "open_databases").current;
       TEquals(open_databases + 1, new_open_databases, name);
     },
    'should increment the number of open databases when opening a db': function(name) {
       var db = new CouchDB("test_suite_db");
       db.deleteDb();
       db.createDb();

       restartServer();

       var open_databases = requestStatsTest("couchdb", "open_databases").current;

       db.open("123");

       var new_open_databases = requestStatsTest("couchdb", "open_databases").current;
       TEquals(open_databases + 1, new_open_databases, name);
     },
       'should decrement the number of open databases when deleting': function(name) {
       var db = new CouchDB("test_suite_db");
       db.deleteDb();
       db.createDb();
       var open_databases = requestStatsTest("couchdb", "open_databases").current;

       db.deleteDb();
       var new_open_databases = requestStatsTest("couchdb", "open_databases").current;
       TEquals(open_databases - 1, new_open_databases, name);
     },
    'should keep the same number of open databases when reaching the max_dbs_open limit': function(name) {
      restartServer();
      var max = 5;
      run_on_modified_server(
        [{section: "couchdb",
          key: "max_dbs_open",
          value: max.toString()}],

        function () {
          var files_open = requestStatsTest("couchdb", "open_os_files").current;
          for(var i=0; i<max+1; i++) {
            var db = new CouchDB("test_suite_db" + i);
            db.deleteDb();
            db.createDb();
          }

          var open_databases = requestStatsTest("couchdb", "open_os_files").max;
          T(open_databases > 0 && max >= open_databases, name);

          for(var i=0; i<max+1; i++) {
            var db = new CouchDB("test_suite_db" + i);
            db.deleteDb();
          }
          T(files_open == requestStatsTest("couchdb", "open_os_files").current);
        })
    },
 };

  var request_count_tests = {
   'should increase the request count for every request': function(name) {
     var requests = requestStatsTest("httpd", "requests").current + 1;

     CouchDB.request("GET", "/");

     var new_requests = requestStatsTest("httpd", "requests").current;

     TEquals(requests + 1, new_requests, name);
   }
 };

 var database_read_count_tests = {
   'should increase database reads counter when a document is read': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();
     db.save({"_id":"test"});

     var reads = requestStatsTest("couchdb", "database_reads").current;
     db.open("test");
     var new_reads = requestStatsTest("couchdb", "database_reads").current;

     TEquals(reads + 1 , new_reads, name);
   },
   'should not increase database read counter when a non-document is read': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();
     db.save({"_id":"test"});

     var reads = requestStatsTest("couchdb", "database_reads").current;
     CouchDB.request("GET", "/");
     var new_reads = requestStatsTest("couchdb", "database_reads").current;

     TEquals(reads, new_reads, name);
   },
   'should increase database read counter when a document\'s revisions are read': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();
     db.save({"_id":"test"});

     var reads = requestStatsTest("couchdb", "database_reads").current;
     db.open("test", {"open_revs":"all"});
     var new_reads = requestStatsTest("couchdb", "database_reads").current;

     TEquals(reads + 1 , new_reads, name);
   }
 };

 var view_read_count_tests = {
   'should increase the permanent view read counter': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var reads = requestStatsTest("httpd", "view_reads").current;
     createAndRequestView(db);
     var new_reads = requestStatsTest("httpd", "view_reads").current;

     TEquals(reads + 1 , new_reads, name);
   },
   'should not increase the permanent view read counter when a document is read': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();
     db.save({"_id":"test"});

     var reads = requestStatsTest("httpd", "view_reads").current;
     db.open("test");
     var new_reads = requestStatsTest("httpd", "view_reads").current;

     TEquals(reads, new_reads, name);
   },
   'should not increase the permanent view read counter when a temporary view is read': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var reads = requestStatsTest("httpd", "view_reads").current;
     db.query(function(doc) { emit(doc._id)});
     var new_reads = requestStatsTest("httpd", "view_reads").current;

     TEquals(reads, new_reads, name);
   },
   'should increase the temporary view read counter': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var reads = requestStatsTest("httpd", "temporary_view_reads").current;
     db.query(function(doc) { emit(doc._id)});
     var new_reads = requestStatsTest("httpd", "temporary_view_reads").current;

     TEquals(reads + 1, new_reads, name);
   },
   'should increase the temporary view read counter when querying a permanent view': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var reads = requestStatsTest("httpd", "view_reads").current;
     createAndRequestView(db);
     var new_reads = requestStatsTest("httpd", "view_reads").current;

     TEquals(reads + 1 , new_reads, name);
   }
 };

 var http_requests_by_method_tests = {
   'should count GET requests': function(name) {
     var requests = requestStatsTest("httpd_request_methods", "GET").current;
     var new_requests = requestStatsTest("httpd_request_methods", "GET").current;

     TEquals(requests + 1, new_requests, name);
   },
   'should not count GET requests for POST request': function(name) {
     var requests = requestStatsTest("httpd_request_methods", "GET").current;
     CouchDB.request("POST", "/");
     var new_requests = requestStatsTest("httpd_request_methods", "GET").current;

     TEquals(requests + 1, new_requests, name);
   },
   'should count POST requests': function(name) {
     var requests = requestStatsTest("httpd_request_methods", "POST").current;
     CouchDB.request("POST", "/");
     var new_requests = requestStatsTest("httpd_request_methods", "POST").current;

     TEquals(requests + 1, new_requests, name);
   }
 };

 var document_write_count_tests = {
   'should increment database changes counter for document creates': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var creates = requestStatsTest("couchdb", "database_writes").current;
     db.save({"a":"1"});
     var new_creates = requestStatsTest("couchdb", "database_writes").current;

     TEquals(creates + 1, new_creates, name);
   },
   'should increment database changes counter for document updates': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var doc = {"_id":"test"};
     db.save(doc);

     var updates = requestStatsTest("couchdb", "database_writes").current;
     db.save(doc);
     var new_updates = requestStatsTest("couchdb", "database_writes").current;

     TEquals(updates + 1, new_updates, name);
   },
   'should increment database changes counter for document deletes': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var doc = {"_id":"test"};
     db.save(doc);

     var deletes = requestStatsTest("couchdb", "database_writes").current;
     db.deleteDoc(doc);
     var new_deletes = requestStatsTest("couchdb", "database_writes").current;

     TEquals(deletes + 1, new_deletes, name);
   },
   'should increment database changes counter for document copies': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var doc = {"_id":"test"};
     db.save(doc);

     var copies = requestStatsTest("couchdb", "database_writes").current;
     CouchDB.request("COPY", "/test_suite_db/test", {
       headers: {"Destination":"copy_of_test"}
     });
     var new_copies = requestStatsTest("couchdb", "database_writes").current;

     TEquals(copies + 1, new_copies, name);
   },
   'should increment database changes counter for document moves': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var doc = {"_id":"test"};
     db.save(doc);

     var moves = requestStatsTest("couchdb", "database_writes").current;
     CouchDB.request("MOVE", "/test_suite_db/test?rev=" + doc._rev, {
       headers: {"Destination":"move_of_test"}
     });
     var new_moves = requestStatsTest("couchdb", "database_writes").current;

     TEquals(moves + 1, new_moves, name);
   },
   'should increase the bulk doc counter': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var bulks = requestStatsTest("httpd", "bulk_requests").current;

     var docs = makeDocs(5);
     db.bulkSave(docs);

     var new_bulks = requestStatsTest("httpd", "bulk_requests").current;

     TEquals(bulks + 1, new_bulks, name);
   },
   'should increment database changes counter for document creates using POST': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var creates = requestStatsTest("couchdb", "database_writes").current;
     CouchDB.request("POST", "/test_suite_db", {body:'{"a":"1"}'});
     var new_creates = requestStatsTest("couchdb", "database_writes").current;

     TEquals(creates + 1, new_creates, name);
   },
   'should increment database changes counter when adding attachment': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var creates = requestStatsTest("couchdb", "database_writes").current;
     CouchDB.request("PUT", "/test_suite_db/bin_doc2/foo2.txt", {
           body:"This is no base64 encoded text",
           headers:{"Content-Type": "text/plain;charset=utf-8"}
     });
     var new_creates = requestStatsTest("couchdb", "database_writes").current;
     TEquals(creates + 1, new_creates, name);
   },
   'should increment database changes counter when adding attachment to existing doc': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var doc = {_id:"test"};
     db.save(doc);

     var updates = requestStatsTest("couchdb", "database_writes").current;
     CouchDB.request("PUT", "/test_suite_db/test/foo2.txt?rev=" + doc._rev, {
           body:"This is no base64 encoded text",
           headers:{"Content-Type": "text/plain;charset=utf-8"}
     });
     var new_updates = requestStatsTest("couchdb", "database_writes").current;
     TEquals(updates + 1, new_updates, name);
   }

 };
 var response_codes_tests = {
   'should increment the response code counter': function(name) {
     var db = new CouchDB("nonexistant_db");
     db.deleteDb();

     var not_founds = requestStatsTest("httpd_status_codes", "404").current;
     CouchDB.request("GET", "/nonexistant_db");
     var new_not_founds = requestStatsTest("httpd_status_codes", "404").current;

     TEquals(not_founds + 1, new_not_founds, name);
   },
   'should not increment respinse code counter for other response code': function(name) {
     var not_founds = requestStatsTest("http_status_codes", "404").current;
     CouchDB.request("GET", "/");
     var new_not_founds = requestStatsTest("http_status_codes", "404").current;

     TEquals(not_founds, new_not_founds, name);
   }
 };

 var aggregation_tests = {
   'should return the mean': function(name) {
     CouchDB.request("GET", "/");

     var mean = requestStatsTest("httpd", "requests").mean;

     T(mean >= 0, name);
   },
   'should return the maximum': function(name) {
     CouchDB.request("GET", "/");

     var maximum = requestStatsTest("httpd", "requests").max;

     T(maximum >= 0, name);
   },
   'should return the minimum': function(name) {
     CouchDB.request("GET", "/");

     var minimum = requestStatsTest("httpd", "requests", "min").min;

     T(minimum >= 0, name);
   },
   'should return the stddev': function(name) {
     CouchDB.request("GET", "/");

     var stddev = requestStatsTest("httpd", "stddev_requests").current;

     T(stddev >= 0, name);
   }
 };

 var summary_tests = {
   'should show a summary of all counters with aggregated values': function(name) {
     var options = {};
     options.headers = {"Accept": "application/json"};
     var summary = JSON.parse(CouchDB.request("GET", "/_stats", options).responseText);
     var aggregates = ["mean", "min", "max", "stddev",
       "current"];

     for(var i in aggregates) {
       T(summary.httpd.requests[aggregates[i]] >= 0, aggregates[i] + " >= 0", name);
     }
   }
 };

   var tests = [
     open_databases_tests,
     request_count_tests,
     database_read_count_tests,
     view_read_count_tests,
     http_requests_by_method_tests,
     document_write_count_tests,
     response_codes_tests,
     aggregation_tests,
     summary_tests
   ];

   for(var testGroup in tests) {
     for(var test in tests[testGroup]) {
       tests[testGroup][test](test);
     }
   };

   function createAndRequestView(db) {
     var designDoc = {
       _id:"_design/test", // turn off couch.js id escaping?
       language: "javascript",
       views: {
         all_docs_twice: {map: "function(doc) { emit(doc.integer, null); emit(doc.integer, null) }"},
       }
     };
     db.save(designDoc);

     db.view("test/all_docs_twice");
   }

   function requestStatsTest(module, key) {
     return CouchDB.requestStats(module, key, true);
   }
}
 <commit_msg>remove leftovers of MOVE form the stats tests<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.stats = function(debug) {
  if (debug) debugger;

  var open_databases_tests = {
    'should increment the number of open databases when creating a db': function(name) {
       var db = new CouchDB("test_suite_db");
       db.deleteDb();
       var open_databases = requestStatsTest("couchdb", "open_databases").current;
       db.createDb();

       var new_open_databases = requestStatsTest("couchdb", "open_databases").current;
       TEquals(open_databases + 1, new_open_databases, name);
     },
    'should increment the number of open databases when opening a db': function(name) {
       var db = new CouchDB("test_suite_db");
       db.deleteDb();
       db.createDb();

       restartServer();

       var open_databases = requestStatsTest("couchdb", "open_databases").current;

       db.open("123");

       var new_open_databases = requestStatsTest("couchdb", "open_databases").current;
       TEquals(open_databases + 1, new_open_databases, name);
     },
       'should decrement the number of open databases when deleting': function(name) {
       var db = new CouchDB("test_suite_db");
       db.deleteDb();
       db.createDb();
       var open_databases = requestStatsTest("couchdb", "open_databases").current;

       db.deleteDb();
       var new_open_databases = requestStatsTest("couchdb", "open_databases").current;
       TEquals(open_databases - 1, new_open_databases, name);
     },
    'should keep the same number of open databases when reaching the max_dbs_open limit': function(name) {
      restartServer();
      var max = 5;
      run_on_modified_server(
        [{section: "couchdb",
          key: "max_dbs_open",
          value: max.toString()}],

        function () {
          var files_open = requestStatsTest("couchdb", "open_os_files").current;
          for(var i=0; i<max+1; i++) {
            var db = new CouchDB("test_suite_db" + i);
            db.deleteDb();
            db.createDb();
          }

          var open_databases = requestStatsTest("couchdb", "open_os_files").max;
          T(open_databases > 0 && max >= open_databases, name);

          for(var i=0; i<max+1; i++) {
            var db = new CouchDB("test_suite_db" + i);
            db.deleteDb();
          }
          T(files_open == requestStatsTest("couchdb", "open_os_files").current);
        })
    },
 };

  var request_count_tests = {
   'should increase the request count for every request': function(name) {
     var requests = requestStatsTest("httpd", "requests").current + 1;

     CouchDB.request("GET", "/");

     var new_requests = requestStatsTest("httpd", "requests").current;

     TEquals(requests + 1, new_requests, name);
   }
 };

 var database_read_count_tests = {
   'should increase database reads counter when a document is read': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();
     db.save({"_id":"test"});

     var reads = requestStatsTest("couchdb", "database_reads").current;
     db.open("test");
     var new_reads = requestStatsTest("couchdb", "database_reads").current;

     TEquals(reads + 1 , new_reads, name);
   },
   'should not increase database read counter when a non-document is read': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();
     db.save({"_id":"test"});

     var reads = requestStatsTest("couchdb", "database_reads").current;
     CouchDB.request("GET", "/");
     var new_reads = requestStatsTest("couchdb", "database_reads").current;

     TEquals(reads, new_reads, name);
   },
   'should increase database read counter when a document\'s revisions are read': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();
     db.save({"_id":"test"});

     var reads = requestStatsTest("couchdb", "database_reads").current;
     db.open("test", {"open_revs":"all"});
     var new_reads = requestStatsTest("couchdb", "database_reads").current;

     TEquals(reads + 1 , new_reads, name);
   }
 };

 var view_read_count_tests = {
   'should increase the permanent view read counter': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var reads = requestStatsTest("httpd", "view_reads").current;
     createAndRequestView(db);
     var new_reads = requestStatsTest("httpd", "view_reads").current;

     TEquals(reads + 1 , new_reads, name);
   },
   'should not increase the permanent view read counter when a document is read': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();
     db.save({"_id":"test"});

     var reads = requestStatsTest("httpd", "view_reads").current;
     db.open("test");
     var new_reads = requestStatsTest("httpd", "view_reads").current;

     TEquals(reads, new_reads, name);
   },
   'should not increase the permanent view read counter when a temporary view is read': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var reads = requestStatsTest("httpd", "view_reads").current;
     db.query(function(doc) { emit(doc._id)});
     var new_reads = requestStatsTest("httpd", "view_reads").current;

     TEquals(reads, new_reads, name);
   },
   'should increase the temporary view read counter': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var reads = requestStatsTest("httpd", "temporary_view_reads").current;
     db.query(function(doc) { emit(doc._id)});
     var new_reads = requestStatsTest("httpd", "temporary_view_reads").current;

     TEquals(reads + 1, new_reads, name);
   },
   'should increase the temporary view read counter when querying a permanent view': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var reads = requestStatsTest("httpd", "view_reads").current;
     createAndRequestView(db);
     var new_reads = requestStatsTest("httpd", "view_reads").current;

     TEquals(reads + 1 , new_reads, name);
   }
 };

 var http_requests_by_method_tests = {
   'should count GET requests': function(name) {
     var requests = requestStatsTest("httpd_request_methods", "GET").current;
     var new_requests = requestStatsTest("httpd_request_methods", "GET").current;

     TEquals(requests + 1, new_requests, name);
   },
   'should not count GET requests for POST request': function(name) {
     var requests = requestStatsTest("httpd_request_methods", "GET").current;
     CouchDB.request("POST", "/");
     var new_requests = requestStatsTest("httpd_request_methods", "GET").current;

     TEquals(requests + 1, new_requests, name);
   },
   'should count POST requests': function(name) {
     var requests = requestStatsTest("httpd_request_methods", "POST").current;
     CouchDB.request("POST", "/");
     var new_requests = requestStatsTest("httpd_request_methods", "POST").current;

     TEquals(requests + 1, new_requests, name);
   }
 };

 var document_write_count_tests = {
   'should increment database changes counter for document creates': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var creates = requestStatsTest("couchdb", "database_writes").current;
     db.save({"a":"1"});
     var new_creates = requestStatsTest("couchdb", "database_writes").current;

     TEquals(creates + 1, new_creates, name);
   },
   'should increment database changes counter for document updates': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var doc = {"_id":"test"};
     db.save(doc);

     var updates = requestStatsTest("couchdb", "database_writes").current;
     db.save(doc);
     var new_updates = requestStatsTest("couchdb", "database_writes").current;

     TEquals(updates + 1, new_updates, name);
   },
   'should increment database changes counter for document deletes': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var doc = {"_id":"test"};
     db.save(doc);

     var deletes = requestStatsTest("couchdb", "database_writes").current;
     db.deleteDoc(doc);
     var new_deletes = requestStatsTest("couchdb", "database_writes").current;

     TEquals(deletes + 1, new_deletes, name);
   },
   'should increment database changes counter for document copies': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var doc = {"_id":"test"};
     db.save(doc);

     var copies = requestStatsTest("couchdb", "database_writes").current;
     CouchDB.request("COPY", "/test_suite_db/test", {
       headers: {"Destination":"copy_of_test"}
     });
     var new_copies = requestStatsTest("couchdb", "database_writes").current;

     TEquals(copies + 1, new_copies, name);
   },
   'should increase the bulk doc counter': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var bulks = requestStatsTest("httpd", "bulk_requests").current;

     var docs = makeDocs(5);
     db.bulkSave(docs);

     var new_bulks = requestStatsTest("httpd", "bulk_requests").current;

     TEquals(bulks + 1, new_bulks, name);
   },
   'should increment database changes counter for document creates using POST': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var creates = requestStatsTest("couchdb", "database_writes").current;
     CouchDB.request("POST", "/test_suite_db", {body:'{"a":"1"}'});
     var new_creates = requestStatsTest("couchdb", "database_writes").current;

     TEquals(creates + 1, new_creates, name);
   },
   'should increment database changes counter when adding attachment': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var creates = requestStatsTest("couchdb", "database_writes").current;
     CouchDB.request("PUT", "/test_suite_db/bin_doc2/foo2.txt", {
           body:"This is no base64 encoded text",
           headers:{"Content-Type": "text/plain;charset=utf-8"}
     });
     var new_creates = requestStatsTest("couchdb", "database_writes").current;
     TEquals(creates + 1, new_creates, name);
   },
   'should increment database changes counter when adding attachment to existing doc': function(name) {
     var db = new CouchDB("test_suite_db");
     db.deleteDb();
     db.createDb();

     var doc = {_id:"test"};
     db.save(doc);

     var updates = requestStatsTest("couchdb", "database_writes").current;
     CouchDB.request("PUT", "/test_suite_db/test/foo2.txt?rev=" + doc._rev, {
           body:"This is no base64 encoded text",
           headers:{"Content-Type": "text/plain;charset=utf-8"}
     });
     var new_updates = requestStatsTest("couchdb", "database_writes").current;
     TEquals(updates + 1, new_updates, name);
   }

 };
 var response_codes_tests = {
   'should increment the response code counter': function(name) {
     var db = new CouchDB("nonexistant_db");
     db.deleteDb();

     var not_founds = requestStatsTest("httpd_status_codes", "404").current;
     CouchDB.request("GET", "/nonexistant_db");
     var new_not_founds = requestStatsTest("httpd_status_codes", "404").current;

     TEquals(not_founds + 1, new_not_founds, name);
   },
   'should not increment respinse code counter for other response code': function(name) {
     var not_founds = requestStatsTest("http_status_codes", "404").current;
     CouchDB.request("GET", "/");
     var new_not_founds = requestStatsTest("http_status_codes", "404").current;

     TEquals(not_founds, new_not_founds, name);
   }
 };

 var aggregation_tests = {
   'should return the mean': function(name) {
     CouchDB.request("GET", "/");

     var mean = requestStatsTest("httpd", "requests").mean;

     T(mean >= 0, name);
   },
   'should return the maximum': function(name) {
     CouchDB.request("GET", "/");

     var maximum = requestStatsTest("httpd", "requests").max;

     T(maximum >= 0, name);
   },
   'should return the minimum': function(name) {
     CouchDB.request("GET", "/");

     var minimum = requestStatsTest("httpd", "requests", "min").min;

     T(minimum >= 0, name);
   },
   'should return the stddev': function(name) {
     CouchDB.request("GET", "/");

     var stddev = requestStatsTest("httpd", "stddev_requests").current;

     T(stddev >= 0, name);
   }
 };

 var summary_tests = {
   'should show a summary of all counters with aggregated values': function(name) {
     var options = {};
     options.headers = {"Accept": "application/json"};
     var summary = JSON.parse(CouchDB.request("GET", "/_stats", options).responseText);
     var aggregates = ["mean", "min", "max", "stddev",
       "current"];

     for(var i in aggregates) {
       T(summary.httpd.requests[aggregates[i]] >= 0, aggregates[i] + " >= 0", name);
     }
   }
 };

   var tests = [
     open_databases_tests,
     request_count_tests,
     database_read_count_tests,
     view_read_count_tests,
     http_requests_by_method_tests,
     document_write_count_tests,
     response_codes_tests,
     aggregation_tests,
     summary_tests
   ];

   for(var testGroup in tests) {
     for(var test in tests[testGroup]) {
       tests[testGroup][test](test);
     }
   };

   function createAndRequestView(db) {
     var designDoc = {
       _id:"_design/test", // turn off couch.js id escaping?
       language: "javascript",
       views: {
         all_docs_twice: {map: "function(doc) { emit(doc.integer, null); emit(doc.integer, null) }"},
       }
     };
     db.save(designDoc);

     db.view("test/all_docs_twice");
   }

   function requestStatsTest(module, key) {
     return CouchDB.requestStats(module, key, true);
   }
}
 <|endoftext|>


<commit_before>
var Completer = new Class ({
  Implements:[Options],
  Declare : 'Completer',

  index:-1,
  vals:[],
  opened:false,
  options:{
    min_chars:3,
    action: 'search',
    one_out:true     //is there's only one result, it's the one
  },
  old_value:'',
  save:false,
  timeout:false,

  initialize:function(el,options){
    this.setOptions(options);
    this.options.url = this.options.url || href_ks;
    this.input = el;
    this.input.addEvent('click', this.load.bind(this));
    if(this.options.save && this.options.onChange )
        this.options.save.addEvent('change', this.options.onChange);
  },

  load:function(){
    this.input.removeEvents('click');
    this.input.addEvent('keyup',this.keypress.bind(this) );
    this.input.addEvent('keydown',this.keydown.bind(this) );
    this.input.addEvent('blur',function(){this.close.delay(200,this)}.bind(this) );

    this.ul = $n('ul',{'class':'completer'});
    this.form= this.input.getParent('form');
    var dims = this.input.getCoordinates();
    this.ul.setStyles({left:dims.left,width:dims.width,top:dims.top+dims.height});
  },

  keydown:function(event){ //up & down options
    var code = event.code;
    if(code == 13 ){event.stop();
        this.set(this.index);
        event.stop();
        return false;
    }
    if(code == 40 ||code == 38){
        if( !this.opened ) return false;
        if(this.index ==-1) this.index = (code==38?0:-1);this.value=this.index;
        this.index = (this.index+(code-39)+this.vals.length)%this.vals.length;
        this.ul.getElements('.focused').removeClass('focused');
        this.vals[this.index].addClass('focused');
        return;
    }
  },

  keypress:function(event){ //chars
    var code = event.code;

    if((!this.input.value) || this.input.value==this.old_value) return;
    this.old_value=this.input.value;
    if(this.input.value.length < this.options.min_chars) {
        this.timeout = this.fire.delay(1000,this);
        return;
    };
    $clear(this.timeout);
    this.fire();
  },

  fire:function(){
    var data = {ks_action:this.options.action, q:this.input.value};
    Xhr.http_lnk('post', this.options.url, data, this.populate.bind(this));
  },

  populate:function(data){
    var val,li, results_list = data.results_list; if($type(results_list)!="object") return;
    this.ul.empty();
    this.vals = []; this.index = -1;
    $H(results_list).each(function(label, key) {
        this.vals.push( li = $n('li').set('html',results_list[key]).store('value', key) );
        li.addEvent('click',this.set.pass(this.vals.length-1,this));
        li.inject(this.ul);
    },this);
    this.ul.inject($(document.body));
    this.opened = true;
    if(this.vals.length == 1 && this.options.one_out) this.set(0);
  },

  set:function(key){
    var item = this.vals[key]; if(!item) return false;
    this.old_value = this.input.value = item.innerHTML;
    if(this.options.save) this.options.save.set('value', item.retrieve('value'));
    this.close();
    this.input.focus();this.input.highlight();
    this.options.save.fireEvent('change');
  },

  close:function(){
    this.ul.dispose();
    this.opened = false;
  }

});<commit_msg>Occlude<commit_after>
var Completer = new Class ({
  Implements:[Options],
  Occlude: 'Completer',

  index:-1,
  vals:[],
  opened:false,
  options:{
    min_chars:3,
    action: 'search',
    one_out:true     //is there's only one result, it's the one
  },
  old_value:'',
  save:false,
  timeout:false,

  initialize:function(el,options){
    this.setOptions(options);
    this.options.url = this.options.url || href_ks;
    this.input = el;
    this.input.addEvent('click', this.load.bind(this));
    if(this.options.save && this.options.onChange )
        this.options.save.addEvent('change', this.options.onChange);
  },

  load:function(){
    this.input.removeEvents('click');
    this.input.addEvent('keyup',this.keypress.bind(this) );
    this.input.addEvent('keydown',this.keydown.bind(this) );
    this.input.addEvent('blur',function(){this.close.delay(200,this)}.bind(this) );

    this.ul = $n('ul',{'class':'completer'});
    this.form= this.input.getParent('form');
    var dims = this.input.getCoordinates();
    this.ul.setStyles({left:dims.left,width:dims.width,top:dims.top+dims.height});
  },

  keydown:function(event){ //up & down options
    var code = event.code;
    if(code == 13 ){event.stop();
        this.set(this.index);
        event.stop();
        return false;
    }
    if(code == 40 ||code == 38){
        if( !this.opened ) return false;
        if(this.index ==-1) this.index = (code==38?0:-1);this.value=this.index;
        this.index = (this.index+(code-39)+this.vals.length)%this.vals.length;
        this.ul.getElements('.focused').removeClass('focused');
        this.vals[this.index].addClass('focused');
        return;
    }
  },

  keypress:function(event){ //chars
    var code = event.code;

    if((!this.input.value) || this.input.value==this.old_value) return;
    this.old_value=this.input.value;
    if(this.input.value.length < this.options.min_chars) {
        this.timeout = this.fire.delay(1000,this);
        return;
    };
    $clear(this.timeout);
    this.fire();
  },

  fire:function(){
    var data = {ks_action:this.options.action, q:this.input.value};
    Xhr.http_lnk('post', this.options.url, data, this.populate.bind(this));
  },

  populate:function(data){
    var val,li, results_list = data.results_list; if($type(results_list)!="object") return;
    this.ul.empty();
    this.vals = []; this.index = -1;
    $H(results_list).each(function(label, key) {
        this.vals.push( li = $n('li').set('html',results_list[key]).store('value', key) );
        li.addEvent('click',this.set.pass(this.vals.length-1,this));
        li.inject(this.ul);
    },this);
    this.ul.inject($(document.body));
    this.opened = true;
    if(this.vals.length == 1 && this.options.one_out) this.set(0);
  },

  set:function(key){
    var item = this.vals[key]; if(!item) return false;
    this.old_value = this.input.value = item.innerHTML;
    if(this.options.save) this.options.save.set('value', item.retrieve('value'));
    this.close();
    this.input.focus();this.input.highlight();
    this.options.save.fireEvent('change');
  },

  close:function(){
    this.ul.dispose();
    this.opened = false;
  }

});<|endoftext|>


<commit_before>const next = require('next');
const express = require('express');
const bodyParser = require('body-parser');
const bearerToken = require('express-bearer-token');
const api = require('./routes/api');

const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const nextServer = next({ dev });
const handle = nextServer.getRequestHandler();
const server = express();

const main = async () => {
  await nextServer.prepare();
  server.use(bodyParser.json());
  server.use(bearerToken({ bodyKey: 'token', queryKey: 'token' }));
  server.use('/api/v1', api);

  server.get('*', (req, res) => handle(req, res));

  server.listen(port, (err) => {
    if (err) { throw err; }
    console.log(`> Ready on http://localhost:${port}`);
  });
};

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
<commit_msg>add parser of POST body<commit_after>const next = require('next');
const express = require('express');
const bodyParser = require('body-parser');
const bearerToken = require('express-bearer-token');
const api = require('./routes/api');

const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const nextServer = next({ dev });
const handle = nextServer.getRequestHandler();
const server = express();

const main = async () => {
  await nextServer.prepare();
  server.use(bodyParser.urlencoded({ extended: false }));
  server.use(bodyParser.json());
  server.use(bearerToken({ bodyKey: 'token', queryKey: 'token' }));
  server.use('/api/v1', api);

  server.get('*', (req, res) => handle(req, res));

  server.listen(port, (err) => {
    if (err) { throw err; }
    console.log(`> Ready on http://localhost:${port}`);
  });
};

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
<|endoftext|>


<commit_before>
var koratDragonDen = koratDragonDen || {};
koratDragonDen.debtCalculatorSample = koratDragonDen.debtCalculatorSample || {};

koratDragonDen.debtCalculatorSample.model = (function model(){
  'use strict';

  var allDebts = {};
  var allocationMethod = 0;
  var prioritizationMethod = 0;
  var monthlyPayments = 0.0;
  var subscribers = [];

  var Debt = function Debt(uid) {
    this.uid = uid;
  };
  Debt.prototype.apr = 0.0;
  Debt.prototype.amountOwed = 0.0;
  Debt.prototype.minimumMonthlyPayment = 0.0;

  var publishDebtUpdates = function publishDebtUpdates(uid, updateType) {

    var debtObject;

    if (updateType === 'delete') {
      debtObject = undefined;
    } else {
      debtObject = allDebts[uid];
    }

    var data = {
      'debtObject' : debtObject,
      'type' : updateType
    };

    for (var i = 0; i < subscribers.length; i++) {
      subscribers[i](data);
    }
  };

  var getDebtsSortedByHighestApr = function getDebtsSortedByHighestApr() {

    var orderedDebts = [];

    for (var debt in allDebts) {
      if (allDebts.hasOwnProperty(debt)) {
        orderedDebts.push({
          debtObject : allDebts[debt],
          remainingOwed : allDebts[debt].amountOwed
        });
      }
    }

    orderedDebts.sort(function(a, b) {
      return a.debtObject.apr - b.debtObject.apr;
    });

    return orderedDebts;
  };

  var getDebtsSortedByLowestOwed = function getDebtsSortedByLowestOwed() {
    // TODO

    var unorderedDebts = [];
    var orderedDebts = [];

    for (var debt in allDebts) {
      if (allDebts.hasOwnProperty(debt)) {
        unorderedDebts.push(allDebts[debt].uid);
      }
    }

    var lowestOwedDebt;
    while (unorderedDebts.length > 0) {

      lowestOwedDebt = 0;

      for (var i = 1, l = unorderedDebts.length; i < l; i++) {
        if (allDebts[unorderedDebts[i]].amountOwed < allDebts[unorderedDebts[lowestOwedDebt]].amountOwed) {
          lowestOwedDebt = i;
        }
      }

      orderedDebts.push({
        debtObject : allDebts[unorderedDebts[lowestOwedDebt]],
        remainingOwed : allDebts[unorderedDebts[lowestOwedDebt]].amountOwed
      });

      unorderedDebts.splice(lowestOwedDebt, 1);
    }

    return orderedDebts;
  };

  var getMonthlyMinimumForPayoffTime = function getMonthlyMinimumForPayoffTime(orderedDebtsObject) {

    var currentMonthlyMinimum = 0.0;
    for (var i = 0; i < orderedDebtsObject.length; i++) {
      currentMonthlyMinimum += orderedDebtsObject[i].debtObject.minimumMonthlyPayment;
    }

    return currentMonthlyMinimum;
  };

  // TODO - This whole thing is a brainstormy mess. Fix it.
  var calculatePayoffTime = function calculatePayoffTime() {

    var debt, i;
    var orderedDebts = [];

    // TODO - Change these to enums
    switch (allocationMethod) {

      case 'highestApr':
        orderedDebts = getDebtsSortedByHighestApr();
        break;

      case 'lowestOwed':
        orderedDebts = getDebtsSortedByLowestOwed();
        break;

      case 'custom':
        // TODO - If custom priority, use customPriority
        break;

      default:
        // TODO - How do we want to handle this?
    }

    var months = 0;
    // TODO - Add stop for amounts that are just absurdly long
    while (orderedDebts.length > 0) {
      // Calculate interest first, then remove amount

      months++;

      var orderedDebtsLength = orderedDebts.length;

      // Calculate interest
      for (i = 0; i < orderedDebtsLength; i++) {
        // TODO - Cache monthly interest rate
        orderedDebts[i].remainingOwed *= ( 1.0 + (orderedDebts[i].debtObject.apr / 1200.0) );
      }

      // Determine amount over monthly minimum, if any
      var currentMonthlyMinimum = getMonthlyMinimumForPayoffTime(orderedDebts);
      var amountOverMonthlyMinimum = Math.max(monthlyPayments - currentMonthlyMinimum, 0.0);

      // TODO - Change these to enums
      switch (prioritizationMethod) {

        case 'evenSplit':
          // TODO - Factor in when this is reset mid-calculation because of a debt(s) being paid off
          var evenSplitExtra = amountOverMonthlyMinimum / orderedDebtsLength;

          for (i = 0; i < orderedDebtsLength; i++) {
            // TODO - Check if this subtracts more than owed
            orderedDebts[i].remainingOwed -= (evenSplitExtra + orderedDebts[i].debtObject.minimumMonthlyPayment);
          }
          break;

        case 'priorityFirst':
          var remainingAmountOverMonthlyMinimum = amountOverMonthlyMinimum;
          for (i = 0; i < orderedDebtsLength; i++) {
            // TODO - Check if this subtracts more than owed
            orderedDebts[i].remainingOwed -= (remainingAmountOverMonthlyMinimum + orderedDebts[i].debtObject.minimumMonthlyPayment);
            remainingAmountOverMonthlyMinimum -= remainingAmountOverMonthlyMinimum;
          }
          break;

        case 'proportionalSplit':
          // If proportional split
          var totalAmountRemaining = 0.0;
          // TODO - This is an array
          for (i = 0; i < orderedDebtsLength; i++) {
            totalAmountRemaining += orderedDebts[i].remainingOwed;
          }

          evenSplitExtra = amountOverMonthlyMinimum / orderedDebtsLength;
          // TODO - Factor in when this is reset mid-calculation because of a debt(s) being paid off

          for (i = 0; i < orderedDebtsLength; i++) {
            // TODO - Check if this subtracts more than owed
            orderedDebts[i].remainingOwed -= ((amountOverMonthlyMinimum * (orderedDebts[i].remainingOwed/totalAmountRemaining)) + orderedDebts[i].debtObject.minimumMonthlyPayment);
          }
          break;

        default:
          // TODO - How do we want to handle this?
      }
    }
  };

  function getNewUid() {

    return Math.random().toString(36).substr(2,9);
  }

  return {
    'subscribeToDebtUpdates' : function subscribeToDebtUpdates(callback) {

      // Sanity check. Don't let the same callback subscribe twice.
      for (var i = 0; i < subscribers.length; i++) {
        if (subscribers[i] === callback) {
          return;
        }
      }

      subscribers.push(callback);
    },

    'unsubscribeFromDebtUpdates' :
        function unsubscribeFromDebtUpdates(callback) {

      for (var i = 0; i < subscribers.length; i++) {
        if (subscribers[i] === callback) {
          subscribers.pop(i);
          return;
        }
      }
    },

    'newDebt' : function newDebt(debtData) {

      var uid = getNewUid();
      var debt = new Debt(uid);

      if (debtData !== undefined) {
        if (debtData.apr !== undefined){
          debt.apr = debtData.apr;
        }
        if (debtData.amountOwed !== undefined){
          debt.amountOwed = debtData.amountOwed;
        }
        if (debtData.minimumMonthlyPayment !== undefined){
          debt.minimumMonthlyPayment = debtData.minimumMonthlyPayment;
        }
      }

      allDebts[uid] = new Debt(uid);

      publishDebtUpdates(uid, 'add');
    },

    'updateDebtInfo' : function updateDebtInfo(uid, property, amount) {

      if (allDebts[uid]) {
        allDebts[uid][property] = amount;
      }

      publishDebtUpdates(uid, 'update');
    },

    'deleteDebt' : function deleteDebt(uid, test) {

      if (allDebts[uid]) {
        delete allDebts[uid];
      }

      publishDebtUpdates(uid, 'delete');
    },

    'getTotalAmountOwed' : function getTotalAmountOwed() {

      var totalAmountOwed = 0.0;

      for (var debt in allDebts) {
        if (allDebts.hasOwnProperty(debt)) {
          totalAmountOwed += allDebts[debt].amountOwed;
        }
      }

      return totalAmountOwed;
    },

    'getTotalMinimumMonthlyPayment' : function getTotalMinimumMonthlyPayment() {

      var totalMinimumMonthlyPayment = 0.0;

      for (var debt in allDebts) {
        if (allDebts.hasOwnProperty(debt)) {
          totalMinimumMonthlyPayment += allDebts[debt].minimumMonthlyPayment;
        }
      }

      return totalMinimumMonthlyPayment;
    }
  };

}());

<commit_msg>Still updating model.js. Still not runable.<commit_after>
var koratDragonDen = koratDragonDen || {};
koratDragonDen.debtCalculatorSample = koratDragonDen.debtCalculatorSample || {};

// TODO - Find places where calculations would demand we cap at two decimals
koratDragonDen.debtCalculatorSample.model = (function model(){
  'use strict';

  var allDebts = {};
  var allocationMethod = 0;
  var prioritizationMethod = 0;
  var monthlyPayments = 0.0;
  var subscribers = [];
  var payoffTime = undefined;

  var Debt = function Debt(uid) {
    this.uid = uid;
  };
  Debt.prototype.apr = 0.0;
  Debt.prototype.monthlyInterest = 0.0;
  Debt.prototype.amountOwed = 0.0;
  Debt.prototype.minimumMonthlyPayment = 0.0;

  // TODO - Rework this
  var publishDebtUpdates = function publishDebtUpdates(uid, updateType) {

    var debtObject;

    if (updateType === 'delete') {
      debtObject = undefined;
    } else {
      debtObject = allDebts[uid];
    }

    var data = {
      'debtObject' : debtObject,
      'type' : updateType
    };

    for (var i = 0; i < subscribers.length; i++) {
      subscribers[i](data);
    }
  };

  // TODO - This and the function below might have combinable code
  var getDebtsSortedByHighestApr = function getDebtsSortedByHighestApr() {

    var orderedDebts = [];

    for (var debt in allDebts) {
      if (allDebts.hasOwnProperty(debt)) {
        orderedDebts.push({
          debtObject : allDebts[debt],
          remainingOwed : allDebts[debt].amountOwed
        });
      }
    }

    orderedDebts.sort(function(a, b) {
      // b - a results in highest first sorting
      return b.debtObject.apr - a.debtObject.apr;
    });

    return orderedDebts;
  };

  var getDebtsSortedByLowestOwed = function getDebtsSortedByLowestOwed() {

    var orderedDebts = [];

    for (var debt in allDebts) {
      if (allDebts.hasOwnProperty(debt)) {
        orderedDebts.push({
          debtObject : allDebts[debt],
          remainingOwed : allDebts[debt].amountOwed
        });
      }
    }

    orderedDebts.sort(function(a, b) {
      // a - b results in lowest first sorting
      return a.debtObject.amountOwed - b.debtObject.amountOwed;
    });

    return orderedDebts;
  };

  // TODO - Rework this? Move it?
  var getMonthlyMinimumForPayoffTime = function getMonthlyMinimumForPayoffTime(orderedDebtsObject) {

    var currentMonthlyMinimum = 0.0;
    for (var i = 0; i < orderedDebtsObject.length; i++) {
      currentMonthlyMinimum += orderedDebtsObject[i].debtObject.minimumMonthlyPayment;
    }

    return currentMonthlyMinimum;
  };

  var calculatePayoffTime = function calculatePayoffTime() {

    var i, orderedDebts, debt, payment, extra, remaining;

    // TODO - Change these to enums
    switch (allocationMethod) {

      case 'highestApr':
        orderedDebts = getDebtsSortedByHighestApr();
        break;

      case 'lowestOwed':
        orderedDebts = getDebtsSortedByLowestOwed();
        break;

      case 'custom':
        // TODO - If custom priority, use customPriority
        break;

      default:
        // TODO - How do we want to handle this?
    }

    var months = 0;
    // TODO - Add stop for amounts that are just absurdly long
    while (orderedDebts.length > 0) {
      // Track how many months of paying this will take
      months++;

      // Calculate interest
      // TODO - Cap this at two decimals
      for (i = 0; i < orderedDebts.length; i++) {
        debt = orderedDebts[i];
        debt.remainingOwed *= debt.monthlyInterest;
      }

      // Determine amount over monthly minimum, if any
      extra = Math.max(monthlyPayments - getMonthlyMinimumForPayoffTime(orderedDebts), 0.0);

      // Handle minimum monthly payments first
      // Looping backwards makes array object deletion logic cleaner
      for (i = orderedDebts.length; i--; ) {
        debt = orderedDebts[i];

        payment = debt.debtObject.minimumMonthlyPayment;
        remaining = debt.remainingOwed;

        if (remaining < payment) {
          extra += (payment - remaining);
          delete orderedDebts[i];
        } else {
          debt.remainingOwed -= payment;
        }
      }

      // TODO - Change these to enums
      switch (prioritizationMethod) {

        case 'evenSplit':

          while (extra > 0.0 && orderedDebts.length) {
            payment = extra / orderedDebts.length;
            extra = 0.0;
            // Looping backwards makes array object deletion logic cleaner
            for (i = orderedDebts.length; i--; ) {
              debt = orderedDebts[i];
              remaining = debt.remainingOwed;

              if (remaining < payment) {
                extra += (payment - remaining);
                delete orderedDebts[i];
              } else {
                debt.remainingOwed -= payment;
              }
            }
          }
          break;

        case 'priorityFirst':

          while (extra > 0.0 && orderedDebts.length) {
            debt = orderedDebts[i];
            remaining = debt.remainingOwed;

            if (remaining < extra) {
              extra -= remaining;
              delete orderedDebts[i];
            } else {
              debt.remainingOwed -= extra;
              extra = 0.0;
            }
          }
          break;

        case 'proportionalSplit':

          while (extra > 0.0 && orderedDebts.length) {

            var fundsAvailableTotal = extra;
            var fundsAvailableRemaining = extra;

            var totalAmountRemaining = 0.0;
            for (i = 0; i < orderedDebts.length; i++) {
              totalAmountRemaining += orderedDebts[i].remainingOwed;
            }

            extra = 0.0;
            // Looping backwards makes array object deletion logic cleaner
            for (i = orderedDebts.length; i--; ) {
              debt = orderedDebts[i];
              remaining = debt.remainingOwed;

              payment = fundsAvailableTotal * (remaining/totalAmountRemaining);
              if (payment > fundsAvailableRemaining) {
                payment = fundsAvailableRemaining;
                fundsAvailableRemaining = 0.0;
              } else {
                fundsAvailableRemaining -= payment;
              }

              if (remaining < payment) {
                extra += (payment - remaining);
                delete orderedDebts[i];
              } else {
                debt.remainingOwed -= payment;
              }
            }
          }
          break;

        default:
          // TODO - How do we want to handle this?
      }
    }
    // TODO - return and/or set something here
  };

  function getNewUid() {

    return Math.random().toString(36).substr(2,9);
  }

  return {
    'subscribeToDataUpdates' : function subscribeToDataUpdates(callback) {

      // Sanity check. Don't let the same callback subscribe twice.
      for (var i = 0; i < subscribers.length; i++) {
        if (subscribers[i] === callback) {
          return;
        }
      }

      subscribers.push(callback);
    },

    'unsubscribeFromDataUpdates' :
        function unsubscribeFromDataUpdates(callback) {

      for (var i = 0; i < subscribers.length; i++) {
        if (subscribers[i] === callback) {
          subscribers.pop(i);
          return;
        }
      }
    },

    'newDebt' : function newDebt(debtData) {

      var uid = getNewUid();
      var debt = new Debt(uid);

      // TODO - Clean this up?
      if (debtData !== undefined) {
        if (debtData.apr !== undefined){
          debt.apr = debtData.apr;
        }
        if (debtData.amountOwed !== undefined){
          debt.amountOwed = debtData.amountOwed;
        }
        if (debtData.minimumMonthlyPayment !== undefined){
          debt.minimumMonthlyPayment = debtData.minimumMonthlyPayment;
        }
      }

      allDebts[uid] = new Debt(uid);

      publishDebtUpdates(uid, 'add');
    },

    'setDebtInfo' : function setDebtInfo(uid, property, amount) {

      if (allDebts[uid]) {
        allDebts[uid][property] = amount;

        // Cache estimated monthly interest rate based on apr
        if (property === 'apr') {
          allDebts[uid].monthlyInterest = ( 1.0 + (amount / 1200.0) );
        }
      }

      publishDebtUpdates(uid, 'update');
    },

    'getDebtInfo' : function getDebtInfo(uid, property) {
      if (allDebts[uid]) {
        return allDebts[uid][property];
      }
    },

    'deleteDebt' : function deleteDebt(uid, test) {

      if (allDebts[uid]) {
        delete allDebts[uid];
      }

      publishDebtUpdates(uid, 'delete');
    },

    'getAllDebtInfo' : function getAllDebtInfo() {
      return allDebts;
    },

    // TODO - Cache? Rework?
    'getTotalAmountOwed' : function getTotalAmountOwed() {

      var totalAmountOwed = 0.0;

      for (var debt in allDebts) {
        if (allDebts.hasOwnProperty(debt)) {
          totalAmountOwed += allDebts[debt].amountOwed;
        }
      }

      return totalAmountOwed;
    },

    // TODO - Cache? Rework?
    'getTotalMinimumMonthlyPayment' : function getTotalMinimumMonthlyPayment() {

      var totalMinimumMonthlyPayment = 0.0;

      for (var debt in allDebts) {
        if (allDebts.hasOwnProperty(debt)) {
          totalMinimumMonthlyPayment += allDebts[debt].minimumMonthlyPayment;
        }
      }

      return totalMinimumMonthlyPayment;
    }
  };

}());

<|endoftext|>


<commit_before>
/*

  index.js

*/

module.exports = function() {

  var server = require("./server");

  // Start the server
  server();

  // Start browser sync and proxy
  global.server.init({
    proxy: "localhost:27182"
  });

}<commit_msg>server: linting<commit_after>
/*

  index.js

*/

module.exports = function() {

  var server = require("./server");

  // Start the server
  server();

  // Start browser sync and proxy
  global.server.init({ proxy : "localhost:27182" });

};
<|endoftext|>


<commit_before>import {dict} from '#core/types/object';

import {isExperimentOn} from '#experiments';

import {userAssert} from '#utils/log';

import {BaseElement} from './base-element';

/** @const {string} */
const TAG = 'amp-wordpress-embed';

class AmpWordPressEmbed extends BaseElement {
  /** @override */
  isLayoutSupported(layout) {
    userAssert(
      isExperimentOn(this.win, 'bento') ||
        isExperimentOn(this.win, 'bento-wordpress-embed'),
      'expected global "bento" or specific "bento-wordpress-embed" experiment to be enabled'
    );
    return super.isLayoutSupported(layout);
  }

  /** @override */
  init() {
    return dict({
      'requestResize': (height) =>
        this.attemptChangeHeight(height).catch(() => {
          /* ignore failures */
        }),
    });
  }
}

AMP.extension(TAG, '1.0', (AMP) => {
  AMP.registerElement(TAG, AmpWordPressEmbed);
});
<commit_msg>Remove Bento experiments from `amp-wordpress-embed` (#37237)<commit_after>import {dict} from '#core/types/object';

import {BaseElement} from './base-element';

/** @const {string} */
const TAG = 'amp-wordpress-embed';

class AmpWordPressEmbed extends BaseElement {
  /** @override */
  isLayoutSupported(layout) {
    return super.isLayoutSupported(layout);
  }

  /** @override */
  init() {
    return dict({
      'requestResize': (height) =>
        this.attemptChangeHeight(height).catch(() => {
          /* ignore failures */
        }),
    });
  }
}

AMP.extension(TAG, '1.0', (AMP) => {
  AMP.registerElement(TAG, AmpWordPressEmbed);
});
<|endoftext|>


<commit_before>var sp = require('serialport')
  , es = require('event-stream')
  , Stream = require('stream')
  , http = require('http')
  , shoe = require('shoe')
  , connect = require('connect')

var serials = (process.env.SERIAL || '/dev/tty.usbmodemfa131,/dev/tty.usbmodemfd121').split(',')
  , port = process.env.PORT || 8080
  , app = connect()
  , server
  , arduinos

arduinos = serials.map(function(serial) {
  return new sp.SerialPort(serial, {})
})

console.log('Serial ports:', serials)
console.log('Server port:', port)

app
 .use(connect.logger('dev'))
 .use(connect.static(__dirname + '/../public'))
 .use(connect.directory(__dirname + '/../public'))

server = http.createServer(app)
server.listen(port)

shoe(function clientStream(stream) {
  var through = es.through(function(data) {
    this.emit('data', data + '\n')
  })

  arduinos.forEach(function(arduino) {
    var split = es.split('\n')

    function listener(data) {
      split.write(data)
    };

    split.pipe(through)

    arduino.on('data', listener)

    stream.on('end', function() {
      arduino.removeListener('data', listener)
      through.end()
    })
  })

  through.pipe(stream)
}).install(server, '/flora')

/**
 * If unable to connect to an Arduino,
 * serve up some dummy data.
 *
 * (disabled for now)
 */
// arduino.once('error', function(err) {
//   if (!/Cannot open/gi.test(err.message)) throw err

//   var time = 0

//   console.log('')
//   console.log('WARNING:', err.message)
//   console.log('Difficulties connecting to Arudino\'s serial port...')
//   console.log('')
//   console.log('Ensure you have the correct serial port set, and in')
//   console.log('the meantime here\'s some dummy data.')
//   console.log('')

//   arduino = new Stream

//   setInterval(function() {
//     var data = 'd1'

//     data += ' '
//     data += Math.floor(512 * (Math.sin(time) + 1))
//     data += '\n'

//     data += 'd2 '
//     data += Math.floor(512 * (Math.sin(time*1.714 + 0.05) + 1))
//     data += '\n'

//     arduino.emit('data', data)
//     time += 0.0221
//   }, 50)

//   watchData(arduino)
// })<commit_msg>add raspi serial ports<commit_after>var sp = require('serialport')
  , es = require('event-stream')
  , Stream = require('stream')
  , http = require('http')
  , shoe = require('shoe')
  , connect = require('connect')

var serials = (process.env.SERIAL || '/dev/tty.usbmodemfa131,/dev/tty.usbmodemfd121,/dev/ttyAMC0,/dev/ttyAMC1').split(',')
  , port = process.env.PORT || 8080
  , app = connect()
  , server
  , arduinos

arduinos = serials.map(function(serial) {
  return new sp.SerialPort(serial, {})
})

console.log('Serial ports:', serials)
console.log('Server port:', port)

app
 .use(connect.logger('dev'))
 .use(connect.static(__dirname + '/../public'))
 .use(connect.directory(__dirname + '/../public'))

server = http.createServer(app)
server.listen(port)

shoe(function clientStream(stream) {
  var through = es.through(function(data) {
    this.emit('data', data + '\n')
  })

  arduinos.forEach(function(arduino) {
    var split = es.split('\n')

    function listener(data) {
      split.write(data)
    };

    split.pipe(through)

    arduino.on('data', listener)

    stream.on('end', function() {
      arduino.removeListener('data', listener)
      through.end()
    })
  })

  through.pipe(stream)
}).install(server, '/flora')

/**
 * If unable to connect to an Arduino,
 * serve up some dummy data.
 *
 * (disabled for now)
 */
// arduino.once('error', function(err) {
//   if (!/Cannot open/gi.test(err.message)) throw err

//   var time = 0

//   console.log('')
//   console.log('WARNING:', err.message)
//   console.log('Difficulties connecting to Arudino\'s serial port...')
//   console.log('')
//   console.log('Ensure you have the correct serial port set, and in')
//   console.log('the meantime here\'s some dummy data.')
//   console.log('')

//   arduino = new Stream

//   setInterval(function() {
//     var data = 'd1'

//     data += ' '
//     data += Math.floor(512 * (Math.sin(time) + 1))
//     data += '\n'

//     data += 'd2 '
//     data += Math.floor(512 * (Math.sin(time*1.714 + 0.05) + 1))
//     data += '\n'

//     arduino.emit('data', data)
//     time += 0.0221
//   }, 50)

//   watchData(arduino)
// })<|endoftext|>


<commit_before>/**
 * CareWheels - Group Status Controller
 *
 */
angular.module('careWheels').controller('groupStatusController',
  function ($scope, $interval, $state, $ionicPopup, GroupInfo, User, PaymentService) {

    var groupArray = GroupInfo.groupInfo();

    // the groupInfo object is not available immediately, spin until available
    var initGroupInfo = setInterval(function () {
      var groupArray = GroupInfo.groupInfo();
      //console.log(groupArray);
      if (groupArray[0] != null) {
        clearInterval(initGroupInfo);
        // app on load
        console.log('hit group controller');
        getLoggedInUser(groupArray);
        setGroupArray(groupArray);
      }
    }, 50);

    /** automatically go through each user square, and
     *  find each 'red' alert, and fade that element in
     *  and out. (flashing effect)
     * */
    $interval(function () {
      /* jQuery element to fade in and out */
      var alertArray = [
        $('#topLeftAlert'),
        $('#topRightAlert'),
        $('#bottomLeftAlert'),
        $('#bottomRightAlert')
      ];
      for (var i = 0; i < alertArray.length; i++) {
        if (alertArray[i].css('background-color') === 'rgb(255, 0, 0)') {
          alertArray[i].fadeOut("slow");
          alertArray[i].fadeIn("slow");
        }
      }
    }, 2000);

    $scope.group = [
      { // center, self
        name: '',
        username: '',
        balance: '0.0',
        image: '',
        userSelected: '',
        displayedError: GroupInfo.getSensorError(),
        selfUserIndex: -1

      },
      { // top left @ index 1
        name: '',
        username: '',
        status: '',
        image: '',
        alertLevelColor: '',
        error: false
      },
      { // top right @ index 2
        name: '',
        username: '',
        status: '',
        image: '',
        alertLevelColor: '',
        error: false
      },
      { // bottom left @ index 3
        name: '',
        username: '',
        status: '',
        image: '',
        alertLevelColor: '',
        error: false
      },
      { // bottom right @ index 4
        name: '',
        username: '',
        status: '',
        image: '',
        alertLevelColor: '',
        error: false
      }
    ];

    /* click/press events */
    $scope.clickTopLeft = function () {
      clickUser(1);
    };
    $scope.clickTopRight = function () {
      clickUser(2);
    };
    $scope.clickBottomLeft = function () {
      clickUser(3);
    };
    $scope.clickBottomRight = function () {
      clickUser(4);
    };
    $scope.clickCenter = function () {
    };
    $scope.clickCareBank = function () {
    };

    // console.log("Calling memberSummary Payment:");
    // PaymentService.memberSummary(1.0);

    // lets figure out which user logged in at this point
    function getLoggedInUser(groupInfo) {
      console.log('group controller: getloggedinuser()');
      var user = User.credentials();
      // error unable to load user object;
      if (user == null){
        console.log('group controller: user not found');
        $scope.group[0].selfUserIndex = -1;
      }

      // loop through the groupInfo array to find the user who
      // logged in.
      for (var i = 0; i < groupInfo.length; i++) {
        console.log('logged in as:', user.username, '  and comparing with:', groupInfo[i].username);

        if (user.username == groupInfo[i].username){
          $scope.group[0].selfUserIndex = i; // gotcha!
          console.log('group controller: user found @ index', i);
        }

      }

    }

    // now lets set the scope variables for the group view.
    function setGroupArray(groupArray) {
      var currentUser = 0;
      var fridgeAlert, medsAlert;

      var loggedInUserIndex = $scope.group[0].selfUserIndex;
      console.log('setGroupArray, logged in user at index', loggedInUserIndex);

      // next lets set the data for the user that logged in,
      // this is reserved at index zero.
      $scope.group[currentUser].image = groupArray[loggedInUserIndex].photoUrl;
      $scope.group[currentUser].username = groupArray[loggedInUserIndex].username;
      $scope.group[currentUser].name = groupArray[loggedInUserIndex].name;
      $scope.group[currentUser].balance = trimZeros(groupArray[loggedInUserIndex].balance);

      // put everyone else into the array
      for (var i = 0; i < 5; i++){
        currentUser++;
        if(i != $scope.group[0].selfUserIndex){
          $scope.group[currentUser].image = groupArray[i].photoUrl;
          $scope.group[currentUser].username = groupArray[i].username;
          $scope.group[currentUser].name = groupArray[i].name;

          try{
            fridgeAlert = groupArray[i].analysisData.fridgeAlertLevel;
            medsAlert = groupArray[i].analysisData.medsAlertLevel;
            $scope.group[currentUser].status = $scope.getAlertColor(fridgeAlert, medsAlert, i);
          }
          catch (Exception) {
            $scope.group[currentUser].status = 'grey';
            $scope.group[currentUser].error = true;
          }

        }
        // on the last element of the loop, now check health
        if (i == 4) {
          console.log('on last element');
          if(!GroupInfo.getSensorError())
            $scope.checkGroupHealth();
        }
      }

        //var userCount = 0;
      //// first lets set the group up, at index 1-4
      //for (var i = 0; i < 5; i++) {
      //  userCount++;
      //  if (i != $scope.group[0].selfUserIndex) {
      //    $scope.group[userCount].image = groupArray[i].photoUrl;
      //    $scope.group[userCount].username = groupArray[i].username;
      //    $scope.group[userCount].name = groupArray[i].name;
      //
      //    try {
      //      var fridgeAlert = groupArray[userCount].analysisData.fridgeAlertLevel;
      //      var medsAlert = groupArray[userCount].analysisData.medsAlertLevel;
      //      $scope.group[userCount].status = $scope.getAlertColor(fridgeAlert, medsAlert, i);
      //    }

      //  }
      //
      //}

    }

    //removes insignificant zeros
    function trimZeros(input) {
      var number = parseFloat(input);
      return number.toString();

    }

    function clickUser(index) {
      if (!$scope.group[index].error) {
        PaymentService.sensorDataView(0.1, $scope.group[index].alertLevelColor);
        $scope.group[0].userSelected = $scope.group[index].name;
        GroupInfo.setMember_new($scope.group[index].username);
        $state.go('app.individualStatus');
      }
    }

    // An error popup dialog
    function displayError(errorString) {
      var alertPopup = $ionicPopup.alert({
        title: '
Unable to load sensor data for:
',
        template: '
' + errorString + '
',
        buttons: [{ // Array[Object] (optional). Buttons to place in the popup footer.
          text: 'Okay',
          type: 'button-calm'
        }]
      });
      alertPopup.then(function (res) {

      });
    }

    /**
     * returns a string of of the color code depending on the
     * alert level. This string is used with ng-class, to
     * append the color class onto the div
     * */
    $scope.getAlertColor = function (fridgeAlert, medsAlert, index) {
      console.log('hit getAlertColor:', fridgeAlert, medsAlert, index);

      // check for null params
      if (fridgeAlert == null || medsAlert == null)
        return '';

      var fridge = parseInt(fridgeAlert);
      var meds = parseInt(medsAlert);
      var alertString = '';

      // check for acceptable bounds
      if (meds < 0 || meds > 2 || fridge < 0 || fridge > 2)
        alertString = ''; // error state
      // check for null
      else if (fridge == 2 || meds == 2)
        alertString = 'red';
      else if (fridge == 1 || meds == 1)
        alertString = 'yellow';
      else if (fridge == 0 || meds == 0)
        alertString = 'blue';
      $scope.group[index].alertLevelColor = alertString;
      return alertString;
    };

    $scope.checkGroupHealth = function () {
      console.log('hit checkGroupHealth();')
      //create a template string
      var errorList = [];
      var errorCount = 0;
      for (var i = 1; i < $scope.group.length; i++) {
        if ($scope.group[i].error) {
          errorCount++;
          errorList.push(String($scope.group[i].name));
        }
        // on the last element now
        if (i == $scope.group.length - 1) {
          // no errors? then return
          if (errorCount == 0){
            GroupInfo.setSensorError(false);
            return true;
          }

          // error found! set the error variable
          if(errorCount > 0)
            GroupInfo.setSensorError(true);

          //lets craft up a string to be displayed
          var errorString = '';
          for (var j = 0; j < errorList.length; j++) {
            errorString += errorList[j];
            if (j < errorList.length - 2)
              errorString += ', ';
            else if (j == errorList.length - 2)
              errorString += ' and ';
            else if (j == errorList.length - 1) {
              // were done, display error message now
              if (!$scope.group[0].displayedError) {
                $scope.group[0].displayedError = true;
                displayError(errorString);
              }

            }
          }
        }
      }
    };

  });
<commit_msg>fixed indexing bug<commit_after>/**
 * CareWheels - Group Status Controller
 *
 */
angular.module('careWheels').controller('groupStatusController',
  function ($scope, $interval, $state, $ionicPopup, GroupInfo, User, PaymentService) {

    var groupArray = GroupInfo.groupInfo();

    // the groupInfo object is not available immediately, spin until available
    var initGroupInfo = setInterval(function () {
      var groupArray = GroupInfo.groupInfo();
      //console.log(groupArray);
      if (groupArray[0] != null) {
        clearInterval(initGroupInfo);
        // app on load
        console.log('hit group controller');
        getLoggedInUser(groupArray);
        setGroupArray(groupArray);
      }
    }, 50);

    /** automatically go through each user square, and
     *  find each 'red' alert, and fade that element in
     *  and out. (flashing effect)
     * */
    $interval(function () {
      /* jQuery element to fade in and out */
      var alertArray = [
        $('#topLeftAlert'),
        $('#topRightAlert'),
        $('#bottomLeftAlert'),
        $('#bottomRightAlert')
      ];
      for (var i = 0; i < alertArray.length; i++) {
        if (alertArray[i].css('background-color') === 'rgb(255, 0, 0)') {
          alertArray[i].fadeOut("slow");
          alertArray[i].fadeIn("slow");
        }
      }
    }, 2000);

    $scope.group = [
      { // center, self
        name: '',
        username: '',
        balance: '0.0',
        image: '',
        userSelected: '',
        displayedError: GroupInfo.getSensorError(),
        selfUserIndex: -1

      },
      { // top left @ index 1
        name: '',
        username: '',
        status: '',
        image: '',
        alertLevelColor: '',
        error: false
      },
      { // top right @ index 2
        name: '',
        username: '',
        status: '',
        image: '',
        alertLevelColor: '',
        error: false
      },
      { // bottom left @ index 3
        name: '',
        username: '',
        status: '',
        image: '',
        alertLevelColor: '',
        error: false
      },
      { // bottom right @ index 4
        name: '',
        username: '',
        status: '',
        image: '',
        alertLevelColor: '',
        error: false
      }
    ];

    /* click/press events */
    $scope.clickTopLeft = function () {
      clickUser(1);
    };
    $scope.clickTopRight = function () {
      clickUser(2);
    };
    $scope.clickBottomLeft = function () {
      clickUser(3);
    };
    $scope.clickBottomRight = function () {
      clickUser(4);
    };
    $scope.clickCenter = function () {
    };
    $scope.clickCareBank = function () {
    };

    // console.log("Calling memberSummary Payment:");
    // PaymentService.memberSummary(1.0);

    // lets figure out which user logged in at this point
    function getLoggedInUser(groupInfo) {
      console.log('group controller: getloggedinuser()');
      var user = User.credentials();
      // error unable to load user object;
      if (user == null){
        console.log('group controller: user not found');
        $scope.group[0].selfUserIndex = -1;
      }

      // loop through the groupInfo array to find the user who
      // logged in.
      for (var i = 0; i < groupInfo.length; i++) {
        console.log('logged in as:', user.username, '  and comparing with:', groupInfo[i].username);

        if (user.username == groupInfo[i].username){
          $scope.group[0].selfUserIndex = i; // gotcha!
          console.log('group controller: user found @ index', i);
          return true;
        }

      }

    }

    // now lets set the scope variables for the group view.
    function setGroupArray(groupArray) {
      var currentUser = 0;
      var fridgeAlert, medsAlert;

      var loggedInUserIndex = $scope.group[0].selfUserIndex;
      console.log('setGroupArray, logged in user at index', loggedInUserIndex);

      // next lets set the data for the user that logged in,
      // this is reserved at index zero.
      $scope.group[currentUser].image = groupArray[loggedInUserIndex].photoUrl;
      $scope.group[currentUser].username = groupArray[loggedInUserIndex].username;
      $scope.group[currentUser].name = groupArray[loggedInUserIndex].name;
      $scope.group[currentUser].balance = trimZeros(groupArray[loggedInUserIndex].balance);

      currentUser++; // = 1 at this point

      // put everyone else into the array
      for (var i = 0; i < 5; i++){
        // skip the user who logged in
        console.log('looping at index:', i);
        if(i != $scope.group[0].selfUserIndex){
          console.log('placing groupInfo member', i, 'into scope index', currentUser);
          $scope.group[currentUser].image = groupArray[i].photoUrl;
          $scope.group[currentUser].username = groupArray[i].username;
          $scope.group[currentUser].name = groupArray[i].name;

          try{
            fridgeAlert = groupArray[i].analysisData.fridgeAlertLevel;
            medsAlert = groupArray[i].analysisData.medsAlertLevel;
            $scope.group[currentUser].status = $scope.getAlertColor(fridgeAlert, medsAlert, i);
          }
          catch (Exception) {
            $scope.group[currentUser].status = 'grey';
            $scope.group[currentUser].error = true;
          }
          currentUser++;
        }
        else{
          console.log('skipping member', i, 'this is user who logged in');
        }
        // on the last element of the loop, now check health
        if (i == 4) {
          console.log('on last element');
          if(!GroupInfo.getSensorError())
            $scope.checkGroupHealth();
        }

      }

        //var userCount = 0;
      //// first lets set the group up, at index 1-4
      //for (var i = 0; i < 5; i++) {
      //  userCount++;
      //  if (i != $scope.group[0].selfUserIndex) {
      //    $scope.group[userCount].image = groupArray[i].photoUrl;
      //    $scope.group[userCount].username = groupArray[i].username;
      //    $scope.group[userCount].name = groupArray[i].name;
      //
      //    try {
      //      var fridgeAlert = groupArray[userCount].analysisData.fridgeAlertLevel;
      //      var medsAlert = groupArray[userCount].analysisData.medsAlertLevel;
      //      $scope.group[userCount].status = $scope.getAlertColor(fridgeAlert, medsAlert, i);
      //    }

      //  }
      //
      //}

    }

    //removes insignificant zeros
    function trimZeros(input) {
      var number = parseFloat(input);
      return number.toString();

    }

    function clickUser(index) {
      if (!$scope.group[index].error) {
        PaymentService.sensorDataView(0.1, $scope.group[index].alertLevelColor);
        $scope.group[0].userSelected = $scope.group[index].name;
        GroupInfo.setMember_new($scope.group[index].username);
        $state.go('app.individualStatus');
      }
    }

    // An error popup dialog
    function displayError(errorString) {
      var alertPopup = $ionicPopup.alert({
        title: '
Unable to load sensor data for:
',
        template: '
' + errorString + '
',
        buttons: [{ // Array[Object] (optional). Buttons to place in the popup footer.
          text: 'Okay',
          type: 'button-calm'
        }]
      });
      alertPopup.then(function (res) {

      });
    }

    /**
     * returns a string of of the color code depending on the
     * alert level. This string is used with ng-class, to
     * append the color class onto the div
     * */
    $scope.getAlertColor = function (fridgeAlert, medsAlert, index) {
      console.log('hit getAlertColor:', fridgeAlert, medsAlert, index);

      // check for null params
      if (fridgeAlert == null || medsAlert == null)
        return '';

      var fridge = parseInt(fridgeAlert);
      var meds = parseInt(medsAlert);
      var alertString = '';

      // check for acceptable bounds
      if (meds < 0 || meds > 2 || fridge < 0 || fridge > 2)
        alertString = ''; // error state
      // check for null
      else if (fridge == 2 || meds == 2)
        alertString = 'red';
      else if (fridge == 1 || meds == 1)
        alertString = 'yellow';
      else if (fridge == 0 || meds == 0)
        alertString = 'blue';
      $scope.group[index].alertLevelColor = alertString;
      return alertString;
    };

    $scope.checkGroupHealth = function () {
      console.log('hit checkGroupHealth();')
      //create a template string
      var errorList = [];
      var errorCount = 0;
      for (var i = 1; i < $scope.group.length; i++) {
        if ($scope.group[i].error) {
          errorCount++;
          errorList.push(String($scope.group[i].name));
        }
        // on the last element now
        if (i == $scope.group.length - 1) {
          // no errors? then return
          if (errorCount == 0){
            GroupInfo.setSensorError(false);
            return true;
          }

          // error found! set the error variable
          if(errorCount > 0)
            GroupInfo.setSensorError(true);

          //lets craft up a string to be displayed
          var errorString = '';
          for (var j = 0; j < errorList.length; j++) {
            errorString += errorList[j];
            if (j < errorList.length - 2)
              errorString += ', ';
            else if (j == errorList.length - 2)
              errorString += ' and ';
            else if (j == errorList.length - 1) {
              // were done, display error message now
              if (!$scope.group[0].displayedError) {
                $scope.group[0].displayedError = true;
                displayError(errorString);
              }

            }
          }
        }
      }
    };

  });
<|endoftext|>


<commit_before>window.ChannelList = Backbone.Collection.extend({
  model: Channel,
  reloadingEnabled: false,

  initialize: function() {
    this.bind('activate', this.setActiveChannel);
    this.bind('reset', this.checkActiveChannel);
  },

  url: function() {
    return '/' + this.getUsername() + '/channels';
  },

  setActiveChannel: function(channel) {
    if ( this.activeChannelId && this.activeChannelId !== channel.id ) {
      this.get(this.activeChannelId).trigger('deactivate');
    }

    this.activeChannelId = channel.id;
  },

  checkActiveChannel: function() {
    if ( this.activeChannelId ) {
      var activeChannel = this.get(this.activeChannelId);

      if ( activeChannel ) {
        activeChannel.trigger('activate', activeChannel);
      }
    }
  },

  getUsername: function() {
    if ( this._username ) {
      return this._username;
    }

    return false;
  },

  setUsername: function(name) {
    this._username = name;
  },

  shouldReload: function(){
    return ! ( typeof localStorage === "object"
      && localStorage !== null
      && localStorage['reload'] === "false" );
  },

  setupReloading: function() {
    if(this.shouldReload() && (! this.reloadingEnabled === true)) {
      this.reloadingEnabled = true;
      this.startReloading();
    }
  },

  startReloading: function(){
    if(this.shouldReload()) {
      var args = arguments;
      var self = this;
      setTimeout(function(){
        self.fetch({
          success: _.bind(args.callee, self),
          error:   _.bind(args.callee, self)
        });
      }, 7000);
    }
  }

});

window.Channels = new ChannelList();
<commit_msg>on is the new bind<commit_after>window.ChannelList = Backbone.Collection.extend({
  model: Channel,
  reloadingEnabled: false,

  initialize: function() {
    this.on('activate', this.setActiveChannel);
    this.on('reset', this.checkActiveChannel);
  },

  url: function() {
    return '/' + this.getUsername() + '/channels';
  },

  setActiveChannel: function(channel) {
    if ( this.activeChannelId && this.activeChannelId !== channel.id ) {
      this.get(this.activeChannelId).trigger('deactivate');
    }

    this.activeChannelId = channel.id;
  },

  checkActiveChannel: function() {
    if ( this.activeChannelId ) {
      var activeChannel = this.get(this.activeChannelId);

      if ( activeChannel ) {
        activeChannel.trigger('activate', activeChannel);
      }
    }
  },

  getUsername: function() {
    if ( this._username ) {
      return this._username;
    }

    return false;
  },

  setUsername: function(name) {
    this._username = name;
  },

  shouldReload: function(){
    return ! ( typeof localStorage === "object"
      && localStorage !== null
      && localStorage['reload'] === "false" );
  },

  setupReloading: function() {
    if(this.shouldReload() && (! this.reloadingEnabled === true)) {
      this.reloadingEnabled = true;
      this.startReloading();
    }
  },

  startReloading: function(){
    if(this.shouldReload()) {
      var args = arguments;
      var self = this;
      setTimeout(function(){
        self.fetch({
          success: _.bind(args.callee, self),
          error:   _.bind(args.callee, self)
        });
      }, 7000);
    }
  }

});

window.Channels = new ChannelList();
<|endoftext|>