<commit_before>const WindowUtils = require('sdk/window/utils');
const BrowserWindows = require("sdk/windows").browserWindows;
const ViewFor = require("sdk/view/core").viewFor;
const PrivateBrowsing = require("sdk/private-browsing");
const _ = require("sdk/l10n").get;

// The style used by other containers. It's applied by element id so we can't
// use the default definition
const CONTAINER_STYLE =
  "padding: 0.5em 0 1em;" +
  "-moz-padding-start: calc(2em + 24px);" +
  "-moz-padding-end: 1em;";

const DESCRIPTION_STYLE = "white-space: pre-wrap;" +
  "font-size: 110%;" +
  "margin: 0;";

const { Enforcer } = require("./enforcer");

const IdentityPopupIntegration = {
  /**
   * Initiates the identity popup integration.
   */
  init: function () {
    this.refreshIdentityPopup = this.refreshIdentityPopup.bind(this);
    this.updateEnforcementStatus = this.updateEnforcementStatus.bind(this);

    // Bug 1196577 - BrowserWindows does not include pre-existing private
    // browsing windows when addon enabled or installed
    //
    // Thus we need to se sdk/window/utils instead which allows us specify that
    // we want them too.
    for (let window of WindowUtils.windows(null, { includePrivate: true }))
      this._attachIdentityPopup(window);

    BrowserWindows.on("open", window => {
      if (PrivateBrowsing.isPrivate(window)) {
        // Ensure that STS is still enforced for private contexts. They are
        // stored in-memory and cleared from time to time.
        Enforcer.ensureSTS();
      }

      // Plug into the identity popup.
      this._attachIdentityPopup(window);
    });
  },

  /**
   * A helper that creates an element.
   *
   * @param {Document} document
   *        The document to create the element to.
   * @param {String} tagName
   *        The element type.
   * @param {Object} attributes.
   *        Attributes of this element as key-value pairs. Optional.
   * @param {String} textContent
   *        The textContent of this element.
   */
  createElement: function (document, tagName, attributes, textContent) {
    let result = document.createElement(tagName);
    for (let key in attributes)
      result.setAttribute(key, attributes[key]);

    if (textContent)
      result.textContent = textContent;

    return result;
  },

  /**
   * Attaches into identity popup of the given window.
   *
   * @param {Window} window
   *        The chrome window to attach to.
   */
  _attachIdentityPopup: function (window) {
    let dom = ViewFor(window);
    if (!dom)
      return console.error("Can't get a DOMWindow from window object.");

    let doc = dom.document;
    if (!doc)
      return console.error("DOMWindow does not have a document.");

    let popup = doc.getElementById("identity-popup");
    if (!popup)
      return console.error("The chrome document does not contain #identity-popup");

    let section = this.createElement(doc, "hbox", {
      "class": "identity-popup-section",
      id: "sts-section"
    });

    let container = this.createElement(doc, "vbox", {
      flex: 1,
      style: CONTAINER_STYLE
    });

    let header = this.createElement(doc, "description", {
      "class": "identity-popup-headline",
      crop: "end",
      value: _("ui.status.title")
    });

    let status = this.createElement(doc, "description", {
      id: "sts-status",
      style: DESCRIPTION_STYLE
    }, _("ui.status.error"));

    let checkboxContainer = this.createElement(doc, "vbox", {
      id: "sts-checkboxes",
      flex: 1
    });

    let cbCurrentDomain = this.createElement(doc, "checkbox", {
      label: _("ui.checkbox.enforce"),
      id: "sts-cb-enforce"
    })

    let cbInclude = this.createElement(doc, "checkbox", {
      label: _("ui.checkbox.include_sub"),
      id: "sts-cb-include"
    });

    checkboxContainer.appendChild(cbCurrentDomain);
    checkboxContainer.appendChild(cbInclude);

    section.appendChild(container);
    container.appendChild(header);
    container.appendChild(status);
    container.appendChild(checkboxContainer);

    popup.addEventListener("popupshowing", this.refreshIdentityPopup);

    cbCurrentDomain.addEventListener("command", this.updateEnforcementStatus);
    cbInclude.addEventListener("command", this.updateEnforcementStatus);

    doc.getElementById("identity-popup-mainView").appendChild(section);
  },

  /**
   * Event handler for the STS checkbox.
   */
  updateEnforcementStatus: function (event) {
    let doc = event.target.ownerDocument;
    let uri = doc.getElementById("content").currentURI;

    let enforce = doc.getElementById("sts-cb-enforce");
    let include = doc.getElementById("sts-cb-include");

    Enforcer.setSTSForHost(uri.host, enforce.checked, include.checked);

    this.refreshIdentityPopup(event);
  },

  /**
   * Refreshes the STS status for the identity popup of the target window of
   * the event.
   */
  refreshIdentityPopup: function (event) {
    let popup = event.target;
    let doc = popup.ownerDocument;
    let uri = doc.getElementById("content").currentURI;
    let section = doc.getElementById("sts-section");
    let status = doc.getElementById("sts-status");
    let enforce = doc.getElementById("sts-cb-enforce");
    let include = doc.getElementById("sts-cb-include");
    if (!uri.schemeIs("https")) {
      section.hidden = true;
      return;
    }

    // Reset all state.
    section.hidden = false;
    include.hidden = false;
    enforce.hidden = false;
    include.disable = false;
    enforce.disable = false;
    include.checked = false;
    enforce.checked = false;

    switch (Enforcer.getSTSStatusForHost(uri.host)) {
      case Enforcer.status.USER_ENFORCED:
        status.textContent = _("ui.status.user_enforced");
        enforce.checked = true;
        break;

      case Enforcer.status.USER_ENFORCED_WITH_SUBDOMAINS:
        status.textContent = _("ui.status.user_enforced");
        include.checked = true;
        enforce.checked = true;
        break;

      case Enforcer.status.USER_ENFORCED_PARENT:
        let h = Enforcer.getEnforcingParentHost(uri.host)
        status.textContent = _("ui.status.user_enforced_parent", h);

        include.disabled = true;
        include.checked = true;

        enforce.disabled = true;
        enforce.checked = true;
        break;

      case Enforcer.status.SITE_ENFORCED:
        status.textContent = _("ui.status.site_enforced");
        include.hidden = true;
        enforce.hidden = true;
        break;

      case Enforcer.status.NOT_ENFORCED:
        status.textContent = _("ui.status.not_enforced");
        break;
    }
  },

  destroy: function () {
    console.log("destroy")
    for (let window of WindowUtils.windows(null, { includePrivate: true })) {
      let dom = ViewFor(window);
      if (!dom)
        return console.error("Can't get a DOMWindow from window object.");

      let doc = dom.document;
      if (!doc)
        return console.error("DOMWindow does not have a document.");

      let popup = doc.getElementById("identity-popup");
      if (!popup)
        return console.error("The chrome document does not contain #identity-popup");

      popup.removeEventListener("popupshowing", this.refreshIdentityPopup);

      let status = doc.getElementById("sts-section");
      if (status) {
        status.remove();

        // Remove checkbox listeners
        let cbEnforce = doc.getElementById("sts-cb-enforce");
        let cbInclude = doc.getElementById("sts-cb-include");

        cbEnforce.removeEventListener("command", this.updateEnforcementStatus);
        cbInclude.removeEventListener("command", this.updateEnforcementStatus);
      }
    }
  }

};

exports.IdentityPopupIntegration = IdentityPopupIntegration;
<commit_msg>Small refactoring cleanups<commit_after>const WindowUtils = require('sdk/window/utils');
const BrowserWindows = require("sdk/windows").browserWindows;
const ViewFor = require("sdk/view/core").viewFor;
const PrivateBrowsing = require("sdk/private-browsing");
const _ = require("sdk/l10n").get;

// The style used by other containers. It's applied by element id so we can't
// use the default definition
const CONTAINER_STYLE =
  "padding: 0.5em 0 1em;" +
  "-moz-padding-start: calc(2em + 24px);" +
  "-moz-padding-end: 1em;";

const DESCRIPTION_STYLE = "white-space: pre-wrap;" +
  "font-size: 110%;" +
  "margin: 0;";

const { Enforcer } = require("./enforcer");

const IdentityPopupIntegration = {
  /**
   * Initiates the identity popup integration.
   */
  init: function () {
    this.refreshIdentityPopup = this.refreshIdentityPopup.bind(this);
    this.updateEnforcementStatus = this.updateEnforcementStatus.bind(this);

    // Bug 1196577 - BrowserWindows does not include pre-existing private
    // browsing windows when addon enabled or installed
    //
    // Thus we need to se sdk/window/utils instead which allows us specify that
    // we want them too.
    for (let window of WindowUtils.windows(null, { includePrivate: true }))
      this._attachIdentityPopup(window);

    BrowserWindows.on("open", window => {
      if (PrivateBrowsing.isPrivate(window)) {
        // Ensure that STS is still enforced for private contexts. They are
        // stored in-memory and cleared from time to time.
        Enforcer.ensureSTS();
      }

      // Plug into the identity popup.
      this._attachIdentityPopup(window);
    });
  },

  /**
   * A helper that creates an element.
   *
   * @param {Document} document
   *        The document to create the element to.
   * @param {String} tagName
   *        The element type.
   * @param {Object} attributes.
   *        Attributes of this element as key-value pairs. Optional.
   * @param {String} textContent
   *        The textContent of this element.
   */
  createElement: function (document, tagName, attributes, textContent) {
    let result = document.createElement(tagName);
    for (let key in attributes)
      result.setAttribute(key, attributes[key]);

    if (textContent)
      result.textContent = textContent;

    return result;
  },

  /**
   * Attaches into identity popup of the given window.
   *
   * @param {Window} window
   *        The chrome window to attach to.
   */
  _attachIdentityPopup: function (window) {
    let { doc, popup } = this.popupFor(window);

    if (!doc || !popup) {
      // Nothing to add here.
      return;
    }

    // The outer container for everything.
    let section = this.createElement(doc, "hbox", {
      "class": "identity-popup-section",
      id: "sts-section"
    });

    // Inner container for text
    let container = this.createElement(doc, "vbox", {
      flex: 1,
      style: CONTAINER_STYLE
    });

    let header = this.createElement(doc, "description", {
      "class": "identity-popup-headline",
      crop: "end",
      value: _("ui.status.title")
    });

    let status = this.createElement(doc, "description", {
      id: "sts-status",
      style: DESCRIPTION_STYLE
    }, _("ui.status.error"));

    let checkboxContainer = this.createElement(doc, "vbox", {
      id: "sts-checkboxes",
      flex: 1
    });

    let cbCurrentDomain = this.createElement(doc, "checkbox", {
      label: _("ui.checkbox.enforce"),
      id: "sts-cb-enforce"
    })

    let cbInclude = this.createElement(doc, "checkbox", {
      label: _("ui.checkbox.include_sub"),
      id: "sts-cb-include"
    });

    checkboxContainer.appendChild(cbCurrentDomain);
    checkboxContainer.appendChild(cbInclude);

    section.appendChild(container);
    container.appendChild(header);
    container.appendChild(status);
    container.appendChild(checkboxContainer);

    popup.addEventListener("popupshowing", this.refreshIdentityPopup);

    cbCurrentDomain.addEventListener("command", this.updateEnforcementStatus);
    cbInclude.addEventListener("command", this.updateEnforcementStatus);

    doc.getElementById("identity-popup-mainView").appendChild(section);
  },

  /**
   * Event handler for the STS checkbox.
   */
  updateEnforcementStatus: function (event) {
    let doc = event.target.ownerDocument;
    let uri = doc.getElementById("content").currentURI;
    let section = doc.getElementById("sts-section");
    let { enforce, include } = this.checkboxesFor(section);

    // Update the state according to the checkboxes.
    Enforcer.setSTSForHost(uri.host, enforce.checked, include.checked);

    // Update the UI.
    this.refreshIdentityPopup(event);
  },

  /**
   * Refreshes the STS status for the identity popup of the target window of
   * the event.
   */
  refreshIdentityPopup: function (event) {
    let doc = event.target.ownerDocument;
    let uri = doc.getElementById("content").currentURI;
    let section = doc.getElementById("sts-section");
    if (!uri.schemeIs("https")) {
      section.hidden = true;
      return;
    }

    // Get the relevant nodes
    let status = doc.getElementById("sts-status");
    let { enforce, include } = this.checkboxesFor(status);

    // Reset all checkbox state.
    section.hidden = false;
    include.hidden = false;
    enforce.hidden = false;
    include.disable = false;
    enforce.disable = false;
    include.checked = false;
    enforce.checked = false;

    switch (Enforcer.getSTSStatusForHost(uri.host)) {
      case Enforcer.status.USER_ENFORCED:
        status.textContent = _("ui.status.user_enforced");
        enforce.checked = true;
        break;

      case Enforcer.status.USER_ENFORCED_WITH_SUBDOMAINS:
        status.textContent = _("ui.status.user_enforced");
        include.checked = true;
        enforce.checked = true;
        break;

      case Enforcer.status.USER_ENFORCED_PARENT:
        let h = Enforcer.getEnforcingParentHost(uri.host)
        status.textContent = _("ui.status.user_enforced_parent", h);

        // Should be edited in the parent domain, not here.
        include.disabled = true;
        include.checked = true;

        enforce.disabled = true;
        enforce.checked = true;
        break;

      case Enforcer.status.SITE_ENFORCED:
        status.textContent = _("ui.status.site_enforced");
        // Don't even show the controls since the site is enforcing STS.
        include.hidden = true;
        enforce.hidden = true;
        break;

      case Enforcer.status.NOT_ENFORCED:
        status.textContent = _("ui.status.not_enforced");
        break;
    }
  },

  destroy: function () {
    for (let win of WindowUtils.windows(null, { includePrivate: true })) {
      let { doc, popup } = this.popupFor(win);

      popup.removeEventListener("popupshowing", this.refreshIdentityPopup);

      let status = doc.getElementById("sts-section");
      if (status) {
        // Remove checkbox listeners.
        let { enforce, include } = this.checkboxesFor(status);
        enforce.removeEventListener("command", this.updateEnforcementStatus);
        include.removeEventListener("command", this.updateEnforcementStatus);

        // Remove the section.
        status.remove();
      }
    }
  },

  /**
   * Resolves the document and identity popup for given window
   *
   * @param {Object} window
   *        The Jetpack window object to use.
   *
   * @return an object with form { popup, doc } with the popup and document of
   *   this window (both null if not avaialble).
   */
  popupFor: function(window) {
    let dom = ViewFor(window);
    if (!dom) {
      console.error("Can't get a DOMWindow from window object.");
      return { popup: null, doc: null };
    }

    let doc = dom.document;
    if (!doc){
      console.error("DOMWindow does not have a document.");
      return { popup: null, doc: null };
    }

    let popup = doc.getElementById("identity-popup");
    if (!popup) {
      console.error("The chrome document does not contain #identity-popup");
      return { popup, doc };
    }
  },

  /**
   * Retrieve the STS checkboxes for the given identity popup.
   *
   * @param {Element} el
   *        The identity popup or STS status container to retrieve the
   *        checkboxes from.
   * @return An object of form { enforce, include } where enforce is the
   * Enforce STS checkbox and include the Include Subdomains checkbox.
   */
  checkboxesFor: function(el) {
    let enforce = el.ownerDocument.getElementById("sts-cb-enforce");
    let include = el.ownerDocument.getElementById("sts-cb-enforce");

    return { enforce, include };
  }
};

exports.IdentityPopupIntegration = IdentityPopupIntegration;
<|endoftext|>


<commit_before>function UploadFileController($scope, $http, mcapi, User, formDataObject) {
    $scope.files = [];
    $scope.percentage = 0;

    mcapi('/user/%/datadirs', User.u())
        .success(function (data) {
            $scope.datagroups = data;
        }).jsonp();

    $scope.addFile = function (element) {
        $scope.$apply(function () {
            var obj = {};
            obj.file = element.files[0];
            obj.status = "Ready";
            obj.datagroup = $scope.datagroup;
            $scope.files.push(obj);
        });
    }

    $scope.uploadEachFile = function (mp, ep) {
        if ($scope.files.length == 0) {
            return;
        }

        $scope.files.forEach(function (fileEntry) {
            if (fileEntry.status != "Uploaded") {
                var url = mcurl("/user/%/upload/%", User.u(), fileEntry.datagroup);
                fileEntry.status = "Uploading...";
                $http({
                    method: 'POST',
                    url: url,
                    headers: {'Content-Type': false},
                    data: { file: fileEntry.file},
                    transformRequest: formDataObject
                })
                    .success(function () {
                        fileEntry.status = "Uploaded";
                    })
                    .error(function () {
                        fileEntry.status = "Failed";
                    });
            }
        });
    };
}

function UploadDirectoryController($scope, mcapi, User) {
    $scope.files = [];
    $scope.percentage = 0;
    $scope.uploadurl = "notset";

    mcapi('/user/%/datadirs', User.u())
        .success(function (data) {
            $scope.datagroups = data;
        }).jsonp();

}

function UpDownLoadQueueController($scope, mcapi, User) {
    mcapi('/user/%/udqueue', User.u())
        .success(function (data) {
            $scope.udentries = data;
        }).jsonp();
}
<commit_msg>Add comment for how to use $http.post() request for uploads.<commit_after>function UploadFileController($scope, $http, mcapi, User, formDataObject) {
    $scope.files = [];
    $scope.percentage = 0;

    mcapi('/user/%/datadirs', User.u())
        .success(function (data) {
            $scope.datagroups = data;
        }).jsonp();

    $scope.addFile = function (element) {
        $scope.$apply(function () {
            var obj = {};
            obj.file = element.files[0];
            obj.status = "Ready";
            obj.datagroup = $scope.datagroup;
            $scope.files.push(obj);
        });
    }

    $scope.uploadEachFile = function (mp, ep) {
        if ($scope.files.length == 0) {
            return;
        }

        $scope.files.forEach(function (fileEntry) {
            if (fileEntry.status != "Uploaded") {
                var url = mcurl("/user/%/upload/%", User.u(), fileEntry.datagroup);
                fileEntry.status = "Uploading...";
                /*
                For mcapi this looks like:
                mcapi('/user/%/upload/%', User.u(), fileEntry.datagroup)
                    .success(function() { fileEntry.status = "Uploaded"; })
                    .error(function() { fileEntry.status = "Failed"; })
                    .post({file: fileEntry.file},
                          {headers: {'Content-Type': false}}, transformRequest:formDataObject});
                 */
                $http({
                    method: 'POST',
                    url: url,
                    headers: {'Content-Type': false},
                    data: { file: fileEntry.file},
                    transformRequest: formDataObject
                })
                    .success(function () {
                        fileEntry.status = "Uploaded";
                    })
                    .error(function () {
                        fileEntry.status = "Failed";
                    });
            }
        });
    };
}

function UploadDirectoryController($scope, mcapi, User) {
    $scope.files = [];
    $scope.percentage = 0;
    $scope.uploadurl = "notset";

    mcapi('/user/%/datadirs', User.u())
        .success(function (data) {
            $scope.datagroups = data;
        }).jsonp();

}

function UpDownLoadQueueController($scope, mcapi, User) {
    mcapi('/user/%/udqueue', User.u())
        .success(function (data) {
            $scope.udentries = data;
        }).jsonp();
}
<|endoftext|>


<commit_before>var roleHealer = require('role.healer');

var roleBuilder = {

	/** @param {Creep} creep **/
	run: function(creep, target) {

		if (creep.memory.harvesting) {
			var sources = creep.room.find(FIND_SOURCES);
			// var spawns = creep.room.find(FIND_STRUCTURES, {
			// 	filter: (structure) => {
			// 		return (
			// 					 (structure.structureType == STRUCTURE_CONTAINER) &&
			// 					 (structure.store[RESOURCE_ENERGY] > creep.carryCapacity));
			// 	}
			// });

			// if (sources.length) {
				if (!creep.memory.source) {
					for (source in sources) {
						if (_.filter(Game.creeps, (creep) =>
								(creep.memory.role == 'builder') &&
								(creep.memory.source == source)
						).length != 1) {
							creep.memory.source = source;
						}
					}
				}
				//var target = creep.pos.findClosestByRange(spawns);

				if (!(creep.pos.isNearTo(target))) {
					creep.moveTo(target);
				}
				else {
					creep.harvest(target, RESOURCE_ENERGY,
												(creep.carryCapacity - _.sum(creep.carry)));
				}
			// }
			if (creep.carry.energy == creep.carryCapacity) {
					creep.say('Building');
			    creep.memory.harvesting = false;
			}
		}
		else {
		  var targets = creep.room.find(FIND_CONSTRUCTION_SITES);

			if (targets.length) {
				var target = creep.pos.findClosestByRange(targets);
				if (creep.build(target) == ERR_NOT_IN_RANGE) {
					creep.moveTo(target);
				}
				else {
					roleHealer.run(creep);
				}
				if (creep.carry.energy == 0) {
					creep.say('Harvesting');
					creep.memory.harvesting = true;
				}
			}
		}

	} // function

}; // roleBuilder

module.exports = roleBuilder;<commit_msg>Fix typo<commit_after>var roleHealer = require('role.healer');

var roleBuilder = {

	/** @param {Creep} creep **/
	run: function(creep, target) {

		if (creep.memory.harvesting) {
			var sources = creep.room.find(FIND_SOURCES);
			// var spawns = creep.room.find(FIND_STRUCTURES, {
			// 	filter: (structure) => {
			// 		return (
			// 					 (structure.structureType == STRUCTURE_CONTAINER) &&
			// 					 (structure.store[RESOURCE_ENERGY] > creep.carryCapacity));
			// 	}
			// });

			// if (sources.length) {
				if (!creep.memory.source) {
					for (source in sources) {
						if (_.filter(Game.creeps, (creep) =>
								(creep.memory.role == 'builder') &&
								(creep.memory.source == source)
						).length != 1) {
							creep.memory.source = source;
						}
					}
				}
				//var target = creep.pos.findClosestByRange(spawns);

				if (!(creep.pos.isNearTo(source))) {
					creep.moveTo(source);
				}
				else {
					creep.harvest(source, RESOURCE_ENERGY,
												(creep.carryCapacity - _.sum(creep.carry)));
				}
			// }
			if (creep.carry.energy == creep.carryCapacity) {
					creep.say('Building');
			    creep.memory.harvesting = false;
			}
		}
		else {
		  var targets = creep.room.find(FIND_CONSTRUCTION_SITES);

			if (targets.length) {
				var target = creep.pos.findClosestByRange(targets);
				if (creep.build(target) == ERR_NOT_IN_RANGE) {
					creep.moveTo(target);
				}
				else {
					roleHealer.run(creep);
				}
				if (creep.carry.energy == 0) {
					creep.say('Harvesting');
					creep.memory.harvesting = true;
				}
			}
		}

	} // function

}; // roleBuilder

module.exports = roleBuilder;<|endoftext|>


<commit_before>"use strict";

var assert = require('assert');

var DEAD = 0;
var LIVE = 1;

var sampleInput = "4 8\n........\n....*...\n...**...\n........\n";

var Game = function(r,c) {
  var game = {
      rows: r,
      cols: c,
      neighbours: function(c,r) {
        var n = 0;
        for (var i=-1;i<=1;++i) {
          for (var j=-1;j<=1;++j) {
            if (i === 0 && j === 0) {
              continue;
            }

            if (this[c+j] && this[c+j][r+i] === LIVE) {
              ++n;
            }
          }
        }
        return n;
      }
  };
  return game;
};

var createGrid = function(s) {
  var lines = s.split('\n');
  var rc = lines[0].split(' ');
  var rows = rc[0] | 0; // 4
  var cols = rc[1] | 0; // 8

  var game = new Game(rows,cols);

  for (var i=0;i<rows;++i) {
    for (var j=0;j<cols;++j) {
      var v = lines[1+i][j];
      if (game[j] === undefined) { game[j] = []; }
      game[j][i] = v === '*' ? LIVE : DEAD;
    }
  }

  return game;
};

var cellState = function(state,neighbours) {
  if (neighbours < 2 && state === LIVE) {
    return DEAD;
  }
  else if (neighbours > 3 && state === LIVE) {
    return DEAD;
  }
  else if ((neighbours === 2 || neighbours === 3) && state === LIVE) {
    return LIVE;
  }
  else if (neighbours === 3 && state === DEAD) {
    return LIVE;
  }
  else {
    return DEAD;
  }
};

describe('game of life', function() {
  describe('cell', function() {
    it('dies with underpopulation', function() {
      assert.equal(DEAD, cellState(LIVE,1));
    });

    it('dies with overcrowding', function() {
      assert.equal(DEAD, cellState(LIVE,4));
    });

    it('maintains live if 2 or three neighbours', function() {
      assert.equal(LIVE, cellState(LIVE,2));
      assert.equal(LIVE, cellState(LIVE,3));
    });

    it('becomes alive', function() {
      assert.equal(LIVE, cellState(DEAD,3));
    });

    it('is fully defined', function() {
      for (var i=0;i<=8;++i) {
        assert(undefined !== cellState(DEAD,i));
        assert(undefined !== cellState(LIVE,i));
      }
    });
  });

  describe('grid', function() {
    it('should read input', function() {
      var grid = createGrid(sampleInput);

      assert.equal(4, grid.rows);

      assert.equal(DEAD, grid[0][0]);
      assert.equal(LIVE, grid[4][1]);
      assert.equal(LIVE, grid[3][2]);
      assert.equal(LIVE, grid[4][2]);
    });

    it('should be able to get the number of live neighbours', function() {
      var grid = createGrid(sampleInput);

      assert.equal(0, grid.neighbours(0,0));
      assert.equal(2, grid.neighbours(3,2));

      grid = createGrid('2 2\n..\n..');
      assert.equal(0, grid.neighbours(0,0));
      assert.equal(0, grid.neighbours(1,0));
      assert.equal(0, grid.neighbours(0,1));
      assert.equal(0, grid.neighbours(1,1));

      grid = createGrid('2 2\n**\n**');
      assert.equal(3, grid.neighbours(0,0));
      assert.equal(3, grid.neighbours(1,0));
      assert.equal(3, grid.neighbours(0,1));
      assert.equal(3, grid.neighbours(1,1));
    });

    it('should have a sensible printed representation', function() {
      var grid = createGrid('1 1\n.');
      assert.equal('1 1\n.\n', grid.to_string());
    });
  });
});

<commit_msg>sensiblish to_string representation<commit_after>"use strict";

var assert = require('assert');

var DEAD = 0;
var LIVE = 1;

var sampleInput = "4 8\n........\n....*...\n...**...\n........\n";

var Game = function(r,c) {
  var game = {
      rows: r,
      cols: c,
      neighbours: function(c,r) {
        var n = 0;
        for (var i=-1;i<=1;++i) {
          for (var j=-1;j<=1;++j) {
            if (i === 0 && j === 0) {
              continue;
            }

            if (this[c+j] && this[c+j][r+i] === LIVE) {
              ++n;
            }
          }
        }
        return n;
      },
      to_string: function() {
        var s = this.rows + ' ' + this.cols + '\n';
        for (var i=0;i<this.rows;++i) {
          for (var j=0;j<this.cols;++j) {
            s+= (this[j][i] === LIVE ? '*' : '.');
          }
          s+='\n';
        }
        return s;
      }
  };
  return game;
};

var createGrid = function(s) {
  var lines = s.split('\n');
  var rc = lines[0].split(' ');
  var rows = rc[0] | 0; // 4
  var cols = rc[1] | 0; // 8

  var game = new Game(rows,cols);

  for (var i=0;i<rows;++i) {
    for (var j=0;j<cols;++j) {
      var v = lines[1+i][j];
      if (game[j] === undefined) { game[j] = []; }
      game[j][i] = v === '*' ? LIVE : DEAD;
    }
  }

  return game;
};

var cellState = function(state,neighbours) {
  if (neighbours < 2 && state === LIVE) {
    return DEAD;
  }
  else if (neighbours > 3 && state === LIVE) {
    return DEAD;
  }
  else if ((neighbours === 2 || neighbours === 3) && state === LIVE) {
    return LIVE;
  }
  else if (neighbours === 3 && state === DEAD) {
    return LIVE;
  }
  else {
    return DEAD;
  }
};

describe('game of life', function() {
  describe('cell', function() {
    it('dies with underpopulation', function() {
      assert.equal(DEAD, cellState(LIVE,1));
    });

    it('dies with overcrowding', function() {
      assert.equal(DEAD, cellState(LIVE,4));
    });

    it('maintains live if 2 or three neighbours', function() {
      assert.equal(LIVE, cellState(LIVE,2));
      assert.equal(LIVE, cellState(LIVE,3));
    });

    it('becomes alive', function() {
      assert.equal(LIVE, cellState(DEAD,3));
    });

    it('is fully defined', function() {
      for (var i=0;i<=8;++i) {
        assert(undefined !== cellState(DEAD,i));
        assert(undefined !== cellState(LIVE,i));
      }
    });
  });

  describe('grid', function() {
    it('should read input', function() {
      var grid = createGrid(sampleInput);

      assert.equal(4, grid.rows);

      assert.equal(DEAD, grid[0][0]);
      assert.equal(LIVE, grid[4][1]);
      assert.equal(LIVE, grid[3][2]);
      assert.equal(LIVE, grid[4][2]);
    });

    it('should be able to get the number of live neighbours', function() {
      var grid = createGrid(sampleInput);

      assert.equal(0, grid.neighbours(0,0));
      assert.equal(2, grid.neighbours(3,2));

      grid = createGrid('2 2\n..\n..');
      assert.equal(0, grid.neighbours(0,0));
      assert.equal(0, grid.neighbours(1,0));
      assert.equal(0, grid.neighbours(0,1));
      assert.equal(0, grid.neighbours(1,1));

      grid = createGrid('2 2\n**\n**');
      assert.equal(3, grid.neighbours(0,0));
      assert.equal(3, grid.neighbours(1,0));
      assert.equal(3, grid.neighbours(0,1));
      assert.equal(3, grid.neighbours(1,1));
    });

    it('should have a sensible printed representation', function() {
      var grid = createGrid('1 1\n.');
      assert.equal('1 1\n.\n', grid.to_string());
    });
  });
});

<|endoftext|>


<commit_before>(function(global) {
  var RS = RemoteStorage;

  /**
   * Class: RemoteStorage.WireClient
   *
   * WireClient Interface
   * --------------------
   *
   * This file exposes a get/put/delete interface on top of XMLHttpRequest.
   * It requires to be configured with parameters about the remotestorage server to
   * connect to.
   * Each instance of WireClient is always associated with a single remotestorage
   * server and access token.
   *
   * Usually the WireClient instance can be accessed via `remoteStorage.remote`.
   *
   * This is the get/put/delete interface:
   *
   *   - #get() takes a path and optionally a ifNoneMatch option carrying a version
   *     string to check. It returns a promise that will be fulfilled with the HTTP
   *     response status, the response body, the MIME type as returned in the
   *     'Content-Type' header and the current revision, as returned in the 'ETag'
   *     header.
   *   - #put() takes a path, the request body and a content type string. It also
   *     accepts the ifMatch and ifNoneMatch options, that map to the If-Match and
   *     If-None-Match headers respectively. See the remotestorage-01 specification
   *     for details on handling these headers. It returns a promise, fulfilled with
   *     the same values as the one for #get().
   *   - #delete() takes a path and the ifMatch option as well. It returns a promise
   *     fulfilled with the same values as the one for #get().
   *
   * In addition to this, the WireClient has some compatibility features to work with
   * remotestorage 2012.04 compatible storages. For example it will cache revisions
   * from folder listings in-memory and return them accordingly as the "revision"
   * parameter in response to #get() requests. Similarly it will return 404 when it
   * receives an empty folder listing, to mimic remotestorage-01 behavior. Note
   * that it is not always possible to know the revision beforehand, hence it may
   * be undefined at times (especially for caching-roots).
   */

  var hasLocalStorage;
  var SETTINGS_KEY = "remotestorage:wireclient";

  var API_2012 = 1, API_00 = 2, API_01 = 3, API_02 = 4, API_HEAD = 5;

  var STORAGE_APIS = {
    'draft-dejong-remotestorage-00': API_00,
    'draft-dejong-remotestorage-01': API_01,
    'draft-dejong-remotestorage-02': API_02,
    'https://www.w3.org/community/rww/wiki/read-write-web-00#simple': API_2012
  };

  var isArrayBufferView;

  if (typeof(ArrayBufferView) === 'function') {
    isArrayBufferView = function(object) { return object && (object instanceof ArrayBufferView); };
  } else {
    var arrayBufferViews = [
      Int8Array, Uint8Array, Int16Array, Uint16Array,
      Int32Array, Uint32Array, Float32Array, Float64Array
    ];
    isArrayBufferView = function(object) {
      for (var i=0;i<8;i++) {
        if (object instanceof arrayBufferViews[i]) {
          return true;
        }
      }
      return false;
    };
  }

  function addQuotes(str) {
    if (typeof(str) !== 'string') {
      return str;
    }
    if (str === '*') {
      return '*';
    }

    return '"' + str + '"';
  }

  function stripQuotes(str) {
    if (typeof(str) !== 'string') {
      return str;
    }

    return str.replace(/^["']|["']$/g, '');
  }

  function readBinaryData(content, mimeType, callback) {
    var blob = new Blob([content], { type: mimeType });
    var reader = new FileReader();
    reader.addEventListener("loadend", function() {
      callback(reader.result); // reader.result contains the contents of blob as a typed array
    });
    reader.readAsArrayBuffer(blob);
  }

  function cleanPath(path) {
    return path.replace(/\/+/g, '/').split('/').map(encodeURIComponent).join('/');
  }

  function isFolder(path) {
    return (path.substr(-1) === '/');
  }

  function isFolderDescription(body) {
    return ((body['@context'] === 'http://remotestorage.io/spec/folder-description')
             && (typeof(body['items']) === 'object'));
  }

  function isSuccessStatus(status) {
    return [201, 204, 304].indexOf(status) >= 0;
  }

  function isErrorStatus(status) {
    return [401, 403, 404, 412].indexOf(status) >= 0;
  }

  var onErrorCb;

  /**
   * Class : RemoteStorage.WireClient
   **/
  RS.WireClient = function(rs) {
    this.connected = false;

    /**
     * Event: change
     *   never fired for some reason
     *
     * Event: connected
     *   fired when the wireclient connect method realizes that it is
     *   in posession of a token and a href
     **/
    RS.eventHandling(this, 'change', 'connected', 'wire-busy', 'wire-done', 'not-connected');

    onErrorCb = function(error){
      if (error instanceof RemoteStorage.Unauthorized) {
        this.configure(undefined, undefined, undefined, null);
      }
    }.bind(this);
    rs.on('error', onErrorCb);
    if (hasLocalStorage) {
      var settings;
      try { settings = JSON.parse(localStorage[SETTINGS_KEY]); } catch(e) {}
      if (settings) {
        setTimeout(function() {
          this.configure(settings.userAddress, settings.href, settings.storageApi, settings.token);
        }.bind(this), 0);
      }
    }

    this._revisionCache = {};

    if (this.connected) {
      setTimeout(this._emit.bind(this), 0, 'connected');
    }
  };

  RS.WireClient.REQUEST_TIMEOUT = 30000;

  RS.WireClient.prototype = {
    /**
     * Property: token
     *
     * Holds the bearer token of this WireClient, as obtained in the OAuth dance
     *
     * Example:
     *   (start code)
     *
     *   remoteStorage.remote.token
     *   // -> 'DEADBEEF01=='
     */

    /**
     * Property: href
     *
     * Holds the server's base URL, as obtained in the Webfinger discovery
     *
     * Example:
     *   (start code)
     *
     *   remoteStorage.remote.href
     *   // -> 'https://storage.example.com/users/jblogg/'
     */

    /**
     * Property: storageApi
     *
     * Holds the spec version the server claims to be compatible with
     *
     * Example:
     *   (start code)
     *
     *   remoteStorage.remote.storageApi
     *   // -> 'draft-dejong-remotestorage-01'
     */

    _request: function(method, uri, token, headers, body, getEtag, fakeRevision) {
      if ((method === 'PUT' || method === 'DELETE') && uri[uri.length - 1] === '/') {
        throw "Don't " + method + " on directories!";
      }

      var promise = promising();
      var revision;
      var reqType;
      var self = this;

      headers['Authorization'] = 'Bearer ' + token;

      this._emit('wire-busy', {
        method: method,
        isFolder: isFolder(uri)
      });

      RS.WireClient.request(method, uri, {
        body: body,
        headers: headers
      }, function(error, response) {
        if (error) {
          self._emit('wire-done', {
            method: method,
            isFolder: isFolder(uri),
            success: false
          });
          self.online = false;
          promise.reject(error);
        } else {
          self._emit('wire-done', {
            method: method,
            isFolder: isFolder(uri),
            success: true
          });
          self.online = true;
          if (isErrorStatus(response.status)) {
            RemoteStorage.log('[WireClient] Error response status', response.status);
            if (getEtag) {
              revision = stripQuotes(response.getResponseHeader('ETag'));
            } else {
              revision = response.status === 200 ? fakeRevision : undefined;
            }
            promise.fulfill(response.status, undefined, undefined, revision);
          } else if (isSuccessStatus(response.status) ||
                     (response.status === 200 && method !== 'GET')) {
            revision = stripQuotes(response.getResponseHeader('ETag'));
            RemoteStorage.log('[WireClient] Successful request', revision);
            promise.fulfill(response.status, undefined, undefined, revision);
          } else {
            var mimeType = response.getResponseHeader('Content-Type');
            var body;
            if (getEtag) {
              revision = stripQuotes(response.getResponseHeader('ETag'));
            } else {
              revision = response.status === 200 ? fakeRevision : undefined;
            }

            if ((!mimeType) || mimeType.match(/charset=binary/)) {
              RS.WireClient.readBinaryData(response.response, mimeType, function(result) {
                RemoteStorage.log('[WireClient] Successful request with unknown or binary mime-type', revision);
                promise.fulfill(response.status, result, mimeType, revision);
              });
            } else {
              if (mimeType && mimeType.match(/^application\/json/)) {
                body = JSON.parse(response.responseText);
              } else {
                body = response.responseText;
              }
              RemoteStorage.log('[WireClient] Successful request', revision);
              promise.fulfill(response.status, body, mimeType, revision);
            }
          }
        }
      });
      return promise;
    },

    configure: function(userAddress, href, storageApi, token) {
      if (typeof(userAddress) !== 'undefined') {
        this.userAddress = userAddress;
      }
      if (typeof(href) !== 'undefined') {
        this.href = href;
      }
      if (typeof(storageApi) !== 'undefined') {
        this.storageApi = storageApi;
      }
      if (typeof(token) !== 'undefined') {
        this.token = token;
      }
      if (typeof(this.storageApi) !== 'undefined') {
        this._storageApi = STORAGE_APIS[this.storageApi] || API_HEAD;
        this.supportsRevs = this._storageApi >= API_00;
      }
      if (this.href && this.token) {
        this.connected = true;
        this.online = true;
        this._emit('connected');
      } else {
        this.connected = false;
      }
      if (hasLocalStorage) {
        localStorage[SETTINGS_KEY] = JSON.stringify({
          userAddress: this.userAddress,
          href: this.href,
          token: this.token,
          storageApi: this.storageApi
        });
      }
      RS.WireClient.configureHooks.forEach(function(hook) {
        hook.call(this);
      }.bind(this));
    },

    stopWaitingForToken: function() {
      if (!this.connected) {
        this._emit('not-connected');
      }
    },

    get: function(path, options) {
      if (!this.connected) {
        throw new Error("not connected (path: " + path + ")");
      }
      if (!options) { options = {}; }
      var headers = {};
      if (this.supportsRevs) {
        if (options.ifNoneMatch) {
          headers['If-None-Match'] = addQuotes(options.ifNoneMatch);
        }
      } else if (options.ifNoneMatch) {
        var oldRev = this._revisionCache[path];
      }
      var promise = this._request('GET', this.href + cleanPath(path), this.token, headers,
                            undefined, this.supportsRevs, this._revisionCache[path]);
      if (isFolder(path)) {
        return promise.then(function(status, body, contentType, revision) {
          var itemsMap = {};

          // New folder listing received
          if (status === 200 && typeof(body) === 'object') {
            // Empty folder listing of any spec
            if (Object.keys(body).length === 0) {
              status = 404;
            }
            // >= 02 spec
            else if (isFolderDescription(body)) {
              for (var item in body.items) {
                this._revisionCache[path + item] = body.items[item].ETag;
              }
              itemsMap = body.items;
            }
            // < 02 spec
            else {
              Object.keys(body).forEach(function(key){
                this._revisionCache[path + key] = body[key];
                itemsMap[key] = {"ETag": body[key]};
              }.bind(this));
            }
            return promising().fulfill(status, itemsMap, contentType, revision);
          } else {
            return promising().fulfill(status, body, contentType, revision);
          }
        }.bind(this));
      } else {
        return promise;
      }
    },

    put: function(path, body, contentType, options) {
      if (!this.connected) {
        throw new Error("not connected (path: " + path + ")");
      }
      if (!options) { options = {}; }
      if (!contentType.match(/charset=/)) {
        contentType += '; charset=' + ((body instanceof ArrayBuffer || isArrayBufferView(body)) ? 'binary' : 'utf-8');
      }
      var headers = { 'Content-Type': contentType };
      if (this.supportsRevs) {
        if (options.ifMatch) {
          headers['If-Match'] = addQuotes(options.ifMatch);
        }
        if (options.ifNoneMatch) {
          headers['If-None-Match'] = addQuotes(options.ifNoneMatch);
        }
      }
      return this._request('PUT', this.href + cleanPath(path), this.token,
                     headers, body, this.supportsRevs);
    },

    'delete': function(path, options) {
      if (!this.connected) {
        throw new Error("not connected (path: " + path + ")");
      }
      if (!options) { options = {}; }
      var headers = {};
      if (this.supportsRevs) {
        if (options.ifMatch) {
          headers['If-Match'] = addQuotes(options.ifMatch);
        }
      }
      return this._request('DELETE', this.href + cleanPath(path), this.token,
                     headers,
                     undefined, this.supportsRevs);
    }
  };

  // Shared cleanPath used by Dropbox
  RS.WireClient.cleanPath = cleanPath;

  // Shared isArrayBufferView used by WireClient and Dropbox
  RS.WireClient.isArrayBufferView = isArrayBufferView;

  RS.WireClient.readBinaryData = readBinaryData;

  // Shared request function used by WireClient, GoogleDrive and Dropbox.
  RS.WireClient.request = function(method, url, options, callback) {
    RemoteStorage.log('[WireClient]', method, url);

    callback = callback.bind(this);

    var timedOut = false;

    var timer = setTimeout(function() {
      timedOut = true;
      callback('timeout');
    }, RS.WireClient.REQUEST_TIMEOUT);

    var xhr = new XMLHttpRequest();
    xhr.open(method, url, true);

    if (options.responseType) {
      xhr.responseType = options.responseType;
    }
    if (options.headers) {
      for (var key in options.headers) {
        xhr.setRequestHeader(key, options.headers[key]);
      }
    }

    xhr.onload = function() {
      if (timedOut) { return; }
      clearTimeout(timer);
      callback(null, xhr);
    };

    xhr.onerror = function(error) {
      if (timedOut) { return; }
      clearTimeout(timer);
      callback(error);
    };

    var body = options.body;

    if (typeof(body) === 'object') {
      if (isArrayBufferView(body)) {
        /* alright. */
        //FIXME empty block
      }
      else if (body instanceof ArrayBuffer) {
        body = new Uint8Array(body);
      } else {
        body = JSON.stringify(body);
      }
    }
    xhr.send(body);
  };

  Object.defineProperty(RemoteStorage.WireClient.prototype, 'storageType', {
    get: function() {
      if (this.storageApi) {
        var spec = this.storageApi.match(/draft-dejong-(remotestorage-\d\d)/);
        return spec ? spec[1] : '2012.04';
      }
    }
  });

  RS.WireClient.configureHooks = [];

  RS.WireClient._rs_init = function(remoteStorage) {
    hasLocalStorage = remoteStorage.localStorageAvailable();
    remoteStorage.remote = new RS.WireClient(remoteStorage);
    this.online = true;
  };

  RS.WireClient._rs_supported = function() {
    return !! global.XMLHttpRequest;
  };

  RS.WireClient._rs_cleanup = function(remoteStorage){
    if (hasLocalStorage){
      delete localStorage[SETTINGS_KEY];
    }
    remoteStorage.removeEventListener('error', onErrorCb);
  };

})(typeof(window) !== 'undefined' ? window : global);
<commit_msg>remove unreachable code fakeRevision inside isErrorStatus<commit_after>(function(global) {
  var RS = RemoteStorage;

  /**
   * Class: RemoteStorage.WireClient
   *
   * WireClient Interface
   * --------------------
   *
   * This file exposes a get/put/delete interface on top of XMLHttpRequest.
   * It requires to be configured with parameters about the remotestorage server to
   * connect to.
   * Each instance of WireClient is always associated with a single remotestorage
   * server and access token.
   *
   * Usually the WireClient instance can be accessed via `remoteStorage.remote`.
   *
   * This is the get/put/delete interface:
   *
   *   - #get() takes a path and optionally a ifNoneMatch option carrying a version
   *     string to check. It returns a promise that will be fulfilled with the HTTP
   *     response status, the response body, the MIME type as returned in the
   *     'Content-Type' header and the current revision, as returned in the 'ETag'
   *     header.
   *   - #put() takes a path, the request body and a content type string. It also
   *     accepts the ifMatch and ifNoneMatch options, that map to the If-Match and
   *     If-None-Match headers respectively. See the remotestorage-01 specification
   *     for details on handling these headers. It returns a promise, fulfilled with
   *     the same values as the one for #get().
   *   - #delete() takes a path and the ifMatch option as well. It returns a promise
   *     fulfilled with the same values as the one for #get().
   *
   * In addition to this, the WireClient has some compatibility features to work with
   * remotestorage 2012.04 compatible storages. For example it will cache revisions
   * from folder listings in-memory and return them accordingly as the "revision"
   * parameter in response to #get() requests. Similarly it will return 404 when it
   * receives an empty folder listing, to mimic remotestorage-01 behavior. Note
   * that it is not always possible to know the revision beforehand, hence it may
   * be undefined at times (especially for caching-roots).
   */

  var hasLocalStorage;
  var SETTINGS_KEY = "remotestorage:wireclient";

  var API_2012 = 1, API_00 = 2, API_01 = 3, API_02 = 4, API_HEAD = 5;

  var STORAGE_APIS = {
    'draft-dejong-remotestorage-00': API_00,
    'draft-dejong-remotestorage-01': API_01,
    'draft-dejong-remotestorage-02': API_02,
    'https://www.w3.org/community/rww/wiki/read-write-web-00#simple': API_2012
  };

  var isArrayBufferView;

  if (typeof(ArrayBufferView) === 'function') {
    isArrayBufferView = function(object) { return object && (object instanceof ArrayBufferView); };
  } else {
    var arrayBufferViews = [
      Int8Array, Uint8Array, Int16Array, Uint16Array,
      Int32Array, Uint32Array, Float32Array, Float64Array
    ];
    isArrayBufferView = function(object) {
      for (var i=0;i<8;i++) {
        if (object instanceof arrayBufferViews[i]) {
          return true;
        }
      }
      return false;
    };
  }

  function addQuotes(str) {
    if (typeof(str) !== 'string') {
      return str;
    }
    if (str === '*') {
      return '*';
    }

    return '"' + str + '"';
  }

  function stripQuotes(str) {
    if (typeof(str) !== 'string') {
      return str;
    }

    return str.replace(/^["']|["']$/g, '');
  }

  function readBinaryData(content, mimeType, callback) {
    var blob = new Blob([content], { type: mimeType });
    var reader = new FileReader();
    reader.addEventListener("loadend", function() {
      callback(reader.result); // reader.result contains the contents of blob as a typed array
    });
    reader.readAsArrayBuffer(blob);
  }

  function cleanPath(path) {
    return path.replace(/\/+/g, '/').split('/').map(encodeURIComponent).join('/');
  }

  function isFolder(path) {
    return (path.substr(-1) === '/');
  }

  function isFolderDescription(body) {
    return ((body['@context'] === 'http://remotestorage.io/spec/folder-description')
             && (typeof(body['items']) === 'object'));
  }

  function isSuccessStatus(status) {
    return [201, 204, 304].indexOf(status) >= 0;
  }

  function isErrorStatus(status) {
    return [401, 403, 404, 412].indexOf(status) >= 0;
  }

  var onErrorCb;

  /**
   * Class : RemoteStorage.WireClient
   **/
  RS.WireClient = function(rs) {
    this.connected = false;

    /**
     * Event: change
     *   never fired for some reason
     *
     * Event: connected
     *   fired when the wireclient connect method realizes that it is
     *   in posession of a token and a href
     **/
    RS.eventHandling(this, 'change', 'connected', 'wire-busy', 'wire-done', 'not-connected');

    onErrorCb = function(error){
      if (error instanceof RemoteStorage.Unauthorized) {
        this.configure(undefined, undefined, undefined, null);
      }
    }.bind(this);
    rs.on('error', onErrorCb);
    if (hasLocalStorage) {
      var settings;
      try { settings = JSON.parse(localStorage[SETTINGS_KEY]); } catch(e) {}
      if (settings) {
        setTimeout(function() {
          this.configure(settings.userAddress, settings.href, settings.storageApi, settings.token);
        }.bind(this), 0);
      }
    }

    this._revisionCache = {};

    if (this.connected) {
      setTimeout(this._emit.bind(this), 0, 'connected');
    }
  };

  RS.WireClient.REQUEST_TIMEOUT = 30000;

  RS.WireClient.prototype = {
    /**
     * Property: token
     *
     * Holds the bearer token of this WireClient, as obtained in the OAuth dance
     *
     * Example:
     *   (start code)
     *
     *   remoteStorage.remote.token
     *   // -> 'DEADBEEF01=='
     */

    /**
     * Property: href
     *
     * Holds the server's base URL, as obtained in the Webfinger discovery
     *
     * Example:
     *   (start code)
     *
     *   remoteStorage.remote.href
     *   // -> 'https://storage.example.com/users/jblogg/'
     */

    /**
     * Property: storageApi
     *
     * Holds the spec version the server claims to be compatible with
     *
     * Example:
     *   (start code)
     *
     *   remoteStorage.remote.storageApi
     *   // -> 'draft-dejong-remotestorage-01'
     */

    _request: function(method, uri, token, headers, body, getEtag, fakeRevision) {
      if ((method === 'PUT' || method === 'DELETE') && uri[uri.length - 1] === '/') {
        throw "Don't " + method + " on directories!";
      }

      var promise = promising();
      var revision;
      var reqType;
      var self = this;

      headers['Authorization'] = 'Bearer ' + token;

      this._emit('wire-busy', {
        method: method,
        isFolder: isFolder(uri)
      });

      RS.WireClient.request(method, uri, {
        body: body,
        headers: headers
      }, function(error, response) {
        if (error) {
          self._emit('wire-done', {
            method: method,
            isFolder: isFolder(uri),
            success: false
          });
          self.online = false;
          promise.reject(error);
        } else {
          self._emit('wire-done', {
            method: method,
            isFolder: isFolder(uri),
            success: true
          });
          self.online = true;
          if (isErrorStatus(response.status)) {
            RemoteStorage.log('[WireClient] Error response status', response.status);
            if (getEtag) {
              revision = stripQuotes(response.getResponseHeader('ETag'));
            } else {
              revision = undefined;
            }
            promise.fulfill(response.status, undefined, undefined, revision);
          } else if (isSuccessStatus(response.status) ||
                     (response.status === 200 && method !== 'GET')) {
            revision = stripQuotes(response.getResponseHeader('ETag'));
            RemoteStorage.log('[WireClient] Successful request', revision);
            promise.fulfill(response.status, undefined, undefined, revision);
          } else {
            var mimeType = response.getResponseHeader('Content-Type');
            var body;
            if (getEtag) {
              revision = stripQuotes(response.getResponseHeader('ETag'));
            } else {
              revision = response.status === 200 ? fakeRevision : undefined;
            }

            if ((!mimeType) || mimeType.match(/charset=binary/)) {
              RS.WireClient.readBinaryData(response.response, mimeType, function(result) {
                RemoteStorage.log('[WireClient] Successful request with unknown or binary mime-type', revision);
                promise.fulfill(response.status, result, mimeType, revision);
              });
            } else {
              if (mimeType && mimeType.match(/^application\/json/)) {
                body = JSON.parse(response.responseText);
              } else {
                body = response.responseText;
              }
              RemoteStorage.log('[WireClient] Successful request', revision);
              promise.fulfill(response.status, body, mimeType, revision);
            }
          }
        }
      });
      return promise;
    },

    configure: function(userAddress, href, storageApi, token) {
      if (typeof(userAddress) !== 'undefined') {
        this.userAddress = userAddress;
      }
      if (typeof(href) !== 'undefined') {
        this.href = href;
      }
      if (typeof(storageApi) !== 'undefined') {
        this.storageApi = storageApi;
      }
      if (typeof(token) !== 'undefined') {
        this.token = token;
      }
      if (typeof(this.storageApi) !== 'undefined') {
        this._storageApi = STORAGE_APIS[this.storageApi] || API_HEAD;
        this.supportsRevs = this._storageApi >= API_00;
      }
      if (this.href && this.token) {
        this.connected = true;
        this.online = true;
        this._emit('connected');
      } else {
        this.connected = false;
      }
      if (hasLocalStorage) {
        localStorage[SETTINGS_KEY] = JSON.stringify({
          userAddress: this.userAddress,
          href: this.href,
          token: this.token,
          storageApi: this.storageApi
        });
      }
      RS.WireClient.configureHooks.forEach(function(hook) {
        hook.call(this);
      }.bind(this));
    },

    stopWaitingForToken: function() {
      if (!this.connected) {
        this._emit('not-connected');
      }
    },

    get: function(path, options) {
      if (!this.connected) {
        throw new Error("not connected (path: " + path + ")");
      }
      if (!options) { options = {}; }
      var headers = {};
      if (this.supportsRevs) {
        if (options.ifNoneMatch) {
          headers['If-None-Match'] = addQuotes(options.ifNoneMatch);
        }
      } else if (options.ifNoneMatch) {
        var oldRev = this._revisionCache[path];
      }
      var promise = this._request('GET', this.href + cleanPath(path), this.token, headers,
                            undefined, this.supportsRevs, this._revisionCache[path]);
      if (isFolder(path)) {
        return promise.then(function(status, body, contentType, revision) {
          var itemsMap = {};

          // New folder listing received
          if (status === 200 && typeof(body) === 'object') {
            // Empty folder listing of any spec
            if (Object.keys(body).length === 0) {
              status = 404;
            }
            // >= 02 spec
            else if (isFolderDescription(body)) {
              for (var item in body.items) {
                this._revisionCache[path + item] = body.items[item].ETag;
              }
              itemsMap = body.items;
            }
            // < 02 spec
            else {
              Object.keys(body).forEach(function(key){
                this._revisionCache[path + key] = body[key];
                itemsMap[key] = {"ETag": body[key]};
              }.bind(this));
            }
            return promising().fulfill(status, itemsMap, contentType, revision);
          } else {
            return promising().fulfill(status, body, contentType, revision);
          }
        }.bind(this));
      } else {
        return promise;
      }
    },

    put: function(path, body, contentType, options) {
      if (!this.connected) {
        throw new Error("not connected (path: " + path + ")");
      }
      if (!options) { options = {}; }
      if (!contentType.match(/charset=/)) {
        contentType += '; charset=' + ((body instanceof ArrayBuffer || isArrayBufferView(body)) ? 'binary' : 'utf-8');
      }
      var headers = { 'Content-Type': contentType };
      if (this.supportsRevs) {
        if (options.ifMatch) {
          headers['If-Match'] = addQuotes(options.ifMatch);
        }
        if (options.ifNoneMatch) {
          headers['If-None-Match'] = addQuotes(options.ifNoneMatch);
        }
      }
      return this._request('PUT', this.href + cleanPath(path), this.token,
                     headers, body, this.supportsRevs);
    },

    'delete': function(path, options) {
      if (!this.connected) {
        throw new Error("not connected (path: " + path + ")");
      }
      if (!options) { options = {}; }
      var headers = {};
      if (this.supportsRevs) {
        if (options.ifMatch) {
          headers['If-Match'] = addQuotes(options.ifMatch);
        }
      }
      return this._request('DELETE', this.href + cleanPath(path), this.token,
                     headers,
                     undefined, this.supportsRevs);
    }
  };

  // Shared cleanPath used by Dropbox
  RS.WireClient.cleanPath = cleanPath;

  // Shared isArrayBufferView used by WireClient and Dropbox
  RS.WireClient.isArrayBufferView = isArrayBufferView;

  RS.WireClient.readBinaryData = readBinaryData;

  // Shared request function used by WireClient, GoogleDrive and Dropbox.
  RS.WireClient.request = function(method, url, options, callback) {
    RemoteStorage.log('[WireClient]', method, url);

    callback = callback.bind(this);

    var timedOut = false;

    var timer = setTimeout(function() {
      timedOut = true;
      callback('timeout');
    }, RS.WireClient.REQUEST_TIMEOUT);

    var xhr = new XMLHttpRequest();
    xhr.open(method, url, true);

    if (options.responseType) {
      xhr.responseType = options.responseType;
    }
    if (options.headers) {
      for (var key in options.headers) {
        xhr.setRequestHeader(key, options.headers[key]);
      }
    }

    xhr.onload = function() {
      if (timedOut) { return; }
      clearTimeout(timer);
      callback(null, xhr);
    };

    xhr.onerror = function(error) {
      if (timedOut) { return; }
      clearTimeout(timer);
      callback(error);
    };

    var body = options.body;

    if (typeof(body) === 'object') {
      if (isArrayBufferView(body)) {
        /* alright. */
        //FIXME empty block
      }
      else if (body instanceof ArrayBuffer) {
        body = new Uint8Array(body);
      } else {
        body = JSON.stringify(body);
      }
    }
    xhr.send(body);
  };

  Object.defineProperty(RemoteStorage.WireClient.prototype, 'storageType', {
    get: function() {
      if (this.storageApi) {
        var spec = this.storageApi.match(/draft-dejong-(remotestorage-\d\d)/);
        return spec ? spec[1] : '2012.04';
      }
    }
  });

  RS.WireClient.configureHooks = [];

  RS.WireClient._rs_init = function(remoteStorage) {
    hasLocalStorage = remoteStorage.localStorageAvailable();
    remoteStorage.remote = new RS.WireClient(remoteStorage);
    this.online = true;
  };

  RS.WireClient._rs_supported = function() {
    return !! global.XMLHttpRequest;
  };

  RS.WireClient._rs_cleanup = function(remoteStorage){
    if (hasLocalStorage){
      delete localStorage[SETTINGS_KEY];
    }
    remoteStorage.removeEventListener('error', onErrorCb);
  };

})(typeof(window) !== 'undefined' ? window : global);
<|endoftext|>


<commit_before>// List module dependancies
var express = require('express');
var bodyParser = require('body-parser');
var db = require('./models');
var http = require('http');
var epilogue = require('epilogue');

// Init express app
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

// test login authentification
db.sequelize
  .authenticate()
  .then(function(success) {
    console.log('Connection has been established successfully.');
  })
  .catch(function (err) {
    console.log('Unable to connect to the database:', err);
  });

// Init Epilogue
epilogue.initialize({
  app: app,
  sequelize: db.sequelize
});

var baseapiurl = '/api/v0/'

// Create REST resources
var taxonResource = epilogue.resource({
  model: db.taxon,
  endpoints: ['taxon','taxon/:id'].map(function(x){return(baseapiurl+x)});
});

var datasetResource = epilogue.resource({
  model: db.dataset,
  endpoints: ['dataset','dataset/:id'].map(function(x){return(baseapiurl+x)});
});

var interactionResource = epilogue.resource({
  model: db.interaction,
  endpoints: ['interaction','interaction/:id'].map(function(x){return(baseapiurl+x)});
});

var itemResource = epilogue.resource({
  model: db.item,
  endpoints: ['item','item/:id'].map(function(x){return(baseapiurl+x)});
});

var networkResource = epilogue.resource({
  model: db.network,
  endpoints: ['network','network/:id'].map(function(x){return(baseapiurl+x)});
});

// Sync database with new models
db.sequelize.sync({force:true});

// start server
var port = process.env.PORT || 3000;
server = http.createServer(app);
server.listen(port);
<commit_msg>Removing unexpected token;<commit_after>// List module dependancies
var express = require('express');
var bodyParser = require('body-parser');
var db = require('./models');
var http = require('http');
var epilogue = require('epilogue');

// Init express app
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

// test login authentification
db.sequelize
  .authenticate()
  .then(function(success) {
    console.log('Connection has been established successfully.');
  })
  .catch(function (err) {
    console.log('Unable to connect to the database:', err);
  });

// Init Epilogue
epilogue.initialize({
  app: app,
  sequelize: db.sequelize
});

var baseapiurl = '/api/v0/'

// Create REST resources
var taxonResource = epilogue.resource({
  model: db.taxon,
  endpoints: ['taxon','taxon/:id'].map(function(x){return(baseapiurl+x)})
});

var datasetResource = epilogue.resource({
  model: db.dataset,
  endpoints: ['dataset','dataset/:id'].map(function(x){return(baseapiurl+x)})
});

var interactionResource = epilogue.resource({
  model: db.interaction,
  endpoints: ['interaction','interaction/:id'].map(function(x){return(baseapiurl+x)})
});

var itemResource = epilogue.resource({
  model: db.item,
  endpoints: ['item','item/:id'].map(function(x){return(baseapiurl+x)})
});

var networkResource = epilogue.resource({
  model: db.network,
  endpoints: ['network','network/:id'].map(function(x){return(baseapiurl+x)})
});

// Sync database with new models
db.sequelize.sync({force:true});

// start server
var port = process.env.PORT || 3000;
server = http.createServer(app);
server.listen(port);
<|endoftext|>


<commit_before>"use strict";

(function () {
    angular
        .module("argo")
        .directive("argoCharts", argoCharts);

    argoCharts.$inject = [];
    function argoCharts() {
        var directive = {
            restrict: "E",
            scope: {
                data: "=",
                feed: "="
            },
            link: link
        };

        return directive;

        function link(scope, element) {
            var lastHistUpdate;

            scope.$watch("data", function (data) {
                if (data && data.length > 0) {
                    drawChart(element[0], data);

                    lastHistUpdate = getLastHistUpdate("M5");
                    console.log("last update", new Date());
                }
            });

            scope.$watch("feed", function (feed) {
                var tick = feed.EUR_USD,
                    nextHistUpdate = getLastHistUpdate("M5", tick);

                if (tick && lastHistUpdate !== nextHistUpdate) {
                    console.log("need update", new Date());
                    lastHistUpdate = nextHistUpdate;
                }

                // console.log(feed);
            }, true);

            function getLastHistUpdate(granularity, tick) {
                var time = tick && tick.time,
                    now = time ? new Date(time) : new Date(),
                    value;

                if (granularity === "M5") {
                    value = Math.floor(now.getMinutes() / 5);
                }

                return value;
            }

        }
    }

    function drawChart(el, data) {
        var margin = {
                top: 0,
                right: 20,
                bottom: 30,
                left: 75
            },
            width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

        var x = techan.scale.financetime()
            .range([0, width]);

        var y = d3.scale.linear()
            .range([height, 0]);

        var yVolume = d3.scale.linear()
            .range([y(0), y(0.2)]);

        var ohlc = techan.plot.ohlc()
            .xScale(x)
            .yScale(y);

        var sma0 = techan.plot.sma()
            .xScale(x)
            .yScale(y);

        var sma0Calculator = techan.indicator.sma()
            .period(10);

        var sma1 = techan.plot.sma()
            .xScale(x)
            .yScale(y);

        var sma1Calculator = techan.indicator.sma()
            .period(20);

        var volume = techan.plot.volume()
            .accessor(ohlc.accessor())
            .xScale(x)
            .yScale(yVolume);

        var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom");

        var yAxis = d3.svg.axis()
            .scale(y)
            .orient("left");

        var volumeAxis = d3.svg.axis()
            .scale(yVolume)
            .orient("right")
            .ticks(3)
            .tickFormat(d3.format(",.3s"));

        var timeAnnotation = techan.plot.axisannotation()
            .axis(xAxis)
            .format(d3.time.format("%Y-%m-%d %H:%M"))
            .width(80)
            .translate([0, height]);

        var ohlcAnnotation = techan.plot.axisannotation()
            .axis(yAxis)
            .format(d3.format(",.4fs"));

        var volumeAnnotation = techan.plot.axisannotation()
            .axis(volumeAxis)
            .width(35);

        var crosshair = techan.plot.crosshair()
            .xScale(x)
            .yScale(y)
            .xAnnotation(timeAnnotation)
            .yAnnotation([ohlcAnnotation, volumeAnnotation]);

        var svg = d3.select(el).append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom);

        var defs = svg.append("defs");

        svg = svg.append("g")
            .attr("transform",
                "translate(" + margin.left + "," + margin.top + ")");

        defs
            .append("clipPath")
                .attr("id", "ohlcClip")
            .append("rect")
                .attr("x", 0)
                .attr("y", 0)
                .attr("width", width)
                .attr("height", height);

        var ohlcSelection = svg.append("g")
            .attr("class", "ohlc")
            .attr("transform", "translate(0,0)");

        ohlcSelection.append("g")
            .attr("class", "volume")
            .attr("clip-path", "url(#ohlcClip)");

        ohlcSelection.append("g")
            .attr("class", "candlestick")
            .attr("clip-path", "url(#ohlcClip)");

        ohlcSelection.append("g")
            .attr("class", "indicator sma ma-0")
            .attr("clip-path", "url(#ohlcClip)");

        ohlcSelection.append("g")
            .attr("class", "indicator sma ma-1")
            .attr("clip-path", "url(#ohlcClip)");

        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")");

        svg
            .append("g")
                .attr("class", "y axis")
            .append("text")
                .attr("transform", "rotate(-90)")
                .attr("y", 6)
                .attr("dy", ".71em")
                .style("text-anchor", "end")
                .text("Price (EUR_USD / M5)");

        svg.append("g")
            .attr("class", "volume axis");

        svg.append("g")
            .attr("class", "crosshair ohlc");

        data = d3.csv.parse(data).map(function (d) {
            return {
                date: new Date(d.Date),
                open: +d.Open,
                high: +d.High,
                low: +d.Low,
                close: +d.Close,
                volume: +d.Volume
            };
        });

        svg.select("g.candlestick").datum(data);
        svg.select("g.sma.ma-0").datum(sma0Calculator(data));
        svg.select("g.sma.ma-1").datum(sma1Calculator(data));
        svg.select("g.volume").datum(data);

        redraw();

        function refreshIndicator(selection, indicator, data2) {
            var datum = selection.datum();

            // Some trickery to remove old and insert new without changing array
            // reference, so no need to update __data__ in the DOM
            datum.splice.apply(datum, [0, datum.length].concat(data2));
            selection.call(indicator);
        }

        function redraw() {
            var accessor = ohlc.accessor();

            x.domain(data.map(accessor.d));
            // Show only 150 points on the plot
            x.zoomable().domain([data.length - 130, data.length]);

            // Update y scale min max, only on viewable zoomable.domain()
            y.domain(techan.scale.plot.ohlc(
                data.slice(data.length - 130, data.length)).domain());
            yVolume.domain(techan.scale.plot.volume(
                data.slice(data.length - 130, data.length)).domain());

            svg.select("g.x.axis").call(xAxis);
            svg.select("g.y.axis").call(yAxis);
            svg.select("g.volume.axis").call(volumeAxis);

            svg.select("g.candlestick").call(ohlc);
            // Recalculate indicators and update the SAME array and
            // redraw moving average
            refreshIndicator(svg.select("g.sma.ma-0"), sma0,
                sma0Calculator(data));
            refreshIndicator(svg.select("g.sma.ma-1"), sma1,
                sma1Calculator(data));

            svg.select("g.volume").call(volume);

            svg.select("g.crosshair.ohlc").call(crosshair);

            // Set next timer expiry
            // setTimeout(function () {
            //     if (feed.length) {
            //         // Simulate a daily feed
            //         data.push(feed.shift());
            //     } else {
            //         // Simulate intra day updates when no feed is left
            //         var last = data[data.length - 1];
            //         // Last must be between high and low
            //         last.close = Math.round(((last.high - last.low) *
            //             Math.random()) * 10) / 10 + last.low;
            //     }

            //     redraw();
            // }, (Math.random() * 1000) + 400);
            // Randomly pick an interval to update the chart
        }

    }

}());
<commit_msg>Remove x axis in charts due to a date issue.<commit_after>"use strict";

(function () {
    angular
        .module("argo")
        .directive("argoCharts", argoCharts);

    argoCharts.$inject = [];
    function argoCharts() {
        var directive = {
            restrict: "E",
            scope: {
                data: "=",
                feed: "="
            },
            link: link
        };

        return directive;

        function link(scope, element) {
            var lastHistUpdate;

            scope.$watch("data", function (data) {
                if (data && data.length > 0) {
                    drawChart(element[0], data);

                    lastHistUpdate = getLastHistUpdate("M5");
                    console.log("last update", new Date());
                }
            });

            scope.$watch("feed", function (feed) {
                var tick = feed.EUR_USD,
                    nextHistUpdate = getLastHistUpdate("M5", tick);

                if (tick && lastHistUpdate !== nextHistUpdate) {
                    console.log("need update", new Date());
                    lastHistUpdate = nextHistUpdate;
                }

                // console.log(feed);
            }, true);

            function getLastHistUpdate(granularity, tick) {
                var time = tick && tick.time,
                    now = time ? new Date(time) : new Date(),
                    value;

                if (granularity === "M5") {
                    value = Math.floor(now.getMinutes() / 5);
                }

                return value;
            }

        }
    }

    function drawChart(el, data) {
        var margin = {
                top: 0,
                right: 20,
                bottom: 30,
                left: 75
            },
            width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

        var x = techan.scale.financetime()
            .range([0, width]);

        var y = d3.scale.linear()
            .range([height, 0]);

        var yVolume = d3.scale.linear()
            .range([y(0), y(0.2)]);

        var ohlc = techan.plot.ohlc()
            .xScale(x)
            .yScale(y);

        var sma0 = techan.plot.sma()
            .xScale(x)
            .yScale(y);

        var sma0Calculator = techan.indicator.sma()
            .period(10);

        var sma1 = techan.plot.sma()
            .xScale(x)
            .yScale(y);

        var sma1Calculator = techan.indicator.sma()
            .period(20);

        var volume = techan.plot.volume()
            .accessor(ohlc.accessor())
            .xScale(x)
            .yScale(yVolume);

        var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom");

        var yAxis = d3.svg.axis()
            .scale(y)
            .orient("left");

        var volumeAxis = d3.svg.axis()
            .scale(yVolume)
            .orient("right")
            .ticks(3)
            .tickFormat(d3.format(",.3s"));

        var timeAnnotation = techan.plot.axisannotation()
            .axis(xAxis)
            .format(d3.time.format("%Y-%m-%d %H:%M"))
            .width(80)
            .translate([0, height]);

        var ohlcAnnotation = techan.plot.axisannotation()
            .axis(yAxis)
            .format(d3.format(",.4fs"));

        var volumeAnnotation = techan.plot.axisannotation()
            .axis(volumeAxis)
            .width(35);

        var crosshair = techan.plot.crosshair()
            .xScale(x)
            .yScale(y)
            .xAnnotation(timeAnnotation)
            .yAnnotation([ohlcAnnotation, volumeAnnotation]);

        var svg = d3.select(el).append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom);

        var defs = svg.append("defs");

        svg = svg.append("g")
            .attr("transform",
                "translate(" + margin.left + "," + margin.top + ")");

        defs
            .append("clipPath")
                .attr("id", "ohlcClip")
            .append("rect")
                .attr("x", 0)
                .attr("y", 0)
                .attr("width", width)
                .attr("height", height);

        var ohlcSelection = svg.append("g")
            .attr("class", "ohlc")
            .attr("transform", "translate(0,0)");

        ohlcSelection.append("g")
            .attr("class", "volume")
            .attr("clip-path", "url(#ohlcClip)");

        ohlcSelection.append("g")
            .attr("class", "candlestick")
            .attr("clip-path", "url(#ohlcClip)");

        ohlcSelection.append("g")
            .attr("class", "indicator sma ma-0")
            .attr("clip-path", "url(#ohlcClip)");

        ohlcSelection.append("g")
            .attr("class", "indicator sma ma-1")
            .attr("clip-path", "url(#ohlcClip)");

        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")");

        svg
            .append("g")
                .attr("class", "y axis")
            .append("text")
                .attr("transform", "rotate(-90)")
                .attr("y", 6)
                .attr("dy", ".71em")
                .style("text-anchor", "end")
                .text("Price (EUR_USD / M5)");

        svg.append("g")
            .attr("class", "volume axis");

        svg.append("g")
            .attr("class", "crosshair ohlc");

        data = d3.csv.parse(data).map(function (d) {
            return {
                date: new Date(d.Date),
                open: +d.Open,
                high: +d.High,
                low: +d.Low,
                close: +d.Close,
                volume: +d.Volume
            };
        });

        svg.select("g.candlestick").datum(data);
        svg.select("g.sma.ma-0").datum(sma0Calculator(data));
        svg.select("g.sma.ma-1").datum(sma1Calculator(data));
        svg.select("g.volume").datum(data);

        redraw();

        function refreshIndicator(selection, indicator, data2) {
            var datum = selection.datum();

            // Some trickery to remove old and insert new without changing array
            // reference, so no need to update __data__ in the DOM
            datum.splice.apply(datum, [0, datum.length].concat(data2));
            selection.call(indicator);
        }

        function redraw() {
            var accessor = ohlc.accessor();

            x.domain(data.map(accessor.d));
            // Show only 150 points on the plot
            x.zoomable().domain([data.length - 130, data.length]);

            // Update y scale min max, only on viewable zoomable.domain()
            y.domain(techan.scale.plot.ohlc(
                data.slice(data.length - 130, data.length)).domain());
            yVolume.domain(techan.scale.plot.volume(
                data.slice(data.length - 130, data.length)).domain());

            // FIX: no idea because throws sometimes an exception (about date)
            // svg.select("g.x.axis").call(xAxis);
            svg.select("g.y.axis").call(yAxis);
            svg.select("g.volume.axis").call(volumeAxis);

            svg.select("g.candlestick").call(ohlc);
            // Recalculate indicators and update the SAME array and
            // redraw moving average
            refreshIndicator(svg.select("g.sma.ma-0"), sma0,
                sma0Calculator(data));
            refreshIndicator(svg.select("g.sma.ma-1"), sma1,
                sma1Calculator(data));

            svg.select("g.volume").call(volume);

            svg.select("g.crosshair.ohlc").call(crosshair);

            // Set next timer expiry
            // setTimeout(function () {
            //     if (feed.length) {
            //         // Simulate a daily feed
            //         data.push(feed.shift());
            //     } else {
            //         // Simulate intra day updates when no feed is left
            //         var last = data[data.length - 1];
            //         // Last must be between high and low
            //         last.close = Math.round(((last.high - last.low) *
            //             Math.random()) * 10) / 10 + last.low;
            //     }

            //     redraw();
            // }, (Math.random() * 1000) + 400);
            // Randomly pick an interval to update the chart
        }

    }

}());
<|endoftext|>


<commit_before>/*
 Force PDFs to render inline in Chrome (for the Stable channel).

 Note: This is a slower version than the Declarative Web Request extension at:
 https://chrome.google.com/webstore/detail/render-pdfs-inline/mpmmilbhemhehclnkpkfepmaikiolaab

 (Unfortunately, the DWR API isn't available on the Stable channel.)

 WARNING: This may have significant security implications. If you don't understand why, do NOT install this extension.

 Author: Nick Semenkovich <semenko@alum.mit.edu> | https://nick.semenkovich.com/
 License: MIT
 */

chrome.webRequest.onHeadersReceived.addListener(
    function(details) {
        var responseHeaders = details.responseHeaders;
        responseHeaders.forEach(function(header){
            switch(header.name.toLowerCase()) {
                case 'content-disposition':
                    header.value = header.value.replace('attachment', 'inline');
                    console.log('Injecting Content-Disposition inline header for:', details);
                    break;
                case 'content-type':
                    if (header.value.indexOf('application/octet-stream') !== -1) {
                        // This might break stuff, but if you name your file PDF, we're gonna force it to be a PDF.
                        header.value = header.value.replace('application/octet-stream', 'application/pdf');
                        console.log('Injecting Content-Type PDF header for:', details);
                    }
                    break;
            }
        });
        return {responseHeaders: responseHeaders};
    },
    // Catch any PDF named files and rewrite attachment to inline.
    {
        urls: ["*://*/*.pdf",
            "*://*/*.Pdf",
            "*://*/*.pDf",
            "*://*/*.pdF",
            "*://*/*.PDf",
            "*://*/*.PdF",
            "*://*/*.pDF",
            "*://*/*.PDF"],
        types: ["main_frame"]
    },
    ["blocking", "responseHeaders"]
);

// Handle PDFs on non .pdf URLs.
chrome.webRequest.onHeadersReceived.addListener(
    function(details) {
        var responseHeaders = details.responseHeaders;
        var contentTypeIsPDF = false;
        var contentNotInline = true;
        var contentDispositionPosition = 0;
        responseHeaders.forEach(function(header, i){
            switch(header.name.toLowerCase()) {
                case 'content-disposition':
                    if (header.value.indexOf('inline') === -1) {
                      // We're not inline. Likely an attachment.
                      contentNotInline = true;
                      contentDispositionPosition = i;
                    }
                    break;
                case 'content-type':
                    if (header.value.indexOf('application/pdf') !== -1) {
                        // It's a PDF! Let's note that.
                        contentTypeIsPDF = true;
                    }
                    break;
            }
        });
        if (contentTypeIsPDF && contentNotInline) {
           // We are a PDF, but we're not inline. Let's set the inline header.
           console.log('Injecting Content-Type PDF header for:', details);
           if (header.name.toLowerCase().indexOf('content-disposition') !== -1)) {
            details.responseHeaders[contentDispositionPosition].value = "inline";
           } else {
            console.warn('Unexpected error in responseHeaders for:', details);
           }
        }
        return {responseHeaders: responseHeaders};
    },
    // Catch anything, and we'll match content type above.
    {
        urls: ["*://*/*],
        types: ["main_frame"]
    },
    ["blocking", "responseHeaders"]
);
<commit_msg>Fix URL regex<commit_after>/*
 Force PDFs to render inline in Chrome (for the Stable channel).

 Note: This is a slower version than the Declarative Web Request extension at:
 https://chrome.google.com/webstore/detail/render-pdfs-inline/mpmmilbhemhehclnkpkfepmaikiolaab

 (Unfortunately, the DWR API isn't available on the Stable channel.)

 WARNING: This may have significant security implications. If you don't understand why, do NOT install this extension.

 Author: Nick Semenkovich <semenko@alum.mit.edu> | https://nick.semenkovich.com/
 License: MIT
 */

chrome.webRequest.onHeadersReceived.addListener(
    function(details) {
        var responseHeaders = details.responseHeaders;
        responseHeaders.forEach(function(header){
            switch(header.name.toLowerCase()) {
                case 'content-disposition':
                    header.value = header.value.replace('attachment', 'inline');
                    console.log('Injecting Content-Disposition inline header for:', details);
                    break;
                case 'content-type':
                    if (header.value.indexOf('application/octet-stream') !== -1) {
                        // This might break stuff, but if you name your file PDF, we're gonna force it to be a PDF.
                        header.value = header.value.replace('application/octet-stream', 'application/pdf');
                        console.log('Injecting Content-Type PDF header for:', details);
                    }
                    break;
            }
        });
        return {responseHeaders: responseHeaders};
    },
    // Catch any PDF named files and rewrite attachment to inline.
    {
        urls: ["*://*/*.pdf",
            "*://*/*.Pdf",
            "*://*/*.pDf",
            "*://*/*.pdF",
            "*://*/*.PDf",
            "*://*/*.PdF",
            "*://*/*.pDF",
            "*://*/*.PDF"],
        types: ["main_frame"]
    },
    ["blocking", "responseHeaders"]
);

// Handle PDFs on non .pdf URLs.
chrome.webRequest.onHeadersReceived.addListener(
    function(details) {
        var responseHeaders = details.responseHeaders;
        var contentTypeIsPDF = false;
        var contentNotInline = true;
        var contentDispositionPosition = 0;
        responseHeaders.forEach(function(header, i){
            switch(header.name.toLowerCase()) {
                case 'content-disposition':
                    if (header.value.indexOf('inline') === -1) {
                      // We're not inline. Likely an attachment.
                      contentNotInline = true;
                      contentDispositionPosition = i;
                    }
                    break;
                case 'content-type':
                    if (header.value.indexOf('application/pdf') !== -1) {
                        // It's a PDF! Let's note that.
                        contentTypeIsPDF = true;
                    }
                    break;
            }
        });
        if (contentTypeIsPDF && contentNotInline) {
           // We are a PDF, but we're not inline. Let's set the inline header.
           console.log('Injecting Content-Type PDF header for:', details);
           if (header.name.toLowerCase().indexOf('content-disposition') !== -1)) {
            details.responseHeaders[contentDispositionPosition].value = "inline";
           } else {
            console.warn('Unexpected error in responseHeaders for:', details);
           }
        }
        return {responseHeaders: responseHeaders};
    },
    // Catch anything, and we'll match content type above.
    {
        urls: ["<all_urls>"],
        types: ["main_frame"]
    },
    ["blocking", "responseHeaders"]
);
<|endoftext|>