<commit_before>const test = require('tape');
const tapDifflet = require('tap-difflet');
const requireText = require('require-text');
// const hasha = require('hasha');

const assembleIndex = require('../src/assemble/index');
const assembleApp = require('../src/assemble/app');
const assembleAppState = require('../src/assemble/appState');
const assembleAppSpec = require('../src/assemble/appSpec');
const assembleDependencies = require('../src/assemble/dependencies');
const assembleDevDependencies = require('../src/assemble/devDependencies');
const assembleNpmScripts = require('../src/assemble/npmScripts');

test.createStream().pipe(tapDifflet()).pipe(process.stdout);

const devReduxArgs = { flow: true, lint: true, test: true, redux: true };
const devReduxStyledArgs = Object.assign({}, devReduxArgs, { styled: true });
const devReduxSassArgs = Object.assign({}, devReduxArgs, { sass: true });

const assembleTest = (msg, func, file, args) => {
  let hash1 = '-';
  let hash2 = '+';
  Promise.all([
    (() => {
      hash1 = func(args).trim();
    })(),
    (() => {
      hash2 = requireText('./templates/' + file, require).trim();
      if (file.split('.').pop() === 'txt') {
        hash2 = hash2.replace(/\s+/g, ' ')
      }
    })()
  ]).then(() => {
    test(msg, (t) => { t.plan(1); t.equal(hash1, hash2); });
  }, err => console.log(err));
};

assembleTest('[dev, redux] === index template',
  assembleIndex, 'index.js', devReduxArgs
);

assembleTest('[dev, redux, styled] === App.styled template',
  assembleApp, 'app.styled.js', devReduxStyledArgs
);

assembleTest('[dev, redux, sass] === App.sass template',
  assembleApp, 'app.sass.js', devReduxSassArgs
);

assembleTest('[dev, redux] === spec template',
  assembleAppSpec, 'spec.js', devReduxArgs
);

assembleTest('[dev, redux] === state template',
  assembleAppState, 'state.js', devReduxArgs
);

assembleTest('[dev, redux, styled] === dependencies.styled template',
  args => assembleDependencies(args), 'dependencies.styled.txt', devReduxStyledArgs
);

assembleTest('[dev, redux, styled] === devDependencies.styled template',
  args => assembleDevDependencies(args), 'devDependencies.styled.txt', devReduxStyledArgs
);

assembleTest('[dev, redux, sass] === devDependencies.sass template',
  args => assembleDevDependencies(args), 'devDependencies.sass.txt', devReduxSassArgs
);

assembleTest('[dev, redux] === npmScripts template',
  assembleNpmScripts, 'npmScripts.json', devReduxArgs
);
<commit_msg>some cleanup<commit_after>const test = require('tape');
const tapDifflet = require('tap-difflet');
const requireText = require('require-text');
// const hasha = require('hasha');

const assembleIndex = require('../src/assemble/index');
const assembleApp = require('../src/assemble/app');
const assembleAppState = require('../src/assemble/appState');
const assembleAppSpec = require('../src/assemble/appSpec');
const assembleDependencies = require('../src/assemble/dependencies');
const assembleDevDependencies = require('../src/assemble/devDependencies');
const assembleNpmScripts = require('../src/assemble/npmScripts');

test.createStream().pipe(tapDifflet()).pipe(process.stdout);

const devReduxArgs = { flow: true, lint: true, test: true, redux: true };
const devReduxStyledArgs = Object.assign({}, devReduxArgs, { styled: true });
const devReduxSassArgs = Object.assign({}, devReduxArgs, { sass: true });

const assembleTest = (msg, func, file, args) => {
  let actual = '-';
  let expected = '+';
  Promise.all([
    (() => {
      actual = func(args).trim();
    })(),
    (() => {
      expected = requireText('./templates/' + file, require).trim();
      if (file.split('.').pop() === 'txt') {
        expected = expected.replace(/\s+/g, ' ')
      }
    })()
  ]).then(() => {
    test(msg, (t) => { t.plan(1); t.equal(actual, expected); });
  }, err => console.log(err));
};

assembleTest('[dev, redux] === index template',
  assembleIndex, 'index.js', devReduxArgs
);

assembleTest('[dev, redux, styled] === App.styled template',
  assembleApp, 'app.styled.js', devReduxStyledArgs
);

assembleTest('[dev, redux, sass] === App.sass template',
  assembleApp, 'app.sass.js', devReduxSassArgs
);

assembleTest('[dev, redux] === spec template',
  assembleAppSpec, 'spec.js', devReduxArgs
);

assembleTest('[dev, redux] === state template',
  assembleAppState, 'state.js', devReduxArgs
);

assembleTest('[dev, redux, styled] === dependencies.styled template',
  args => assembleDependencies(args), 'dependencies.styled.txt', devReduxStyledArgs
);

assembleTest('[dev, redux, styled] === devDependencies.styled template',
  args => assembleDevDependencies(args), 'devDependencies.styled.txt', devReduxStyledArgs
);

assembleTest('[dev, redux, sass] === devDependencies.sass template',
  args => assembleDevDependencies(args), 'devDependencies.sass.txt', devReduxSassArgs
);

assembleTest('[dev, redux] === npmScripts template',
  assembleNpmScripts, 'npmScripts.json', devReduxArgs
);
<|endoftext|>


<commit_before>module.exports = function (grunt) {
  var globalConfig = {
    adminTool:'admin-tool',
    frontEnd:'front-end'
  };

  grunt.initConfig({
    globalConfig: globalConfig,

    copy: {
      frontEnd: {
        cwd: 'front-end/front-end',
        src: '**/*',
        dest: 'data',
        expand:true
      },
      adminTool: {
        cwd: 'admin-tool/admin-tool',
        src: '**/*',
        dest: 'data/admin',
        expand: true
      }
    },

    connect: {
      server: {
        options: {
          port: 8000,
          base: 'data',
          hostname: 'localhost',

          middleware: function (connect, options, defaultMiddleware) {
            var proxy = require('grunt-connect-proxy/lib/utils').proxyRequest;
            return [
              // Include the proxy first
              proxy
            ].concat(defaultMiddleware);
          }
        },
        proxies: [{
          context: '/API', // the context of the data service
          host: 'localhost', // wherever the data service is running
          port: 9000, // the port that the data service is running on
          changeOrigin: true
        }]
      }
    },
    watch: {
      frontEnd: {
        files: ['front-end/src/**/*'],
        tasks: ['grunt-frontEnd', 'copy:frontEnd']
      },
      adminTool: {
        files: ['admin-tool/src/**/*'],
        tasks: ['grunt-adminTool', 'copy:adminTool']
      }
    },
    clean: {
      app: ['data']
    }
  });

  grunt.registerTask('grunt-frontEnd', function () {
      var done = this.async();
      grunt.util.spawn(
        {
          grunt: true,
          args: ['default'],
          opts: {
              cwd: 'front-end'
          }
        },
        function (err, result, code) {
          done();
        }
      );
  });

  grunt.registerTask('grunt-adminTool', function () {
      var done = this.async();
      grunt.util.spawn(
        {
          grunt: true,
          args: ['default'],
          opts: {
              cwd: 'front-end'
          }
        },
        function (err, result, code) {
          done();
        }
      );
  });

  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-connect-proxy');
  grunt.loadNpmTasks('grunt-contrib-clean');

  grunt.registerTask('default', ['grunt-frontEnd', 'grunt-adminTool', 'copy', 'configureProxies:server', 'connect:server', 'watch']);
};
<commit_msg>grunt<commit_after>module.exports = function (grunt) {
  var globalConfig = {
    adminTool:'admin-tool',
    frontEnd:'front-end'
  };

  grunt.initConfig({
    globalConfig: globalConfig,

    copy: {
      frontEnd: {
        cwd: 'front-end/tmp',
        src: '**/*',
        dest: 'data',
        expand:true
      },
      adminTool: {
        cwd: 'admin-tool/admin-tool',
        src: '**/*',
        dest: 'data/admin',
        expand: true
      }
    },

    connect: {
      server: {
        options: {
          port: 8000,
          base: 'data',
          hostname: 'localhost',

          middleware: function (connect, options, defaultMiddleware) {
            var proxy = require('grunt-connect-proxy/lib/utils').proxyRequest;
            return [
              // Include the proxy first
              proxy
            ].concat(defaultMiddleware);
          }
        },
        proxies: [{
          context: '/API', // the context of the data service
          host: 'localhost', // wherever the data service is running
          port: 9000, // the port that the data service is running on
          changeOrigin: true
        }]
      }
    },
    watch: {
      frontEnd: {
        files: ['front-end/src/**/*'],
        tasks: ['grunt-frontEnd', 'copy:frontEnd']
      },
      adminTool: {
        files: ['admin-tool/src/**/*'],
        tasks: ['grunt-adminTool', 'copy:adminTool']
      }
    },
    clean: {
      app: ['data']
    }
  });

  grunt.registerTask('grunt-frontEnd', function () {
      var done = this.async();
      grunt.util.spawn(
        {
          grunt: true,
          args: ['default'],
          opts: {
              cwd: 'front-end'
          }
        },
        function (err, result, code) {
          done();
        }
      );
  });

  grunt.registerTask('grunt-adminTool', function () {
      var done = this.async();
      grunt.util.spawn(
        {
          grunt: true,
          args: ['default'],
          opts: {
              cwd: 'front-end'
          }
        },
        function (err, result, code) {
          done();
        }
      );
  });

  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-connect-proxy');
  grunt.loadNpmTasks('grunt-contrib-clean');

  grunt.registerTask('default', ['grunt-frontEnd', 'grunt-adminTool', 'copy', 'configureProxies:server', 'connect:server', 'watch']);
};
<|endoftext|>


<commit_before>(function($) {
  "use strict";
  var compareFunction = function(a, b) {
    return a - b;
  };
  var inittree = function(binheap) {
    var size = binheap.size(),
      bt = binheap._tree,
      nodes = [];
    var donode = function(node, pos) {
      if (pos === 1) {
        node.value(binheap.value(pos - 1));
      }
      node.element.attr("data-jsav-heap-index", pos);
      nodes[pos - 1] = node;
      var lpos = pos * 2,
          rpos = lpos + 1;
      if (lpos <= size) {
        if (!node.left()) {
          node.left(binheap.value(lpos - 1));
        } else {
          node.left().value(binheap.value(lpos - 1));
        }
        donode(node.left(), lpos);
      }
      if (rpos <= size) {
        if (!node.right()) {
          node.right(binheap.value(rpos - 1));
        } else {
          node.right().value(binheap.value(rpos - 1));
        }
        donode(node.right(), rpos);
      }
    };
    binheap._treenodes = nodes;
    donode(bt.root(), 1);
  };

  var BinaryHeap = function(jsav, element, options) {
    this.jsav = jsav;
    this.options = $.extend({indexed: true, layout: "array"}, options);
    if (!this.options.template) {
      var tmplName = this.options.layout + (this.options.indexed?"-indexed":"");
      this.options.template = JSAV._types.ds.AVArray._templates[tmplName];
    }
    this._indices = [];
    if ($.isArray(element)) {
      var arrsize = element.length;
      if ('size' in options) {
        element.length = options.size;
      }
      this.initialize(element);
      this.element.attr("data-jsav-heap-size", arrsize);
    } else {
      if (element) { // assume it's a DOM element
        this.element = $(element);
      } else {
        this.element = $("<ol/>");
        $(this.jsav.container).append(this.element).addClass("jsavbinaryheap");
      }
      var size = 0;
      $.each(this.element.find("li"), function(index) {
        if (this.value(index) !== "") {
          size++;
        }
      });
      this.element.attr("data-jsav-heap-size", size.length);

      this.initializeFromElement();
    }
    var oldfx = $.fx.off || false;
    $.fx.off = true;

    if (options.stats) {
      this.stats = {"swaps": 0, "leftswaps": 0, "rightswaps": 0,
                    "recursiveswaps": 0, "partlyrecursiveswaps": 0};
    }

    if (options.tree) {
      this._tree = jsav.ds.bintree(options);
      inittree(this);
      this._tree.layout();
    }
    if (options.heapify) {
      for (var i = Math.floor(this.heapsize()/2); i > 0; i--) {
        this.heapify(i);
      }
    }
     if (this.options.center) {
      this.element.addClass("jsavcenter");
    }
   $.fx.off = oldfx;
  };
  JSAV.utils.extend(BinaryHeap, JSAV._types.ds.AVArray);
  var bhproto = BinaryHeap.prototype;
  //$.extend(bhproto, JSAV._types.ds.AVArray.prototype);
  bhproto.arrayswap = bhproto.swap;
  bhproto.arraycss = bhproto.css;
  bhproto.arrayclear = bhproto.clear;
  bhproto.arrayvalue = bhproto.value;

  bhproto.value = function(index, newValue) {
    if (typeof newValue === "undefined") {
      return this.arrayvalue(index);
    }
    this.arrayvalue(index, newValue);
    if (index >= this.heapsize()) {
      this.element.attr("data-jsav-heap-size", index + 1);
    }
    if (this.options.tree) {
      this._treenodes[index].value(newValue);
    }
  };

  bhproto.clear = function() {
    this.arrayclear();
    if (this.options.tree) {
      this._tree.clear();
    }
  };

  // create versions of some array functions that will also change
  // the treenodes
  var funcs = ["css", "highlight", "unhighlight"];
  var getDelegateFunction = function(name) {
    // return a "delegate" function bound to the array function with given name
    return function() {
      var node;
      // first call the stored original array function
      var val = this["_array" + name].apply(this, arguments);
      // then the treenode functions, based on the type of the index
      // argument (first argument)
      if (this.options.tree && typeof arguments[0] === "number") {
        node = this._treenodes[arguments[0]];
        node[name].apply(node, [].slice.call(arguments, 1));
      } else if (this.options.tree && $.isArray(arguments[0])) {
        for (var i = arguments[0].length; i--; ) {
          node = this._treenodes[arguments[0][i]];
          node[name].apply(node, [].slice.call(arguments, 1))
        }
      }
      // finally return the value of the array function
      return val;
    }
  };
  // go through the function names, store the array functions, and create
  // delegate functions to the heap prototype
  for (var i = funcs.length; i--; ) {
    bhproto["_array" + funcs[i]] = bhproto[funcs[i]];
    bhproto[funcs[i]] = getDelegateFunction(funcs[i]);
  }

  bhproto._setsize = JSAV.anim(function(newsize) {
    var oldsize = this.element.attr("data-jsav-heap-size");
    this.element.attr("data-jsav-heap-size", newsize);
    return [oldsize];
  });
  bhproto.heapsize = function(newsize) {
    if (typeof newsize !== "undefined") {
      return this._setsize(newsize);
    } else {
      return parseInt(this.element.attr("data-jsav-heap-size"), 10);
    }
  };

  bhproto.heapify = function(pos, options) {
    var size = this.heapsize(),
      lpos = pos * 2,
      rpos = pos * 2 + 1,
      smallest = pos,
      comp = this.options.compare,
      step = this.options.steps ? this.jsav.step : function() {};
    if (lpos <= size && comp(this.value(lpos - 1), this.value(pos - 1)) < 0) {
      smallest = lpos;
    }
    if (rpos <= size && comp(this.value(rpos - 1), this.value(smallest - 1)) < 0) {
      smallest = rpos;
    }
    if (smallest !== pos) {
      if (this.options.stats) {
        this.stats.swaps++;
        if (smallest === lpos) { this.stats.leftswaps++; }
        else { this.stats.rightswaps++; }
      }
      if (options && options.noAnimation) {
        var tmp = this.value(pos - 1);
        this.value(pos - 1, this.value(smallest - 1));
        this.value(smallest - 1, tmp);
      } else {
        this.swap(smallest - 1, pos - 1);
      }
      step.apply(this.jsav);
      if (this.heapify(smallest, options) && this.options.stats) {
        this.stats.recursiveswaps++;
      } else if (this.options.stats) {
        this.stats.partlyrecursiveswaps++;
      }
      return true;
    } else if (this.options.stats) {
      this.stats.interrupted = true;
    }
    return false;
  };
  bhproto.swap = function(index1, index2, options) {
    this.arrayswap(index1, index2, options);
    if (this.options.tree) {
      // swap the values in the tree
      this.jsav.effects.swapValues(this._treenodes[index1],
                                   this._treenodes[index2]);
    }
  };
  bhproto.insert = function(val) {
    var i = this.heapsize() + 1,
      parent = Math.floor(i / 2),
      comp = this.options.compare,
      step = this.options.steps ? this.jsav.step : function() {};
    this.value(i - 1, val);
    if (this.options.steps) { this.jsav.stepOption("grade", true); }
    step.apply(this.jsav);
    while (i > 1 && comp(this.value(parent - 1), val) > 0) {
      if (this.options.stats) {
        this.stats.swaps += 1;
      }
      this.swap(i - 1, parent - 1);
      step.apply(this.jsav);
      i = parent;
      parent = Math.floor(i / 2);
    }
    if (comp(this.value(parent -1), val) === 0 && this.options.stats) {
      this.stats.collision = true;
    }
    return this;
  };

  JSAV.ext.ds.binheap = function(element, options) {
    return new BinaryHeap(this, element, $.extend(true, {'compare': compareFunction, "stats": false,
                                                         'steps': true, 'tree': true,
                                                         'heapify': true, 'center': true}, options));
  };
}(jQuery));<commit_msg>Added add/remove/toggleClass functions to binary heap<commit_after>(function($) {
  "use strict";
  var compareFunction = function(a, b) {
    return a - b;
  };
  var inittree = function(binheap) {
    var size = binheap.size(),
      bt = binheap._tree,
      nodes = [];
    var donode = function(node, pos) {
      if (pos === 1) {
        node.value(binheap.value(pos - 1));
      }
      node.element.attr("data-jsav-heap-index", pos);
      nodes[pos - 1] = node;
      var lpos = pos * 2,
          rpos = lpos + 1;
      if (lpos <= size) {
        if (!node.left()) {
          node.left(binheap.value(lpos - 1));
        } else {
          node.left().value(binheap.value(lpos - 1));
        }
        donode(node.left(), lpos);
      }
      if (rpos <= size) {
        if (!node.right()) {
          node.right(binheap.value(rpos - 1));
        } else {
          node.right().value(binheap.value(rpos - 1));
        }
        donode(node.right(), rpos);
      }
    };
    binheap._treenodes = nodes;
    donode(bt.root(), 1);
  };

  var BinaryHeap = function(jsav, element, options) {
    this.jsav = jsav;
    this.options = $.extend({indexed: true, layout: "array"}, options);
    if (!this.options.template) {
      var tmplName = this.options.layout + (this.options.indexed?"-indexed":"");
      this.options.template = JSAV._types.ds.AVArray._templates[tmplName];
    }
    this._indices = [];
    if ($.isArray(element)) {
      var arrsize = element.length;
      if ('size' in options) {
        element.length = options.size;
      }
      this.initialize(element);
      this.element.attr("data-jsav-heap-size", arrsize);
    } else {
      if (element) { // assume it's a DOM element
        this.element = $(element);
      } else {
        this.element = $("<ol/>");
        $(this.jsav.container).append(this.element).addClass("jsavbinaryheap");
      }
      var size = 0;
      $.each(this.element.find("li"), function(index) {
        if (this.value(index) !== "") {
          size++;
        }
      });
      this.element.attr("data-jsav-heap-size", size.length);

      this.initializeFromElement();
    }
    var oldfx = $.fx.off || false;
    $.fx.off = true;

    if (options.stats) {
      this.stats = {"swaps": 0, "leftswaps": 0, "rightswaps": 0,
                    "recursiveswaps": 0, "partlyrecursiveswaps": 0};
    }

    if (options.tree) {
      this._tree = jsav.ds.bintree(options);
      inittree(this);
      this._tree.layout();
    }
    if (options.heapify) {
      for (var i = Math.floor(this.heapsize()/2); i > 0; i--) {
        this.heapify(i);
      }
    }
     if (this.options.center) {
      this.element.addClass("jsavcenter");
    }
   $.fx.off = oldfx;
  };
  JSAV.utils.extend(BinaryHeap, JSAV._types.ds.AVArray);
  var bhproto = BinaryHeap.prototype;
  //$.extend(bhproto, JSAV._types.ds.AVArray.prototype);
  bhproto.arrayswap = bhproto.swap;
  bhproto.arraycss = bhproto.css;
  bhproto.arrayclear = bhproto.clear;
  bhproto.arrayvalue = bhproto.value;

  bhproto.value = function(index, newValue) {
    if (typeof newValue === "undefined") {
      return this.arrayvalue(index);
    }
    this.arrayvalue(index, newValue);
    if (index >= this.heapsize()) {
      this.element.attr("data-jsav-heap-size", index + 1);
    }
    if (this.options.tree) {
      this._treenodes[index].value(newValue);
    }
  };

  bhproto.clear = function() {
    this.arrayclear();
    if (this.options.tree) {
      this._tree.clear();
    }
  };

  // create versions of some array functions that will also change
  // the treenodes
  var funcs = ["css", "highlight", "unhighlight", "addClass", "removeClass", "toggleClass"];
  var getDelegateFunction = function(name) {
    // return a "delegate" function bound to the array function with given name
    return function() {
      var node;
      // first call the stored original array function
      var val = this["_array" + name].apply(this, arguments);
      // then the treenode functions, based on the type of the index
      // argument (first argument)
      if (this.options.tree && typeof arguments[0] === "number") {
        node = this._treenodes[arguments[0]];
        node[name].apply(node, [].slice.call(arguments, 1));
      } else if (this.options.tree && $.isArray(arguments[0])) {
        for (var i = arguments[0].length; i--; ) {
          node = this._treenodes[arguments[0][i]];
          node[name].apply(node, [].slice.call(arguments, 1))
        }
      }
      // finally return the value of the array function
      return val;
    }
  };
  // go through the function names, store the array functions, and create
  // delegate functions to the heap prototype
  for (var i = funcs.length; i--; ) {
    bhproto["_array" + funcs[i]] = bhproto[funcs[i]];
    bhproto[funcs[i]] = getDelegateFunction(funcs[i]);
  }

  bhproto._setsize = JSAV.anim(function(newsize) {
    var oldsize = this.element.attr("data-jsav-heap-size");
    this.element.attr("data-jsav-heap-size", newsize);
    return [oldsize];
  });
  bhproto.heapsize = function(newsize) {
    if (typeof newsize !== "undefined") {
      return this._setsize(newsize);
    } else {
      return parseInt(this.element.attr("data-jsav-heap-size"), 10);
    }
  };

  bhproto.heapify = function(pos, options) {
    var size = this.heapsize(),
      lpos = pos * 2,
      rpos = pos * 2 + 1,
      smallest = pos,
      comp = this.options.compare,
      step = this.options.steps ? this.jsav.step : function() {};
    if (lpos <= size && comp(this.value(lpos - 1), this.value(pos - 1)) < 0) {
      smallest = lpos;
    }
    if (rpos <= size && comp(this.value(rpos - 1), this.value(smallest - 1)) < 0) {
      smallest = rpos;
    }
    if (smallest !== pos) {
      if (this.options.stats) {
        this.stats.swaps++;
        if (smallest === lpos) { this.stats.leftswaps++; }
        else { this.stats.rightswaps++; }
      }
      if (options && options.noAnimation) {
        var tmp = this.value(pos - 1);
        this.value(pos - 1, this.value(smallest - 1));
        this.value(smallest - 1, tmp);
      } else {
        this.swap(smallest - 1, pos - 1);
      }
      step.apply(this.jsav);
      if (this.heapify(smallest, options) && this.options.stats) {
        this.stats.recursiveswaps++;
      } else if (this.options.stats) {
        this.stats.partlyrecursiveswaps++;
      }
      return true;
    } else if (this.options.stats) {
      this.stats.interrupted = true;
    }
    return false;
  };
  bhproto.swap = function(index1, index2, options) {
    this.arrayswap(index1, index2, options);
    if (this.options.tree) {
      // swap the values in the tree
      this.jsav.effects.swapValues(this._treenodes[index1],
                                   this._treenodes[index2]);
    }
  };
  bhproto.insert = function(val) {
    var i = this.heapsize() + 1,
      parent = Math.floor(i / 2),
      comp = this.options.compare,
      step = this.options.steps ? this.jsav.step : function() {};
    this.value(i - 1, val);
    if (this.options.steps) { this.jsav.stepOption("grade", true); }
    step.apply(this.jsav);
    while (i > 1 && comp(this.value(parent - 1), val) > 0) {
      if (this.options.stats) {
        this.stats.swaps += 1;
      }
      this.swap(i - 1, parent - 1);
      step.apply(this.jsav);
      i = parent;
      parent = Math.floor(i / 2);
    }
    if (comp(this.value(parent -1), val) === 0 && this.options.stats) {
      this.stats.collision = true;
    }
    return this;
  };

  JSAV.ext.ds.binheap = function(element, options) {
    return new BinaryHeap(this, element, $.extend(true, {'compare': compareFunction, "stats": false,
                                                         'steps': true, 'tree': true,
                                                         'heapify': true, 'center': true}, options));
  };
}(jQuery));<|endoftext|>


<commit_before>'use strict';

const expect = require('chai').expect;
const TeamspeakQuery = require('..');

let testString = 'notifytextmessage targetmode=3 msg=x=y=z invokerid=2 invokername=schroffl invokeruid=3ZLOUe2rnjkorZfn98EdKyadVV4=';

describe('TeamspeakQuery', () => {

  describe('#escape', () => {
    it('Should escape strings according to the specs', () => {
      expect( TeamspeakQuery.escape('\\') ).to.equal('\\\\');
      expect( TeamspeakQuery.escape('/')  ).to.equal('\\/');
      expect( TeamspeakQuery.escape(' ')  ).to.equal('\\s');
      expect( TeamspeakQuery.escape('\n') ).to.equal('\\n');
      expect( TeamspeakQuery.escape('\r') ).to.equal('\\r');
      expect( TeamspeakQuery.escape('\t') ).to.equal('\\t');
      expect( TeamspeakQuery.escape('\v') ).to.equal('\\v');
      expect( TeamspeakQuery.escape('\f') ).to.equal('\\f');
    });
  });

  describe('#unescape', () => {
    it('Should unescape strings according to the specs', () => {
      expect( TeamspeakQuery.unescape('\\\\') ).to.equal('\\');
      expect( TeamspeakQuery.unescape('\\/')  ).to.equal('/');
      expect( TeamspeakQuery.unescape('\\s')  ).to.equal(' ');
      expect( TeamspeakQuery.unescape('\\n')  ).to.equal('\n');
      expect( TeamspeakQuery.unescape('\\r')  ).to.equal('\r');
      expect( TeamspeakQuery.unescape('\\t')  ).to.equal('\t');
      expect( TeamspeakQuery.unescape('\\v')  ).to.equal('\v');
      expect( TeamspeakQuery.unescape('\\f')  ).to.equal('\f');
    });
  });

  describe('#assembleCommandString', () => {
    it('Should correctly construct and escape a command string', () => {
      expect( TeamspeakQuery.assembleCommandString('command', { 'this': 'is' }, 'just', { 'msg': 'a stupid test' }) )
      .to.equal('command this=is just msg=a\\sstupid\\stest');
    });
  });

  describe('#parse', () => {
    it('Should detect error- and notify-messages', () => {
      let notify = TeamspeakQuery.parse('notifytextmessage msg=text'),
          error = TeamspeakQuery.parse('error id=0 msg=ok');

      expect(notify.type).to.equal('notifytextmessage');
      expect(notify.params.msg).to.equal('text');

      expect(error.type).to.equal('error');
      expect(error.params.msg).to.equal('ok');
    });

    it('Should parse multiple values for the same key into an array', () => {
      let str = 'clid=1|clid=2',
          parsed = TeamspeakQuery.parse(str);

      expect(parsed.type).to.equal(null);
      expect(parsed.params.clid).to.be.a('array');
    });

    it('Should not fail when an equal sign is in a parameter', () => {
      let str = 'notifytextmessage msg=x=y=z invokername=This\\s=\\smy\\pname',
          parsed = TeamspeakQuery.parse(str);

      expect(parsed.type).to.equal('notifytextmessage');
      expect(parsed.params.msg).to.equal('x=y=z');
      expect(parsed.params.invokername).to.equal('This = my|name');
    });
  });

});<commit_msg>Fix test to require lib/base.js<commit_after>'use strict';

const expect = require('chai').expect;
const TeamspeakQuery = require('../lib/base');

let testString = 'notifytextmessage targetmode=3 msg=x=y=z invokerid=2 invokername=schroffl invokeruid=3ZLOUe2rnjkorZfn98EdKyadVV4=';

describe('TeamspeakQuery', () => {

  describe('#escape', () => {
    it('Should escape strings according to the specs', () => {
      expect( TeamspeakQuery.escape('\\') ).to.equal('\\\\');
      expect( TeamspeakQuery.escape('/')  ).to.equal('\\/');
      expect( TeamspeakQuery.escape(' ')  ).to.equal('\\s');
      expect( TeamspeakQuery.escape('\n') ).to.equal('\\n');
      expect( TeamspeakQuery.escape('\r') ).to.equal('\\r');
      expect( TeamspeakQuery.escape('\t') ).to.equal('\\t');
      expect( TeamspeakQuery.escape('\v') ).to.equal('\\v');
      expect( TeamspeakQuery.escape('\f') ).to.equal('\\f');
    });
  });

  describe('#unescape', () => {
    it('Should unescape strings according to the specs', () => {
      expect( TeamspeakQuery.unescape('\\\\') ).to.equal('\\');
      expect( TeamspeakQuery.unescape('\\/')  ).to.equal('/');
      expect( TeamspeakQuery.unescape('\\s')  ).to.equal(' ');
      expect( TeamspeakQuery.unescape('\\n')  ).to.equal('\n');
      expect( TeamspeakQuery.unescape('\\r')  ).to.equal('\r');
      expect( TeamspeakQuery.unescape('\\t')  ).to.equal('\t');
      expect( TeamspeakQuery.unescape('\\v')  ).to.equal('\v');
      expect( TeamspeakQuery.unescape('\\f')  ).to.equal('\f');
    });
  });

  describe('#assembleCommandString', () => {
    it('Should correctly construct and escape a command string', () => {
      expect( TeamspeakQuery.assembleCommandString('command', { 'this': 'is' }, 'just', { 'msg': 'a stupid test' }) )
      .to.equal('command this=is just msg=a\\sstupid\\stest');
    });
  });

  describe('#parse', () => {
    it('Should detect error- and notify-messages', () => {
      let notify = TeamspeakQuery.parse('notifytextmessage msg=text'),
          error = TeamspeakQuery.parse('error id=0 msg=ok');

      expect(notify.type).to.equal('notifytextmessage');
      expect(notify.params.msg).to.equal('text');

      expect(error.type).to.equal('error');
      expect(error.params.msg).to.equal('ok');
    });

    it('Should parse multiple values for the same key into an array', () => {
      let str = 'clid=1|clid=2',
          parsed = TeamspeakQuery.parse(str);

      expect(parsed.type).to.equal(null);
      expect(parsed.params.clid).to.be.a('array');
    });

    it('Should not fail when an equal sign is in a parameter', () => {
      let str = 'notifytextmessage msg=x=y=z invokername=This\\s=\\smy\\pname',
          parsed = TeamspeakQuery.parse(str);

      expect(parsed.type).to.equal('notifytextmessage');
      expect(parsed.params.msg).to.equal('x=y=z');
      expect(parsed.params.invokername).to.equal('This = my|name');
    });
  });

});<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

goog.provide('shaka.media.TimeRangesUtils');

/**
 * @namespace shaka.media.TimeRangesUtils
 * @summary A set of utility functions for dealing with TimeRanges objects.
 */

/**
 * Gets the first timestamp in buffer.
 *
 * @param {TimeRanges} b
 * @return {?number} The first buffered timestamp, in seconds, if |buffered|
 *   is non-empty; otherwise, return null.
 */
shaka.media.TimeRangesUtils.bufferStart = function(b) {
  if (!b) return null;
  // Workaround Safari bug: https://goo.gl/EDRCoZ
  if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) return null;
  // Workaround Edge bug: https://goo.gl/BtxKgb
  if (b.length == 1 && b.start(0) < 0) return 0;
  return b.length ? b.start(0) : null;
};

/**
 * Gets the last timestamp in buffer.
 *
 * @param {TimeRanges} b
 * @return {?number} The last buffered timestamp, in seconds, if |buffered|
 *   is non-empty; otherwise, return null.
 */
shaka.media.TimeRangesUtils.bufferEnd = function(b) {
  if (!b) return null;
  // Workaround Safari bug: https://goo.gl/EDRCoZ
  if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) return null;
  return b.length ? b.end(b.length - 1) : null;
};

/**
 * Determines if the given time is inside a buffered range.  This includes gaps,
 * meaning if the playhead is in a gap, it is considered buffered.
 *
 * @param {TimeRanges} b
 * @param {number} time
 * @return {boolean}
 */
shaka.media.TimeRangesUtils.isBuffered = function(b, time) {
  if (!b || !b.length) return false;
  // Workaround Safari bug: https://goo.gl/EDRCoZ
  if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) return false;

  return time >= b.start(0) && time <= b.end(b.length - 1);
};

/**
 * Computes how far ahead of the given timestamp is buffered.  To provide smooth
 * playback while jumping gaps, we don't include the gaps when calculating this.
 * This only includes the amount of content that is buffered.
 *
 * @param {TimeRanges} b
 * @param {number} time
 * @return {number} The number of seconds buffered, in seconds, ahead of the
 *   given time.
 */
shaka.media.TimeRangesUtils.bufferedAheadOf = function(b, time) {
  if (!b || !b.length) return 0;
  // Workaround Safari bug: https://goo.gl/EDRCoZ
  if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) return 0;

  // NOTE: On IE11, buffered ranges may show appended data before the associated
  // append operation is complete.

  // We calculate buffered amount by ONLY accounting for the content buffered
  // (i.e. we ignore the times of the gaps).  We also buffer through all gaps.
  // So start at the end and add up all buffers until |time|.
  var result = 0;
  for (var i = b.length - 1; i >= 0 && b.end(i) > time; --i) {
    result += b.end(i) - Math.max(b.start(i), time);
  }

  return result;
};

/**
 * Determines if the given time is inside a gap between buffered ranges.  If it
 * is, this returns the index of the buffer that is *ahead* of the gap.
 *
 * @param {TimeRanges} b
 * @param {number} time
 * @return {?number} The index of the buffer after the gap, or null if not in a
 *   gap.
 */
shaka.media.TimeRangesUtils.getGapIndex = function(b, time) {
  if (!b || !b.length) return null;
  // Workaround Safari bug: https://goo.gl/EDRCoZ
  if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) return null;

  // IE/Edge stops 0.5 seconds before a gap, so it needs a much larger
  // threshold, but we don't want to punish other browsers that stop closer.
  // See: https://goo.gl/cuAcYd
  var threshold = 0.1;
  if (/(Edge|Trident)\//.test(navigator.userAgent))
    threshold = 0.5;

  for (var i = 0; i < b.length; i++) {
    if (b.start(i) > time && (i == 0 || b.end(i - 1) - time <= threshold)) {
      return i;
    }
  }

  return null;
};
<commit_msg>Fix test timeouts on Tizen TV.<commit_after>/**
 * @license
 * Copyright 2016 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

goog.provide('shaka.media.TimeRangesUtils');

/**
 * @namespace shaka.media.TimeRangesUtils
 * @summary A set of utility functions for dealing with TimeRanges objects.
 */

/**
 * Gets the first timestamp in buffer.
 *
 * @param {TimeRanges} b
 * @return {?number} The first buffered timestamp, in seconds, if |buffered|
 *   is non-empty; otherwise, return null.
 */
shaka.media.TimeRangesUtils.bufferStart = function(b) {
  if (!b) return null;
  // Workaround Safari bug: https://goo.gl/EDRCoZ
  if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) return null;
  // Workaround Edge bug: https://goo.gl/BtxKgb
  if (b.length == 1 && b.start(0) < 0) return 0;
  return b.length ? b.start(0) : null;
};

/**
 * Gets the last timestamp in buffer.
 *
 * @param {TimeRanges} b
 * @return {?number} The last buffered timestamp, in seconds, if |buffered|
 *   is non-empty; otherwise, return null.
 */
shaka.media.TimeRangesUtils.bufferEnd = function(b) {
  if (!b) return null;
  // Workaround Safari bug: https://goo.gl/EDRCoZ
  if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) return null;
  return b.length ? b.end(b.length - 1) : null;
};

/**
 * Determines if the given time is inside a buffered range.  This includes gaps,
 * meaning if the playhead is in a gap, it is considered buffered.
 *
 * @param {TimeRanges} b
 * @param {number} time
 * @return {boolean}
 */
shaka.media.TimeRangesUtils.isBuffered = function(b, time) {
  if (!b || !b.length) return false;
  // Workaround Safari bug: https://goo.gl/EDRCoZ
  if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) return false;

  return time >= b.start(0) && time <= b.end(b.length - 1);
};

/**
 * Computes how far ahead of the given timestamp is buffered.  To provide smooth
 * playback while jumping gaps, we don't include the gaps when calculating this.
 * This only includes the amount of content that is buffered.
 *
 * @param {TimeRanges} b
 * @param {number} time
 * @return {number} The number of seconds buffered, in seconds, ahead of the
 *   given time.
 */
shaka.media.TimeRangesUtils.bufferedAheadOf = function(b, time) {
  if (!b || !b.length) return 0;
  // Workaround Safari bug: https://goo.gl/EDRCoZ
  if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) return 0;

  // NOTE: On IE11, buffered ranges may show appended data before the associated
  // append operation is complete.

  // We calculate buffered amount by ONLY accounting for the content buffered
  // (i.e. we ignore the times of the gaps).  We also buffer through all gaps.
  // So start at the end and add up all buffers until |time|.
  var result = 0;
  for (var i = b.length - 1; i >= 0 && b.end(i) > time; --i) {
    result += b.end(i) - Math.max(b.start(i), time);
  }

  return result;
};

/**
 * Determines if the given time is inside a gap between buffered ranges.  If it
 * is, this returns the index of the buffer that is *ahead* of the gap.
 *
 * @param {TimeRanges} b
 * @param {number} time
 * @return {?number} The index of the buffer after the gap, or null if not in a
 *   gap.
 */
shaka.media.TimeRangesUtils.getGapIndex = function(b, time) {
  if (!b || !b.length) return null;
  // Workaround Safari bug: https://goo.gl/EDRCoZ
  if (b.length == 1 && b.end(0) - b.start(0) < 1e-6) return null;

  // IE/Edge stops 0.5 seconds before a gap, so it needs a much larger
  // threshold, but we don't want to punish other browsers that stop closer.
  // See: https://goo.gl/cuAcYd
  var threshold = 0.1;
  if (/(Edge\/|Trident\/|Tizen)/.test(navigator.userAgent))
    threshold = 0.5;

  for (var i = 0; i < b.length; i++) {
    if (b.start(i) > time && (i == 0 || b.end(i - 1) - time <= threshold)) {
      return i;
    }
  }

  return null;
};
<|endoftext|>


<commit_before>var Parser = require('binary-parser').Parser;

//==============================================================================
// Helper functions
//==============================================================================

// Parser choices needs an int value as key.
// This function returns an int regarding to its property type.
var selectDataType = function() {
  if(this.type === 'IntProperty')
    return 1;
  else if(this.type === 'ArrayProperty')
    return 2;
  else if(this.type === 'StrProperty' || this.type === 'NameProperty')
    return 3;
  else if(this.type === 'ByteProperty')
    return 4;
  else if(this.type === 'QWordProperty')
    return 5;
  else if(this.type === 'BoolProperty')
    return 6;
  else if(this.type === 'FloatProperty')
    return 7;
};

// A function which returns 1 if the property name is "None", 0 if not.
// Again the parser choices needs int keys.
var isNone = function() {
  if(this.name === 'None')
    return 1;

  return 0;
}

// Helper function, which returns true, if the stream has read "None"
// (or isNone() was 1).
var readUntilNone = function(item, buf) {
  return item.name === 'None';
}

// JS can not handle 64 bit integers, so the parser reads 2 32 bit integers.
// This function converts the 32 bit integer from decimal to hex (little endian).
var decToHex = function(item) {
  var hex = parseInt(item, 10).toString(16);
  var len = 8 - hex.length;

  if (len > 0) {
    for(len; len > 0; --len)
      hex = '0' + hex;
  }

  return hex;
}

//==============================================================================
// Parsers
// (All are little endian)
//==============================================================================

//------------------------------------------------------------------------------
// Value parsers
//------------------------------------------------------------------------------

// Parses an 32 bit integer.
var IntProperty = new Parser()
  .endianess('little')
  .int32('value');

// Parses a 32 bit integer length value of the following string
// and the string itself with Null stripped.
var StrProperty = new Parser()
  .endianess('little')
  .int32('vl')
  .string('value', { encoding: 'ascii', length: 'vl', stripNull: true });

// The byte property contains 2 strings prefixed by 2 32 bit integers as lengths
// (Strange byte type ...)
var ByteProperty = new Parser()
  .endianess('little')
  .int32('vl1')
  .string('value1', { encoding: 'ascii', length: 'vl1', stripNull: true })
  .int32('vl2')
  .string('value2', { encoding: 'ascii', length: 'vl2', stripNull: true });

// Parses a 64 bit integer into 2 32 bit integers as hex values.
var QWordProperty = new Parser()
  .endianess('little')
  .int32('hex2', { formatter: decToHex })
  .int32('hex1', { formatter: decToHex });

// Parses 0 or 1 (1 byte).
var BoolProperty = new Parser()
  .endianess('little')
  .bit8('value');

// Parses a 32 bit single precision value.
var FloatProperty = new Parser()
  .endianess('little')
  .float('value');

//------------------------------------------------------------------------------
// Array Parsers
//------------------------------------------------------------------------------

// This parser is like the property parser, just for the properties of the array.
// See below for description.
var ArrayPropertyDetail = new Parser()
  .endianess('little')
  .int32('nl')
  .string('name', { encoding: 'ascii', length: 'nl', stripNull: true })
  .choice('more', {
    tag: isNone,
    choices: {
      1: new Parser(),
      0: new Parser()
        .endianess('little')
        .int32('tl')
        .string('type', { encoding: 'ascii', length: 'tl', stripNull: true })
        .int32('unkn1')
        .int32('unkn2')
        .choice('details', {
            tag: selectDataType,
            choices: {
              1: IntProperty,
              3: StrProperty,
              4: ByteProperty,
              5: QWordProperty,
              6: BoolProperty,
              7: FloatProperty
            }
        })
    }
  });

// This parser parses the array property, which has a length of elements
// (like 4 representing 4 Goals) and a array of goal properties.
var ArrayProperty = new Parser()
  .endianess('little')
  .int32('length')
  .array('array', {
    type: new Parser().array('part', { type: ArrayPropertyDetail, readUntil: readUntilNone }),
    length: 'length'
  });

//------------------------------------------------------------------------------
// Property parser
//------------------------------------------------------------------------------

// This Parser parses the property section. It contains every single match
// information like goals, teamsize, score, etc.
// Every property has a name (string) prefixed by a length (int32).
// Then a type information (string) prefixed by a length (int32).
// And the value of the property (Selecting the right value parser).
// Btw: After the property type there are 2 unknown 32 bit integers.
var Property = new Parser()
  .endianess('little')
  .int32('nl')
  .string('name', { encoding: 'ascii', length: 'nl', stripNull: true })
  .choice('more', {
    tag: isNone,
    choices: {
      1: new Parser(),
      0: new Parser()
        .endianess('little')
        .int32('tl')
        .string('type', { encoding: 'ascii', length: 'tl', stripNull: true })
        .int32('unkn1')
        .int32('unkn2')
        .choice('details', {
            tag: selectDataType,
            choices: {
              1: IntProperty,
              2: ArrayProperty,
              3: StrProperty,
              4: ByteProperty,
              5: QWordProperty,
              6: BoolProperty,
              7: FloatProperty
            }
        })
    }
  });

//------------------------------------------------------------------------------
// Main parser and export
//------------------------------------------------------------------------------

// This is the main parser which first parses the meta information of the replay.
// Followed by the property section.
// A small explanation: Strings are length prefixed, so the tags for the prefixes
// are 2 chars like "tl" which means "type length".
// Those values are only necessary to know how long the string will be.
module.exports = new Parser()
  .endianess('little')
  .int32('identifier')
  .int32('crc')
  .int32('version_major')
  .int32('version_minor')
  .int32('tl')
  .string('type', { encoding: 'ascii', length: 'tl', stripNull: true })
  .array('properties', {
    type: Property,
    readUntil: readUntilNone
  });
<commit_msg>Added keyframe parsing<commit_after>var Parser = require('binary-parser').Parser;

//==============================================================================
// Helper functions
//==============================================================================

// Parser choices needs an int value as key.
// This function returns an int regarding to its property type.
var selectDataType = function() {
  if(this.type === 'IntProperty')
    return 1;
  else if(this.type === 'ArrayProperty')
    return 2;
  else if(this.type === 'StrProperty' || this.type === 'NameProperty')
    return 3;
  else if(this.type === 'ByteProperty')
    return 4;
  else if(this.type === 'QWordProperty')
    return 5;
  else if(this.type === 'BoolProperty')
    return 6;
  else if(this.type === 'FloatProperty')
    return 7;
};

// A function which returns 1 if the property name is "None", 0 if not.
// Again the parser choices needs int keys.
var isNone = function() {
  if(this.name === 'None')
    return 1;

  return 0;
}

// Helper function, which returns true, if the stream has read "None"
// (or isNone() was 1).
var readUntilNone = function(item, buf) {
  return item.name === 'None';
}

// JS can not handle 64 bit integers, so the parser reads 2 32 bit integers.
// This function converts the 32 bit integer from decimal to hex (little endian).
var decToHex = function(item) {
  var hex = parseInt(item, 10).toString(16);
  var len = 8 - hex.length;

  if (len > 0) {
    for(len; len > 0; --len)
      hex = '0' + hex;
  }

  return hex;
}

//==============================================================================
// Parsers
// (All are little endian)
//==============================================================================

//------------------------------------------------------------------------------
// Value parsers
//------------------------------------------------------------------------------

// Parses an 32 bit integer.
var IntProperty = new Parser()
  .endianess('little')
  .int32('value');

// Parses a 32 bit integer length value of the following string
// and the string itself with Null stripped.
var StrProperty = new Parser()
  .endianess('little')
  .int32('vl')
  .string('value', { encoding: 'ascii', length: 'vl', stripNull: true });

// The byte property contains 2 strings prefixed by 2 32 bit integers as lengths
// (Strange byte type ...)
var ByteProperty = new Parser()
  .endianess('little')
  .int32('vl1')
  .string('value1', { encoding: 'ascii', length: 'vl1', stripNull: true })
  .int32('vl2')
  .string('value2', { encoding: 'ascii', length: 'vl2', stripNull: true });

// Parses a 64 bit integer into 2 32 bit integers as hex values.
var QWordProperty = new Parser()
  .endianess('little')
  .int32('hex2', { formatter: decToHex })
  .int32('hex1', { formatter: decToHex });

// Parses 0 or 1 (1 byte).
var BoolProperty = new Parser()
  .endianess('little')
  .bit8('value');

// Parses a 32 bit single precision value.
var FloatProperty = new Parser()
  .endianess('little')
  .float('value');

//------------------------------------------------------------------------------
// Array Parsers
//------------------------------------------------------------------------------

// This parser is like the property parser, just for the properties of the array.
// See below for description.
var ArrayPropertyDetail = new Parser()
  .endianess('little')
  .int32('nl')
  .string('name', { encoding: 'ascii', length: 'nl', stripNull: true })
  .choice('more', {
    tag: isNone,
    choices: {
      1: new Parser(),
      0: new Parser()
        .endianess('little')
        .int32('tl')
        .string('type', { encoding: 'ascii', length: 'tl', stripNull: true })
        .int32('unkn1')
        .int32('unkn2')
        .choice('details', {
            tag: selectDataType,
            choices: {
              1: IntProperty,
              3: StrProperty,
              4: ByteProperty,
              5: QWordProperty,
              6: BoolProperty,
              7: FloatProperty
            }
        })
    }
  });

// This parser parses the array property, which has a length of elements
// (like 4 representing 4 Goals) and a array of goal properties.
var ArrayProperty = new Parser()
  .endianess('little')
  .int32('length')
  .array('array', {
    type: new Parser().array('part', { type: ArrayPropertyDetail, readUntil: readUntilNone }),
    length: 'length'
  });

//------------------------------------------------------------------------------
// Keyframe parser
//------------------------------------------------------------------------------

var Keyframe = new Parser()
  .endianess('little')
  .float('time')
  .int32('frame')
  .int32('file_position');

//------------------------------------------------------------------------------
// Property parser
//------------------------------------------------------------------------------

// This Parser parses the property section. It contains every single match
// information like goals, teamsize, score, etc.
// Every property has a name (string) prefixed by a length (int32).
// Then a type information (string) prefixed by a length (int32).
// And the value of the property (Selecting the right value parser).
// Btw: After the property type there are 2 unknown 32 bit integers.
var Property = new Parser()
  .endianess('little')
  .int32('nl')
  .string('name', { encoding: 'ascii', length: 'nl', stripNull: true })
  .choice('more', {
    tag: isNone,
    choices: {
      1: new Parser(),
      0: new Parser()
        .endianess('little')
        .int32('tl')
        .string('type', { encoding: 'ascii', length: 'tl', stripNull: true })
        .int32('unkn1')
        .int32('unkn2')
        .choice('details', {
            tag: selectDataType,
            choices: {
              1: IntProperty,
              2: ArrayProperty,
              3: StrProperty,
              4: ByteProperty,
              5: QWordProperty,
              6: BoolProperty,
              7: FloatProperty
            }
        })
    }
  });

//------------------------------------------------------------------------------
// Main parser and export
//------------------------------------------------------------------------------

// This is the main parser which first parses the meta information of the replay.
// Followed by the property section.
// A small explanation: Strings are length prefixed, so the tags for the prefixes
// are 2 chars like "tl" which means "type length".
// Those values are only necessary to know how long the string will be.
module.exports = new Parser()
  .endianess('little')
  .int32('identifier')
  .int32('crc')
  .int32('version_major')
  .int32('version_minor')
  .int32('tl')
  .string('type', { encoding: 'ascii', length: 'tl', stripNull: true })
  .array('properties', {
    type: Property,
    readUntil: readUntilNone
  })
  .int32('length_of_remaining_data')
  .uint32('unkn1')
  .int32('ldl')
  .array('level_data', {
    type: StrProperty,
    length: 'ldl'
  })
  .int32('kl')
  .array('keyframes', {
    type: Keyframe,
    length: 'kl'
  });
<|endoftext|>


<commit_before>var assert = require('assert');
var tjs = require('../TeslaJS');

// set these in your environment before testing
var user = process.env.TESLAJS_USER;
var pass = process.env.TESLAJS_PASS;

process.env.TESLAJS_SERVER || process.exit(1);

describe('TeslaJS', function () {
    var options = {authToken: "abc123"};
    this.timeout(5000);

	describe('#login()', function() {
		it('should succeed with valid user and pwd', function(done) {
			tjs.login(user, pass, function(result) {
				if (result.response.statusCode == 200) {
				    options.authToken = result.authToken;
                    done();
				} else {
				    done(result.response.statusMessage);
				}
			});
		});
//		it('should fail with invalid pwd', function(done) {
//			tjs.login(user, 'badpassword', function(result) {
//				if (result.response.statusCode == 200) {
//					done(result.response.statusMessage);
//				} else {
//					done();
//				}
//			});
	    //		});
	});

	describe('#vehicles()', function () {
	    it('should succeed enumerating vehicles', function (done) {
	        tjs.vehicles(options, function (result) {
	            if (result.vehicle_id) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#vehicleState()', function () {
	    it('should return vehicle state', function (done) {
	        tjs.vehicleState(options, function (result) {
	            if (result.car_version) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#climateState()', function () {
	    it('should return climate state', function (done) {
	        tjs.climateState(options, function (result) {
	            if (result.inside_temp) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#driveState()', function () {
	    it('should return drive state', function (done) {
	        tjs.driveState(options, function (result) {
	            if (result.heading) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#chargeState()', function () {
	    it('should return charge state', function (done) {
	        tjs.chargeState(options, function (result) {
	            if (result.est_battery_range) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#guiSettings()', function () {
	    it('should return gui settings', function (done) {
	        tjs.guiSettings(options, function (result) {
	            if (result.gui_distance_units) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#mobileEnabled()', function () {
	    it('should return mobile enabled', function (done) {
	        tjs.mobileEnabled(options, function (result) {
	            if (result) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#honkHorn()', function () {
	    it('should return true', function (done) {
	        tjs.honkHorn(options, function (result) {
	            if (result) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#flashLights()', function () {
	    it('should return true', function (done) {
	        tjs.flashLights(options, function (result) {
	            if (result) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});
});
<commit_msg>more test cases<commit_after>var assert = require('assert');
var tjs = require('../TeslaJS');

var sepia = require('sepia');

sepia.configure({
    verbose: false,
    touchHits: true
});

// set these in your environment before testing
var user = process.env.TESLAJS_USER;
var pass = process.env.TESLAJS_PASS;

process.env.TESLAJS_SERVER || process.exit(1);

describe('TeslaJS', function () {
    var options = {authToken: "abc123"};
    this.timeout(5000);

	describe('#login()', function() {
		it('should succeed with valid user and pwd', function(done) {
			tjs.login(user, pass, function(result) {
				if (result.response.statusCode == 200) {
				    options.authToken = result.authToken;
                    done();
				} else {
				    done(result.response.statusMessage);
				}
			});
		});
/*
		it('should fail with invalid pwd', function(done) {
			tjs.login(user, 'badpassword', function(result) {
				if (result.response.statusCode == 200) {
					done(result.response.statusMessage);
				} else {
					done();
				}
			});
		});
*/
	});

	describe('#vehicles()', function () {
	    it('should succeed enumerating vehicles', function (done) {
	        tjs.vehicles(options, function (result) {
	            if (result.vehicle_id) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#vehicleState()', function () {
	    it('should return vehicle state', function (done) {
	        tjs.vehicleState(options, function (result) {
	            if (result.car_version) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#climateState()', function () {
	    it('should return climate state', function (done) {
	        tjs.climateState(options, function (result) {
	            if (result.inside_temp) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#driveState()', function () {
	    it('should return drive state', function (done) {
	        tjs.driveState(options, function (result) {
	            if (result.heading) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#chargeState()', function () {
	    it('should return charge state', function (done) {
	        tjs.chargeState(options, function (result) {
	            if (result.est_battery_range) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#guiSettings()', function () {
	    it('should return gui settings', function (done) {
	        tjs.guiSettings(options, function (result) {
	            if (result.gui_distance_units) {
	                done();
	            } else {
	                done(result.response.statusMessage);
	            }
	        });
	    });
	});

	describe('#mobileEnabled()', function () {
	    it('should return mobile enabled', function (done) {
	        tjs.mobileEnabled(options, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});

	describe('#honkHorn()', function () {
	    it('should return true', function (done) {
	        tjs.honkHorn(options, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});

	describe('#flashLights()', function () {
	    it('should return true', function (done) {
	        tjs.flashLights(options, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});

	describe('#startCharge()', function () {
	    it('should return true', function (done) {
	        tjs.startCharge(options, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});

	describe('#stopCharge()', function () {
	    it('should return true', function (done) {
	        tjs.stopCharge(options, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});

	describe('#openChargePort()', function () {
	    it('should return true', function (done) {
	        tjs.openChargePort(options, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});

/*
	describe('#closeChargePort()', function () {
	    it('should return true', function (done) {
	        tjs.closeChargePort(options, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});
*/
	describe('#setChargeLimit()', function () {
	    it('CHARGE_STORAGE should return true', function (done) {
	        tjs.setChargeLimit(options, tjs.CHARGE_STORAGE, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });

	    it('CHARGE_DAILY should return true', function (done) {
	        tjs.setChargeLimit(options, tjs.CHARGE_DAILY, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });

	    it('CHARGE_STANDARD should return true', function (done) {
	        tjs.setChargeLimit(options, tjs.CHARGE_STANDARD, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });

	    it('CHARGE_RANGE should return true', function (done) {
	        tjs.setChargeLimit(options, tjs.CHARGE_RANGE, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});

	describe('#chargeMaxRange()', function () {
	    it('should return false', function (done) {
	        tjs.chargeMaxRange(options, function (result) {
	            if (!result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});

	describe('#chargeStandard()', function () {
	    it('should return false', function (done) {
	        tjs.chargeStandard(options, function (result) {
	            if (!result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});

	describe('#doorUnlock()', function () {
	    it('should return true', function (done) {
	        tjs.doorUnlock(options, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});

	describe('#doorLock()', function () {
	    it('should return true', function (done) {
	        tjs.doorLock(options, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});

	describe('#wakeUp()', function () {
	    it('should return true', function (done) {
	        tjs.wakeUp(options, function (result) {
	            if (result.result) {
	                done();
	            } else {
	                done(result.reason);
	            }
	        });
	    });
	});
});
<|endoftext|>


<commit_before>// Generated on 2015-11-11 using generator-angular 0.14.0
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Automatically load required Grunt tasks
  require('jit-grunt')(grunt, {
    useminPrepare: 'grunt-usemin',
    ngtemplates: 'grunt-angular-templates',
    cdnify: 'grunt-google-cdn'
  });

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  // mod rewrite for html5-mode
  var modRewrite = require('connect-modrewrite');

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all', 'newer:jscs:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'newer:jscs:test', 'karma']
      },
      styles: {
        files: ['<%= yeoman.app %>/assets/styles/{,*/}*.css'],
        tasks: ['newer:copy:styles', 'postcss']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '<%= yeoman.app %>/views/{,*/}*.md',
          '.tmp/assets/styles/{,*/}*.css',
          '<%= yeoman.app %>/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              modRewrite([
                '!\\.htm*|\\.md|\\.js|\\.css|\\.svg|\\.ico|\\.png|\\.eot|\\.otf|\\.ttf|\\.woff$ /index.html [L]'
              ]),
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/assets/styles',
                connect.static('./app/assets/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    // Make sure there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Make sure code styles are up to par
    jscs: {
      options: {
        config: '.jscsrc',
        verbose: true
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    postcss: {
      options: {
        processors: [
          require('autoprefixer-core')({browsers: ['last 1 version']})
        ]
      },
      server: {
        options: {
          map: true
        },
        files: [{
          expand: true,
          cwd: '.tmp/assets/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/assets/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/assets/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/assets/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/assets/fonts/*',
          '<%= yeoman.dist %>/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/assets/styles/{,*/}*.css',
          '<%= yeoman.dist %>/assets/svg/{,*/}*.{svg}',
          '<%= yeoman.dist %>/scripts/{,*/}*.js'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat'/*, 'uglifyjs'*/],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/assets/styles/{,*/}*.css'],
      js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/assets/fonts',
          '<%= yeoman.dist %>/assets/images',
          '<%= yeoman.dist %>/assets/styles',
          '<%= yeoman.dist %>/assets/svg'
        ],
        patterns: {
          js: [
            [/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp))/g, 'Replacing references to images'],
            [/(svg\/[^''""]*\.(svg))/g, 'Replacing references to svg']
          ]
        }
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/assets/styles/main.css': [
    //         '.tmp/assets/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/assets/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/assets/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
            cwd: '<%= yeoman.app %>/assets/svg',
            src: '{,*/}*.svg',
            dest: '<%= yeoman.dist %>/assets/svg'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    ngtemplates: {
      dist: {
        options: {
          module: 'dresdenjsioApp',
          htmlmin: '<%= htmlmin.dist.options %>',
          usemin: 'scripts/scripts.js'
        },
        cwd: '<%= yeoman.app %>',
        src: 'views/{,*/}*.html',
        dest: '.tmp/templateCache.js'
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '.htaccess',
            '*.{ico,png,txt}',
            '*.html',
            'assets/presentations/{,*/}*.*',
            'assets/fonts/{,*/}*.*',
            'views/{,*/}*.*',
            'layouts/{,*/}*.*',
            'assets/images/{,*/}*.{webp}',
            'assets/svg/{,*/}*.*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/assets/images',
          dest: '<%= yeoman.dist %>/assets/images',
          src: ['generated/*']
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/assets/styles',
        dest: '.tmp/assets/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'copy:styles'
      ],
      test: [
        'copy:styles'
      ],
      dist: [
        'copy:styles',
        'imagemin',
        //'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'postcss:server',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'postcss',
    //'ngtemplates',
    'concat',
    'ngAnnotate',
    'copy:dist',
    //'cdnify',
    'cssmin',
    //'uglify',
    'filerev',
    'usemin',
    //'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'newer:jscs',
    'test',
    'build'
  ]);
};
<commit_msg>enable minification<commit_after>// Generated on 2015-11-11 using generator-angular 0.14.0
'use strict';

// # Globbing
// for performance reasons we're only matching one level down:
// 'test/spec/{,*/}*.js'
// use this if you want to recursively match all subfolders:
// 'test/spec/**/*.js'

module.exports = function (grunt) {

  // Time how long tasks take. Can help when optimizing build times
  require('time-grunt')(grunt);

  // Automatically load required Grunt tasks
  require('jit-grunt')(grunt, {
    useminPrepare: 'grunt-usemin',
    ngtemplates: 'grunt-angular-templates',
    cdnify: 'grunt-google-cdn'
  });

  // Configurable paths for the application
  var appConfig = {
    app: require('./bower.json').appPath || 'app',
    dist: 'dist'
  };

  // mod rewrite for html5-mode
  var modRewrite = require('connect-modrewrite');

  // Define the configuration for all the tasks
  grunt.initConfig({

    // Project settings
    yeoman: appConfig,

    // Watches files for changes and runs tasks based on the changed files
    watch: {
      bower: {
        files: ['bower.json'],
        tasks: ['wiredep']
      },
      js: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.js'],
        tasks: ['newer:jshint:all', 'newer:jscs:all'],
        options: {
          livereload: '<%= connect.options.livereload %>'
        }
      },
      jsTest: {
        files: ['test/spec/{,*/}*.js'],
        tasks: ['newer:jshint:test', 'newer:jscs:test', 'karma']
      },
      styles: {
        files: ['<%= yeoman.app %>/assets/styles/{,*/}*.css'],
        tasks: ['newer:copy:styles', 'postcss']
      },
      gruntfile: {
        files: ['Gruntfile.js']
      },
      livereload: {
        options: {
          livereload: '<%= connect.options.livereload %>'
        },
        files: [
          '<%= yeoman.app %>/{,*/}*.html',
          '<%= yeoman.app %>/views/{,*/}*.md',
          '.tmp/assets/styles/{,*/}*.css',
          '<%= yeoman.app %>/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}'
        ]
      }
    },

    // The actual grunt server settings
    connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              modRewrite([
                '!\\.htm*|\\.md|\\.js|\\.css|\\.svg|\\.ico|\\.png|\\.eot|\\.otf|\\.ttf|\\.woff$ /index.html [L]'
              ]),
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/assets/styles',
                connect.static('./app/assets/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      }
    },

    // Make sure there are no obvious mistakes
    jshint: {
      options: {
        jshintrc: '.jshintrc',
        reporter: require('jshint-stylish')
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        options: {
          jshintrc: 'test/.jshintrc'
        },
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Make sure code styles are up to par
    jscs: {
      options: {
        config: '.jscsrc',
        verbose: true
      },
      all: {
        src: [
          'Gruntfile.js',
          '<%= yeoman.app %>/scripts/{,*/}*.js'
        ]
      },
      test: {
        src: ['test/spec/{,*/}*.js']
      }
    },

    // Empties folders to start fresh
    clean: {
      dist: {
        files: [{
          dot: true,
          src: [
            '.tmp',
            '<%= yeoman.dist %>/{,*/}*',
            '!<%= yeoman.dist %>/.git{,*/}*'
          ]
        }]
      },
      server: '.tmp'
    },

    // Add vendor prefixed styles
    postcss: {
      options: {
        processors: [
          require('autoprefixer-core')({browsers: ['last 1 version']})
        ]
      },
      server: {
        options: {
          map: true
        },
        files: [{
          expand: true,
          cwd: '.tmp/assets/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/assets/styles/'
        }]
      },
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/assets/styles/',
          src: '{,*/}*.css',
          dest: '.tmp/assets/styles/'
        }]
      }
    },

    // Automatically inject Bower components into the app
    wiredep: {
      app: {
        src: ['<%= yeoman.app %>/index.html'],
        ignorePath:  /\.\.\//
      },
      test: {
        devDependencies: true,
        src: '<%= karma.unit.configFile %>',
        ignorePath:  /\.\.\//,
        fileTypes:{
          js: {
            block: /(([\s\t]*)\/{2}\s*?bower:\s*?(\S*))(\n|\r|.)*?(\/{2}\s*endbower)/gi,
              detect: {
                js: /'(.*\.js)'/gi
              },
              replace: {
                js: '\'{{filePath}}\','
              }
            }
          }
      }
    },

    // Renames files for browser caching purposes
    filerev: {
      dist: {
        src: [
          '<%= yeoman.dist %>/assets/fonts/*',
          '<%= yeoman.dist %>/assets/images/{,*/}*.{png,jpg,jpeg,gif,webp,svg}',
          '<%= yeoman.dist %>/assets/styles/{,*/}*.css',
          '<%= yeoman.dist %>/assets/svg/{,*/}*.{svg}',
          '<%= yeoman.dist %>/scripts/{,*/}*.js'
        ]
      }
    },

    // Reads HTML for usemin blocks to enable smart builds that automatically
    // concat, minify and revision files. Creates configurations in memory so
    // additional tasks can operate on them
    useminPrepare: {
      html: '<%= yeoman.app %>/index.html',
      options: {
        dest: '<%= yeoman.dist %>',
        flow: {
          html: {
            steps: {
              js: ['concat', 'uglifyjs'],
              css: ['cssmin']
            },
            post: {}
          }
        }
      }
    },

    // Performs rewrites based on filerev and the useminPrepare configuration
    usemin: {
      html: ['<%= yeoman.dist %>/{,*/}*.html'],
      css: ['<%= yeoman.dist %>/assets/styles/{,*/}*.css'],
      js: ['<%= yeoman.dist %>/scripts/{,*/}*.js'],
      options: {
        assetsDirs: [
          '<%= yeoman.dist %>',
          '<%= yeoman.dist %>/assets/fonts',
          '<%= yeoman.dist %>/assets/images',
          '<%= yeoman.dist %>/assets/styles',
          '<%= yeoman.dist %>/assets/svg'
        ],
        patterns: {
          js: [
            [/(images\/[^''""]*\.(png|jpg|jpeg|gif|webp))/g, 'Replacing references to images'],
            [/(svg\/[^''""]*\.(svg))/g, 'Replacing references to svg']
          ]
        }
      }
    },

    // The following *-min tasks will produce minified files in the dist folder
    // By default, your `index.html`'s <!-- Usemin block --> will take care of
    // minification. These next options are pre-configured if you do not wish
    // to use the Usemin blocks.
    // cssmin: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/assets/styles/main.css': [
    //         '.tmp/assets/styles/{,*/}*.css'
    //       ]
    //     }
    //   }
    // },
    // uglify: {
    //   dist: {
    //     files: {
    //       '<%= yeoman.dist %>/scripts/scripts.js': [
    //         '<%= yeoman.dist %>/scripts/scripts.js'
    //       ]
    //     }
    //   }
    // },
    // concat: {
    //   dist: {}
    // },

    imagemin: {
      dist: {
        files: [{
          expand: true,
          cwd: '<%= yeoman.app %>/assets/images',
          src: '{,*/}*.{png,jpg,jpeg,gif}',
          dest: '<%= yeoman.dist %>/assets/images'
        }]
      }
    },

    svgmin: {
      dist: {
        files: [{
          expand: true,
            cwd: '<%= yeoman.app %>/assets/svg',
            src: '{,*/}*.svg',
            dest: '<%= yeoman.dist %>/assets/svg'
        }]
      }
    },

    htmlmin: {
      dist: {
        options: {
          collapseWhitespace: true,
          conservativeCollapse: true,
          collapseBooleanAttributes: true,
          removeCommentsFromCDATA: true
        },
        files: [{
          expand: true,
          cwd: '<%= yeoman.dist %>',
          src: ['*.html'],
          dest: '<%= yeoman.dist %>'
        }]
      }
    },

    ngtemplates: {
      dist: {
        options: {
          module: 'dresdenjsioApp',
          htmlmin: '<%= htmlmin.dist.options %>',
          usemin: 'scripts/scripts.js'
        },
        cwd: '<%= yeoman.app %>',
        src: 'views/{,*/}*.html',
        dest: '.tmp/templateCache.js'
      }
    },

    // ng-annotate tries to make the code safe for minification automatically
    // by using the Angular long form for dependency injection.
    ngAnnotate: {
      dist: {
        files: [{
          expand: true,
          cwd: '.tmp/concat/scripts',
          src: '*.js',
          dest: '.tmp/concat/scripts'
        }]
      }
    },

    // Replace Google CDN references
    cdnify: {
      dist: {
        html: ['<%= yeoman.dist %>/*.html']
      }
    },

    // Copies remaining files to places other tasks can use
    copy: {
      dist: {
        files: [{
          expand: true,
          dot: true,
          cwd: '<%= yeoman.app %>',
          dest: '<%= yeoman.dist %>',
          src: [
            '.htaccess',
            '*.{ico,png,txt}',
            '*.html',
            'assets/presentations/{,*/}*.*',
            'assets/fonts/{,*/}*.*',
            'views/{,*/}*.*',
            'layouts/{,*/}*.*',
            'assets/images/{,*/}*.{webp}',
            'assets/svg/{,*/}*.*'
          ]
        }, {
          expand: true,
          cwd: '.tmp/assets/images',
          dest: '<%= yeoman.dist %>/assets/images',
          src: ['generated/*']
        }]
      },
      styles: {
        expand: true,
        cwd: '<%= yeoman.app %>/assets/styles',
        dest: '.tmp/assets/styles/',
        src: '{,*/}*.css'
      }
    },

    // Run some tasks in parallel to speed up the build process
    concurrent: {
      server: [
        'copy:styles'
      ],
      test: [
        'copy:styles'
      ],
      dist: [
        'copy:styles',
        'imagemin',
        //'svgmin'
      ]
    },

    // Test settings
    karma: {
      unit: {
        configFile: 'test/karma.conf.js',
        singleRun: true
      }
    }
  });

  grunt.registerTask('serve', 'Compile then start a connect web server', function (target) {
    if (target === 'dist') {
      return grunt.task.run(['build', 'connect:dist:keepalive']);
    }

    grunt.task.run([
      'clean:server',
      'wiredep',
      'concurrent:server',
      'postcss:server',
      'connect:livereload',
      'watch'
    ]);
  });

  grunt.registerTask('server', 'DEPRECATED TASK. Use the "serve" task instead', function (target) {
    grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
    grunt.task.run(['serve:' + target]);
  });

  grunt.registerTask('test', [
    'clean:server',
    'wiredep',
    'concurrent:test',
    'postcss',
    'connect:test',
    'karma'
  ]);

  grunt.registerTask('build', [
    'clean:dist',
    'wiredep',
    'useminPrepare',
    'concurrent:dist',
    'postcss',
    //'ngtemplates',
    'concat',
    'ngAnnotate',
    'copy:dist',
    //'cdnify',
    'cssmin',
    'uglify',
    'filerev',
    'usemin',
    'htmlmin'
  ]);

  grunt.registerTask('default', [
    'newer:jshint',
    'newer:jscs',
    'test',
    'build'
  ]);
};
<|endoftext|>


<commit_before>var assert = require('assert')
var convert = require('../chinese_convert')

describe('convert', function () {
  it('test cn2tw', function () {
    assert.equal(convert.cn2tw('简体转繁体功能测试'), '簡體轉繁體功能測試') // start travis ci
  })
  it('test tw2cn', function () {
    assert.equal(convert.tw2cn('繁體轉簡體功能測試'), '繁体转简体功能测试')
  })
})
<commit_msg>Update test.js<commit_after>var assert = require('assert')
var convert = require('../chinese_convert')

describe('convert', function () {
  it('test cn2tw', function () {
    assert.equal(convert.cn2tw('简体转繁体功能测试'), '體轉繁體功能測試') // start travis ci
  })
  it('test tw2cn', function () {
    assert.equal(convert.tw2cn('繁體轉簡體功能測試'), '繁体转简体功能测试')
  })
})
<|endoftext|>


<commit_before>'use strict';

/**
 * Module dependencies.
 */

var Memcached = require('memcached');
var parser = require('groan');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var oneDay = 8640000;

/**
 * Initialize memcached session middleware with `opts`:
 *
 * @param {Object} options
 *   - {Object} client    memcached client
 *   - {String} host      memcached connect host (with out options.client)
 *   - {Number} port      memcached connect port (with out options.client)
 *   - {String} socket    memcached connect socket (with out options.client)
 */
var MemcachedStore = module.exports = function (options) {
    if (!(this instanceof MemcachedStore)) {
        return new MemcachedStore(options);
    }
    EventEmitter.call(this);
    options = options || {};
    var client;

    if (!options.client) {
        var memcacheHost = (options.host || 'localhost') + ':' + (options.port || 11211);
        client = new Memcached(memcacheHost, options);
    } else {
        client = options.client;
    }

    options.pass && client.auth(options.pass, function (err) {
        if (err) {
            throw err;
        }
    });

    client.on('error', this.emit.bind(this, 'disconnect'));
    client.on('end', this.emit.bind(this, 'disconnect'));
    client.on('connect', this.emit.bind(this, 'connect'));

    this.client = client;
};

util.inherits(MemcachedStore, EventEmitter);

function getMem(sid, client) {
    return function(fn){
        client.get(sid, function (err, data) {
            if (err) return fn(err);
            console.log('typeof data ---> ', typeof data);
            console.log(data);
            if(typeof data === "string") {
//                console.log('GET string parser(data) -->>>',parser(data));
                data = parser(data);
            }
            console.log(data);

            data.passport = {
                "user":{
                    "user_id":data.person_info.email,
                    "email":data.person_id,
                    "state_id":data.person_info.stateID,
                    "city_id":data.person_info.cityID,
                    "name":data.person_name,
                    "avatar":data.person_info.photo
                }
            };
            fn(null, data);
        });
    }
};

function setMem(sid, sess, ttl, client) {
    return function(fn){
        client.set(sid, sess, ttl, function (err) {
            if (err) return fn(err);
            fn();
        });
    }
};

MemcachedStore.prototype.get = function *(sid) {
    var self = this;
    var data = yield getMem(sid, this.client);
    if (!data) {
        console.log('GET RETURN NULL');
        return null;
    }
    return data;
};

MemcachedStore.prototype.set = function *(sid, sess, ttl) {
    if(!ttl){
        ttl = oneDay;
    }
    if (typeof ttl === 'number') {
        ttl = ttl / 1000;
    }
    var data = yield setMem(sid, sess, ttl, this.client);
    return data;
};

MemcachedStore.prototype.destroy = function *(sid, sess) {
    this.client.del(sid, function (err) { /* stuff */ });
};
<commit_msg>deploy<commit_after>'use strict';

/**
 * Module dependencies.
 */

var Memcached = require('memcached');
var parser = require('groan');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var oneDay = 86400000;

/**
 * Initialize memcached session middleware:
 *
 * @param {Object} options
 *   - {Object} client    memcached client
 *   - {String} host      memcached connect host (with out options.client)
 *   - {Number} port      memcached connect port (with out options.client)
 */
var MemcachedStore = module.exports = function (options) {
    if (!(this instanceof MemcachedStore)) {
        return new MemcachedStore(options);
    }
    EventEmitter.call(this);
    options = options || {};
    var client;

    if (!options.client) {
        var memcachedHost = (options.host || 'localhost') + ':' + (options.port || 11211);
        client = new Memcached(memcachedHost, options);
    } else {
        client = options.client;
    }

    options.pass && client.auth(options.pass, function (err) {
        if (err) {
            throw err;
        }
    });

    client.on('error', this.emit.bind(this, 'disconnect'));
    client.on('end', this.emit.bind(this, 'disconnect'));
    client.on('connect', this.emit.bind(this, 'connect'));

    this.client = client;
};

util.inherits(MemcachedStore, EventEmitter);

function getMem(sid, client) {
    return function(fn){
        client.get(sid, function (err, data) {
            if (err) return fn(err);
            console.log('typeof data ---> ', typeof data);
            if(typeof data === "string") {
//                console.log('GET string parser(data) -->>>',parser(data));
                data = parser(data);
            }
            console.log(data);
            if(data.person_id){
                data.passport = {
                    "user":{
                        "user_id": (data.person_info)?data.person_info.email:'',
                        "email":data.person_id,
                        "state_id":(data.person_info)?data.person_info.stateID:0,
                        "city_id":(data.person_info)?data.person_info.cityID:0,
                        "name":data.person_name,
                        "avatar":(data.person_info)?data.person_info.photo:null
                    }
                };
            }
            fn(null, data);
        });
    }
};

function setMem(sid, sess, ttl, client) {
    return function(fn){
        client.set(sid, sess, ttl, function (err) {
            if (err) return fn(err);
            fn();
        });
    }
};

MemcachedStore.prototype.get = function *(sid) {
    var self = this;
    var data = yield getMem(sid, this.client);
    if (!data) {
        console.log('GET RETURN NULL');
        return null;
    }
    return data;
};

MemcachedStore.prototype.set = function *(sid, sess, ttl) {
    if(!ttl){
        ttl = oneDay;
    }
    console.log(ttl);
    if (typeof ttl === 'number') {
        ttl = ttl / 1000;
    }
    var data = yield setMem(sid, sess, ttl, this.client);
    return data;
};

MemcachedStore.prototype.destroy = function *(sid, sess) {
    this.client.del(sid, function (err) { /* stuff */ });
};
<|endoftext|>