<commit_before>'use strict';

/**
 * @file Choko core controllers.
 */

angular.module('choko')

  .controller('ApplicationController', ['$rootScope', '$location', '$http', 'applicationState',
    function ($rootScope, $location, $http, applicationState) {
      $rootScope.state = {};

      $rootScope.changeState = function() {
        var path = (!$location.path() || $location.path() == '/') ? '/home' : $location.path();

        $http.get(path)
        .success(function(data, status, headers, config) {
          if (data.data.redirect) {
            // Server returned a redirect.
            return $location.path(data.data.redirect);
          }

          // Rebuild the layout only when context changes.
          if ($rootScope.contexts instanceof Array && $rootScope.contexts.toString() == data.data.contexts.toString()) {
            // Update only panels in content region, and page information.
            // @todo: get the region the page-content panel is attached to
            // dinamically currently this is hadcoded to 'content' and will not work
            // if the page-content panel is attacehd to a different region.
            $rootScope.panels['content'] = data.data.panels['content'];
            $rootScope.page = data.data.page;
          }
          else {
            // Merge data from the server.
            angular.extend($rootScope, data.data);

            // Store scope as application state.
            applicationState.set($rootScope);
          }
        })
        .error(function(data, status, headers, config) {
          // Merge data from the server.
          angular.extend($rootScope.page, data.data);

          $rootScope.page.template = '/templates/error.html';

          // Store scope as application state.
          applicationState.set($rootScope);
        });
      }

      $rootScope.$watch(function() {
        return $location.path();
      }, function(){
        $rootScope.changeState();
      });
    }])

  .controller('ItemController', ['$scope',
    function ($scope) {

    }])

  .controller('ViewController', ['$scope', '$location', '$http', 'Choko', 'Params',
    function ($scope, $location, $http, Choko, Params) {

      // Parse parameters when needed.
      if (typeof $scope.view.itemKey !== 'undefined') {
        $scope.view.itemKey = Params.parse($scope.view.itemKey, $scope);
      }

      // Parse other params.
      Object.keys($scope.view.query || {}).forEach(function (param) {
        $scope.view.query[param] = Params.parse($scope.view.query[param], $scope);
      });

      // Handle 'list' type views.
      if ($scope.view.type === 'list' && $scope.view.itemType) {
        var query = {
          type: $scope.view.itemType
        };

        if ($scope.view.query) {
          angular.extend(query, $scope.view.query);
        }

        $scope.items = {};

        Choko.get(query, function(response) {
          $scope.items = response;
        });

        if (!$scope.view.template && $scope.view.listStyle) {
          $scope.view.template = '/templates/' + $scope.view.listStyle + '.html';
        }

        if (!$scope.view.itemTemplate && $scope.view.itemDisplay) {
          Choko.get({type: 'display', key: $scope.view.itemDisplay}, function(display) {
            $scope.display = display;
            if (display.layout) {
              Choko.get({type: 'displayLayout', key: display.layout}, function(layout) {
                $scope.layout = layout;
                $scope.view.itemTemplate = '/templates/display-layout.html';
              });
            }
          });
        }
      }

      // Handle 'item' type views.
      if ($scope.view.type === 'item' && $scope.view.itemType) {
        $scope.data = {};
        $scope.view.title = '';
        Choko.get({type: $scope.view.itemType, key: $scope.view.itemKey}, function(response) {
          $scope.data = response;
          $scope.view.title = response.title;
        },
        function(response) {
          // Error.
          if ($scope.page) {
            // If it's a page, show error, otherwise fail silently.
            $scope.data = response.data;
            $scope.view.title = response.data.title;
            $scope.view.template = '/templates/error.html';
          }
        });
      }

      // Handle 'form' type views.
      if ($scope.view.type === 'form' && $scope.view.formName) {
        $scope.data = {};
        $scope.buildForm = function () {
          Choko.get({type: 'form', key: $scope.view.formName}, function(response) {
            $scope.form = response;

            if ($scope.form.mainTypeName) {
              $scope.data.type = $scope.form.shortName;
            }

            // First we look for view (page/panel) redirect, then for form redirect.
            // The submit button will first look for a property of its own and
            // fallback to this.
            $scope.form.redirect = $scope.view.redirect || $scope.form.redirect || null;

            $scope.view.template = $scope.view.template || $scope.form.template;
            $scope.view.template = $scope.view.template || '/templates/form.html';
          });
        };

        if ($scope.view.itemType && $scope.view.itemKey) {
          // Load item for editing.
          Choko.get({type: $scope.view.itemType, key: $scope.view.itemKey}, function(response) {
            $scope.data = response;
            $scope.buildForm();
          });
        }
        else {
          $scope.buildForm();
        }

        $scope.submit = function(url, redirect) {
          // Add itemKey to the URL if any.
          if ($scope.view.itemKey) {
            url += '/' + $scope.view.itemKey;
          }

          $http.post(url, $scope.data)
            .success(function(data, status, headers, config) {
              $scope.data = data.data;
              delete $scope.errors;
              if (redirect) {
                $location.path(redirect);
              }
            })
            .error(function(data, status, headers, config) {
              $scope.status = status;
              $scope.errors = data.data;
            });
        };
      }
    }]);
<commit_msg>Making rebuilding the page only if context, theme or layout has changed. Issue #153.<commit_after>'use strict';

/**
 * @file Choko core controllers.
 */

angular.module('choko')

  .controller('ApplicationController', ['$rootScope', '$location', '$http', 'applicationState',
    function ($rootScope, $location, $http, applicationState) {
      $rootScope.state = {};

      $rootScope.changeState = function() {
        var path = (!$location.path() || $location.path() == '/') ? '/home' : $location.path();

        $http.get(path)
        .success(function(data, status, headers, config) {
          if (data.data.redirect) {
            // Server returned a redirect.
            return $location.path(data.data.redirect);
          }

          // If contexts didn't change we just need to update main page content.
          if ($rootScope.contexts instanceof Array && angular.equals($rootScope.contexts, data.data.contexts)) {
            // Update only panels in content region, and page information.
            // @todo: get the region the page-content panel is attached to
            // dinamically currently this is hadcoded to 'content' and will not work
            // if the page-content panel is attacehd to a different region.
            $rootScope.panels['content'] = data.data.panels['content'];

            // Set page data.
            $rootScope.page = data.data.page;
          }
          else {
            // We only set everything on scope if it's the first page being
            // loaded or if the theme or the layout has changed, to avoid some
            // glitches.
            // @todo: selectivelly replace/add/remove panels.
            var needsRebuild = !('page' in $rootScope) ||
              ('theme' in $rootScope && $rootScope.theme.name != data.data.theme.name) ||
              ('layout' in $rootScope && $rootScope.layout.name != data.data.layout.name);

            if (needsRebuild) {
              // Merge all data from the server.
              angular.extend($rootScope, data.data);
            }
            else {
              // Selectivelly merge data from the server.
              Object.keys(data.data).forEach(function(propName) {
                if (['theme', 'layout'].indexOf(propName) === -1) {
                  $rootScope[propName] = data.data[propName];
                }
              });
            }

            // Store scope as application state.
            applicationState.set($rootScope);
          }
        })
        .error(function(data, status, headers, config) {
          // Merge data from the server.
          angular.extend($rootScope.page, data.data);

          $rootScope.page.template = '/templates/error.html';

          // Store scope as application state.
          applicationState.set($rootScope);
        });
      }

      $rootScope.$watch(function() {
        return $location.path();
      }, function(){
        $rootScope.changeState();
      });
    }])

  .controller('ItemController', ['$scope',
    function ($scope) {

    }])

  .controller('ViewController', ['$scope', '$location', '$http', 'Choko', 'Params',
    function ($scope, $location, $http, Choko, Params) {

      // Parse parameters when needed.
      if (typeof $scope.view.itemKey !== 'undefined') {
        $scope.view.itemKey = Params.parse($scope.view.itemKey, $scope);
      }

      // Parse other params.
      Object.keys($scope.view.query || {}).forEach(function (param) {
        $scope.view.query[param] = Params.parse($scope.view.query[param], $scope);
      });

      // Handle 'list' type views.
      if ($scope.view.type === 'list' && $scope.view.itemType) {
        var query = {
          type: $scope.view.itemType
        };

        if ($scope.view.query) {
          angular.extend(query, $scope.view.query);
        }

        $scope.items = {};

        Choko.get(query, function(response) {
          $scope.items = response;
        });

        if (!$scope.view.template && $scope.view.listStyle) {
          $scope.view.template = '/templates/' + $scope.view.listStyle + '.html';
        }

        if (!$scope.view.itemTemplate && $scope.view.itemDisplay) {
          Choko.get({type: 'display', key: $scope.view.itemDisplay}, function(display) {
            $scope.display = display;
            if (display.layout) {
              Choko.get({type: 'displayLayout', key: display.layout}, function(layout) {
                $scope.layout = layout;
                $scope.view.itemTemplate = '/templates/display-layout.html';
              });
            }
          });
        }
      }

      // Handle 'item' type views.
      if ($scope.view.type === 'item' && $scope.view.itemType) {
        $scope.data = {};
        $scope.view.title = '';
        Choko.get({type: $scope.view.itemType, key: $scope.view.itemKey}, function(response) {
          $scope.data = response;
          $scope.view.title = response.title;
        },
        function(response) {
          // Error.
          if ($scope.page) {
            // If it's a page, show error, otherwise fail silently.
            $scope.data = response.data;
            $scope.view.title = response.data.title;
            $scope.view.template = '/templates/error.html';
          }
        });
      }

      // Handle 'form' type views.
      if ($scope.view.type === 'form' && $scope.view.formName) {
        $scope.data = {};
        $scope.buildForm = function () {
          Choko.get({type: 'form', key: $scope.view.formName}, function(response) {
            $scope.form = response;

            if ($scope.form.mainTypeName) {
              $scope.data.type = $scope.form.shortName;
            }

            // First we look for view (page/panel) redirect, then for form redirect.
            // The submit button will first look for a property of its own and
            // fallback to this.
            $scope.form.redirect = $scope.view.redirect || $scope.form.redirect || null;

            $scope.view.template = $scope.view.template || $scope.form.template;
            $scope.view.template = $scope.view.template || '/templates/form.html';
          });
        };

        if ($scope.view.itemType && $scope.view.itemKey) {
          // Load item for editing.
          Choko.get({type: $scope.view.itemType, key: $scope.view.itemKey}, function(response) {
            $scope.data = response;
            $scope.buildForm();
          });
        }
        else {
          $scope.buildForm();
        }

        $scope.submit = function(url, redirect) {
          // Add itemKey to the URL if any.
          if ($scope.view.itemKey) {
            url += '/' + $scope.view.itemKey;
          }

          $http.post(url, $scope.data)
            .success(function(data, status, headers, config) {
              $scope.data = data.data;
              delete $scope.errors;
              if (redirect) {
                $location.path(redirect);
              }
            })
            .error(function(data, status, headers, config) {
              $scope.status = status;
              $scope.errors = data.data;
            });
        };
      }
    }]);
<|endoftext|>


<commit_before>var http = require('http');
var url = require('url');

function start(route, handle){
	function onRequest(req, res){
		var pathName = url.parse(req.url).pathname;
		console.log('Request for ' + pathName + ' received');

		route(handle, pathName);

		res.writeHead(200, {'Content-Type': 'text/plain'});
		res.write('Hello World');
		res.end();
	}

	http.createServer(onRequest).listen(8888);
	console.log('Server has started.');
}

exports.start = start;

<commit_msg>Update server.js<commit_after>var http = require('http');
var url = require('url');

function start(route, handle){
	function onRequest(req, res){
		var pathName = url.parse(req.url).pathname;
		console.log('Request for ' + pathName + ' received');

		route(handle, pathName, res);
	}

	http.createServer(onRequest).listen(8888);
	console.log('Server has started.');
}

exports.start = start;

<|endoftext|>


<commit_before>(function ($) {
  "use strict";
  /*global alert: true, ODSA */
  $(document).ready(function () {
    var initData, bh,
        settings = new JSAV.utils.Settings($(".jsavsettings")),
        jsav = new JSAV($('.avcontainer'), {settings: settings}),
        exercise,
        swapIndex;

		var graph;

		jsav.recorded();

    function init() {
		graph = jsav.ds.graph({width: 200, height: 300, layout: "manual", directed: false});

		initGraph();
		graph.layout();

	  /*
      var nodeNum = 10;
      if (bh) {
        bh.clear();
      }
      initData = JSAV.utils.rand.numKeys(10, 100, nodeNum);

      // Log the initial state of the exercise
      var exInitData = {};
      exInitData.gen_array = initData;
      ODSA.AV.logExerciseInit(exInitData);

      bh = jsav.ds.binheap(initData, { nodegap: 25, compare: function (a, b) { return b - a; }});
      swapIndex = jsav.variable(-1);
      jsav.displayInit();
      return bh;
	  */
    }

    function fixState(modelHeap) {
      var size = modelHeap.size();
      swapIndex.value(-1); // only swaps are graded so swapIndex cannot be anything else after correct step
      for (var i = 0; i < size; i++) {
        bh.css(i, {"background-color": modelHeap.css(i, "background-color")});
        bh.value(i, modelHeap.value(i));
      }
      bh.heapsize(modelHeap.heapsize());
      exercise.gradeableStep();
    }

    function model(modeljsav) {
      var modelbh = modeljsav.ds.binheap(initData, {nodegap: 20, compare: function (a, b) { return b - a; }});
      modelbh.origswap = modelbh.swap; // store original heap grade function
      // set all steps gradeable that include a swap
      modelbh.swap = function (ind1, ind2, opts) {
        this.origswap(ind1, ind2, opts);
        this.jsav.stepOption("grade", true);
      };
      modeljsav._undo = [];
      while (modelbh.heapsize() > 1) {
        if (modelbh.heapsize() === initData.length) {
          modeljsav.umsg("We start by swapping largest and last items in heap.");
          modeljsav.step();
        } else if (modelbh.heapsize() > initData.length - 3) {
          modeljsav.umsg("Again, we swap largest and last items in heap.");
        } else {
          modeljsav.umsg("...swap largest and last items in heap.");
        }
        modelbh.swap(0, modelbh.heapsize() - 1);
        modeljsav.step();
        modelbh.heapsize(modelbh.heapsize() - 1);
        modeljsav.umsg("
...decrement the heap size", {preserve: true});
        modelbh.css(modelbh.heapsize(), {"background-color": "#ddd"});
        modeljsav.stepOption("grade", true);
        modeljsav.step();
        modeljsav.umsg("
...and restore the heap property", {preserve: true});
        modelbh.heapify(1);
        modeljsav.umsg("");
        modeljsav.step();
      }
      modelbh.css(0, {"background-color": "#ddd"});
      modeljsav.stepOption("grade", true);
      modeljsav.step();
      return modelbh;
    }

    function clickHandler(index) {
      if (bh.heapsize() === 0 || index >= bh.heapsize()) {
        return;
      }
      jsav._redo = []; // clear the forward stack, should add a method for this in lib
      var sIndex = swapIndex.value();
      if (sIndex === -1) { // if first click
        bh.css(index, {"font-size": "145%"});
        swapIndex.value(index);
        jsav.step();
      } else if (sIndex === index) {
        bh.css(index, {"font-size": "100%"});
        swapIndex.value(-1);
        jsav.step();
      } else { // second click will swap
        bh.css([sIndex, index], {"font-size": "100%"});
        bh.swap(sIndex, index, {});
        swapIndex.value(-1);
        exercise.gradeableStep();
      }
    }

function initGraph() {

    //Nodes of the original graph
    var a = graph.addNode("A", {"left": 25, "top": 50});
    var b = graph.addNode("B", {"left": 325, "top": 50});
    var c = graph.addNode("C", {"left": 145, "top": 75});
    var d = graph.addNode("D", {"left": 145, "top": 200});
    var e = graph.addNode("E", {"left": 0, "top": 300});
    var f = graph.addNode("F", {"left": 325, "top": 250});
    //Original graph edges
    graph.addEdge(a, c, {"weight": 7});
    graph.addEdge(a, e, {"weight": 9});
    graph.addEdge(c, b, {"weight": 5});
    graph.addEdge(c, d, {"weight": 1});
    graph.addEdge(c, f, {"weight": 2});
    graph.addEdge(f, b, {"weight": 6});
    graph.addEdge(d, f, {"weight": 2});
    graph.addEdge(e, f, {"weight": 1});
    }

      // Process About button: Pop up a message with an Alert
    function about() {
      alert("Heapsort Proficiency Exercise\nWritten by Ville Karavirta\nCreated as part of the OpenDSA hypertextbook project\nFor more information, see http://algoviz.org/OpenDSA\nSource and development history available at\nhttps://github.com/cashaffer/OpenDSA\nCompiled with JSAV library version " + JSAV.version());
    }

    exercise = jsav.exercise(model, init, { css: "background-color" },
                            { feedback: "continuous",
                             controls: $('.jsavexercisecontrols'),
                              fixmode: "fix",
                             fix: fixState });
    exercise.reset();

    $(".jsavcontainer").on("click", ".jsavarray .jsavindex", function () {
      var index = $(this).parent(".jsavarray").find(".jsavindex").index(this);
      clickHandler(index);
    });
    $(".jsavcontainer").on("click", ".jsavbinarytree .jsavbinarynode", function () {
      var index = $(this).data("jsav-heap-index") - 1;
      clickHandler(index);
    });
    $("#decrement").click(function () {
      if (bh.heapsize() === 0) {
        alert("Heapsize is already zero, cannot decrement!");
        return;
      }
      bh.heapsize(bh.heapsize() - 1);
      bh.css(bh.heapsize(), {"background-color": "#ddd"});
      exercise.gradeableStep();
    });
    $("#about").click(about);
  });
}(jQuery));
<commit_msg>testing<commit_after>(function ($) {
  "use strict";
  /*global alert: true, ODSA */
  $(document).ready(function () {
    var initData, bh,
        settings = new JSAV.utils.Settings($(".jsavsettings")),
        jsav = new JSAV($('.avcontainer'), {settings: settings}),
        exercise,
        swapIndex, graph, modelGraph;
		jsav.recorded();

    function init() {
		graph = jsav.ds.graph({width: 600, height: 600, layout: "manual", directed: false});
		initGraph();
		graph.layout();

	  /*
      var nodeNum = 10;
      if (bh) {
        bh.clear();
      }
      initData = JSAV.utils.rand.numKeys(10, 100, nodeNum);

      // Log the initial state of the exercise
      var exInitData = {};
      exInitData.gen_array = initData;
      ODSA.AV.logExerciseInit(exInitData);

      bh = jsav.ds.binheap(initData, { nodegap: 25, compare: function (a, b) { return b - a; }});
      swapIndex = jsav.variable(-1);
      jsav.displayInit();
      return bh;
	  */
    }

    function fixState(modelHeap) {
	  /*
      var size = modelHeap.size();
      swapIndex.value(-1); // only swaps are graded so swapIndex cannot be anything else after correct step
      for (var i = 0; i < size; i++) {
        bh.css(i, {"background-color": modelHeap.css(i, "background-color")});
        bh.value(i, modelHeap.value(i));
      }
      bh.heapsize(modelHeap.heapsize());
      exercise.gradeableStep();
	  */
    }

    function model(modeljsav) {
		modelGraph = modeljsav.ds.graph({width: 600, height: 600, layout: "manual", directed: false});
		initModelGraph();
		modelGraph.layout();
		//alert(modelGraph.nodes()[0].value());
		modeljsav._undo = [];
		for(var i=0;i<modelGraph.nodeCount;i++)
		{
			modeljsav.umsg("Highlighting node "+modelGraph.nodes()[i].value());
			modelGraph.nodes()[i].highlight();
			modeljsav.stepOption("grade", true);
			modeljsav.step();
		}
      /*
	  var modelbh = modeljsav.ds.binheap(initData, {nodegap: 20, compare: function (a, b) { return b - a; }});
      modelbh.origswap = modelbh.swap; // store original heap grade function
      // set all steps gradeable that include a swap
      modelbh.swap = function (ind1, ind2, opts) {
        this.origswap(ind1, ind2, opts);
        this.jsav.stepOption("grade", true);
      };
      modeljsav._undo = [];
      while (modelbh.heapsize() > 1) {
        if (modelbh.heapsize() === initData.length) {
          modeljsav.umsg("We start by swapping largest and last items in heap.");
          modeljsav.step();
        } else if (modelbh.heapsize() > initData.length - 3) {
          modeljsav.umsg("Again, we swap largest and last items in heap.");
        } else {
          modeljsav.umsg("...swap largest and last items in heap.");
        }
        modelbh.swap(0, modelbh.heapsize() - 1);
        modeljsav.step();
        modelbh.heapsize(modelbh.heapsize() - 1);
        modeljsav.umsg("
...decrement the heap size", {preserve: true});
        modelbh.css(modelbh.heapsize(), {"background-color": "#ddd"});
        modeljsav.stepOption("grade", true);
        modeljsav.step();
        modeljsav.umsg("
...and restore the heap property", {preserve: true});
        modelbh.heapify(1);
        modeljsav.umsg("");
        modeljsav.step();
      }
      modelbh.css(0, {"background-color": "#ddd"});
      modeljsav.stepOption("grade", true);
      modeljsav.step();
      return modelbh;
	 */
	  return modelGraph;

    }

    function clickHandler(index) {
      if (bh.heapsize() === 0 || index >= bh.heapsize()) {
        return;
      }
      jsav._redo = []; // clear the forward stack, should add a method for this in lib
      var sIndex = swapIndex.value();
      if (sIndex === -1) { // if first click
        bh.css(index, {"font-size": "145%"});
        swapIndex.value(index);
        jsav.step();
      } else if (sIndex === index) {
        bh.css(index, {"font-size": "100%"});
        swapIndex.value(-1);
        jsav.step();
      } else { // second click will swap
        bh.css([sIndex, index], {"font-size": "100%"});
        bh.swap(sIndex, index, {});
        swapIndex.value(-1);
        exercise.gradeableStep();
      }
    }

function initGraph() {

    //Nodes of the original graph
    var a = graph.addNode("A", {"left": 25, "top": 50});
    var b = graph.addNode("B", {"left": 325, "top": 50});
    var c = graph.addNode("C", {"left": 145, "top": 75});
    var d = graph.addNode("D", {"left": 145, "top": 200});
    var e = graph.addNode("E", {"left": 0, "top": 300});
    var f = graph.addNode("F", {"left": 325, "top": 250});
    //Original graph edges
    graph.addEdge(a, c, {"weight": 7});
    graph.addEdge(a, e, {"weight": 9});
    graph.addEdge(c, b, {"weight": 5});
    graph.addEdge(c, d, {"weight": 1});
    graph.addEdge(c, f, {"weight": 2});
    graph.addEdge(f, b, {"weight": 6});
    graph.addEdge(d, f, {"weight": 2});
    graph.addEdge(e, f, {"weight": 1});
    }

function initModelGraph() {

    //Nodes of the original graph
    var a = modelGraph.addNode("A", {"left": 25, "top": 50});
    var b = modelGraph.addNode("B", {"left": 325, "top": 50});
    var c = modelGraph.addNode("C", {"left": 145, "top": 75});
    var d = modelGraph.addNode("D", {"left": 145, "top": 200});
    var e = modelGraph.addNode("E", {"left": 0, "top": 300});
    var f = modelGraph.addNode("F", {"left": 325, "top": 250});
    //Original graph edges
    modelGraph.addEdge(a, c, {"weight": 7});
    modelGraph.addEdge(a, e, {"weight": 9});
    modelGraph.addEdge(c, b, {"weight": 5});
    modelGraph.addEdge(c, d, {"weight": 1});
    modelGraph.addEdge(c, f, {"weight": 2});
    modelGraph.addEdge(f, b, {"weight": 6});
    modelGraph.addEdge(d, f, {"weight": 2});
    modelGraph.addEdge(e, f, {"weight": 1});
    }

      // Process About button: Pop up a message with an Alert
    function about() {
      alert("Heapsort Proficiency Exercise\nWritten by Ville Karavirta\nCreated as part of the OpenDSA hypertextbook project\nFor more information, see http://algoviz.org/OpenDSA\nSource and development history available at\nhttps://github.com/cashaffer/OpenDSA\nCompiled with JSAV library version " + JSAV.version());
    }

    exercise = jsav.exercise(model, init, { css: "background-color" },
                            { feedback: "continuous",
                             controls: $('.jsavexercisecontrols'),
                              fixmode: "fix",
                             fix: fixState });
    exercise.reset();

    $(".jsavcontainer").on("click", ".jsavarray .jsavindex", function () {
      var index = $(this).parent(".jsavarray").find(".jsavindex").index(this);
      clickHandler(index);
    });
    $(".jsavcontainer").on("click", ".jsavbinarytree .jsavbinarynode", function () {
      var index = $(this).data("jsav-heap-index") - 1;
      clickHandler(index);
    });
    $("#decrement").click(function () {
      if (bh.heapsize() === 0) {
        alert("Heapsize is already zero, cannot decrement!");
        return;
      }
      bh.heapsize(bh.heapsize() - 1);
      bh.css(bh.heapsize(), {"background-color": "#ddd"});
      exercise.gradeableStep();
    });
    $("#about").click(about);
  });
}(jQuery));
<|endoftext|>


<commit_before>var mediaArchiveApp = angular.module('mediaArchiveApp', []);

mediaArchiveApp.controller('MediaArchiveCtrl', function ($scope, $http, $location) {
  $scope.items = [];
  $scope.mediatypes = { "audio" : true, "video" : true };
  $scope.talktypes = { "lecture" : true, "conference_session" : true };
  var use_static_data = $location.search('static');

  $scope.loadItems = function() {
    if(use_static_data === 'false') {
      var avItemsRequest = $http({
        method: 'GET',
        url: '/search/audio_video_items'
      }).success(function(data, status) {
        $scope.audio_video_items = data.items;
      });

      var articleItemsRequest = $http({
        method: 'GET',
        url: '/search/articles'
      }).success(function(data, status) {
        $scope.articles = data.items;
      });
    } else {
      var httpRequest = $http({
        method: 'GET',
        url: '/wp-content/themes/lsecities-2012/assets/js/media-archive-app/media_archive_data.json'
      }).success(function(data, status) {
        $scope.audio_video_items = data.audio_video_items;
        $scope.articles = data.articles;
      });
    };
  };

  $scope.loadItems();
});

/**
 * override standard filter to return everything when no input text
 * is provided
 */
mediaArchiveApp.filter('textFilter', function($filter) {
  return function(items, search_query) {
    console.log(items);
    console.log('search_query: ' . search_query);

    if(search_query !== null && search_query.length == 0) {
      return items;
    } else {
      return $filter('filter')(search_query);
    }
  }
});

mediaArchiveApp.filter('mediatypefilter', function() {
  return function(items, mediatypes) {
    var filtered = [];

    // If no specific media type has been selected, return everything
    if(mediatypes.audio == false && mediatypes.video == false) {
        return items;
    }

    // Otherwise, filter by media type
    angular.forEach(items, function(item) {
      if(mediatypes.audio == true && item.youtube_uri.length > 0){
        filtered.push(item);
      }
      else if(mediatypes.video == true && item.audio_uri.length > 0){
        filtered.push(item);
      }
    });

    return filtered;
  };
});

mediaArchiveApp.filter('talkTypeFilter', function() {
  return function(items, talktypes) {
    var filtered = [];

    angular.forEach(items, function(item) {
      if(talktypes.lecture == true && item.parent_event !== null && typeof item.parent_event === 'object'){
        filtered.push(item);
      }
      else if(talktypes.conference_session == true && item.related_session !== null && typeof item.related_session === 'object'){
        filtered.push(item);
      }
    });

    return filtered;
  };
});
<commit_msg>fixup!also return all items if query is null<commit_after>var mediaArchiveApp = angular.module('mediaArchiveApp', []);

mediaArchiveApp.controller('MediaArchiveCtrl', function ($scope, $http, $location) {
  $scope.items = [];
  $scope.mediatypes = { "audio" : true, "video" : true };
  $scope.talktypes = { "lecture" : true, "conference_session" : true };
  var use_static_data = $location.search('static');

  $scope.loadItems = function() {
    if(use_static_data === 'false') {
      var avItemsRequest = $http({
        method: 'GET',
        url: '/search/audio_video_items'
      }).success(function(data, status) {
        $scope.audio_video_items = data.items;
      });

      var articleItemsRequest = $http({
        method: 'GET',
        url: '/search/articles'
      }).success(function(data, status) {
        $scope.articles = data.items;
      });
    } else {
      var httpRequest = $http({
        method: 'GET',
        url: '/wp-content/themes/lsecities-2012/assets/js/media-archive-app/media_archive_data.json'
      }).success(function(data, status) {
        $scope.audio_video_items = data.audio_video_items;
        $scope.articles = data.articles;
      });
    };
  };

  $scope.loadItems();
});

/**
 * override standard filter to return everything when no input text
 * is provided
 */
mediaArchiveApp.filter('textFilter', function($filter) {
  return function(items, query) {
    console.log(items);
    console.log('search_query: ' . query);

    if(query == null || (query !== null && query.length == 0)) {
      return items;
    } else {
      return $filter('filter')(query);
    }
  }
});

mediaArchiveApp.filter('mediatypefilter', function() {
  return function(items, mediatypes) {
    var filtered = [];

    // If no specific media type has been selected, return everything
    if(mediatypes.audio == false && mediatypes.video == false) {
        return items;
    }

    // Otherwise, filter by media type
    angular.forEach(items, function(item) {
      if(mediatypes.audio == true && item.youtube_uri.length > 0){
        filtered.push(item);
      }
      else if(mediatypes.video == true && item.audio_uri.length > 0){
        filtered.push(item);
      }
    });

    return filtered;
  };
});

mediaArchiveApp.filter('talkTypeFilter', function() {
  return function(items, talktypes) {
    var filtered = [];

    angular.forEach(items, function(item) {
      if(talktypes.lecture == true && item.parent_event !== null && typeof item.parent_event === 'object'){
        filtered.push(item);
      }
      else if(talktypes.conference_session == true && item.related_session !== null && typeof item.related_session === 'object'){
        filtered.push(item);
      }
    });

    return filtered;
  };
});
<|endoftext|>


<commit_before>$(document).ready(function () {
    $('#results').empty;
    var userID = localStorage['userID'];
    var Snapster;
    var playlists = [];
    var currentTracks = [];
    var j;
    var obj = {};
    var sendInfo;
    // $("#filename").focus(function (event) {
    $('#infoHeader').empty();
    $('#infoHeader').append("Upcoming Songs");
    if (localStorage.getItem("lastFM") != "null" || localStorage.getItem("lastFM") != "") {
        $.ajax({
            type: "GET",
            url: "https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=" + localStorage.getItem("lastFM") + "&api_key=9fc54977379828d52d1d779dc62f569b&format=json",
            dataType: "json",
            data: "formdata",
            success: function (currentData) {
                $('#footer2').append("" + currentData.recenttracks.track[0].artist['#text'] + " - " + "" + currentData.recenttracks.track[0].name + "" + "
");
                localStorage["currentlyPlaying"] = currentData.recenttracks.track[0].name.toUpperCase();
            }
        });
        localStorage["totalSongs"] = 0;
        localStorage["currentlyPlayingWC"] = "";
        localStorage["currentlyPlaying"] = "";
         localStorage["currentTrack"] = 0;
          localStorage["offsetNumber"] = 0;
          partyPlaylist = 0;
        $.ajax({
            type: "GET",
            url: "https://api.spotify.com/v1/users/" + userID + "/playlists/" + localStorage["Snapster"] + "/tracks",
            headers: { 'Authorization': 'Bearer ' + access_token },
            dataType: "json",
            data: "formdata",
            success: function (trackData) {
                currentTracks = [];
                for (i = 0; i < trackData.items.length; i++) {
                    currentTracks[i] = trackData.items[i].track.name.toUpperCase();
                }
                console.log(currentTracks);
                localStorage["totalSongs"] = currentTracks.length;
                localStorage["currentlyPlayingWC"] = localStorage["currentlyPlaying"].replace(/,/g, '');
                localStorage["currentTrack"] = currentTracks.indexOf(localStorage["currentlyPlayingWC"]);
                for (i = 0; i < currentTracks.length; i++) {
                    if (localStorage["currentTrack"] >= 5) {
                        localStorage["offsetNumber"] = localStorage["currentTrack"] - 4;
                    }
                    else {
                        localStorage["offsetNumber"] = 0;
                    }
                    currentTracks = [];
                }
            }
        });
        $.ajax({
            type: "GET",
            url: "https://api.spotify.com/v1/users/" + userID + "/playlists",
            headers: { 'Authorization': 'Bearer ' + access_token },
            dataType: "json",
            data: "formdata",
            success: function (data) {
                for (i = 0; i < data.items.length; i++) {
                    playlists.push(data.items[i].name);
                }
                partyPlaylist = playlists.indexOf("Partify");
                if (playlists.indexOf("Partify") != -1 && data.items[partyPlaylist].id === localStorage['Snapster']) {
                    for (i = 0; i < data.items.length; i++) {
                        localStorage['Snapster'] = data.items[partyPlaylist].id;
                        Snapster = localStorage['Snapster'];
                    }
                    $("#results").css("text-align", "center");
                    $.ajax( {
                        type: "GET",
                        url: "https://api.spotify.com/v1/users/" + userID + "/playlists/" + Snapster + "/tracks?limit=100&offset=" + localStorage["offsetNumber"],
                        headers: { 'Authorization': 'Bearer ' + access_token },
                        dataType: "json",
                        data: "formdata",
                        success: function (currentPLData) {
                            $('#results').empty();
                            for (i = 0; i < currentPLData.items.length; i++) {
                                $('#results').append("" + currentPLData.items[i].track.artists[0].name + "
" + currentPLData.items[i].track.name + "
");
                            }

                            for (i = 0; i < localStorage["totalSongs"] + 1; i++) {
                                if (i >= localStorage["currentTrack"] && localStorage["currentTrack"] > 3) {
                                    document.getElementById("songLinkClick" + 4).style.color = "pink";
                                    $(".songLinkClick:gt(4)").css("color", "white");
                                }
                                else if (i >= localStorage["currentTrack"] && localStorage["currentTrack"] == 0) {
                                    document.getElementById("songLinkClick" + 0).style.color = "pink";
                                    $(".songLinkClick:gt(0)").css("color", "white");
                                }
                                else if (i >= localStorage["currentTrack"] && localStorage["currentTrack"] == 1) {
                                    document.getElementById("songLinkClick" + 1).style.color = "pink";
                                    $(".songLinkClick:gt(1)").css("color", "white");
                                }
                                else if (i >= localStorage["currentTrack"] && localStorage["currentTrack"] == 2) {
                                    document.getElementById("songLinkClick" + 2).style.color = "pink";
                                    $(".songLinkClick:gt(2)").css("color", "white");
                                }
                                else if (i >= localStorage["currentTrack"] && localStorage["currentTrack"] == 3) {
                                    document.getElementById("songLinkClick" + 3).style.color = "pink";
                                    $(".songLinkClick:gt(3)").css("color", "white");
                                }
                                $(document).on('taphold', '#songLinkClick' + i, function () {
                                    for (i = 0; i < localStorage["totalSongs"]; i++) {
                                        obj["range_start"] = parseInt($('#songLinkClick' + i).attr('alt'));
                                        obj["range_length"] = 1;
                                        obj["insert_before"] = parseInt(localStorage["currentTrack"]) + 1;
                                        console.log("Clicked");
                                    }
                                    $.ajax({
                                        type: "PUT",
                                        url: "https://api.spotify.com/v1/users/" + localStorage["userID"] + "/playlists/" + localStorage["Snapster"] + "/tracks",
                                        headers: { 'Authorization': 'Bearer ' + access_token },
                                        dataType: "json",
                                        data: JSON.stringify(obj),
                                        success: function (dataFirst) {
                                            partyPlaylist = [];
                                            $("#results").empty();
                                            $("#results").css("text-align", "center");
                                            console.log("Success");
                                            location.reload();
                                        }
                                    });
                                    console.log(obj);
                                });
                                $(document).on('click', '#songLinkClick' + i, function () {
                                    for (i = 0; i < localStorage["totalSongs"]; i++) {
                                        obj["range_start"] = parseInt($('#songLinkClick' + i).attr('alt'));
                                        obj["range_length"] = 1;
                                        obj["insert_before"] = parseInt(localStorage["currentTrack"]) + 1;
                                        console.log("Clicked");
                                    }
                                    $.ajax({
                                        type: "PUT",
                                        url: "https://api.spotify.com/v1/users/" + localStorage["userID"] + "/playlists/" + localStorage["Snapster"] + "/tracks",
                                        headers: { 'Authorization': 'Bearer ' + access_token },
                                        dataType: "json",
                                        data: JSON.stringify(obj),
                                        success: function (dataFirst) {
                                            partyPlaylist = [];
                                            $("#results").empty();
                                            $("#results").css("text-align", "center");
                                            console.log("Success");
                                            location.reload();
                                        }
                                    });
                                    console.log(obj);
                                });

                            }

                        }
                    });
                    playlists = [];
                    currentTracks = [];
                }
            }

        });

    }
});
<commit_msg>Update upcomingSongs.js<commit_after>$(document).ready(function () {
    $('#results').empty;
    var userID = localStorage['userID'];
    var Snapster;
    var playlists = [];
    var currentTracks = [];
    var j;
    var obj = {};
    var sendInfo;
    localStorage["totalSongs"] = 0;
    localStorage["currentlyPlayingWC"] = "";
    localStorage["currentlyPlaying"] = "";
    localStorage["currentTrack"] = 0;
    localStorage["offsetNumber"] = 0;
    partyPlaylist = 0;
    // $("#filename").focus(function (event) {
    $('#infoHeader').empty();
    $('#infoHeader').append("Upcoming Songs");
    if (localStorage.getItem("lastFM") != "null" || localStorage.getItem("lastFM") != "") {
        $.ajax({
            type: "GET",
            url: "https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=" + localStorage.getItem("lastFM") + "&api_key=9fc54977379828d52d1d779dc62f569b&format=json",
            dataType: "json",
            data: "formdata",
            success: function (currentData) {
                $('#footer2').append("" + currentData.recenttracks.track[0].artist['#text'] + " - " + "" + currentData.recenttracks.track[0].name + "" + "
");
                localStorage["currentlyPlaying"] = currentData.recenttracks.track[0].name.toUpperCase();
            }
        });
        $.ajax({
            type: "GET",
            url: "https://api.spotify.com/v1/users/" + userID + "/playlists/" + localStorage["Snapster"] + "/tracks",
            headers: { 'Authorization': 'Bearer ' + access_token },
            dataType: "json",
            data: "formdata",
            success: function (trackData) {
                currentTracks = [];
                for (i = 0; i < trackData.items.length; i++) {
                    currentTracks[i] = trackData.items[i].track.name.toUpperCase();
                }
                console.log(currentTracks);
                localStorage["totalSongs"] = currentTracks.length;
                localStorage["currentlyPlayingWC"] = localStorage["currentlyPlaying"].replace(/,/g, '');
                localStorage["currentTrack"] = currentTracks.indexOf(localStorage["currentlyPlayingWC"]);
                for (i = 0; i < currentTracks.length; i++) {
                    if (localStorage["currentTrack"] >= 5) {
                        localStorage["offsetNumber"] = localStorage["currentTrack"] - 4;
                    }
                    else {
                        localStorage["offsetNumber"] = 0;
                    }
                    currentTracks = [];
                }
            }
        });
        $.ajax({
            type: "GET",
            url: "https://api.spotify.com/v1/users/" + userID + "/playlists",
            headers: { 'Authorization': 'Bearer ' + access_token },
            dataType: "json",
            data: "formdata",
            success: function (data) {
                for (i = 0; i < data.items.length; i++) {
                    playlists.push(data.items[i].name);
                }
                partyPlaylist = playlists.indexOf("Partify");
                if (playlists.indexOf("Partify") != -1 && data.items[partyPlaylist].id === localStorage['Snapster']) {
                    for (i = 0; i < data.items.length; i++) {
                        localStorage['Snapster'] = data.items[partyPlaylist].id;
                        Snapster = localStorage['Snapster'];
                    }
                    $("#results").css("text-align", "center");
                    $.ajax( {
                        type: "GET",
                        url: "https://api.spotify.com/v1/users/" + userID + "/playlists/" + Snapster + "/tracks?limit=100&offset=" + localStorage["offsetNumber"],
                        headers: { 'Authorization': 'Bearer ' + access_token },
                        dataType: "json",
                        data: "formdata",
                        success: function (currentPLData) {
                            $('#results').empty();
                            for (i = 0; i < currentPLData.items.length; i++) {
                                $('#results').append("" + currentPLData.items[i].track.artists[0].name + "
" + currentPLData.items[i].track.name + "
");
                            }

                            for (i = 0; i < localStorage["totalSongs"] + 1; i++) {
                                if (i >= localStorage["currentTrack"] && localStorage["currentTrack"] > 3) {
                                    document.getElementById("songLinkClick" + 4).style.color = "pink";
                                    $(".songLinkClick:gt(4)").css("color", "white");
                                }
                                else if (i >= localStorage["currentTrack"] && localStorage["currentTrack"] == 0) {
                                    document.getElementById("songLinkClick" + 0).style.color = "pink";
                                    $(".songLinkClick:gt(0)").css("color", "white");
                                }
                                else if (i >= localStorage["currentTrack"] && localStorage["currentTrack"] == 1) {
                                    document.getElementById("songLinkClick" + 1).style.color = "pink";
                                    $(".songLinkClick:gt(1)").css("color", "white");
                                }
                                else if (i >= localStorage["currentTrack"] && localStorage["currentTrack"] == 2) {
                                    document.getElementById("songLinkClick" + 2).style.color = "pink";
                                    $(".songLinkClick:gt(2)").css("color", "white");
                                }
                                else if (i >= localStorage["currentTrack"] && localStorage["currentTrack"] == 3) {
                                    document.getElementById("songLinkClick" + 3).style.color = "pink";
                                    $(".songLinkClick:gt(3)").css("color", "white");
                                }
                                $(document).on('taphold', '#songLinkClick' + i, function () {
                                    for (i = 0; i < localStorage["totalSongs"]; i++) {
                                        obj["range_start"] = parseInt($('#songLinkClick' + i).attr('alt'));
                                        obj["range_length"] = 1;
                                        obj["insert_before"] = parseInt(localStorage["currentTrack"]) + 1;
                                        console.log("Clicked");
                                    }
                                    $.ajax({
                                        type: "PUT",
                                        url: "https://api.spotify.com/v1/users/" + localStorage["userID"] + "/playlists/" + localStorage["Snapster"] + "/tracks",
                                        headers: { 'Authorization': 'Bearer ' + access_token },
                                        dataType: "json",
                                        data: JSON.stringify(obj),
                                        success: function (dataFirst) {
                                            partyPlaylist = [];
                                            $("#results").empty();
                                            $("#results").css("text-align", "center");
                                            console.log("Success");
                                            location.reload();
                                        }
                                    });
                                    console.log(obj);
                                });
                                $(document).on('click', '#songLinkClick' + i, function () {
                                    for (i = 0; i < localStorage["totalSongs"]; i++) {
                                        obj["range_start"] = parseInt($('#songLinkClick' + i).attr('alt'));
                                        obj["range_length"] = 1;
                                        obj["insert_before"] = parseInt(localStorage["currentTrack"]) + 1;
                                        console.log("Clicked");
                                    }
                                    $.ajax({
                                        type: "PUT",
                                        url: "https://api.spotify.com/v1/users/" + localStorage["userID"] + "/playlists/" + localStorage["Snapster"] + "/tracks",
                                        headers: { 'Authorization': 'Bearer ' + access_token },
                                        dataType: "json",
                                        data: JSON.stringify(obj),
                                        success: function (dataFirst) {
                                            partyPlaylist = [];
                                            $("#results").empty();
                                            $("#results").css("text-align", "center");
                                            console.log("Success");
                                            location.reload();
                                        }
                                    });
                                    console.log(obj);
                                });

                            }

                        }
                    });
                    playlists = [];
                    currentTracks = [];
                }
            }

        });

    }
});
<|endoftext|>


<commit_before>'use strict';

describe('gameCreator', function() {
  var gameCreator;
  var learningProgress = {isLearnt: ()=>false};
  var puzzleBuilder = {buildFromPositionObject: ()=>({})};
  var positionSelector = {getNextPositionOfTheColor: ()=>{}};

  beforeEach(module('melissa.services'));
  beforeEach(module(function($provide) {
    $provide.value("learningProgress", learningProgress);
    $provide.value("puzzleBuilder", puzzleBuilder);
    $provide.value("positionSelector", positionSelector);
  }));
  beforeEach(inject(function (_gameCreator_) {
    gameCreator = _gameCreator_;
  }));

  describe('create', function() {
    it('ignores games with less than 10 moves', () => {
      var game = gameCreator.create({});
      expect(game).toEqual(null);
    });
  })

  describe('isBetter', function() {
    it('better to have longest game', function() {
      expect(gameCreator.isBetter([{},{}], [{}])).toBeTruthy();
    });
    it('better to have not-learnt positions', function() {
      spyOn(puzzleBuilder, 'buildFromPositionObject').and.callFake(position => position);
      spyOn(learningProgress, 'isLearnt').and.callFake((puzzle) => ({"a": true,"b": false}[puzzle]));
      var gameLongButLearnt = ["a", "a", "a"];
      var gameShortButNotLearnt = ["b"];
      expect(gameCreator.isBetter(gameLongButLearnt, gameShortButNotLearnt)).toBeFalsy();
    });
  })

  describe('getNotLearntPositionsCount', function() {
    beforeEach(() => {
      learningProgress.isLearnt = () => false;
    });
    it('return zero for empty game', function() {
      expect(gameCreator.getNotLearntPositionsCount([])).toBe(0);
    });
    it('returns game length if everything is not learnt', function() {
      expect(gameCreator.getNotLearntPositionsCount([{},{}])).toBe(2);
    });
    it('returns zero if a single position is learnt', function() {
      learningProgress.isLearnt = () => false;
      spyOn(learningProgress, 'isLearnt').and.returnValue(true);
      expect(gameCreator.getNotLearntPositionsCount([{}])).toBe(0);
    });
    it('counts as not learnt if there is no info about learning progress', () => {
      learningProgress.isLearnt = undefined;
      expect(gameCreator.getNotLearntPositionsCount([{}, {}, {}])).toBe(3);
    })
  })
})
<commit_msg>test fix<commit_after>'use strict';

describe('gameCreator', function() {
  var gameCreator;
  var learningProgress = {isLearnt: ()=>false};
  var puzzleBuilder = {buildFromPositionObject: ()=>({})};
  var positionSelector = {getNextPositionOfTheColor: ()=>{}};

  beforeEach(module('melissa.services'));
  beforeEach(module(function($provide) {
    $provide.value("learningProgress", learningProgress);
    $provide.value("puzzleBuilder", puzzleBuilder);
    $provide.value("positionSelector", positionSelector);
  }));
  beforeEach(inject(function (_gameCreator_) {
    gameCreator = _gameCreator_;
  }));

  describe('create', function() {
    it('ignores games with less than 10 moves', () => {
      var game = gameCreator.create({});
      expect(game).toEqual(null);
    });
  })

  describe('isBetter', function() {
    it('better to have longest game', function() {
      expect(gameCreator.isBetter([{},{}], [{}])).toBeTruthy();
    });
    it('better to have not-learnt positions', function() {
      spyOn(puzzleBuilder, 'buildFromPositionObject').and.callFake(position => position);
      learningProgress.isLearnt = (puzzle) => ({"a": true,"b": false}[puzzle]);
      var gameLongButLearnt = ["a", "a", "a"];
      var gameShortButNotLearnt = ["b"];
      expect(gameCreator.isBetter(gameLongButLearnt, gameShortButNotLearnt)).toBeFalsy();
    });
  })

  describe('getNotLearntPositionsCount', function() {
    beforeEach(() => {
      learningProgress.isLearnt = () => false;
    });
    it('return zero for empty game', function() {
      expect(gameCreator.getNotLearntPositionsCount([])).toBe(0);
    });
    it('returns game length if everything is not learnt', function() {
      expect(gameCreator.getNotLearntPositionsCount([{},{}])).toBe(2);
    });
    it('returns zero if a single position is learnt', function() {
      learningProgress.isLearnt = () => false;
      spyOn(learningProgress, 'isLearnt').and.returnValue(true);
      expect(gameCreator.getNotLearntPositionsCount([{}])).toBe(0);
    });
    it('counts as not learnt if there is no info about learning progress', () => {
      learningProgress.isLearnt = undefined;
      expect(gameCreator.getNotLearntPositionsCount([{}, {}, {}])).toBe(3);
    })
  })
})
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';
import { MethodHooks } from 'meteor/doctorpangloss:method-hooks';
import { lodash } from 'meteor/stevezhu:lodash';

MethodHooks.after('Games.addGame', (options) => {
	if (options.error) {
		return;
	} else if (options.result) {
		const gameId = options.result;

		let yourClubTeamId = Meteor.call('Teams.addTeam', gameId);
		let opponentTeamId = Meteor.call('Teams.addTeam', gameId);

		Meteor.call('Games.addTeamsId', gameId, yourClubTeamId, opponentTeamId);

		return options.result;
	}
});

MethodHooks.after('Games.deleteGame', (options) => {
	if (options.error) {
		return;
	} else if (options.result) {
		const gameId = options.arguments[0];

		Meteor.call('Teams.deleteTeams', gameId);
		Meteor.call('Players.deletePlayers', gameId);
		Meteor.call('Coachs.deleteCoachs', gameId);

		return options.result;
	}
});
<commit_msg>change variable from let to const<commit_after>import { Meteor } from 'meteor/meteor';
import { MethodHooks } from 'meteor/doctorpangloss:method-hooks';
import { lodash } from 'meteor/stevezhu:lodash';

MethodHooks.after('Games.addGame', (options) => {
	if (options.error) {
		return;
	} else if (options.result) {
		const gameId = options.result;

		const yourClubTeamId = Meteor.call('Teams.addTeam', gameId);
		const opponentTeamId = Meteor.call('Teams.addTeam', gameId);

		Meteor.call('Games.addTeamsId', gameId, yourClubTeamId, opponentTeamId);

		return options.result;
	}
});

MethodHooks.after('Games.deleteGame', (options) => {
	if (options.error) {
		return;
	} else if (options.result) {
		const gameId = options.arguments[0];

		Meteor.call('Teams.deleteTeams', gameId);
		Meteor.call('Players.deletePlayers', gameId);
		Meteor.call('Coachs.deleteCoachs', gameId);

		return options.result;
	}
});
<|endoftext|>


<commit_before>import { Meteor } from 'meteor/meteor';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
import _ from 'underscore';

import Works from './works';
import Books from './books';
import Tenants from './tenants';

/**
 * Comments are the primary data type of the commentaries. They represent
 * thoughts from commentators on the source text (such as a comment on a specific
 * line of Homer). They are also used for annotations on the CHS websites
 * @type {Meteor.Collection}
 */
const Comments = new Meteor.Collection('comments');

/**
 * Comments schema
 * @type {SimpleSchema}
 */
Comments.schema = new SimpleSchema({
	urn: {
		type: Object,
		optional: true,
	},

	originalDate: {
		type: Date,
		optional: true,
	},

	status: {
		type: String,
		optional: true,
	},

	wordpressId: {
		type: Number,
		optional: true,
	},

	tenantId: {
		type: String,
	},

	commenters: {
		type: [Object],
		optional: true,
	},

	'commenters.$._id': {
		type: String,
		optional: true,
	},

	'commenters.$.name': {
		type: String,
		optional: true,
	},

	'commenters.$.slug': {
		type: String,
		optional: true,
	},

	'commenters.$.wordpressId': {
		type: Number,
		optional: true,
	},

	users: {
		type: [String],
		optional: true,
	},

	work: {
		type: Object,
		optional: true,

	},

	'work.title': {
		type: String,
		optional: true,
	},

	'work.slug': {
		type: String,
		optional: true,
	},

	'work.order': {
		type: Number,
		optional: true,
	},

	subwork: {
		type: Object,
		optional: true,
	},

	'subwork.title': {
		type: String,
		optional: true,
	},

	'subwork.slug': {
		type: String,
		optional: true,
	},

	'subwork.n': {
		type: Number,
		optional: true,
	},

	lineFrom: {
		type: Number,
		optional: true,
	},

	lineTo: {
		type: Number,
		optional: true,
	},

	lineLetter: {
		type: String,
		optional: true,
	},

	bookChapterUrl: {
		type: String,
		optional: true,
	},

	paragraphN: {
		type: Number,
		optional: true,
	},

	nLines: {
		type: Number,
		optional: true,
	},

	commentOrder: {
		type: Number,
		optional: true,
	},

	parentCommentId: {
		type: String,
		optional: true,
	},

	referenceId: {
		type: String,
		optional: true,
	},

	referenceWorks: {
		type: [Object],
		optional: true,
	},

	'referenceWorks.$.referenceWorkId': {
		type: String,
		optional: true,
	},

	'referenceWorks.$.section': {
		type: Number,
		optional: true,
	},

	'referenceWorks.$.chapter': {
		type: Number,
		optional: true,
	},

	'referenceWorks.$.translation': {
		type: Number,
		optional: true,
	},

	'referenceWorks.$.note': {
		type: Number,
		optional: true,
	},

	keywords: {
		type: [Object],
		optional: true,
	},

	'keywords.$._id': {
		type: String,
		optional: true,
	},

	'keywords.$.wordpressId': {
		type: Number,
		optional: true,
	},

	'keywords.$.title': {
		type: String,
		optional: true,
	},

	'keywords.$.slug': {
		type: String,
		optional: true,
	},

	'keywords.$.description': {
		type: String,
		optional: true,
	},

	'keywords.$.descriptionRaw': {
		type: Object,
		optional: true,
	},

	'keywords.$.type': {
		type: String,
		optional: true,
	},

	'keywords.$.count': {
		type: Number,
		optional: true,
	},

	'keywords.$.work': {
		type: Object,
		optional: true,
	},

	'keywords.$.lineFrom': {
		type: Number,
		optional: true,
	},

	'keywords.$.lineTo': {
		type: Number,
		optional: true,
	},

	'keywords.$.lineLetters': {
		type: String,
		optional: true,
	},

	'keywords.$.nLines': {
		type: Number,
		optional: true,
	},

	'keywords.$.tenantId': {
		type: String,
		optional: true,
	},

	'keywords.$.isMentionedInLemma': {
		type: Boolean,
		optional: true,
	},

	revisions: {
		type: [Object],
		optional: true,
	},

	'revisions.$.title': {
		type: String,
		optional: true,
	},

	'revisions.$.text': {
		type: String,
		optional: true,
	},

	'revisions.$.textRaw': {
		type: Object,
		optional: true,
		blackbox: true,
	},

	'revisions.$.originalDate': {
		type: Date,
		optional: true,
	},

	'revisions.$.created': {
		type: Date,
		optional: true,
	},

	discussionComments: {
		type: [Object],
		optional: true,
	},

	isAnnotation: {
		type: Boolean,
		optional: true,
	},

	discussionCommentsDisabled: {
		type: Boolean,
		optional: true,
	},

	created: {
		type: Date,
		optional: true,
	},

	updated: {
		type: Date,
		optional: true,
	},
});

Comments.attachSchema(Comments.schema);

Comments.attachBehaviour('timestampable', {
	createdAt: 'created',
	createdBy: 'createdBy',
	updatedAt: 'updated',
	updatedBy: 'updatedBy'
});

const COMMENT_ID_LENGTH = 7;

const _getCommentURN = (comment) => {
	const work = Works.findOne({ slug: comment.work.slug }),
	tenant = Tenants.findOne({_id: comment.tenantId}),
	urnPrefixV1 = 'urn:cts:CHS.Commentary',
	urnPrefixV2 = 'urn:cts:CHS:Commentaries.' + tenant.subdomain.toUpperCase();
	// Use work tlg if it exists, otherwise, search for subwork tlg number
	// Failing either, just use creator
	let urnTLG = work.tlgCreator;
	if (work.tlg && work.tlg.length) {
		urnTLG += `.${work.tlg}`;
	} else {
		work.subworks.forEach((subwork) => {
			if (
					subwork.n === comment.subwork.n
				&& subwork.tlgNumber
				&& subwork.tlgNumber.length
			) {
				urnTLG += `.${subwork.tlgNumber}`;
			}
		});
	}

	//
	urnTLG += '.chsCommentary';
	const workTitle = comment.work.title.replace(' ', '');

	let urnComment = `${workTitle}.${comment.subwork.title}.${comment.lineFrom}`;

	if (typeof comment.lineTo !== 'undefined' && comment.lineFrom !== comment.lineTo) {
		urnComment += `-${comment.subwork.title}.${comment.lineTo}`;
	}

	const urnCommentId = `${comment._id.slice(-COMMENT_ID_LENGTH)}`;
	return {
		 'v1': `${urnPrefixV1}:${urnComment}.${urnCommentId}`,
		 'v2': `${urnPrefixV2}:${urnComment}.${urnCommentId}`};
};

const _getAnnotationURN = (comment) => {
	const book = Books.findOne({ 'chapters.url': comment.bookChapterUrl }),
	chapter = _.find(book.chapters, c => c.url === comment.bookChapterUrl),
	tenant = Tenants.findOne({_id: comment.tenantId}),
	urnPrefixV1 = 'urn:cts:CHS.Annotations',
	urnPrefixV2 = 'urn:cts:CHS:Annotations.' + tenant.subdomain.toUpperCase(),
	urnBook = `${book.authorURN}.${book.slug}`,
	urnComment = `${chapter.n}.${comment.paragraphN}`,
	urnCommentId = `${comment._id.slice(-COMMENT_ID_LENGTH)}`;

	return {
		'v1': `${urnPrefixV1}:${urnComment}.${urnCommentId}`,
	 	'v2': `${urnPrefixV2}:${urnComment}.${urnCommentId}`};
};

function getURN(comment) {
	if (comment.isAnnotation) {
		return _getAnnotationURN(comment);
	}

	return _getCommentURN(comment);
}

// hooks:
Comments.before.insert((userId, doc) => {
	doc.urn = getURN(doc);
});

Comments.before.update((userId, doc, fieldNames, modifier, options) => {
	modifier.$set.urn = getURN(doc);
});

export default Comments;
export { getURN };
<commit_msg>add _id to revisions in comments schema<commit_after>import { Meteor } from 'meteor/meteor';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
import _ from 'underscore';

import Works from './works';
import Books from './books';
import Tenants from './tenants';

/**
 * Comments are the primary data type of the commentaries. They represent
 * thoughts from commentators on the source text (such as a comment on a specific
 * line of Homer). They are also used for annotations on the CHS websites
 * @type {Meteor.Collection}
 */
const Comments = new Meteor.Collection('comments');

/**
 * Comments schema
 * @type {SimpleSchema}
 */
Comments.schema = new SimpleSchema({
	urn: {
		type: Object,
		optional: true,
	},

	originalDate: {
		type: Date,
		optional: true,
	},

	status: {
		type: String,
		optional: true,
	},

	wordpressId: {
		type: Number,
		optional: true,
	},

	tenantId: {
		type: String,
	},

	commenters: {
		type: [Object],
		optional: true,
	},

	'commenters.$._id': {
		type: String,
		optional: true,
	},

	'commenters.$.name': {
		type: String,
		optional: true,
	},

	'commenters.$.slug': {
		type: String,
		optional: true,
	},

	'commenters.$.wordpressId': {
		type: Number,
		optional: true,
	},

	users: {
		type: [String],
		optional: true,
	},

	work: {
		type: Object,
		optional: true,

	},

	'work.title': {
		type: String,
		optional: true,
	},

	'work.slug': {
		type: String,
		optional: true,
	},

	'work.order': {
		type: Number,
		optional: true,
	},

	subwork: {
		type: Object,
		optional: true,
	},

	'subwork.title': {
		type: String,
		optional: true,
	},

	'subwork.slug': {
		type: String,
		optional: true,
	},

	'subwork.n': {
		type: Number,
		optional: true,
	},

	lineFrom: {
		type: Number,
		optional: true,
	},

	lineTo: {
		type: Number,
		optional: true,
	},

	lineLetter: {
		type: String,
		optional: true,
	},

	bookChapterUrl: {
		type: String,
		optional: true,
	},

	paragraphN: {
		type: Number,
		optional: true,
	},

	nLines: {
		type: Number,
		optional: true,
	},

	commentOrder: {
		type: Number,
		optional: true,
	},

	parentCommentId: {
		type: String,
		optional: true,
	},

	referenceId: {
		type: String,
		optional: true,
	},

	referenceWorks: {
		type: [Object],
		optional: true,
	},

	'referenceWorks.$.referenceWorkId': {
		type: String,
		optional: true,
	},

	'referenceWorks.$.section': {
		type: Number,
		optional: true,
	},

	'referenceWorks.$.chapter': {
		type: Number,
		optional: true,
	},

	'referenceWorks.$.translation': {
		type: Number,
		optional: true,
	},

	'referenceWorks.$.note': {
		type: Number,
		optional: true,
	},

	keywords: {
		type: [Object],
		optional: true,
	},

	'keywords.$._id': {
		type: String,
		optional: true,
	},

	'keywords.$.wordpressId': {
		type: Number,
		optional: true,
	},

	'keywords.$.title': {
		type: String,
		optional: true,
	},

	'keywords.$.slug': {
		type: String,
		optional: true,
	},

	'keywords.$.description': {
		type: String,
		optional: true,
	},

	'keywords.$.descriptionRaw': {
		type: Object,
		optional: true,
	},

	'keywords.$.type': {
		type: String,
		optional: true,
	},

	'keywords.$.count': {
		type: Number,
		optional: true,
	},

	'keywords.$.work': {
		type: Object,
		optional: true,
	},

	'keywords.$.lineFrom': {
		type: Number,
		optional: true,
	},

	'keywords.$.lineTo': {
		type: Number,
		optional: true,
	},

	'keywords.$.lineLetters': {
		type: String,
		optional: true,
	},

	'keywords.$.nLines': {
		type: Number,
		optional: true,
	},

	'keywords.$.tenantId': {
		type: String,
		optional: true,
	},

	'keywords.$.isMentionedInLemma': {
		type: Boolean,
		optional: true,
	},

	revisions: {
		type: [Object],
		optional: true,
	},

	'revisions.$._id': {
		type: String,
		optional: true,
	},

	'revisions.$.title': {
		type: String,
		optional: true,
	},

	'revisions.$.text': {
		type: String,
		optional: true,
	},

	'revisions.$.textRaw': {
		type: Object,
		optional: true,
		blackbox: true,
	},

	'revisions.$.originalDate': {
		type: Date,
		optional: true,
	},

	'revisions.$.created': {
		type: Date,
		optional: true,
	},

	discussionComments: {
		type: [Object],
		optional: true,
	},

	isAnnotation: {
		type: Boolean,
		optional: true,
	},

	discussionCommentsDisabled: {
		type: Boolean,
		optional: true,
	},

	created: {
		type: Date,
		optional: true,
	},

	updated: {
		type: Date,
		optional: true,
	},
});

Comments.attachSchema(Comments.schema);

Comments.attachBehaviour('timestampable', {
	createdAt: 'created',
	createdBy: 'createdBy',
	updatedAt: 'updated',
	updatedBy: 'updatedBy'
});

const COMMENT_ID_LENGTH = 7;

const _getCommentURN = (comment) => {
	const work = Works.findOne({ slug: comment.work.slug }),
	tenant = Tenants.findOne({_id: comment.tenantId}),
	urnPrefixV1 = 'urn:cts:CHS.Commentary',
	urnPrefixV2 = 'urn:cts:CHS:Commentaries.' + tenant.subdomain.toUpperCase();
	// Use work tlg if it exists, otherwise, search for subwork tlg number
	// Failing either, just use creator
	let urnTLG = work.tlgCreator;
	if (work.tlg && work.tlg.length) {
		urnTLG += `.${work.tlg}`;
	} else {
		work.subworks.forEach((subwork) => {
			if (
					subwork.n === comment.subwork.n
				&& subwork.tlgNumber
				&& subwork.tlgNumber.length
			) {
				urnTLG += `.${subwork.tlgNumber}`;
			}
		});
	}

	//
	urnTLG += '.chsCommentary';
	const workTitle = comment.work.title.replace(' ', '');

	let urnComment = `${workTitle}.${comment.subwork.title}.${comment.lineFrom}`;

	if (typeof comment.lineTo !== 'undefined' && comment.lineFrom !== comment.lineTo) {
		urnComment += `-${comment.subwork.title}.${comment.lineTo}`;
	}

	const urnCommentId = `${comment._id.slice(-COMMENT_ID_LENGTH)}`;
	return {
		 'v1': `${urnPrefixV1}:${urnComment}.${urnCommentId}`,
		 'v2': `${urnPrefixV2}:${urnComment}.${urnCommentId}`};
};

const _getAnnotationURN = (comment) => {
	const book = Books.findOne({ 'chapters.url': comment.bookChapterUrl }),
	chapter = _.find(book.chapters, c => c.url === comment.bookChapterUrl),
	tenant = Tenants.findOne({_id: comment.tenantId}),
	urnPrefixV1 = 'urn:cts:CHS.Annotations',
	urnPrefixV2 = 'urn:cts:CHS:Annotations.' + tenant.subdomain.toUpperCase(),
	urnBook = `${book.authorURN}.${book.slug}`,
	urnComment = `${chapter.n}.${comment.paragraphN}`,
	urnCommentId = `${comment._id.slice(-COMMENT_ID_LENGTH)}`;

	return {
		'v1': `${urnPrefixV1}:${urnComment}.${urnCommentId}`,
	 	'v2': `${urnPrefixV2}:${urnComment}.${urnCommentId}`};
};

function getURN(comment) {
	if (comment.isAnnotation) {
		return _getAnnotationURN(comment);
	}

	return _getCommentURN(comment);
}

// hooks:
Comments.before.insert((userId, doc) => {
	doc.urn = getURN(doc);
});

Comments.before.update((userId, doc, fieldNames, modifier, options) => {
	modifier.$set.urn = getURN(doc);
});

export default Comments;
export { getURN };
<|endoftext|>


<commit_before>import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';

import { Patients } from '../api/patients.js';
import {Datasample_second} from '../api/patients.js';
import {Assesment} from '../api/patients.js';

import { patientHasAllergies } from '../api/demographic.js'
// import { temperature_color } from 'patient_info_ui.js'

import './patient_info.html';
import './patient_info.css';
// import './patient_info_ui.js';
const patient_tile_styles = require('./patient_info_ui.js');

// This dumy patient is just to represent the "empty template"
// meaning giving "fake" context data to the template
const dummy_patient = {
	"_id" : '000',
	"lastName" : "no name",
	"firstName" : "no name",
	"gender" : "?",
	"birthDate" : new Date(),
	"maritalStatus" : "?",
	"race" : "?",
	"allergies" : "none",
	"height" : 0,
	"weight" : 0
}

Template.patient_info.helpers({
  //returns the information of a single patient
   patient() {
   	//return a single patient for template data context
   	const instance = Template.instance();
    if (instance.state.get('patientID')) {//check patient that has been selected on the dropdown
      const patientID = instance.state.get('patientID');
      return Patients.findOne({'patientID' : Number(patientID)});
    }
    // return Patients.findOne();
    return dummy_patient;
  }
  //returns all patients
   ,patients() {
    // return Patients.find({});
    return Patients.find({}, {sort : {'lastName':1, 'firstName' : 1} });
  }
  ,datasamples(){
    const instance = Template.instance();
    let data = undefined
    if (instance.state.get('patientID')) {
        const patientID = instance.state.get('patientID');
        //find returns a cursor, so we need to use fetch, to convert to array.
        // We are limiting to only one (the latest) sample --> array notation to get the object from the array
        data = Datasample_second.find({'patientID' : Number(patientID)} , {sort : {'timestamp' : -1}, limit : 1}).fetch()[0];
    }

    const temp_avg = data === undefined || data.temperature === undefined ? '-' : data.temperature.sum / data.temperature.count;
    const bp_sys_avg = data === undefined || data.blood_pressure_sys === undefined ? '-' : data.blood_pressure_sys.sum / data.blood_pressure_sys.count;
    const bp_dias_avg = data === undefined || data.blood_pressure_dias === undefined ? '-' : data.blood_pressure_dias.sum / data.blood_pressure_dias.count;
    const hr_avg = data === undefined || data.heart_rate === undefined ? '-' : data.heart_rate.sum / data.heart_rate.count;
    const spo2_avg = data === undefined || data.spo2 === undefined ? '-' : data.spo2.sum / data.spo2.count;
    const pr_avg = data === undefined || data.pulse_rate === undefined ? '-' : data.pulse_rate.sum / data.pulse_rate.count;

    data_sample = {
      temperature : temp_avg
      ,blood_pressure_sys : bp_sys_avg
      ,blood_pressure_dias : bp_dias_avg
      ,heart_rate : hr_avg
      ,spo2_sat : spo2_avg
      ,pulse_rate : pr_avg
    }

    // console.log(data_sample)

    return data_sample;

  }

  ,calc_age() {
//calculate age. See http://stackoverflow.com/a/21984136/3961519
	if (this.birthDate == undefined)
	return '' ;

  	const ageDifMs = Date.now() - this.birthDate.getTime();
    const ageDate = new Date(ageDifMs); // miliseconds from epoch
    return Math.abs(ageDate.getUTCFullYear() - 1970);
  }
  ,hasAllergies () {
  	return patientHasAllergies(this);
  }
  ,noAllergies(){
  	return !patientHasAllergies(this);
  }

  ,getTemperatureColor(temperature){
// if (undefined != this.temperature) {}
    return patient_tile_styles.temperature_color(temperature);
  }

  // returns a patient assesment base on their metrics
  // this function returns a JSON object with
  //  - color : background color to display in the UI:
  //		Healthy green : textcolor: '#0f3d0f, backgroundcolor : '#47d147',
  //		Alert Yellow  : textcolor: #8a6d3b,  backgroundcolor: #ffff00;
  //		Danger Red    : textcolor: #fff, 	 backgroundcolor: #ff0000;
  //		Info blue     : textcolor: #31708f;  backgroundcolor: #d9edf7;
  //  - message : message to display to the clinical staff
  ,patientAssesment() {
    let patientdata = undefined;
    const instance = Template.instance();
    if (instance.state.get('patientID')) {
        const patientID = instance.state.get('patientID');
        //find returns a cursor, so we need to use fetch, to convert to array.
        // We are limiting to only one (the latest) sample --> array notation to get the object from the array
        patientdata = Datasample_second.find({'patientID' : Number(patientID)} , {sort : {'timestamp' : -1}, limit : 1}).fetch()[0];
    }
    return patient_tile_styles.patient_assesment(patientdata);

  }

//returns the formated date of the latest assesment for this patient
  ,lastAssesment(){
    let lastestAssesment = "N.A.";
    const instance = Template.instance();
    if (instance.state.get('patientID')) {
        const patientID = instance.state.get('patientID');
        // lastDate = Assesment.find({'patientID' : Number(patientID)} , {sort : {'assement_date' : -1}, limit : 1}).fetch()[0];
        lastestAssesment = Assesment.find({'patientID' : Number(patientID)}, {sort : {'assement_date' : -1}, limit : 1}).fetch()[0];
    }
    if(undefined != lastestAssesment && "N.A." != lastestAssesment){
      //using moment library to format date : https://atmospherejs.com/momentjs/moment
          return moment(lastestAssesment.assement_date).format('MM/DD/YY HH:mm:ss');
    }else{
      return lastestAssesment;
    }

  }

});

// // Auxiliarify function to reuse functionality.
// // returns 'true' if the patient has allergies
// // (the parameter patient object has an allergies field and its content is not 'none')
// patientHasAllergies = function(patient){
// 	if (patient === undefined || patient.allergies === undefined)
//   		return false;
//   	if (patient.allergies == null || patient.allergies.trim() === '' || patient.allergies === 'none')
//   		return false;

//   	return true;
// }

Template.patient_info.events({
	 "change #patient-select": function (event, template) {
        var patientID = template.$(event.currentTarget).val();
        template.state.set('patientID', patientID);
        // console.log(patientID);
    }
    ,"click #assespatient" : function(){
      const patientID = Template.instance().state.get('patientID');
      // const now = Date.now();
      // console.log(patientID);

      // Insert an assesment into the collection
      if(patientID != undefined){
        Meteor.call('assesment.insert', patientID);
      }

    }

});

Template.patient_info.onCreated(function piOnCreated() {
  //subscriptions
  Meteor.subscribe('patients_demo');
  Meteor.subscribe('datasample_second');
  Meteor.subscribe('assesment');
  this.state = new ReactiveDict();

});<commit_msg>Improved message when the is no patient selelcted or no data for the patient<commit_after>import { Template } from 'meteor/templating';
import { ReactiveDict } from 'meteor/reactive-dict';

import { Patients } from '../api/patients.js';
import {Datasample_second} from '../api/patients.js';
import {Assesment} from '../api/patients.js';

import { patientHasAllergies } from '../api/demographic.js'
// import { temperature_color } from 'patient_info_ui.js'

import './patient_info.html';
import './patient_info.css';
// import './patient_info_ui.js';
const patient_tile_styles = require('./patient_info_ui.js');

// This dumy patient is just to represent the "empty template"
// meaning giving "fake" context data to the template
const dummy_patient = {
	"_id" : '000',
	"lastName" : "no name",
	"firstName" : "no name",
	"gender" : "?",
	"birthDate" : new Date(),
	"maritalStatus" : "?",
	"race" : "?",
	"allergies" : "none",
	"height" : 0,
	"weight" : 0
}

Template.patient_info.helpers({
  //returns the information of a single patient
   patient() {
   	//return a single patient for template data context
   	const instance = Template.instance();
    if (instance.state.get('patientID')) {//check patient that has been selected on the dropdown
      const patientID = instance.state.get('patientID');
      return Patients.findOne({'patientID' : Number(patientID)});
    }
    // return Patients.findOne();
    return dummy_patient;
  }
  //returns all patients
   ,patients() {
    // return Patients.find({});
    return Patients.find({}, {sort : {'lastName':1, 'firstName' : 1} });
  }
  ,datasamples(){
    const instance = Template.instance();
    let data = undefined
    if (instance.state.get('patientID')) {
        const patientID = instance.state.get('patientID');
        //find returns a cursor, so we need to use fetch, to convert to array.
        // We are limiting to only one (the latest) sample --> array notation to get the object from the array
        data = Datasample_second.find({'patientID' : Number(patientID)} , {sort : {'timestamp' : -1}, limit : 1}).fetch()[0];
    }

    const temp_avg = data === undefined || data.temperature === undefined ? '-' : data.temperature.sum / data.temperature.count;
    const bp_sys_avg = data === undefined || data.blood_pressure_sys === undefined ? '-' : data.blood_pressure_sys.sum / data.blood_pressure_sys.count;
    const bp_dias_avg = data === undefined || data.blood_pressure_dias === undefined ? '-' : data.blood_pressure_dias.sum / data.blood_pressure_dias.count;
    const hr_avg = data === undefined || data.heart_rate === undefined ? '-' : data.heart_rate.sum / data.heart_rate.count;
    const spo2_avg = data === undefined || data.spo2 === undefined ? '-' : data.spo2.sum / data.spo2.count;
    const pr_avg = data === undefined || data.pulse_rate === undefined ? '-' : data.pulse_rate.sum / data.pulse_rate.count;

    data_sample = {
      temperature : temp_avg
      ,blood_pressure_sys : bp_sys_avg
      ,blood_pressure_dias : bp_dias_avg
      ,heart_rate : hr_avg
      ,spo2_sat : spo2_avg
      ,pulse_rate : pr_avg
    }

    // console.log(data_sample)

    return data_sample;

  }

  ,calc_age() {
//calculate age. See http://stackoverflow.com/a/21984136/3961519
	if (this.birthDate == undefined)
	return '' ;

  	const ageDifMs = Date.now() - this.birthDate.getTime();
    const ageDate = new Date(ageDifMs); // miliseconds from epoch
    return Math.abs(ageDate.getUTCFullYear() - 1970);
  }
  ,hasAllergies () {
  	return patientHasAllergies(this);
  }
  ,noAllergies(){
  	return !patientHasAllergies(this);
  }

  ,getTemperatureColor(temperature){
// if (undefined != this.temperature) {}
    return patient_tile_styles.temperature_color(temperature);
  }

  // returns a patient assesment base on their metrics
  // this function returns a JSON object with
  //  - color : background color to display in the UI:
  //		Healthy green : textcolor: '#0f3d0f, backgroundcolor : '#47d147',
  //		Alert Yellow  : textcolor: #8a6d3b,  backgroundcolor: #ffff00;
  //		Danger Red    : textcolor: #fff, 	 backgroundcolor: #ff0000;
  //		Info blue     : textcolor: #31708f;  backgroundcolor: #d9edf7;
  //  - message : message to display to the clinical staff
  ,patientAssesment() {
    let patientdata = undefined;
    const instance = Template.instance();
    if (instance.state.get('patientID')) {
        const patientID = instance.state.get('patientID');
        //find returns a cursor, so we need to use fetch, to convert to array.
        // We are limiting to only one (the latest) sample --> array notation to get the object from the array
        patientdata = Datasample_second.find({'patientID' : Number(patientID)} , {sort : {'timestamp' : -1}, limit : 1}).fetch()[0];
    }
    return patient_tile_styles.patient_assesment(patientdata);

  }

//returns the formated date of the latest assesment for this patient
  ,lastAssesment(){
    let lastestAssesment = "N.A.";
    const instance = Template.instance();
    if (instance.state.get('patientID')) {
        const patientID = instance.state.get('patientID');
        // lastDate = Assesment.find({'patientID' : Number(patientID)} , {sort : {'assement_date' : -1}, limit : 1}).fetch()[0];
        lastestAssesment = Assesment.find({'patientID' : Number(patientID)}, {sort : {'assement_date' : -1}, limit : 1}).fetch()[0];
    }
    if(undefined != lastestAssesment && "N.A." != lastestAssesment){
      //using moment library to format date : https://atmospherejs.com/momentjs/moment
          return moment(lastestAssesment.assement_date).format('MM/DD/YY HH:mm:ss');
    }else{
      lastestAssesment = "N.A.";
      return lastestAssesment;
    }

  }

});

// // Auxiliarify function to reuse functionality.
// // returns 'true' if the patient has allergies
// // (the parameter patient object has an allergies field and its content is not 'none')
// patientHasAllergies = function(patient){
// 	if (patient === undefined || patient.allergies === undefined)
//   		return false;
//   	if (patient.allergies == null || patient.allergies.trim() === '' || patient.allergies === 'none')
//   		return false;

//   	return true;
// }

Template.patient_info.events({
	 "change #patient-select": function (event, template) {
        var patientID = template.$(event.currentTarget).val();
        template.state.set('patientID', patientID);
        // console.log(patientID);
    }
    ,"click #assespatient" : function(){
      const patientID = Template.instance().state.get('patientID');
      // const now = Date.now();
      // console.log(patientID);

      // Insert an assesment into the collection
      if(patientID != undefined){
        Meteor.call('assesment.insert', patientID);
      }

    }

});

Template.patient_info.onCreated(function piOnCreated() {
  //subscriptions
  Meteor.subscribe('patients_demo');
  Meteor.subscribe('datasample_second');
  Meteor.subscribe('assesment');
  this.state = new ReactiveDict();

});<|endoftext|>


<commit_before>/* ===========================================================
 * bootstrap-confirmation.js v1.0.1
 * http://ethaizone.github.io/Bootstrap-Confirmation/
 * ===========================================================
 * Copyright 2013 Nimit Suwannagate <ethaizone@hotmail.com>
 *
 * 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.
 * =========================================================== */

!function ($) {

	"use strict"; // jshint ;_;

 /* CONFIRMATION PUBLIC CLASS DEFINITION
	* =============================== */

	//var for check event at body can have only one.
	var event_body = false;

	var Confirmation = function (element, options) {
		var that = this;

		// remove href attribute of button
		$(element).removeAttr('href')

		this.init('confirmation', element, options)

		$(element).on('show', function(e) {
			var options = that.options;
			var all = options.all_selector;
			if(options.singleton) {
				$(all).not(that.$element).confirmation('hide');
			}
		});

		$(element).on('shown', function(e) {
			var options = that.options;
			var all = options.all_selector;
			$(this).next('.popover').one('click.dismiss.confirmation', '[data-dismiss="confirmation"]', $.proxy(that.hide, that))
			if(that.isPopout()) {
				if(!event_body) {
					event_body = $('body').on('click', function (e) {
						if($(all).is(e.target)) return;
						if($(all).next('div').has(e.target).length) return;

						$(all).confirmation('hide');
						$('body').unbind(e);
						event_body = false;

						return;
					});
				}
			}
		});
	}

	/* NOTE: CONFIRMATION EXTENDS BOOTSTRAP-TOOLTIP.js
		 ========================================== */

	Confirmation.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype, {

		constructor: Confirmation

		, setContent: function () {
				var $tip = this.tip()
					, title = this.getTitle()
					, href = this.getHref()
					, target = this.getTarget()
					, $e = this.$element
					, btnOkClass = this.getBtnOkClass()
					, btnCancelClass = this.getBtnCancelClass()
					, btnOkLabel = this.getBtnOkLabel()
					, btnCancelLabel = this.getBtnCancelLabel()
					, o = this.options

				$tip.find('.popover-title').text(title);

				var btnOk = $tip.find('.popover-content > div > a:not([data-dismiss="confirmation"])');
				var btnCancel = $tip.find('.popover-content > div > a[data-dismiss="confirmation"]');

				btnOk.addClass(btnOkClass).html(btnOkLabel).attr('href', href).attr('target', target).on('click', o.onConfirm);
				btnCancel.addClass(btnCancelClass).html(btnCancelLabel).on('click', o.onCancel);

				$tip.removeClass('fade top bottom left right in')
			}

		, hasContent: function () {
				return this.getTitle()
			}

		, isPopout: function () {
				var popout
					, $e = this.$element
					, o = this.options

				popout = $e.attr('data-popout') || (typeof o.popout == 'function' ? o.popout.call($e[0]) :	o.popout)

				if(popout == 'false') popout = false;

				return popout
			}

		, getHref: function () {
				var href
					, $e = this.$element
					, o = this.options

				href = $e.attr('data-href') || (typeof o.href == 'function' ? o.href.call($e[0]) :	o.href)

				return href
			}

		, getTarget: function () {
				var target
					, $e = this.$element
					, o = this.options

				target = $e.attr('data-target') || (typeof o.target == 'function' ? o.target.call($e[0]) :	o.target)

				return target
			}

		, getBtnOkClass: function () {
				var btnOkClass
					, $e = this.$element
					, o = this.options

				btnOkClass = $e.attr('data-btnOkClass') || (typeof o.btnOkClass == 'function' ? o.btnOkClass.call($e[0]) :	o.btnOkClass)

				return btnOkClass
			}

		, getBtnCancelClass: function () {
				var btnCancelClass
					, $e = this.$element
					, o = this.options

				btnCancelClass = $e.attr('data-btnCancelClass') || (typeof o.btnCancelClass == 'function' ? o.btnCancelClass.call($e[0]) :	o.btnCancelClass)

				return btnCancelClass
			}

		, getBtnOkLabel: function () {
				var btnOkLabel
					, $e = this.$element
					, o = this.options

				btnOkLabel = $e.attr('data-btnOkLabel') || (typeof o.btnOkLabel == 'function' ? o.btnOkLabel.call($e[0]) :	o.btnOkLabel)

				return btnOkLabel
			}

		, getBtnCancelLabel: function () {
				var btnCancelLabel
					, $e = this.$element
					, o = this.options

				btnCancelLabel = $e.attr('data-btnCancelLabel') || (typeof o.btnCancelLabel == 'function' ? o.btnCancelLabel.call($e[0]) :	o.btnCancelLabel)

				return btnCancelLabel
			}

		, tip: function () {
				this.$tip = this.$tip || $(this.options.template)
				return this.$tip
			}

		, destroy: function () {
				this.hide().$element.off('.' + this.type).removeData(this.type)
			}

	})

 /* CONFIRMATION PLUGIN DEFINITION
	* ======================= */

	var old = $.fn.confirmation

	$.fn.confirmation = function (option) {
		var that = this
		return this.each(function () {
			var $this = $(this)
				, data = $this.data('confirmation')
				, options = typeof option == 'object' && option
			options = options || {}
			options.all_selector = that.selector
			if (!data) $this.data('confirmation', (data = new Confirmation(this, options)))
			if (typeof option == 'string') data[option]()
		})
	}

	$.fn.confirmation.Constructor = Confirmation

	$.fn.confirmation.defaults = $.extend({} , $.fn.tooltip.defaults, {
		placement: 'top'
		, trigger: 'click'
		, target : '_self'
		, href   : '#'
		, title: 'Are you sure?'
		, template: '
' +
				'

' +
				'

' +
				'
' +
				'
' +
				'' +
				'' +
				'
' +
				'
' +
				'
'
		, btnOkClass:  'btn-primary'
		, btnCancelClass:  ''
		, btnOkLabel: ' Yes'
		, btnCancelLabel: ' No'
		, singleton: false
		, popout: false
		, onConfirm: function(){}
		, onCancel: function(){}
	})

 /* POPOVER NO CONFLICT
	* =================== */

	$.fn.confirmation.noConflict = function () {
		$.fn.confirmation = old
		return this
	}

}(window.jQuery);
<commit_msg>Update bootstrap-confirmation plugin which for bootstrap 3.x. got here https://github.com/mistic100/Bootstrap-Confirmation/blob/master/bootstrap-confirmation.js<commit_after>/* ========================================================================
 * bootstrap-confirmation.js v2.0.0
 * https://github.com/mistic100/Bootstrap-Confirmation
 * ========================================================================
 * Copyright 2013 Nimit Suwannagate <ethaizone@hotmail.com>
 * Copyright 2014 Damien "Mistic" Sorel <http://www.strangeplanet.fr>
 *
 * 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.
 * ======================================================================== */

+function ($) {
  'use strict';

  // Confirmation extends popover.js
  if (!$.fn.popover) throw new Error('Confirmation requires popover.js');

  // CONFIRMATION PUBLIC CLASS DEFINITION
  // ===============================

  var eventBody = false;

  var Confirmation = function (element, options) {
    this.init('confirmation', element, options);

    var that = this;

    // get existing href and target
    if (this.$element.attr('href')) {
      this.options.href = this.$element.attr('href');
      this.$element.removeAttr('href');
      if (this.$element.attr('target')) {
        this.options.target = this.$element.attr('target');
      }
    }

    // cancel original event
    this.$element.on(that.options.trigger, function(e, ack) {
      if (!ack) {
        e.preventDefault();
        e.stopPropagation();
        e.stopImmediatePropagation();
      }
    });

    // trigger original event on confirm
    this.$element.on('confirmed.bs.confirmation', function(e) {
      $(this).trigger(that.options.trigger, [true]);
    });

    // manage singleton
    this.$element.on('show.bs.confirmation', function(e) {
      var o = that.options
      if (o.singleton) {
        $(o._all_selector).not(that.$element).confirmation('hide')
      }
    });

    // manage popout
    this.$element.on('shown.bs.confirmation', function(e) {
      var o = that.options;
      if (o.popout && !eventBody) {
        eventBody = $('body').on('click', function (e) {
          if ($(o._all_selector).is(e.target)) return;
          $(o._all_selector).confirmation('hide');

          $('body').off(e);
          eventBody = false;
        });
      }
    });
  }

  Confirmation.DEFAULTS = $.extend({}, $.fn.popover.Constructor.DEFAULTS, {
    placement: 'top',
    title: 'Are you sure?',
	html: true,
    href: false,
    popout: false,
    singleton: false,
    target: '_self',
    onConfirm: $.noop,
    onCancel: $.noop,
    btnOkClass: 'btn-xs btn-primary',
    btnOkIcon: 'glyphicon glyphicon-ok',
    btnOkLabel: 'Yes',
    btnCancelClass: 'btn-xs btn-default',
    btnCancelIcon: 'glyphicon glyphicon-remove',
    btnCancelLabel: 'No',
    template:
      '
' +
        '

' +
        '

' +
        '
'+
          '
'+
            ''+
            ''+
          '
'+
        '
'+
      '
'
  });

  Confirmation.prototype = $.extend({}, $.fn.popover.Constructor.prototype);

  Confirmation.prototype.constructor = Confirmation;

  Confirmation.prototype.getDefaults = function () {
    return Confirmation.DEFAULTS;
  };

  Confirmation.prototype.setContent = function () {
    var that    = this;
    var $tip    = this.tip();
    var title   = this.getTitle();
	var o		= this.options;

    $tip.find('.popover-title')[o.html ? 'html' : 'text'](title);

    // configure 'ok' button
    $tip.find('[data-apply="confirmation"]')
      .addClass(o.btnOkClass)
      .html(o.btnOkLabel)
      .prepend($('').addClass(o.btnOkIcon), ' ')
      .off('click')
      .one('click', function(e) {
        that.getOnConfirm.call(that).call(that.$element);
        that.$element.trigger('confirmed.bs.confirmation');
        that.leave(that);
      });

    // add href to confirm button if needed
    if (o.href) {
      $tip.find('[data-apply="confirmation"]').attr({
        href: o.href,
        target: o.target
      });
    }

    // configure 'cancel' button
    $tip.find('[data-dismiss="confirmation"]')
      .addClass(o.btnCancelClass)
      .html(o.btnCancelLabel)
      .prepend($('').addClass(o.btnCancelIcon), ' ')
      .off('click')
      .one('click', function(e) {
        that.getOnCancel.call(that).call(that.$element);
        that.$element.trigger('canceled.bs.confirmation');
        that.leave(that);
      })

    $tip.removeClass('fade top bottom left right in');

    // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
    // this manually by checking the contents.
    if (!$tip.find('.popover-title').html()) {
      $tip.find('.popover-title').hide();
    }
  }

  Confirmation.prototype.getOnConfirm = function() {
    var $e = this.$element;
    var o = this.options;

    if ($e.attr('data-on-confirm')) {
      return getFunctionFromString($e.attr('data-on-confirm'));
    }
    else {
      return o.onConfirm;
    }
  }

  Confirmation.prototype.getOnCancel = function() {
    var $e = this.$element;
    var o = this.options;

    if ($e.attr('data-on-cancel')) {
      return getFunctionFromString($e.attr('data-on-cancel'));
    }
    else {
      return o.onCancel;
    }
  }

  /*
   * Generates an anonymous function from a function name
   * function name may contain dots (.) to navigate through objects
   * root context is window
   */
  function getFunctionFromString(functionName) {
    var context = window;
    var namespaces = functionName.split(".");
    var func = namespaces.pop();

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

    return function() {
      context[func].call(this);
    }
  }

  // CONFIRMATION PLUGIN DEFINITION
  // =========================

  var old = $.fn.confirmation;

  $.fn.confirmation = function (option) {
    var options = (typeof option == 'object' && option) || {};
    options._all_selector = this.selector;

    return this.each(function () {
      var $this   = $(this);
      var data    = $this.data('bs.confirmation');

      if (!data && option == 'destroy') return;
      if (!data) $this.data('bs.confirmation', (data = new Confirmation(this, options)));
      if (typeof option == 'string') data[option]();
    })
  }

  $.fn.confirmation.Constructor = Confirmation;

  // CONFIRMATION NO CONFLICT
  // ===================

  $.fn.confirmation.noConflict = function () {
    $.fn.confirmation = old;
    return this;
  }

}(jQuery);<|endoftext|>