<commit_before>/**
 * Graphology Utils Unit Tests
 * ============================
 */
var assert = require('assert');
var Graph = require('graphology');
var inferType = require('./infer-type.js');
var isGraph = require('./is-graph.js');
var isGraphConstructor = require('./is-graph-constructor.js');
var mergeClique = require('./merge-clique.js');
var mergeCycle = require('./merge-cycle.js');
var mergePath = require('./merge-path.js');
var mergeStar = require('./merge-star.js');
var renameGraphKeys = require('./rename-graph-keys.js');
var updateGraphKeys = require('./update-graph-keys.js');
var getters = require('./getters.js');
var resolveDefaults = require('./defaults.js');

var UndirectedGraph = Graph.UndirectedGraph;
var createWeightGetter = getters.createWeightGetter;

describe('graphology-utils', function () {
  describe('inferType', function () {
    it('should correctly infer the type of the given graph.', function () {
      var graph = new Graph({type: 'mixed'});
      graph.mergeDirectedEdge(1, 2);

      assert.strictEqual(inferType(graph), 'directed');

      graph = new Graph({type: 'mixed'});
      graph.mergeUndirectedEdge(1, 2);

      assert.strictEqual(inferType(graph), 'undirected');

      graph = new Graph({type: 'mixed'});
      graph.mergeDirectedEdge(1, 2);
      graph.mergeUndirectedEdge(3, 4);

      assert.strictEqual(inferType(graph), 'mixed');

      graph = new Graph({type: 'mixed'});

      assert.strictEqual(inferType(graph), 'mixed');

      graph = new Graph({type: 'directed'});

      assert.strictEqual(inferType(graph), 'directed');

      graph = new Graph({type: 'undirected'});

      assert.strictEqual(inferType(graph), 'undirected');
    });
  });

  describe('isGraph', function () {
    it('should correctly return whether the given value is a graphology instance.', function () {
      var graph = new Graph(),
        multiDirectedGraph = new Graph(null, {multi: true, type: 'directed'});

      assert.strictEqual(isGraph(graph), true);
      assert.strictEqual(isGraph(multiDirectedGraph), true);

      var nonGraphs = [
        null,
        false,
        '',
        'test',
        0,
        -45,
        5380,
        6.4,
        {},
        [],
        {hello: 'world'},
        [1, 2, 3],
        new RegExp(),
        new Date()
      ];

      nonGraphs.forEach(function (value) {
        assert.strictEqual(isGraph(value), false);
      });
    });
  });

  describe('isGraphConstructor', function () {
    it('should correctly return whether the given value is a graphology constructor.', function () {
      assert.strictEqual(isGraphConstructor(Graph), true);
      assert.strictEqual(isGraphConstructor(UndirectedGraph), true);

      var nonGraphsConstructors = [
        null,
        false,
        '',
        'test',
        0,
        -45,
        5380,
        6.4,
        {},
        [],
        {hello: 'world'},
        [1, 2, 3],
        new RegExp(),
        new Date(),
        new Graph(),
        new UndirectedGraph()
      ];

      nonGraphsConstructors.forEach(function (value) {
        assert.strictEqual(isGraphConstructor(value), false);
      });
    });
  });

  describe('mergeClique', function () {
    it('should correctly add the given clique to the graph.', function () {
      var graph = new Graph();

      mergeClique(graph, ['1', '2', '3', '4', '5']);

      assert.strictEqual(graph.order, 5);
      assert.strictEqual(graph.size, 10);

      var adj = graph.edges().map(function (edge) {
        return graph.extremities(edge);
      });

      assert.deepStrictEqual(adj, [
        ['1', '2'],
        ['1', '3'],
        ['1', '4'],
        ['1', '5'],
        ['2', '3'],
        ['2', '4'],
        ['2', '5'],
        ['3', '4'],
        ['3', '5'],
        ['4', '5']
      ]);
    });
  });

  describe('mergeCycle', function () {
    it('should correctly add the given path to the graph.', function () {
      var graph = new Graph();

      mergeCycle(graph, ['1', '2', '3', '4', '5']);

      assert.strictEqual(graph.order, 5);
      assert.strictEqual(graph.size, 5);

      var adj = graph.edges().map(function (edge) {
        return graph.extremities(edge);
      });

      assert.deepStrictEqual(adj, [
        ['1', '2'],
        ['2', '3'],
        ['3', '4'],
        ['4', '5'],
        ['5', '1']
      ]);
    });
  });

  describe('mergePath', function () {
    it('should correctly add the given path to the graph.', function () {
      var graph = new Graph();

      mergePath(graph, ['1', '2', '3', '4', '5']);

      assert.strictEqual(graph.order, 5);
      assert.strictEqual(graph.size, 4);

      var adj = graph.edges().map(function (edge) {
        return graph.extremities(edge);
      });

      assert.deepStrictEqual(adj, [
        ['1', '2'],
        ['2', '3'],
        ['3', '4'],
        ['4', '5']
      ]);
    });
  });

  describe('mergeStar', function () {
    it('should correctly add the given star to the graph.', function () {
      var graph = new Graph();

      mergeStar(graph, ['1', '2', '3', '4', '5']);

      assert.strictEqual(graph.order, 5);
      assert.strictEqual(graph.size, 4);

      var adj = graph.edges().map(function (edge) {
        return graph.extremities(edge);
      });

      assert.deepStrictEqual(adj, [
        ['1', '2'],
        ['1', '3'],
        ['1', '4'],
        ['1', '5']
      ]);
    });
  });

  describe('renameGraphKeys', function () {
    it('should work with only node mapping.', function () {
      var graph = new Graph();
      graph.addNode('Martha');
      graph.addNode('Catherine');
      graph.addNode('John');
      graph.addEdgeWithKey('M->C', 'Martha', 'Catherine');
      graph.addEdgeWithKey('C->J', 'Catherine', 'John');

      var newGraph = renameGraphKeys(graph, {
        Martha: 1,
        Catherine: 2,
        John: 3
      });

      // Tests
      assert.strictEqual(newGraph.order, 3);
      assert.strictEqual(newGraph.size, 2);
      assert(newGraph.hasNode(1));
      assert(newGraph.hasNode(2));
      assert(newGraph.hasNode(3));
      assert.strictEqual(newGraph.edge(1, 2), 'M->C');
      assert.strictEqual(newGraph.edge(2, 3), 'C->J');
    });

    it('should work with full mapping.', function () {
      var graph = new Graph();
      graph.addNode('Martha');
      graph.addNode('Catherine');
      graph.addNode('John');
      graph.addEdgeWithKey('M->C', 'Martha', 'Catherine');
      graph.addEdgeWithKey('C->J', 'Catherine', 'John');

      var newGraph = renameGraphKeys(
        graph,
        {Martha: 1, Catherine: 2, John: 3},
        {'M->C': 'rel1', 'C->J': 'rel2'}
      );

      // Tests
      assert.strictEqual(newGraph.order, 3);
      assert.strictEqual(newGraph.size, 2);
      assert(newGraph.hasNode(1));
      assert(newGraph.hasNode(2));
      assert(newGraph.hasNode(3));
      assert.strictEqual(newGraph.edge(1, 2), 'rel1');
      assert.strictEqual(newGraph.edge(2, 3), 'rel2');
    });
  });

  describe('updateGraphKeys', function () {
    it('should work with only node mapping.', function () {
      var graph = new Graph();
      graph.addNode('Martha');
      graph.addNode('Catherine');
      graph.addNode('John');
      graph.addEdgeWithKey('M->C', 'Martha', 'Catherine');
      graph.addEdgeWithKey('C->J', 'Catherine', 'John');

      var newGraph = updateGraphKeys(graph, function (key) {
        if (key === 'Martha') return 1;
        if (key === 'Catherine') return 2;
        return 3;
      });

      // Tests
      assert.strictEqual(newGraph.order, 3);
      assert.strictEqual(newGraph.size, 2);
      assert(newGraph.hasNode(1));
      assert(newGraph.hasNode(2));
      assert(newGraph.hasNode(3));
      assert.strictEqual(newGraph.edge(1, 2), 'M->C');
      assert.strictEqual(newGraph.edge(2, 3), 'C->J');
    });

    it('should work with full mapping.', function () {
      var graph = new Graph();
      graph.addNode('Martha');
      graph.addNode('Catherine');
      graph.addNode('John');
      graph.addEdgeWithKey('M->C', 'Martha', 'Catherine');
      graph.addEdgeWithKey('C->J', 'Catherine', 'John');

      var newGraph = updateGraphKeys(
        graph,
        function (key) {
          if (key === 'Martha') return 1;
          if (key === 'Catherine') return 2;
          return 3;
        },
        function (key) {
          if (key === 'M->C') return 'rel1';
          return 'rel2';
        }
      );

      // Tests
      assert.strictEqual(newGraph.order, 3);
      assert.strictEqual(newGraph.size, 2);
      assert(newGraph.hasNode(1));
      assert(newGraph.hasNode(2));
      assert(newGraph.hasNode(3));
      assert.strictEqual(newGraph.edge(1, 2), 'rel1');
      assert.strictEqual(newGraph.edge(2, 3), 'rel2');
    });
  });

  describe('createWeightGetter', function () {
    it('should return valid weights from attributes.', function () {
      var graph = new Graph();
      graph.mergeEdge(1, 2, {weight: 3});
      graph.mergeEdge(3, 4, {custom: 2});
      graph.mergeEdge(4, 5);
      graph.mergeEdge(6, 7, {weight: NaN});
      graph.mergeEdge(8, 9, {weight: 'test'});

      var defaultGetter = createWeightGetter(null);
      var weightGetter = createWeightGetter('weight');
      var customGetter = createWeightGetter('custom');

      assert.strictEqual(defaultGetter(graph.getEdgeAttributes(1, 2)), 1);
      assert.strictEqual(weightGetter(graph.getEdgeAttributes(1, 2)), 3);
      assert.strictEqual(weightGetter(graph.getEdgeAttributes(3, 4)), 1);
      assert.strictEqual(customGetter(graph.getEdgeAttributes(3, 4)), 2);
      assert.strictEqual(weightGetter(graph.getEdgeAttributes(4, 5)), 1);
      assert.strictEqual(weightGetter(graph.getEdgeAttributes(6, 7)), 1);
      assert.strictEqual(weightGetter(graph.getEdgeAttributes(8, 9)), 1);
    });
  });

  describe('resolveDefaults', function () {
    it('should correctly resolve defaults.', function () {
      var defaults = {
        attributes: {
          weight: 'weight'
        },
        weighted: false
      };

      assert.deepStrictEqual(resolveDefaults({}, defaults), defaults);
      assert.deepStrictEqual(
        resolveDefaults({unkown: false, otherUnknown: 'test'}, defaults),
        defaults
      );
      assert.deepStrictEqual(resolveDefaults({weighted: true}, defaults), {
        attributes: {
          weight: 'weight'
        },
        weighted: true
      });
      assert.deepStrictEqual(
        resolveDefaults(
          {attributes: {unkown: 'test', weight: 'custom'}},
          defaults
        ),
        {
          attributes: {
            weight: 'custom'
          },
          weighted: false
        }
      );

      assert.deepStrictEqual(
        resolveDefaults({index: new Set([0, 1])}, {index: null}),
        {index: new Set([0, 1])}
      );

      assert.deepStrictEqual(
        resolveDefaults({index: null}, {index: new Set([0, 1])}),
        {index: new Set([0, 1])}
      );
    });
  });
});
<commit_msg>Adding unit test related to #252<commit_after>/**
 * Graphology Utils Unit Tests
 * ============================
 */
var assert = require('assert');
var Graph = require('graphology');
var inferType = require('./infer-type.js');
var isGraph = require('./is-graph.js');
var isGraphConstructor = require('./is-graph-constructor.js');
var mergeClique = require('./merge-clique.js');
var mergeCycle = require('./merge-cycle.js');
var mergePath = require('./merge-path.js');
var mergeStar = require('./merge-star.js');
var renameGraphKeys = require('./rename-graph-keys.js');
var updateGraphKeys = require('./update-graph-keys.js');
var getters = require('./getters.js');
var resolveDefaults = require('./defaults.js');

var UndirectedGraph = Graph.UndirectedGraph;
var createWeightGetter = getters.createWeightGetter;

describe('graphology-utils', function () {
  describe('inferType', function () {
    it('should correctly infer the type of the given graph.', function () {
      var graph = new Graph({type: 'mixed'});
      graph.mergeDirectedEdge(1, 2);

      assert.strictEqual(inferType(graph), 'directed');

      graph = new Graph({type: 'mixed'});
      graph.mergeUndirectedEdge(1, 2);

      assert.strictEqual(inferType(graph), 'undirected');

      graph = new Graph({type: 'mixed'});
      graph.mergeDirectedEdge(1, 2);
      graph.mergeUndirectedEdge(3, 4);

      assert.strictEqual(inferType(graph), 'mixed');

      graph = new Graph({type: 'mixed'});

      assert.strictEqual(inferType(graph), 'mixed');

      graph = new Graph({type: 'directed'});

      assert.strictEqual(inferType(graph), 'directed');

      graph = new Graph({type: 'undirected'});

      assert.strictEqual(inferType(graph), 'undirected');
    });
  });

  describe('isGraph', function () {
    it('should correctly return whether the given value is a graphology instance.', function () {
      var graph = new Graph(),
        multiDirectedGraph = new Graph(null, {multi: true, type: 'directed'});

      assert.strictEqual(isGraph(graph), true);
      assert.strictEqual(isGraph(multiDirectedGraph), true);

      var nonGraphs = [
        null,
        false,
        '',
        'test',
        0,
        -45,
        5380,
        6.4,
        {},
        [],
        {hello: 'world'},
        [1, 2, 3],
        new RegExp(),
        new Date()
      ];

      nonGraphs.forEach(function (value) {
        assert.strictEqual(isGraph(value), false);
      });
    });
  });

  describe('isGraphConstructor', function () {
    it('should correctly return whether the given value is a graphology constructor.', function () {
      assert.strictEqual(isGraphConstructor(Graph), true);
      assert.strictEqual(isGraphConstructor(UndirectedGraph), true);

      var nonGraphsConstructors = [
        null,
        false,
        '',
        'test',
        0,
        -45,
        5380,
        6.4,
        {},
        [],
        {hello: 'world'},
        [1, 2, 3],
        new RegExp(),
        new Date(),
        new Graph(),
        new UndirectedGraph()
      ];

      nonGraphsConstructors.forEach(function (value) {
        assert.strictEqual(isGraphConstructor(value), false);
      });
    });
  });

  describe('mergeClique', function () {
    it('should correctly add the given clique to the graph.', function () {
      var graph = new Graph();

      mergeClique(graph, ['1', '2', '3', '4', '5']);

      assert.strictEqual(graph.order, 5);
      assert.strictEqual(graph.size, 10);

      var adj = graph.edges().map(function (edge) {
        return graph.extremities(edge);
      });

      assert.deepStrictEqual(adj, [
        ['1', '2'],
        ['1', '3'],
        ['1', '4'],
        ['1', '5'],
        ['2', '3'],
        ['2', '4'],
        ['2', '5'],
        ['3', '4'],
        ['3', '5'],
        ['4', '5']
      ]);
    });
  });

  describe('mergeCycle', function () {
    it('should correctly add the given path to the graph.', function () {
      var graph = new Graph();

      mergeCycle(graph, ['1', '2', '3', '4', '5']);

      assert.strictEqual(graph.order, 5);
      assert.strictEqual(graph.size, 5);

      var adj = graph.edges().map(function (edge) {
        return graph.extremities(edge);
      });

      assert.deepStrictEqual(adj, [
        ['1', '2'],
        ['2', '3'],
        ['3', '4'],
        ['4', '5'],
        ['5', '1']
      ]);
    });
  });

  describe('mergePath', function () {
    it('should correctly add the given path to the graph.', function () {
      var graph = new Graph();

      mergePath(graph, ['1', '2', '3', '4', '5']);

      assert.strictEqual(graph.order, 5);
      assert.strictEqual(graph.size, 4);

      var adj = graph.edges().map(function (edge) {
        return graph.extremities(edge);
      });

      assert.deepStrictEqual(adj, [
        ['1', '2'],
        ['2', '3'],
        ['3', '4'],
        ['4', '5']
      ]);
    });
  });

  describe('mergeStar', function () {
    it('should correctly add the given star to the graph.', function () {
      var graph = new Graph();

      mergeStar(graph, ['1', '2', '3', '4', '5']);

      assert.strictEqual(graph.order, 5);
      assert.strictEqual(graph.size, 4);

      var adj = graph.edges().map(function (edge) {
        return graph.extremities(edge);
      });

      assert.deepStrictEqual(adj, [
        ['1', '2'],
        ['1', '3'],
        ['1', '4'],
        ['1', '5']
      ]);
    });
  });

  describe('renameGraphKeys', function () {
    it('should work with only node mapping.', function () {
      var graph = new Graph();
      graph.addNode('Martha');
      graph.addNode('Catherine');
      graph.addNode('John');
      graph.addEdgeWithKey('M->C', 'Martha', 'Catherine');
      graph.addEdgeWithKey('C->J', 'Catherine', 'John');

      var newGraph = renameGraphKeys(graph, {
        Martha: 1,
        Catherine: 2,
        John: 3
      });

      // Tests
      assert.strictEqual(newGraph.order, 3);
      assert.strictEqual(newGraph.size, 2);
      assert(newGraph.hasNode(1));
      assert(newGraph.hasNode(2));
      assert(newGraph.hasNode(3));
      assert.strictEqual(newGraph.edge(1, 2), 'M->C');
      assert.strictEqual(newGraph.edge(2, 3), 'C->J');
    });

    it('should work with full mapping.', function () {
      var graph = new Graph();
      graph.addNode('Martha');
      graph.addNode('Catherine');
      graph.addNode('John');
      graph.addEdgeWithKey('M->C', 'Martha', 'Catherine');
      graph.addEdgeWithKey('C->J', 'Catherine', 'John');

      var newGraph = renameGraphKeys(
        graph,
        {Martha: 1, Catherine: 2, John: 3},
        {'M->C': 'rel1', 'C->J': 'rel2'}
      );

      // Tests
      assert.strictEqual(newGraph.order, 3);
      assert.strictEqual(newGraph.size, 2);
      assert(newGraph.hasNode(1));
      assert(newGraph.hasNode(2));
      assert(newGraph.hasNode(3));
      assert.strictEqual(newGraph.edge(1, 2), 'rel1');
      assert.strictEqual(newGraph.edge(2, 3), 'rel2');
    });

    it.skip('should work with undirected graphs.', function () {
      var graph = new Graph({type: 'undirected'});
      graph.mergeEdge('Jon', 'Ishtar');
      graph.mergeEdge('Julia', 'Robin');

      var newGraph = renameGraphKeys(graph, {
        Jon: 'Joseph',
        Ishtar: 'Quixal'
      });

      console.log(newGraph);
    });
  });

  describe('updateGraphKeys', function () {
    it('should work with only node mapping.', function () {
      var graph = new Graph();
      graph.addNode('Martha');
      graph.addNode('Catherine');
      graph.addNode('John');
      graph.addEdgeWithKey('M->C', 'Martha', 'Catherine');
      graph.addEdgeWithKey('C->J', 'Catherine', 'John');

      var newGraph = updateGraphKeys(graph, function (key) {
        if (key === 'Martha') return 1;
        if (key === 'Catherine') return 2;
        return 3;
      });

      // Tests
      assert.strictEqual(newGraph.order, 3);
      assert.strictEqual(newGraph.size, 2);
      assert(newGraph.hasNode(1));
      assert(newGraph.hasNode(2));
      assert(newGraph.hasNode(3));
      assert.strictEqual(newGraph.edge(1, 2), 'M->C');
      assert.strictEqual(newGraph.edge(2, 3), 'C->J');
    });

    it('should work with full mapping.', function () {
      var graph = new Graph();
      graph.addNode('Martha');
      graph.addNode('Catherine');
      graph.addNode('John');
      graph.addEdgeWithKey('M->C', 'Martha', 'Catherine');
      graph.addEdgeWithKey('C->J', 'Catherine', 'John');

      var newGraph = updateGraphKeys(
        graph,
        function (key) {
          if (key === 'Martha') return 1;
          if (key === 'Catherine') return 2;
          return 3;
        },
        function (key) {
          if (key === 'M->C') return 'rel1';
          return 'rel2';
        }
      );

      // Tests
      assert.strictEqual(newGraph.order, 3);
      assert.strictEqual(newGraph.size, 2);
      assert(newGraph.hasNode(1));
      assert(newGraph.hasNode(2));
      assert(newGraph.hasNode(3));
      assert.strictEqual(newGraph.edge(1, 2), 'rel1');
      assert.strictEqual(newGraph.edge(2, 3), 'rel2');
    });
  });

  describe('createWeightGetter', function () {
    it('should return valid weights from attributes.', function () {
      var graph = new Graph();
      graph.mergeEdge(1, 2, {weight: 3});
      graph.mergeEdge(3, 4, {custom: 2});
      graph.mergeEdge(4, 5);
      graph.mergeEdge(6, 7, {weight: NaN});
      graph.mergeEdge(8, 9, {weight: 'test'});

      var defaultGetter = createWeightGetter(null);
      var weightGetter = createWeightGetter('weight');
      var customGetter = createWeightGetter('custom');

      assert.strictEqual(defaultGetter(graph.getEdgeAttributes(1, 2)), 1);
      assert.strictEqual(weightGetter(graph.getEdgeAttributes(1, 2)), 3);
      assert.strictEqual(weightGetter(graph.getEdgeAttributes(3, 4)), 1);
      assert.strictEqual(customGetter(graph.getEdgeAttributes(3, 4)), 2);
      assert.strictEqual(weightGetter(graph.getEdgeAttributes(4, 5)), 1);
      assert.strictEqual(weightGetter(graph.getEdgeAttributes(6, 7)), 1);
      assert.strictEqual(weightGetter(graph.getEdgeAttributes(8, 9)), 1);
    });
  });

  describe('resolveDefaults', function () {
    it('should correctly resolve defaults.', function () {
      var defaults = {
        attributes: {
          weight: 'weight'
        },
        weighted: false
      };

      assert.deepStrictEqual(resolveDefaults({}, defaults), defaults);
      assert.deepStrictEqual(
        resolveDefaults({unkown: false, otherUnknown: 'test'}, defaults),
        defaults
      );
      assert.deepStrictEqual(resolveDefaults({weighted: true}, defaults), {
        attributes: {
          weight: 'weight'
        },
        weighted: true
      });
      assert.deepStrictEqual(
        resolveDefaults(
          {attributes: {unkown: 'test', weight: 'custom'}},
          defaults
        ),
        {
          attributes: {
            weight: 'custom'
          },
          weighted: false
        }
      );

      assert.deepStrictEqual(
        resolveDefaults({index: new Set([0, 1])}, {index: null}),
        {index: new Set([0, 1])}
      );

      assert.deepStrictEqual(
        resolveDefaults({index: null}, {index: new Set([0, 1])}),
        {index: new Set([0, 1])}
      );
    });
  });
});
<|endoftext|>


<commit_before>/*
 * A Facet interactor is an object that exposes a list of events that
 * Facet.init uses to hook up to canvas event handlers.
 *
 * Facet.UI.center_zoom_interactor provides event handlers for the
 * common interaction mode of zooming and panning. Its main visible variables
 * are center and zoom Shade.parameter objects, together with a Shade.camera
 * that computes the appropriate projection matrix.
 *
 * usage examples:
 *   demos/beauty_of_roots
 *
 */

Facet.UI.center_zoom_interactor = function(opts)
{
    opts = _.defaults(opts, {
        mousemove: function() {},
        mousedown: function() {},
        mousewheel: function() {},
        center: vec.make([0,0]),
        zoom: 1
    });

    var height = opts.height;
    var width = opts.width;
    var center = Shade.parameter("vec2", opts.center);
    var zoom = Shade.parameter("float", opts.zoom);
    var prev_mouse_pos;

    function mousedown(event) {
        prev_mouse_pos = [event.offsetX, event.offsetY];
        opts.mousedown(event);
    }

    var c = vec.make([0, 0]);

    function mousemove(event) {
        if ((event.which & 1) && !event.shiftKey) {
            var deltaX =  (event.offsetX - prev_mouse_pos[0]) / (height * zoom.get() / 2);
            var deltaY = -(event.offsetY - prev_mouse_pos[1]) / (height * zoom.get() / 2);
            var negdelta = vec.make([-deltaX, -deltaY]);
            // we use a kahan compensated sum here:
            // http://en.wikipedia.org/wiki/Kahan_summation_algorithm
            // to accumulate minute changes in the center that come from deep zooms.
            var y = vec.minus(negdelta, c);
            var t = vec.plus(center.get(), y);
            c = vec.minus(vec.minus(t, center.get()), y);
            center.set(t); // vec.plus(center.get(), negdelta));
            Facet.Scene.invalidate();
        } else if ((event.which & 1) && event.shiftKey) {
            zoom.set(zoom.get() * (1.0 + (event.offsetY - prev_mouse_pos[1]) / 240));
            Facet.Scene.invalidate();
        }
        prev_mouse_pos = [ event.offsetX, event.offsetY ];
        opts.mousemove(event);
    }

    function mousewheel(event, delta, deltaX, deltaY) {
        zoom.set(zoom.get() * (1.0 - deltaY / 15));
        opts.mousewheel(event, delta, deltaX, deltaY);
        Facet.Scene.invalidate();
    }

    var aspect_ratio = Shade.parameter("float", width/height);
    var camera = Shade.Camera.ortho({
        center: center,
        zoom: zoom,
        aspect_ratio: aspect_ratio
    });

    return {
        camera: camera,
        center: center,
        zoom: zoom,

        resize: function(w, h) {
            aspect_ratio.set(w/h);
            width = w;
            height = h;
            Facet.Scene.invalidate();
        },

        events: {
            mousedown: mousedown,
            mousemove: mousemove,
            mousewheel: mousewheel
        }
    };
}
<commit_msg>missing semicolon<commit_after>/*
 * A Facet interactor is an object that exposes a list of events that
 * Facet.init uses to hook up to canvas event handlers.
 *
 * Facet.UI.center_zoom_interactor provides event handlers for the
 * common interaction mode of zooming and panning. Its main visible variables
 * are center and zoom Shade.parameter objects, together with a Shade.camera
 * that computes the appropriate projection matrix.
 *
 * usage examples:
 *   demos/beauty_of_roots
 *
 */

Facet.UI.center_zoom_interactor = function(opts)
{
    opts = _.defaults(opts, {
        mousemove: function() {},
        mousedown: function() {},
        mousewheel: function() {},
        center: vec.make([0,0]),
        zoom: 1
    });

    var height = opts.height;
    var width = opts.width;
    var center = Shade.parameter("vec2", opts.center);
    var zoom = Shade.parameter("float", opts.zoom);
    var prev_mouse_pos;

    function mousedown(event) {
        prev_mouse_pos = [event.offsetX, event.offsetY];
        opts.mousedown(event);
    }

    var c = vec.make([0, 0]);

    function mousemove(event) {
        if ((event.which & 1) && !event.shiftKey) {
            var deltaX =  (event.offsetX - prev_mouse_pos[0]) / (height * zoom.get() / 2);
            var deltaY = -(event.offsetY - prev_mouse_pos[1]) / (height * zoom.get() / 2);
            var negdelta = vec.make([-deltaX, -deltaY]);
            // we use a kahan compensated sum here:
            // http://en.wikipedia.org/wiki/Kahan_summation_algorithm
            // to accumulate minute changes in the center that come from deep zooms.
            var y = vec.minus(negdelta, c);
            var t = vec.plus(center.get(), y);
            c = vec.minus(vec.minus(t, center.get()), y);
            center.set(t); // vec.plus(center.get(), negdelta));
            Facet.Scene.invalidate();
        } else if ((event.which & 1) && event.shiftKey) {
            zoom.set(zoom.get() * (1.0 + (event.offsetY - prev_mouse_pos[1]) / 240));
            Facet.Scene.invalidate();
        }
        prev_mouse_pos = [ event.offsetX, event.offsetY ];
        opts.mousemove(event);
    }

    function mousewheel(event, delta, deltaX, deltaY) {
        zoom.set(zoom.get() * (1.0 - deltaY / 15));
        opts.mousewheel(event, delta, deltaX, deltaY);
        Facet.Scene.invalidate();
    }

    var aspect_ratio = Shade.parameter("float", width/height);
    var camera = Shade.Camera.ortho({
        center: center,
        zoom: zoom,
        aspect_ratio: aspect_ratio
    });

    return {
        camera: camera,
        center: center,
        zoom: zoom,

        resize: function(w, h) {
            aspect_ratio.set(w/h);
            width = w;
            height = h;
            Facet.Scene.invalidate();
        },

        events: {
            mousedown: mousedown,
            mousemove: mousemove,
            mousewheel: mousewheel
        }
    };
};
<|endoftext|>


<commit_before>import global from 'global';
import '../../shared/regenerator';
import { isProd } from '../../shared/EnvUtil';

// const System = global.System ? { import: global.System.import } : {};

// if (!System.import) {
//   System.import = function sysImport(arg) {
//     return require(arg); // eslint-disable-line global-require
//   };
// }

export default function loadPolyfills() {
  const promises = [];

  if (!global.Intl) {
    promises.push(
      System.import('intl'),
      System.import('intl/locale-data/jsonp/en.js'),
    );
  }

  if (!isProd) {
    promises.push(System.import('source-map-support/register'));
  }

  return Promise.all(promises);
}
<commit_msg>Node source maps support<commit_after>import global from 'global';
import '../../shared/regenerator';

// const System = global.System ? { import: global.System.import } : {};

// if (!System.import) {
//   System.import = function sysImport(arg) {
//     return require(arg); // eslint-disable-line global-require
//   };
// }

export default function loadPolyfills() {
  const promises = [];

  if (!global.Intl) {
    promises.push(
      System.import('intl'),
      System.import('intl/locale-data/jsonp/en.js'),
    );
  }

  if (webpack_globals.SIDE === 'server') { // eslint-disable-line
    promises.push(System.import('source-map-support/register'));
  }

  return Promise.all(promises);
}
<|endoftext|>


<commit_before>export default class Timer {
  constructor ({name, interval, currentTime}) {
    if(name == null){
      this.name = ''
    }else{
      this.name = name
    }

    this.interval = interval
    this.lastTime = currentTime
    this.callTime = 0

    this.listeners = new Set()
  }

  addListener (listener) {
    this.listeners.add(listener)
  }

  removeListener (listener) {
    this.listeners.delete(listener)
  }

  update (currentTime) {
    if(currentTime - this.lastTime >= this.interval) {
      this.callListeners()
      this.lastTime = currentTime
      this.callTime ++
      return
    }
  }

  callListeners () {
    var timeEvent = this.createTimeEvent()

    for (let listener of this.listeners) {
      var method = listener['on'+this.name+'Timer']
      method.call(listener, timeEvent)
    }
  }

  createTimeEvent () {
    return {time: this.callTime}
  }
}
<commit_msg>docsit<commit_after>export default class Timer {
  /**
   *
   * @param {string} name
   * @param {int} interval in millis
   * @param {int} currentTime in millis
   */
  constructor ({name, interval, currentTime}) {
    if(name == null){
      this.name = ''
    }else{
      this.name = name
    }

    this.interval = interval
    this.lastTime = currentTime
    this.callTime = 0

    this.listeners = new Set()
  }

  /**
   * Adds new listener to be called when timer updates
   *
   * @param {*} listener
   */
  addListener (listener) {
    this.listeners.add(listener)
  }

  /**
   * Removes listener from listeners
   *
   * @param {*} listener
  */
  removeListener (listener) {
    this.listeners.delete(listener)
  }

  /**
   * Checks if enough time has passed for timer update, and if it has, updates
   *
   * @param {*} currentTime
   */
  update (currentTime) {
    if(currentTime - this.lastTime >= this.interval) {
      this.callListeners()
      this.lastTime = currentTime
      this.callTime ++
      return
    }
  }

  /**
   * Helper method for calling all of the listeners
   */
  callListeners () {
    var timeEvent = this.createTimeEvent()

    for (let listener of this.listeners) {
      var method = listener['on'+this.name+'Timer']
      method.call(listener, timeEvent)
    }
  }

  /**
   * Function that creates the time event to be given to listeners
   */
  createTimeEvent () {
    return {time: this.callTime}
  }
}
<|endoftext|>


<commit_before>import React from 'react';
import Layout from './layout';
import Navbar from './navbar';
import { BadgeImage } from './inline';

const Dependencies = ({ caption, dependencies }) => (

  {
    dependencies.length
    ? (

        {caption}
        {dependencies.map(dep => {dep} )}

    )
    : null
  }

);

const Report = ({ caption, dependencies, devDependencies, badgeUrl }) => (

        {caption}
        <BadgeImage badgeUrl={badgeUrl} />

        {
          !dependencies.length && !devDependencies.length
          ?
Everything is good in this report, there is no unused dependencies.

          : null
        }
        <Dependencies
          caption="Unused dependencies"
          dependencies={dependencies}
        />
        <Dependencies
          caption="Unused devDependencies"
          dependencies={devDependencies}
        />

);

const Token = ({ repo, token, url }) =>
  token
  ? (

Repository token: {token}

Please keep the token security. Follow the depcheck tutorial to enjoy it.

  )
  : (
    <form method="post" action={url}>

Repository {repo} is not enabled for depcheck. Enable it with the below button, and follow the depcheck tutorial to enjoy it.

      <input className="btn btn-success pull-right" type="submit" value="Enable Depcheck" />
    </form>
  );

export default React.createClass({
  render() {
    return (
      <Layout>

          {this.props.repo}

          from {this.props.provider}/{this.props.user}

        <Navbar />

            {
              this.props.reports.map(report =>
                <Report key={report.caption} {...report}/>)
            }

            <Token
              repo={this.props.repo}
              token={this.props.token}
              url={this.props.tokenUrl}
            />

      </Layout>
    );
  },
});
<commit_msg>Add the tutorial link in the repo page anchors.<commit_after>import React from 'react';
import Layout from './layout';
import Navbar from './navbar';
import { BadgeImage } from './inline';

const Dependencies = ({ caption, dependencies }) => (

  {
    dependencies.length
    ? (

        {caption}
        {dependencies.map(dep => {dep} )}

    )
    : null
  }

);

const Report = ({ caption, dependencies, devDependencies, badgeUrl }) => (

        {caption}
        <BadgeImage badgeUrl={badgeUrl} />

        {
          !dependencies.length && !devDependencies.length
          ?
Everything is good in this report, there is no unused dependencies.

          : null
        }
        <Dependencies
          caption="Unused dependencies"
          dependencies={dependencies}
        />
        <Dependencies
          caption="Unused devDependencies"
          dependencies={devDependencies}
        />

);

const Token = ({ repo, token, url }) =>
  token
  ? (

Repository token: {token}

Please keep the token security. Follow the depcheck tutorial to enjoy it.

  )
  : (
    <form method="post" action={url}>

Repository {repo} is not enabled for depcheck. Enable it with the below button, and follow the depcheck tutorial to enjoy it.

      <input className="btn btn-success pull-right" type="submit" value="Enable Depcheck" />
    </form>
  );

export default React.createClass({
  render() {
    return (
      <Layout>

          {this.props.repo}

          from {this.props.provider}/{this.props.user}

        <Navbar />

            {
              this.props.reports.map(report =>
                <Report key={report.caption} {...report}/>)
            }

            <Token
              repo={this.props.repo}
              token={this.props.token}
              url={this.props.tokenUrl}
            />

      </Layout>
    );
  },
});
<|endoftext|>


<commit_before>/*global navigator, window */

var VideoFlow = require('./videoFlow');
module.exports = WebCamFlow;

/**
 * A high level interface to capture optical flow from the web camera.
 * @param defaultVideoTag {DOMElement} optional reference to <video> tag
 *   where web camera output should be rendered. If parameter is not
 *   present a new invisible <video> tag is created.
 * @param zoneSize {int} optional size of a flow zone in pixels. 8 by default
 * @param cameraFacing {string} optional direction camera is facing (either
 * 'user' or 'environment') used to give preference to a particular mobile
 * camera. If matching camera is not found, any available one will be used.
 *
 * Usage example:
 *  var flow = new WebCamFlow();
 *
 *  // Every time when optical flow is calculated
 *  // call the passed in callback:
 *  flow.onCalculated(function (direction) {
 *      // direction is an object which describes current flow:
 *      // direction.u, direction.v {floats} general flow vector
 *      // direction.zones {Array} is a collection of flowZones.
 *      //  Each flow zone describes optical flow direction inside of it.
 *  });
 *  // Starts capturing the flow from webcamera:
 *  flow.startCapture();
 *  // once you are done capturing call
 *  flow.stopCapture();
 */
function WebCamFlow(defaultVideoTag, zoneSize, cameraFacing) {
    var videoTag,
        isCapturing,
        localStream,
        calculatedCallbacks = [],
        flowCalculatedCallback,
        videoFlow,
        onWebCamFail = function onWebCamFail(e) {
            if(e.code === 1){
                window.alert('You have denied access to your camera. I cannot do anything.');
            } else {
                window.alert('getUserMedia() is not supported in your browser.');
            }
        },
        gotFlow = function(direction) {
            calculatedCallbacks.forEach(function (callback) {
                callback(direction);
            });
        },
        initCapture = function() {
        if (!videoFlow) {
            videoTag = defaultVideoTag || window.document.createElement('video');
            videoTag.setAttribute('autoplay', true);
            videoFlow = new VideoFlow(videoTag, zoneSize);
        }

        if (window.MediaStreamTrack.getSources) {
            window.MediaStreamTrack.getSources(function(sourceInfos) {
                for (var i = 0; i < sourceInfos.length; i++) {
                    if (sourceInfos[i].kind === 'video'){
                        selectedVideoSource = sourceInfos[i].id;
                        // if camera facing requested direction is found, stop search
                        if (sourceInfos[i].facing === cameraFacing) {
                            break;
                        }
                    }
                }

                desiredDevice = { optional: [{sourceId: selectedVideoSource}] };

                navigator.getUserMedia({ video: desiredDevice }, function(stream) {
                    isCapturing = true;
                    localStream = stream;
                    videoTag.src = window.URL.createObjectURL(stream);
                    if (stream) {
                        videoFlow.startCapture(videoTag);
                        videoFlow.onCalculated(gotFlow);
                    }
                }, onWebCamFail);
            });
        } else if(navigator.mediaDevices.enumerateDevices) {
            navigator.mediaDevices.enumerateDevices().then(
                function(sourceInfos){
                    for (var i = 0; i < sourceInfos.length; i++) {
                        if(sourceInfos[i].kind == "videoinput"){
                            selectedVideoSource = sourceInfos[i].deviceId;
                        }
                    }

                    desiredDevice = { optional: [{sourceId: selectedVideoSource}] };

                    navigator.getUserMedia({ video: desiredDevice }, function(stream) {
                        isCapturing = true;
                        localStream = stream;
                        videoTag.src = window.URL.createObjectURL(stream);
                        if (stream) {
                            videoFlow.startCapture(videoTag);
                            videoFlow.onCalculated(gotFlow);
                        }
                    }, onWebCamFail);
                }
            );
        }

    };

    if (!navigator.getUserMedia) {
        navigator.getUserMedia = navigator.getUserMedia ||
                                 navigator.webkitGetUserMedia ||
                                 navigator.mozGetUserMedia ||
                                 navigator.msGetUserMedia;
    }

    // our public API
    this.startCapture = function () {
        if (!isCapturing) {
            initCapture();
        }
    };
    this.onCalculated = function (callback) {
        calculatedCallbacks.push(callback);
    };
    this.stopCapture = function() {
        isCapturing = false;
        if (videoFlow) { videoFlow.stopCapture(); }
        if (videoTag) { videoTag.pause(); }
        if (localStream) { localStream.stop(); }
    };
}
<commit_msg>Fixes Deprecation of createObjectURL in new browsers<commit_after>/*global navigator, window */

var VideoFlow = require('./videoFlow');
module.exports = WebCamFlow;

/**
 * A high level interface to capture optical flow from the web camera.
 * @param defaultVideoTag {DOMElement} optional reference to <video> tag
 *   where web camera output should be rendered. If parameter is not
 *   present a new invisible <video> tag is created.
 * @param zoneSize {int} optional size of a flow zone in pixels. 8 by default
 * @param cameraFacing {string} optional direction camera is facing (either
 * 'user' or 'environment') used to give preference to a particular mobile
 * camera. If matching camera is not found, any available one will be used.
 *
 * Usage example:
 *  var flow = new WebCamFlow();
 *
 *  // Every time when optical flow is calculated
 *  // call the passed in callback:
 *  flow.onCalculated(function (direction) {
 *      // direction is an object which describes current flow:
 *      // direction.u, direction.v {floats} general flow vector
 *      // direction.zones {Array} is a collection of flowZones.
 *      //  Each flow zone describes optical flow direction inside of it.
 *  });
 *  // Starts capturing the flow from webcamera:
 *  flow.startCapture();
 *  // once you are done capturing call
 *  flow.stopCapture();
 */
function WebCamFlow(defaultVideoTag, zoneSize, cameraFacing) {
    var videoTag,
        isCapturing,
        localStream,
        calculatedCallbacks = [],
        flowCalculatedCallback,
        videoFlow,
        onWebCamFail = function onWebCamFail(e) {
            if(e.code === 1){
                window.alert('You have denied access to your camera. I cannot do anything.');
            } else {
                window.alert('getUserMedia() is not supported in your browser.');
            }
        },
        gotFlow = function(direction) {
            calculatedCallbacks.forEach(function (callback) {
                callback(direction);
            });
        },
        initCapture = function() {
        if (!videoFlow) {
            videoTag = defaultVideoTag || window.document.createElement('video');
            videoTag.setAttribute('autoplay', true);
            videoFlow = new VideoFlow(videoTag, zoneSize);
        }

        if (window.MediaStreamTrack.getSources) {
            window.MediaStreamTrack.getSources(function(sourceInfos) {
                for (var i = 0; i < sourceInfos.length; i++) {
                    if (sourceInfos[i].kind === 'video'){
                        selectedVideoSource = sourceInfos[i].id;
                        // if camera facing requested direction is found, stop search
                        if (sourceInfos[i].facing === cameraFacing) {
                            break;
                        }
                    }
                }

                desiredDevice = { optional: [{sourceId: selectedVideoSource}] };

                navigator.getUserMedia({ video: desiredDevice }, function(stream) {
                    isCapturing = true;
                    localStream = stream;
                    if ("srcObject" in videoTag) {
                        videoTag.srcObject = stream;
                    } else {
                        videoTag.src = window.URL.createObjectURL(stream);
                    }
                    if (stream) {
                        videoFlow.startCapture(videoTag);
                        videoFlow.onCalculated(gotFlow);
                    }
                }, onWebCamFail);
            });
        } else if(navigator.mediaDevices.enumerateDevices) {
            navigator.mediaDevices.enumerateDevices().then(
                function(sourceInfos){
                    for (var i = 0; i < sourceInfos.length; i++) {
                        if(sourceInfos[i].kind == "videoinput"){
                            selectedVideoSource = sourceInfos[i].deviceId;
                        }
                    }

                    desiredDevice = { optional: [{sourceId: selectedVideoSource}] };

                    navigator.getUserMedia({ video: desiredDevice }, function(stream) {
                        isCapturing = true;
                        localStream = stream;
                        if ("srcObject" in videoTag) {
                            videoTag.srcObject = stream;
                        } else {
                            videoTag.src = window.URL.createObjectURL(stream);
                        }
                        if (stream) {
                            videoFlow.startCapture(videoTag);
                            videoFlow.onCalculated(gotFlow);
                        }
                    }, onWebCamFail);
                }
            );
        }

    };

    if (!navigator.getUserMedia) {
        navigator.getUserMedia = navigator.getUserMedia ||
                                 navigator.webkitGetUserMedia ||
                                 navigator.mozGetUserMedia ||
                                 navigator.msGetUserMedia;
    }

    // our public API
    this.startCapture = function () {
        if (!isCapturing) {
            initCapture();
        }
    };
    this.onCalculated = function (callback) {
        calculatedCallbacks.push(callback);
    };
    this.stopCapture = function() {
        isCapturing = false;
        if (videoFlow) { videoFlow.stopCapture(); }
        if (videoTag) { videoTag.pause(); }
        if (localStream) { localStream.stop(); }
    };
}
<|endoftext|>


<commit_before>//requires: wef

/*!
 * Wef logger
 * Copyright (c) 2011 Pablo Escalada
 * MIT Licensed
 */
(function () {
    var LOGLEVEL = {
        all:-1,
        trace:1,
        debug:2,
        log:2,
        info:3,
        warn:4,
        error:5,
        none:100
    };

    var textFormatter = function() {
        return this;
    };

    textFormatter.prototype.format = function (messages, indentationLevel, type) {
        var tmp = [],
            levelMarks = "                                                                                ",
            levelText, typeText;
        tmp = Array.prototype.slice.call(messages, tmp);
        if (failSafeIndentation && indentationLevel) {
            levelText = levelMarks.slice(0, indentationLevel);
            tmp.unshift(levelText);
        }
        if (type) {
            typeText = "[" + type + "]";
            tmp.unshift(levelText);
        }
        return tmp;
    };

    var registered = {},
        lastLogger,
        failSafeIndentation = false,
        logger = function(logName) {
            if (!logName || logName == "") {
                logName = "default";
            }
            var name = lastLogger = logName || lastLogger;
            if (registered[lastLogger]) {
                return registered[lastLogger].logger;
            } else {
                var tmpLogger = new logger.prototype.init(lastLogger);
                registered[lastLogger] = {logLevel: LOGLEVEL.all, indentationLevel: 0, logger: tmpLogger};
                return tmpLogger;
            }
        };

    logger.prototype.constructor = logger;
    logger.prototype.version = "0.0.1";
    logger.prototype.formatter = new textFormatter();
    logger.prototype.init = function (logName) {
        this.logName = logName;
        return this;
    };

    logger.prototype._filteredLogs = function() {
        return filteredLogs;
    };
    logger.prototype._getIndentLevel = function(logName) {
        return registered[logName].indentationLevel;
    };

    /**
     * Filter current loggers by name and priority level.
     * Only log entries from matched loggers and priority > filter level are allowed. Filtered logs are lost.
     *
     * @param {Object|string} options Filter options. There are two shorcuts :
     * string "all" activate all loggers (logLevel: -1, pattern: ".*")
     * string "none" deactivate all loggers (logLevel: 100, pattern: ".*")
     * @param {number} options.logLevel Priority level
     * @param {string} options.pattern Pattern that matches against current registered loggers. Pattern must be regExp
     * compatible.
     * */
    logger.filter = logger.prototype.filter = function (options) {
        if (!options) return this;

        if (options == "none" || options == "off") {
            options = {logLevel: LOGLEVEL.none, pattern: ".*"};
        }

        if (options == "all" || options == "on") {
            options = {logLevel: LOGLEVEL.all, pattern: ".*"};
        }

        if (!options.logLevel || typeof options.logLevel != "number" || !options.pattern || typeof options.pattern != "string") {
            //do nothing
            return this;
        }
        var regExp = new RegExp(options.pattern), logLevel = options.logLevel;

        for (var name in registered) {
            if (regExp.test(name)) {
                registered[name].logLevel = logLevel;
            } else {
                registered[name].logLevel = LOGLEVEL.none;
            }
        }
        filteredLogs = 0;
        return this;
    };

    logger.prototype.backend = window.console || {};
    logger.prototype.backend.failSafe = function () {
        //silent
    };
    logger.prototype.backend.failSafeGroup = function () {
        failSafeIndentation = true;
    };
    logger.prototype.backend.failSafeGroupEnd = function () {
        failSafeIndentation = true;
    };
    logger.prototype.backend.trace = window.console.trace || logger.prototype.backend.log;
    logger.prototype.backend.log = window.console.log || logger.prototype.backend.failSafe;
    logger.prototype.backend.debug = window.console.debug || logger.prototype.backend.log;
    logger.prototype.backend.info = window.console.info || logger.prototype.backend.log;
    logger.prototype.backend.warn = window.console.warn || logger.prototype.backend.log;
    logger.prototype.backend.error = window.console.error || logger.prototype.backend.log;
    logger.prototype.backend.group = window.console.group || logger.prototype.backend.failSafeGroup;
    logger.prototype.backend.groupCollapsed = window.console.groupCollapsed || window.console.group || logger.prototype.backend.failSafeGroup;
    logger.prototype.backend.groupEnd = window.console.groupEnd || logger.prototype.backend.failSafeGroupEnd;

    logger.prototype.init.prototype = logger.prototype;

    logger.prototype.init.prototype.debug = function (message) {
        if (registered[lastLogger].logLevel > LOGLEVEL.debug) {
            filteredLogs++;
            return this;
        }
        this.backend.debug.apply(this.backend, this.formatter.format(arguments, registered[lastLogger].indentationLevel));
        return this;
    };

    logger.prototype.init.prototype.error = function (message) {
        if (registered[lastLogger].logLevel > LOGLEVEL.error) {
            filteredLogs++;
            return this;
        }
        this.backend.error.apply(this.backend, this.formatter.format(arguments, registered[lastLogger].indentationLevel));
        return this;
    };

    logger.prototype.init.prototype.info = function (message) {
        if (registered[lastLogger].logLevel > LOGLEVEL.info) {
            filteredLogs++;
            return this;
        }
        this.backend.info.apply(this.backend, this.formatter.format(arguments, registered[lastLogger].indentationLevel));
        return this;
    };

    logger.prototype.init.prototype.warn = function (message) {
        if (registered[lastLogger].logLevel > LOGLEVEL.warn) {
            filteredLogs++;
            return this;
        }
        this.backend.warn.apply(this.backend, this.formatter.format(arguments, registered[lastLogger].indentationLevel));
        return this;
    };

    logger.prototype.init.prototype.log = function (message) {
        if (registered[lastLogger].logLevel > LOGLEVEL.log) {
            filteredLogs++;
            return this;
        }
        this.backend.log.apply(this.backend, this.formatter.format(arguments, registered[lastLogger].indentationLevel));
        return this;
    };

    logger.prototype.init.prototype.trace = function () {
        if (registered[lastLogger].logLevel > LOGLEVEL.trace) {
            filteredLogs++;
            return this;
        }
        this.backend.trace.call(this.backend);
        return this;
    };

    logger.prototype.init.prototype.group = function (message) {
        registered[lastLogger].indentationLevel++;
        this.backend.groupCollapsed.call(this.backend);
        if (registered[lastLogger].logLevel > LOGLEVEL.log) {
            filteredLogs++;
            return this;
        }
        if (message) {
            this.log.apply(this, arguments);
        }
        return this;
    };

    logger.prototype.init.prototype.groupEnd = function (message) {
        registered[lastLogger].indentationLevel--;
        this.backend.groupEnd.call(this.backend);
        if (registered[lastLogger].logLevel > LOGLEVEL.trace) {
            filteredLogs++;
            return this;
        }
        if (message) {
            this.log.apply(this, arguments);
        }
        return this;
    };

    wef.logger = logger;
})();<commit_msg>Fix lint errors<commit_after>/*!
 * Wef logger
 * Copyright (c) 2011 Pablo Escalada
 * MIT Licensed
 */
(function (wef) {
    var LOGLEVEL = {
        all:-1,
        trace:1,
        debug:2,
        log:2,
        info:3,
        warn:4,
        error:5,
        none:100
    }, textFormatter, registered = {}, lastLogger, failSafeIndentation = false, logger, filteredLogs = 0;

    textFormatter = function () {
        return this;
    };

    textFormatter.prototype.format = function (messages, indentationLevel, type) {
        var tmp = [], levelMarks = "                                                                                ", levelText, typeText;
        tmp = new Array(Array.prototype.slice.call(messages, tmp));
        if (failSafeIndentation && indentationLevel) {
            levelText = levelMarks.slice(0, indentationLevel);
            tmp.unshift(levelText);
        }
        if (type) {
            typeText = "[" + type + "]";
            tmp.unshift(typeText);
        }
        return tmp;
    };

    logger = function (logName) {
        if (!logName || logName === "") {
            logName = "default";
        }
        lastLogger = logName;
        if (registered[lastLogger]) {
            return registered[lastLogger].logger;
        } else {
            var tmpLogger = new logger.prototype.init(lastLogger);
            registered[lastLogger] = {logLevel:LOGLEVEL.all, indentationLevel:0, logger:tmpLogger};
            return tmpLogger;
        }
    };

    logger.prototype.constructor = logger;

    logger.prototype.version = "0.0.1";

    logger.prototype.logName = "";

    logger.prototype.formatter = new textFormatter();

    logger.prototype.init = function (logName) {
        this.logName = logName;
        return this;
    };

    logger.prototype._filteredLogs = function () {
        return filteredLogs;
    };

    logger.prototype._getIndentLevel = function (logName) {
        return registered[logName].indentationLevel;
    };

    /**
     * Filter current loggers by name and priority level.
     * Only log entries from matched loggers and priority > filter level are allowed. Filtered logs are lost.
     *
     * @param {Object|string} options Filter options. There are two shorcuts :
     * string "all" activate all loggers (logLevel: -1, pattern: ".*")
     * string "none" deactivate all loggers (logLevel: 100, pattern: ".*")
     * @param {number} options.logLevel Priority level
     * @param {string} options.pattern Pattern that matches against current registered loggers. Pattern must be regExp
     * compatible.
     * */
    logger.filter = logger.prototype.filter = function (options) {
        if (!options) {
            return this;
        }

        if (options == "none" || options == "off") {
            options = {logLevel:LOGLEVEL.none, pattern:".*"};
        }

        if (options == "all" || options == "on") {
            options = {logLevel:LOGLEVEL.all, pattern:".*"};
        }

        if (!options.logLevel || typeof options.logLevel != "number" || !options.pattern || typeof options.pattern != "string") {
            //do nothing
            return this;
        }
        var regExp = new RegExp(options.pattern), logLevel = options.logLevel, name;

        for (name in registered) {
            if (registered.hasOwnProperty(name)) {
                if (regExp.test(name)) {
                    registered[name].logLevel = logLevel;
                } else {
                    registered[name].logLevel = LOGLEVEL.none;
                }
            }
        }
        filteredLogs = 0;
        return this;
    };

    logger.prototype.backend = window.console || {};

    logger.prototype.backend.failSafe = function () {
        //silent
    };

    logger.prototype.backend.failSafeGroup = function () {
        failSafeIndentation = true;
    };

    logger.prototype.backend.failSafeGroupEnd = function () {
        failSafeIndentation = true;
    };

    logger.prototype.backend.trace = window.console.trace || logger.prototype.backend.log;

    logger.prototype.backend.log = window.console.log || logger.prototype.backend.failSafe;

    logger.prototype.backend.debug = window.console.debug || logger.prototype.backend.log;

    logger.prototype.backend.info = window.console.info || logger.prototype.backend.log;

    logger.prototype.backend.warn = window.console.warn || logger.prototype.backend.log;

    logger.prototype.backend.error = window.console.error || logger.prototype.backend.log;

    logger.prototype.backend.group = window.console.group || logger.prototype.backend.failSafeGroup;

    logger.prototype.backend.groupCollapsed = window.console.groupCollapsed || window.console.group || logger.prototype.backend.failSafeGroup;

    logger.prototype.backend.groupEnd = window.console.groupEnd || logger.prototype.backend.failSafeGroupEnd;

    logger.prototype.init.prototype = logger.prototype;

    logger.prototype.init.prototype.debug = function (message) {
        if (registered[lastLogger].logLevel > LOGLEVEL.debug) {
            filteredLogs++;
            return this;
        }
        this.backend.debug.apply(this.backend, this.formatter.format(arguments, registered[lastLogger].indentationLevel));
        return this;
    };

    logger.prototype.init.prototype.error = function (message) {
        if (registered[lastLogger].logLevel > LOGLEVEL.error) {
            filteredLogs++;
            return this;
        }
        this.backend.error.apply(this.backend, this.formatter.format(arguments, registered[lastLogger].indentationLevel));
        return this;
    };

    logger.prototype.init.prototype.info = function (message) {
        if (registered[lastLogger].logLevel > LOGLEVEL.info) {
            filteredLogs++;
            return this;
        }
        this.backend.info.apply(this.backend, this.formatter.format(arguments, registered[lastLogger].indentationLevel));
        return this;
    };

    logger.prototype.init.prototype.warn = function (message) {
        if (registered[lastLogger].logLevel > LOGLEVEL.warn) {
            filteredLogs++;
            return this;
        }
        this.backend.warn.apply(this.backend, this.formatter.format(arguments, registered[lastLogger].indentationLevel));
        return this;
    };

    logger.prototype.init.prototype.log = function (message) {
        if (registered[lastLogger].logLevel > LOGLEVEL.log) {
            filteredLogs++;
            return this;
        }
        this.backend.log.apply(this.backend, this.formatter.format(arguments, registered[lastLogger].indentationLevel));
        return this;
    };

    logger.prototype.init.prototype.trace = function () {
        if (registered[lastLogger].logLevel > LOGLEVEL.trace) {
            filteredLogs++;
            return this;
        }
        this.backend.trace.call(this.backend);
        return this;
    };

    logger.prototype.init.prototype.group = function (message) {
        registered[lastLogger].indentationLevel++;
        this.backend.groupCollapsed.call(this.backend);
        if (registered[lastLogger].logLevel > LOGLEVEL.log) {
            filteredLogs++;
            return this;
        }
        if (message) {
            this.log.apply(this, arguments);
        }
        return this;
    };

    logger.prototype.init.prototype.groupEnd = function (message) {
        registered[lastLogger].indentationLevel--;
        this.backend.groupEnd.call(this.backend);
        if (registered[lastLogger].logLevel > LOGLEVEL.trace) {
            filteredLogs++;
            return this;
        }
        if (message) {
            this.log.apply(this, arguments);
        }
        return this;
    };

    wef.logger = logger;

})(window.wef);<|endoftext|>


<commit_before>// Loader for the changelog.json
define(['ash', 'game/GameGlobals', 'game/GlobalSignals', 'game/constants/GameConstants'],
function (Ash, GameGlobals, GlobalSignals, GameConstants) {

    var ChangeLogHelper = Ash.Class.extend({

		loadingSuccesfull: undefined,
		versions: null,

		constructor: function () {
			var helper = this;
            $.getJSON('changelog.json', function (json) {
				helper.loadingSuccessful = true;
				helper.versions = json.versions;
                var version = helper.getCurrentVersionNumber();
                log.i("Loaded version: " + version);
                gtag('set', { 'app_version': version });
                GlobalSignals.changelogLoadedSignal.dispatch(true);
                helper.displayVersionWarnings();
			})
			.fail(function (jqxhr, textStatus, error) {
				helper.loadingSuccessful = false;
                helper.versions = [];
                log.w("Failed to load version.");
				var err = "";
                if (jqxhr && jqxhr.status) err += "[" + jqxhr.status + "] ";
                err += textStatus;
				if (error) err += ", " + error;
                gtag('set', { 'app_version': 'unknown' });
                GlobalSignals.changelogLoadedSignal.dispatch(false);
                helper.displayVersionWarnings();
			});
		},

        displayVersionWarnings: function () {
            if (GameConstants.isDebugVersion) return;
			var currentVersion = this.getCurrentVersion();
            if (!currentVersion || !currentVersion.final) {
                GameGlobals.uiFunctions.showInfoPopup(
                    "Warning",
                    "Looks like you are playing an unsupported version of Level 13.
Continue at your own risk or play the latest official version here.",
                    "Continue"
                );
            }
        },

		getCurrentVersionNumber: function () {
			var currentVersion = this.getCurrentVersion();
			if (currentVersion) {
				return this.getVersionNumber(currentVersion);
			}
			return "unknown";
		},

        getCurrentVersionDate: function () {
			var currentVersion = this.getCurrentVersion();
			if (currentVersion) {
				return currentVersion.final ? currentVersion.released : currentVersion.updated;
			}
			return "[no time stamp]";
        },

		getVersionNumber: function (version) {
			return version.version + " (" + version.phase + ")";
		},

		getCurrentVersion: function () {
			if (!this.versions) return null;

			var version = null;
			var i = 0;
			while (!version && i < this.versions.length) {
				if (this.versions[i].changes.length > 0) version = this.versions[i];
				i++;
			}
			return version;
		},

        getVersionDigits: function (version) {
            var parts1 = version.split(" ");
            var parts2 = parts1[0].split(".");
            return { major: parts2[0], minor: parts2[1], patch: parts2[2] };
        },

        isOldVersion: function (version) {
            var currentVersionNumber = this.getCurrentVersionNumber();
            var currentVersionDigits = this.getVersionDigits(currentVersionNumber);
            var compareVersionDigits = this.getVersionDigits(version);
            log.i("isOldVersion?")
            log.i(currentVersionDigits);
            log.i(compareVersionDigits)
            if (!currentVersionDigits) return false;
            if (!compareVersionDigits) return false;
            return compareVersionDigits.major < currentVersionDigits.major || compareVersionDigits.minor < currentVersionDigits.minor || compareVersionDigits.patch < currentVersionDigits.patch;
        },

    });

    return ChangeLogHelper;
});
<commit_msg>[versioning] define requiredVersion for each version and use it to determine whether to show the save version warning popup<commit_after>// Loader for the changelog.json
define(['ash', 'game/GameGlobals', 'game/GlobalSignals', 'game/constants/GameConstants'],
function (Ash, GameGlobals, GlobalSignals, GameConstants) {

    var ChangeLogHelper = Ash.Class.extend({

		loadingSuccesfull: undefined,
		versions: null,

		constructor: function () {
			var helper = this;
            $.getJSON('changelog.json', function (json) {
				helper.loadingSuccessful = true;
				helper.versions = json.versions;
                var version = helper.getCurrentVersionNumber();
                log.i("Loaded version: " + version);
                gtag('set', { 'app_version': version });
                GlobalSignals.changelogLoadedSignal.dispatch(true);
                helper.displayVersionWarnings();
			})
			.fail(function (jqxhr, textStatus, error) {
				helper.loadingSuccessful = false;
                helper.versions = [];
                log.w("Failed to load version.");
				var err = "";
                if (jqxhr && jqxhr.status) err += "[" + jqxhr.status + "] ";
                err += textStatus;
				if (error) err += ", " + error;
                gtag('set', { 'app_version': 'unknown' });
                GlobalSignals.changelogLoadedSignal.dispatch(false);
                helper.displayVersionWarnings();
			});
		},

        displayVersionWarnings: function () {
            if (GameConstants.isDebugVersion) return;
			var currentVersion = this.getCurrentVersion();
            if (!currentVersion || !currentVersion.final) {
                GameGlobals.uiFunctions.showInfoPopup(
                    "Warning",
                    "Looks like you are playing an unsupported version of Level 13.
Continue at your own risk or play the latest official version here.",
                    "Continue"
                );
            }
        },

		getCurrentVersionNumber: function () {
			var currentVersion = this.getCurrentVersion();
			if (currentVersion) {
				return this.getVersionNumber(currentVersion);
			}
			return "unknown";
		},

        getCurrentVersionDate: function () {
			var currentVersion = this.getCurrentVersion();
			if (currentVersion) {
				return currentVersion.final ? currentVersion.released : currentVersion.updated;
			}
			return "[no time stamp]";
        },

		getVersionNumber: function (version) {
			return version.version + " (" + version.phase + ")";
		},

		getCurrentVersion: function () {
			if (!this.versions) return null;

			var version = null;
			var i = 0;
			while (!version && i < this.versions.length) {
				if (this.versions[i].changes.length > 0) version = this.versions[i];
				i++;
			}
			return version;
		},

        getVersion: function (version) {
            for (var i = 0; i < this.versions.legnth; i++) {
                if (this.versions[i].version == version) {
                    return this.versions[i];
                }
            }
            return null;
        },

        getVersionDigits: function (version) {
            var parts1 = version.split(" ");
            var parts2 = parts1[0].split(".");
            return { major: parts2[0], minor: parts2[1], patch: parts2[2] };
        },

        isOldVersion: function (version) {
            var currentVersionNumber = this.getCurrentVersionNumber();
            var currentVersionDetails = this.getCurrentVersion();
            var requiredVersion = currentVersionDetails && currentVersionDetails.requiredVersion || currentVersionNumber;
            var requiredVersionDigits = this.getVersionDigits(requiredVersion);
            var compareVersionDigits = this.getVersionDigits(version);

            log.i("isOldVersion? " + version + ", current: " + currentVersionNumber + ", required: " + requiredVersion);
            if (!requiredVersionDigits) return false;
            if (!compareVersionDigits) return false;
            return compareVersionDigits.major < requiredVersionDigits.major || compareVersionDigits.minor < requiredVersionDigits.minor || compareVersionDigits.patch < requiredVersionDigits.patch;
        },

    });

    return ChangeLogHelper;
});
<|endoftext|>


<commit_before>// import isFinite from 'lodash/isFinite'
import isEqual from 'lodash/isEqual'
import pickBy from 'lodash/pickBy'
import { utcFormat, utcParse } from 'd3-time-format'

import {
  camelToSnakeCase,
  createRawObject,
  forEach,
  isArray,
  isBoolean,
  isFunction,
  isInteger,
  isObject,
  isString,
  map,
  mapToArray,
  noop
} from '../utils'

// ===================================================================

export const asBoolean = value => Boolean(value)

// const asFloat = value => {
//   value = String(value)
//   return value.indexOf('.') === -1
//     ? `${value}.0`
//     : value
// }

export const asInteger = value => String(value)

export const filterUndefineds = obj => pickBy(obj, value => value !== undefined)

export const optional = (value, fn) => value == null
  ? undefined
  : fn ? fn(value) : value

export const prepareXapiParam = param => {
  // if (isFinite(param) && !isInteger(param)) {
  //   return asFloat(param)
  // }
  if (isInteger(param)) {
    return asInteger(param)
  }
  if (isBoolean(param)) {
    return asBoolean(param)
  }
  if (isObject(param)) {
    return map(filterUndefineds(param), prepareXapiParam)
  }

  return param
}

// -------------------------------------------------------------------

const OPAQUE_REF_RE = /OpaqueRef:[0-9a-z-]+/
export const extractOpaqueRef = str => {
  const matches = OPAQUE_REF_RE.exec(str)
  if (!matches) {
    throw new Error('no opaque ref found')
  }
  return matches[0]
}

// -------------------------------------------------------------------

const TYPE_TO_NAMESPACE = createRawObject()
forEach([
  'Bond',
  'DR_task',
  'GPU_group',
  'PBD',
  'PCI',
  'PGPU',
  'PIF',
  'PIF_metrics',
  'SM',
  'SR',
  'VBD',
  'VBD_metrics',
  'VDI',
  'VGPU',
  'VGPU_type',
  'VLAN',
  'VM',
  'VM_appliance',
  'VM_guest_metrics',
  'VM_metrics',
  'VMPP',
  'VTPM'
], namespace => {
  TYPE_TO_NAMESPACE[namespace.toLowerCase()] = namespace
})

// Object types given by `xen-api` are always lowercase but the
// namespaces in the Xen API can have a different casing.
export const getNamespaceForType = type => TYPE_TO_NAMESPACE[type] || type

// -------------------------------------------------------------------

// Format a date (pseudo ISO 8601) from one XenServer get by
// xapi.call('host.get_servertime', host.$ref) for example
export const formatDateTime = utcFormat('%Y%m%dT%H:%M:%SZ')

export const parseDateTime = utcParse('%Y%m%dT%H:%M:%SZ')

// -------------------------------------------------------------------

export const isHostRunning = host => {
  const { $metrics } = host

  return $metrics && $metrics.live
}

// -------------------------------------------------------------------

export const isVmHvm = vm => Boolean(vm.HVM_boot_policy)

const VM_RUNNING_POWER_STATES = {
  Running: true,
  Paused: true
}
export const isVmRunning = vm => VM_RUNNING_POWER_STATES[vm.power_state]

// -------------------------------------------------------------------

const _DEFAULT_ADD_TO_LIMITS = (next, current) => next - current

const _mapFilter = (collection, iteratee) => {
  const result = []
  forEach(collection, (...args) => {
    const value = iteratee(...args)
    if (value) {
      result.push(value)
    }
  })
  return result
}

export const makeEditObject = specs => {
  const normalizeGet = (get, name) => {
    if (get === true) {
      const prop = camelToSnakeCase(name)
      return object => object[prop]
    }

    if (isString(get)) {
      return object => object[get]
    }

    return get
  }
  const normalizeSet = (set, name) => {
    if (isFunction(set)) {
      return set
    }

    if (set === true) {
      const prop = camelToSnakeCase(name)
      return function (value) {
        return this._set(prop, value)
      }
    }

    if (isString(set)) {
      const index = set.indexOf('.')
      if (index === -1) {
        return function (value) {
          return this._set(set, value)
        }
      }

      const map = set.slice(0, index)
      const prop = set.slice(index + 1)

      return function (value, object) {
        return this._updateObjectMapProperty(object, map, { [prop]: value })
      }
    }

    if (!isArray(set)) {
      throw new Error('must be an array, a function or a string')
    }

    set = mapToArray(set, normalizeSet)

    const { length } = set
    if (!length) {
      throw new Error('invalid setter')
    }

    if (length === 1) {
      return set[0]
    }

    return function (value, object) {
      return Promise.all(mapToArray(set, set => set.call(this, value, object)))
    }
  }

  const normalizeSpec = (spec, name) => {
    if (isString(spec)) {
      return normalizeSpec(specs[spec], spec)
    }

    if (spec === true) {
      spec = {
        get: true,
        set: true
      }
    }

    if (spec.addToLimits === true) {
      spec.addToLimits = _DEFAULT_ADD_TO_LIMITS
    }

    forEach(spec.constraints, (constraint, constraintName) => {
      if (!isFunction(constraint)) {
        throw new Error('constraint must be a function')
      }

      const constraintSpec = specs[constraintName]
      if (!constraintSpec.get) {
        throw new Error('constraint values must have a get')
      }
    })

    const { get } = spec
    if (get) {
      spec.get = normalizeGet(get, name)
    } else if (spec.addToLimits) {
      throw new Error('addToLimits cannot be defined without get')
    }

    spec.set = normalizeSet(spec.set, name)

    return spec
  }
  forEach(specs, (spec, name) => {
    specs[name] = normalizeSpec(spec, name)
  })

  return async function _editObject_ (id, values, checkLimits) {
    const limits = checkLimits && {}
    const object = this.getObject(id)

    const _objectRef = object.$ref
    const _setMethodPrefix = `${getNamespaceForType(object.$type)}.set_`

    // Context used to execute functions.
    const context = {
      __proto__: this,
      _set: (prop, value) => this.call(_setMethodPrefix + prop, _objectRef, prepareXapiParam(value))
    }

    const set = (value, name) => {
      const spec = specs[name]
      if (!spec) {
        return
      }

      const { preprocess } = spec
      if (preprocess) {
        value = preprocess(value)
      }

      const { get } = spec
      if (get) {
        const current = get(object)
        if (isEqual(value, current)) {
          return
        }

        let addToLimits
        if (limits && (addToLimits = spec.addToLimits)) {
          limits[name] = addToLimits(value, current)
        }
      }

      const cb = () => spec.set.call(context, value, object)

      const { constraints } = spec
      if (constraints) {
        const cbs = []

        forEach(constraints, (constraint, constraintName) => {
          // This constraint value is already defined: bypass the constraint.
          if (values[constraintName] != null) {
            return
          }

          if (!constraint(specs[constraintName].get(object), value)) {
            const cb = set(value, constraintName)
            cbs.push(cb)
          }
        })

        if (cbs.length) {
          return () => Promise.all(mapToArray(cbs, cb => cb())).then(cb)
        }
      }

      return cb
    }

    const cbs = _mapFilter(values, set)

    if (checkLimits) {
      await checkLimits(limits, object)
    }

    return Promise.all(mapToArray(cbs, cb => cb())).then(noop)
  }
}
<commit_msg>feat(xapi/utils/makeEditObject): support camelCase and snake_case aliases<commit_after>// import isFinite from 'lodash/isFinite'
import camelCase from 'lodash/camelCase'
import isEqual from 'lodash/isEqual'
import pickBy from 'lodash/pickBy'
import { utcFormat, utcParse } from 'd3-time-format'

import {
  camelToSnakeCase,
  createRawObject,
  forEach,
  isArray,
  isBoolean,
  isFunction,
  isInteger,
  isObject,
  isString,
  map,
  mapToArray,
  noop
} from '../utils'

// ===================================================================

export const asBoolean = value => Boolean(value)

// const asFloat = value => {
//   value = String(value)
//   return value.indexOf('.') === -1
//     ? `${value}.0`
//     : value
// }

export const asInteger = value => String(value)

export const filterUndefineds = obj => pickBy(obj, value => value !== undefined)

export const optional = (value, fn) => value == null
  ? undefined
  : fn ? fn(value) : value

export const prepareXapiParam = param => {
  // if (isFinite(param) && !isInteger(param)) {
  //   return asFloat(param)
  // }
  if (isInteger(param)) {
    return asInteger(param)
  }
  if (isBoolean(param)) {
    return asBoolean(param)
  }
  if (isObject(param)) {
    return map(filterUndefineds(param), prepareXapiParam)
  }

  return param
}

// -------------------------------------------------------------------

const OPAQUE_REF_RE = /OpaqueRef:[0-9a-z-]+/
export const extractOpaqueRef = str => {
  const matches = OPAQUE_REF_RE.exec(str)
  if (!matches) {
    throw new Error('no opaque ref found')
  }
  return matches[0]
}

// -------------------------------------------------------------------

const TYPE_TO_NAMESPACE = createRawObject()
forEach([
  'Bond',
  'DR_task',
  'GPU_group',
  'PBD',
  'PCI',
  'PGPU',
  'PIF',
  'PIF_metrics',
  'SM',
  'SR',
  'VBD',
  'VBD_metrics',
  'VDI',
  'VGPU',
  'VGPU_type',
  'VLAN',
  'VM',
  'VM_appliance',
  'VM_guest_metrics',
  'VM_metrics',
  'VMPP',
  'VTPM'
], namespace => {
  TYPE_TO_NAMESPACE[namespace.toLowerCase()] = namespace
})

// Object types given by `xen-api` are always lowercase but the
// namespaces in the Xen API can have a different casing.
export const getNamespaceForType = type => TYPE_TO_NAMESPACE[type] || type

// -------------------------------------------------------------------

// Format a date (pseudo ISO 8601) from one XenServer get by
// xapi.call('host.get_servertime', host.$ref) for example
export const formatDateTime = utcFormat('%Y%m%dT%H:%M:%SZ')

export const parseDateTime = utcParse('%Y%m%dT%H:%M:%SZ')

// -------------------------------------------------------------------

export const isHostRunning = host => {
  const { $metrics } = host

  return $metrics && $metrics.live
}

// -------------------------------------------------------------------

export const isVmHvm = vm => Boolean(vm.HVM_boot_policy)

const VM_RUNNING_POWER_STATES = {
  Running: true,
  Paused: true
}
export const isVmRunning = vm => VM_RUNNING_POWER_STATES[vm.power_state]

// -------------------------------------------------------------------

const _DEFAULT_ADD_TO_LIMITS = (next, current) => next - current

const _mapFilter = (collection, iteratee) => {
  const result = []
  forEach(collection, (...args) => {
    const value = iteratee(...args)
    if (value) {
      result.push(value)
    }
  })
  return result
}

export const makeEditObject = specs => {
  const normalizeGet = (get, name) => {
    if (get === true) {
      const prop = camelToSnakeCase(name)
      return object => object[prop]
    }

    if (isString(get)) {
      return object => object[get]
    }

    return get
  }
  const normalizeSet = (set, name) => {
    if (isFunction(set)) {
      return set
    }

    if (set === true) {
      const prop = camelToSnakeCase(name)
      return function (value) {
        return this._set(prop, value)
      }
    }

    if (isString(set)) {
      const index = set.indexOf('.')
      if (index === -1) {
        return function (value) {
          return this._set(set, value)
        }
      }

      const map = set.slice(0, index)
      const prop = set.slice(index + 1)

      return function (value, object) {
        return this._updateObjectMapProperty(object, map, { [prop]: value })
      }
    }

    if (!isArray(set)) {
      throw new Error('must be an array, a function or a string')
    }

    set = mapToArray(set, normalizeSet)

    const { length } = set
    if (!length) {
      throw new Error('invalid setter')
    }

    if (length === 1) {
      return set[0]
    }

    return function (value, object) {
      return Promise.all(mapToArray(set, set => set.call(this, value, object)))
    }
  }

  const normalizeSpec = (spec, name) => {
    if (spec === true) {
      spec = {
        get: true,
        set: true
      }
    }

    if (spec.addToLimits === true) {
      spec.addToLimits = _DEFAULT_ADD_TO_LIMITS
    }

    forEach(spec.constraints, (constraint, constraintName) => {
      if (!isFunction(constraint)) {
        throw new Error('constraint must be a function')
      }

      const constraintSpec = specs[constraintName]
      if (!constraintSpec.get) {
        throw new Error('constraint values must have a get')
      }
    })

    const { get } = spec
    if (get) {
      spec.get = normalizeGet(get, name)
    } else if (spec.addToLimits) {
      throw new Error('addToLimits cannot be defined without get')
    }

    spec.set = normalizeSet(spec.set, name)

    return spec
  }
  forEach(specs, (spec, name) => {
    isString(spec) || (specs[name] = normalizeSpec(spec, name))
  })

  // Resolves aliases and add camelCase and snake_case aliases.
  forEach(specs, (spec, name) => {
    if (isString(spec)) {
      do {
        spec = specs[spec]
      } while (isString(spec))
      specs[name] = spec
    }

    let tmp
    specs[tmp = camelCase(name)] || (specs[tmp] = spec)
    specs[tmp = camelToSnakeCase(name)] || (specs[tmp] = spec)
  })

  return async function _editObject_ (id, values, checkLimits) {
    const limits = checkLimits && {}
    const object = this.getObject(id)

    const _objectRef = object.$ref
    const _setMethodPrefix = `${getNamespaceForType(object.$type)}.set_`

    // Context used to execute functions.
    const context = {
      __proto__: this,
      _set: (prop, value) => this.call(_setMethodPrefix + prop, _objectRef, prepareXapiParam(value))
    }

    const set = (value, name) => {
      const spec = specs[name]
      if (!spec) {
        return
      }

      const { preprocess } = spec
      if (preprocess) {
        value = preprocess(value)
      }

      const { get } = spec
      if (get) {
        const current = get(object)
        if (isEqual(value, current)) {
          return
        }

        let addToLimits
        if (limits && (addToLimits = spec.addToLimits)) {
          limits[name] = addToLimits(value, current)
        }
      }

      const cb = () => spec.set.call(context, value, object)

      const { constraints } = spec
      if (constraints) {
        const cbs = []

        forEach(constraints, (constraint, constraintName) => {
          // This constraint value is already defined: bypass the constraint.
          if (values[constraintName] != null) {
            return
          }

          if (!constraint(specs[constraintName].get(object), value)) {
            const cb = set(value, constraintName)
            cbs.push(cb)
          }
        })

        if (cbs.length) {
          return () => Promise.all(mapToArray(cbs, cb => cb())).then(cb)
        }
      }

      return cb
    }

    const cbs = _mapFilter(values, set)

    if (checkLimits) {
      await checkLimits(limits, object)
    }

    return Promise.all(mapToArray(cbs, cb => cb())).then(noop)
  }
}
<|endoftext|>


<commit_before>// ViewState stores a State and some additional information used for a StateView specifically.
// These states are used internally by a StateView.
function ViewState(positive, normative, attrs) {
  this.positive = new PositiveState(positive);
  this.normative = new NormativeState(normative);

  this.viewFrozen = defaultValue(attrs.viewFrozen, false);

  this.yLabels = defaultValue(attrs.yLabels, null);

  this.chunkView = defaultValue(attrs.chunkView, null);
  this.chunkViewStartIndex = defaultValue(attrs.chunkViewStartIndex, -1);
  this.chunkViewLength = defaultValue(attrs.chunkViewLength, -1);

  this.showingContent = defaultValue(attrs.showingContent, false);
  this.animate = defaultValue(attrs.animate, false);

  this.animating = defaultValue(attrs.animating, false);
  this.animationChunkView = defaultValue(attrs.animationChunkView, null);
  this.animationProgress = defaultValue(attrs.animationProgress, -1);
  this.startLeftmostLabelWidth = defaultValue(attrs.startLeftmostLabelWidth, -1);
  this.startYLabels = defaultValue(attrs.startYLabels, null);

  this.liveLeftmostLabelWidth = defaultValue(attrs.liveLeftmostLabelWidth, -1);
  this.liveContentWidth = defaultValue(attrs.liveContentWidth, -1);
}

// copy generates a quasi-deep copy of this state.
// Every y-label and ChunkView is shallow copied, but everything else is deeply copied.
ViewState.prototype.copy = function() {
  return new ViewState(this.positive, this.normative, this);
};

// State stores both a PositiveState and NormativeState.
function State(positive, normative) {
  this.positive = positive;
  this.normative = normative;
}

// copy generates a deep copy of the state.
State.prototype.copy = function() {
  return new State(new PositiveState(this.positive), new NormativeState(this.normative));
};

// PositiveState stores information about the current visual state of a ContentView.
function PositiveState(attrs) {
  this.dataSourceLength = defaultValue(attrs.dataSourceLength, 0);

  this.visibleChunkStart = defaultValue(attrs.visibleChunkStart, -1);
  this.visibleChunkLength = defaultValue(attrs.visibleChunkLength, -1);

  this.leftmostChunkLength = defaultValue(attrs.leftmostChunkLength, -1);
  this.leftmostYLabelsWidth = defaultValue(attrs.leftmostYLabelsWidth, -1);
  this.leftmostYLabelsPointCount = defaultValue(attrs.leftmostYLabelsPointCount, -1);

  this.contentWidth = defaultValue(attrs.contentWidth, 0);
  this.viewportX = defaultValue(attrs.viewportX, 0);
  this.viewportWidth = defaultValue(attrs.viewportWidth, 0);
  this.viewportHeight = defaultValue(attrs.viewportHeight, 0);
  this.barShowingHeight = defaultValue(attrs.barShowingHeight, 0);
}

// NormativeState stores information about what will or ought to change about the current visual
// state of a content view.
function NormativeState(attrs) {
  this.needsLeftmostChunk = defaultValue(attrs.needsLeftmostChunk, false);
  this.loadingLeftmostChunk = defaultValue(attrs.loadingLeftmostChunk, false);
  this.leftmostChunkLength = defaultValue(attrs.leftmostChunkLength, 0);

  this.needsVisibleChunk = defaultValue(attrs.needsVisibleChunk, false);
  this.loadingVisibleChunk = defaultValue(attrs.loadingVisibleChunk, false);
  this.visibleChunkStart = defaultValue(attrs.visibleChunkStart, 0);
  this.visibleChunkLength = defaultValue(attrs.visibleChunkLength, 0);
}

NormativeState.LEFTMOST_START_BUFFER = 1000;
NormativeState.LEFTMOST_MIN_BUFFER = 0;
NormativeState.VISIBLE_START_BUFFER = 2000;
NormativeState.VISIBLE_MIN_BUFFER = 1000;

// recompute uses a ViewProvider and a PositiveState to update this normative state's fields based
// on what data should be loaded.
NormativeState.prototype.recompute = function(provider, positiveState) {
  this._recomputeLeftmost(provider, positiveState);
  this._recomputeVisible(provider, positiveState);
};

NormativeState.prototype._recomputeLeftmost = function(provider, positiveState) {
  var minWidth = positiveState.viewportWidth + NormativeState.LEFTMOST_MIN_BUFFER;
  var minLength = provider.computeTheoreticalChunk({width: minWidth, left: 0},
    positiveState.dataSourceLength).length;

  if (positiveState.leftmostChunkLength >= minLength) {
    this.needsLeftmostChunk = false;
    this.loadingLeftmostChunk = false;
  } else if (!this.needsLeftmostChunk || this.leftmostChunkLength < minLength) {
    this.loadingLeftmostChunk = true;
    this.needsLeftmostChunk = true;

    var theoreticalChunk = {
      left: 0,
      width: positiveState.viewportWidth + NormativeState.LEFTMOST_START_BUFFER
    };
    this.leftmostChunkLength = provider.computeTheoreticalChunk(theoreticalChunk,
      positiveState.dataSourceLength).length;
  }
};

NormativeState.prototype._recomputeVisible = function(provider, positiveState) {
  var viewportX;
  if (positiveState.visibleChunkLength < 0) {
    viewportX = positiveState.contentWidth + positiveState.leftmostYLabelsWidth -
      positiveState.viewportWidth;
  } else {
    viewportX = positiveState.viewportX;
  }
  var minRegion = {
    left: viewportX - positiveState.leftmostYLabelsWidth - NormativeState.VISIBLE_MIN_BUFFER,
    width: NormativeState.VISIBLE_MIN_BUFFER*2 + positiveState.viewportWidth
  };
  var minChunk = provider.computeTheoreticalChunk(minRegion, positiveState.dataSourceLength);

  var visibleChunkEnd = positiveState.visibleChunkStart + positiveState.visibleChunkLength;
  if (positiveState.visibleChunkStart <= minChunk.start &&
      visibleChunkEnd >= minChunk.start+minChunk.length) {
    this.needsVisibleChunk = false;
    this.loadingVisibleChunk = false;
    return;
  }

  if (this.needsVisibleChunk) {
    var gettingChunkEnd = this.visibleChunkStart + this.visibleChunkLength;
    if (this.visibleChunkStart <= minChunk.start &&
        gettingChunkEnd >= minChunk.start+minChunk.length) {
      return;
    }
  }

  var needRegion = {
    left: viewportX - positiveState.leftmostYLabelsWidth - NormativeState.VISIBLE_START_BUFFER,
    width: NormativeState.VISIBLE_START_BUFFER*2 + positiveState.viewportWidth
  };

  // NOTE: we do this to ensure that we use up as much buffer space as possible even if the user is
  // scrolled all the way to the left or to the right.
  if (needRegion.left+needRegion.width > positiveState.contentWidth) {
    needRegion.left -= needRegion.left + needRegion.width - positiveState.contentWidth;
  } else if (needRegion.left < 0) {
    needRegion.left = 0;
  }

  var needChunk = provider.computeTheoreticalChunk(needRegion, positiveState.dataSourceLength);

  this.needsVisibleChunk = true;
  this.loadingVisibleChunk = true;
  this.visibleChunkStart = needChunk.startIndex;
  this.visibleChunkLength = needChunk.length;
};

function defaultValue(value, d) {
  return ('undefined' === typeof value ? d : value);
}
<commit_msg>fixed startIndex bug recomputing NormativeState<commit_after>// ViewState stores a State and some additional information used for a StateView specifically.
// These states are used internally by a StateView.
function ViewState(positive, normative, attrs) {
  this.positive = new PositiveState(positive);
  this.normative = new NormativeState(normative);

  this.viewFrozen = defaultValue(attrs.viewFrozen, false);

  this.yLabels = defaultValue(attrs.yLabels, null);

  this.chunkView = defaultValue(attrs.chunkView, null);
  this.chunkViewStartIndex = defaultValue(attrs.chunkViewStartIndex, -1);
  this.chunkViewLength = defaultValue(attrs.chunkViewLength, -1);

  this.showingContent = defaultValue(attrs.showingContent, false);
  this.animate = defaultValue(attrs.animate, false);

  this.animating = defaultValue(attrs.animating, false);
  this.animationChunkView = defaultValue(attrs.animationChunkView, null);
  this.animationProgress = defaultValue(attrs.animationProgress, -1);
  this.startLeftmostLabelWidth = defaultValue(attrs.startLeftmostLabelWidth, -1);
  this.startYLabels = defaultValue(attrs.startYLabels, null);

  this.liveLeftmostLabelWidth = defaultValue(attrs.liveLeftmostLabelWidth, -1);
  this.liveContentWidth = defaultValue(attrs.liveContentWidth, -1);
}

// copy generates a quasi-deep copy of this state.
// Every y-label and ChunkView is shallow copied, but everything else is deeply copied.
ViewState.prototype.copy = function() {
  return new ViewState(this.positive, this.normative, this);
};

// State stores both a PositiveState and NormativeState.
function State(positive, normative) {
  this.positive = positive;
  this.normative = normative;
}

// copy generates a deep copy of the state.
State.prototype.copy = function() {
  return new State(new PositiveState(this.positive), new NormativeState(this.normative));
};

// PositiveState stores information about the current visual state of a ContentView.
function PositiveState(attrs) {
  this.dataSourceLength = defaultValue(attrs.dataSourceLength, 0);

  this.visibleChunkStart = defaultValue(attrs.visibleChunkStart, -1);
  this.visibleChunkLength = defaultValue(attrs.visibleChunkLength, -1);

  this.leftmostChunkLength = defaultValue(attrs.leftmostChunkLength, -1);
  this.leftmostYLabelsWidth = defaultValue(attrs.leftmostYLabelsWidth, -1);
  this.leftmostYLabelsPointCount = defaultValue(attrs.leftmostYLabelsPointCount, -1);

  this.contentWidth = defaultValue(attrs.contentWidth, 0);
  this.viewportX = defaultValue(attrs.viewportX, 0);
  this.viewportWidth = defaultValue(attrs.viewportWidth, 0);
  this.viewportHeight = defaultValue(attrs.viewportHeight, 0);
  this.barShowingHeight = defaultValue(attrs.barShowingHeight, 0);
}

// NormativeState stores information about what will or ought to change about the current visual
// state of a content view.
function NormativeState(attrs) {
  this.needsLeftmostChunk = defaultValue(attrs.needsLeftmostChunk, false);
  this.loadingLeftmostChunk = defaultValue(attrs.loadingLeftmostChunk, false);
  this.leftmostChunkLength = defaultValue(attrs.leftmostChunkLength, 0);

  this.needsVisibleChunk = defaultValue(attrs.needsVisibleChunk, false);
  this.loadingVisibleChunk = defaultValue(attrs.loadingVisibleChunk, false);
  this.visibleChunkStart = defaultValue(attrs.visibleChunkStart, 0);
  this.visibleChunkLength = defaultValue(attrs.visibleChunkLength, 0);
}

NormativeState.LEFTMOST_START_BUFFER = 1000;
NormativeState.LEFTMOST_MIN_BUFFER = 0;
NormativeState.VISIBLE_START_BUFFER = 2000;
NormativeState.VISIBLE_MIN_BUFFER = 1000;

// recompute uses a ViewProvider and a PositiveState to update this normative state's fields based
// on what data should be loaded.
NormativeState.prototype.recompute = function(provider, positiveState) {
  this._recomputeLeftmost(provider, positiveState);
  this._recomputeVisible(provider, positiveState);
};

NormativeState.prototype._recomputeLeftmost = function(provider, positiveState) {
  var minWidth = positiveState.viewportWidth + NormativeState.LEFTMOST_MIN_BUFFER;
  var minLength = provider.computeTheoreticalChunk({width: minWidth, left: 0},
    positiveState.dataSourceLength).length;

  if (positiveState.leftmostChunkLength >= minLength) {
    this.needsLeftmostChunk = false;
    this.loadingLeftmostChunk = false;
  } else if (!this.needsLeftmostChunk || this.leftmostChunkLength < minLength) {
    this.loadingLeftmostChunk = true;
    this.needsLeftmostChunk = true;

    var theoreticalChunk = {
      left: 0,
      width: positiveState.viewportWidth + NormativeState.LEFTMOST_START_BUFFER
    };
    this.leftmostChunkLength = provider.computeTheoreticalChunk(theoreticalChunk,
      positiveState.dataSourceLength).length;
  }
};

NormativeState.prototype._recomputeVisible = function(provider, positiveState) {
  var viewportX;
  if (positiveState.visibleChunkLength < 0) {
    viewportX = positiveState.contentWidth + positiveState.leftmostYLabelsWidth -
      positiveState.viewportWidth;
  } else {
    viewportX = positiveState.viewportX;
  }
  var minRegion = {
    left: viewportX - positiveState.leftmostYLabelsWidth - NormativeState.VISIBLE_MIN_BUFFER,
    width: NormativeState.VISIBLE_MIN_BUFFER*2 + positiveState.viewportWidth
  };
  var minChunk = provider.computeTheoreticalChunk(minRegion, positiveState.dataSourceLength);

  var visibleChunkEnd = positiveState.visibleChunkStart + positiveState.visibleChunkLength;
  if (positiveState.visibleChunkStart <= minChunk.startIndex &&
      visibleChunkEnd >= minChunk.startIndex+minChunk.length) {
    this.needsVisibleChunk = false;
    this.loadingVisibleChunk = false;
    return;
  }

  if (this.needsVisibleChunk) {
    var gettingChunkEnd = this.visibleChunkStart + this.visibleChunkLength;
    if (this.visibleChunkStart <= minChunk.startIndex &&
        gettingChunkEnd >= minChunk.startIndex+minChunk.length) {
      return;
    }
  }

  var needRegion = {
    left: viewportX - positiveState.leftmostYLabelsWidth - NormativeState.VISIBLE_START_BUFFER,
    width: NormativeState.VISIBLE_START_BUFFER*2 + positiveState.viewportWidth
  };

  // NOTE: we do this to ensure that we use up as much buffer space as possible even if the user is
  // scrolled all the way to the left or to the right.
  if (needRegion.left+needRegion.width > positiveState.contentWidth) {
    needRegion.left -= needRegion.left + needRegion.width - positiveState.contentWidth;
  } else if (needRegion.left < 0) {
    needRegion.left = 0;
  }

  var needChunk = provider.computeTheoreticalChunk(needRegion, positiveState.dataSourceLength);

  this.needsVisibleChunk = true;
  this.loadingVisibleChunk = true;
  this.visibleChunkStart = needChunk.startIndex;
  this.visibleChunkLength = needChunk.length;
};

function defaultValue(value, d) {
  return ('undefined' === typeof value ? d : value);
}
<|endoftext|>


<commit_before>$('document').ready(function() {
	require(['composer', 'composer/controls'], function(composer, controls) {
		composer.addButton('fa fa-eye-slash', function(textarea, selectionStart, selectionEnd) {
			if(selectionStart === selectionEnd){
				controls.insertIntoTextarea(textarea, "```"
				"Insert Code Here"
				"```");
				controls.updateTextareaSelection(textarea, selectionStart + 3, selectionStart + 26);
			} else {
				controls.wrapSelectionInTextareaWith(textarea, '```', '```');
				controls.updateTextareaSelection(textarea, selectionStart + 3, selectionEnd + 3);
			}
		});
	});
});
<commit_msg>Update buttons.js<commit_after>$('document').ready(function() {
	require(['composer', 'composer/controls'], function(composer, controls) {
		composer.addButton('fa fa-eye-slash', function(textarea, selectionStart, selectionEnd) {
			if(selectionStart === selectionEnd){
				controls.insertIntoTextarea(textarea, '```',
				'',
				'```');
				controls.updateTextareaSelection(textarea, selectionStart + 3, selectionStart + 26);
			} else {
				controls.wrapSelectionInTextareaWith(textarea, '```', '```');
				controls.updateTextareaSelection(textarea, selectionStart + 3, selectionEnd + 3);
			}
		});
	});
});
<|endoftext|>