<commit_before>(function($, window, document, undefined){

    var PufferfishImageChangeEvent = function(element, newImageSrc, oldImageSrc){
        this.element = element;
        this.newImageSrc = newImageSrc;
        this.oldImageSrc = oldImageSrc;
    };

    PufferfishImageChangeEvent.prototype.element = null;
    PufferfishImageChangeEvent.prototype.newImageSrc = null;
    PufferfishImageChangeEvent.prototype.oldImageSrc = null;
    PufferfishImageChangeEvent.prototype.isDefaultPrevented = false;

    PufferfishImageChangeEvent.prototype.preventDefault = function(){
        this.isDefaultPrevented = true;
    };

    var defaults = {
        'onChange': function(element, newImageSrc, oldImageSrc){},
        'afterChange': function(element, newImageSrc, oldImageSrc){}
    };

    $.pufferfish = (function(){

        var settings = $.extend({}, defaults);

        var sizeDefinitionRegex =       /\[([^,]+)(\s+)?,(\s+)?\(([^\)]+)\)(\s+)?\]/;
        var sizeDefinitionRegexGlobal = /\[([^,]+)(\s+)?,(\s+)?\(([^\)]+)\)(\s+)?\]/g;
        var constraintRegex =       /([^,\s:]+):(\s+)?([^,]+)/;
        var constraintRegexGlobal = /([^,\s:]+):(\s+)?([^,]+)/g;

        var watchedImages = [];

        function getDataAttrKey(name){
            return 'data-pufferfish' + (typeof name !== 'undefined' ? '-' + name : '');
        }

        function getDataAttrSelector(name){
            return '[' + getDataAttrKey(name) + ']';
        }

        function parseConstraints(constraintString){

            var defaults = {
                'max-width': null,
                'min-width': null
            };

            var constraints = {};

            var constraintStringParts = constraintString.match(constraintRegexGlobal);
            constraintStringParts.forEach(function(constraintStringPart){
                var constraintVars = constraintStringPart.match(constraintRegex);
                constraints[constraintVars[1]] = parseInt(constraintVars[3]);
            });

            return $.extend({}, defaults, constraints);

        }

        function parseSizeDefinitions(sizeDefString){

            var sizeDefStringParts = sizeDefString.match(sizeDefinitionRegexGlobal);
            var sizeDefs = [];

            sizeDefStringParts.forEach(function(sizeDefStringPart){
                var sizeDefVars = sizeDefStringPart.match(sizeDefinitionRegex);

                sizeDefs.push({
                    'src': sizeDefVars[1],
                    'constraints': parseConstraints(sizeDefVars[4])
                });

            });

            return sizeDefs;

        }

        function watchImage(img){

            var sizeDefString = img.attr( getDataAttrKey() );
            var sizeDefinitions = parseSizeDefinitions(sizeDefString);

            var srcAttr = img.attr( getDataAttrKey('src-attr') );
            if(!srcAttr) srcAttr = 'src';

            img.data( getDataAttrKey('watched'), true );

            watchedImages.push({
                'img': img,
                'sizeDefinitions': sizeDefinitions,
                'srcAttr': srcAttr,
                'currentSrc': null
            });

        }

        function reflow(){

            watchedImages.forEach(function(watchedImage){

                var img = watchedImage.img;

                var sizeDefinitions = watchedImage.sizeDefinitions;
                var container = img.parent();
                var availableWidth = container.innerWidth();

                var selectedSizeDefinition = null;

                $.each(sizeDefinitions, function(key, sizeDefinition){

                    if(
                        sizeDefinition.constraints['min-width'] !== null &&
                        availableWidth < sizeDefinition.constraints['min-width']
                    ){
                        return;
                    }

                    if(
                        sizeDefinition.constraints['max-width'] !== null &&
                        availableWidth > sizeDefinition.constraints['max-width']
                    ){
                        return;
                    }

                    selectedSizeDefinition = sizeDefinition;
                    return false;

                });

                if(selectedSizeDefinition !== null && watchedImage.currentSrc !== selectedSizeDefinition.src){

                    var oldImageSrc = watchedImage.currentSrc;
                    var newImageSrc = selectedSizeDefinition.src;

                    watchedImage.currentSrc = newImageSrc;

                    var event = new PufferfishImageChangeEvent(img, newImageSrc, oldImageSrc);
                    settings.onChange(event);

                    if(!event.isDefaultPrevented && elementIsVisible(img)){
                        img.attr(watchedImage.srcAttr, newImageSrc);
                    }

                    settings.afterChange(event);
                }

            });

        }

        function elementIsVisible(element){
            if(element[0] === window || element[0] === document) return true;

            if(element.css('display') === 'none') return false;
            else return elementIsVisible(element.parent());
        }

        function bindUnwatched(context){
            if(typeof context === 'undefined') context = document;
            $(context).find( getDataAttrSelector() ).each(function(){
                var img = $(this);
                if(img.data( getDataAttrKey('watched') )) return;
                watchImage(img);
            });
        }

        function init(context, _settings){
            settings = $.extend({}, defaults, _settings);
            if(typeof context === 'undefined') context = document;
            bindUnwatched(context);
            reflow();
        }

        // Public methods
        return {
            'init': init,
            'reflow': reflow
        };

    })();

    $.fn.pufferfish = function(settings){
        $.pufferfish.init(this, settings);
        $(window).on('resize', function(){
            $.pufferfish.reflow();
        });
    };

})( jQuery, window, window.document);
<commit_msg>Fixed issue where visibility checking would enter an infinite loop<commit_after>(function($, window, document, undefined){

    var PufferfishImageChangeEvent = function(element, newImageSrc, oldImageSrc){
        this.element = element;
        this.newImageSrc = newImageSrc;
        this.oldImageSrc = oldImageSrc;
    };

    PufferfishImageChangeEvent.prototype.element = null;
    PufferfishImageChangeEvent.prototype.newImageSrc = null;
    PufferfishImageChangeEvent.prototype.oldImageSrc = null;
    PufferfishImageChangeEvent.prototype.isDefaultPrevented = false;

    PufferfishImageChangeEvent.prototype.preventDefault = function(){
        this.isDefaultPrevented = true;
    };

    var defaults = {
        'onChange': function(element, newImageSrc, oldImageSrc){},
        'afterChange': function(element, newImageSrc, oldImageSrc){}
    };

    $.pufferfish = (function(){

        var settings = $.extend({}, defaults);

        var sizeDefinitionRegex =       /\[([^,]+)(\s+)?,(\s+)?\(([^\)]+)\)(\s+)?\]/;
        var sizeDefinitionRegexGlobal = /\[([^,]+)(\s+)?,(\s+)?\(([^\)]+)\)(\s+)?\]/g;
        var constraintRegex =       /([^,\s:]+):(\s+)?([^,]+)/;
        var constraintRegexGlobal = /([^,\s:]+):(\s+)?([^,]+)/g;

        var watchedImages = [];

        function getDataAttrKey(name){
            return 'data-pufferfish' + (typeof name !== 'undefined' ? '-' + name : '');
        }

        function getDataAttrSelector(name){
            return '[' + getDataAttrKey(name) + ']';
        }

        function parseConstraints(constraintString){

            var defaults = {
                'max-width': null,
                'min-width': null
            };

            var constraints = {};

            var constraintStringParts = constraintString.match(constraintRegexGlobal);
            constraintStringParts.forEach(function(constraintStringPart){
                var constraintVars = constraintStringPart.match(constraintRegex);
                constraints[constraintVars[1]] = parseInt(constraintVars[3]);
            });

            return $.extend({}, defaults, constraints);

        }

        function parseSizeDefinitions(sizeDefString){

            var sizeDefStringParts = sizeDefString.match(sizeDefinitionRegexGlobal);
            var sizeDefs = [];

            sizeDefStringParts.forEach(function(sizeDefStringPart){
                var sizeDefVars = sizeDefStringPart.match(sizeDefinitionRegex);

                sizeDefs.push({
                    'src': sizeDefVars[1],
                    'constraints': parseConstraints(sizeDefVars[4])
                });

            });

            return sizeDefs;

        }

        function watchImage(img){

            var sizeDefString = img.attr( getDataAttrKey() );
            var sizeDefinitions = parseSizeDefinitions(sizeDefString);

            var srcAttr = img.attr( getDataAttrKey('src-attr') );
            if(!srcAttr) srcAttr = 'src';

            img.data( getDataAttrKey('watched'), true );

            watchedImages.push({
                'img': img,
                'sizeDefinitions': sizeDefinitions,
                'srcAttr': srcAttr,
                'currentSrc': null
            });

        }

        function reflow(){

            watchedImages.forEach(function(watchedImage){

                var img = watchedImage.img;

                var sizeDefinitions = watchedImage.sizeDefinitions;
                var container = img.parent();
                var availableWidth = container.innerWidth();

                var selectedSizeDefinition = null;

                $.each(sizeDefinitions, function(key, sizeDefinition){

                    if(
                        sizeDefinition.constraints['min-width'] !== null &&
                        availableWidth < sizeDefinition.constraints['min-width']
                    ){
                        return;
                    }

                    if(
                        sizeDefinition.constraints['max-width'] !== null &&
                        availableWidth > sizeDefinition.constraints['max-width']
                    ){
                        return;
                    }

                    selectedSizeDefinition = sizeDefinition;
                    return false;

                });

                if(selectedSizeDefinition !== null && watchedImage.currentSrc !== selectedSizeDefinition.src){

                    var oldImageSrc = watchedImage.currentSrc;
                    var newImageSrc = selectedSizeDefinition.src;

                    watchedImage.currentSrc = newImageSrc;

                    var event = new PufferfishImageChangeEvent(img, newImageSrc, oldImageSrc);
                    settings.onChange(event);

                    if(!event.isDefaultPrevented && elementIsVisible(img)){
                        img.attr(watchedImage.srcAttr, newImageSrc);
                    }

                    settings.afterChange(event);
                }

            });

        }

        function elementIsVisible(element){
            if(element[0] === window || element[0] === document) return true;

            if(element.css('display') === 'none'){
                return false;
            }
            else{
                var parent = element.parent();
                if(parent.length === 0) return false;
                return elementIsVisible(parent);
            }
        }

        function bindUnwatched(context){
            if(typeof context === 'undefined') context = document;
            $(context).find( getDataAttrSelector() ).each(function(){
                var img = $(this);
                if(img.data( getDataAttrKey('watched') )) return;
                watchImage(img);
            });
        }

        function init(context, _settings){
            settings = $.extend({}, defaults, _settings);
            if(typeof context === 'undefined') context = document;
            bindUnwatched(context);
            reflow();
        }

        // Public methods
        return {
            'init': init,
            'reflow': reflow
        };

    })();

    $.fn.pufferfish = function(settings){
        $.pufferfish.init(this, settings);
        $(window).on('resize', function(){
            $.pufferfish.reflow();
        });
    };

})( jQuery, window, window.document);
<|endoftext|>


<commit_before>// Copyright 2008 Google Inc. All Rights Reserved.
// test_protocol.js

/**
 * @fileoverview Unit tests for testing debugger protocol betweeen front-end JS
 * and back-end.
 * Run with the following command line:
 * v8_shell_sample.exe --allow-natives-syntax --expose-debug-as debugContext
 *                     chrome/browser/resources/shell.js
 *                     v8/tests/mjsunit.js
 *                     chrome/test/debugger/test_protocol.js
 */

/**
 * shell() is normally a native function exposed to shell.js in Chrome that
 * sets the global DebugShell (shell_) object used for the debugger front-end.
 */
function shell(sh) {
  shell_ = sh;
};

/**
 * @class The global chrome object has some functions to control some status UI
 * in the debugger window.  Stub them out here.
 */
function chrome() {
};
chrome.setDebuggerReady = function(ready) {};
chrome.setDebuggerBreak = function(brk) {};

/**
 * @constructor a pseudo namespace to wrap the various functions and data for
 * the test
 */
function DebuggerTest() {
};

/**
 * initialize the member
 */
DebuggerTest.initialize = function() {
  DebuggerTest.pendingCommand = null;
  DebuggerTest.output = [];

  // swap out the built-in print with our own so that we can verify output
  DebuggerTest.realPrint = print;
  print = DebuggerTest.print;
  // uncomment this to see more verbose information
  //dprint = DebuggerTest.realPrint;

  debugContext.Debug.addListener(DebuggerTest.listener);
};

/**
 * Collects calls to print() in an array for test verification.
 */
DebuggerTest.print = function(str) {
  DebuggerTest.output.push(str);
  // uncomment this if you need to trace what's happening while it's happening
  // rather than waiting for the end
  //DebuggerTest.realPrint(str);
};

/**
 * Processes pendingCommand and sends response to shell_.  Since that may in
 * turn generate a new pendingCommand, repeat this until there is no
 * pendingCommand.
 */
DebuggerTest.processCommands = function(dcp) {
  while (DebuggerTest.pendingCommand) {
    var json = DebuggerTest.pendingCommand;
    DebuggerTest.pendingCommand = null;
    var result = dcp.processDebugJSONRequest(json);
    shell_.response(result);
  }
};

/**
 * Handles DebugEvents from the Debug object.  Hooked in via addListener above.
 */
DebuggerTest.listener = function(event, exec_state, event_data, data) {
  try {
    if (event == debugContext.Debug.DebugEvent.Break) {
      var dcp = exec_state.debugCommandProcessor();
      // process any pending commands prior to handling the breakpoint
      DebuggerTest.processCommands(dcp);
      var json = event_data.toJSONProtocol();
      shell_.response(json);
      // response() may have added another command to process
      DebuggerTest.processCommands(dcp);
    }
  } catch(e) {
    print(e);
  }
};

/**
 * Send the next command from the command-list.
 */
DebuggerTest.sendNextCommand = function() {
  var cmd = DebuggerTest.commandList.shift();
  print("$ " + cmd);
  shell_.command(cmd);
};

/**
 * Verify that the actual output matches the expected output
 * depends on mjsunit
 */
DebuggerTest.verifyOutput = function() {
  // restore print since mjsunit depends on it
  print = DebuggerTest.realPrint;

  var out = DebuggerTest.output;
  var expected = DebuggerTest.expectedOutput;
  if (out.length != expected.length) {
    assertTrue(out.length == expected.length,
               "length mismatch: " + out.length + " == " + expected.length);
  } else {
    var succeeded = true;
    for (var i in out) {
      // match the front of the string so we can avoid testing changes in frames
      // that are in the test harness
      if (out[i].indexOf(expected[i]) != 0) {
        assertTrue(out[i] == expected[i],
                   "actual '" + out[i] + "' == " + "expected '" + expected[i] + "'");
        succeeded = false;
        break;
      }
    }
    if (succeeded)
      print("Success");
  }

  // useful for generating a new version of DebuggerTest.expectedOutput
  for (var i in DebuggerTest.output) {
    //print("  \"" + DebuggerTest.output[i] + "\",");
  }
};

/**
 * @class DebugShell is passed a "Tab" object that it uses to communicate with
 * the debugger.  This mock simulates that.
 * @param {string} title
 */
DebuggerTest.TabMock = function(title) {
  this.title = title;
  this.attach = function() {};
  this.debugBreak = function() {
    // TODO(erikkay)
  };
  this.sendToDebugger = function(str) {
    DebuggerTest.pendingCommand = str;
  };
};

/**
 * @class Uses prototype chaining to allow DebugShell methods to be overridden
 * selectively.
 */
function DebugShellOverrides() {
  this._origPrototype = DebugShell.prototype;
};
DebugShellOverrides.prototype = DebugShell.prototype;
DebugShell.prototype = new DebugShellOverrides;

/**
 * Overrides DebugShell.prototype.response so that we can log the responses
 * and trigger the next command to be processed.
 */
DebugShell.prototype.response = function(str) {
  var msg = eval('(' + str + ')');
  print("< " + msg.type + ":" + (msg.command || msg.event));
  var sendAnother = (msg.type == "event");
  if (!sendAnother && shell_.current_command) {
    sendAnother = (shell_.current_command.from_user &&
        msg.type == "response" && msg.command != "continue")
  }
  this._origPrototype.response.call(this, str)

  // Send the next command, but only if the program is paused (a continue
  // command response means that we're about to be running again) and the
  // command we just processed isn't a continue
  if (!this.running && sendAnother)
    DebuggerTest.sendNextCommand();
};

// The list of commands to be processed
// TODO(erikkay): this doesn't test the full set of debugger commands yet,
// but it should be enough to verify that the protocol is still working.
DebuggerTest.commandList = [
"next", "step", "backtrace", "source", "print x", "args", "locals", "frame 1",
"stepout", "continue"
];

DebuggerTest.expectedOutput = [
  "< event:break",
  "g(), foo.html",
  "60:   debugger;",
  "$ next",
  "< response:continue",
  "< event:break",
  "61:   f(1);",
  "$ step",
  "< response:continue",
  "< event:break",
  "f(x=1, y=undefined), foo.html",
  "29:   return a;",
  "$ backtrace",
  "< response:backtrace",
  "Frames #0 to #3 of 4:",
  "#00 f(x=1, y=undefined) foo.html line 29 column 3 (position 62)",
  "#01 g() foo.html line 61 column 3 (position 30)",
  "#02 function DebuggerTest()", // prefix
  "#03 [anonymous]()", // prefix
  "$ source",
  "< response:source",
  "24: function f(x, y) {",
  "25:   var a=1;",
  "26:   if (x == 1) {",
  "27:     a++;",
  "28:   }",
  ">>>>  return a;",
  "30: };",
  "$ print x",
  "< response:evaluate",
  "1",
  "$ args",
  "< response:frame",
  "x = 1",
  "y = undefined",
  "$ locals",
  "< response:frame",
  "a = 2",
  "$ frame 1",
  "< response:frame",
  "#01 g, foo.html",
  "61:   f(1);",
  "$ stepout",
  "< response:continue",
  "< event:break",
  "g(), foo.html",
  "62: };",
  "$ continue",
  "< response:continue"
];

/**
 * Tests the debugger and protocol for a couple of simple scripts.
 */
DebuggerTest.testProtocol = function() {
  DebuggerTest.initialize();

  // Startup the front-end.
  debug(new DebuggerTest.TabMock("testing"));

  script1 =
      "function f(x, y) {\n" + // line 23
      "  var a=1;\n" + // line 24
      "  if (x == 1) {\n" + // line 25
      "    a++;\n  }\n" + // line 26
      "  return a;\n" + // line 27
      "};"; // line 28
  script2 =
      "function g() {\n" + // line 58
      "  debugger;\n" + // line 59
      "  f(1);\n" + // line 60
      "};"; // line 61
  %CompileScript(script1, "foo.html", 23, 0)();
  %CompileScript(script2, "foo.html", 58, 0)();

  try {
    g();
  } catch(e) {
    print(e);
  }

  DebuggerTest.verifyOutput();
}

DebuggerTest.testProtocol();
<commit_msg>Allow undefined as the script name in the debugger test. Review URL: http://codereview.chromium.org/19423<commit_after>// Copyright 2008 Google Inc. All Rights Reserved.
// test_protocol.js

/**
 * @fileoverview Unit tests for testing debugger protocol betweeen front-end JS
 * and back-end.
 * Run with the following command line:
 * v8_shell_sample.exe --allow-natives-syntax --expose-debug-as debugContext
 *                     chrome/browser/resources/shell.js
 *                     v8/tests/mjsunit.js
 *                     chrome/test/debugger/test_protocol.js
 */

/**
 * shell() is normally a native function exposed to shell.js in Chrome that
 * sets the global DebugShell (shell_) object used for the debugger front-end.
 */
function shell(sh) {
  shell_ = sh;
};

/**
 * @class The global chrome object has some functions to control some status UI
 * in the debugger window.  Stub them out here.
 */
function chrome() {
};
chrome.setDebuggerReady = function(ready) {};
chrome.setDebuggerBreak = function(brk) {};

/**
 * @constructor a pseudo namespace to wrap the various functions and data for
 * the test
 */
function DebuggerTest() {
};

/**
 * initialize the member
 */
DebuggerTest.initialize = function() {
  DebuggerTest.pendingCommand = null;
  DebuggerTest.output = [];

  // swap out the built-in print with our own so that we can verify output
  DebuggerTest.realPrint = print;
  print = DebuggerTest.print;
  // uncomment this to see more verbose information
  //dprint = DebuggerTest.realPrint;

  debugContext.Debug.addListener(DebuggerTest.listener);
};

/**
 * Collects calls to print() in an array for test verification.
 */
DebuggerTest.print = function(str) {
  DebuggerTest.output.push(str);
  // uncomment this if you need to trace what's happening while it's happening
  // rather than waiting for the end
  //DebuggerTest.realPrint(str);
};

/**
 * Processes pendingCommand and sends response to shell_.  Since that may in
 * turn generate a new pendingCommand, repeat this until there is no
 * pendingCommand.
 */
DebuggerTest.processCommands = function(dcp) {
  while (DebuggerTest.pendingCommand) {
    var json = DebuggerTest.pendingCommand;
    DebuggerTest.pendingCommand = null;
    var result = dcp.processDebugJSONRequest(json);
    shell_.response(result);
  }
};

/**
 * Handles DebugEvents from the Debug object.  Hooked in via addListener above.
 */
DebuggerTest.listener = function(event, exec_state, event_data, data) {
  try {
    if (event == debugContext.Debug.DebugEvent.Break) {
      var dcp = exec_state.debugCommandProcessor();
      // process any pending commands prior to handling the breakpoint
      DebuggerTest.processCommands(dcp);
      var json = event_data.toJSONProtocol();
      shell_.response(json);
      // response() may have added another command to process
      DebuggerTest.processCommands(dcp);
    }
  } catch(e) {
    print(e);
  }
};

/**
 * Send the next command from the command-list.
 */
DebuggerTest.sendNextCommand = function() {
  var cmd = DebuggerTest.commandList.shift();
  print("$ " + cmd);
  shell_.command(cmd);
};

/**
 * Verify that the actual output matches the expected output
 * depends on mjsunit
 */
DebuggerTest.verifyOutput = function() {
  // restore print since mjsunit depends on it
  print = DebuggerTest.realPrint;

  var out = DebuggerTest.output;
  var expected = DebuggerTest.expectedOutput;
  if (out.length != expected.length) {
    assertTrue(out.length == expected.length,
               "length mismatch: " + out.length + " == " + expected.length);
  } else {
    var succeeded = true;
    for (var i in out) {
      // match the front of the string so we can avoid testing changes in frames
      // that are in the test harness
      if (out[i].indexOf(expected[i]) != 0) {
        assertTrue(out[i] == expected[i],
                   "actual '" + out[i] + "' == " + "expected '" + expected[i] + "'");
        succeeded = false;
        break;
      }
    }
    if (succeeded)
      print("Success");
  }

  // useful for generating a new version of DebuggerTest.expectedOutput
  for (var i in DebuggerTest.output) {
    //print("  \"" + DebuggerTest.output[i] + "\",");
  }
};

/**
 * @class DebugShell is passed a "Tab" object that it uses to communicate with
 * the debugger.  This mock simulates that.
 * @param {string} title
 */
DebuggerTest.TabMock = function(title) {
  this.title = title;
  this.attach = function() {};
  this.debugBreak = function() {
    // TODO(erikkay)
  };
  this.sendToDebugger = function(str) {
    DebuggerTest.pendingCommand = str;
  };
};

/**
 * @class Uses prototype chaining to allow DebugShell methods to be overridden
 * selectively.
 */
function DebugShellOverrides() {
  this._origPrototype = DebugShell.prototype;
};
DebugShellOverrides.prototype = DebugShell.prototype;
DebugShell.prototype = new DebugShellOverrides;

/**
 * Overrides DebugShell.prototype.response so that we can log the responses
 * and trigger the next command to be processed.
 */
DebugShell.prototype.response = function(str) {
  var msg = eval('(' + str + ')');
  print("< " + msg.type + ":" + (msg.command || msg.event));
  var sendAnother = (msg.type == "event");
  if (!sendAnother && shell_.current_command) {
    sendAnother = (shell_.current_command.from_user &&
        msg.type == "response" && msg.command != "continue")
  }
  this._origPrototype.response.call(this, str)

  // Send the next command, but only if the program is paused (a continue
  // command response means that we're about to be running again) and the
  // command we just processed isn't a continue
  if (!this.running && sendAnother)
    DebuggerTest.sendNextCommand();
};

// The list of commands to be processed
// TODO(erikkay): this doesn't test the full set of debugger commands yet,
// but it should be enough to verify that the protocol is still working.
DebuggerTest.commandList = [
"next", "step", "backtrace", "source", "print x", "args", "locals", "frame 1",
"stepout", "continue"
];

DebuggerTest.expectedOutput = [
  "< event:break",
  "g(), foo.html",
  "60:   debugger;",
  "$ next",
  "< response:continue",
  "< event:break",
  "61:   f(1);",
  "$ step",
  "< response:continue",
  "< event:break",
  "f(x=1, y=undefined), foo.html",
  "29:   return a;",
  "$ backtrace",
  "< response:backtrace",
  "Frames #0 to #3 of 4:",
  "#00 f(x=1, y=undefined) foo.html line 29 column 3 (position 62)",
  "#01 g() foo.html line 61 column 3 (position 30)",
  "#02 function DebuggerTest()", // prefix
  "#03 [anonymous]()", // prefix
  "$ source",
  "< response:source",
  "24: function f(x, y) {",
  "25:   var a=1;",
  "26:   if (x == 1) {",
  "27:     a++;",
  "28:   }",
  ">>>>  return a;",
  "30: };",
  "$ print x",
  "< response:evaluate",
  "1",
  "$ args",
  "< response:frame",
  "x = 1",
  "y = undefined",
  "$ locals",
  "< response:frame",
  "a = 2",
  "$ frame 1",
  "< response:frame",
  // Temporarily allow undefined as the script name.
  // "#01 g, foo.html",
  "#01 g, undefined",
  "61:   f(1);",
  "$ stepout",
  "< response:continue",
  "< event:break",
  "g(), foo.html",
  "62: };",
  "$ continue",
  "< response:continue"
];

/**
 * Tests the debugger and protocol for a couple of simple scripts.
 */
DebuggerTest.testProtocol = function() {
  DebuggerTest.initialize();

  // Startup the front-end.
  debug(new DebuggerTest.TabMock("testing"));

  script1 =
      "function f(x, y) {\n" + // line 23
      "  var a=1;\n" + // line 24
      "  if (x == 1) {\n" + // line 25
      "    a++;\n  }\n" + // line 26
      "  return a;\n" + // line 27
      "};"; // line 28
  script2 =
      "function g() {\n" + // line 58
      "  debugger;\n" + // line 59
      "  f(1);\n" + // line 60
      "};"; // line 61
  %CompileScript(script1, "foo.html", 23, 0)();
  %CompileScript(script2, "foo.html", 58, 0)();

  try {
    g();
  } catch(e) {
    print(e);
  }

  DebuggerTest.verifyOutput();
}

DebuggerTest.testProtocol();
<|endoftext|>


<commit_before>const debug = require('debug')('push2cloud-cf-adapter:graceRequest');
const request = require('request');
const _ = require('lodash');
const notAuthenticatedCheck = require('../lib/notAuthenticated');
const commonRetryChecks = [
  require('../lib/graceRequestHandler/connectionReset'),
  require('../lib/graceRequestHandler/timeout')
];

module.exports = (api) => {
  return (opt, retryFns, callback) => {
    opt = opt || {};

    if (!callback) {
      callback = retryFns;
      retryFns = null;
    }
    if (!retryFns) retryFns = [];
    if (_.isFunction(retryFns)) retryFns = [retryFns];

    retryFns = commonRetryChecks.concat(retryFns).concat(api.graceRequestHandlers);

    var defaults = {
      method: 'GET',
      baseUrl: api.options.api,
      rejectUnauthorized: api.options.rejectUnauthorized,
      json: true,
      headers: api.token ? {
        Authorization: `${api.token.token_type} ${api.token.access_token}`
      } : undefined
    };

    _.defaults(opt, defaults);

    var attempt = 0;

    (function retry() {
      setTimeout(() => {
        request(opt, (err, response, result) => {
          if (err) debug(err, result, opt);
          if (!err && response && response.statusCode < 300) {
            return callback(err, response, result);
          }
          if (attempt >= api.options.maxRetries) {
            if (result && result.error_code) {
              return callback(new Error(result.description), response, result);
            }
            return callback(err, response, result);
          }
          if (response) {
            debug(`StatusCode: ${response.statusCode}`);
            debug(err, result, opt);
          }

          const toCheck = {
            error: err,
            response: response,
            result: result,
            attempt: attempt,
            infos: opt
          };

          if (notAuthenticatedCheck(toCheck)) {
            api.login((err, refreshedToken) => {
              if (err) {
                debug(err);
                return callback(err);
              }
              if (refreshedToken) {
                api.token = refreshedToken;
              }

              opt.headers = api.token ? {
                Authorization: `${api.token.token_type} ${api.token.access_token}`
              } : undefined;

              attempt++;
              debug(`${attempt}. retry`);
              retry();
            });
            return;
          }

          var shouldRetry = false;
          _.some(retryFns, (fn) => {
            shouldRetry = fn(toCheck);
            return !!shouldRetry;
          });

          if (shouldRetry) {
            attempt++;
            var reason = '';
            if (_.isString(shouldRetry)) reason = ` reason: ${shouldRetry}`;
            debug(`${attempt}. retry${reason}`);

            api.stats.emit('retry', {
              error: toCheck.error,
              response: toCheck.response,
              result: toCheck.result,
              attempt: toCheck.attempt,
              infos: toCheck.infos,
              reason: reason
            });

            return retry();
          }

          if (result && result.error_code) {
            return callback(new Error(result.description), response, result);
          }

          callback(err, response, result);
        });
      }, attempt * api.options.delay * api.options.delayFactor);
    })();
  };
};
<commit_msg>fix require statement<commit_after>const debug = require('debug')('push2cloud-cf-adapter:graceRequest');
const request = require('request');
const _ = require('lodash');
const notAuthenticatedCheck = require('../lib/graceRequestHandler/notAuthenticated');
const commonRetryChecks = [
  require('../lib/graceRequestHandler/connectionReset'),
  require('../lib/graceRequestHandler/timeout')
];

module.exports = (api) => {
  return (opt, retryFns, callback) => {
    opt = opt || {};

    if (!callback) {
      callback = retryFns;
      retryFns = null;
    }
    if (!retryFns) retryFns = [];
    if (_.isFunction(retryFns)) retryFns = [retryFns];

    retryFns = commonRetryChecks.concat(retryFns).concat(api.graceRequestHandlers);

    var defaults = {
      method: 'GET',
      baseUrl: api.options.api,
      rejectUnauthorized: api.options.rejectUnauthorized,
      json: true,
      headers: api.token ? {
        Authorization: `${api.token.token_type} ${api.token.access_token}`
      } : undefined
    };

    _.defaults(opt, defaults);

    var attempt = 0;

    (function retry() {
      setTimeout(() => {
        request(opt, (err, response, result) => {
          if (err) debug(err, result, opt);
          if (!err && response && response.statusCode < 300) {
            return callback(err, response, result);
          }
          if (attempt >= api.options.maxRetries) {
            if (result && result.error_code) {
              return callback(new Error(result.description), response, result);
            }
            return callback(err, response, result);
          }
          if (response) {
            debug(`StatusCode: ${response.statusCode}`);
            debug(err, result, opt);
          }

          const toCheck = {
            error: err,
            response: response,
            result: result,
            attempt: attempt,
            infos: opt
          };

          if (notAuthenticatedCheck(toCheck)) {
            api.login((err, refreshedToken) => {
              if (err) {
                debug(err);
                return callback(err);
              }
              if (refreshedToken) {
                api.token = refreshedToken;
              }

              opt.headers = api.token ? {
                Authorization: `${api.token.token_type} ${api.token.access_token}`
              } : undefined;

              attempt++;
              debug(`${attempt}. retry`);
              retry();
            });
            return;
          }

          var shouldRetry = false;
          _.some(retryFns, (fn) => {
            shouldRetry = fn(toCheck);
            return !!shouldRetry;
          });

          if (shouldRetry) {
            attempt++;
            var reason = '';
            if (_.isString(shouldRetry)) reason = ` reason: ${shouldRetry}`;
            debug(`${attempt}. retry${reason}`);

            api.stats.emit('retry', {
              error: toCheck.error,
              response: toCheck.response,
              result: toCheck.result,
              attempt: toCheck.attempt,
              infos: toCheck.infos,
              reason: reason
            });

            return retry();
          }

          if (result && result.error_code) {
            return callback(new Error(result.description), response, result);
          }

          callback(err, response, result);
        });
      }, attempt * api.options.delay * api.options.delayFactor);
    })();
  };
};
<|endoftext|>


<commit_before>var Context         = require('pex-context/Context');
var isBrowser       = require('is-browser');
var WindowBrowser   = require('./WindowBrowser');
var WindowPlask     = require('./WindowPlask');
var ResourceLoader  = require('./ResourceLoader');
var Time            = require('./Time');
var Mouse           = require('./Mouse');
var MouseEvent      = require('./MouseEvent');
var Keyboard        = require('./Keyboard');
var KeyboardEvent   = require('./KeyboardEvent');

var current = null;

var ListenerCallbackMethod = {
    MOUSE_DOWN    : 'onMouseDown',
    MOUSE_UP      : 'onMouseUp',
    MOUSE_DRAG    : 'onMouseDrag',
    MOUSE_MOVE    : 'onMouseMove',
    MOUSE_SCROLL  : 'onMouseScroll',
    KEY_DOWN      : 'onKeyDown',
    KEY_PRESS     : 'onKeyPress',
    KEY_UP        : 'onKeyUp',
    WINDOW_RESIZE : 'onWindowResize'
};

function Window(){
    this._ctx = null;
    this._resources = { };

    this._time = new Time();
    this._mouse = new Mouse();
    this._keyboard = new Keyboard();
}

Window.prototype.init = function(){};
Window.prototype.draw = function(){};

Window.prototype.getWidth = function(){
    return this._width;
};

Window.prototype.getHeight = function(){
    return this._height;
};

Window.prototype.getAspectRatio = function(){
    return this.getWidth() / this.getHeight();
};

Window.prototype.getSize = function(out){
    out = out || new Array(2);
    out[0] = this.getWidth();
    out[1] = this.getHeight();
    return out;
};

Window.prototype.getBounds = function(out){
    out = out || new Array(4);
    out[0] = out[1] = 0;
    out[2] = this.getWidth();
    out[3] = this.getHeight();
    return out;
};

Window.prototype.getContext = function(){
    return this._ctx;
};

Window.prototype.getResources = function(){
    return this._resources;
};

Window.prototype.getTime = function() {
    return this._time;
};

Window.prototype.getMouse = function() {
    return this._mouse;
};

Window.prototype.getKeyboard = function() {
    return this._keyboard;
};

Window.prototype.addEventListener = function(listenerObjOrType, method){
    if(method === undefined){
        if(listenerObjOrType === null || typeof listenerObjOrType !== 'object'){
            throw new Error('Invalid listener object.');
        }
        var mouse    = this._mouse;
        var keyboard = this._keyboard;
        for(var p in listenerObjOrType){
            if(typeof listenerObjOrType[p] !== 'function'){
                continue;
            }
            var func = listenerObjOrType[p];
            switch (p){
                case ListenerCallbackMethod.MOUSE_DOWN :
                    mouse.addEventListener(MouseEvent.MOUSE_DOWN,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.MOUSE_UP :
                    mouse.addEventListener(MouseEvent.MOUSE_UP,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.MOUSE_DRAG :
                    mouse.addEventListener(MouseEvent.MOUSE_DRAG,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.MOUSE_MOVE :
                    mouse.addEventListener(MouseEvent.MOUSE_MOVE,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.MOUSE_SCROLL:
                    mouse.addEventListener(MouseEvent.MOUSE_SCROLL,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.KEY_DOWN :
                    keyboard.addEventListener(KeyboardEvent.KEY_DOWN,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.KEY_PRESS :
                    keyboard.addEventListener(KeyboardEvent.KEY_PRESS,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.KEY_UP :
                    keyboard.addEventListener(KeyboardEvent.KEY_UP,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.WINDOW_RESIZE :
                    break;
            }
        }
        return;
    }

    //window listener
};

Window.create = function(obj){
    var window = new Window();

    for (var p in obj) {
        window[p] = obj[p];
    }

    if (window.onMouseDown) window._mouse.addEventListener(MouseEvent.MOUSE_DOWN, window.onMouseDown.bind(window));
    if (window.onMouseUp) window._mouse.addEventListener(MouseEvent.MOUSE_UP, window.onMouseUp.bind(window));
    if (window.onMouseMove) window._mouse.addEventListener(MouseEvent.MOUSE_MOVE, window.onMouseMove.bind(window));
    if (window.onMouseDrag) window._mouse.addEventListener(MouseEvent.MOUSE_DRAG, window.onMouseDrag.bind(window));
    if (window.onMouseScroll) window._mouse.addEventListener(MouseEvent.MOUSE_SCROLL, window.onMouseScroll.bind(window));

    if (window.onKeyDown) window._keyboard.addEventListener(KeyboardEvent.KEY_DOWN, window.onKeyDown.bind(window));
    if (window.onKeyPress) window._keyboard.addEventListener(KeyboardEvent.KEY_PRESS, window.onKeyPress.bind(window));
    if (window.onKeyUp) window._keyboard.addEventListener(KeyboardEvent.KEY_UP, window.onKeyUp.bind(window));

    var winObj = {
        settings : {
            width      : window.settings.width || 1280,
            height     : window.settings.height || 720,
            fullscreen : window.settings.fullscreen || false,
        },
        time : window._time,
        input : {
            mouse    : window._mouse,
            keyboard : window._keyboard
        },
        init : function() {
            window._ctx = new Context(this.gl);
            window._width = this.width;
            window._height = this.height;
            window.init();
        },
        draw: window.draw.bind(window)
    };

    ResourceLoader.load(window.resources || {}, function(err, res) {
        if (err) {
            console.log('Window.create failed loading resources');
            console.log(err);
        }
        else {
            window._resources = res;

            if (isBrowser) {
                WindowBrowser.create(winObj);
            }
            else {
                WindowPlask.create(winObj);
            }
        }
    })
};

//FIXME: finish implementing or drop Window.getCurrent()
Window.getCurrent = function(){
    return current;
};

module.exports = Window;
<commit_msg>Window passing on highdpi flag<commit_after>var Context         = require('pex-context/Context');
var isBrowser       = require('is-browser');
var WindowBrowser   = require('./WindowBrowser');
var WindowPlask     = require('./WindowPlask');
var ResourceLoader  = require('./ResourceLoader');
var Time            = require('./Time');
var Mouse           = require('./Mouse');
var MouseEvent      = require('./MouseEvent');
var Keyboard        = require('./Keyboard');
var KeyboardEvent   = require('./KeyboardEvent');

var current = null;

var ListenerCallbackMethod = {
    MOUSE_DOWN    : 'onMouseDown',
    MOUSE_UP      : 'onMouseUp',
    MOUSE_DRAG    : 'onMouseDrag',
    MOUSE_MOVE    : 'onMouseMove',
    MOUSE_SCROLL  : 'onMouseScroll',
    KEY_DOWN      : 'onKeyDown',
    KEY_PRESS     : 'onKeyPress',
    KEY_UP        : 'onKeyUp',
    WINDOW_RESIZE : 'onWindowResize'
};

function Window(){
    this._ctx = null;
    this._resources = { };

    this._time = new Time();
    this._mouse = new Mouse();
    this._keyboard = new Keyboard();
}

Window.prototype.init = function(){};
Window.prototype.draw = function(){};

Window.prototype.getWidth = function(){
    return this._width;
};

Window.prototype.getHeight = function(){
    return this._height;
};

Window.prototype.getAspectRatio = function(){
    return this.getWidth() / this.getHeight();
};

Window.prototype.getSize = function(out){
    out = out || new Array(2);
    out[0] = this.getWidth();
    out[1] = this.getHeight();
    return out;
};

Window.prototype.getBounds = function(out){
    out = out || new Array(4);
    out[0] = out[1] = 0;
    out[2] = this.getWidth();
    out[3] = this.getHeight();
    return out;
};

Window.prototype.getContext = function(){
    return this._ctx;
};

Window.prototype.getResources = function(){
    return this._resources;
};

Window.prototype.getTime = function() {
    return this._time;
};

Window.prototype.getMouse = function() {
    return this._mouse;
};

Window.prototype.getKeyboard = function() {
    return this._keyboard;
};

Window.prototype.addEventListener = function(listenerObjOrType, method){
    if(method === undefined){
        if(listenerObjOrType === null || typeof listenerObjOrType !== 'object'){
            throw new Error('Invalid listener object.');
        }
        var mouse    = this._mouse;
        var keyboard = this._keyboard;
        for(var p in listenerObjOrType){
            if(typeof listenerObjOrType[p] !== 'function'){
                continue;
            }
            var func = listenerObjOrType[p];
            switch (p){
                case ListenerCallbackMethod.MOUSE_DOWN :
                    mouse.addEventListener(MouseEvent.MOUSE_DOWN,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.MOUSE_UP :
                    mouse.addEventListener(MouseEvent.MOUSE_UP,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.MOUSE_DRAG :
                    mouse.addEventListener(MouseEvent.MOUSE_DRAG,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.MOUSE_MOVE :
                    mouse.addEventListener(MouseEvent.MOUSE_MOVE,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.MOUSE_SCROLL:
                    mouse.addEventListener(MouseEvent.MOUSE_SCROLL,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.KEY_DOWN :
                    keyboard.addEventListener(KeyboardEvent.KEY_DOWN,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.KEY_PRESS :
                    keyboard.addEventListener(KeyboardEvent.KEY_PRESS,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.KEY_UP :
                    keyboard.addEventListener(KeyboardEvent.KEY_UP,func.bind(listenerObjOrType));
                    break;
                case ListenerCallbackMethod.WINDOW_RESIZE :
                    break;
            }
        }
        return;
    }

    //window listener
};

Window.create = function(obj){
    var window = new Window();

    for (var p in obj) {
        window[p] = obj[p];
    }

    if (window.onMouseDown) window._mouse.addEventListener(MouseEvent.MOUSE_DOWN, window.onMouseDown.bind(window));
    if (window.onMouseUp) window._mouse.addEventListener(MouseEvent.MOUSE_UP, window.onMouseUp.bind(window));
    if (window.onMouseMove) window._mouse.addEventListener(MouseEvent.MOUSE_MOVE, window.onMouseMove.bind(window));
    if (window.onMouseDrag) window._mouse.addEventListener(MouseEvent.MOUSE_DRAG, window.onMouseDrag.bind(window));
    if (window.onMouseScroll) window._mouse.addEventListener(MouseEvent.MOUSE_SCROLL, window.onMouseScroll.bind(window));

    if (window.onKeyDown) window._keyboard.addEventListener(KeyboardEvent.KEY_DOWN, window.onKeyDown.bind(window));
    if (window.onKeyPress) window._keyboard.addEventListener(KeyboardEvent.KEY_PRESS, window.onKeyPress.bind(window));
    if (window.onKeyUp) window._keyboard.addEventListener(KeyboardEvent.KEY_UP, window.onKeyUp.bind(window));

    var winObj = {
        settings : {
            width      : window.settings.width || 1280,
            height     : window.settings.height || 720,
            fullscreen : window.settings.fullscreen || false,
            highdpi    : window.settings.highdpi || 1
        },
        time : window._time,
        input : {
            mouse    : window._mouse,
            keyboard : window._keyboard
        },
        init : function() {
            window._ctx = new Context(this.gl);
            window._width = this.width;
            window._height = this.height;
            window.init();
        },
        draw: window.draw.bind(window)
    };

    ResourceLoader.load(window.resources || {}, function(err, res) {
        if (err) {
            console.log('Window.create failed loading resources');
            console.log(err);
        }
        else {
            window._resources = res;

            if (isBrowser) {
                WindowBrowser.create(winObj);
            }
            else {
                WindowPlask.create(winObj);
            }
        }
    })
};

//FIXME: finish implementing or drop Window.getCurrent()
Window.getCurrent = function(){
    return current;
};

module.exports = Window;
<|endoftext|>


<commit_before>'use strict';

var randu = require( '@stdlib/math/base/random/randu' );
var cdf = require( './../lib' );

var gamma;
var x0;
var x;
var y;
var i;

for ( i = 0; i < 10; i++ ) {
	x = randu() * 10.0;
	x0 = randu() * 10.0;
	gamma = randu() * 10.0;
	y = cdf( x, x0, gamma );
	console.log( 'x: %d, x0: %d, γ: %d, F(x;x0,γ): %d',
		x.toFixed( 4 ),
		x0.toFixed( 4 ),
		gamma.toFixed( 4 ),
		y.toFixed( 4 )
	);
}
<commit_msg>Guard against NaN<commit_after>'use strict';

var randu = require( '@stdlib/math/base/random/randu' );
var EPS = require( '@stdlib/math/constants/float64-eps' );
var cdf = require( './../lib' );

var gamma;
var x0;
var x;
var y;
var i;

for ( i = 0; i < 10; i++ ) {
	x = randu() * 10.0;
	x0 = randu() * 10.0;
	gamma = ( randu()*10.0 ) + EPS;
	y = cdf( x, x0, gamma );
	console.log( 'x: %d, x0: %d, γ: %d, F(x;x0,γ): %d', x.toFixed( 4 ), x0.toFixed( 4 ), gamma.toFixed( 4 ), y.toFixed( 4 ) );
}
<|endoftext|>


<commit_before>/* global Movement, Detainee, Event, Prebooking, Heartbeat, Bed */
'use strict';

const ValidationError = require('../lib/exceptions/ValidationError');
const BedCountService = require('../services/BedCountService');
const LinkingModels = require('sails-linking-models');
const _ = require('lodash');

const unreconciledMovementReducer = (movements, gender, direction) => movements.reduce((reduced, m) => {
  if (m.gender === gender && m.direction === direction) {
    reduced.push({id: m.id, cid_id: m.cid_id});
  }
  return reduced;
}, []);
const unreconciledEventReducer = (events, gender, operations) => events.reduce((reduced, event) => {
  if (event.detainee.gender === gender && operations.indexOf(event.operation) >= 0) {
    reduced.push({id: event.id, cid_id: event.detainee.cid_id});
  }
  return reduced;
}, []);

const model = {
  schema: true,
  autoCreatedAt: true,
  autoUpdatedAt: true,
  attributes: {
    heartbeat_received: {
      type: 'datetime'
    },
    cid_received_date: {
      type: 'datetime'
    },
    prebooking_received: {
      type: 'datetime'
    },
    name: {
      type: 'string',
      defaultsTo: 0,
      required: true,
      unique: true
    },
    male_capacity: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_capacity: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_in_use: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_in_use: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_out_of_commission: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_out_of_commission: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_cid_name: {
      type: 'array'
    },
    female_cid_name: {
      type: 'array'
    },
    events: {
      collection: 'event',
      via: 'centre'
    },
    detainees: {
      collection: 'detainee',
      via: 'centre'
    },
    movements: {
      collection: 'movement',
      via: 'centre'
    },
    toJSON: function () {
      const response = {
        type: 'centre',
        id: this.id.toString(),
        attributes: {
          cidReceivedDate: this.cid_received_date ? this.cid_received_date.toString() : null,
          updated: this.updatedAt,
          heartbeatReceived: this.heartbeat_received ? this.heartbeat_received.toString() : null,
          prebookingReceived: this.prebooking_received ? this.prebooking_received.toString() : null,
          name: this.name
        },
        links: this.modelLinks('centres', reverseRouteService)
      };
      ['male', 'female'].forEach((gender) => {
        response.attributes[gender + 'Capacity'] = this[gender + '_capacity'];
        response.attributes[gender + 'InUse'] = this[gender + '_in_use'];
        response.attributes[gender + 'OutOfCommissionTotal'] = this[gender + '_out_of_commission'];
        response.attributes[gender + 'OutOfCommissionDetail'] = this.outOfCommission ? this.outOfCommission[gender] : null;
        response.attributes[gender + 'PrebookingTotal'] = this.prebooking ? this.prebooking[gender].total : null;
        response.attributes[gender + 'PrebookingDetail'] = this.prebooking ? this.prebooking[gender].detail : null;
        response.attributes[gender + 'ContingencyTotal'] = this.contingency ? this.contingency[gender].total : null;
        response.attributes[gender + 'ContingencyDetail'] = this.contingency ? this.contingency[gender].detail : null;
        response.attributes[gender + 'Availability'] = response.attributes[gender + 'Capacity'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'InUse'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'OutOfCommissionTotal'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'ContingencyTotal'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'PrebookingTotal'];
        if (this.reconciled) {
          response.attributes[gender + 'UnexpectedIn'] = unreconciledEventReducer(this.unreconciledEvents, gender, ['check in']);
          response.attributes[gender + 'ExpectedIn'] = unreconciledMovementReducer(this.unreconciledMovements, gender, 'in');
          response.attributes[gender + 'ExpectedOut'] = unreconciledMovementReducer(this.unreconciledMovements, gender, 'out');
          response.attributes[gender + 'Availability'] -= response.attributes[gender + 'ExpectedIn'].length;
        }
      });
      return response;
    }
  },
  getGenderAndCentreByCIDLocation: function (location) {
    return this.find().then(centres =>
      _.compact(_.map(centres, centre => {
        centre.male_cid_name = _.map(centre.male_cid_name, _.lowerCase);
        centre.female_cid_name = _.map(centre.female_cid_name, _.lowerCase);
        if (_.includes(centre.male_cid_name, location.toLowerCase())) {
          return {
            centre: centre.id,
            gender: 'male'
          };
        }
        if (_.includes(centre.female_cid_name, location.toLowerCase())) {
          return {
            centre: centre.id,
            gender: 'female'
          };
        }
      }))[0]
    );
  },

  afterCreate: (centre, done) =>
    Centres.findReconciled({id: centre.id})
      .map((centre) => Centres.publishCreate(centre.toJSON()))
      .finally(() => done()),

  findReconciled: (query) =>
    Centres.find(query || {})
      .toPromise()
      .map(BedCountService.performConfiguredReconciliation),

  publishUpdateOne: (centre) =>
    Centres.findReconciled({id: centre.id || centre})
      .map((centre) => Centres.publishUpdate(centre.id, centre.toJSON())),

  publishUpdateAll: () =>
    Centres.findReconciled()
      .map((centre) => Centres.publishUpdate(centre.id, centre.toJSON())),

  afterDestroy: function (records, done) {
    Promise.all(_.map(records, (record) =>
        Movement.destroy({centre: record.id})
          .then(() => Prebooking.destroy({centre: record.id}))
          .then(() => Event.destroy({centre: record.id}))
          .then(() => Bed.destroy({centre: record.id}))
          .then(() => Detainee.destroy({centre: record.id}))
          .then(() => Heartbeat.destroy({centre: record.id}))
          .then(() => this.publishDestroy(record.id))
      ))
      .then(() => done());
  },

  getByName: function (name) {
    return this.findByName(name)
      .then((centre) => {
        if (centre === undefined || centre.length !== 1) {
          throw new ValidationError('Invalid centre');
        }
        return centre[0];
      });
  }

};

module.exports = LinkingModels.mixin(model);
<commit_msg>better case insensitive mapping<commit_after>/* global Movement, Detainee, Event, Prebooking, Heartbeat, Bed */
'use strict';

const ValidationError = require('../lib/exceptions/ValidationError');
const BedCountService = require('../services/BedCountService');
const LinkingModels = require('sails-linking-models');
const _ = require('lodash');

const unreconciledMovementReducer = (movements, gender, direction) => movements.reduce((reduced, m) => {
  if (m.gender === gender && m.direction === direction) {
    reduced.push({id: m.id, cid_id: m.cid_id});
  }
  return reduced;
}, []);
const unreconciledEventReducer = (events, gender, operations) => events.reduce((reduced, event) => {
  if (event.detainee.gender === gender && operations.indexOf(event.operation) >= 0) {
    reduced.push({id: event.id, cid_id: event.detainee.cid_id});
  }
  return reduced;
}, []);

const model = {
  schema: true,
  autoCreatedAt: true,
  autoUpdatedAt: true,
  attributes: {
    heartbeat_received: {
      type: 'datetime'
    },
    cid_received_date: {
      type: 'datetime'
    },
    prebooking_received: {
      type: 'datetime'
    },
    name: {
      type: 'string',
      defaultsTo: 0,
      required: true,
      unique: true
    },
    male_capacity: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_capacity: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_in_use: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_in_use: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_out_of_commission: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    female_out_of_commission: {
      type: 'integer',
      defaultsTo: 0,
      required: true
    },
    male_cid_name: {
      type: 'array'
    },
    female_cid_name: {
      type: 'array'
    },
    events: {
      collection: 'event',
      via: 'centre'
    },
    detainees: {
      collection: 'detainee',
      via: 'centre'
    },
    movements: {
      collection: 'movement',
      via: 'centre'
    },
    toJSON: function () {
      const response = {
        type: 'centre',
        id: this.id.toString(),
        attributes: {
          cidReceivedDate: this.cid_received_date ? this.cid_received_date.toString() : null,
          updated: this.updatedAt,
          heartbeatReceived: this.heartbeat_received ? this.heartbeat_received.toString() : null,
          prebookingReceived: this.prebooking_received ? this.prebooking_received.toString() : null,
          name: this.name
        },
        links: this.modelLinks('centres', reverseRouteService)
      };
      ['male', 'female'].forEach((gender) => {
        response.attributes[gender + 'Capacity'] = this[gender + '_capacity'];
        response.attributes[gender + 'InUse'] = this[gender + '_in_use'];
        response.attributes[gender + 'OutOfCommissionTotal'] = this[gender + '_out_of_commission'];
        response.attributes[gender + 'OutOfCommissionDetail'] = this.outOfCommission ? this.outOfCommission[gender] : null;
        response.attributes[gender + 'PrebookingTotal'] = this.prebooking ? this.prebooking[gender].total : null;
        response.attributes[gender + 'PrebookingDetail'] = this.prebooking ? this.prebooking[gender].detail : null;
        response.attributes[gender + 'ContingencyTotal'] = this.contingency ? this.contingency[gender].total : null;
        response.attributes[gender + 'ContingencyDetail'] = this.contingency ? this.contingency[gender].detail : null;
        response.attributes[gender + 'Availability'] = response.attributes[gender + 'Capacity'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'InUse'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'OutOfCommissionTotal'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'ContingencyTotal'];
        response.attributes[gender + 'Availability'] -= response.attributes[gender + 'PrebookingTotal'];
        if (this.reconciled) {
          response.attributes[gender + 'UnexpectedIn'] = unreconciledEventReducer(this.unreconciledEvents, gender, ['check in']);
          response.attributes[gender + 'ExpectedIn'] = unreconciledMovementReducer(this.unreconciledMovements, gender, 'in');
          response.attributes[gender + 'ExpectedOut'] = unreconciledMovementReducer(this.unreconciledMovements, gender, 'out');
          response.attributes[gender + 'Availability'] -= response.attributes[gender + 'ExpectedIn'].length;
        }
      });
      return response;
    }
  },
  getGenderAndCentreByCIDLocation: function (location) {
    return this.find().then(centres =>
      _.compact(_.map(centres, centre => {
        centre.male_cid_name = _.map(centre.male_cid_name, string => string.toLowerCase());
        centre.female_cid_name = _.map(centre.female_cid_name, string => string.toLowerCase());
        if (_.includes(centre.male_cid_name, location.toLowerCase())) {
          return {
            centre: centre.id,
            gender: 'male'
          };
        }
        if (_.includes(centre.female_cid_name, location.toLowerCase())) {
          return {
            centre: centre.id,
            gender: 'female'
          };
        }
      }))[0]
    );
  },

  afterCreate: (centre, done) =>
    Centres.findReconciled({id: centre.id})
      .map((centre) => Centres.publishCreate(centre.toJSON()))
      .finally(() => done()),

  findReconciled: (query) =>
    Centres.find(query || {})
      .toPromise()
      .map(BedCountService.performConfiguredReconciliation),

  publishUpdateOne: (centre) =>
    Centres.findReconciled({id: centre.id || centre})
      .map((centre) => Centres.publishUpdate(centre.id, centre.toJSON())),

  publishUpdateAll: () =>
    Centres.findReconciled()
      .map((centre) => Centres.publishUpdate(centre.id, centre.toJSON())),

  afterDestroy: function (records, done) {
    Promise.all(_.map(records, (record) =>
      Movement.destroy({centre: record.id})
        .then(() => Prebooking.destroy({centre: record.id}))
        .then(() => Event.destroy({centre: record.id}))
        .then(() => Bed.destroy({centre: record.id}))
        .then(() => Detainee.destroy({centre: record.id}))
        .then(() => Heartbeat.destroy({centre: record.id}))
        .then(() => this.publishDestroy(record.id))
    ))
      .then(() => done());
  },

  getByName: function (name) {
    return this.findByName(name)
      .then((centre) => {
        if (centre === undefined || centre.length !== 1) {
          throw new ValidationError('Invalid centre');
        }
        return centre[0];
      });
  }

};

module.exports = LinkingModels.mixin(model);
<|endoftext|>


<commit_before>import Promise from 'bluebird';
import whacko from 'whacko';
import fs from 'fs';
import path from 'path';
import globby from 'globby';
import utils from 'systemjs-builder/lib/utils';
import Builder from 'systemjs-builder';
import _ from 'lodash';

export function bundle(cfg) {

  let builder = new Builder(cfg.baseURL, cfg.configPath);
  builder.config(cfg.builderCfg);

  let templates = [];
  let baseURL = path.resolve(cfg.baseURL);
  let outfile = path.resolve(baseURL, cfg.bundleName) + '.html';

  if (fs.existsSync(outfile)) {
    if (!cfg.force) {
      throw new Error(`A bundle named '${outfile}' already exists. Use the --force option to overwrite it.`);
    }
    fs.unlinkSync(outfile);
  }

  globby
    .sync(cfg.includes, {
      cwd: baseURL.replace(/\\/g, '/')
    })
    .forEach(function(file) {
      file = path.resolve(baseURL, file);
      var content = fs.readFileSync(file, {
        encoding: 'utf8'
      });

      var $ = whacko.load(content);
      var name = getCanonicalName(builder, file, 'view').replace(/!view$/g, '');

      $('template').attr('id', name);
      var template = $.html('template');
      templates.push(template);
    });

  fs.writeFileSync(outfile, templates.join('\n'));

  if (cfg.options.inject) {
    injectLink(outfile, baseURL, cfg.options.inject);
  }

  return Promise.resolve();
}

function injectLink(outfile, baseURL, inject) {
  let bundleFile = path.resolve(baseURL, path.relative(baseURL, outfile));
  var indexFile = path.resolve(baseURL, inject.indexFile);
  var destFile = path.resolve(baseURL, inject.destFile);
  var relpath = path.relative(path.dirname(indexFile), path.dirname(bundleFile)).replace(/\\/g, '/');

  let link = createLink(bundleFile, relpath);
  addLink(link, indexFile, destFile);
}

function addLink(link, indexFile, destFile){
  var content = fs.readFileSync(indexFile, {
    encoding: 'utf8'
  });

  var $ = whacko.load(content);

  if ($('link[aurelia-view-bundle][href="' + link + '"]').length === 0) {
    $('head').append('<link aurelia-view-bundle rel="import" href="' + link + '">');
  }

  fs.writeFileSync(destFile, $.html());
}

function createLink(bundleFile, relpath){
  if (!relpath.startsWith('.')) {
    return relpath ? './' + relpath + '/' + path.basename(bundleFile) : './' + path.basename(bundleFile);
  } else {
    return relpath + '/' + path.basename(bundleFile);
  }
}

function getCanonicalName(builder, file, pluginName) {
  return builder.getCanonicalName(utils.toFileURL(file) + '!' + pluginName);
}
<commit_msg>fix to check for current path "." in file list<commit_after>import Promise from 'bluebird';
import whacko from 'whacko';
import fs from 'fs';
import path from 'path';
import globby from 'globby';
import utils from 'systemjs-builder/lib/utils';
import Builder from 'systemjs-builder';
import _ from 'lodash';

export function bundle(cfg) {

  let builder = new Builder(cfg.baseURL, cfg.configPath);
  builder.config(cfg.builderCfg);

  let templates = [];
  let baseURL = path.resolve(cfg.baseURL);
  let outfile = path.resolve(baseURL, cfg.bundleName) + '.html';

  if (fs.existsSync(outfile)) {
    if (!cfg.force) {
      throw new Error(`A bundle named '${outfile}' already exists. Use the --force option to overwrite it.`);
    }
    fs.unlinkSync(outfile);
  }

  globby
    .sync(cfg.includes, {
      cwd: baseURL.replace(/\\/g, '/')
    })
    .forEach(function(file) {
      if(file != '.') {
        file = path.resolve(baseURL, file);
        var content = fs.readFileSync(file, {
          encoding: 'utf8'
        });

        var $ = whacko.load(content);
        var name = getCanonicalName(builder, file, 'view').replace(/!view$/g, '');

        $('template').attr('id', name);
        var template = $.html('template');
        templates.push(template);
      }
    });

  fs.writeFileSync(outfile, templates.join('\n'));

  if (cfg.options.inject) {
    injectLink(outfile, baseURL, cfg.options.inject);
  }

  return Promise.resolve();
}

function injectLink(outfile, baseURL, inject) {
  let bundleFile = path.resolve(baseURL, path.relative(baseURL, outfile));
  var indexFile = path.resolve(baseURL, inject.indexFile);
  var destFile = path.resolve(baseURL, inject.destFile);
  var relpath = path.relative(path.dirname(indexFile), path.dirname(bundleFile)).replace(/\\/g, '/');

  let link = createLink(bundleFile, relpath);
  addLink(link, indexFile, destFile);
}

function addLink(link, indexFile, destFile){
  var content = fs.readFileSync(indexFile, {
    encoding: 'utf8'
  });

  var $ = whacko.load(content);

  if ($('link[aurelia-view-bundle][href="' + link + '"]').length === 0) {
    $('head').append('<link aurelia-view-bundle rel="import" href="' + link + '">');
  }

  fs.writeFileSync(destFile, $.html());
}

function createLink(bundleFile, relpath){
  if (!relpath.startsWith('.')) {
    return relpath ? './' + relpath + '/' + path.basename(bundleFile) : './' + path.basename(bundleFile);
  } else {
    return relpath + '/' + path.basename(bundleFile);
  }
}

function getCanonicalName(builder, file, pluginName) {
  return builder.getCanonicalName(utils.toFileURL(file) + '!' + pluginName);
}
<|endoftext|>


<commit_before>var tabsPresenter = function (presenterPath) {
    window.rhubarb.viewBridgeClasses.ViewBridge.apply(this, arguments);
};

tabsPresenter.prototype = new window.rhubarb.viewBridgeClasses.ViewBridge();
tabsPresenter.prototype.constructor = tabsPresenter;

tabsPresenter.prototype.attachEvents = function () {
    var nodes = this.viewNode.querySelectorAll('li');
    var self = this;

    for(var i = 0; i<nodes.length; i++){
        nodes[i].addEventListener('click',function () {
            var lis = this.parentNode.childNodes;
            var index = Array.prototype.indexOf.call(lis, this);

            self.raiseServerEvent("tabSelected", index);

            for(var j = 0; j<nodes.length; j++){
                nodes[j].classList.remove('selected');
            }

            this.classList.add('selected');
        });
    }
};

window.rhubarb.viewBridgeClasses.TabsViewBridge = tabsPresenter;<commit_msg>Refactoring from presenters to leaves<commit_after>var tabsPresenter = function (leafPath) {
    window.rhubarb.viewBridgeClasses.ViewBridge.apply(this, arguments);
};

tabsPresenter.prototype = new window.rhubarb.viewBridgeClasses.ViewBridge();
tabsPresenter.prototype.constructor = tabsPresenter;

tabsPresenter.prototype.attachEvents = function () {
    var nodes = this.viewNode.querySelectorAll('li');
    var self = this;

    for(var i = 0; i<nodes.length; i++){
        nodes[i].addEventListener('click',function () {
            var lis = this.parentNode.childNodes;
            var index = Array.prototype.indexOf.call(lis, this);

            self.raiseServerEvent("tabSelected", index);

            for(var j = 0; j<nodes.length; j++){
                nodes[j].classList.remove('selected');
            }

            this.classList.add('selected');
        });
    }
};

window.rhubarb.viewBridgeClasses.TabsViewBridge = tabsPresenter;<|endoftext|>


<commit_before>// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/

/*********************************************
This ambient module example console.logs
ambient light and sound levels and whenever a
specified light or sound level trigger is met.
*********************************************/

var tessel = require('tessel');
var ambientlib = require('../');// Replace '../' with 'ambient-attx4' in your own code

var ambient = ambientlib.use(tessel.port['A']);

ambient.on('ready', function () {
 // Get points of light and sound data.
  setInterval( function () {
    ambient.getLightLevel( function(err, ldata) {
      ambient.getSoundLevel( function(err, sdata) {
        console.log("Light level:", ldata.toFixed(8), " ", "Sound Level:", sdata.toFixed(8));
    });
  })}, 500); // The readings will happen every .5 seconds unless the trigger is hit

  ambient.setLightTrigger(0.5);

  // Set a light level trigger
  // The trigger is a float between 0 and 1
  ambient.on('light-trigger', function(data) {
    console.log("Our light trigger was hit:", data);

    // Clear the trigger so it stops firing
    ambient.clearLightTrigger();
    //After 1.5 seconds reset light trigger
    setTimeout(function () {

        ambient.setLightTrigger(0.5);

    },1500);
  });

  // Set a sound level trigger
  // The trigger is a float between 0 and 1
  ambient.setSoundTrigger(0.1);

  ambient.on('sound-trigger', function(data) {
    console.log("Something happened with sound: ", data);

    // Clear it
    ambient.clearSoundTrigger();

    //After 1.5 seconds reset sound trigger
    setTimeout(function () {

        ambient.setSoundTrigger(0.1);

    },1500);

  });
});

ambient.on('error', function (err) {
  console.log(err)
});
<commit_msg>Add space.<commit_after>// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/publicdomain/zero/1.0/

/*********************************************
This ambient module example console.logs
ambient light and sound levels and whenever a
specified light or sound level trigger is met.
*********************************************/

var tessel = require('tessel');
var ambientlib = require('../'); // Replace '../' with 'ambient-attx4' in your own code

var ambient = ambientlib.use(tessel.port['A']);

ambient.on('ready', function () {
 // Get points of light and sound data.
  setInterval( function () {
    ambient.getLightLevel( function(err, ldata) {
      ambient.getSoundLevel( function(err, sdata) {
        console.log("Light level:", ldata.toFixed(8), " ", "Sound Level:", sdata.toFixed(8));
    });
  })}, 500); // The readings will happen every .5 seconds unless the trigger is hit

  ambient.setLightTrigger(0.5);

  // Set a light level trigger
  // The trigger is a float between 0 and 1
  ambient.on('light-trigger', function(data) {
    console.log("Our light trigger was hit:", data);

    // Clear the trigger so it stops firing
    ambient.clearLightTrigger();
    //After 1.5 seconds reset light trigger
    setTimeout(function () {

        ambient.setLightTrigger(0.5);

    },1500);
  });

  // Set a sound level trigger
  // The trigger is a float between 0 and 1
  ambient.setSoundTrigger(0.1);

  ambient.on('sound-trigger', function(data) {
    console.log("Something happened with sound: ", data);

    // Clear it
    ambient.clearSoundTrigger();

    //After 1.5 seconds reset sound trigger
    setTimeout(function () {

        ambient.setSoundTrigger(0.1);

    },1500);

  });
});

ambient.on('error', function (err) {
  console.log(err)
});
<|endoftext|>


<commit_before>var engine = require('player-engine')()
var coversActions = require('./covers.js')
var shuffle = require('shuffle-array')

var actions = {

  // Synchronize the player engine with the loaded state
  PLAYER_SYNCHRONIZE: () => {
    return (dispatch, getState) => {
      // Bind the event listeners to the actions
      engine.on('timeupdate', duration => dispatch(actions.PLAYER_CURRENT_DURATION(duration)))
      engine.on('ended', () => dispatch(actions.PLAYBACK_NEXT()))

      // Get the current state (just after loading)
      const state = getState()

      // Set the old volume and reset playing status
      actions.PLAYER_SET_VOLUME(state.player.volume)
      dispatch(actions.PLAYER_SET_PLAYING(false))

      // Get the filename of the last played song
      const song = getSong(state.player.songId, state)
      const filename = song ? song.filename : false
      if (!filename) {
        // Old file is not here anymore :(
        dispatch(actions.PLAYER_CURRENT_DURATION(0))
      } else {
        // Old file is still here, let's load it! :)
        engine.load(filename)
        engine.seek(state.player.currentDuration)
        coversActions.GET_COVER(song.album, song.artist, song.coverId)(dispatch, getState)
      }
    }
  },

  // Set the player engine to play a song
  PLAYER_SET_SONG: (id, ignoreHistory = false) => {
    return (dispatch, getState) => {
      var state = getState()

      // Don't write multiple times in the history if we are playing the same song
      if (state.player.songId === id) {
        ignoreHistory = true
      }

      // Get the song and the filename
      const song = getSong(id, state)
      const filename = song ? song.filename : false

      // Load and play the file in the engine
      engine.load(filename)
      engine.play()

      // Try and load an cover art
      coversActions.GET_COVER(song.album, song.artist, song.coverId)(dispatch, getState)

      // Update the view
      dispatch({
        type: 'PLAYER_SET_SONG',
        id,
        ignoreHistory
      })
    }
  },

  // Set the playing status to true or false
  PLAYER_SET_PLAYING: (playing) => {
    (playing) ? engine.play() : engine.pause()
    return {
      type: 'PLAYER_SET_PLAYING',
      playing
    }
  },

  // Seek to a position in the player
  PLAYER_SEEK: (duration) => {
    engine.seek(duration)
    return {
      type: 'PLAYER_CURRENT_DURATION',
      duration
    }
  },

  // Set the volume ofo the player
  PLAYER_SET_VOLUME: (volume) => {
    engine.volume(volume)
    return {
      type: 'PLAYER_SET_VOLUME',
      volume
    }
  },

  // Update the current duration of the player
  PLAYER_CURRENT_DURATION: (currentDuration) => {
    return {
      type: 'PLAYER_CURRENT_DURATION',
      currentDuration
    }
  },

  // Play a song and queue the next songs to be played
  PLAYBACK_SONG: (songs, index, push = false) => {
    return (dispatch, getState) => {
      const state = getState()

      songs = songs.map(x => x.id || x)

      if (!push) {
        // Take the first song and play it
        dispatch(actions.PLAYER_SET_SONG(songs[index]))
        dispatch({type: 'SAVE_POSSIBLE_SONG_QUEUE', songs})
        // Remove the played songs
        songs = [...songs.slice(0, index), ...songs.slice(index + 1)]
      }

      if (state.player.randomPlayback) {
        // Random playback, shuffle all possible songs
        shuffle(songs)
      } else {
        // Normal playback, take the songs *after* the clicked song
        songs = [...songs.slice(index)]
      }

      // Queue the rest, but *not* for single songs
      if (songs.length > 0 && !push) {
        dispatch({
          type: 'PLAYBACK_AUTOMATIC_QUEUE',
          songs
        })
      }

      if (songs.length > 0 && push) {
        dispatch({
          type: 'PLAYBACK_AUTOMATIC_QUEUE_PUSH',
          songs
        })
      }
    }
  },

  // Set the previous song for the player out of the history
  PLAYBACK_BACK: () => {
    return (dispatch, getState) => {
      const history = getState().player.history
      var id = history.songs[history.currentIndex - 1]
      dispatch(actions.PLAYER_SET_SONG(id, true))
      dispatch({
        type: 'HISTORY_BACK'
      })
    }
  },

  // Queue a song for playback
  PLAYBACK_USER_QUEUE: (id) => {
    return {
      type: 'PLAYBACK_USER_QUEUE_PUSH',
      id
    }
  },

  // Set the next song for the player
  PLAYBACK_NEXT: () => {
    return (dispatch, getState) => {
      const state = getState()

      // If we have a queue entry, it *always* takes priority
      const userQueue = state.player.userQueue
      if (userQueue.length > 0) {
        dispatch(actions.PLAYER_SET_SONG(userQueue[0]))
        dispatch({
          type: 'PLAYBACK_USER_QUEUE_POP'
        })
        return
      }

      // We have a history entry set, let's use that one.
      const history = state.player.history
      if (history.songs.length - 1 > history.currentIndex) {
        const id = history.songs[history.currentIndex + 1]
        dispatch(actions.PLAYER_SET_SONG(id, true))
        dispatch({
          type: 'HISTORY_NEXT'
        })
        return
      }

      // If we are on infinite playback, make sure that we have songs added to the automatic queue
      const automaticQueue = state.player.automaticQueue
      if (state.player.repeatPlayback && automaticQueue.length <= 15) {
        const index = !state.player.randomPlayback ? 0 : Math.floor(Math.random() * state.player.possibleQueue.length);
        actions.PLAYBACK_SONG(state.player.possibleQueue, index, true)(dispatch, getState)
      }

      // Take the automatically queued songs
      // (e.g. songs of a album or the radio songs)
      if (automaticQueue.length > 0) {
        dispatch(actions.PLAYER_SET_SONG(automaticQueue[0]))
        dispatch({
          type: 'PLAYBACK_AUTOMATIC_QUEUE_POP'
        })
        return
      }

      // Nothing set, let's pause on the last track
      console.log('Queue empty')
      dispatch(actions.PLAYER_SET_PLAYING(false))
      dispatch(actions.PLAYER_SEEK(0))
    }
  },

  // Toggle random playback
  TOGGLE_RANDOM_PLAYBACK: () => {
    return (dispatch, getState) => {
      const state = getState()

      if (!state.player.randomPlayback) {
        dispatch({type: 'SHUFFLE_AUTOMATIC_QUEUE'})
      }

      dispatch({type: 'TOGGLE_RANDOM_PLAYBACK'})
    }
  },

  // Toggle repeat playback
  TOGGLE_REPEAT_PLAYBACK: () => {
    return {type: 'TOGGLE_REPEAT_PLAYBACK'}
  }

}

// Get the song off the state based on a song id
function getSong (songId, state) {
  return state.songs.filter(x => x.id === songId)[0]
}

module.exports = actions
<commit_msg>Add ability to "unshuffle"<commit_after>var engine = require('player-engine')()
var coversActions = require('./covers.js')
var shuffle = require('shuffle-array')

var actions = {

  // Synchronize the player engine with the loaded state
  PLAYER_SYNCHRONIZE: () => {
    return (dispatch, getState) => {
      // Bind the event listeners to the actions
      engine.on('timeupdate', duration => dispatch(actions.PLAYER_CURRENT_DURATION(duration)))
      engine.on('ended', () => dispatch(actions.PLAYBACK_NEXT()))

      // Get the current state (just after loading)
      const state = getState()

      // Set the old volume and reset playing status
      actions.PLAYER_SET_VOLUME(state.player.volume)
      dispatch(actions.PLAYER_SET_PLAYING(false))

      // Get the filename of the last played song
      const song = getSong(state.player.songId, state)
      const filename = song ? song.filename : false
      if (!filename) {
        // Old file is not here anymore :(
        dispatch(actions.PLAYER_CURRENT_DURATION(0))
      } else {
        // Old file is still here, let's load it! :)
        engine.load(filename)
        engine.seek(state.player.currentDuration)
        coversActions.GET_COVER(song.album, song.artist, song.coverId)(dispatch, getState)
      }
    }
  },

  // Set the player engine to play a song
  PLAYER_SET_SONG: (id, ignoreHistory = false) => {
    return (dispatch, getState) => {
      var state = getState()

      // Don't write multiple times in the history if we are playing the same song
      if (state.player.songId === id) {
        ignoreHistory = true
      }

      // Get the song and the filename
      const song = getSong(id, state)
      const filename = song ? song.filename : false

      // Load and play the file in the engine
      engine.load(filename)
      engine.play()

      // Try and load an cover art
      coversActions.GET_COVER(song.album, song.artist, song.coverId)(dispatch, getState)

      // Update the view
      dispatch({
        type: 'PLAYER_SET_SONG',
        id,
        ignoreHistory
      })
    }
  },

  // Set the playing status to true or false
  PLAYER_SET_PLAYING: (playing) => {
    (playing) ? engine.play() : engine.pause()
    return {
      type: 'PLAYER_SET_PLAYING',
      playing
    }
  },

  // Seek to a position in the player
  PLAYER_SEEK: (duration) => {
    engine.seek(duration)
    return {
      type: 'PLAYER_CURRENT_DURATION',
      duration
    }
  },

  // Set the volume ofo the player
  PLAYER_SET_VOLUME: (volume) => {
    engine.volume(volume)
    return {
      type: 'PLAYER_SET_VOLUME',
      volume
    }
  },

  // Update the current duration of the player
  PLAYER_CURRENT_DURATION: (currentDuration) => {
    return {
      type: 'PLAYER_CURRENT_DURATION',
      currentDuration
    }
  },

  // Play a song and queue the next songs to be played
  PLAYBACK_SONG: (songs, index, push = false) => {
    return (dispatch, getState) => {
      const state = getState()

      songs = songs.map(x => x.id || x)

      if (!push) {
        // Take the first song and play it
        dispatch(actions.PLAYER_SET_SONG(songs[index]))
        dispatch({type: 'SAVE_POSSIBLE_SONG_QUEUE', songs})
        // Remove the played songs
        songs = [...songs.slice(0, index), ...songs.slice(index + 1)]
      }

      if (state.player.randomPlayback) {
        // Random playback, shuffle all possible songs
        shuffle(songs)
      } else {
        // Normal playback, take the songs *after* the clicked song
        songs = [...songs.slice(index)]
      }

      // Queue the rest, but *not* for single songs
      if (songs.length > 0 && !push) {
        dispatch({
          type: 'PLAYBACK_AUTOMATIC_QUEUE',
          songs
        })
      }

      if (songs.length > 0 && push) {
        dispatch({
          type: 'PLAYBACK_AUTOMATIC_QUEUE_PUSH',
          songs
        })
      }
    }
  },

  // Set the previous song for the player out of the history
  PLAYBACK_BACK: () => {
    return (dispatch, getState) => {
      const history = getState().player.history
      var id = history.songs[history.currentIndex - 1]
      dispatch(actions.PLAYER_SET_SONG(id, true))
      dispatch({
        type: 'HISTORY_BACK'
      })
    }
  },

  // Queue a song for playback
  PLAYBACK_USER_QUEUE: (id) => {
    return {
      type: 'PLAYBACK_USER_QUEUE_PUSH',
      id
    }
  },

  // Set the next song for the player
  PLAYBACK_NEXT: () => {
    return (dispatch, getState) => {
      const state = getState()

      // If we have a queue entry, it *always* takes priority
      const userQueue = state.player.userQueue
      if (userQueue.length > 0) {
        dispatch(actions.PLAYER_SET_SONG(userQueue[0]))
        dispatch({
          type: 'PLAYBACK_USER_QUEUE_POP'
        })
        return
      }

      // We have a history entry set, let's use that one.
      const history = state.player.history
      if (history.songs.length - 1 > history.currentIndex) {
        const id = history.songs[history.currentIndex + 1]
        dispatch(actions.PLAYER_SET_SONG(id, true))
        dispatch({
          type: 'HISTORY_NEXT'
        })
        return
      }

      // If we are on infinite playback, make sure that we have songs added to the automatic queue
      const automaticQueue = state.player.automaticQueue
      if (state.player.repeatPlayback && automaticQueue.length <= 15) {
        const index = !state.player.randomPlayback ? 0 : Math.floor(Math.random() * state.player.possibleQueue.length)
        actions.PLAYBACK_SONG(state.player.possibleQueue, index, true)(dispatch, getState)
      }

      // Take the automatically queued songs
      // (e.g. songs of a album or the radio songs)
      if (automaticQueue.length > 0) {
        dispatch(actions.PLAYER_SET_SONG(automaticQueue[0]))
        dispatch({
          type: 'PLAYBACK_AUTOMATIC_QUEUE_POP'
        })
        return
      }

      // Nothing set, let's pause on the last track
      console.log('Queue empty')
      dispatch(actions.PLAYER_SET_PLAYING(false))
      dispatch(actions.PLAYER_SEEK(0))
    }
  },

  // Toggle random playback
  TOGGLE_RANDOM_PLAYBACK: () => {
    return (dispatch, getState) => {
      const state = getState()

      if (!state.player.randomPlayback) {
        dispatch({type: 'SHUFFLE_AUTOMATIC_QUEUE'})
      } else {
        const index = state.player.possibleQueue.indexOf(state.player.songId)
        dispatch({
          type: 'PLAYBACK_AUTOMATIC_QUEUE',
          songs: [...state.player.possibleQueue.slice(index + 1)]
        })
      }

      dispatch({type: 'TOGGLE_RANDOM_PLAYBACK'})
    }
  },

  // Toggle repeat playback
  TOGGLE_REPEAT_PLAYBACK: () => {
    return {type: 'TOGGLE_REPEAT_PLAYBACK'}
  }

}

// Get the song off the state based on a song id
function getSong (songId, state) {
  return state.songs.filter(x => x.id === songId)[0]
}

module.exports = actions
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var Tag           = require('../../../models/tag');
var TagHourlyStat = require('../../../models/tagHourlyStat');
var CheckEvent    = require('../../../models/checkEvent');
var async         = require('async');

/**
 * Check Routes
 */
module.exports = function(app) {

  app.get('/tags', function(req, res) {
    Tag
    .find()
    .sort({ name: 1 })
    .exec(function(err, tags) {
      if (err) return next(err);
      res.json(tags);
    });
  });

  // tag route middleware
  var loadTag = function(req, res, next) {
    Tag.findOne({ name: req.params.name }, function(err, tag) {
      if (err) return next(err);
      if (!tag) return res.json(404, { error: 'failed to load tag ' + req.params.name });
      req.tag = tag;
      next();
    });
  };

  app.get('/tags/:name', loadTag, function(req, res, next) {
    res.json(req.tag);
  });

  app.get('/tags/:name/checks/:period/:timestamp', loadTag, function(req, res, next) {
    req.tag.getChecksForPeriod(req.params.period, new Date(parseInt(req.params.timestamp)), function(err, checks) {
      if (err) return next(err);
      res.json(checks);
    })
  });

  app.get('/tags/:name/stat/:period/:timestamp', loadTag, function(req, res, next) {
    req.tag.getSingleStatsForPeriod(req.params.period, new Date(parseInt(req.params.timestamp)), function(err, stat) {
      if(err) return next(err);
      res.json(stat);
    });
  });

  app.get('/tags/:name/stats/:type', loadTag, function(req, res, next) {
    req.tag.getStatsForPeriod(req.params.type, req.query.begin, req.query.end, function(err, stats) {
      if(err) return next(err);
      res.json(stats);
    });
  });

  app.get('/tags/:name/events', function(req, res) {
    var query = {
      tags: req.params.name,
      timestamp: { $gte: req.query.begin || new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) }
    };
    if (req.query.end) {
      query.timestamp.$lte = req.query.end;
    }
    CheckEvent
    .find(query)
    .sort({ timestamp: -1 })
    .select({ tags: 0 })
    .limit(100)
    .exec(function(err, events) {
      if (err) return next(err);
      CheckEvent.aggregateEventsByDay(events, function(err, aggregatedEvents) {
        res.json(aggregatedEvents);
      });
    });
  });

};
<commit_msg>Add API to get checks for a tag<commit_after>/**
 * Module dependencies.
 */

var Tag           = require('../../../models/tag');
var TagHourlyStat = require('../../../models/tagHourlyStat');
var CheckEvent    = require('../../../models/checkEvent');
var Check         = require('../../../models/check');
var async         = require('async');

/**
 * Check Routes
 */
module.exports = function(app) {

  app.get('/tags', function(req, res) {
    Tag
    .find()
    .sort({ name: 1 })
    .exec(function(err, tags) {
      if (err) return next(err);
      res.json(tags);
    });
  });

  // tag route middleware
  var loadTag = function(req, res, next) {
    Tag.findOne({ name: req.params.name }, function(err, tag) {
      if (err) return next(err);
      if (!tag) return res.json(404, { error: 'failed to load tag ' + req.params.name });
      req.tag = tag;
      next();
    });
  };

  app.get('/tags/:name', loadTag, function(req, res, next) {
    res.json(req.tag);
  });

  app.get('/tags/:name/checks', function(req, res, next) {
    Check.find({ tags: req.params.name} ).sort({ isUp: 1, lastChanged: -1 }).exec(function(err, checks) {
      if (err) return next(err);
      res.json(checks);
    });
  });

  app.get('/tags/:name/checks/:period/:timestamp', loadTag, function(req, res, next) {
    req.tag.getChecksForPeriod(req.params.period, new Date(parseInt(req.params.timestamp)), function(err, checks) {
      if (err) return next(err);
      res.json(checks);
    })
  });

  app.get('/tags/:name/stat/:period/:timestamp', loadTag, function(req, res, next) {
    req.tag.getSingleStatsForPeriod(req.params.period, new Date(parseInt(req.params.timestamp)), function(err, stat) {
      if(err) return next(err);
      res.json(stat);
    });
  });

  app.get('/tags/:name/stats/:type', loadTag, function(req, res, next) {
    req.tag.getStatsForPeriod(req.params.type, req.query.begin, req.query.end, function(err, stats) {
      if(err) return next(err);
      res.json(stats);
    });
  });

  app.get('/tags/:name/events', function(req, res) {
    var query = {
      tags: req.params.name,
      timestamp: { $gte: req.query.begin || new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) }
    };
    if (req.query.end) {
      query.timestamp.$lte = req.query.end;
    }
    CheckEvent
    .find(query)
    .sort({ timestamp: -1 })
    .select({ tags: 0 })
    .limit(100)
    .exec(function(err, events) {
      if (err) return next(err);
      CheckEvent.aggregateEventsByDay(events, function(err, aggregatedEvents) {
        res.json(aggregatedEvents);
      });
    });
  });

};
<|endoftext|>