<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Node, Shaders } from 'gl-react';
import { Surface } from 'gl-react-dom';
import Loader from '../Loader/Loader';

class Fractal extends Component {
  static propTypes = {
    width: PropTypes.number,
    height: PropTypes.number,
    uniforms: PropTypes.object,
    shader: PropTypes.string,
    quality: PropTypes.number,
    onSurfaceRef: PropTypes.func,
    onDraw: PropTypes.func
  };
  static defaultProps = {
    quality: 1,
    onDraw: () => {}
  };

  state = {
    shaderDef: {}
  };

  async loadShader(shaderKey) {
    // TODO Shaders could be cached (no need to load and create if it's already there)
    const hostname = window.location.hostname;
    const response = await fetch(
      `http://${hostname}:3001/compile/${shaderKey}`,
      { cache: 'no-cache' }
    );
    const fragmentShader = await response.text();

    const shaders = await Shaders.create({
      [shaderKey]: {
        frag: fragmentShader
      }
    });
    const shaderDef = shaders[shaderKey];
    this.setState({ shader: shaderKey, shaderDef });
  }

  async componentDidMount() {
    const { shader } = this.props;
    await this.loadShader(shader);
  }

  async componentDidUpdate() {
    const { shader } = this.props;
    await this.loadShader(shader);
  }

  render() {
    const { width, height, uniforms, quality } = this.props;
    const { shaderDef } = this.state;

    // TODO Would be nice to display different states: Loading, compiling, rendering

    // If shaderID is not present yet, shader might still be compiling
    // or if page was refreshed, ID is there but it anyway might not be compiled yet
    const shaderExists = Shaders.getShortName({ id: shaderDef.id }) !== '???';
    if (!shaderDef || !shaderExists) {
      return <Loader />;
    }

    // If the shader changes, we shouldn't render anything before new shader has been loaded & compiled
    // Otherwise we could end up briefly rendering previous shader with new uniforms
    if (this.props.shader !== this.state.shader) {
      return <Loader />;
    }

    // Append some constants to the uniforms
    const qlty = Math.min(Math.max(quality, 1), 5);
    const uniformValues = Object.assign({}, uniforms, {
      size: [width, height],
      outputSize: [width / qlty, height / qlty]
    });

    return (
      <Surface
        width={width}
        height={height}
        webglContextAttributes={{ preserveDrawingBuffer: true }}
        ref={this.props.onSurfaceRef}
      >
        <Node
          shader={shaderDef}
          uniforms={uniformValues}
          onDraw={this.props.onDraw}
        />
      </Surface>
    );
  }
}

export default Fractal;
<commit_msg>Fix infinite rendering loop<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Node, Shaders } from 'gl-react';
import { Surface } from 'gl-react-dom';
import Loader from '../Loader/Loader';

class Fractal extends Component {
  static propTypes = {
    width: PropTypes.number,
    height: PropTypes.number,
    uniforms: PropTypes.object,
    shader: PropTypes.string,
    quality: PropTypes.number,
    onSurfaceRef: PropTypes.func,
    onDraw: PropTypes.func
  };
  static defaultProps = {
    quality: 1,
    onDraw: () => {}
  };

  state = {
    shaderDef: {}
  };

  async loadShader(shaderKey) {
    // TODO Shaders could be cached (no need to load and create if it's already there)
    const hostname = window.location.hostname;
    const response = await fetch(
      `http://${hostname}:3001/compile/${shaderKey}`,
      { cache: 'no-cache' }
    );
    const fragmentShader = await response.text();

    const shaders = await Shaders.create({
      [shaderKey]: {
        frag: fragmentShader
      }
    });
    const shaderDef = shaders[shaderKey];
    this.setState({ shader: shaderKey, shaderDef });
  }

  async componentDidMount() {
    const { shader } = this.props;
    await this.loadShader(shader);
  }

  async componentDidUpdate(prevProps) {
    if (this.props.shader !== prevProps.shader) {
      await this.loadShader(this.props.shader);
    }
  }

  render() {
    const { width, height, uniforms, quality } = this.props;
    const { shaderDef } = this.state;

    // TODO Would be nice to display different states: Loading, compiling, rendering

    // If shaderID is not present yet, shader might still be compiling
    // or if page was refreshed, ID is there but it anyway might not be compiled yet
    const shaderExists = Shaders.getShortName({ id: shaderDef.id }) !== '???';
    if (!shaderDef || !shaderExists) {
      return <Loader />;
    }

    // If the shader changes, we shouldn't render anything before new shader has been loaded & compiled
    // Otherwise we could end up briefly rendering previous shader with new uniforms
    if (this.props.shader !== this.state.shader) {
      return <Loader />;
    }

    // Append some constants to the uniforms
    const qlty = Math.min(Math.max(quality, 1), 5);
    const uniformValues = Object.assign({}, uniforms, {
      size: [width, height],
      outputSize: [width / qlty, height / qlty]
    });

    return (
      <Surface
        width={width}
        height={height}
        webglContextAttributes={{ preserveDrawingBuffer: true }}
        ref={this.props.onSurfaceRef}
      >
        <Node
          shader={shaderDef}
          uniforms={uniformValues}
          onDraw={this.props.onDraw}
        />
      </Surface>
    );
  }
}

export default Fractal;
<|endoftext|>


<commit_before>import Ember from 'ember';
import ENV from 'analytics-dashboard/config/environment';
import isUrl from 'npm:is-url';

var isHTTPURL = function(value) {
    var httpURL = /^https?/;
    return httpURL.test(value.trim()) && isUrl(value);
};

export default Ember.Component.extend({

    showJSON: false,

    objectData: Ember.computed(function() {
        return this.get('data');
    }),

    dataAsString: Ember.computed(function() {
        var data = this.get('data');
        return JSON.stringify(data, null, '    ');
    }),

    identifierURLs: Ember.computed('objectData._source.identifiers', function() {
        return this.get('objectData')._source.identifiers.filter(function(id) {
            return isHTTPURL(id);
        });
    }),

    dataUrl: Ember.computed(function() {
        // Use the doi url to link to the resource, otherwise use the first http url
        var data = this.get('objectData');
        var identifiers = data._source.identifiers;
        var httpUrl = null;
        for (var id of identifiers) {
            if (id.includes('doi')) {
                return id;
            }
            else if (!httpUrl && id.includes('http')) {
                httpUrl = id;
            }
        }
        return httpUrl;
    }),

    funders: Ember.computed('objectData._source.lists.funders', function() {
        this.get('objectData')._source.lists.funders.map((funder) => {
            let total = funder.awards.reduce((total, award) => total + award.amount)
            let formattedTotal = total.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
            return {name: funder.name, awardTotal: formattedTotal}
        })
    }),

    init(){
        this._super(...arguments);
        let data = this.processData(this.get('data'));
        this.set('data', data);
    },

    processData (data) {
            let datum = data.hits.hits[0];
            var options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
            options.timeZone = 'UTC';
            options.timeZoneName = 'short'
            if (datum._source.date) {
                datum["_source"]["date"] = (new Date(datum["_source"]["date"])).toLocaleDateString('en-US', options);
            }
            if (datum._source.date_created) {
                datum["_source"]["date_created"] = (new Date(datum["_source"]["date_created"])).toLocaleDateString('en-US', options)
            }
            if (datum._source.date_modified) {
                datum["_source"]["date_modified"] = (new Date(datum["_source"]["date_modified"])).toLocaleDateString('en-US', options)
            }
            if (datum._source.date_published) {
                datum["_source"]["date_published"] = (new Date(datum["_source"]["date_published"])).toLocaleDateString('en-US', options)
            }
            if (datum._source.date_updated) {
                datum["_source"]["date_updated"] = (new Date(datum["_source"]["date_updated"])).toLocaleDateString('en-US', options)
            }
            return datum;
    },

    actions: {

        transitionToFacet(facetDash, parameterName, parameter) {
            let queryParams = {
                id: undefined
            };
            queryParams[parameterName] = parameter;
            this.attrs.transitionToFacet(facetDash, queryParams);
        },

        transitionToSHARE(item) {
              window.location.href = item.url;
        },

        transitionToViewAll(item) {
            this.attrs.transitionToFacet(item.dataType, item);
        }

    }

});
<commit_msg>Fix funder/award display on object detail page<commit_after>import Ember from 'ember';
import ENV from 'analytics-dashboard/config/environment';
import isUrl from 'npm:is-url';

var isHTTPURL = function(value) {
    var httpURL = /^https?/;
    return httpURL.test(value.trim()) && isUrl(value);
};

export default Ember.Component.extend({

    showJSON: false,

    objectData: Ember.computed(function() {
        return this.get('data');
    }),

    dataAsString: Ember.computed(function() {
        var data = this.get('data');
        return JSON.stringify(data, null, '    ');
    }),

    identifierURLs: Ember.computed('objectData._source.identifiers', function() {
        return this.get('objectData')._source.identifiers.filter(function(id) {
            return isHTTPURL(id);
        });
    }),

    dataUrl: Ember.computed(function() {
        // Use the doi url to link to the resource, otherwise use the first http url
        var data = this.get('objectData');
        var identifiers = data._source.identifiers;
        var httpUrl = null;
        for (var id of identifiers) {
            if (id.includes('doi')) {
                return id;
            }
            else if (!httpUrl && id.includes('http')) {
                httpUrl = id;
            }
        }
        return httpUrl;
    }),

    funders: Ember.computed('objectData._source.lists.funders', function() {
        var funders = this.get('objectData')._source.lists.funders;
        if (funders) {
            return funders.map((funder) => {
                let total = funder.awards.reduce((total, award) => {
                    return total + award.amount;
                }, 0);
                let formattedTotal = total.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
                return {name: funder.name, awardTotal: formattedTotal}
            })
        }
    }),

    init(){
        this._super(...arguments);
        let data = this.processData(this.get('data'));
        this.set('data', data);
    },

    processData (data) {
            let datum = data.hits.hits[0];
            var options = { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' };
            options.timeZone = 'UTC';
            options.timeZoneName = 'short'
            if (datum._source.date) {
                datum["_source"]["date"] = (new Date(datum["_source"]["date"])).toLocaleDateString('en-US', options);
            }
            if (datum._source.date_created) {
                datum["_source"]["date_created"] = (new Date(datum["_source"]["date_created"])).toLocaleDateString('en-US', options)
            }
            if (datum._source.date_modified) {
                datum["_source"]["date_modified"] = (new Date(datum["_source"]["date_modified"])).toLocaleDateString('en-US', options)
            }
            if (datum._source.date_published) {
                datum["_source"]["date_published"] = (new Date(datum["_source"]["date_published"])).toLocaleDateString('en-US', options)
            }
            if (datum._source.date_updated) {
                datum["_source"]["date_updated"] = (new Date(datum["_source"]["date_updated"])).toLocaleDateString('en-US', options)
            }
            return datum;
    },

    actions: {

        transitionToFacet(facetDash, parameterName, parameter) {
            let queryParams = {
                id: undefined
            };
            queryParams[parameterName] = parameter;
            this.attrs.transitionToFacet(facetDash, queryParams);
        },

        transitionToSHARE(item) {
              window.location.href = item.url;
        },

        transitionToViewAll(item) {
            this.attrs.transitionToFacet(item.dataType, item);
        }

    }

});
<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
        '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' +
        '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
        ' Licensed <%= pkg.license %> */'
    },
    lint: {
      files: ['grunt.js', 'jquery.kinetic.js']
    },
    qunit: {
      files: ['test/specs/**/*.html']
    },
    min: {
      dist: {
        src: ['<banner:meta.banner>', 'jquery.kinetic.js'],
        dest: 'jquery.kinetic.min.js'
      }
    },
    watch: {
      files: '<config:lint.files>',
      tasks: 'lint qunit'
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        browser: true
      },
      globals: {
        jQuery: true
      }
    },
    uglify: {},
    vows: {
        local: {
            files: ["test/local.vows.js"],
            // String {spec|json|dot-matrix|xunit|tap}
            // defaults to "dot-matrix"
            reporter: "spec"
        },
        sauce: {
            files: ["test/sauce.vows.js"],
            // String {spec|json|dot-matrix|xunit|tap}
            // defaults to "dot-matrix"
            reporter: "spec"
        }
    },
    "string-replace": {
      version: {
        files: {
          "jquery.kinetic.js": "jquery.kinetic.js"
        },
        options: {
          replacements: [{
            pattern: /jQuery\.kinetic v\d\.\d\.\d/g,
            replacement: "jQuery.kinetic v<%= pkg.version %>"
          }]
        }
      }
    }
  });

  // Load tasks
  grunt.loadNpmTasks('grunt-vows');
  grunt.loadNpmTasks('grunt-bump');
  grunt.loadNpmTasks('grunt-string-replace');

  // Default task.
  grunt.registerTask('default', 'lint qunit');
  grunt.registerTask('selenium', 'vows:local');
  grunt.registerTask('sauce', 'vows:sauce');
  grunt.registerTask('minor', 'bump:minor');
  grunt.registerTask('patch', 'bump');
  grunt.registerTask('release', 'default string-replace:version min');

};
<commit_msg>use internal grunt server for tests<commit_after>/*global module:false*/
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
        '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
        '<%= pkg.homepage ? "* " + pkg.homepage + "\n" : "" %>' +
        '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
        ' Licensed <%= pkg.license %> */'
    },
    lint: {
      files: ['grunt.js', 'jquery.kinetic.js']
    },
    server: {
      port: 9999,
      base: '.'
    },
    qunit: {
      files: ['test/specs/**/*.html']
    },
    min: {
      dist: {
        src: ['<banner:meta.banner>', 'jquery.kinetic.js'],
        dest: 'jquery.kinetic.min.js'
      }
    },
    watch: {
      files: '<config:lint.files>',
      tasks: 'lint qunit'
    },
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        boss: true,
        eqnull: true,
        browser: true
      },
      globals: {
        jQuery: true
      }
    },
    uglify: {},
    vows: {
        local: {
            files: ["test/local.vows.js"],
            // String {spec|json|dot-matrix|xunit|tap}
            // defaults to "dot-matrix"
            reporter: "spec"
        },
        sauce: {
            files: ["test/sauce.vows.js"],
            // String {spec|json|dot-matrix|xunit|tap}
            // defaults to "dot-matrix"
            reporter: "spec"
        }
    },
    "string-replace": {
      version: {
        files: {
          "jquery.kinetic.js": "jquery.kinetic.js"
        },
        options: {
          replacements: [{
            pattern: /jQuery\.kinetic v\d\.\d\.\d/g,
            replacement: "jQuery.kinetic v<%= pkg.version %>"
          }]
        }
      }
    }
  });

  // Load tasks
  grunt.loadNpmTasks('grunt-vows');
  grunt.loadNpmTasks('grunt-bump');
  grunt.loadNpmTasks('grunt-string-replace');

  // Default task.
  grunt.registerTask('default', 'lint server qunit');
  grunt.registerTask('selenium', 'vows:local');
  grunt.registerTask('sauce', 'vows:sauce');
  grunt.registerTask('minor', 'bump:minor');
  grunt.registerTask('patch', 'bump');
  grunt.registerTask('release', 'default string-replace:version min');

};
<|endoftext|>


<commit_before>/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View
} from 'react-native'
import {  Main } from './Main'

export default class Example extends Component {
  render() {
    return (
      <Main />
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
});

AppRegistry.registerComponent('Example', () => Example);
<commit_msg>Update index.ios.js<commit_after>/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import { AppRegistry } from 'react-native'
import { Main } from './Main'

export default class Example extends Component {
  render() {
    return (
      <Main />
    )
  }
}

AppRegistry.registerComponent('Example', () => Example);
<|endoftext|>


<commit_before>'use strict';

function defn(node, state, log) {
    var elems = node.elems;
    if ( elems.length >= 2 ) {
        var second = elems[1];
        if ( second.type === 'symbol' ) {
            var name = second.name;
            // one major drawback (for now):
            //   ignoring namespaces
            if ( state.is_bound(name) ) {
                log.issue({'severity': 'warning', 'name': 'defn',
                           'position': second.pos, 'message': 'redefining symbol',
                           'symbol': name, 'original position': state.position(name)});
            } else {
                state.define(name, second.pos);
            }
        } else {
            log.issue({'name': 'defn', 'severity': 'error', 'position': second.pos,
                       'message': '2nd arg must be a symbol'});
        }
    }
}

var macros = {
    'defn': defn,
    'defn-': defn,
    'defmacro': defn
};

function macro(node, state, log) {
    if ( node.elems.length === 0 ) {
        return;
    }
    var first = node.elems[0];
    if ( ( first.type !== 'symbol'            ) ||
         ( first.ns !== null                  ) ||
         ( !macros.hasOwnProperty(first.name) ) ) {
        return;
    }
    console.log('macro: ' + first.name + ' ...');
    return macros[first.name](node, state, log);
}

module.exports = {
    'macro': macro,

    'defn'      : defn,
    'defn-'     : defn,
    'defmacro'  : defn
};

<commit_msg>rough stabs at let/fn/loop macros (to be finished later)<commit_after>'use strict';

/*
function let_(node, state, log) {
    num_args('let', 2, error, null, null, node, log);
    if ( node.elems.length === 2 ) {
        log.push(warning('let', 'missing body forms', node.pos, {}));
    }
    // TODO this is going to become part of the 'binding forms' check
    if ( ( node.elems.length >= 2 ) && ( node.elems[1].type !== 'vector' ) ) {
        log.push(error('let', '2nd arg must be a vector', node.pos, {}));
    }
}

function loop(node, state, log) {
    num_args('loop', 2, error, null, null, node, log);
    if ( node.elems.length === 2 ) {
        log.push(warning('loop', 'missing body forms', node.pos, {}));
    }
    // TODO this is going to become part of the 'binding forms' check
    if ( ( node.elems.length >= 2 ) && ( node.elems[1].type !== 'vector' ) ) {
        log.push(error('loop', '2nd arg must be a vector', node.pos, {}));
    }
}

function fn(node, state, log) {
    // TODO
}
*/

function defn(node, state, log) {
    var elems = node.elems;
    if ( elems.length >= 2 ) {
        var second = elems[1];
        if ( second.type === 'symbol' ) {
            var name = second.name;
            // one major drawback (for now):
            //   ignoring namespaces
            if ( state.is_bound(name) ) {
                log.issue({'severity': 'warning', 'name': 'defn',
                           'position': second.pos, 'message': 'redefining symbol',
                           'symbol': name, 'original position': state.position(name)});
            } else {
                state.define(name, second.pos);
            }
        } else {
            log.issue({'name': 'defn', 'severity': 'error', 'position': second.pos,
                       'message': '2nd arg must be a symbol'});
        }
    }
}

var macros = {
    'defn': defn,
    'defn-': defn,
    'defmacro': defn
};

function macro(node, state, log) {
    if ( node.elems.length === 0 ) {
        return;
    }
    var first = node.elems[0];
    if ( ( first.type !== 'symbol'            ) ||
         ( first.ns !== null                  ) ||
         ( !macros.hasOwnProperty(first.name) ) ) {
        return;
    }
    console.log('macro: ' + first.name + ' ...');
    return macros[first.name](node, state, log);
}

module.exports = {
    'macro': macro,

    'defn'      : defn,
    'defn-'     : defn,
    'defmacro'  : defn
};

<|endoftext|>


<commit_before>/**
 * @fileOverview HistoryCtrl angular controller
 */

define(['./module', 'bitcoinjs-lib'], function (controllers, Bitcoin) {
  'use strict';
  controllers.controller('HistoryCtrl', ['$scope', '$timeout', 'toaster', function($scope, $timeout, toaster) {

  // History

  $scope.pocketName = "All Pockets";
  $scope.pocket = {index: undefined, name: 'All Pockets', mpk: undefined, addresses: $scope.allAddresses};
  $scope.isAll = true;
  $scope.selectPocket = function(pocket, pocketIndex) {
      if (pocket === undefined) {
          $scope.pocket.name = "All Pockets";
          $scope.pocket.index = undefined;
          $scope.pocket.mpk = undefined;
          $scope.pocket.stealth = undefined;
          $scope.pocket.addresses = $scope.allAddresses;
          $scope.isAll = true;
      } else {
          $scope.pocket.index = $scope.identity.wallet.pockets.indexOf(pocket);
          $scope.pocket.name = pocket;
          var walletAddress = $scope.identity.wallet.getAddress([$scope.pocket.index]);
          if (!walletAddress.mpk) {
              // derive mpk here for now so we can show as master address
	      var mpKey = Bitcoin.HDWallet.fromBase58($scope.identity.wallet.mpk);
              var childKey = mpKey.derive($scope.pocket.index);
              walletAddress.mpk = childKey.toBase58(false);
              $scope.identity.wallet.store.save();
          }
          $scope.pocket.mpk = walletAddress.mpk;
          $scope.pocket.stealth = walletAddress.stealth;
          $scope.pocket.addresses = $scope.addresses[$scope.pocket.index];
          $scope.isAll = false;
      }
      $scope.selectedPocket = pocketIndex;
      $scope.balance = $scope.identity.wallet.getBalance(pocket);
  }

  // Send

  $scope.send = {recipient: '', amount: 0.2, fee: 0.00002};

  $scope.sendBitcoins = function() {
      // get a free change address
      var changeAddress = $scope.getChangeAddress();

      // prepare amounts
      var satoshis = 100000000;
      var amount = $scope.send.amount * satoshis;
      var fee = $scope.send.fee * satoshis;

      // prepare the transaction
      $scope.identity.wallet.sendBitcoins($scope.send.recipient,
                                          changeAddress,
                                          amount,
                                          fee,
                                          $scope.send.password);
      // this should actually be a starting note, but we don't have a finishing callback yet.
      // we can also use something to show radar progress
      toaster.pop('success', 'Bitcoins sent', 'Sent ' + (fee + amount) + ' satoshis');
  }

  // Pockets
  $scope.newPocketName = '';
  $scope.creatingPocket = false;
  $scope.createPocket = function() {
    if ($scope.creatingPocket) {
      if ($scope.newPocketName) {
          $scope.identity.wallet.createPocket($scope.newPocketName);
          $scope.identity.wallet.createPocket($scope.newPocketName+'-change');
          $scope.selectPocket($scope.newPocketName, $scope.identity.wallet.pockets.length-2);
          $scope.newPocketName = '';
      }
    } else {
      // wait a bit since we can't focus till the element is shown
      $timeout(function() {
        document.getElementById('pocketNameInput').focus()
      });
    }
    $scope.creatingPocket = !$scope.creatingPocket;
  }

}]);
});
<commit_msg>Removed duplicated code from history.<commit_after>/**
 * @fileOverview HistoryCtrl angular controller
 */

define(['./module', 'bitcoinjs-lib'], function (controllers, Bitcoin) {
  'use strict';
  controllers.controller('HistoryCtrl', ['$scope', '$timeout', 'toaster', function($scope, $timeout, toaster) {

  // History

  $scope.pocketName = "All Pockets";
  $scope.pocket = {index: undefined, name: 'All Pockets', mpk: undefined, addresses: $scope.allAddresses};
  $scope.isAll = true;
  $scope.selectPocket = function(pocket, pocketIndex) {
      if (pocket === undefined) {
          $scope.pocket.name = "All Pockets";
          $scope.pocket.index = undefined;
          $scope.pocket.mpk = undefined;
          $scope.pocket.stealth = undefined;
          $scope.pocket.addresses = $scope.allAddresses;
          $scope.isAll = true;
      } else {
          $scope.pocket.index = $scope.identity.wallet.pockets.indexOf(pocket);
          $scope.pocket.name = pocket;
          var walletAddress = $scope.identity.wallet.getAddress([$scope.pocket.index]);
          if (!walletAddress.mpk) {
              // derive mpk here for now so we can show as master address
	      var mpKey = Bitcoin.HDWallet.fromBase58($scope.identity.wallet.mpk);
              var childKey = mpKey.derive($scope.pocket.index);
              walletAddress.mpk = childKey.toBase58(false);
              $scope.identity.wallet.store.save();
          }
          $scope.pocket.mpk = walletAddress.mpk;
          $scope.pocket.stealth = walletAddress.stealth;
          $scope.pocket.addresses = $scope.addresses[$scope.pocket.index];
          $scope.isAll = false;
      }
      $scope.selectedPocket = pocketIndex;
      $scope.balance = $scope.identity.wallet.getBalance(pocket);
  }

  // Pockets
  $scope.newPocketName = '';
  $scope.creatingPocket = false;
  $scope.createPocket = function() {
    if ($scope.creatingPocket) {
      if ($scope.newPocketName) {
          $scope.identity.wallet.createPocket($scope.newPocketName);
          $scope.identity.wallet.createPocket($scope.newPocketName+'-change');
          $scope.selectPocket($scope.newPocketName, $scope.identity.wallet.pockets.length-2);
          $scope.newPocketName = '';
      }
    } else {
      // wait a bit since we can't focus till the element is shown
      $timeout(function() {
        document.getElementById('pocketNameInput').focus()
      });
    }
    $scope.creatingPocket = !$scope.creatingPocket;
  }

}]);
});
<|endoftext|>


<commit_before>var fs = require('fs'),
    events = require('events'),
    buffer = require('buffer'),
    http = require('http'),
    url = require('url'),
    path = require('path');

this.version = [0, 6, 0];

var mime = require('./node-static/mime');
var util = require('./node-static/util');

// In-memory file store
this.store = {};
this.indexStore = {};

this.Server = function (root, options) {
    if (root && (typeof(root) === 'object')) { options = root, root = null }

    this.root    = path.resolve(root || '.');
    this.options = options || {};
    this.cache   = 3600;

    this.defaultHeaders  = {};
    this.options.headers = this.options.headers || {};

    if ('cache' in this.options) {
        if (typeof(this.options.cache) === 'number') {
            this.cache = this.options.cache;
        } else if (! this.options.cache) {
            this.cache = false;
        }
    }

    if ('serverInfo' in this.options) {
        this.serverInfo = this.options.serverInfo.toString();
    } else {
        this.serverInfo = 'node-static/' + exports.version.join('.');
    }

    this.defaultHeaders['Server'] = this.serverInfo;

    if (this.cache !== false) {
        this.defaultHeaders['Cache-Control'] = 'max-age=' + this.cache;
    }

    for (var k in this.defaultHeaders) {
        this.options.headers[k] = this.options.headers[k] ||
                                  this.defaultHeaders[k];
    }
};

this.Server.prototype.serveDir = function (pathname, req, res, finish) {
    var htmlIndex = path.join(pathname, 'index.html'),
        that = this;

    fs.stat(htmlIndex, function (e, stat) {
        if (!e) {
            that.respond(null, 200, {}, [htmlIndex], stat, req, res, finish);
        } else {
            if (pathname in exports.store) {
                streamFiles(exports.indexStore[pathname].files);
            } else {
                // Stream a directory of files as a single file.
                fs.readFile(path.join(pathname, 'index.json'), function (e, contents) {
                    if (e) { return finish(404, {}) }
                    var index = JSON.parse(contents);
                    exports.indexStore[pathname] = index;
                    streamFiles(index.files);
                });
            }
        }
    });
    function streamFiles(files) {
        util.mstat(pathname, files, function (e, stat) {
            that.respond(pathname, 200, {}, files, stat, req, res, finish);
        });
    }
};
this.Server.prototype.serveFile = function (pathname, status, headers, req, res) {
    var that = this;
    var promise = new(events.EventEmitter);

    pathname = this.resolve(pathname);

    fs.stat(pathname, function (e, stat) {
        if (e) {
            return promise.emit('error', e);
        }
        that.respond(null, status, headers, [pathname], stat, req, res, function (status, headers) {
            that.finish(status, headers, req, res, promise);
        });
    });
    return promise;
};
this.Server.prototype.finish = function (status, headers, req, res, promise, callback) {
    var result = {
        status:  status,
        headers: headers,
        message: http.STATUS_CODES[status]
    };

    headers['Server'] = this.serverInfo;

    if (!status || status >= 400) {
        if (callback) {
            callback(result);
        } else {
            if (promise.listeners('error').length > 0) {
                promise.emit('error', result);
            }
            res.writeHead(status, headers);
            res.end();
        }
    } else {
        // Don't end the request here, if we're streaming;
        // it's taken care of in `prototype.stream`.
        if (status !== 200 || req.method !== 'GET') {
            res.writeHead(status, headers);
            res.end();
        }
        callback && callback(null, result);
        promise.emit('success', result);
    }
};

this.Server.prototype.servePath = function (pathname, status, headers, req, res, finish) {
    var that = this,
        promise = new(events.EventEmitter);

    pathname = this.resolve(pathname);

    // Only allow GET and HEAD requests
    if (req.method !== 'GET' && req.method !== 'HEAD') {
        finish(405, { 'Allow': 'GET, HEAD' });
        return promise;
    }

    // Make sure we're not trying to access a
    // file outside of the root.
    if (pathname.indexOf(that.root) === 0) {
        fs.stat(pathname, function (e, stat) {
            if (e) {
                finish(404, {});
            } else if (stat.isFile()) {      // Stream a single file.
                that.respond(null, status, headers, [pathname], stat, req, res, finish);
            } else if (stat.isDirectory()) { // Stream a directory of files.
                that.serveDir(pathname, req, res, finish);
            } else {
                finish(400, {});
            }
        });
    } else {
        // Forbidden
        finish(403, {});
    }
    return promise;
};
this.Server.prototype.resolve = function (pathname) {
    return path.resolve(path.join(this.root, pathname));
};
this.Server.prototype.serve = function (req, res, callback) {
    var that = this,
        promise = new(events.EventEmitter);

    var pathname = decodeURI(url.parse(req.url).pathname);

    var finish = function (status, headers) {
        that.finish(status, headers, req, res, promise, callback);
    };

    process.nextTick(function () {
        that.servePath(pathname, 200, {}, req, res, finish).on('success', function (result) {
            promise.emit('success', result);
        }).on('error', function (err) {
            promise.emit('error');
        });
    });
    if (! callback) { return promise }
};

this.Server.prototype.respond = function (pathname, status, _headers, files, stat, req, res, finish) {
    var mtime   = Date.parse(stat.mtime),
        key     = pathname || files[0],
        headers = {};

    // Copy default headers
    for (var k in this.options.headers) {  headers[k] = this.options.headers[k] }

    headers['ETag']          = JSON.stringify([stat.ino, stat.size, mtime].join('-'));
    headers['Date']          = new(Date)().toUTCString();
    headers['Last-Modified'] = new(Date)(stat.mtime).toUTCString();

    // Conditional GET
    // If the "If-Modified-Since" or "If-None-Match" headers
    // match the conditions, send a 304 Not Modified.
    if (req.headers['if-none-match'] === headers['ETag'] ||
        Date.parse(req.headers['if-modified-since']) >= mtime) {
        finish(304, headers);
    } else {
        var fileExtension = path.extname(files[0]).slice(1).toLowerCase();
        headers['Content-Length'] = stat.size;
        headers['Content-Type']   = mime.contentTypes[fileExtension] ||
                                   'application/octet-stream';

        for (var k in _headers) { headers[k] = _headers[k] }

        res.writeHead(status, headers);

        if (req.method === 'HEAD') {
            finish(200, headers);
            return;
        }

        // If the file was cached and it's not older
        // than what's on disk, serve the cached version.
        if (this.cache && (key in exports.store) &&
            exports.store[key].stat.mtime >= stat.mtime) {
            res.end(exports.store[key].buffer);
            finish(status, headers);
        } else {
            this.stream(pathname, files, new(buffer.Buffer)(stat.size), res, function (e, buffer) {
                if (e) { return finish(500, {}) }
                exports.store[key] = {
                    stat:      stat,
                    buffer:    buffer,
                    timestamp: Date.now()
                };
                finish(status, headers);
            });
        }
    }
};

this.Server.prototype.stream = function (pathname, files, buffer, res, callback) {
    (function streamFile(files, offset) {
        var file = files.shift();

        if (file) {
            file = file[0] === '/' ? file : path.join(pathname || '.', file);

            // Stream the file to the client
            fs.createReadStream(file, {
                flags: 'r',
                mode: 0666
            }).on('data', function (chunk) {
                chunk.copy(buffer, offset);
                offset += chunk.length;
            }).on('close', function () {
                streamFile(files, offset);
            }).on('error', function (err) {
                callback(err);
                console.error(err);
            }).pipe(res, { end: false });
        } else {
            res.end();
            callback(null, buffer, offset);
        }
    })(files.slice(0), 0);
};
<commit_msg>minor fix: handle mstat err, check indexstore instead of store<commit_after>var fs = require('fs'),
    events = require('events'),
    buffer = require('buffer'),
    http = require('http'),
    url = require('url'),
    path = require('path');

this.version = [0, 6, 0];

var mime = require('./node-static/mime');
var util = require('./node-static/util');

// In-memory file store
this.store = {};
this.indexStore = {};

this.Server = function (root, options) {
    if (root && (typeof(root) === 'object')) { options = root, root = null }

    this.root    = path.resolve(root || '.');
    this.options = options || {};
    this.cache   = 3600;

    this.defaultHeaders  = {};
    this.options.headers = this.options.headers || {};

    if ('cache' in this.options) {
        if (typeof(this.options.cache) === 'number') {
            this.cache = this.options.cache;
        } else if (! this.options.cache) {
            this.cache = false;
        }
    }

    if ('serverInfo' in this.options) {
        this.serverInfo = this.options.serverInfo.toString();
    } else {
        this.serverInfo = 'node-static/' + exports.version.join('.');
    }

    this.defaultHeaders['Server'] = this.serverInfo;

    if (this.cache !== false) {
        this.defaultHeaders['Cache-Control'] = 'max-age=' + this.cache;
    }

    for (var k in this.defaultHeaders) {
        this.options.headers[k] = this.options.headers[k] ||
                                  this.defaultHeaders[k];
    }
};

this.Server.prototype.serveDir = function (pathname, req, res, finish) {
    var htmlIndex = path.join(pathname, 'index.html'),
        that = this;

    fs.stat(htmlIndex, function (e, stat) {
        if (!e) {
            that.respond(null, 200, {}, [htmlIndex], stat, req, res, finish);
        } else {
            if (pathname in exports.indexStore) {
                streamFiles(exports.indexStore[pathname].files);
            } else {
                // Stream a directory of files as a single file.
                fs.readFile(path.join(pathname, 'index.json'), function (e, contents) {
                    if (e) { return finish(404, {}) }
                    var index = JSON.parse(contents);
                    exports.indexStore[pathname] = index;
                    streamFiles(index.files);
                });
            }
        }
    });
    function streamFiles(files) {
        util.mstat(pathname, files, function (e, stat) {
            if (e) { return finish(404, {}) }
            that.respond(pathname, 200, {}, files, stat, req, res, finish);
        });
    }
};
this.Server.prototype.serveFile = function (pathname, status, headers, req, res) {
    var that = this;
    var promise = new(events.EventEmitter);

    pathname = this.resolve(pathname);

    fs.stat(pathname, function (e, stat) {
        if (e) {
            return promise.emit('error', e);
        }
        that.respond(null, status, headers, [pathname], stat, req, res, function (status, headers) {
            that.finish(status, headers, req, res, promise);
        });
    });
    return promise;
};
this.Server.prototype.finish = function (status, headers, req, res, promise, callback) {
    var result = {
        status:  status,
        headers: headers,
        message: http.STATUS_CODES[status]
    };

    headers['Server'] = this.serverInfo;

    if (!status || status >= 400) {
        if (callback) {
            callback(result);
        } else {
            if (promise.listeners('error').length > 0) {
                promise.emit('error', result);
            }
            res.writeHead(status, headers);
            res.end();
        }
    } else {
        // Don't end the request here, if we're streaming;
        // it's taken care of in `prototype.stream`.
        if (status !== 200 || req.method !== 'GET') {
            res.writeHead(status, headers);
            res.end();
        }
        callback && callback(null, result);
        promise.emit('success', result);
    }
};

this.Server.prototype.servePath = function (pathname, status, headers, req, res, finish) {
    var that = this,
        promise = new(events.EventEmitter);

    pathname = this.resolve(pathname);

    // Only allow GET and HEAD requests
    if (req.method !== 'GET' && req.method !== 'HEAD') {
        finish(405, { 'Allow': 'GET, HEAD' });
        return promise;
    }

    // Make sure we're not trying to access a
    // file outside of the root.
    if (pathname.indexOf(that.root) === 0) {
        fs.stat(pathname, function (e, stat) {
            if (e) {
                finish(404, {});
            } else if (stat.isFile()) {      // Stream a single file.
                that.respond(null, status, headers, [pathname], stat, req, res, finish);
            } else if (stat.isDirectory()) { // Stream a directory of files.
                that.serveDir(pathname, req, res, finish);
            } else {
                finish(400, {});
            }
        });
    } else {
        // Forbidden
        finish(403, {});
    }
    return promise;
};
this.Server.prototype.resolve = function (pathname) {
    return path.resolve(path.join(this.root, pathname));
};
this.Server.prototype.serve = function (req, res, callback) {
    var that = this,
        promise = new(events.EventEmitter);

    var pathname = decodeURI(url.parse(req.url).pathname);

    var finish = function (status, headers) {
        that.finish(status, headers, req, res, promise, callback);
    };

    process.nextTick(function () {
        that.servePath(pathname, 200, {}, req, res, finish).on('success', function (result) {
            promise.emit('success', result);
        }).on('error', function (err) {
            promise.emit('error');
        });
    });
    if (! callback) { return promise }
};

this.Server.prototype.respond = function (pathname, status, _headers, files, stat, req, res, finish) {
    var mtime   = Date.parse(stat.mtime),
        key     = pathname || files[0],
        headers = {};

    // Copy default headers
    for (var k in this.options.headers) {  headers[k] = this.options.headers[k] }

    headers['ETag']          = JSON.stringify([stat.ino, stat.size, mtime].join('-'));
    headers['Date']          = new(Date)().toUTCString();
    headers['Last-Modified'] = new(Date)(stat.mtime).toUTCString();

    // Conditional GET
    // If the "If-Modified-Since" or "If-None-Match" headers
    // match the conditions, send a 304 Not Modified.
    if (req.headers['if-none-match'] === headers['ETag'] ||
        Date.parse(req.headers['if-modified-since']) >= mtime) {
        finish(304, headers);
    } else {
        var fileExtension = path.extname(files[0]).slice(1).toLowerCase();
        headers['Content-Length'] = stat.size;
        headers['Content-Type']   = mime.contentTypes[fileExtension] ||
                                   'application/octet-stream';

        for (var k in _headers) { headers[k] = _headers[k] }

        res.writeHead(status, headers);

        if (req.method === 'HEAD') {
            finish(200, headers);
            return;
        }

        // If the file was cached and it's not older
        // than what's on disk, serve the cached version.
        if (this.cache && (key in exports.store) &&
            exports.store[key].stat.mtime >= stat.mtime) {
            res.end(exports.store[key].buffer);
            finish(status, headers);
        } else {
            this.stream(pathname, files, new(buffer.Buffer)(stat.size), res, function (e, buffer) {
                if (e) { return finish(500, {}) }
                exports.store[key] = {
                    stat:      stat,
                    buffer:    buffer,
                    timestamp: Date.now()
                };
                finish(status, headers);
            });
        }
    }
};

this.Server.prototype.stream = function (pathname, files, buffer, res, callback) {
    (function streamFile(files, offset) {
        var file = files.shift();

        if (file) {
            file = file[0] === '/' ? file : path.join(pathname || '.', file);

            // Stream the file to the client
            fs.createReadStream(file, {
                flags: 'r',
                mode: 0666
            }).on('data', function (chunk) {
                chunk.copy(buffer, offset);
                offset += chunk.length;
            }).on('close', function () {
                streamFile(files, offset);
            }).on('error', function (err) {
                callback(err);
                console.error(err);
            }).pipe(res, { end: false });
        } else {
            res.end();
            callback(null, buffer, offset);
        }
    })(files.slice(0), 0);
};
<|endoftext|>


<commit_before>/* JavaScript Telephone Challenge

My role in the group is person 1/Danielle Cameron: Test to User Stories

As a user I want to be able to calculate the sum by going through a list of numbers and adding all the numbers in it as its own function called sum.

As a user I want to be able to calculate the mean by going through a list of numbers, adding all the numbers and dividing by the total amount of numbers, as its function called mean.

As a user I want to be able to calculate the median by going through a list of numbers and finding the middle number of that list, as its own function called median.

Person 2 Armani Pseudocode

 define a function called sum that takes an array of numbers as an arguement
 	set a variable called total equal to zero
 	then set a variable called position equal to zero
 	while position is less than the length of the array
 		add total and array[position]
 	psoitions value goes up by one
 	return total

 define a function called mean that takes an array of numbers as an arguement
 	return the value of sum being called with the array divided by the length of the array

 define a function called sortNumber that takes two arguements (a and b)
 	return a - b

 define a function called median that takes an array as an arguement
 	create a new_array equal to sorted original array
 	if there are an odd number of digits in the array
 		return new_array[find middle digit by dividing by two and subtracting .5]
 	else
 		return (new_array[new_array.length divided by 2] + new_array[(new_array.length divided by 2) - 1]) divided by 2

Person 3: Issac
Person 4: Celeste
<commit_msg>Person 3<commit_after>/* JavaScript Telephone Challenge

My role in the group is person 1/Danielle Cameron: Test to User Stories

As a user I want to be able to calculate the sum by going through a list of numbers and adding all the numbers in it as its own function called sum.

As a user I want to be able to calculate the mean by going through a list of numbers, adding all the numbers and dividing by the total amount of numbers, as its function called mean.

As a user I want to be able to calculate the median by going through a list of numbers and finding the middle number of that list, as its own function called median.

Person 2 Armani Pseudocode

 define a function called sum that takes an array of numbers as an arguement
 	set a variable called total equal to zero
 	then set a variable called position equal to zero
 	while position is less than the length of the array
 		add total and array[position]
 	psoitions value goes up by one
 	return total

 define a function called mean that takes an array of numbers as an arguement
 	return the value of sum being called with the array divided by the length of the array

 define a function called sortNumber that takes two arguements (a and b)
 	return a - b

 define a function called median that takes an array as an arguement
 	create a new_array equal to sorted original array
 	if there are an odd number of digits in the array
 		return new_array[find middle digit by dividing by two and subtracting .5]
 	else
 		return (new_array[new_array.length divided by 2] + new_array[(new_array.length divided by 2) - 1]) divided by 2

Person 3: Issac
function sum(array){
	var total = 0;
	for (var position = 0; position < array.length; position++)
		total += array[position];
		return total
}

function mean(array){
	return (sum(array)/array.length);
}

function sortNumber(a,b) {
	return a - b;
}

function median(array){
	var new_array = array.sort(sortNumber);
		if (new_array.length%2 == 1)
			return new_array[(new_array.length/2)-0.5];
		else
			return (new_array[new_array.length/2] + new_array[(new_array.length/2) - 1])/2;
}

var a = [1,15,8,19,2,11,100,]
// console.log(sum(a))
// console.log(mean(a))
// console.log(a.sort(sortNumber))
// console.log(median(a))
Person 4: Celeste
<|endoftext|>


<commit_before>'use strict';
/**
 * Created by Online By Design LLC.
 *
 * The master is in charge of keeping track of task requests from the workers and assigning tasks as they become available.
 * The master also manages adding and updating tasks in the mongodb
 */

/**
 * Master is initialized here
 *
 * @param config - Configuration options
 */
module.exports = function (config) {
    //var express = require('express');
    //var connect = require('connect');
    var io = require('socket.io')(config.masterPort || 3000);
    var mongoose = require('mongoose');
    var _ = require('lodash');
    var async = require('async');
    var moment = require('moment');
    var Log = require('../logger')(config.logger);

    // Load models
    var Task = require('../models/tasks');

    // Module configuration
    mongoose.connect(config.taskDb || 'mongodb://localhost/taskrunner');

    Log.info("Master started");

    // Variables
    var timeout = config.workerTimeout || 300000; // 5 minutes is the default timeout time for master
    var assigningTasks = 0;

    // Connect to database and get the list of tasks
    var db = mongoose.connection;
    db.on('error', function (err) {
        Log.error({err: err}, 'Could not connect to mongodb')
    }); // TODO: test this out
    db.once('open', function () {
        // Query: {'task.assigned': {$exists: true}, 'task.completed': {$exists: false}}
        Task.where('task.assigned').exists(true)
            .where('task.completed').exists(false)
            .exec(function (err, tasks) {
                if (err) return Log.error({err: err}, 'Error when finding tasks'); // TODO: test this out

                var startTime = moment().unix();

                // After loading tasks check to see if any assignments have exceeded the timeout.
                for (var i = 0; i < tasks.length; i++) {
                    var task = tasks[i];
                    var taskTimeout = task.timeout || timeout;
                    // TODO: if the task was assigned then add a timer if it isn't stale.
                    if (task.assigned && !task.assigned.completed && task.assigned.when && task.assigned.when + taskTimeout / 1000 < startTime) {
                        errorTask(task, null, 'Master started with stale task.', 'Task assigned ' + moment.unix(task.assigned.when).format());
                    }
                }

                if (tasks.length > 0) {
                    assignTasks();
                }
            });
    });

    /**
     * When a worker establishes/reestablishes connection
     */
    io.on('connection', function (socket) {
        Log.info('Worker connected.  (', findWorkers().length, ')');

        /**
         * When the worker disconnects
         */
        socket.on('disconnect', function () {
            Log.warn('Worker disconnected.  (', findWorkers().length, ')');
        });

        /**
         * When the socket has an error
         */
        socket.on('error', function (err) {
            Log.error({err: err}, "A socket had an error");
        });

        /**
         * When the worker requests a task
         */
        socket.on('task:request', function () {
            socket._idleWorker = true;

            assignTasks();
        });

        /**
         * When a worker worker finishes a task
         */
        socket.on('task:done', function (taskJSON) {
            clearTimeout(socket._timer);

            // Update the task and save it to the database.
            var taskParsed = JSON.parse(taskJSON);
            // Query: {'_id': taskParsed._id}
            // Limit: 1
            Task.where('_id').equals(mongoose.Types.ObjectId(taskParsed._id)).limit(1).exec(function (err, tasks) {
                if (err || tasks.length === 0) {
                    Log.error({err: err}, 'Error finding task to mark as completed');

                    assignTasks();
                } else {
                    var task = tasks.shift();
                    task.assigned.completed = moment().unix();

                    Log.info({module: task.module}, 'Task completed'); // TODO: Indicate worker name
                    task.save(function (err) {
                        if (err) return Log.error({err: err}, 'Error updating task status as complete to mongodb');

                        assignTasks();
                    });
                }
            });
        });

        /**
         * When a worker worker has a task error
         */
        socket.on('task:error', function (err, taskJSON) {
            // Delete assigned state so task can be reassigned
            var taskParsed = JSON.parse(taskJSON);

            // Query: {'_id': taskParsed._id}
            // Limit: 1
            Task.where('_id').equals(mongoose.Types.ObjectId(taskParsed._id)).limit(1).exec(function (newErr, tasks) {
                if (err) Log.error({err: err}, 'Error finding task passed in from an error');

                errorTask(tasks.shift(), this, 'Task error', err)
            });
        });

        /**
         * When a worker wants to add tasks to the list
         */
        socket.on('task:add', function (newTasks) {

            function addNewTask(newTask, done) {
                var task = new Task(newTask);
                task.save(function (err) {
                    if (err) done(err);

                    done()
                })
            }

            // TODO: Develop some anti-duplication logic, either in code or allow communication with the Feeder.
            async.each(newTasks, addNewTask, function (err) {
                if (err) {
                    socket.emit('task:error', err);
                    return Log.error({err: err}, 'Error while adding tasks');
                }

                socket.emit('task:added', 'Tasks have been successfully added', newTasks);
                Log.info('Task(s) added'); // TODO: Indicate what tasks were added to the list
                assignTasks();
            });

        });

    });
    /***********************************************************************************************************************
     * Helper functions
     **********************************************************************************************************************/

    /**
     * Assigns the next available task to the next available worker while there is still an available task and worker.
     * This is done synchronously since multiple instances of it may be running at a time.
     */
    function assignTasks() {
        if (!assigningTasks) {
            assigningTasks = true;

            var task;
            var socket;

            async.forever(
                function (next) {
                    findNextTask(function (err, returnedTask) {
                        if (err) next(err);

                        if (returnedTask) {
                            task = returnedTask;
                            if ((socket = findIdleWorker())) {
                                saveAssignedTask(task, socket, next);
                            } else {
                                next('Done');
                            }
                        }
                    })
                },
                function (err) {
                    if (err !== 'Done') Log.error({err: err}, 'Error assigning task.');

                    // Even if we have an error we still need to stop assigning tasks.
                    assigningTasks = false;
                }
            );
        }
    }

    /**
     * Handles errors from or related to tasks. Logs error, stops any timers associated with task, and clears assignment.
     */
    function errorTask(task, socket, message, err) {
        if (socket) {
            clearTimeout(socket._timer);

            socket._idleWorker = true;
            socket.emit('task:cancel', JSON.stringify(task));
        }

        // It is possible that a break in communication resulted in the worker moving to a different socket and completing
        // the task but it still times out since the timer is attached to the socket.
        if (task.assigned.completed) {
            Log.error({err: err}, message, 'Even though the task returned an error it was marked as complete by a worker.');

            assignTasks();
        } else {
            Log.error({err: err}, message);

            if (task) {
                task.assigned = undefined;

                task.save(function (err) {
                    if (err) return Log.error({err: err}, 'Error un-assigning task assignment to mongodb');

                    assignTasks();
                });
            } else {
                assignTasks();
            }
        }
    }

    /**
     * Save a newly assigned task to the database then send the task to the worker.
     *
     * @param task
     * @param socket
     * @param done
     */
    function saveAssignedTask(task, socket, done) {
        // Mark the task as assigned
        task.assigned.who = 'workername'; // TODO: Pull the worker name from the socket
        task.assigned.when = moment().unix();

        task.save(function (err) {
            if (err) done(err);

            // Use global timeout unless specific task timeout is set.
            var taskTimeout = task.timeout || timeout;

            socket._timer = setTimeout((function () {
                errorTask(this.task, this.socket, 'Task timed out without response from client.', 'Task assigned ' + moment.unix(this.task.assigned.when).format());
            }).bind({task: task, socket: socket, timeout: taskTimeout}), taskTimeout);

            socket.emit('task:send', JSON.stringify(task));
            Log.info({module: task.module, assignee: task.assigned.who}, 'Task sent');
            done();
        });
    }

    /**
     * Finds the next available task
     */
    function findNextTask(callback) {

        var returnTask;
        var offset = 0;

        // A queue to check for dependencies. If there is an unmet dependency then it kills the queue since we don't
        // need to keep checking this task anymore.
        var dependencyQueue = async.queue(function (dependency, queueDone) {
            // Query: {'assigned.completed': {$exists: true}, 'module': dependency.module, 'params': dependency.params}
            Task.where('assigned.completed').exists(true)
                .where('module').equals(dependency.module)
                .where('params').equals(dependency.params)
                .limit(1)
                .exec(function (err, completedTasks) {
                    if (err) queueDone(err);
                    if (completedTasks.length > 0) {
                        queueDone();
                    } else {
                        dependencyQueue.kill();
                    }
                });
        },1);

        async.doUntil(
            function (done) {
                // Sort the tasks by reversed priority
                // Query: {assigned: {$exists: false}}
                // Sort: {priority: -1, created: 1}
                // Limit: 1
                Task.where('assigned').exists(false)
                    .sort('-priority')
                    .sort('created')
                    .limit(1)
                    .skip(offset)
                    .exec(function (err, tasks) {

                        // We are checking returnTask to see when it isn't undefined to determine if we are done but if
                        // we are at the end of the task list then we need to still say we are done so we set returnTask
                        // to null.
                        if (tasks.length > 0) {
                            returnTask = null;
                        }

                        var task = tasks[0];

                        offset++;

                        var dependencies = task.dependencies;

                        // If there are dependencies we need to check if they are completed.
                        if (dependencies.length > 0) {

                            // Drain is only called if all dependencies are met so we set the return task when it is
                            // called. The queue is killed otherwise.
                            dependencyQueue.drain = function () {
                                returnTask = task;
                            };

                            // Add all the dependencies to the queue.
                            for (var i = 0; i < dependencies.length; i++) {
                                dependencyQueue.push(dependencies[i], done);
                            }
                        } else {
                            // No dependencies exist so this is the task to return.
                            returnTask = task;
                            done();
                        }
                    });
            },
            function () {
                // If returnTask is ever set then we are done with our loop.
                if (!_.isUndefined(returnTask)) return true;
            },
            function (err) {
                if (err) callback(err);

                // Return whatever we have at the end of our task search.
                callback(null, returnTask);
            }
        );

    }

    /**
     * Finds a worker with an idle worker and decreases the idle worker count before returning the socket
     */
    function findIdleWorker() {
        // Get the first worker with idle workers.
        var socket = _.find(findWorkers(), function (worker) {
            return worker._idleWorker;
        });

        // If an idle worker is set idleWorker to false and return it.
        if (socket) {
            socket._idleWorker = false;
            return socket;
        }

        return null;
    }

    /**
     * Searches for workers connected to the socket.io master (Copied from some where online)
     *
     * @param {String} [namespace] - Filter workers by namespace
     * @param {String} [room] - Filter workers by room
     * @returns {Array} - List of workers
     */
    function findWorkers(namespace, room) {
        var workers = [], ns = io.of(namespace || "/");

        if (ns) {
            for (var id in ns.connected) {
                if (room) {
                    var index = ns.connected[id].rooms.indexOf(room);
                    if (index !== -1) {
                        workers.push(ns.connected[id]);
                    }
                } else {
                    workers.push(ns.connected[id]);
                }
            }
        }
        return workers;
    }
}
;
<commit_msg>Fixed an inverted array.length check.<commit_after>'use strict';
/**
 * Created by Online By Design LLC.
 *
 * The master is in charge of keeping track of task requests from the workers and assigning tasks as they become available.
 * The master also manages adding and updating tasks in the mongodb
 */

/**
 * Master is initialized here
 *
 * @param config - Configuration options
 */
module.exports = function (config) {
    //var express = require('express');
    //var connect = require('connect');
    var io = require('socket.io')(config.masterPort || 3000);
    var mongoose = require('mongoose');
    var _ = require('lodash');
    var async = require('async');
    var moment = require('moment');
    var Log = require('../logger')(config.logger);

    // Load models
    var Task = require('../models/tasks');

    // Module configuration
    mongoose.connect(config.taskDb || 'mongodb://localhost/taskrunner');

    Log.info("Master started");

    // Variables
    var timeout = config.workerTimeout || 300000; // 5 minutes is the default timeout time for master
    var assigningTasks = 0;

    // Connect to database and get the list of tasks
    var db = mongoose.connection;
    db.on('error', function (err) {
        Log.error({err: err}, 'Could not connect to mongodb')
    }); // TODO: test this out
    db.once('open', function () {
        // Query: {'task.assigned': {$exists: true}, 'task.completed': {$exists: false}}
        Task.where('task.assigned').exists(true)
            .where('task.completed').exists(false)
            .exec(function (err, tasks) {
                if (err) return Log.error({err: err}, 'Error when finding tasks'); // TODO: test this out

                var startTime = moment().unix();

                // After loading tasks check to see if any assignments have exceeded the timeout.
                for (var i = 0; i < tasks.length; i++) {
                    var task = tasks[i];
                    var taskTimeout = task.timeout || timeout;
                    // TODO: if the task was assigned then add a timer if it isn't stale.
                    if (task.assigned && !task.assigned.completed && task.assigned.when && task.assigned.when + taskTimeout / 1000 < startTime) {
                        errorTask(task, null, 'Master started with stale task.', 'Task assigned ' + moment.unix(task.assigned.when).format());
                    }
                }

                if (tasks.length > 0) {
                    assignTasks();
                }
            });
    });

    /**
     * When a worker establishes/reestablishes connection
     */
    io.on('connection', function (socket) {
        Log.info('Worker connected.  (', findWorkers().length, ')');

        /**
         * When the worker disconnects
         */
        socket.on('disconnect', function () {
            Log.warn('Worker disconnected.  (', findWorkers().length, ')');
        });

        /**
         * When the socket has an error
         */
        socket.on('error', function (err) {
            Log.error({err: err}, "A socket had an error");
        });

        /**
         * When the worker requests a task
         */
        socket.on('task:request', function () {
            socket._idleWorker = true;

            assignTasks();
        });

        /**
         * When a worker worker finishes a task
         */
        socket.on('task:done', function (taskJSON) {
            clearTimeout(socket._timer);

            // Update the task and save it to the database.
            var taskParsed = JSON.parse(taskJSON);
            // Query: {'_id': taskParsed._id}
            // Limit: 1
            Task.where('_id').equals(mongoose.Types.ObjectId(taskParsed._id)).limit(1).exec(function (err, tasks) {
                if (err || tasks.length === 0) {
                    Log.error({err: err}, 'Error finding task to mark as completed');

                    assignTasks();
                } else {
                    var task = tasks.shift();
                    task.assigned.completed = moment().unix();

                    Log.info({module: task.module}, 'Task completed'); // TODO: Indicate worker name
                    task.save(function (err) {
                        if (err) return Log.error({err: err}, 'Error updating task status as complete to mongodb');

                        assignTasks();
                    });
                }
            });
        });

        /**
         * When a worker worker has a task error
         */
        socket.on('task:error', function (err, taskJSON) {
            // Delete assigned state so task can be reassigned
            var taskParsed = JSON.parse(taskJSON);

            // Query: {'_id': taskParsed._id}
            // Limit: 1
            Task.where('_id').equals(mongoose.Types.ObjectId(taskParsed._id)).limit(1).exec(function (newErr, tasks) {
                if (err) Log.error({err: err}, 'Error finding task passed in from an error');

                errorTask(tasks.shift(), this, 'Task error', err)
            });
        });

        /**
         * When a worker wants to add tasks to the list
         */
        socket.on('task:add', function (newTasks) {

            function addNewTask(newTask, done) {
                var task = new Task(newTask);
                task.save(function (err) {
                    if (err) done(err);

                    done()
                })
            }

            // TODO: Develop some anti-duplication logic, either in code or allow communication with the Feeder.
            async.each(newTasks, addNewTask, function (err) {
                if (err) {
                    socket.emit('task:error', err);
                    return Log.error({err: err}, 'Error while adding tasks');
                }

                socket.emit('task:added', 'Tasks have been successfully added', newTasks);
                Log.info('Task(s) added'); // TODO: Indicate what tasks were added to the list
                assignTasks();
            });

        });

    });
    /***********************************************************************************************************************
     * Helper functions
     **********************************************************************************************************************/

    /**
     * Assigns the next available task to the next available worker while there is still an available task and worker.
     * This is done synchronously since multiple instances of it may be running at a time.
     */
    function assignTasks() {
        if (!assigningTasks) {
            assigningTasks = true;

            var task;
            var socket;

            async.forever(
                function (next) {
                    findNextTask(function (err, returnedTask) {
                        if (err) next(err);

                        if (returnedTask) {
                            task = returnedTask;
                            if ((socket = findIdleWorker())) {
                                saveAssignedTask(task, socket, next);
                            } else {
                                next('Done');
                            }
                        }
                    })
                },
                function (err) {
                    if (err !== 'Done') Log.error({err: err}, 'Error assigning task.');

                    // Even if we have an error we still need to stop assigning tasks.
                    assigningTasks = false;
                }
            );
        }
    }

    /**
     * Handles errors from or related to tasks. Logs error, stops any timers associated with task, and clears assignment.
     */
    function errorTask(task, socket, message, err) {
        if (socket) {
            clearTimeout(socket._timer);

            socket._idleWorker = true;
            socket.emit('task:cancel', JSON.stringify(task));
        }

        // It is possible that a break in communication resulted in the worker moving to a different socket and completing
        // the task but it still times out since the timer is attached to the socket.
        if (task.assigned.completed) {
            Log.error({err: err}, message, 'Even though the task returned an error it was marked as complete by a worker.');

            assignTasks();
        } else {
            Log.error({err: err}, message);

            if (task) {
                task.assigned = undefined;

                task.save(function (err) {
                    if (err) return Log.error({err: err}, 'Error un-assigning task assignment to mongodb');

                    assignTasks();
                });
            } else {
                assignTasks();
            }
        }
    }

    /**
     * Save a newly assigned task to the database then send the task to the worker.
     *
     * @param task
     * @param socket
     * @param done
     */
    function saveAssignedTask(task, socket, done) {
        // Mark the task as assigned
        task.assigned.who = 'workername'; // TODO: Pull the worker name from the socket
        task.assigned.when = moment().unix();

        task.save(function (err) {
            if (err) done(err);

            // Use global timeout unless specific task timeout is set.
            var taskTimeout = task.timeout || timeout;

            socket._timer = setTimeout((function () {
                errorTask(this.task, this.socket, 'Task timed out without response from client.', 'Task assigned ' + moment.unix(this.task.assigned.when).format());
            }).bind({task: task, socket: socket, timeout: taskTimeout}), taskTimeout);

            socket.emit('task:send', JSON.stringify(task));
            Log.info({module: task.module, assignee: task.assigned.who}, 'Task sent');
            done();
        });
    }

    /**
     * Finds the next available task
     */
    function findNextTask(callback) {

        var returnTask;
        var offset = 0;

        // A queue to check for dependencies. If there is an unmet dependency then it kills the queue since we don't
        // need to keep checking this task anymore.
        var dependencyQueue = async.queue(function (dependency, queueDone) {
            // Query: {'assigned.completed': {$exists: true}, 'module': dependency.module, 'params': dependency.params}
            Task.where('assigned.completed').exists(true)
                .where('module').equals(dependency.module)
                .where('params').equals(dependency.params)
                .limit(1)
                .exec(function (err, completedTasks) {
                    if (err) queueDone(err);
                    if (completedTasks.length > 0) {
                        queueDone();
                    } else {
                        dependencyQueue.kill();
                    }
                });
        },1);

        async.doUntil(
            function (done) {
                // Sort the tasks by reversed priority
                // Query: {assigned: {$exists: false}}
                // Sort: {priority: -1, created: 1}
                // Limit: 1
                Task.where('assigned').exists(false)
                    .sort('-priority')
                    .sort('created')
                    .limit(1)
                    .skip(offset)
                    .exec(function (err, tasks) {

                        // We are checking returnTask to see when it isn't undefined to determine if we are done but if
                        // we are at the end of the task list then we need to still say we are done so we set returnTask
                        // to null.
                        if (tasks.length === 0) {
                            returnTask = null;
                        }

                        var task = tasks[0];

                        offset++;

                        var dependencies = task.dependencies;

                        // If there are dependencies we need to check if they are completed.
                        if (dependencies.length > 0) {

                            // Drain is only called if all dependencies are met so we set the return task when it is
                            // called. The queue is killed otherwise.
                            dependencyQueue.drain = function () {
                                returnTask = task;
                            };

                            // Add all the dependencies to the queue.
                            for (var i = 0; i < dependencies.length; i++) {
                                dependencyQueue.push(dependencies[i], done);
                            }
                        } else {
                            // No dependencies exist so this is the task to return.
                            returnTask = task;
                            done();
                        }
                    });
            },
            function () {
                // If returnTask is ever set then we are done with our loop.
                if (!_.isUndefined(returnTask)) return true;
            },
            function (err) {
                if (err) callback(err);

                // Return whatever we have at the end of our task search.
                callback(null, returnTask);
            }
        );

    }

    /**
     * Finds a worker with an idle worker and decreases the idle worker count before returning the socket
     */
    function findIdleWorker() {
        // Get the first worker with idle workers.
        var socket = _.find(findWorkers(), function (worker) {
            return worker._idleWorker;
        });

        // If an idle worker is set idleWorker to false and return it.
        if (socket) {
            socket._idleWorker = false;
            return socket;
        }

        return null;
    }

    /**
     * Searches for workers connected to the socket.io master (Copied from some where online)
     *
     * @param {String} [namespace] - Filter workers by namespace
     * @param {String} [room] - Filter workers by room
     * @returns {Array} - List of workers
     */
    function findWorkers(namespace, room) {
        var workers = [], ns = io.of(namespace || "/");

        if (ns) {
            for (var id in ns.connected) {
                if (room) {
                    var index = ns.connected[id].rooms.indexOf(room);
                    if (index !== -1) {
                        workers.push(ns.connected[id]);
                    }
                } else {
                    workers.push(ns.connected[id]);
                }
            }
        }
        return workers;
    }
}
;
<|endoftext|>


<commit_before>ccm_closeDashboardPane = function(r) {
	$(r).closest('div.ccm-pane').fadeOut(120, 'easeOutExpo');
}

ccm_getDashboardBackgroundImageData = function(image, display) {
	$.getJSON(CCM_TOOLS_PATH + '/dashboard/get_image_data', {
		'image': image
	}, function(r) {
		if (r && display) {
			var html = '
';
			html += '' + r.title + ' ' + ccmi18n.authoredBy + ' ';
			if (r.link) {
				html += '' + r.author + '';
			} else {
				html += r.author;
			}
			$('
').html(html).appendTo(document.body).show();
			setTimeout(function() {
				$('#ccm-dashboard-image-caption').fadeOut(1000, 'easeOutExpo');
			}, 5000);
		}
	});
}

ccm_dashboardEqualizeMenus = function() {
	if ($(window).width() < 560) {
		$('div.dashboard-icon-list div.well').css('visibility', 'visible');
		return false;
	}
	var j = -1;
	var i;
	var pos = 0;
	var menus = new Array();
	$('ul.nav-list').each(function() {
		if ($(this).position().top != pos) {
			j++;
			menus[j] = new Array();
		}

		menus[j].push($(this));
		pos = $(this).position().top;
	});

	for (i = 0; i < menus.length; i++) {
		var h = 0;
		for (j = 0; j < menus[i].length; j++) {
			var mx = menus[i][j];
			if (mx.height() > h) {
				h = mx.height();
			}
		}
		for (j = 0; j < menus[i].length; j++) {
			var mx = menus[i][j];
			mx.css('height', h);
		}
	}
	$('div.dashboard-icon-list div.well').css('visibility', 'visible');
}

$(function() {
	ccm_activateToolbar();

	$("#ccm-page-help").popover({
		trigger: 'click',
		content: function() {
		var id = $(this).attr('id') + '-content';
		return $('#' + id).html();

	}, placement: 'bottom', html: true});
	$('.launch-tooltip').tooltip({placement: 'bottom'});
	if ($('#ccm-dashboard-result-message').length > 0) {
		if ($('.ccm-pane').length > 0) {
			var pclass = $('.ccm-pane').parent().attr('class');
			var gpclass = $('.ccm-pane').parent().parent().attr('class');
			var html = $('#ccm-dashboard-result-message').html();
			$('#ccm-dashboard-result-message').html('

' + html + '

').fadeIn(400);
		}
	} else {
		$("#ccm-dashboard-result-message").fadeIn(200);
	}
});
<commit_msg>Fix Help Popover Close on Click<commit_after>ccm_closeDashboardPane = function(r) {
	$(r).closest('div.ccm-pane').fadeOut(120, 'easeOutExpo');
}

ccm_getDashboardBackgroundImageData = function(image, display) {
	$.getJSON(CCM_TOOLS_PATH + '/dashboard/get_image_data', {
		'image': image
	}, function(r) {
		if (r && display) {
			var html = '
';
			html += '' + r.title + ' ' + ccmi18n.authoredBy + ' ';
			if (r.link) {
				html += '' + r.author + '';
			} else {
				html += r.author;
			}
			$('
').html(html).appendTo(document.body).show();
			setTimeout(function() {
				$('#ccm-dashboard-image-caption').fadeOut(1000, 'easeOutExpo');
			}, 5000);
		}
	});
}

ccm_dashboardEqualizeMenus = function() {
	if ($(window).width() < 560) {
		$('div.dashboard-icon-list div.well').css('visibility', 'visible');
		return false;
	}
	var j = -1;
	var i;
	var pos = 0;
	var menus = new Array();
	$('ul.nav-list').each(function() {
		if ($(this).position().top != pos) {
			j++;
			menus[j] = new Array();
		}

		menus[j].push($(this));
		pos = $(this).position().top;
	});

	for (i = 0; i < menus.length; i++) {
		var h = 0;
		for (j = 0; j < menus[i].length; j++) {
			var mx = menus[i][j];
			if (mx.height() > h) {
				h = mx.height();
			}
		}
		for (j = 0; j < menus[i].length; j++) {
			var mx = menus[i][j];
			mx.css('height', h);
		}
	}
	$('div.dashboard-icon-list div.well').css('visibility', 'visible');
}

$(function() {
	ccm_activateToolbar();

	var $ccmPageHelp = $("#ccm-page-help").popover({
		trigger: 'click',
		content: function() {
		var id = $(this).attr('id') + '-content';
		return $('#' + id).html();

	}, placement: 'bottom', html: true})
	.click(function(e) {
		e.stopPropagation();
	});
	$(document).click(function() {
		$ccmPageHelp.data('popover').hide();
	});
	$('.launch-tooltip').tooltip({placement: 'bottom'});
	if ($('#ccm-dashboard-result-message').length > 0) {
		if ($('.ccm-pane').length > 0) {
			var pclass = $('.ccm-pane').parent().attr('class');
			var gpclass = $('.ccm-pane').parent().parent().attr('class');
			var html = $('#ccm-dashboard-result-message').html();
			$('#ccm-dashboard-result-message').html('

' + html + '

').fadeIn(400);
		}
	} else {
		$("#ccm-dashboard-result-message").fadeIn(200);
	}
});
<|endoftext|>


<commit_before>/* global describe, it, beforeEach */
/* eslint-disable no-new */

var assert = require('assert')
var ecdsa = require('../src/ecdsa')
var ecurve = require('ecurve')
var proxyquire = require('proxyquire')
var sinon = require('sinon')

var BigInteger = require('bigi')
var ECPair = require('../src/ecpair')

var fixtures = require('./fixtures/ecpair.json')
var secp256k1 = ecurve.getCurveByName('secp256k1')

var NETWORKS = require('../src/networks')
var NETWORKS_LIST = [] // Object.values(NETWORKS)
for (var networkName in NETWORKS) {
  NETWORKS_LIST.push(NETWORKS[networkName])
}

describe('ECPair', function () {
  describe('constructor', function () {
    it('defaults to compressed', function () {
      var keyPair = new ECPair(BigInteger.ONE)

      assert.strictEqual(keyPair.compressed, true)
    })

    it('supports the uncompressed option', function () {
      var keyPair = new ECPair(BigInteger.ONE, null, {
        compressed: false
      })

      assert.strictEqual(keyPair.compressed, false)
    })

    it('supports the network option', function () {
      var keyPair = new ECPair(BigInteger.ONE, null, {
        compressed: false,
        network: NETWORKS.testnet
      })

      assert.strictEqual(keyPair.network, NETWORKS.testnet)
    })

    it('throws if compressed option is not a bool', function () {
      assert.throws(function () {
        new ECPair(null, null, {
          compressed: 2
        }, /Expected Boolean, got 2/)
      })
    })

    it('throws if public and private key given', function () {
      var qBuffer = new Buffer('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 'hex')
      var Q = ecurve.Point.decodeFrom(secp256k1, qBuffer)

      assert.throws(function () {
        new ECPair(BigInteger.ONE, Q)
      }, /Unexpected publicKey parameter/)
    })

    it('throws if network is missing pubKeyHash constants', function () {
      assert.throws(function () {
        new ECPair(null, null, {
          network: {}
        }, /Unknown pubKeyHash constants for network/)
      })
    })

    fixtures.valid.forEach(function (f) {
      it('calculates the public point for ' + f.WIF, function () {
        var d = new BigInteger(f.d)
        var keyPair = new ECPair(d, null, {
          compressed: f.compressed
        })

        assert.strictEqual(keyPair.getPublicKeyBuffer().toString('hex'), f.Q)
      })
    })

    fixtures.invalid.constructor.forEach(function (f) {
      it('throws on ' + f.d, function () {
        var d = new BigInteger(f.d)

        assert.throws(function () {
          new ECPair(d)
        }, new RegExp(f.exception))
      })
    })
  })

  describe('getPublicKeyBuffer', function () {
    var keyPair

    beforeEach(function () {
      keyPair = new ECPair(BigInteger.ONE)
    })

    it('wraps Q.getEncoded', sinon.test(function () {
      this.mock(keyPair.Q).expects('getEncoded')
        .once().calledWith(keyPair.compressed)

      keyPair.getPublicKeyBuffer()
    }))
  })

  describe('fromWIF', function () {
    fixtures.valid.forEach(function (f) {
      it('imports ' + f.WIF + ' (' + f.network + ')', function () {
        var network = NETWORKS[f.network]
        var keyPair = ECPair.fromWIF(f.WIF, network)

        assert.strictEqual(keyPair.d.toString(), f.d)
        assert.strictEqual(keyPair.compressed, f.compressed)
        assert.strictEqual(keyPair.network, network)
      })
    })

    fixtures.valid.forEach(function (f) {
      it('imports ' + f.WIF + ' (via list of networks)', function () {
        var keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)

        assert.strictEqual(keyPair.d.toString(), f.d)
        assert.strictEqual(keyPair.compressed, f.compressed)
        assert.strictEqual(keyPair.network, NETWORKS[f.network])
      })
    })

    fixtures.invalid.fromWIF.forEach(function (f) {
      it('throws on ' + f.WIF, function () {
        assert.throws(function () {
          ECPair.fromWIF(f.WIF)
        }, new RegExp(f.exception))
      })
    })
  })

  describe('toWIF', function () {
    fixtures.valid.forEach(function (f) {
      it('exports ' + f.WIF, function () {
        var keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
        var result = keyPair.toWIF()

        assert.strictEqual(result, f.WIF)
      })
    })
  })

  describe('makeRandom', function () {
    var d = new Buffer('0404040404040404040404040404040404040404040404040404040404040404', 'hex')
    var exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv'

    describe('uses randombytes RNG', function () {
      it('generates a ECPair', function () {
        var stub = { randombytes: function () { return d } }
        var ProxiedECPair = proxyquire('../src/ecpair', stub)

        var keyPair = ProxiedECPair.makeRandom()
        assert.strictEqual(keyPair.toWIF(), exWIF)
      })

      it('passes the options param', sinon.test(function () {
        var options = {
          compressed: true
        }

        // FIXME: waiting on https://github.com/cjohansen/Sinon.JS/issues/613
//        this.mock(ECPair).expects('constructor')
//          .once().calledWith(options)

        ECPair.makeRandom(options)
      }))
    })

    it('allows a custom RNG to be used', function () {
      var keyPair = ECPair.makeRandom({
        rng: function (size) { return d.slice(0, size) }
      })

      assert.strictEqual(keyPair.toWIF(), exWIF)
    })
  })

  describe('getAddress', function () {
    fixtures.valid.forEach(function (f) {
      it('returns ' + f.address + ' for ' + f.WIF, function () {
        var keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)

        assert.strictEqual(keyPair.getAddress(), f.address)
      })
    })
  })

  describe('ecdsa wrappers', function () {
    var keyPair, hash

    beforeEach(function () {
      keyPair = ECPair.makeRandom()
      hash = new Buffer(32)
    })

    describe('signing', function () {
      it('wraps ecdsa.sign', sinon.test(function () {
        this.mock(ecdsa).expects('sign')
          .once().calledWith(secp256k1, hash, keyPair.d)

        keyPair.sign(hash)
      }))

      it('throws if no private key is found', function () {
        keyPair.d = null

        assert.throws(function () {
          keyPair.sign(hash)
        }, /Missing private key/)
      })
    })

    describe('verify', function () {
      var signature

      beforeEach(function () {
        signature = keyPair.sign(hash)
      })

      it('wraps ecdsa.verify', sinon.test(function () {
        this.mock(ecdsa).expects('verify')
          .once().calledWith(secp256k1, hash, signature, keyPair.Q)

        keyPair.verify(hash, signature)
      }))
    })
  })
})
<commit_msg>tests: fix ECPair wrapper tests<commit_after>/* global describe, it, beforeEach */
/* eslint-disable no-new */

var assert = require('assert')
var ecdsa = require('../src/ecdsa')
var ecurve = require('ecurve')
var proxyquire = require('proxyquire')
var sinon = require('sinon')

var BigInteger = require('bigi')
var ECPair = require('../src/ecpair')

var fixtures = require('./fixtures/ecpair.json')
var curve = ecdsa.__curve

var NETWORKS = require('../src/networks')
var NETWORKS_LIST = [] // Object.values(NETWORKS)
for (var networkName in NETWORKS) {
  NETWORKS_LIST.push(NETWORKS[networkName])
}

describe('ECPair', function () {
  describe('constructor', function () {
    it('defaults to compressed', function () {
      var keyPair = new ECPair(BigInteger.ONE)

      assert.strictEqual(keyPair.compressed, true)
    })

    it('supports the uncompressed option', function () {
      var keyPair = new ECPair(BigInteger.ONE, null, {
        compressed: false
      })

      assert.strictEqual(keyPair.compressed, false)
    })

    it('supports the network option', function () {
      var keyPair = new ECPair(BigInteger.ONE, null, {
        compressed: false,
        network: NETWORKS.testnet
      })

      assert.strictEqual(keyPair.network, NETWORKS.testnet)
    })

    it('throws if compressed option is not a bool', function () {
      assert.throws(function () {
        new ECPair(null, null, {
          compressed: 2
        }, /Expected Boolean, got 2/)
      })
    })

    it('throws if public and private key given', function () {
      var qBuffer = new Buffer('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 'hex')
      var Q = ecurve.Point.decodeFrom(curve, qBuffer)

      assert.throws(function () {
        new ECPair(BigInteger.ONE, Q)
      }, /Unexpected publicKey parameter/)
    })

    it('throws if network is missing pubKeyHash constants', function () {
      assert.throws(function () {
        new ECPair(null, null, {
          network: {}
        }, /Unknown pubKeyHash constants for network/)
      })
    })

    fixtures.valid.forEach(function (f) {
      it('calculates the public point for ' + f.WIF, function () {
        var d = new BigInteger(f.d)
        var keyPair = new ECPair(d, null, {
          compressed: f.compressed
        })

        assert.strictEqual(keyPair.getPublicKeyBuffer().toString('hex'), f.Q)
      })
    })

    fixtures.invalid.constructor.forEach(function (f) {
      it('throws on ' + f.d, function () {
        var d = new BigInteger(f.d)

        assert.throws(function () {
          new ECPair(d)
        }, new RegExp(f.exception))
      })
    })
  })

  describe('getPublicKeyBuffer', function () {
    var keyPair

    beforeEach(function () {
      keyPair = new ECPair(BigInteger.ONE)
    })

    it('wraps Q.getEncoded', sinon.test(function () {
      this.mock(keyPair.Q).expects('getEncoded')
        .once().withArgs(keyPair.compressed)

      keyPair.getPublicKeyBuffer()
    }))
  })

  describe('fromWIF', function () {
    fixtures.valid.forEach(function (f) {
      it('imports ' + f.WIF + ' (' + f.network + ')', function () {
        var network = NETWORKS[f.network]
        var keyPair = ECPair.fromWIF(f.WIF, network)

        assert.strictEqual(keyPair.d.toString(), f.d)
        assert.strictEqual(keyPair.compressed, f.compressed)
        assert.strictEqual(keyPair.network, network)
      })
    })

    fixtures.valid.forEach(function (f) {
      it('imports ' + f.WIF + ' (via list of networks)', function () {
        var keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)

        assert.strictEqual(keyPair.d.toString(), f.d)
        assert.strictEqual(keyPair.compressed, f.compressed)
        assert.strictEqual(keyPair.network, NETWORKS[f.network])
      })
    })

    fixtures.invalid.fromWIF.forEach(function (f) {
      it('throws on ' + f.WIF, function () {
        assert.throws(function () {
          ECPair.fromWIF(f.WIF)
        }, new RegExp(f.exception))
      })
    })
  })

  describe('toWIF', function () {
    fixtures.valid.forEach(function (f) {
      it('exports ' + f.WIF, function () {
        var keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)
        var result = keyPair.toWIF()

        assert.strictEqual(result, f.WIF)
      })
    })
  })

  describe('makeRandom', function () {
    var d = new Buffer('0404040404040404040404040404040404040404040404040404040404040404', 'hex')
    var exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv'

    describe('uses randombytes RNG', function () {
      it('generates a ECPair', function () {
        var stub = { randombytes: function () { return d } }
        var ProxiedECPair = proxyquire('../src/ecpair', stub)

        var keyPair = ProxiedECPair.makeRandom()
        assert.strictEqual(keyPair.toWIF(), exWIF)
      })
    })

    it('allows a custom RNG to be used', function () {
      var keyPair = ECPair.makeRandom({
        rng: function (size) { return d.slice(0, size) }
      })

      assert.strictEqual(keyPair.toWIF(), exWIF)
    })
  })

  describe('getAddress', function () {
    fixtures.valid.forEach(function (f) {
      it('returns ' + f.address + ' for ' + f.WIF, function () {
        var keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST)

        assert.strictEqual(keyPair.getAddress(), f.address)
      })
    })
  })

  describe('ecdsa wrappers', function () {
    var keyPair, hash

    beforeEach(function () {
      keyPair = ECPair.makeRandom()
      hash = new Buffer(32)
    })

    describe('signing', function () {
      it('wraps ecdsa.sign', sinon.test(function () {
        this.mock(ecdsa).expects('sign')
          .once().withArgs(hash, keyPair.d)

        keyPair.sign(hash)
      }))

      it('throws if no private key is found', function () {
        keyPair.d = null

        assert.throws(function () {
          keyPair.sign(hash)
        }, /Missing private key/)
      })
    })

    describe('verify', function () {
      var signature

      beforeEach(function () {
        signature = keyPair.sign(hash)
      })

      it('wraps ecdsa.verify', sinon.test(function () {
        this.mock(ecdsa).expects('verify')
          .once().withArgs(hash, signature, keyPair.Q)

        keyPair.verify(hash, signature)
      }))
    })
  })
})
<|endoftext|>