<commit_before>var _ = require('lodash');

module.exports = function(self, options) {

  // Returns the minimum permission name that should be checked for
  // to determine if this user has some edit privileges for
  // this doc type (not necessarily every instance of it),
  // for example the ability to create one. Determines
  // admin bar menu item visibility

  self.getEditPermissionName = function() {
    return self.isAdminOnly() ? 'admin' : ('edit-' + self.name);
  };

  // Returns the minimum permission name that should be checked for
  // to determine if this user has full admin privileges for
  // this doc type

  self.getAdminPermissionName = function() {
    return self.isAdminOnly() ? 'admin' : ('admin-' + self.name);
  };

  // Define the related type "cursor", so that all of our subclasses
  // automatically have a cursor type too, and it is autoloaded from
  // ./lib/cursor.js if that exists, otherwise given an empty
  // definition.

  self.defineCursor = function() {
    self.defineRelatedType('cursor', {
      stop: 'apostrophe-doc-type-manager'
    });
  };

  // Returns a cursor that will only yield docs of the appropriate type
  // as determined by the `name` option of the module. Returns a cursor of
  // the appropriate type for the current module, even if it is a subclass.

  // Returns a cursor for use in finding docs. See cursor.js for chainable
  // filters, and also yielders that actually deliver the docs to you.

  self.find = function(req, criteria, projection) {
    return self.createRelatedType('cursor', {
      apos: self.apos,
      module: self,
      req: req,
      criteria: criteria,
      projection: projection
    });
  };

  // Returns a new instance of the doc type, with the appropriate default
  // values for each schema field.

  self.newInstance = function() {
    var doc = self.apos.schemas.newInstance(self.schema);
    doc.type = self.name;
    return doc;
  };

  // Returns a MongoDB projection object to be used when querying
  // for this type if all that is needed is a title for display
  // in an autocomplete menu. Default behavior is to
  // return only the `title`, `_id` and `slug` properties.
  // Removing any of these three is not recommended.
  //
  // `query.field` will contain the schema field definition for
  // the join the user is attempting to match titles from.

  self.getAutocompleteProjection = function(query) {
    return {
      title: 1,
      _id: 1,
      slug: 1
    };
  };

  // Returns a string to represent the given `doc` in an
  // autocomplete menu. `doc` will contain only the fields returned
  // by `getAutocompleteProjection`. `query.field` will contain
  // the schema field definition for the join the user is attempting
  // to match titles from. The default behavior is to return
  // the `title` property. This is sometimes extended to include
  // event start dates and similar information that helps the
  // user distinguish between docs.

  self.getAutocompleteTitle = function(doc, query) {
    return doc.title;
  };

  // Used by `apostrophe-versions` to label changes that
  // are made to joins by ID. Set `change.text` to the
  // desired text.

  self.decorateChange = function(doc, change) {
    change.text = doc.title;
  };

  // Returns true if only admins are allowed to edit this type.
  // Respected by the pieces module when deciding whether to
  // enumerate more specific permissions as choices for this
  // module.

  self.isAdminOnly = function() {
    return false;
  };

  // Return a new schema containing only fields for which the
  // current user has the permission specified by the `permission`
  // property of the schema field, or there is no `permission` property for the field.

  self.allowedSchema = function(req) {
    var disabled;
    var type;
    var schema = _.filter(self.schema, function(field) {
      return (!field.permission) || self.apos.permissions.can(req, field.permission);
    });
    var typeIndex = _.findIndex(schema, { name: 'type' });
    if (typeIndex !== -1) {
      // This option exists so that the
      // apostrophe-option-overrides and apostrophe-workflow modules,
      // if present, can be used together to disable various types based
      // on locale settings
      var disabled = self.apos.pages.getOption(req, 'disabledTypes');
      if (disabled) {
        // Take care to clone so we don't wind up modifying
        // the original schema, the allowed schema is only
        // a shallow clone of the array so far
        type = _.cloneDeep(schema[typeIndex]);
        type.choices = _.filter(type.choices, function(choice) {
          return !_.contains(disabled, choice.value);
        });
        // Make sure the allowed schema refers to the clone,
        // not the original
        schema[typeIndex] = type;
      }
    }
    return schema;
  };

  self.composeSchema = function() {

    // If a type is adminOnly remove the fields relating to permissions editing
    if (self.isAdminOnly()) {
      options.removeFields = (options.removeFields || []).concat([
        'loginRequired',
        '_viewUsers',
        '_viewGroups',
        '_editUsers',
        '_editGroups'
      ]);
    }

    self.schema = self.apos.schemas.compose(self.options);

    // Extend `composeSchema` to flag the use of field names
    // that are forbidden or nonfunctional in all doc types, i.e.
    // properties that will be overwritten by non-schema-driven
    // logic, such as `_id` or `docPermissions`

    const forbiddenFields = [ '_id', 'docPermissions', 'titleSortified', 'highSearchText', 'highSearchWords', 'lowSearchText', 'searchSummary' ];
    _.each(self.schema, function(field) {
      if (_.contains(forbiddenFields, field.name)) {
        throw new Error('Doc type ' + self.name + ': the field name ' + field.name + ' is forbidden');
      }
    });

    self.patchAdminPermissionInSchema();
  };

  // In the schema, `_editUsers` and `_editGroups` are
  // initially locked down to sitewide admins. Now that
  // we've constructed the module completely, take advantage
  // of `getAdminPermissionName` to specify a more nuanced permission,
  // such as the admin permission for this piece type, or for pages

  self.patchAdminPermissionInSchema = function() {
    var fieldNames = [ '_editUsers', '_editGroups' ];
    _.each(fieldNames, function(fieldName) {
      var field = _.find(self.schema, { name: fieldName });
      if (field) {
        field.permission = self.getAdminPermissionName();
      }
    });
  };

  // This method provides the back end of /autocomplete routes.
  // For the implementation of the autocomplete() filter see autocomplete.js.
  //
  // "query" must contain a "field" property which is the schema join field
  // that describes the relationship we're adding items to.
  //
  // "query" must also contain a "term" property, which is a partial
  // string to be autocompleted; otherwise an empty array is delivered
  // to the callback.
  //
  // We don't launder the input here, see the 'autocomplete' route.

  self.autocomplete = function(req, query, callback) {
    var criteria = {};
    var typeName = query && query.field && query.field.withType;
    var type = self.apos.launder.string(typeName);
    var cursor = self.find(req, {}, {}).sort('search');
    if (self.extendAutocompleteCursor) {
      self.extendAutocompleteCursor(cursor);
    }

    cursor.projection(self.getAutocompleteProjection(), query);

    // Try harder not to call autocomplete with something that doesn't
    // result in a search
    if (query.term && query.term.toString && query.term.toString().length) {
      var term = self.apos.launder.string(query.term);
      cursor.autocomplete(term);
    } else {
      return callback(null, []);
    }

    if (!(query.filters && query.filters.limit)) {
      cursor.limit(10);
    }

    // This is the big payoff of blessing join fields: we can apply their
    // filters in API calls like this one, knowing that the field definition
    // the browser sent us is one the developer created
    cursor.queryToFilters(query.field.filters || {});

    // Format it as value & id properties for compatibility with jquery UI autocomplete
    cursor.toArray(function(err, docs) {
      if (err) {
        return callback(err);
      }
      // Put the snippets in id order
      if (query.values) {
        docs = self.apos.utils.orderById(query.values, docs);
      }
      var results = _.map(docs, function(doc) {
        var response = {
          // jquery ui autocomplete demands label and value
          label: self.getAutocompleteTitle(doc, query),
          value: doc._id
        };
        _.defaults(response, _.omit(doc, 'title', '_id'));
        return response;
      });
      return callback(null, results);
    });
  };

  // Adds a listener for the `docSearchIndex` Apostrophe event, pointing to the
  // `searchIndexListener` method.

  self.addSearchIndexListener = function() {
    self.apos.on('docSearchIndex', self.searchIndexListener);
  };

  // Invoked when a `docSearchIndex` event takes place, this method adds
  // additional search texts to the `texts` array (modify it in place by
  // pushing new objects to it). These texts influence search results.
  // The default behavior is quite useful, so you won't often need to
  // override this.
  //
  // Each "text" is an *object* and must have at least `weight` and `text` properties.
  // If `weight` is >= 10, the text will be included in autocomplete searches and
  // given higher priority in full-text searches. Otherwise it will be included
  // only in full-text searches.
  //
  // If `silent` is `true`, the `searchSummary` property will not contain
  // the text.
  //
  // By default this method invokes `schemas.indexFields`, which will push
  // texts for all of the schema fields that support this unless they are
  // explicitly set `searchable: false`.
  //
  // In any case, the text of rich text widgets is always included as
  // lower-priority search text.

  self.searchIndexListener = function(doc, texts) {
    if (doc.type !== self.name) {
      return;
    }
    self.apos.schemas.indexFields(self.schema, doc, texts);
  };

};
<commit_msg>duplicate var<commit_after>var _ = require('lodash');

module.exports = function(self, options) {

  // Returns the minimum permission name that should be checked for
  // to determine if this user has some edit privileges for
  // this doc type (not necessarily every instance of it),
  // for example the ability to create one. Determines
  // admin bar menu item visibility

  self.getEditPermissionName = function() {
    return self.isAdminOnly() ? 'admin' : ('edit-' + self.name);
  };

  // Returns the minimum permission name that should be checked for
  // to determine if this user has full admin privileges for
  // this doc type

  self.getAdminPermissionName = function() {
    return self.isAdminOnly() ? 'admin' : ('admin-' + self.name);
  };

  // Define the related type "cursor", so that all of our subclasses
  // automatically have a cursor type too, and it is autoloaded from
  // ./lib/cursor.js if that exists, otherwise given an empty
  // definition.

  self.defineCursor = function() {
    self.defineRelatedType('cursor', {
      stop: 'apostrophe-doc-type-manager'
    });
  };

  // Returns a cursor that will only yield docs of the appropriate type
  // as determined by the `name` option of the module. Returns a cursor of
  // the appropriate type for the current module, even if it is a subclass.

  // Returns a cursor for use in finding docs. See cursor.js for chainable
  // filters, and also yielders that actually deliver the docs to you.

  self.find = function(req, criteria, projection) {
    return self.createRelatedType('cursor', {
      apos: self.apos,
      module: self,
      req: req,
      criteria: criteria,
      projection: projection
    });
  };

  // Returns a new instance of the doc type, with the appropriate default
  // values for each schema field.

  self.newInstance = function() {
    var doc = self.apos.schemas.newInstance(self.schema);
    doc.type = self.name;
    return doc;
  };

  // Returns a MongoDB projection object to be used when querying
  // for this type if all that is needed is a title for display
  // in an autocomplete menu. Default behavior is to
  // return only the `title`, `_id` and `slug` properties.
  // Removing any of these three is not recommended.
  //
  // `query.field` will contain the schema field definition for
  // the join the user is attempting to match titles from.

  self.getAutocompleteProjection = function(query) {
    return {
      title: 1,
      _id: 1,
      slug: 1
    };
  };

  // Returns a string to represent the given `doc` in an
  // autocomplete menu. `doc` will contain only the fields returned
  // by `getAutocompleteProjection`. `query.field` will contain
  // the schema field definition for the join the user is attempting
  // to match titles from. The default behavior is to return
  // the `title` property. This is sometimes extended to include
  // event start dates and similar information that helps the
  // user distinguish between docs.

  self.getAutocompleteTitle = function(doc, query) {
    return doc.title;
  };

  // Used by `apostrophe-versions` to label changes that
  // are made to joins by ID. Set `change.text` to the
  // desired text.

  self.decorateChange = function(doc, change) {
    change.text = doc.title;
  };

  // Returns true if only admins are allowed to edit this type.
  // Respected by the pieces module when deciding whether to
  // enumerate more specific permissions as choices for this
  // module.

  self.isAdminOnly = function() {
    return false;
  };

  // Return a new schema containing only fields for which the
  // current user has the permission specified by the `permission`
  // property of the schema field, or there is no `permission` property for the field.

  self.allowedSchema = function(req) {
    var disabled;
    var type;
    var schema = _.filter(self.schema, function(field) {
      return (!field.permission) || self.apos.permissions.can(req, field.permission);
    });
    var typeIndex = _.findIndex(schema, { name: 'type' });
    if (typeIndex !== -1) {
      // This option exists so that the
      // apostrophe-option-overrides and apostrophe-workflow modules,
      // if present, can be used together to disable various types based
      // on locale settings
      disabled = self.apos.pages.getOption(req, 'disabledTypes');
      if (disabled) {
        // Take care to clone so we don't wind up modifying
        // the original schema, the allowed schema is only
        // a shallow clone of the array so far
        type = _.cloneDeep(schema[typeIndex]);
        type.choices = _.filter(type.choices, function(choice) {
          return !_.contains(disabled, choice.value);
        });
        // Make sure the allowed schema refers to the clone,
        // not the original
        schema[typeIndex] = type;
      }
    }
    return schema;
  };

  self.composeSchema = function() {

    // If a type is adminOnly remove the fields relating to permissions editing
    if (self.isAdminOnly()) {
      options.removeFields = (options.removeFields || []).concat([
        'loginRequired',
        '_viewUsers',
        '_viewGroups',
        '_editUsers',
        '_editGroups'
      ]);
    }

    self.schema = self.apos.schemas.compose(self.options);

    // Extend `composeSchema` to flag the use of field names
    // that are forbidden or nonfunctional in all doc types, i.e.
    // properties that will be overwritten by non-schema-driven
    // logic, such as `_id` or `docPermissions`

    const forbiddenFields = [ '_id', 'docPermissions', 'titleSortified', 'highSearchText', 'highSearchWords', 'lowSearchText', 'searchSummary' ];
    _.each(self.schema, function(field) {
      if (_.contains(forbiddenFields, field.name)) {
        throw new Error('Doc type ' + self.name + ': the field name ' + field.name + ' is forbidden');
      }
    });

    self.patchAdminPermissionInSchema();
  };

  // In the schema, `_editUsers` and `_editGroups` are
  // initially locked down to sitewide admins. Now that
  // we've constructed the module completely, take advantage
  // of `getAdminPermissionName` to specify a more nuanced permission,
  // such as the admin permission for this piece type, or for pages

  self.patchAdminPermissionInSchema = function() {
    var fieldNames = [ '_editUsers', '_editGroups' ];
    _.each(fieldNames, function(fieldName) {
      var field = _.find(self.schema, { name: fieldName });
      if (field) {
        field.permission = self.getAdminPermissionName();
      }
    });
  };

  // This method provides the back end of /autocomplete routes.
  // For the implementation of the autocomplete() filter see autocomplete.js.
  //
  // "query" must contain a "field" property which is the schema join field
  // that describes the relationship we're adding items to.
  //
  // "query" must also contain a "term" property, which is a partial
  // string to be autocompleted; otherwise an empty array is delivered
  // to the callback.
  //
  // We don't launder the input here, see the 'autocomplete' route.

  self.autocomplete = function(req, query, callback) {
    var criteria = {};
    var typeName = query && query.field && query.field.withType;
    var type = self.apos.launder.string(typeName);
    var cursor = self.find(req, {}, {}).sort('search');
    if (self.extendAutocompleteCursor) {
      self.extendAutocompleteCursor(cursor);
    }

    cursor.projection(self.getAutocompleteProjection(), query);

    // Try harder not to call autocomplete with something that doesn't
    // result in a search
    if (query.term && query.term.toString && query.term.toString().length) {
      var term = self.apos.launder.string(query.term);
      cursor.autocomplete(term);
    } else {
      return callback(null, []);
    }

    if (!(query.filters && query.filters.limit)) {
      cursor.limit(10);
    }

    // This is the big payoff of blessing join fields: we can apply their
    // filters in API calls like this one, knowing that the field definition
    // the browser sent us is one the developer created
    cursor.queryToFilters(query.field.filters || {});

    // Format it as value & id properties for compatibility with jquery UI autocomplete
    cursor.toArray(function(err, docs) {
      if (err) {
        return callback(err);
      }
      // Put the snippets in id order
      if (query.values) {
        docs = self.apos.utils.orderById(query.values, docs);
      }
      var results = _.map(docs, function(doc) {
        var response = {
          // jquery ui autocomplete demands label and value
          label: self.getAutocompleteTitle(doc, query),
          value: doc._id
        };
        _.defaults(response, _.omit(doc, 'title', '_id'));
        return response;
      });
      return callback(null, results);
    });
  };

  // Adds a listener for the `docSearchIndex` Apostrophe event, pointing to the
  // `searchIndexListener` method.

  self.addSearchIndexListener = function() {
    self.apos.on('docSearchIndex', self.searchIndexListener);
  };

  // Invoked when a `docSearchIndex` event takes place, this method adds
  // additional search texts to the `texts` array (modify it in place by
  // pushing new objects to it). These texts influence search results.
  // The default behavior is quite useful, so you won't often need to
  // override this.
  //
  // Each "text" is an *object* and must have at least `weight` and `text` properties.
  // If `weight` is >= 10, the text will be included in autocomplete searches and
  // given higher priority in full-text searches. Otherwise it will be included
  // only in full-text searches.
  //
  // If `silent` is `true`, the `searchSummary` property will not contain
  // the text.
  //
  // By default this method invokes `schemas.indexFields`, which will push
  // texts for all of the schema fields that support this unless they are
  // explicitly set `searchable: false`.
  //
  // In any case, the text of rich text widgets is always included as
  // lower-priority search text.

  self.searchIndexListener = function(doc, texts) {
    if (doc.type !== self.name) {
      return;
    }
    self.apos.schemas.indexFields(self.schema, doc, texts);
  };

};
<|endoftext|>


<commit_before>// ==========================================================================
// Project:   xTuple Postbooks - Business Management System Framework
// Copyright: ©2012 OpenMFG LLC, d/b/a xTuple
// ==========================================================================

/*globals XM */

sc_require('mixins/_ledger_account');

/**
  @class

  @extends XT.Record
*/
XM.LedgerAccount = XT.Record.extend(XM._LedgerAccount,
/** @scope XM.LedgerAccount.prototype */ {

// .................................................
// CALCULATED PROPERTIES
//

number: SC.Record.attr(Number, {
  toType: function(record, key, value) {
  if(value) return value.get('length') <= 4 ? value : null;
  }
}),

//..................................................
// METHODS
//

//..................................................
// OBSERVERS
//

});

XM.LayoutIncomeStatementDetail.mixin( /** @scope XM.LayoutIncomeStatementDetail */ {

/**
  @static
  @constant
  @type String
  @default A
*/
  ASSET: 'A',

/**
  @static
  @constant
  @type String
  @default E
*/
  EXPENSE: 'E',

/**
  @static
  @constant
  @type String
  @default L
*/
  LIABILITY: 'L',

/**
  @static
  @constant
  @type String
  @default Q
*/
  EQUITY: 'Q',

/**
  @static
  @constant
  @type String
  @default R
*/
  REVENUE: 'R'

});
<commit_msg>fix to ledger account constants mixin<commit_after>// ==========================================================================
// Project:   xTuple Postbooks - Business Management System Framework
// Copyright: ©2012 OpenMFG LLC, d/b/a xTuple
// ==========================================================================

/*globals XM */

sc_require('mixins/_ledger_account');

/**
  @class

  @extends XT.Record
*/
XM.LedgerAccount = XT.Record.extend(XM._LedgerAccount,
/** @scope XM.LedgerAccount.prototype */ {

// .................................................
// CALCULATED PROPERTIES
//

number: SC.Record.attr(Number, {
  toType: function(record, key, value) {
  if(value) return value.get('length') <= 4 ? value : null;
  }
}),

//..................................................
// METHODS
//

//..................................................
// OBSERVERS
//

});

XM.LedgerAccount.mixin( /** @scope XM.LayoutIncomeStatementDetail */ {

/**
  @static
  @constant
  @type String
  @default A
*/
  ASSET: 'A',

/**
  @static
  @constant
  @type String
  @default E
*/
  EXPENSE: 'E',

/**
  @static
  @constant
  @type String
  @default L
*/
  LIABILITY: 'L',

/**
  @static
  @constant
  @type String
  @default Q
*/
  EQUITY: 'Q',

/**
  @static
  @constant
  @type String
  @default R
*/
  REVENUE: 'R'

});
<|endoftext|>


<commit_before>import stripePackage from "stripe";
import { calculateCost } from "./libs/billing-lib";
import { success, failure } from "./libs/response-lib";

export async function main(event, context, callback) {
  const { storage, source } = JSON.parse(event.body);
  const amount = calculateCost(storage);
  const description = "Scratch charge";

  // Load our secret key from the  environment variables
  const stripe = stripePackage(process.env.stripeSecretKey);

  try {
    await stripe.charges.create({
      source,
      amount,
      description,
      currency: "usd"
    });
    callback(null, success({ status: true }));
  } catch (e) {
    callback(null, failure({ message: e.message }));
  }
}
<commit_msg>Returning for async functions<commit_after>import stripePackage from "stripe";
import { calculateCost } from "./libs/billing-lib";
import { success, failure } from "./libs/response-lib";

export async function main(event, context) {
  const { storage, source } = JSON.parse(event.body);
  const amount = calculateCost(storage);
  const description = "Scratch charge";

  // Load our secret key from the  environment variables
  const stripe = stripePackage(process.env.stripeSecretKey);

  try {
    await stripe.charges.create({
      source,
      amount,
      description,
      currency: "usd"
    });
    return success({ status: true });
  } catch (e) {
    return failure({ message: e.message });
  }
}
<|endoftext|>


<commit_before>/**
 * Created by Mihail on 8/15/2016.
 */
'use strict';

import GenerateCardNumbers from '../../../src/card/card-numbers-generator';
import { expect } from 'chai';

describe('Card Numbers Generator', () => {

	let arrAmericanNumbers = [1, 2, 3, 4, 5,
							  6, 7, 8, 9, 10,
							  11, 12, 13, 14, 15,
							  16, 17, 18, 19, 20,
							  21, 22, 23, 24, 25,
							  26, 27, 28, 29, 30,
							  31, 32, 33, 34, 35,
							  36, 37, 38, 39, 40,
							  41, 42, 43, 44, 45,
							  46, 47, 48, 49, 50,
							  51, 52, 53, 54, 55,
							  56, 57, 58, 59, 60,
							  61, 62, 63, 64, 65,
							  66, 67, 68, 69, 70,
							  71, 72, 73, 74, 75
							 ];

	let cardGen = new GenerateCardNumbers({'gameConf': {'numbers': arrAmericanNumbers}});

	test('Should initialize with an array of 75 numbers', () => {
		expect(cardGen.arrAmericanNumbers.length).to.be.equal(75);
	});

	test(
        'Should generate a random card with 24 numbers divided by columns',
        () => {
            const card = cardGen.generate();

            expect(card).to.be.object;
            expect(card).to.have.property('col1').that.is.an('array').with.length.of(5);
            expect(card).to.have.property('col2').that.is.an('array').with.length.of(5);
            expect(card).to.have.property('col3').that.is.an('array').with.length.of(5);
            expect(card).to.have.property('col4').that.is.an('array').with.length.of(5);
            expect(card).to.have.property('col5').that.is.an('array').with.length.of(5);

        }
    );

});<commit_msg>:heavy_check_mark: Migrating front end unit tests from Mocha to Jest - updated card-numbers-generator.spec.js<commit_after>import GenerateCardNumbers from '../../../src/card/card-numbers-generator';

describe('Card Numbers Generator', () => {

  let arrAmericanNumbers = [1, 2, 3, 4, 5,
    6, 7, 8, 9, 10,
    11, 12, 13, 14, 15,
    16, 17, 18, 19, 20,
    21, 22, 23, 24, 25,
    26, 27, 28, 29, 30,
    31, 32, 33, 34, 35,
    36, 37, 38, 39, 40,
    41, 42, 43, 44, 45,
    46, 47, 48, 49, 50,
    51, 52, 53, 54, 55,
    56, 57, 58, 59, 60,
    61, 62, 63, 64, 65,
    66, 67, 68, 69, 70,
    71, 72, 73, 74, 75
  ];

  let cardGen = new GenerateCardNumbers({ 'gameConf': { 'numbers': arrAmericanNumbers } });

  test('Should initialize with an array of 75 numbers', () => {
    expect(cardGen.arrAmericanNumbers.length).toEqual(75);
  });

  test('Should generate a random card with 24 numbers divided by columns', () => {
      const card = cardGen.generate();

      expect(card).toBeTruthy();
      expect(card).toHaveProperty('col1');
      expect(card['col1'].length).toEqual(5);
      expect(card).toHaveProperty('col2');
      expect(card['col2'].length).toEqual(5);
      expect(card).toHaveProperty('col3');
      expect(card['col3'].length).toEqual(5);
      expect(card).toHaveProperty('col4');
      expect(card['col4'].length).toEqual(5);
      expect(card).toHaveProperty('col5');
      expect(card['col5'].length).toEqual(5);
    }
  );

});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var Datastore = require('nedb');
var Discord = require('discord.js');
var async = require('async');
var auth = require('../blitzbot.json');

// set WarGaming API key, so require does not return an init function
process.env.APPLICATION_ID = '48fe1a85faacb26a079a627f8483cb6f';

var helpers = require('../lib/helpers.js');
var wotblitz = require('wotblitz');

var client = new Discord.Client();
var db = new Datastore({
  filename: './blitzbot.db',
  timestampData: true,
});

var commands = {};

commands.add = {
  'args': 1,
  'description': 'Associate your blitz screenname with discord.',
  'fn': function(msg, screenname, cb) {
    screenname = screenname.toLowerCase();

    wotblitz.players.list(screenname, null, function(pErr, players) {
      if (pErr) return cb(pErr);

      var player = players.find(function(p) { return p.nickname.toLowerCase() === screenname; });

      if (player) {
        client.reply(msg, 'Welcome! You now have access to all commands. :)', {}, function(rErr, sent) {
          if (rErr) return cb(rErr);

          console.log('sent msg: ' + sent);
          cb(null, player);
        });
      } else {
        // this could be an error, but for now avoid the noise
        cb(null);
      }
    });
  },
  'passRecord': false,
  'signatures': ['@blitzbot add <screenname>'],
};

commands.roster = {
  'args': 1,
  'description': 'List a clan roster. Defaults to your clan if none specified.',
  'fn': function(msg, record, tag, cb) {
    if (typeof tag === 'function') {
      cb = tag;
      tag = null;
    }

    // if a tag was provided and is does not follow the rules
    if (tag && !tag.match(/^[A-Z0-9-_]{2,5}$/)) return cb(null);

    var doRoster = function(clan_id) {
      wotblitz.clans.info([clan_id], ['members'], ['name', 'members'], null, function(iErr, info) {
        if (iErr) return cb(iErr);

        var members = info[clan_id].members;
        var roleOrder = Array.prototype.indexOf.bind(['commander', 'executive_officer', 'private']);
        var roleStyle = {commander: /* bold */ '**', executive_officer: /* italics */ '*', private: null};
        var names = Object.keys(members)
          .map(function(id) { return members[id]; })
          .sort(helpers.sortBy({name: 'role', primer: roleOrder}, 'joined_at'))
          .map(function(member) {
            var style = roleStyle[member.role];

            return [style, member.account_name.replace(/([*_~])/g, '\\$1'), style].join('');
          });

        client.reply(msg, 'The roster for `' + info[clan_id].name + '` is: ' + names.join(', '), {}, function(rErr, sent) {
          if (rErr) return cb(rErr);

          console.log('sent msg: ' + sent);
          cb(null);
        });
      });
    };

    if (tag) {
      wotblitz.clans.list(tag, null, 1, ['clan_id', 'tag'], null, function(lErr, list) {
        if (lErr) return cb(lErr);

        var result = list.find(function(clan) {
          return clan.tag === tag;
        });

        if (!result) return cb(null);

        doRoster(result.clan_id);
      });
    } else {
      wotblitz.clans.accountinfo([record.account_id], [], ['clan_id'], null, function(aErr, accountinfo) {
        if (aErr) return cb(aErr);

        doRoster(accountinfo[record.account_id].clan_id);
      });
    }
  },
  'passRecord': true,
  'signatures': ['@blitzbot roster [clan-tag]'],
};

commands.tankWinRate = {
  'args': 1,
  'description': 'Get your win rate on the given tank (replace spaces with dashes).',
  'fn': function(msg, record, tankName, cb) {
    var fields = ['name', 'nation', 'tier'];

    tankName = tankName.replace(/-/g, ' ');

    wotblitz.tankopedia.vehicles(null, [], fields, function(vErr, tanks) {
      if (vErr) return cb(vErr);

      var tankIds = Object.keys(tanks).filter(function(id) {
        // this is not good enough, WarGaming is not very careful about giving tank unique names
        return tanks[id].name.indexOf(tankName) > -1;
      });

      if (tankIds.length < 1) {
        cb(null);
      }

      fields = ['tank_id', 'all.battles', 'all.wins'];

      wotblitz.tankStats.stats(Number(record.account_id), tankIds, null, fields, null, function(sErr, stats) {
        if (sErr) return cb(sErr);

        var lines = stats[record.account_id].map(function(stat) {
          var tankopedia = tanks[stat.tank_id];
          var winRate = (stat.all.wins / stat.all.battles) * 100;

          return tankopedia.name + ' (' + tankopedia.nation + ', ' + tankopedia.tier + '): ' + winRate.toFixed(2) + '%';
        });

        client.reply(msg, lines.join('\n'), {}, function(rErr, sent) {
          if (rErr) return cb(rErr);

          console.log('sent msg: ' + sent);
          cb(null);
        });
      });
    });
  },
  'passRecord': true,
  'signatures': ['@blitzbot tank-win-rate <tank-name>'],
};

commands.winRate = {
  'args': 0,
  'description': 'Get the win rate of your account.',
  'fn': function(msg, record, cb) {
    var fields = ['statistics.all.battles', 'statistics.all.wins'];

    wotblitz.players.info([record.account_id], [], fields, null, function(iErr, info) {
      if (iErr) return cb(iErr);

      var wins = info[record.account_id].statistics.all.wins;
      var battles = info[record.account_id].statistics.all.battles;
      var percent = (wins / battles) * 100;
      var send = 'You have won ' + wins + ' of ' + battles + ' battles. That is ' + percent.toFixed(2) + '% victory!';

      client.reply(msg, send, {}, function(rErr, sent) {
        if (rErr) return cb(rErr);

        console.log('sent msg: ' + sent);

        record.wins = wins;
        record.battles = battles;

        cb(null, record);
      });
    });
  },
  'passRecord': true,
  'signatures': ['@blitzbot win-rate'],
};

commands.help = {
  'args': 1,
  'description': 'List all known commands or get help for a particular command.',
  'fn': null,
  'passRecord': false,
  'signatures': [
    '@blitzbot help [command]',
    '(direct message): help [command]',
  ],
};

// done last so that the help function can read the entire "commands" structure
commands.help.fn = function(msg, helpFor, cb) {
  if (typeof helpFor === 'function') {
    cb = helpFor;
    helpFor = null;
  }

  var lines = [];
  var push = function(key) {
    commands[key].signatures.forEach(function(signature) {
      lines.push('`' + signature + '` -- ' + commands[key].description);
    });
  };

  if (helpFor) {
    if (helpFor in commands) {
      push(helpFor);
    } else {
      lines.push('Unknown command: ' + helpFor);
    }
  } else {
    Object.keys(commands).forEach(push);
  }

  async.each(lines, function(send, callback) {
    client.sendMessage(msg.author, send, {}, callback);
  }, function(err) {
    if (err) return cb(err);

    cb(null);
  });
};

client.on('ready', function() {
  console.log('blitzbot ready!');
  console.log('===============');
});

client.on('message', function(message) {
  // Bot will only respond in a DM or when mentioned.
  if (!message.channel.isPrivate && !message.isMentioned(client.user)) return;
  if (message.author.id === client.user.id) return;

  var userId = message.author.id;
  var text = message.cleanContent.split(' ');
  var index = text.findIndex(function(e, i, a) {
    return (message.channel.isPrivate && e === 'help') || (i > 0 && a[i - 1] === '@' + client.user.username);
  });
  // force command to camelcase
  var command = text[index].toLowerCase().replace(/-[A-Za-z]/g, function(m) { return m[1].toUpperCase(); });
  var args = text.slice(index + 1);

  if (!(command in commands)) return;

  async.auto({
    record: function(cb) { db.findOne({_id: userId}, cb); },
    runCmd: ['record', function(cb, d) {
      console.log(userId + ' -- running command: "' + command + '"');

      var obj = commands[command];
      var arr = [message];

      if (obj.passRecord) {
        // commands require a saved 'account_id'.
        if (d.record && d.record.account_id) {
          arr.push(d.record);
        } else {
          var send = "I don't know who you are! Do `@blitzbot add <screenname>` first.";

          return client.reply(message, send, {}, function(aErr, sent) {
            if (aErr) return cb(aErr);

            console.log('sent msg: ' + sent);
            cb(null);
          });
        }
      }

      if (obj.args > 0) Array.prototype.push.apply(arr, args.slice(0, obj.args));
      arr.push(cb);

      obj.fn.apply(null, arr);
    }],
    update: ['runCmd', function(cb, d) {
      if (!d.runCmd) return cb(null);

      console.log(userId + ' -- update document');

      var newRecord = d.runCmd;

      newRecord._id = userId;
      delete newRecord.updatedAt;

      db.update({_id: userId}, newRecord, {upsert: true}, cb);
    }],
  }, function(err) {
    if (err) return console.error(helpers.getFieldByPath(err, 'response.error.text') || err.stack || err);

    console.log(userId + ' -- done');
  });
});

async.auto({
  loadDb: function(cb) { db.loadDatabase(cb); },
  discordLogin: function(cb) { client.loginWithToken(auth.user.token, null, null, cb); },
}, function(err) {
  if (err) return console.error(helpers.getFieldByPath(err, 'response.error.text') || err.stack || err);
});
<commit_msg>Clan roster cleanup.<commit_after>#!/usr/bin/env node

var Datastore = require('nedb');
var Discord = require('discord.js');
var async = require('async');
var auth = require('../blitzbot.json');

// set WarGaming API key, so require does not return an init function
process.env.APPLICATION_ID = '48fe1a85faacb26a079a627f8483cb6f';

var helpers = require('../lib/helpers.js');
var wotblitz = require('wotblitz');

var client = new Discord.Client();
var db = new Datastore({
  filename: './blitzbot.db',
  timestampData: true,
});

var commands = {};

commands.add = {
  'args': 1,
  'description': 'Associate your blitz screenname with discord.',
  'fn': function(msg, screenname, cb) {
    screenname = screenname.toLowerCase();

    wotblitz.players.list(screenname, null, function(pErr, players) {
      if (pErr) return cb(pErr);

      var player = players.find(function(p) { return p.nickname.toLowerCase() === screenname; });

      if (player) {
        client.reply(msg, 'Welcome! You now have access to all commands. :)', {}, function(rErr, sent) {
          if (rErr) return cb(rErr);

          console.log('sent msg: ' + sent);
          cb(null, player);
        });
      } else {
        // this could be an error, but for now avoid the noise
        cb(null);
      }
    });
  },
  'passRecord': false,
  'signatures': ['@blitzbot add <screenname>'],
};

commands.roster = {
  'args': 1,
  'description': 'List a clan roster. Defaults to your clan if none specified.',
  'fn': function(msg, record, tag, cb) {
    if (typeof tag === 'function') {
      cb = tag;
      tag = null;
    }

    var doRoster = function(clan_id) {
      wotblitz.clans.info([clan_id], ['members'], ['name', 'members'], null, function(iErr, info) {
        if (iErr) return cb(iErr);

        var members = info[clan_id].members;
        var roleOrder = Array.prototype.indexOf.bind(['commander', 'executive_officer', 'private']);
        var roleStyle = {commander: /* bold */ '**', executive_officer: /* italics */ '*', private: null};
        var names = Object.keys(members)
          .map(function(id) { return members[id]; })
          .sort(helpers.sortBy({name: 'role', primer: roleOrder}, 'joined_at'))
          .map(function(member) {
            var style = roleStyle[member.role];

            return [style, member.account_name.replace(/([*_~])/g, '\\$1'), style].join('');
          });
        var text = 'The roster for `' + info[clan_id].name + '` is: ' + names.join(', ');

        client.reply(msg, text, {}, function(rErr, sent) {
          if (rErr) return cb(rErr);

          console.log('sent msg: ' + sent);
          cb(null);
        });
      });
    };

    if (tag) {
      tag = tag.toUpperCase();

      // if a tag does not follow the rules
      if (!tag.match(/^[A-Z0-9-_]{2,5}$/)) return cb(null);

      wotblitz.clans.list(tag, null, 1, ['clan_id', 'tag'], null, function(lErr, list) {
        if (lErr) return cb(lErr);

        var result = list.find(function(clan) {
          return clan.tag === tag;
        });

        if (!result) return cb(null);

        doRoster(result.clan_id);
      });
    } else {
      wotblitz.clans.accountinfo([record.account_id], [], ['clan_id'], null, function(aErr, accountinfo) {
        if (aErr) return cb(aErr);

        doRoster(accountinfo[record.account_id].clan_id);
      });
    }
  },
  'passRecord': true,
  'signatures': ['@blitzbot roster [clan-tag]'],
};

commands.tankWinRate = {
  'args': 1,
  'description': 'Get your win rate on the given tank (replace spaces with dashes).',
  'fn': function(msg, record, tankName, cb) {
    var fields = ['name', 'nation', 'tier'];

    tankName = tankName.replace(/-/g, ' ');

    wotblitz.tankopedia.vehicles(null, [], fields, function(vErr, tanks) {
      if (vErr) return cb(vErr);

      var tankIds = Object.keys(tanks).filter(function(id) {
        // this is not good enough, WarGaming is not very careful about giving tank unique names
        return tanks[id].name.indexOf(tankName) > -1;
      });

      if (tankIds.length < 1) {
        cb(null);
      }

      fields = ['tank_id', 'all.battles', 'all.wins'];

      wotblitz.tankStats.stats(Number(record.account_id), tankIds, null, fields, null, function(sErr, stats) {
        if (sErr) return cb(sErr);

        var lines = stats[record.account_id].map(function(stat) {
          var tankopedia = tanks[stat.tank_id];
          var winRate = (stat.all.wins / stat.all.battles) * 100;

          return tankopedia.name + ' (' + tankopedia.nation + ', ' + tankopedia.tier + '): ' + winRate.toFixed(2) + '%';
        });

        client.reply(msg, lines.join('\n'), {}, function(rErr, sent) {
          if (rErr) return cb(rErr);

          console.log('sent msg: ' + sent);
          cb(null);
        });
      });
    });
  },
  'passRecord': true,
  'signatures': ['@blitzbot tank-win-rate <tank-name>'],
};

commands.winRate = {
  'args': 0,
  'description': 'Get the win rate of your account.',
  'fn': function(msg, record, cb) {
    var fields = ['statistics.all.battles', 'statistics.all.wins'];

    wotblitz.players.info([record.account_id], [], fields, null, function(iErr, info) {
      if (iErr) return cb(iErr);

      var wins = info[record.account_id].statistics.all.wins;
      var battles = info[record.account_id].statistics.all.battles;
      var percent = (wins / battles) * 100;
      var send = 'You have won ' + wins + ' of ' + battles + ' battles. That is ' + percent.toFixed(2) + '% victory!';

      client.reply(msg, send, {}, function(rErr, sent) {
        if (rErr) return cb(rErr);

        console.log('sent msg: ' + sent);

        record.wins = wins;
        record.battles = battles;

        cb(null, record);
      });
    });
  },
  'passRecord': true,
  'signatures': ['@blitzbot win-rate'],
};

commands.help = {
  'args': 1,
  'description': 'List all known commands or get help for a particular command.',
  'fn': null,
  'passRecord': false,
  'signatures': [
    '@blitzbot help [command]',
    '(direct message): help [command]',
  ],
};

// done last so that the help function can read the entire "commands" structure
commands.help.fn = function(msg, helpFor, cb) {
  if (typeof helpFor === 'function') {
    cb = helpFor;
    helpFor = null;
  }

  var lines = [];
  var push = function(key) {
    commands[key].signatures.forEach(function(signature) {
      lines.push('`' + signature + '` -- ' + commands[key].description);
    });
  };

  if (helpFor) {
    if (helpFor in commands) {
      push(helpFor);
    } else {
      lines.push('Unknown command: ' + helpFor);
    }
  } else {
    Object.keys(commands).forEach(push);
  }

  async.each(lines, function(send, callback) {
    client.sendMessage(msg.author, send, {}, callback);
  }, function(err) {
    if (err) return cb(err);

    cb(null);
  });
};

client.on('ready', function() {
  console.log('blitzbot ready!');
  console.log('===============');
});

client.on('message', function(message) {
  // Bot will only respond in a DM or when mentioned.
  if (!message.channel.isPrivate && !message.isMentioned(client.user)) return;
  if (message.author.id === client.user.id) return;

  var userId = message.author.id;
  var text = message.cleanContent.split(' ');
  var index = text.findIndex(function(e, i, a) {
    return (message.channel.isPrivate && e === 'help') || (i > 0 && a[i - 1] === '@' + client.user.username);
  });
  // force command to camelcase
  var command = text[index].toLowerCase().replace(/-[A-Za-z]/g, function(m) { return m[1].toUpperCase(); });
  var args = text.slice(index + 1);

  if (!(command in commands)) return;

  async.auto({
    record: function(cb) { db.findOne({_id: userId}, cb); },
    runCmd: ['record', function(cb, d) {
      console.log(userId + ' -- running command: "' + command + '"');

      var obj = commands[command];
      var arr = [message];

      if (obj.passRecord) {
        // commands require a saved 'account_id'.
        if (d.record && d.record.account_id) {
          arr.push(d.record);
        } else {
          var send = "I don't know who you are! Do `@blitzbot add <screenname>` first.";

          return client.reply(message, send, {}, function(aErr, sent) {
            if (aErr) return cb(aErr);

            console.log('sent msg: ' + sent);
            cb(null);
          });
        }
      }

      if (obj.args > 0) Array.prototype.push.apply(arr, args.slice(0, obj.args));
      arr.push(cb);

      obj.fn.apply(null, arr);
    }],
    update: ['runCmd', function(cb, d) {
      if (!d.runCmd) return cb(null);

      console.log(userId + ' -- update document');

      var newRecord = d.runCmd;

      newRecord._id = userId;
      delete newRecord.updatedAt;

      db.update({_id: userId}, newRecord, {upsert: true}, cb);
    }],
  }, function(err) {
    if (err) return console.error(helpers.getFieldByPath(err, 'response.error.text') || err.stack || err);

    console.log(userId + ' -- done');
  });
});

async.auto({
  loadDb: function(cb) { db.loadDatabase(cb); },
  discordLogin: function(cb) { client.loginWithToken(auth.user.token, null, null, cb); },
}, function(err) {
  if (err) return console.error(helpers.getFieldByPath(err, 'response.error.text') || err.stack || err);
});
<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
 * The main command line interface for running Angularity
 * from the npm global install.
 */
'use strict';

var path        = require('path'),
    gulp        = require('gulp'),
    gutil       = require('gulp-util'),
    wordwrap    = require('wordwrap'),
    runSequence = require('run-sequence'),
    chalk       = require('chalk'),
    prettyTime  = require('pretty-hrtime'),
    yargs       = require('yargs');

var taskYargs     = require('../lib/util/task-yargs'),
    taskYargsRun  = require('../lib/util/task-yargs-run');

// TODO @bholloway menus
// var mainMenu = require('../lib/cli/mainMenu');

// we need to duplicate some event handlers from the gulp cli since we have bypassed it
gulp.on('task_start', function (e) {
  gutil.log('Starting', '\'' + chalk.cyan(e.task) + '\'...');
});

gulp.on('task_stop', function (e) {
  var time = prettyTime(e.hrDuration);
  gutil.log(
    'Finished', '\'' + chalk.cyan(e.task) + '\'',
    'after', chalk.magenta(time)
  );
});

var packageJson = require(path.join(__dirname, '..', 'package.json'));
var helpOption = {
  key: 'help',
  value: {
    describe: 'This help message, or help on a specific task',
    alias: ['h', '?'],
    boolean: true
  }
};
var defaultYargsInstance = yargs
  .usage(wordwrap(2, 80)([
    packageJson.description,
    '',
    'Tasks include:'
    //TODO add task list here
  ].join('\n')))
  // .example('angularity', 'Interactive menu') //TODO reinstate when interactive menu is reinstated
  .example('angularity -v', 'Display the version of angularity')
  .example('angularity \<task name\> -h', 'Get help on a particular task')
  .example('angularity \<task name\>', 'Run the given task')
  .option('version', {
    describe: 'Display the curent version',
    alias: ['v'],
    boolean: true
  })
  .option(helpOption.key, helpOption.value);

taskYargsRun.taskYargs.register('help', {
  description: (wordwrap(2, 80)('Displays context-specific help messages')),
  prerequisiteTasks: [],
  options: [
    {
      key: 'help',
      value: {
        describe: 'This help message, or help on a specific task',
        alias: ['h', '?'],
        boolean: true
      }
    }
  ],
  checks: []
});

require('../index');

//TODO move these to ../index.js
require('../tasks/html')(taskYargsRun);
require('../tasks/css')(taskYargsRun);
require('../tasks/javascript')(taskYargsRun);
require('../tasks/test')(taskYargsRun);
require('../tasks/build')(taskYargsRun);
require('../tasks/release')(taskYargsRun);
require('../tasks/server')(taskYargsRun);
require('../tasks/watch')(taskYargsRun);
require('../tasks/init')(taskYargsRun);
require('../tasks/webstorm')(taskYargsRun);

var cliArgs;
var taskName = taskYargsRun.taskYargs.getCurrentName();
if (taskName) {
  taskYargsRun.current();
}
else {
  cliArgs = defaultYargsInstance.argv;
  if (cliArgs.version) {
    console.log('angularity:', packageJson.version);
  }
  else {
    if (!cliArgs.help) {
      console.log('Task specified is not recognised');
    }
    defaultYargsInstance.showHelp();
  }
}
<commit_msg>removed commented code<commit_after>#!/usr/bin/env node
/**
 * The main command line interface for running Angularity
 * from the npm global install.
 */
'use strict';

var path        = require('path'),
    gulp        = require('gulp'),
    gutil       = require('gulp-util'),
    wordwrap    = require('wordwrap'),
    runSequence = require('run-sequence'),
    chalk       = require('chalk'),
    prettyTime  = require('pretty-hrtime'),
    yargs       = require('yargs');

var taskYargs     = require('../lib/util/task-yargs'),
    taskYargsRun  = require('../lib/util/task-yargs-run');

// we need to duplicate some event handlers from the gulp cli since we have bypassed it
gulp.on('task_start', function (e) {
  gutil.log('Starting', '\'' + chalk.cyan(e.task) + '\'...');
});

gulp.on('task_stop', function (e) {
  var time = prettyTime(e.hrDuration);
  gutil.log(
    'Finished', '\'' + chalk.cyan(e.task) + '\'',
    'after', chalk.magenta(time)
  );
});

var packageJson = require(path.join(__dirname, '..', 'package.json'));
var helpOption = {
  key: 'help',
  value: {
    describe: 'This help message, or help on a specific task',
    alias: ['h', '?'],
    boolean: true
  }
};
var defaultYargsInstance = yargs
  .usage(wordwrap(2, 80)([
    packageJson.description,
    '',
    'Tasks include:'
    //TODO add task list here
  ].join('\n')))
  // .example('angularity', 'Interactive menu') //TODO reinstate when interactive menu is reinstated
  .example('angularity -v', 'Display the version of angularity')
  .example('angularity \<task name\> -h', 'Get help on a particular task')
  .example('angularity \<task name\>', 'Run the given task')
  .option('version', {
    describe: 'Display the curent version',
    alias: ['v'],
    boolean: true
  })
  .option(helpOption.key, helpOption.value);

taskYargsRun.taskYargs.register('help', {
  description: (wordwrap(2, 80)('Displays context-specific help messages')),
  prerequisiteTasks: [],
  options: [
    {
      key: 'help',
      value: {
        describe: 'This help message, or help on a specific task',
        alias: ['h', '?'],
        boolean: true
      }
    }
  ],
  checks: []
});

require('../index');

//TODO move these to ../index.js
require('../tasks/html')(taskYargsRun);
require('../tasks/css')(taskYargsRun);
require('../tasks/javascript')(taskYargsRun);
require('../tasks/test')(taskYargsRun);
require('../tasks/build')(taskYargsRun);
require('../tasks/release')(taskYargsRun);
require('../tasks/server')(taskYargsRun);
require('../tasks/watch')(taskYargsRun);
require('../tasks/init')(taskYargsRun);
require('../tasks/webstorm')(taskYargsRun);

var cliArgs;
var taskName = taskYargsRun.taskYargs.getCurrentName();
if (taskName) {
  taskYargsRun.current();
}
else {
  cliArgs = defaultYargsInstance.argv;
  if (cliArgs.version) {
    console.log('angularity:', packageJson.version);
  }
  else {
    if (!cliArgs.help) {
      console.log('Task specified is not recognised');
    }
    defaultYargsInstance.showHelp();
  }
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
 * math.js
 * https://github.com/josdejong/mathjs
 *
 * Math.js is an extensive math library for JavaScript and Node.js,
 * It features real and complex numbers, units, matrices, a large set of
 * mathematical functions, and a flexible expression parser.
 *
 * Usage:
 *
 *     mathjs [scriptfile(s)] {OPTIONS}
 *
 * Options:
 *
 *     --version, -v       Show application version
 *     --help,    -h       Show this message
 *     --tex               Generate LaTeX instead of evaluating
 *     --string            Generate string instead of evaluating
 *     --parenthesis=      Set the parenthesis option to
 *                         either of "keep", "auto" and "all"
 *
 * Example usage:
 *     mathjs                                 Open a command prompt
 *     mathjs script.txt                      Run a script file
 *     mathjs script1.txt script2.txt         Run two script files
 *     mathjs script.txt > results.txt        Run a script file, output to file
 *     cat script.txt | mathjs                Run input stream
 *     cat script.txt | mathjs > results.txt  Run input stream, output to file
 *
 * @license
 * Copyright (C) 2013-2016 Jos de Jong <wjosdejong@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy
 * of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

var math = require('../index');
var scope = {};
var fs = require('fs');

var PRECISION = 14; // decimals

/**
 * Helper function to format a value. Regular numbers will be rounded
 * to 14 digits to prevent round-off errors from showing up.
 * @param {*} value
 */
function format(value) {
  return math.format(value, {
    fn: function (value) {
      if (typeof value === 'number') {
        // round numbers
        return math.format(value, PRECISION);
      }
      else {
        return math.format(value);
      }
    }
  });
}

/**
 * auto complete a text
 * @param {String} text
 * @return {[Array, String]} completions
 */
function completer (text) {
  var name;
  var matches = [];
  var m = /[a-zA-Z_0-9]+$/.exec(text);
  if (m) {
    var keyword = m[0];

    // scope variables
    for (var def in scope) {
      if (scope.hasOwnProperty(def)) {
        if (def.indexOf(keyword) == 0) {
          matches.push(def);
        }
      }
    }

    // commandline keywords
    ['exit', 'quit', 'clear'].forEach(function (cmd) {
      if (cmd.indexOf(keyword) == 0) {
        matches.push(cmd);
      }
    });

    // math functions and constants
    var ignore = ['expr', 'type'];
    for (var func in math) {
      if (math.hasOwnProperty(func)) {
        if (func.indexOf(keyword) == 0 && ignore.indexOf(func) == -1) {
          matches.push(func);
        }
      }
    }

    // units
    var Unit = math.type.Unit;
    for (name in Unit.UNITS) {
      if (Unit.UNITS.hasOwnProperty(name)) {
        if (name.indexOf(keyword) == 0) {
          matches.push(name);
        }
      }
    }
    for (name in Unit.PREFIXES) {
      if (Unit.PREFIXES.hasOwnProperty(name)) {
        var prefixes = Unit.PREFIXES[name];
        for (var prefix in prefixes) {
          if (prefixes.hasOwnProperty(prefix)) {
            if (prefix.indexOf(keyword) == 0) {
              matches.push(prefix);
            }
            else if (keyword.indexOf(prefix) == 0) {
              var unitKeyword = keyword.substring(prefix.length);
              for (var n in Unit.UNITS) {
                if (Unit.UNITS.hasOwnProperty(n)) {
                  if (n.indexOf(unitKeyword) == 0 &&
                      Unit.isValuelessUnit(prefix + n)) {
                    matches.push(prefix + n);
                  }
                }
              }
            }
          }
        }
      }
    }

    // remove duplicates
    matches = matches.filter(function(elem, pos, arr) {
      return arr.indexOf(elem) == pos;
    });
  }

  return [matches, keyword];
}

/**
 * Run stream, read and evaluate input and stream that to output.
 * Text lines read from the input are evaluated, and the results are send to
 * the output.
 * @param input   Input stream
 * @param output  Output stream
 * @param mode    Output mode
 * @param parenthesis Parenthesis option
 */
function runStream (input, output, mode, parenthesis) {
  var readline = require('readline'),
      rl = readline.createInterface({
        input: input || process.stdin,
        output: output || process.stdout,
        completer: completer
      });

  if (rl.output.isTTY) {
    rl.setPrompt('> ');
    rl.prompt();
  }

  // TODO: automatic insertion of 'ans' before operators like +, -, *, /

  rl.on('line', function(line) {
    var expr = line.trim();

    switch (expr.toLowerCase()) {
      case 'quit':
      case 'exit':
        // exit application
        rl.close();
        break;
      case 'clear':
        // clear memory
        scope = {};
        console.log('memory cleared');

        // get next input
        if (rl.output.isTTY) {
          rl.prompt();
        }
        break;
      default:
        if (!expr) {
          break;
        }
        switch (mode) {
          case 'eval':
            // evaluate expression
            try {
              var node = math.parse(expr);
              var res = node.eval(scope);
              if (node.isAssignmentNode || node.isUpdateNode) {
                console.log(node.name + ' = ' + format(scope[node.name]));
              }
              else if (res.isResultSet) {
                res.entries.forEach(function (entry) {
                  console.log(format(entry));
                });
                if (res.entries.length) {
                  // set last answer from the ResultSet as ans
                  scope.ans = res.entries[res.entries.length - 1];
                }
              }
              else if (res instanceof math.type.Help) {
                console.log(res.toString());
              }
              else {
                scope.ans = res;
                console.log(format(res));
              }
            }
            catch (err) {
              console.log(err.toString());
            }
            break;

          case 'string':
            try {
              var string = math.parse(expr).toString({parenthesis: parenthesis});
              console.log(string);
            }
            catch (err) {
              console.log(err.toString());
            }
            break;

          case 'tex':
            try {
              var tex = math.parse(expr).toTex({parenthesis: parenthesis});
              console.log(tex);
            }
            catch (err) {
              console.log(err.toString());
            }
            break;
        }
    }

    // get next input
    if (rl.output.isTTY) {
      rl.prompt();
    }
  });

  rl.on('close', function() {
    console.log();
    process.exit(0);
  });
}

/**
 * Output application version number.
 * Version number is read version from package.json.
 */
function outputVersion () {
  fs.readFile(__dirname + '/../package.json', function (err, data) {
    if (err) {
      console.log(err.toString());
    }
    else {
      var pkg = JSON.parse(data);
      var version = pkg && pkg.version ? pkg.version : 'unknown';
      console.log(version);
    }
    process.exit(0);
  });
}

/**
 * Output a help message
 */
function outputHelp() {
  console.log('math.js');
  console.log('http://mathjs.org');
  console.log();
  console.log('Math.js is an extensive math library for JavaScript and Node.js. It features ');
  console.log('real and complex numbers, units, matrices, a large set of mathematical');
  console.log('functions, and a flexible expression parser.');
  console.log();
  console.log('Usage:');
  console.log('    mathjs [scriptfile(s)] {OPTIONS}');
  console.log();
  console.log('Options:');
  console.log('    --version, -v       Show application version');
  console.log('    --help,    -h       Show this message');
  console.log('    --tex               Generate LaTeX instead of evaluating');
  console.log('    --string            Generate string instead of evaluating');
  console.log('    --parenthesis=      Set the parenthesis option to');
  console.log('                        either of "keep", "auto" and "all"');
  console.log();
  console.log('Example usage:');
  console.log('    mathjs                                Open a command prompt');
  console.log('    mathjs script.txt                     Run a script file');
  console.log('    mathjs script.txt script2.txt         Run two script files');
  console.log('    mathjs script.txt > results.txt       Run a script file, output to file');
  console.log('    cat script.txt | mathjs               Run input stream');
  console.log('    cat script.txt | mathjs > results.txt Run input stream, output to file');
  console.log();
  process.exit(0);
}

/**
 * Process input and output, based on the command line arguments
 */
var scripts = []; //queue of scripts that need to be processed
var mode = 'eval'; //one of 'eval', 'tex' or 'string'
var parenthesis = 'keep';
var version = false;
var help = false;

process.argv.forEach(function (arg, index) {
  if (index < 2) {
    return;
  }

  switch (arg) {
    case '-v':
    case '--version':
      version = true;
      break;

    case '-h':
    case '--help':
      help = true;
      break;

    case '--tex':
      mode = 'tex';
      break;

    case '--string':
      mode = 'string';
      break;

    case '--parenthesis=keep':
      parenthesis = 'keep';
      break;

    case '--parenthesis=auto':
      parenthesis = 'auto';
      break;

    case '--parenthesis=all':
      parenthesis = 'all';
      break;

    // TODO: implement configuration via command line arguments

    default:
      scripts.push(arg);
  }
});

if (version) {
  outputVersion();
}
else if (help) {
  outputHelp();
}
else if (scripts.length === 0) {
  // run a stream, can be user input or pipe input
  runStream(process.stdin, process.stdout, mode, parenthesis);
}
else {
  //work through the queue of scripts
  scripts.forEach(function (arg) {
    // run a script file
    runStream(fs.createReadStream(arg), process.stdout, mode, parenthesis);
  });
}
<commit_msg>Improved handling of result sets<commit_after>#!/usr/bin/env node
/**
 * math.js
 * https://github.com/josdejong/mathjs
 *
 * Math.js is an extensive math library for JavaScript and Node.js,
 * It features real and complex numbers, units, matrices, a large set of
 * mathematical functions, and a flexible expression parser.
 *
 * Usage:
 *
 *     mathjs [scriptfile(s)] {OPTIONS}
 *
 * Options:
 *
 *     --version, -v       Show application version
 *     --help,    -h       Show this message
 *     --tex               Generate LaTeX instead of evaluating
 *     --string            Generate string instead of evaluating
 *     --parenthesis=      Set the parenthesis option to
 *                         either of "keep", "auto" and "all"
 *
 * Example usage:
 *     mathjs                                 Open a command prompt
 *     mathjs script.txt                      Run a script file
 *     mathjs script1.txt script2.txt         Run two script files
 *     mathjs script.txt > results.txt        Run a script file, output to file
 *     cat script.txt | mathjs                Run input stream
 *     cat script.txt | mathjs > results.txt  Run input stream, output to file
 *
 * @license
 * Copyright (C) 2013-2016 Jos de Jong <wjosdejong@gmail.com>
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy
 * of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

var math = require('../index');
var scope = {};
var fs = require('fs');

var PRECISION = 14; // decimals

/**
 * Helper function to format a value. Regular numbers will be rounded
 * to 14 digits to prevent round-off errors from showing up.
 * @param {*} value
 */
function format(value) {
  return math.format(value, {
    fn: function (value) {
      if (typeof value === 'number') {
        // round numbers
        return math.format(value, PRECISION);
      }
      else {
        return math.format(value);
      }
    }
  });
}

/**
 * auto complete a text
 * @param {String} text
 * @return {[Array, String]} completions
 */
function completer (text) {
  var name;
  var matches = [];
  var m = /[a-zA-Z_0-9]+$/.exec(text);
  if (m) {
    var keyword = m[0];

    // scope variables
    for (var def in scope) {
      if (scope.hasOwnProperty(def)) {
        if (def.indexOf(keyword) == 0) {
          matches.push(def);
        }
      }
    }

    // commandline keywords
    ['exit', 'quit', 'clear'].forEach(function (cmd) {
      if (cmd.indexOf(keyword) == 0) {
        matches.push(cmd);
      }
    });

    // math functions and constants
    var ignore = ['expr', 'type'];
    for (var func in math) {
      if (math.hasOwnProperty(func)) {
        if (func.indexOf(keyword) == 0 && ignore.indexOf(func) == -1) {
          matches.push(func);
        }
      }
    }

    // units
    var Unit = math.type.Unit;
    for (name in Unit.UNITS) {
      if (Unit.UNITS.hasOwnProperty(name)) {
        if (name.indexOf(keyword) == 0) {
          matches.push(name);
        }
      }
    }
    for (name in Unit.PREFIXES) {
      if (Unit.PREFIXES.hasOwnProperty(name)) {
        var prefixes = Unit.PREFIXES[name];
        for (var prefix in prefixes) {
          if (prefixes.hasOwnProperty(prefix)) {
            if (prefix.indexOf(keyword) == 0) {
              matches.push(prefix);
            }
            else if (keyword.indexOf(prefix) == 0) {
              var unitKeyword = keyword.substring(prefix.length);
              for (var n in Unit.UNITS) {
                if (Unit.UNITS.hasOwnProperty(n)) {
                  if (n.indexOf(unitKeyword) == 0 &&
                      Unit.isValuelessUnit(prefix + n)) {
                    matches.push(prefix + n);
                  }
                }
              }
            }
          }
        }
      }
    }

    // remove duplicates
    matches = matches.filter(function(elem, pos, arr) {
      return arr.indexOf(elem) == pos;
    });
  }

  return [matches, keyword];
}

/**
 * Run stream, read and evaluate input and stream that to output.
 * Text lines read from the input are evaluated, and the results are send to
 * the output.
 * @param input   Input stream
 * @param output  Output stream
 * @param mode    Output mode
 * @param parenthesis Parenthesis option
 */
function runStream (input, output, mode, parenthesis) {
  var readline = require('readline'),
      rl = readline.createInterface({
        input: input || process.stdin,
        output: output || process.stdout,
        completer: completer
      });

  if (rl.output.isTTY) {
    rl.setPrompt('> ');
    rl.prompt();
  }

  // TODO: automatic insertion of 'ans' before operators like +, -, *, /

  rl.on('line', function(line) {
    var expr = line.trim();

    switch (expr.toLowerCase()) {
      case 'quit':
      case 'exit':
        // exit application
        rl.close();
        break;
      case 'clear':
        // clear memory
        scope = {};
        console.log('memory cleared');

        // get next input
        if (rl.output.isTTY) {
          rl.prompt();
        }
        break;
      default:
        if (!expr) {
          break;
        }
        switch (mode) {
          case 'eval':
            // evaluate expression
            try {
              var node = math.parse(expr);
              var res = node.eval(scope);

              if (res.isResultSet) {
                // we can have 0 or 1 results in the ResultSet, as the CLI
                // does not allow multiple expressions separated by a return
                res = res.entries[0];
                node = node.blocks
                    .filter(function (entry) { return entry.visible; })
                    .map(function (entry) { return entry.node })[0];
              }

              if (node) {
                if (node.isAssignmentNode || node.isUpdateNode) {
                  scope.ans = scope[node.name];
                  console.log(node.name + ' = ' + format(scope[node.name]));
                }
                else if (res instanceof math.type.Help) {
                  console.log(res.toString());
                }
                else {
                  scope.ans = res;
                  console.log(format(res));
                }
              }
            }
            catch (err) {
              console.log(err.toString());
            }
            break;

          case 'string':
            try {
              var string = math.parse(expr).toString({parenthesis: parenthesis});
              console.log(string);
            }
            catch (err) {
              console.log(err.toString());
            }
            break;

          case 'tex':
            try {
              var tex = math.parse(expr).toTex({parenthesis: parenthesis});
              console.log(tex);
            }
            catch (err) {
              console.log(err.toString());
            }
            break;
        }
    }

    // get next input
    if (rl.output.isTTY) {
      rl.prompt();
    }
  });

  rl.on('close', function() {
    console.log();
    process.exit(0);
  });
}

/**
 * Output application version number.
 * Version number is read version from package.json.
 */
function outputVersion () {
  fs.readFile(__dirname + '/../package.json', function (err, data) {
    if (err) {
      console.log(err.toString());
    }
    else {
      var pkg = JSON.parse(data);
      var version = pkg && pkg.version ? pkg.version : 'unknown';
      console.log(version);
    }
    process.exit(0);
  });
}

/**
 * Output a help message
 */
function outputHelp() {
  console.log('math.js');
  console.log('http://mathjs.org');
  console.log();
  console.log('Math.js is an extensive math library for JavaScript and Node.js. It features ');
  console.log('real and complex numbers, units, matrices, a large set of mathematical');
  console.log('functions, and a flexible expression parser.');
  console.log();
  console.log('Usage:');
  console.log('    mathjs [scriptfile(s)] {OPTIONS}');
  console.log();
  console.log('Options:');
  console.log('    --version, -v       Show application version');
  console.log('    --help,    -h       Show this message');
  console.log('    --tex               Generate LaTeX instead of evaluating');
  console.log('    --string            Generate string instead of evaluating');
  console.log('    --parenthesis=      Set the parenthesis option to');
  console.log('                        either of "keep", "auto" and "all"');
  console.log();
  console.log('Example usage:');
  console.log('    mathjs                                Open a command prompt');
  console.log('    mathjs script.txt                     Run a script file');
  console.log('    mathjs script.txt script2.txt         Run two script files');
  console.log('    mathjs script.txt > results.txt       Run a script file, output to file');
  console.log('    cat script.txt | mathjs               Run input stream');
  console.log('    cat script.txt | mathjs > results.txt Run input stream, output to file');
  console.log();
  process.exit(0);
}

/**
 * Process input and output, based on the command line arguments
 */
var scripts = []; //queue of scripts that need to be processed
var mode = 'eval'; //one of 'eval', 'tex' or 'string'
var parenthesis = 'keep';
var version = false;
var help = false;

process.argv.forEach(function (arg, index) {
  if (index < 2) {
    return;
  }

  switch (arg) {
    case '-v':
    case '--version':
      version = true;
      break;

    case '-h':
    case '--help':
      help = true;
      break;

    case '--tex':
      mode = 'tex';
      break;

    case '--string':
      mode = 'string';
      break;

    case '--parenthesis=keep':
      parenthesis = 'keep';
      break;

    case '--parenthesis=auto':
      parenthesis = 'auto';
      break;

    case '--parenthesis=all':
      parenthesis = 'all';
      break;

    // TODO: implement configuration via command line arguments

    default:
      scripts.push(arg);
  }
});

if (version) {
  outputVersion();
}
else if (help) {
  outputHelp();
}
else if (scripts.length === 0) {
  // run a stream, can be user input or pipe input
  runStream(process.stdin, process.stdout, mode, parenthesis);
}
else {
  //work through the queue of scripts
  scripts.forEach(function (arg) {
    // run a script file
    runStream(fs.createReadStream(arg), process.stdout, mode, parenthesis);
  });
}
<|endoftext|>


<commit_before>import React from 'react';
import Grid from 'material-ui/Grid';
import PropTypes from 'prop-types';
import { reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import GridColumn from '../../../common/grid/gridColumn';
import Timeline from './timeline';
import ProjectDetails from './projectDetails';
import SelectionCriteria from './selectionCriteria';
import InformedPartners from './informedPartners';
import { selectCfeiDetails } from '../../../../store';

const CfeiOverview = (props) => {
  const { params: { id } } = props;
  return (
    <form >
      <GridColumn >
        <Timeline id={id} />
        <Grid container direction="row">
          <Grid item xs={12} sm={8}>
            <ProjectDetails />
          </Grid>
          <Grid item xs={12} sm={4}>
            <GridColumn >
              <SelectionCriteria id={id} />
              <InformedPartners id={id} />
            </GridColumn>
          </Grid>
        </Grid>
      </GridColumn>
    </form>
  );
};

CfeiOverview.propTypes = {
  params: PropTypes.object,
};

const formCfeiDetails = reduxForm({
  form: 'cfeiDetails',
})(CfeiOverview);

const mapStateToProps = (state, ownProps) => ({
  initialValues: selectCfeiDetails(state, ownProps.params.id),
});

export default connect(
  mapStateToProps,
)(formCfeiDetails);
<commit_msg>adding reinitialization<commit_after>import React from 'react';
import Grid from 'material-ui/Grid';
import PropTypes from 'prop-types';
import { reduxForm } from 'redux-form';
import { connect } from 'react-redux';
import GridColumn from '../../../common/grid/gridColumn';
import Timeline from './timeline';
import ProjectDetails from './projectDetails';
import SelectionCriteria from './selectionCriteria';
import InformedPartners from './informedPartners';
import { selectCfeiDetails } from '../../../../store';

const CfeiOverview = (props) => {
  const { params: { id } } = props;
  return (
    <form >
      <GridColumn >
        <Timeline id={id} />
        <Grid container direction="row">
          <Grid item xs={12} sm={8}>
            <ProjectDetails />
          </Grid>
          <Grid item xs={12} sm={4}>
            <GridColumn >
              <SelectionCriteria id={id} />
              <InformedPartners id={id} />
            </GridColumn>
          </Grid>
        </Grid>
      </GridColumn>
    </form>
  );
};

CfeiOverview.propTypes = {
  params: PropTypes.object,
};

const formCfeiDetails = reduxForm({
  form: 'cfeiDetails',
  enableReinitialize: true,
})(CfeiOverview);

const mapStateToProps = (state, ownProps) => ({
  initialValues: selectCfeiDetails(state, ownProps.params.id),
});

export default connect(
  mapStateToProps,
)(formCfeiDetails);
<|endoftext|>


<commit_before>#!/usr/bin/env node

var fs = require('fs');
var minimist = require('minimist');
var path = require('path');
var zlib = require('zlib');

var minimistOpts = {
  boolean: ['d', 'h', '1', '9'],
  alias: {
    d: ['decompress', 'uncompress'],
    h: 'help',
    1: 'fast',
    9: 'best'
  }
};

var argv = minimist(process.argv.slice(2), minimistOpts);

var decompress = argv.decompress;
var help = argv.help;
var compressionLevel = (argv.fast) ? zlib.Z_BEST_SPEED :
    (argv.best) ? zlib.Z_BEST_COMPRESSION :
    zlib.Z_DEFAULT_COMPRESSION;

if (help) { // help
  return fs.createReadStream(__dirname + '/usage.txt')
    .pipe(process.stdout)
    .on('close', function () { process.exit(1); });
}

function gzip(inStream, outStream) {
  var gzip = zlib.createGzip({ level: compressionLevel });
  inStream
    .on('error', errorExit)
    .pipe(gzip)
    .pipe(outStream);
}

function gunzip(inStream, outStream) {
  var gunzip = zlib.createGunzip();
  inStream
    .on('error', errorExit)
    .pipe(gunzip)
    .pipe(outStream);
}

function errorExit(err) {
    if (err.stack) {
        console.error(err.stack);
    }
    else {
        console.error(String(err));
    }
    process.exit(1);
}

var inStream = process.stdin;
var outStream = process.stdout;

if (decompress) { // decompression
  return gunzip(inStream, outStream);
}

return gzip(inStream, outStream);
<commit_msg>Allow input filename to be passed in as an arg<commit_after>#!/usr/bin/env node

var fs = require('fs');
var minimist = require('minimist');
var zlib = require('zlib');

var minimistOpts = {
  boolean: ['d', 'h', '1', '9'],
  alias: {
    d: ['decompress', 'uncompress'],
    h: 'help',
    1: 'fast',
    9: 'best'
  }
};

var argv = minimist(process.argv.slice(2), minimistOpts);

var decompress = argv.decompress;
var help = argv.help;
var compressionLevel = (argv.fast) ? zlib.Z_BEST_SPEED :
    (argv.best) ? zlib.Z_BEST_COMPRESSION :
    zlib.Z_DEFAULT_COMPRESSION;
var inputFilename = argv._[0]

if (help) { // help
  return fs.createReadStream(__dirname + '/usage.txt')
    .pipe(process.stdout)
    .on('close', function () { process.exit(1); });
}

function gzip(inStream, outStream) {
  var gzip = zlib.createGzip({ level: compressionLevel });
  inStream
    .on('error', errorExit)
    .pipe(gzip)
    .pipe(outStream);
}

function gunzip(inStream, outStream) {
  var gunzip = zlib.createGunzip();
  inStream
    .on('error', errorExit)
    .pipe(gunzip)
    .pipe(outStream);
}

function errorExit(err) {
    if (err.stack) {
        console.error(err.stack);
    }
    else {
        console.error(String(err));
    }
    process.exit(1);
}

var inStream = inputFilename ? fs.createReadStream(inputFilename) : process.stdin;
var outStream = process.stdout;

if (decompress) { // decompression
  return gunzip(inStream, outStream);
}

return gzip(inStream, outStream);
<|endoftext|>


<commit_before>#!/usr/bin/env node
var FRAMEWORK_PATH = __dirname.toString().slice(0, -4);
var PROJECT_PATH = process.cwd().toString();
var BRUNCH_PATH = FRAMEWORK_PATH + '/node_modules/.bin/brunch';
var CORDOVA_PATH = FRAMEWORK_PATH + '/node_modules/.bin/cordova';
var SOURCE_PATH = FRAMEWORK_PATH + '/src';

var minimist = require('minimist');
var shell = require('shelljs');
var arguments = minimist(process.argv.slice(2));
var commands = arguments['_'];

if (['n', 'new'].indexOf(commands[0]) > -1) {
    var createCommand = [BRUNCH_PATH, 'new', SOURCE_PATH];
    if (commands[1]) {
        createCommand.push(commands[1]);
    }
    shell.exec(createCommand.join(' '));
    process.exit(1);
}

try {
    var project = require(PROJECT_PATH + '/package.json');
} catch (error) {
    switch (error.code) {
        case 'MODULE_NOT_FOUND':
            console.log("Directory package.json not found.");
            break;
    }
    process.exit(0);
}

if (project.framework !== 'gelato') {
    console.log("Directory is not gelato project.");
    process.exit(0);
}

if (['b', 'build'].indexOf(commands[0]) > -1) {
    var buildCommand = [BRUNCH_PATH, 'build'];
    if (arguments['e'] || arguments['env']) {
        buildCommand.push('--env ' + arguments['e'] || arguments['env']);
    }
    if (arguments['P'] || arguments['production']) {
        buildCommand.push('--production');
    }
    shell.exec(buildCommand.join(' '));
    process.exit(1);
}

if (['u', 'update'].indexOf(commands[0]) > -1) {
    shell.rm('-rf', PROJECT_PATH + '/app/gelato');
    shell.cp('-r', SOURCE_PATH + '/app/gelato', PROJECT_PATH + '/app');
    process.exit(1);
}

if (['w', 'watch'].indexOf(commands[0]) > -1) {
    var watchCommand = [BRUNCH_PATH, 'watch'];
    if (arguments['p'] || arguments['port']) {
        watchCommand.push('--port ' + arguments['p'] || arguments['port']);
    }
    if (arguments['s'] || arguments['server']) {
        watchCommand.push('--server');
    }
    shell.exec(watchCommand.join(' '));
    process.exit(1);
}

console.log("If you don't eat your meat, you can't have any pudding!");
process.exit(0);
<commit_msg>Updated the command line to use latest brunch changes.<commit_after>#!/usr/bin/env node
var FRAMEWORK_PATH = __dirname.toString().slice(0, -4);
var PROJECT_PATH = process.cwd().toString();
var BRUNCH_PATH = FRAMEWORK_PATH + '/node_modules/.bin/brunch';
var CORDOVA_PATH = FRAMEWORK_PATH + '/node_modules/.bin/cordova';

var minimist = require('minimist');
var shell = require('shelljs');
var arguments = minimist(process.argv.slice(2));
var commands = arguments['_'];

if (['n', 'new'].indexOf(commands[0]) > -1) {
    var createCommand = [BRUNCH_PATH, 'new', FRAMEWORK_PATH + '/skeletons/default'];
    if (commands[1]) {
        createCommand.push(commands[1]);
    }
    shell.exec(createCommand.join(' '));
    process.exit(1);
}

try {
    var project = require(PROJECT_PATH + '/package.json');
} catch (error) {
    switch (error.code) {
        case 'MODULE_NOT_FOUND':
            console.log("Directory package.json not found.");
            break;
    }
    process.exit(0);
}

if (project.framework !== 'gelato') {
    console.log("Directory is not gelato project.");
    process.exit(0);
}

if (['b', 'build'].indexOf(commands[0]) > -1) {
    var buildCommand = [BRUNCH_PATH, 'build'];
    if (arguments['e'] || arguments['env']) {
        buildCommand.push('--env ' + arguments['e'] || arguments['env']);
    }
    if (arguments['P'] || arguments['production']) {
        buildCommand.push('--production');
    }
    shell.exec(buildCommand.join(' '));
    process.exit(1);
}

if (['u', 'update'].indexOf(commands[0]) > -1) {
    var updateCommand = [BRUNCH_PATH, 'build'];
    shell.cd(FRAMEWORK_PATH);
    shell.exec(updateCommand.join(' '));
    shell.mkdir('-p', PROJECT_PATH + '/vendor/gelato');
    shell.rm('-rf', PROJECT_PATH + '/vendor/gelato/*');
    shell.cp('-rf', FRAMEWORK_PATH + '/public/*', PROJECT_PATH + '/vendor/gelato');
    process.exit(1);
}

if (['w', 'watch'].indexOf(commands[0]) > -1) {
    var watchCommand = [BRUNCH_PATH, 'watch'];
    if (arguments['p'] || arguments['port']) {
        watchCommand.push('--port ' + arguments['p'] || arguments['port']);
    }
    if (arguments['s'] || arguments['server']) {
        watchCommand.push('--server');
    }
    shell.exec(watchCommand.join(' '));
    process.exit(1);
}

console.log("If you don't eat your meat, you can't have any pudding!");
process.exit(0);
<|endoftext|>


<commit_before>#!/usr/bin/env node
var doc = `Comic Viewer

Usage:
  comic-viewer [--port <port>] [--start | --stop] [<file>]
  comic-viewer --help | --version

Options:
  --port <port>  Set the port of the server. [default: 8080]
  --start        Start the server, if the server is not already running.
  --stop         Stop the server.
  <file>         The file to open in browser, if provided.
  --help         Show help message.
  --version      Show version number.`;

var docopt = require("docopt"),
	mkdirp = require("mkdirp"),
	process = require("process"),
	fs = require("fs"),

	args = docopt.docopt(doc, {version: "0.0.0"}),
	path = require("path-extra"),
	appDir = path.datadir("comic-viewer"),
	lock = path.join(appDir, "lock"),

	server = {
		pid: null,
		isLocked: null
	},

	createCV = require("../lib/comic-viewer");

function launchFile() {
	if (!args["<file>"]) {
		return;
	}
	var opener = require("opener");
	opener("http://localhost:" + args["--port"] + "/view?path=" + encodeURIComponent(args["<file>"]));
}

function createLock() {
	console.log("Server started at port:" + args["--port"]);
	mkdirp(appDir, function(err) {
		if (err && err.code != "EEXIST") {
			console.err(err);
			exit();
			return;
		}
		fs.writeFile(lock, process.pid, function(err) {
			if (err) {
				console.err(err);
				exit();
				return;
			}
			// handle SIGINT
			process.on("SIGINT", function(){
				exit();
			});
		});
	});
}

function startServer() {
	createCV(args["--port"], createLock, exit);
}

function exit() {
	removeLock(process.exit);
}

function removeLock(callback) {
	fs.unlink(lock, callback);
}

function init() {
	if (args["--start"]) {
		if (server.isLocked) {
			console.log("Server is already running at pid:" + server.pid);
		} else {
			startServer();
		}
	}
	if (args["--stop"] && server.isLocked) {
		process.kill(server.pid);
	}
	launchFile();
}

if (args["<file>"]) {
	args["<file>"] = path.join(process.cwd(), args["<file>"]);
}

process.chdir(path.join(__dirname, ".."));

fs.readFile(lock, function(err, pid) {
	server.isLocked = !err;
	server.pid = +pid;

	if (server.isLocked) {
		try {
			process.kill(+pid, 0);
		} catch (err) {
			// the process doesn't exist
			server.isLocked = false;
			removeLock(init);
			return;
		}
	}
	process.nextTick(init);
});
<commit_msg>Fix abs path bug<commit_after>#!/usr/bin/env node
var doc = `Comic Viewer

Usage:
  comic-viewer [--port <port>] [--start | --stop] [<file>]
  comic-viewer --help | --version

Options:
  --port <port>  Set the port of the server. [default: 8080]
  --start        Start the server, if the server is not already running.
  --stop         Stop the server.
  <file>         The file to open in browser, if provided.
  --help         Show help message.
  --version      Show version number.`;

var docopt = require("docopt"),
	mkdirp = require("mkdirp"),
	process = require("process"),
	fs = require("fs"),

	args = docopt.docopt(doc, {version: "0.0.0"}),
	path = require("path-extra"),
	appDir = path.datadir("comic-viewer"),
	lock = path.join(appDir, "lock"),

	server = {
		pid: null,
		isLocked: null
	},

	createCV = require("../lib/comic-viewer");

function launchFile() {
	if (!args["<file>"]) {
		return;
	}
	var opener = require("opener");
	opener("http://localhost:" + args["--port"] + "/view?path=" + encodeURIComponent(args["<file>"]));
}

function createLock() {
	console.log("Server started at port:" + args["--port"]);
	mkdirp(appDir, function(err) {
		if (err && err.code != "EEXIST") {
			console.err(err);
			exit();
			return;
		}
		fs.writeFile(lock, process.pid, function(err) {
			if (err) {
				console.err(err);
				exit();
				return;
			}
			// handle SIGINT
			process.on("SIGINT", function(){
				exit();
			});
		});
	});
}

function startServer() {
	createCV(args["--port"], createLock, exit);
}

function exit() {
	removeLock(process.exit);
}

function removeLock(callback) {
	fs.unlink(lock, callback);
}

function init() {
	if (args["--start"]) {
		if (server.isLocked) {
			console.log("Server is already running at pid:" + server.pid);
		} else {
			startServer();
		}
	}
	if (args["--stop"] && server.isLocked) {
		process.kill(server.pid);
	}
	launchFile();
}

if (args["<file>"] && !path.isAbsolute(args["<file>"])) {
	args["<file>"] = path.join(process.cwd(), args["<file>"]);
}

process.chdir(path.join(__dirname, ".."));

fs.readFile(lock, function(err, pid) {
	server.isLocked = !err;
	server.pid = +pid;

	if (server.isLocked) {
		try {
			process.kill(+pid, 0);
		} catch (err) {
			// the process doesn't exist
			server.isLocked = false;
			removeLock(init);
			return;
		}
	}
	process.nextTick(init);
});
<|endoftext|>


<commit_before>#!/usr/bin/env node

var fs = require('fs')
var org2html = require('../index')

// TODO: accept stdin if no argv[2]
var stream = fs.createReadStream(process.argv[2])

stream
  .pipe(org2html())
  .pipe(process.stdout)
<commit_msg>accept input from stdin if no filename is given<commit_after>#!/usr/bin/env node

var fs = require('fs')
var org2html = require('../index')

var stream = (process.argv.length < 3) ? process.stdin : fs.createReadStream(process.argv[2])

stream
  .pipe(org2html())
  .pipe(process.stdout)
<|endoftext|>