<commit_before>var ___ = '___send-to-shoulder___';
var _ = '_hole_';
var log = 1 ? console.log : function(){} ;

var purry = module.exports = function(f){
  if (f.length === 0) throw new Error('purry is not compatible with variable-argument functions.')
  var initial_stock = [];
  var i = f.length;
  while(i > 0){
    initial_stock.push(_);
    i--;
  }
  return accumulate_arguments(f, f.length, 0, initial_stock, 0, f.length - 1, false);
};

// @f –– The wrapped function
// @capacity –– The param count of f
// @_capacity_used –– The remaining holes of _stock
// @_stock –– The plugged holes so far
// @_stock_i_min –– The minimum index to start stocking at.
function accumulate_arguments(f, capacity, _capacity_used, _stock, _stock_i_min, _stock_i_max, _f_has_holes){
  var _is_capacity_full = capacity === _capacity_used;
  return function(){
    var arguments_count = arguments.length;

    // Bail ASAP if no arguments given
    if (!arguments_count) {
      return _is_capacity_full ?
        f.apply(null, _stock) :
        accumulate_arguments(f, capacity, _capacity_used, _stock, _stock_i_min, _stock_i_max, _f_has_holes) ;

    }

    // TODO? Bail ASAP if all arguments given in single shot
    // if (!_capacity_used && arguments_count === capacity)

    // index for various loops below
    var i;

    // log('\n\nInvoked: capacity %d | instance capacity %d | stock %j | new args %j', capacity, capacity - _capacity_used, _stock, arguments)

    // Cloning, to avoid clobbering
    var stock = [];
    var _stock_count = _stock.length;
    i = 0;
    while(i < _stock_count) {
      stock[i] = _stock[i]; i++;
    }

    // Shadowing, to avoid clobbering
    var capacity_used = _capacity_used;
    var stock_i_min = _stock_i_min;
    var stock_i_max = _stock_i_max;
    var f_has_holes = _f_has_holes;

    var is_delayed_execution = false;
    var argument;
    var stock_i = stock_i_min;
    var incby = 1;
    var endloop = arguments_count;
    var limit = stock_i_max + 1;
    process_new_arguments:
    for(i = 0; i !== endloop; i += incby) {
      // log('\nend condition: %d !== %d | stock_i: %d', i, endloop, stock_i);
      argument = arguments[i];

      if (argument === _) {
        is_delayed_execution = true;
        // If _ is last argument it has no affect
        // other than delaying execution.
        if (i + incby === endloop) break;
        f_has_holes = true;
        stock_i += incby
        // log('Hit Hole _, offset @ %d');
        continue;
      }

      if (argument === ___) {
        is_delayed_execution = true;
        if (i + incby === endloop) break;
        incby = -1;
        stock_i = stock_i_max;
        limit = stock_i_min - 1;
        // log('Hit shoulder ___ of size (%d)', (arguments_count - (i + 1)));
        endloop = i;
        i = arguments_count;
        continue;
      }

      if (f_has_holes) {
        while (stock[stock_i] !== _) {
          // If an argument falls out of bounds, discard it.
          // Also discard everything after, because all subsequent
          // arguments will be out of bounds too.
          if (stock_i === limit) break process_new_arguments;
          stock_i += incby;
        }
      }

      // With an argument and and its resolved index in hand,
      // stock it!
      // log('Add argument: %j @ i%d', argument, stock_i);
      stock[stock_i] = argument;
      // Take note of new argument minimum/maximums.
      // For example if the min is at 0 and we fill 0 we know we can
      // never fill it again.
      // These markers allow subsequent invocation to start/stop
      // stock_i at optimized points meaning a certain amount of
      // loops are skipped.
      if (stock_i_min === stock_i) stock_i_min++;
      if (stock_i_max === stock_i) stock_i_max--;
      capacity_used++;
      stock_i += incby;
      // log('stock: %j', stock);
    }

    // log('\nProcessing Complete. ')
    // log('Not applicable, stock: %j', stock);
    // log('Applicable! %j', stock);
    return is_delayed_execution || capacity !== capacity_used ?
      accumulate_arguments(f, capacity, capacity_used, stock, stock_i_min, stock_i_max, f_has_holes) :
      f.apply(null, stock) ;
  };
}

purry._ = _;
purry.___ = ___;

purry.install = function(symbol_, symbol___){
  purry.installSyntax(symbol_, symbol___);
  Function.prototype.purry = purry;
};

purry.installSyntax = function(symbol_, symbol___){
  GLOBAL[symbol_ || '_'] = _;
  GLOBAL[symbol___ || '___'] = ___;
};<commit_msg>Optimize if if statements into if-else statements<commit_after>var ___ = '___send-to-shoulder___';
var _ = '_hole_';
var log = 1 ? console.log : function(){} ;

var purry = module.exports = function(f){
  if (f.length === 0) throw new Error('purry is not compatible with variable-argument functions.')
  var initial_stock = [];
  var i = f.length;
  while(i > 0){
    initial_stock.push(_);
    i--;
  }
  return accumulate_arguments(f, f.length, 0, initial_stock, 0, f.length - 1, false);
};

// @f –– The wrapped function
// @capacity –– The param count of f
// @_capacity_used –– The remaining holes of _stock
// @_stock –– The plugged holes so far
// @_stock_i_min –– The minimum index to start stocking at.
function accumulate_arguments(f, capacity, _capacity_used, _stock, _stock_i_min, _stock_i_max, _f_has_holes){
  var _is_capacity_full = capacity === _capacity_used;
  return function(){
    var arguments_count = arguments.length;

    // Bail ASAP if no arguments given
    if (!arguments_count) {
      return _is_capacity_full ?
        f.apply(null, _stock) :
        accumulate_arguments(f, capacity, _capacity_used, _stock, _stock_i_min, _stock_i_max, _f_has_holes) ;

    }

    // TODO? Bail ASAP if all arguments given in single shot
    // if (!_capacity_used && arguments_count === capacity)

    // index for various loops below
    var i;

    // log('\n\nInvoked: capacity %d | instance capacity %d | stock %j | new args %j', capacity, capacity - _capacity_used, _stock, arguments)

    // Cloning, to avoid clobbering
    var stock = [];
    var _stock_count = _stock.length;
    i = 0;
    while(i < _stock_count) {
      stock[i] = _stock[i]; i++;
    }

    // Shadowing, to avoid clobbering
    var capacity_used = _capacity_used;
    var stock_i_min = _stock_i_min;
    var stock_i_max = _stock_i_max;
    var f_has_holes = _f_has_holes;

    var is_delayed_execution = false;
    var argument;
    var stock_i = stock_i_min;
    var incby = 1;
    var endloop = arguments_count;
    var limit = stock_i_max + 1;
    process_new_arguments:
    for(i = 0; i !== endloop; i += incby) {
      // log('\nend condition: %d !== %d | stock_i: %d', i, endloop, stock_i);
      argument = arguments[i];

      if (argument === _) {
        is_delayed_execution = true;
        // If _ is last argument it has no affect
        // other than delaying execution.
        if (i + incby === endloop) break;
        f_has_holes = true;
        stock_i += incby
        // log('Hit Hole _, offset @ %d');
        continue;
      }

      if (argument === ___) {
        is_delayed_execution = true;
        if (i + incby === endloop) break;
        incby = -1;
        stock_i = stock_i_max;
        limit = stock_i_min - 1;
        // log('Hit shoulder ___ of size (%d)', (arguments_count - (i + 1)));
        endloop = i;
        i = arguments_count;
        continue;
      }

      if (f_has_holes) {
        while (stock[stock_i] !== _) {
          // If an argument falls out of bounds, discard it.
          // Also discard everything after, because all subsequent
          // arguments will be out of bounds too.
          if (stock_i === limit) break process_new_arguments;
          stock_i += incby;
        }
      }

      // With an argument and and its resolved index in hand,
      // stock it!
      // log('Add argument: %j @ i%d', argument, stock_i);
      stock[stock_i] = argument;
      // Take note of new argument minimum/maximums.
      // For example if the min is at 0 and we fill 0 we know we can
      // never fill it again.
      // These markers allow subsequent invocation to start/stop
      // stock_i at optimized points meaning a certain amount of
      // loops are skipped.
      if      (stock_i_min === stock_i) { stock_i_min++; }
      else if (stock_i_max === stock_i) { stock_i_max--; }
      capacity_used++;
      stock_i += incby;
      // log('stock: %j', stock);
    }

    // log('\nProcessing Complete. ')
    // log('Not applicable, stock: %j', stock);
    // log('Applicable! %j', stock);
    return is_delayed_execution || capacity !== capacity_used ?
      accumulate_arguments(f, capacity, capacity_used, stock, stock_i_min, stock_i_max, f_has_holes) :
      f.apply(null, stock) ;
  };
}

purry._ = _;
purry.___ = ___;

purry.install = function(symbol_, symbol___){
  purry.installSyntax(symbol_, symbol___);
  Function.prototype.purry = purry;
};

purry.installSyntax = function(symbol_, symbol___){
  GLOBAL[symbol_ || '_'] = _;
  GLOBAL[symbol___ || '___'] = ___;
};<|endoftext|>


<commit_before>(function() {
    this.deactivateAllParts = function(formPartNodes) {
        Array.prototype.forEach.call(formPartNodes,function(node) {
            node.setAttribute('data-form-part-state', 'inactive');
        });
    };

    this.activateSelectedPart = function(form, formPartsSwitcher, formPartsButtons) {
        var formPartId = (formPartsButtons.item(formPartsSwitcher.selectedIndex)).getAttribute('data-form-part-for');
        form.querySelector('[data-form-part="'+formPartId+'"]').setAttribute('data-form-part-state', 'active');
        if(window.location.hash.substring(1) != formPartId) {
            window.history.pushState({ formPartId: formPartId }, '', '#'+formPartId);
        }
    };

    this.initializeFormModes = function(form, formPartsSwitcher, formPartsButtons, formPartNodes, activeFormPartId) {
        var formModeParam = window.location.hash.substring(1);

        // no param given -> update param to id of first form part (the current active form part)
        if(formModeParam == '') {
            window.history.replaceState({ formPartId: activeFormPartId }, '', '#'+activeFormPartId);
        }

        // param of inactive form part given -> change to parts
        if(formModeParam != '' && formModeParam != activeFormPartId) {
            formPartsSwitcher.value = formModeParam;
        }

        // IE may throw an error here "Object doesn't support this action".
        // It seems IE won't trigger a change event on select boxes
        // I didn't found a solution to get the supported actions,
        // so the error is still there: Fuck you IE
        // Note: The switcher is working anyway
        formPartsSwitcher.dispatchEvent(new Event('change'));
    };

    window.addEventListener('load', function() {
        var formPartNodes = document.querySelectorAll('[data-form-part]');
        var form = formPartNodes.item(0).parentNode;
        var formPartsSwitcher = document.querySelector('select[data-form-part-switcher]');
        var formPartsButtons = document.querySelectorAll('[data-form-part-for]');

        formPartsSwitcher.addEventListener('change',function(event) {
            deactivateAllParts(formPartNodes);
            activateSelectedPart(form, formPartsSwitcher, formPartsButtons);
        });

        window.onpopstate = function(event) {
            // if pushState tries to push the current location, there will be no history entry -> event.state is undefined
            var formPartId = (event.state) ? event.state.formPartId : window.location.hash;
            var currentButton = document.querySelector('[data-form-part-for="'+formPartId+'"]');

            if(formPartsSwitcher.value != formPartId) {
                formPartsSwitcher.value = formPartId;
                // IE may throw an error here "Object doesn't support this action".
                // It seems IE won't trigger a change event on select boxes
                // I didn't found a solution to get the supported actions,
                // so the error is still there: Fuck you IE
                // Note: The switcher is working anyway
                formPartsSwitcher.dispatchEvent(new Event('change'));
            }
        };

        var currentActiveFormPart = document.querySelector('[data-form-part-state="active"]');
        var activeFormPartId = (currentActiveFormPart) ? currentActiveFormPart.getAttribute('data-form-part-for') :
            document.querySelector('[data-form-part]').getAttribute('data-form-part');
        initializeFormModes(form, formPartsSwitcher, formPartsButtons, formPartNodes, activeFormPartId );
    });
})();
<commit_msg>fix grammar in comments<commit_after>(function() {
    this.deactivateAllParts = function(formPartNodes) {
        Array.prototype.forEach.call(formPartNodes,function(node) {
            node.setAttribute('data-form-part-state', 'inactive');
        });
    };

    this.activateSelectedPart = function(form, formPartsSwitcher, formPartsButtons) {
        var formPartId = (formPartsButtons.item(formPartsSwitcher.selectedIndex)).getAttribute('data-form-part-for');
        form.querySelector('[data-form-part="'+formPartId+'"]').setAttribute('data-form-part-state', 'active');
        if(window.location.hash.substring(1) != formPartId) {
            window.history.pushState({ formPartId: formPartId }, '', '#'+formPartId);
        }
    };

    this.initializeFormModes = function(form, formPartsSwitcher, formPartsButtons, formPartNodes, activeFormPartId) {
        var formModeParam = window.location.hash.substring(1);

        // no param given -> update param to id of first form part (the current active form part)
        if(formModeParam == '') {
            window.history.replaceState({ formPartId: activeFormPartId }, '', '#'+activeFormPartId);
        }

        // param of inactive form part given -> change to parts
        if(formModeParam != '' && formModeParam != activeFormPartId) {
            formPartsSwitcher.value = formModeParam;
        }

        // IE may throw an error here "Object doesn't support this action".
        // It seems IE won't trigger a change event on select boxes.
        // I didn't find a solution to get the supported actions,
        // so the error is still there: Fuck you IE.
        // Note: The switcher is working regardless.
        formPartsSwitcher.dispatchEvent(new Event('change'));
    };

    window.addEventListener('load', function() {
        var formPartNodes = document.querySelectorAll('[data-form-part]');
        var form = formPartNodes.item(0).parentNode;
        var formPartsSwitcher = document.querySelector('select[data-form-part-switcher]');
        var formPartsButtons = document.querySelectorAll('[data-form-part-for]');

        formPartsSwitcher.addEventListener('change',function(event) {
            deactivateAllParts(formPartNodes);
            activateSelectedPart(form, formPartsSwitcher, formPartsButtons);
        });

        window.onpopstate = function(event) {
            // if pushState tries to push the current location, there will be no history entry -> event.state is undefined
            var formPartId = (event.state) ? event.state.formPartId : window.location.hash;
            var currentButton = document.querySelector('[data-form-part-for="'+formPartId+'"]');

            if(formPartsSwitcher.value != formPartId) {
                formPartsSwitcher.value = formPartId;
                // IE may throw an error here "Object doesn't support this action".
                // It seems IE won't trigger a change event on select boxes.
                // I didn't find a solution to get the supported actions,
                // so the error is still there: Fuck you IE.
                // Note: The switcher is working regardless.
                formPartsSwitcher.dispatchEvent(new Event('change'));
            }
        };

        var currentActiveFormPart = document.querySelector('[data-form-part-state="active"]');
        var activeFormPartId = (currentActiveFormPart) ? currentActiveFormPart.getAttribute('data-form-part-for') :
            document.querySelector('[data-form-part]').getAttribute('data-form-part');
        initializeFormModes(form, formPartsSwitcher, formPartsButtons, formPartNodes, activeFormPartId );
    });
})();
<|endoftext|>


<commit_before>(function(fs, path, lib){
  'use strict';

  // Destructure
  // let {parser, reader, writer} = lib;
  var parser = lib.parser,
      reader = lib.reader,
      writer = lib.writer;

  // Set default parsing to JSON
  parser
  .set('parse', JSON.parse)
  .set('serialize', function(input, indent){
    return JSON.stringify(input, null, indent);
  });
})(
  require('fs'),
  require('path'),
  require(__dirname + '/lib')
);
<commit_msg>A bit more setting up<commit_after>(function(fs, path, lib){
  'use strict';

  // Destructure
  // let {parser, reader, writer} = lib;
  var parser = lib.parser,
      reader = lib.reader,
      writer = lib.writer;

  // Set default parsing to JSON
  parser
  .set('parse', JSON.parse)
  .set('serialize', function(input, indent){
    return JSON.stringify(input, null, indent);
  });

  // Library essentials
  reader.set('parser', parser);
  writer.set('parser', parser);
})(
  require('fs'),
  require('path'),
  require(__dirname + '/lib')
);
<|endoftext|>


<commit_before>import React from 'react';
import renderer from 'react-test-renderer';
import {createMockSpark} from '@ciscospark/react-redux-spark';

import SparkOAuth from '.';

describe('SparkOAuth component', () => {
  const component = renderer.create(<SparkOAuth />);

  it('renders properly', () => {
    expect(component).toMatchSnapshot();
  });
});

describe('SparkOAuth functionality', () => {
  let onAuth, spark, sparkOAuth;
  beforeEach(() => {
    onAuth = jest.fn();
    sparkOAuth = new SparkOAuth({doAuth: false, onAuth});
    spark = createMockSpark();
    sparkOAuth.spark = spark;
  });

  it('should call spark auth when told', () => {
    sparkOAuth.props.doAuth = false;
    const props = {doAuth: true};
    sparkOAuth.componentWillReceiveProps(props);
    expect(spark.authenticate).toHaveBeenCalled();
  });

  it('should call onAuth after a successful authorization', () => {
    spark.credentials.canAuthorize = true;
    spark.credentials.supertoken = 'supertoken';
    sparkOAuth.checkForOauthToken();
    expect(onAuth).toHaveBeenCalled();
  });

  it('should not call onAuth when not authorized', () => {
    spark.credentials.canAuthorize = false;
    spark.credentials.supertoken = 'supertoken';
    sparkOAuth.checkForOauthToken();
    expect(onAuth).not.toHaveBeenCalled();
  });
});
<commit_msg>chore(spark-oauth): use fixture library<commit_after>import React from 'react';
import renderer from 'react-test-renderer';
import {createMockSpark} from '@ciscospark/react-redux-spark-fixtures';

import SparkOAuth from '.';

describe('SparkOAuth component', () => {
  const component = renderer.create(<SparkOAuth />);

  it('renders properly', () => {
    expect(component).toMatchSnapshot();
  });
});

describe('SparkOAuth functionality', () => {
  let onAuth, spark, sparkOAuth;
  beforeEach(() => {
    onAuth = jest.fn();
    sparkOAuth = new SparkOAuth({doAuth: false, onAuth});
    spark = createMockSpark();
    sparkOAuth.spark = spark;
  });

  it('should call spark auth when told', () => {
    sparkOAuth.props.doAuth = false;
    const props = {doAuth: true};
    sparkOAuth.componentWillReceiveProps(props);
    expect(spark.authenticate).toHaveBeenCalled();
  });

  it('should call onAuth after a successful authorization', () => {
    spark.credentials.canAuthorize = true;
    spark.credentials.supertoken = 'supertoken';
    sparkOAuth.checkForOauthToken();
    expect(onAuth).toHaveBeenCalled();
  });

  it('should not call onAuth when not authorized', () => {
    spark.credentials.canAuthorize = false;
    spark.credentials.supertoken = 'supertoken';
    sparkOAuth.checkForOauthToken();
    expect(onAuth).not.toHaveBeenCalled();
  });
});
<|endoftext|>


<commit_before>'use strict';

const http = require('http');
const url = require('url');
const querystring = require('querystring');

const _ = require('lodash');
const { ImplementationError } = require('flora-errors');

const SUPPORTED_FILTERS = ['equal', 'notEqual', 'lessOrEqual', 'greaterOrEqual', 'range'];

const NO_LIMIT = 1000000;

/**
 * Return true if two filters on same attribute can be used as single range filter.
 *
 * @param {Array.<Object>} filters
 * @return {boolean}
 * @private
 */
function filterRangeQueries(filters) {
    if (filters.length !== 2) return false;

    const rangeOperators = ['lessOrEqual', 'greaterOrEqual'];
    const operator1 = filters[0].operator;
    const operator2 = filters[1].operator;

    return rangeOperators.indexOf(operator1) !== -1 && rangeOperators.indexOf(operator2) !== -1;
}

/**
 * Create range filter from a greatOrEqual and lessOrEqual filter.
 *
 * @param {Array.<string>} attributeFilters
 * @return {Object}
 * @private
 */
function createRangeFilter(attributeFilters) {
    const rangeFilter = { attribute: attributeFilters[0].attribute, operator: 'range' };

    // make sure greaterOrEqual filter comes first
    attributeFilters.sort(filter1 => (filter1.operator === 'greaterOrEqual' ? -1 : 1));

    rangeFilter.value = [attributeFilters[0].value, attributeFilters[1].value];
    return rangeFilter;
}

/**
 * Convert greaterOrEqual and lessOrEqual filters on same attribute
 * to a single range filter.
 *
 * @param {Array.<Object>} filters
 * @return {Array.<Object>}
 * @private
 */
function rangify(filters) {
    const groupedAttrs = _.groupBy(filters, 'attribute');
    const rangeQueries = _.filter(groupedAttrs, filterRangeQueries);

    if (!rangeQueries.length) return filters;

    const rangeQueryAttrs = rangeQueries.map(rangeQuery => rangeQuery[0].attribute);

    // copy non-range query attributes
    return filters.filter(filter => rangeQueryAttrs.indexOf(filter.attribute) === -1).concat(rangeQueries.map(createRangeFilter));
}

/**
 * @param {string} value
 * @return {string}
 * @private
 */
function escapeSpecialChars(value) {
    const specialCharRegex = /(\\|\/|\+|-|&|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:)/g;
    return value.replace(specialCharRegex, '\\$1');
}

/**
 * @param {string} value
 * @return {string}
 * @private
 */
function escapeSpecialCharsSolrSyntax(value) {
    const specialCharRegex = /(\\|\/|\+|-|&|\||!|\(|\)|\{|}|\[|]|\^|~|\?)/g;
    return value.replace(specialCharRegex, '\\$1');
}

/**
 * Escape strings and convert boolean values.
 *
 * @param {*} value
 * @param {boolean} exposeSolrSyntax
 * @return {*}
 * @private
 */
function escapeValueForSolr(value, exposeSolrSyntax) {
    if (typeof value === 'string') {
        value = exposeSolrSyntax ? escapeSpecialCharsSolrSyntax(value) : escapeSpecialChars(value);
    } else if (typeof value === 'boolean') value = value === false ? 0 : 1;
    return value;
}

/**
 * @param {Object} filter
 * @return {string}
 * @private
 */
function convertFilterToSolrSyntax(filter) {
    const { operator } = filter;
    let { value } = filter;

    if (SUPPORTED_FILTERS.indexOf(filter.operator) === -1) {
        throw new ImplementationError(`DataSource "flora-solr" does not support "${operator}" filters`);
    }

    if (!Array.isArray(filter.attribute)) {
        value = escapeValueForSolr(value);
        if (Array.isArray(value)) {
            if (operator === 'range') value = '[' + value[0] + ' TO ' + value[1] + ']';
            else value = '(' + value.join(' OR ') + ')';
        }

        if (operator !== 'notEqual') {
            if (operator === 'greaterOrEqual') value = '[' + value + ' TO *]';
            if (operator === 'lessOrEqual') value = '[* TO ' + value + ']';
            return filter.attribute + ':' + value;
        }
        return '-' + filter.attribute + ':' + value;
    }

    // convert composite keys to SOLR syntax
    return value
        .map(values => {
            const conditions = values.map((val, index) => filter.attribute[index] + ':' + escapeValueForSolr(val));
            return '(' + conditions.join(' AND ') + ')';
        })
        .join(' OR ');
}

function buildSolrFilterString(floraFilters) {
    const orConditions = floraFilters.map(andFilters => {
        if (andFilters.length > 1) andFilters = rangify(andFilters);
        const conditions = andFilters.map(convertFilterToSolrSyntax);
        return '(' + conditions.join(' AND ') + ')';
    });

    if (orConditions.length > 1) return '(' + orConditions.join(' OR ') + ')';

    return orConditions.join('');
}

/**
 * @param {Array.<Object>} floraOrders
 * @return {string}
 * @private
 */
function buildSolrOrderString(floraOrders) {
    return floraOrders.map(order => order.attribute + ' ' + order.direction).join(',');
}

function parseData(str) {
    try {
        return JSON.parse(str);
    } catch (e) {
        return new Error('Could not parse response: ' + str);
    }
}

function prepareQueryAddition(queryAdditions) {
    return queryAdditions
        .replace(/[\r\n]+/g, ' ')
        .replace(/\s{2,}/g, ' ')
        .trim();
}

/**
 * @param {Object} servers
 * @return {Object}
 */
function getUrlGenerators(servers) {
    return Object.keys(servers).reduce((acc, server) => {
        const { urls } = servers[server];

        acc[server] = (function* urlGenerator() {
            while (true) {
                for (let i = 0, l = urls.length; i < l; ++i) {
                    yield urls[i];
                }
            }
        })();

        return acc;
    }, {});
}

/**
 *
 * @param {string} requestUrl
 * @param {Object} params
 * @param {Object} requestOptions
 * @param {Agent} agent
 * @returns {Promise}
 * @private
 */
function querySolr(requestUrl, params, requestOptions, agent) {
    return new Promise((resolve, reject) => {
        const options = Object.assign(url.parse(requestUrl), {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            timeout: requestOptions.connectTimeout,
            agent
        });

        const req = http.request(options, res => {
            const chunks = [];

            res.on('data', chunk => chunks.push(chunk));

            res.on('end', () => {
                const data = parseData(Buffer.concat(chunks).toString('utf8'));

                if (res.statusCode >= 400 || data instanceof Error) {
                    const error = new Error('Solr error: ' + res.statusCode + ' ' + http.STATUS_CODES[res.statusCode]);
                    if (data instanceof Error) {
                        error.message += ': ' + data.message;
                    } else if (data && data.error && data.error.msg) {
                        error.message += ': ' + data.error.msg;
                    }

                    return reject(error);
                }

                return resolve({ totalCount: data.response.numFound, data: data.response.docs });
            });
        });

        req.setTimeout(requestOptions.requestTimeout, () => req.abort());

        req.write(querystring.stringify(params)); // add params to POST body

        req.on('error', err => {
            err.message = 'Solr error: ' + err.message + ' (' + options.host + ')';
            reject(err);
        });

        req.end();
    });
}

function prepareSearchTerm(request) {
    const escapedSearchTerm = escapeValueForSolr(request.search, request.exposeSolrSyntax);
    const allowedSearchFields =
        request.allowedSearchFields && request.allowedSearchFields.trim() ? request.allowedSearchFields.trim().split(',') : [];

    if (!allowedSearchFields.length) {
        return escapedSearchTerm;
    }

    const regex = new RegExp(`^(?<field>${allowedSearchFields.join('|')}):(?<search>.+)`);
    const match = regex.exec(request.search);

    if (match === null) {
        return escapedSearchTerm;
    }

    return `(${match.groups.field}:"${match.groups.search}")`;
}

class DataSource {
    /**
     * @param {Api} api
     * @param {Object} config
     */
    constructor(api, config) {
        this.options = config;
        this._urls = getUrlGenerators(config.servers);
        this._status = config._status;
        delete config._status;

        this._agent = new http.Agent({ maxSockets: 10 });
    }

    /**
     * @public
     */
    prepare() {}

    /**
     * @param {Object} request
     * @returns {Promise<Object>}
     */
    async process(request) {
        const server = request.server || 'default';
        const queryParts = [];
        const params = { wt: 'json' };
        const serverOpts = this.options.servers;

        if (!serverOpts[server]) throw new Error(`Server "${server}" not defined`);

        const requestUrl = this._urls[server].next().value + request.collection + '/select';

        if (request.attributes) params.fl = request.attributes.join(',');
        if (request.order) params.sort = buildSolrOrderString(request.order);

        if (request.df) params.df = request.df;
        if (request.search && request.search.trim()) queryParts.push(prepareSearchTerm(request));
        if (request.filter) {
            queryParts.push(buildSolrFilterString(request.filter));
        }
        if (request.queryAddition) queryParts.push(prepareQueryAddition(request.queryAddition));
        if (queryParts.length === 0) queryParts.push('*:*');

        // overwrite SOLR default limit for sub-resource processing
        if (!request.limit) request.limit = NO_LIMIT;
        if (request.page) params.start = (request.page - 1) * request.limit;

        if (!request.limitPer) params.rows = request.limit;
        else {
            Object.assign(params, {
                group: 'true',
                'group.format': 'simple',
                'group.main': 'true',
                'group.field': request.limitPer,
                'group.limit': request.limit,
                rows: NO_LIMIT // disable default limit because groups are returned as list
            });
        }

        params.q = queryParts.join(' AND ');

        if (request._explain) Object.assign(request._explain, { url: requestUrl, params });
        if (this._status) this._status.increment('dataSourceQueries');

        const requestOpts = {
            connectTimeout: serverOpts[server].connectTimeout || 2000,
            requestTimeout: serverOpts[server].requestTimeout || 10000
        };

        return querySolr(requestUrl, params, requestOpts, this._agent);
    }

    /**
     * @returns {Promise}
     */
    close() {
        return Promise.resolve();
    }

    /**
     * @param {...string} args
     */
    escape(...args) {
        return escapeValueForSolr(...args);
    }
}

module.exports = DataSource;
<commit_msg>Keep Solr connections alive for 10 seconds<commit_after>'use strict';

const http = require('http');
const url = require('url');
const querystring = require('querystring');

const _ = require('lodash');
const { ImplementationError } = require('flora-errors');

const SUPPORTED_FILTERS = ['equal', 'notEqual', 'lessOrEqual', 'greaterOrEqual', 'range'];

const NO_LIMIT = 1000000;

/**
 * Return true if two filters on same attribute can be used as single range filter.
 *
 * @param {Array.<Object>} filters
 * @return {boolean}
 * @private
 */
function filterRangeQueries(filters) {
    if (filters.length !== 2) return false;

    const rangeOperators = ['lessOrEqual', 'greaterOrEqual'];
    const operator1 = filters[0].operator;
    const operator2 = filters[1].operator;

    return rangeOperators.indexOf(operator1) !== -1 && rangeOperators.indexOf(operator2) !== -1;
}

/**
 * Create range filter from a greatOrEqual and lessOrEqual filter.
 *
 * @param {Array.<string>} attributeFilters
 * @return {Object}
 * @private
 */
function createRangeFilter(attributeFilters) {
    const rangeFilter = { attribute: attributeFilters[0].attribute, operator: 'range' };

    // make sure greaterOrEqual filter comes first
    attributeFilters.sort(filter1 => (filter1.operator === 'greaterOrEqual' ? -1 : 1));

    rangeFilter.value = [attributeFilters[0].value, attributeFilters[1].value];
    return rangeFilter;
}

/**
 * Convert greaterOrEqual and lessOrEqual filters on same attribute
 * to a single range filter.
 *
 * @param {Array.<Object>} filters
 * @return {Array.<Object>}
 * @private
 */
function rangify(filters) {
    const groupedAttrs = _.groupBy(filters, 'attribute');
    const rangeQueries = _.filter(groupedAttrs, filterRangeQueries);

    if (!rangeQueries.length) return filters;

    const rangeQueryAttrs = rangeQueries.map(rangeQuery => rangeQuery[0].attribute);

    // copy non-range query attributes
    return filters.filter(filter => rangeQueryAttrs.indexOf(filter.attribute) === -1).concat(rangeQueries.map(createRangeFilter));
}

/**
 * @param {string} value
 * @return {string}
 * @private
 */
function escapeSpecialChars(value) {
    const specialCharRegex = /(\\|\/|\+|-|&|\||!|\(|\)|\{|}|\[|]|\^|"|~|\*|\?|:)/g;
    return value.replace(specialCharRegex, '\\$1');
}

/**
 * @param {string} value
 * @return {string}
 * @private
 */
function escapeSpecialCharsSolrSyntax(value) {
    const specialCharRegex = /(\\|\/|\+|-|&|\||!|\(|\)|\{|}|\[|]|\^|~|\?)/g;
    return value.replace(specialCharRegex, '\\$1');
}

/**
 * Escape strings and convert boolean values.
 *
 * @param {*} value
 * @param {boolean} exposeSolrSyntax
 * @return {*}
 * @private
 */
function escapeValueForSolr(value, exposeSolrSyntax) {
    if (typeof value === 'string') {
        value = exposeSolrSyntax ? escapeSpecialCharsSolrSyntax(value) : escapeSpecialChars(value);
    } else if (typeof value === 'boolean') value = value === false ? 0 : 1;
    return value;
}

/**
 * @param {Object} filter
 * @return {string}
 * @private
 */
function convertFilterToSolrSyntax(filter) {
    const { operator } = filter;
    let { value } = filter;

    if (SUPPORTED_FILTERS.indexOf(filter.operator) === -1) {
        throw new ImplementationError(`DataSource "flora-solr" does not support "${operator}" filters`);
    }

    if (!Array.isArray(filter.attribute)) {
        value = escapeValueForSolr(value);
        if (Array.isArray(value)) {
            if (operator === 'range') value = '[' + value[0] + ' TO ' + value[1] + ']';
            else value = '(' + value.join(' OR ') + ')';
        }

        if (operator !== 'notEqual') {
            if (operator === 'greaterOrEqual') value = '[' + value + ' TO *]';
            if (operator === 'lessOrEqual') value = '[* TO ' + value + ']';
            return filter.attribute + ':' + value;
        }
        return '-' + filter.attribute + ':' + value;
    }

    // convert composite keys to SOLR syntax
    return value
        .map(values => {
            const conditions = values.map((val, index) => filter.attribute[index] + ':' + escapeValueForSolr(val));
            return '(' + conditions.join(' AND ') + ')';
        })
        .join(' OR ');
}

function buildSolrFilterString(floraFilters) {
    const orConditions = floraFilters.map(andFilters => {
        if (andFilters.length > 1) andFilters = rangify(andFilters);
        const conditions = andFilters.map(convertFilterToSolrSyntax);
        return '(' + conditions.join(' AND ') + ')';
    });

    if (orConditions.length > 1) return '(' + orConditions.join(' OR ') + ')';

    return orConditions.join('');
}

/**
 * @param {Array.<Object>} floraOrders
 * @return {string}
 * @private
 */
function buildSolrOrderString(floraOrders) {
    return floraOrders.map(order => order.attribute + ' ' + order.direction).join(',');
}

function parseData(str) {
    try {
        return JSON.parse(str);
    } catch (e) {
        return new Error('Could not parse response: ' + str);
    }
}

function prepareQueryAddition(queryAdditions) {
    return queryAdditions
        .replace(/[\r\n]+/g, ' ')
        .replace(/\s{2,}/g, ' ')
        .trim();
}

/**
 * @param {Object} servers
 * @return {Object}
 */
function getUrlGenerators(servers) {
    return Object.keys(servers).reduce((acc, server) => {
        const { urls } = servers[server];

        acc[server] = (function* urlGenerator() {
            while (true) {
                for (let i = 0, l = urls.length; i < l; ++i) {
                    yield urls[i];
                }
            }
        })();

        return acc;
    }, {});
}

/**
 *
 * @param {string} requestUrl
 * @param {Object} params
 * @param {Object} requestOptions
 * @param {Agent} agent
 * @returns {Promise}
 * @private
 */
function querySolr(requestUrl, params, requestOptions, agent) {
    return new Promise((resolve, reject) => {
        const options = Object.assign(url.parse(requestUrl), {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            timeout: requestOptions.connectTimeout,
            agent
        });

        const req = http.request(options, res => {
            const chunks = [];

            res.on('data', chunk => chunks.push(chunk));

            res.on('end', () => {
                const data = parseData(Buffer.concat(chunks).toString('utf8'));

                if (res.statusCode >= 400 || data instanceof Error) {
                    const error = new Error('Solr error: ' + res.statusCode + ' ' + http.STATUS_CODES[res.statusCode]);
                    if (data instanceof Error) {
                        error.message += ': ' + data.message;
                    } else if (data && data.error && data.error.msg) {
                        error.message += ': ' + data.error.msg;
                    }

                    return reject(error);
                }

                return resolve({ totalCount: data.response.numFound, data: data.response.docs });
            });
        });

        req.setTimeout(requestOptions.requestTimeout, () => req.abort());

        req.write(querystring.stringify(params)); // add params to POST body

        req.on('error', err => {
            err.message = 'Solr error: ' + err.message + ' (' + options.host + ')';
            reject(err);
        });

        req.end();
    });
}

function prepareSearchTerm(request) {
    const escapedSearchTerm = escapeValueForSolr(request.search, request.exposeSolrSyntax);
    const allowedSearchFields =
        request.allowedSearchFields && request.allowedSearchFields.trim() ? request.allowedSearchFields.trim().split(',') : [];

    if (!allowedSearchFields.length) {
        return escapedSearchTerm;
    }

    const regex = new RegExp(`^(?<field>${allowedSearchFields.join('|')}):(?<search>.+)`);
    const match = regex.exec(request.search);

    if (match === null) {
        return escapedSearchTerm;
    }

    return `(${match.groups.field}:"${match.groups.search}")`;
}

class DataSource {
    /**
     * @param {Api} api
     * @param {Object} config
     */
    constructor(api, config) {
        this.options = config;
        this._urls = getUrlGenerators(config.servers);
        this._status = config._status;
        delete config._status;

        this._agent = new http.Agent({
            maxSockets: 10,
            keepAlive: true,
            keepAliveMsecs: 10000
        });
    }

    /**
     * @public
     */
    prepare() {}

    /**
     * @param {Object} request
     * @returns {Promise<Object>}
     */
    async process(request) {
        const server = request.server || 'default';
        const queryParts = [];
        const params = { wt: 'json' };
        const serverOpts = this.options.servers;

        if (!serverOpts[server]) throw new Error(`Server "${server}" not defined`);

        const requestUrl = this._urls[server].next().value + request.collection + '/select';

        if (request.attributes) params.fl = request.attributes.join(',');
        if (request.order) params.sort = buildSolrOrderString(request.order);

        if (request.df) params.df = request.df;
        if (request.search && request.search.trim()) queryParts.push(prepareSearchTerm(request));
        if (request.filter) {
            queryParts.push(buildSolrFilterString(request.filter));
        }
        if (request.queryAddition) queryParts.push(prepareQueryAddition(request.queryAddition));
        if (queryParts.length === 0) queryParts.push('*:*');

        // overwrite SOLR default limit for sub-resource processing
        if (!request.limit) request.limit = NO_LIMIT;
        if (request.page) params.start = (request.page - 1) * request.limit;

        if (!request.limitPer) params.rows = request.limit;
        else {
            Object.assign(params, {
                group: 'true',
                'group.format': 'simple',
                'group.main': 'true',
                'group.field': request.limitPer,
                'group.limit': request.limit,
                rows: NO_LIMIT // disable default limit because groups are returned as list
            });
        }

        params.q = queryParts.join(' AND ');

        if (request._explain) Object.assign(request._explain, { url: requestUrl, params });
        if (this._status) this._status.increment('dataSourceQueries');

        const requestOpts = {
            connectTimeout: serverOpts[server].connectTimeout || 2000,
            requestTimeout: serverOpts[server].requestTimeout || 10000
        };

        return querySolr(requestUrl, params, requestOpts, this._agent);
    }

    /**
     * @returns {Promise}
     */
    close() {
        return Promise.resolve();
    }

    /**
     * @param {...string} args
     */
    escape(...args) {
        return escapeValueForSolr(...args);
    }
}

module.exports = DataSource;
<|endoftext|>


<commit_before>var _ = require('underscore');
_.mixin( require('underscore.deferred') );
var inflection = require('inflection');
var Twit = require('twit');
var T = new Twit(require('./config.js'));
var wordfilter = require('wordfilter');
var wordnikKey = process.env.WORDNIK_KEY;
var request = require('request');

var randomWords = {
    noun: [],
    adjective: [],
    verb: [],
    pnoun: [],
    nounplural: [],
    adverb: [],
    inter: []
};

var nounCache = [];
var pluralNounCache = [];

Array.prototype.pick = function() {
    return this[Math.floor(Math.random()*this.length)];
};

Array.prototype.pickRemove = function() {
    var index = Math.floor(Math.random()*this.length);
    return this.splice(index,1)[0];
};

var templates = [
    "SCUM: You <%= verbTransitive() %>. We’ll take care of the <%= nounPlural() %>.",
    "SCUM is against <%= adjective() %>, <%= adjective() %>, <%= nounPlural() %>, with no clear objective in mind, and in which many of your own kind are picked off.",
    "SCUM is out to destroy the <%= noun() %>, not attain certain rights within it.",
    "SCUM will always be <%= adjective() %>, <%= adjective() %>, <%= adjective() %> (although SCUM <%= nounPlural() %> will always be known to be such).",
    "SCUM is against the entire system, the very idea of <%= noun() %> and <%= noun() %>.",
    "SCUM will destroy all useless and harmful objects -- <%= nounPlural() %>, <%= nounPlural() %>, <%= nounPlural() %>  etc.",
    "SCUM: Not Your Typical <%= capitalNoun() %>",
    "SCUM: What’s in your <%= noun() %>?",
    "SCUM: the <%= noun() %> of <%= noun1() %> <%= nounPlural() %>",
    "SCUM: not just for <%= nounPlural() %>!",
    "SCUM will kill all <%= nounPlural() %> who are not in the <%= capitalize(nounPlural1()) %>’s Auxiliary of SCUM.",
    "SCUM will <%= adverb() %>, <%= adverb() %>, stalk its <%= noun() %> and quietly move in for the kill."
];

var wordFinders = function() {

    var capitalize = function(word) {
        return word.charAt(0).toUpperCase() + word.slice(1);
    };

    var adjective = function() { return randomWords.adjective.pick().word; };
    var adverb = function() { return randomWords.adverb.pick().word; };
    var capitalNoun = function() { var n = randomWords.noun.pick().word; nounCache.push(n); return capitalize(n); };
    var capitalNoun1 = function() { return capitalize(nounCache[0]); };
    var noun = function() { var n = randomWords.noun.pick().word; nounCache.push(n); return n; };
    var noun1 = function() { return nounCache[0]; };
    var nounPlural = function() { var np = randomWords.nounplural.pick().word; pluralNounCache.push(np); return np; };
    var nounPlural1 = function() { return pluralNounCache[0]; };
    var verb = function() { return randomWords.verb.pick().word; };
    var verbTransitive = function() { return randomWords.verb.pick().word; };

    return {
        adjective: adjective,
        adverb: adverb,
        capitalNoun1: capitalNoun1,
        capitalNoun: capitalNoun,
        capitalize: capitalize,
        noun1: noun1,
        noun: noun,
        nounPlural: nounPlural,
        nounPlural1: nounPlural1,
        verb: verb,
        verbTransitive: verbTransitive
    };

}();

function getSentence() {

    // console.log(randomWords);
    nounCache = [];
    pluralNounCache = [];

    var tmpl = templates.pick();
    //console.log(tmpl);
    var t = _.template(tmpl);
    var s = t(wordFinders);

    //console.log(s);

    return s;

};

function generate() {

    var dfd = new _.Deferred();

    var randomWordNounPromise = getRandomWordsPromise('noun');
    var randomWordAdjPromise = getRandomWordsPromise('adjective');
    var randomWordNounPluralPromise = getRandomWordsPromise('noun-plural');
    var randomWordAdvPromise = getRandomWordsPromise('adverb');
    var randomWordVerbPromise = getRandomWordsPromise('verb-transitive');

    _.when(
        randomWordNounPromise,
        randomWordAdjPromise,
        randomWordNounPluralPromise,
        randomWordAdvPromise,
        randomWordVerbPromise
    ).done(function() {
        dfd.resolve(getSentence());
    });

    //dfd.resolve();
    return dfd.promise();
}

function getRandomWordsPromise(pos,minCount) {
    minCount = minCount || 1000; // the lower the number, the less common
    var url = "http://api.wordnik.com/v4/words.json/randomWords?includePartOfSpeech="+pos+"&excludePartOfSpeech=proper-noun-plural,proper-noun-posessive,suffix,family-name,idiom,affix&minCorpusCount="+minCount+"&hasDictionaryDef=true&limit=10&api_key=" + wordnikKey;
    var rwDeferred = _.Deferred();
    var randomWordNounPromise = rwDeferred.promise();
    request({
        url: url
    }, function (error, response, body) {
        // console.log(body);
        if (JSON.parse(body).message === "exceeded access limits") {
            console.log("We're over the access limit, nooo!");
            rwDeferred.reject(error);
        }
        else if (!error && response.statusCode === 200) {
            //console.log(JSON.parse(body).word);
            //console.log(I.singularize(JSON.parse(body).word));
            rwDeferred.resolve(JSON.parse(body));
        }
        else {
            rwDeferred.reject(error);
        }
    });
    (function(pos) {
        randomWordNounPromise.done(function(words) {
            if (pos === "noun") {
                randomWords.noun = words;
            }
            else if (pos === "adjective") {
                randomWords.adjective = words;
            }
            else if (pos === "verb") {
                randomWords.verb = words;
            }
            else if (pos === "verb-transitive") {
                randomWords.verb = words;
            }
            else if (pos === "proper-noun") {
                randomWords.pnoun = words;
            }
            else if (pos === "noun-plural") {
                randomWords.nounplural = words;
            }
            else if (pos === "interjection") {
                randomWords.inter = words;
            }
            else if (pos === "adverb") {
                randomWords.adverb = words;
            }
        });
    })(pos);
    return randomWordNounPromise;
}

function tweet() {
    generate().then(function(myTweet) {
        if (!wordfilter.blacklisted(myTweet)) {
            console.log(myTweet);

            T.post('statuses/update', { status: myTweet }, function(err, reply) {
                if (err) {
                    console.log('error:', err);
                }
                else {
                    console.log('reply:', reply);
                }
            });
        }
    });
}

// Tweet every 60 minutes
setInterval(function () {
    try {
        tweet();
    }
    catch (e) {
        console.log(e);
    }
// }, 1000 * 30 * 60);
}, 1000 * 10);

// Tweet once on initialization
tweet();
<commit_msg>15 minutes<commit_after>var _ = require('underscore');
_.mixin( require('underscore.deferred') );
var inflection = require('inflection');
var Twit = require('twit');
var T = new Twit(require('./config.js'));
var wordfilter = require('wordfilter');
var wordnikKey = process.env.WORDNIK_KEY;
var request = require('request');

var randomWords = {
    noun: [],
    adjective: [],
    verb: [],
    pnoun: [],
    nounplural: [],
    adverb: [],
    inter: []
};

var nounCache = [];
var pluralNounCache = [];

Array.prototype.pick = function() {
    return this[Math.floor(Math.random()*this.length)];
};

Array.prototype.pickRemove = function() {
    var index = Math.floor(Math.random()*this.length);
    return this.splice(index,1)[0];
};

var templates = [
    "SCUM: You <%= verbTransitive() %>. We’ll take care of the <%= nounPlural() %>.",
    "SCUM is against <%= adjective() %>, <%= adjective() %>, <%= nounPlural() %>, with no clear objective in mind, and in which many of your own kind are picked off.",
    "SCUM is out to destroy the <%= noun() %>, not attain certain rights within it.",
    "SCUM will always be <%= adjective() %>, <%= adjective() %>, <%= adjective() %> (although SCUM <%= nounPlural() %> will always be known to be such).",
    "SCUM is against the entire system, the very idea of <%= noun() %> and <%= noun() %>.",
    "SCUM will destroy all useless and harmful objects -- <%= nounPlural() %>, <%= nounPlural() %>, <%= nounPlural() %>  etc.",
    "SCUM: Not Your Typical <%= capitalNoun() %>",
    "SCUM: What’s in your <%= noun() %>?",
    "SCUM: the <%= noun() %> of <%= noun1() %> <%= nounPlural() %>",
    "SCUM: not just for <%= nounPlural() %>!",
    "SCUM will kill all <%= nounPlural() %> who are not in the <%= capitalize(nounPlural1()) %>’s Auxiliary of SCUM.",
    "SCUM will <%= adverb() %>, <%= adverb() %>, stalk its <%= noun() %> and quietly move in for the kill."
];

var wordFinders = function() {

    var capitalize = function(word) {
        return word.charAt(0).toUpperCase() + word.slice(1);
    };

    var adjective = function() { return randomWords.adjective.pick().word; };
    var adverb = function() { return randomWords.adverb.pick().word; };
    var capitalNoun = function() { var n = randomWords.noun.pick().word; nounCache.push(n); return capitalize(n); };
    var capitalNoun1 = function() { return capitalize(nounCache[0]); };
    var noun = function() { var n = randomWords.noun.pick().word; nounCache.push(n); return n; };
    var noun1 = function() { return nounCache[0]; };
    var nounPlural = function() { var np = randomWords.nounplural.pick().word; pluralNounCache.push(np); return np; };
    var nounPlural1 = function() { return pluralNounCache[0]; };
    var verb = function() { return randomWords.verb.pick().word; };
    var verbTransitive = function() { return randomWords.verb.pick().word; };

    return {
        adjective: adjective,
        adverb: adverb,
        capitalNoun1: capitalNoun1,
        capitalNoun: capitalNoun,
        capitalize: capitalize,
        noun1: noun1,
        noun: noun,
        nounPlural: nounPlural,
        nounPlural1: nounPlural1,
        verb: verb,
        verbTransitive: verbTransitive
    };

}();

function getSentence() {

    // console.log(randomWords);
    nounCache = [];
    pluralNounCache = [];

    var tmpl = templates.pick();
    //console.log(tmpl);
    var t = _.template(tmpl);
    var s = t(wordFinders);

    //console.log(s);

    return s;

};

function generate() {

    var dfd = new _.Deferred();

    var randomWordNounPromise = getRandomWordsPromise('noun');
    var randomWordAdjPromise = getRandomWordsPromise('adjective');
    var randomWordNounPluralPromise = getRandomWordsPromise('noun-plural');
    var randomWordAdvPromise = getRandomWordsPromise('adverb');
    var randomWordVerbPromise = getRandomWordsPromise('verb-transitive');

    _.when(
        randomWordNounPromise,
        randomWordAdjPromise,
        randomWordNounPluralPromise,
        randomWordAdvPromise,
        randomWordVerbPromise
    ).done(function() {
        dfd.resolve(getSentence());
    });

    //dfd.resolve();
    return dfd.promise();
}

function getRandomWordsPromise(pos,minCount) {
    minCount = minCount || 1000; // the lower the number, the less common
    var url = "http://api.wordnik.com/v4/words.json/randomWords?includePartOfSpeech="+pos+"&excludePartOfSpeech=proper-noun-plural,proper-noun-posessive,suffix,family-name,idiom,affix&minCorpusCount="+minCount+"&hasDictionaryDef=true&limit=10&api_key=" + wordnikKey;
    var rwDeferred = _.Deferred();
    var randomWordNounPromise = rwDeferred.promise();
    request({
        url: url
    }, function (error, response, body) {
        // console.log(body);
        if (JSON.parse(body).message === "exceeded access limits") {
            console.log("We're over the access limit, nooo!");
            rwDeferred.reject(error);
        }
        else if (!error && response.statusCode === 200) {
            //console.log(JSON.parse(body).word);
            //console.log(I.singularize(JSON.parse(body).word));
            rwDeferred.resolve(JSON.parse(body));
        }
        else {
            rwDeferred.reject(error);
        }
    });
    (function(pos) {
        randomWordNounPromise.done(function(words) {
            if (pos === "noun") {
                randomWords.noun = words;
            }
            else if (pos === "adjective") {
                randomWords.adjective = words;
            }
            else if (pos === "verb") {
                randomWords.verb = words;
            }
            else if (pos === "verb-transitive") {
                randomWords.verb = words;
            }
            else if (pos === "proper-noun") {
                randomWords.pnoun = words;
            }
            else if (pos === "noun-plural") {
                randomWords.nounplural = words;
            }
            else if (pos === "interjection") {
                randomWords.inter = words;
            }
            else if (pos === "adverb") {
                randomWords.adverb = words;
            }
        });
    })(pos);
    return randomWordNounPromise;
}

function tweet() {
    generate().then(function(myTweet) {
        if (!wordfilter.blacklisted(myTweet)) {
            console.log(myTweet);

            T.post('statuses/update', { status: myTweet }, function(err, reply) {
                if (err) {
                    console.log('error:', err);
                }
                else {
                    console.log('reply:', reply);
                }
            });
        }
    });
}

// Tweet every 60 minutes
setInterval(function () {
    try {
        tweet();
    }
    catch (e) {
        console.log(e);
    }
// TODO: get this into a heroku variable...
}, 1000 * 15 * 60);
// }, 1000 * 10);

// Tweet once on initialization
tweet();
<|endoftext|>


<commit_before>class ApiService {
  constructor () {
    this.url = 'https://36yfx8yfid.execute-api.eu-west-1.amazonaws.com/dev';
  }
}

class TopicsService {
  constructor ($http, apiService) {
    Object.assign(this, {$http, apiService});
  }

  getTopics () {
    if (!this.topicsPromise) {
      this.topicsPromise = this.$http.get(`${this.apiService.url}/topics`);
    }

    return this.topicsPromise;
  }

  createTopic (topic) {
    return this.$http.post(`${this.apiService.url}/topics`, topic);
  }
}

class VotingService {
  constructor ($http, apiService) {
    Object.assign(this, {$http, apiService});
  }

  vote (id, vote) {
    this.$http.post(`${this.apiService.url}/votes`, {topic_id: id, vote});
  }

  downVote (topic) {
    this.vote(topic.id, '-1');
  }

  upVote (topic) {
    this.vote(topic.id, '1');
  }
}

class VotingTopicsComponentController {
  constructor (topicsService) {
    this.loading = true;
    topicsService.getTopics().then(({data}) => {
      if (data.errorMessage) {
        this.error = data.errorMessage;
      } else if (data.length >= 0) {
        this.topics = data;
        this.loading = false;
      }
    });
  }
}

class VoterComponentController {
  constructor (votingService) {
    this.votingService = votingService;
  }

  downVote () {
    if (!this.clickedDownVote) {
      this.clickedDownVote = true;
      this.clickedUpVote = false;
      this.votingService.downVote(this.topic);
      this.topic.total--;
    }
  }

  upVote () {
    if (!this.clickedUpVote) {
      this.clickedUpVote = true;
      this.clickedDownVote = false;
      this.votingService.upVote(this.topic);
      this.topic.total++;
    }
  }
}

class topicCreatorComponentController {
  constructor (topicsService) {
    this.topicsService = topicsService;
  }

  createTopic (topic) {
    this.topicsService.createTopic(topic).then(({data}) => {
      Object.assign(topic, {id: data.id, total: 0});
      this.topics.push(topic);
      this.newTopic = {};
    });
  }
}

angular.module('app', [])
  .service('apiService', ApiService)
  .service('topicsService', TopicsService)
  .service('votingService', VotingService)
  .component('votingTopics', {
    controller: VotingTopicsComponentController,
    controllerAs: 'votingTopics',
    template: `

            toc
            account_circle
            thumbs_up_down
            star

              <voter topic="topic"></voter>

    `
  }).component('voter', {
    controller: VoterComponentController,
    controllerAs: 'voter',
    bindings: {
      topic: '='
    },
    template: `
      <button ng-click="voter.downVote()" ng-class="{selecttup: voter.clickedDownVote}">thumb_down</button>
      <button ng-click="voter.upVote()" ng-class="{selectdn: voter.clickedUpVote}">thumb_up</button>
    `
  }).component('tfoot', {
    controller: topicCreatorComponentController,
    controllerAs: 'topicCreator',
    bindings: {
      topics: '='
    },
    template: `

        <input ng-model="topicCreator.newTopic.topic" placeholder="Topic">
        <input ng-model="topicCreator.newTopic.speaker" placeholder="Speaker">

          <button ng-click="topicCreator.createTopic(topicCreator.newTopic)">add_circle</button>

    `
  });

angular.element(document).ready(function() {
  angular.bootstrap(document, ['app']);
});

// GET https://36yfx8yfid.execute-api.eu-west-1.amazonaws.com/dev/topics/ivlPpLzsLb

// POST https://36yfx8yfid.execute-api.eu-west-1.amazonaws.com/dev/topics
// body: {
//  "title" : "doood",
//  "speaker" : "Michael Osl"
//}

// POST /dev/votes
// {
//     "id": ID
//     "vote": 1 // or -1
// }
<commit_msg>Fix voting bug<commit_after>class ApiService {
  constructor () {
    this.url = 'https://36yfx8yfid.execute-api.eu-west-1.amazonaws.com/dev';
  }
}

class TopicsService {
  constructor ($http, apiService) {
    Object.assign(this, {$http, apiService});
  }

  getTopics () {
    if (!this.topicsPromise) {
      this.topicsPromise = this.$http.get(`${this.apiService.url}/topics`);
    }

    return this.topicsPromise;
  }

  createTopic (topic) {
    return this.$http.post(`${this.apiService.url}/topics`, topic);
  }
}

class VotingService {
  constructor ($http, apiService) {
    Object.assign(this, {$http, apiService});
  }

  vote (id, vote) {
    this.$http.post(`${this.apiService.url}/votes`, {topic_id: id, vote});
  }

  downVote (topic) {
    this.vote(topic.id, '-1');
  }

  upVote (topic) {
    this.vote(topic.id, '1');
  }
}

class VotingTopicsComponentController {
  constructor (topicsService) {
    this.loading = true;
    topicsService.getTopics().then(({data}) => {
      if (data.errorMessage) {
        this.error = data.errorMessage;
      } else if (data.length >= 0) {
        this.topics = data;
        this.loading = false;
      }
    });
  }
}

class VoterComponentController {
  constructor (votingService) {
    this.votingService = votingService;
  }

  downVote () {
    if (!this.clickedDownVote) {
      // Reset existing vote
      if (this.clickedUpVote) {
        this.votingService.downVote(this.topic);
        this.topic.total--;
      }

      this.clickedDownVote = true;
      this.clickedUpVote = false;
      this.votingService.downVote(this.topic);
      this.topic.total--;
    }
  }

  upVote () {
    if (!this.clickedUpVote) {
      // Reset existing vote
      if (this.clickedDownVote) {
        this.votingService.upVote(this.topic);
        this.topic.total++;
      }

      this.clickedUpVote = true;
      this.clickedDownVote = false;
      this.votingService.upVote(this.topic);
      this.topic.total++;
    }
  }
}

class topicCreatorComponentController {
  constructor (topicsService) {
    this.topicsService = topicsService;
  }

  createTopic (topic) {
    this.topicsService.createTopic(topic).then(({data}) => {
      Object.assign(topic, {id: data.id, total: 0});
      this.topics.push(topic);
      this.newTopic = {};
    });
  }
}

angular.module('app', [])
  .service('apiService', ApiService)
  .service('topicsService', TopicsService)
  .service('votingService', VotingService)
  .component('votingTopics', {
    controller: VotingTopicsComponentController,
    controllerAs: 'votingTopics',
    template: `

            toc
            account_circle
            thumbs_up_down
            star

              <voter topic="topic"></voter>

    `
  }).component('voter', {
    controller: VoterComponentController,
    controllerAs: 'voter',
    bindings: {
      topic: '='
    },
    template: `
      <button ng-click="voter.downVote()" ng-class="{selecttup: voter.clickedDownVote}">thumb_down</button>
      <button ng-click="voter.upVote()" ng-class="{selectdn: voter.clickedUpVote}">thumb_up</button>
    `
  }).component('tfoot', {
    controller: topicCreatorComponentController,
    controllerAs: 'topicCreator',
    bindings: {
      topics: '='
    },
    template: `

        <input ng-model="topicCreator.newTopic.topic" placeholder="Topic">
        <input ng-model="topicCreator.newTopic.speaker" placeholder="Speaker">

          <button ng-click="topicCreator.createTopic(topicCreator.newTopic)">add_circle</button>

    `
  });

angular.element(document).ready(function() {
  angular.bootstrap(document, ['app']);
});

// GET https://36yfx8yfid.execute-api.eu-west-1.amazonaws.com/dev/topics/ivlPpLzsLb

// POST https://36yfx8yfid.execute-api.eu-west-1.amazonaws.com/dev/topics
// body: {
//  "title" : "doood",
//  "speaker" : "Michael Osl"
//}

// POST /dev/votes
// {
//     "id": ID
//     "vote": 1 // or -1
// }
<|endoftext|>


<commit_before>require('dotenv').load();

const express = require('express');
const next = require('next');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const basicAuth = require('basic-auth');
const sass = require('node-sass');
const serveStatic = require('serve-static');
const postcssMiddleware = require('postcss-middleware');
const redis = require('redis');
const RedisStore = require('connect-redis')(session);
const { parse } = require('url');
const path = require('path');
const routes = require('./routes');
const postcssConfig = require('./postcss.config');
const auth = require('./auth');

const port = process.env.PORT || 3000;
const prod = process.env.NODE_ENV === 'production';

// Next app creation
const app = next({ dev: !prod });
const handle = routes.getRequestHandler(app, ({
  req, res, route, query
}) => {
  app.render(req, res, route.page, query);
});

// Express app creation
const server = express();

function checkBasicAuth(users) {
  return function authMiddleware(req, res, nextAction) {
    if (!/(AddSearchBot)|(HeadlessChrome)/.test(req.headers['user-agent'])) {
      const user = basicAuth(req);
      let authorized = false;
      if (user && ((user.name === users[0].name && user.pass === users[0].pass) ||
        (user.name === users[1].name && user.pass === users[1].pass))) {
        authorized = true;
      }

      if (!authorized) {
        res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
        return res.sendStatus(401);
      }
    }
    return nextAction();
  };
}

function isAuthenticated(req, res, nextAction) {
  // Saving referrer of user
  req.session.referrer = req.url;
  if (req.isAuthenticated()) return nextAction();
  // if they aren't redirect them to the home page
  return res.redirect('/login');
}

function isAdmin(req, res, nextAction) {
  if (req.user.role === 'ADMIN') return nextAction();
  // if they aren't redirect them to the home page
  return res.redirect('/myrw');
}

// Configuring session and cookie options
const sessionOptions = {
  secret: process.env.SECRET || 'keyboard cat',
  resave: false,
  saveUninitialized: true
};

if (prod) {
  const redisClient = redis.createClient(process.env.REDIS_URL);
  sessionOptions.store = new RedisStore({
    client: redisClient,
    logErrors: true,
    prefix: 'resourcewatch_sess_'
  });
}

// Using basic auth in prod mode
const { USERNAME, PASSWORD, RW_USERNAME, RW_PASSWORD } = process.env;
if (prod && ((USERNAME && PASSWORD) || (RW_USERNAME && RW_PASSWORD))) {
  server.use(checkBasicAuth([{
    name: USERNAME,
    pass: PASSWORD
  }, {
    name: RW_USERNAME,
    pass: RW_PASSWORD
  }]));
}

// configure Express
server.use(cookieParser());
server.use(bodyParser.urlencoded({ extended: false }));
server.use(bodyParser.json());
server.use(session(sessionOptions));
server.use(serveStatic(path.join(__dirname, 'static')));

// Middleware check: Make sure that we trigger auth if a token is passed to RW
server.use((req, res, nextAction) => {
  if (req.query && req.query.token && !/auth/.test(req.url)) {
    return res.redirect(`/auth?token=${req.query.token}`);
  }
  return nextAction();
});

// Authentication
auth.initialize(server);

// Initializing next app before express server
app.prepare()
  .then(() => {
    // Configuring next routes with express
    const handleUrl = (req, res) => {
      const parsedUrl = parse(req.url, true);
      return handle(req, res, parsedUrl);
    };

    // Redirecting data to data/explore
    // TODO: create data page
    server.get('/data', (req, res) => res.redirect('/data/explore'));

    // Authentication
    server.get('/auth', auth.authenticate({ failureRedirect: '/login' }), (req, res) => {
      if (req.user.role === 'ADMIN' && /admin/.test(req.session.referrer)) return res.redirect('/admin');
      const authRedirect = req.cookies.authUrl || '/myrw';

      if (req.cookies.authUrl) {
        res.clearCookie('authUrl');
      }

      return res.redirect(authRedirect);
    });

    // Authenticate specific service, and set authUrl cookie so we remember where we where
    server.get('/auth/:service', (req, res) => {
      const { service } = req.params;

      // Returning user data
      if (service === 'user') return res.json(req.user || {});

      if (!/facebook|google|twitter/.test(service)) {
        return res.redirect('/');
      }

      if (req.cookies.authUrl) {
        res.clearCookie('authUrl');
      }

      // save the current url for redirect if successfull, set it to expire in 5 min
      res.cookie('authUrl', req.headers.referer, { maxAge: 3E5, httpOnly: true });
      return res.redirect(`${process.env.CONTROL_TOWER_URL}/auth/${service}?callbackUrl=${process.env.CALLBACK_URL}&applications=rw&token=true&origin=rw`);
    });

    server.get('/login', auth.login);
    server.get('/logout', (req, res) => {
      req.session.destroy();
      req.logout();
      res.redirect('back');
    });

    // Routes with required authentication
    server.get('/myrw-detail*?', isAuthenticated, handleUrl); // TODO: review these routes
    server.get('/myrw*?', isAuthenticated, handleUrl);
    server.get('/admin*?', isAuthenticated, isAdmin, handleUrl);

    server.use(handle);

    server.listen(port, (err) => {
      if (err) throw err;
      console.info(`> Ready on http://localhost:${port} [${process.env.NODE_ENV || 'development'}]`);
    });
  });
<commit_msg>removed not necessary libs in index<commit_after>require('dotenv').load();

const express = require('express');
const next = require('next');
const session = require('express-session');
const cookieParser = require('cookie-parser');
const bodyParser = require('body-parser');
const basicAuth = require('basic-auth');
const serveStatic = require('serve-static');
const redis = require('redis');
const RedisStore = require('connect-redis')(session);
const { parse } = require('url');
const path = require('path');
const routes = require('./routes');
const auth = require('./auth');

const port = process.env.PORT || 3000;
const prod = process.env.NODE_ENV === 'production';

// Next app creation
const app = next({ dev: !prod });
const handle = routes.getRequestHandler(app, ({ req, res, route, query }) => {
  app.render(req, res, route.page, query);
});

// Express app creation
const server = express();

function checkBasicAuth(users) {
  return function authMiddleware(req, res, nextAction) {
    if (!/(AddSearchBot)|(HeadlessChrome)/.test(req.headers['user-agent'])) {
      const user = basicAuth(req);
      let authorized = false;
      if (user && ((user.name === users[0].name && user.pass === users[0].pass) ||
        (user.name === users[1].name && user.pass === users[1].pass))) {
        authorized = true;
      }

      if (!authorized) {
        res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
        return res.sendStatus(401);
      }
    }
    return nextAction();
  };
}

function isAuthenticated(req, res, nextAction) {
  // Saving referrer of user
  req.session.referrer = req.url;
  if (req.isAuthenticated()) return nextAction();
  // if they aren't redirect them to the home page
  return res.redirect('/login');
}

function isAdmin(req, res, nextAction) {
  if (req.user.role === 'ADMIN') return nextAction();
  // if they aren't redirect them to the home page
  return res.redirect('/myrw');
}

// Configuring session and cookie options
const sessionOptions = {
  secret: process.env.SECRET || 'keyboard cat',
  resave: false,
  saveUninitialized: true
};

if (prod) {
  const redisClient = redis.createClient(process.env.REDIS_URL);
  sessionOptions.store = new RedisStore({
    client: redisClient,
    logErrors: true,
    prefix: 'resourcewatch_sess_'
  });
}

// Using basic auth in prod mode
const { USERNAME, PASSWORD, RW_USERNAME, RW_PASSWORD } = process.env;
if (prod && ((USERNAME && PASSWORD) || (RW_USERNAME && RW_PASSWORD))) {
  server.use(checkBasicAuth([{
    name: USERNAME,
    pass: PASSWORD
  }, {
    name: RW_USERNAME,
    pass: RW_PASSWORD
  }]));
}

// configure Express
server.use(cookieParser());
server.use(bodyParser.urlencoded({ extended: false }));
server.use(bodyParser.json());
server.use(session(sessionOptions));
server.use(serveStatic(path.join(__dirname, 'static')));

// Middleware check: Make sure that we trigger auth if a token is passed to RW
server.use((req, res, nextAction) => {
  if (req.query && req.query.token && !/auth/.test(req.url)) {
    return res.redirect(`/auth?token=${req.query.token}`);
  }
  return nextAction();
});

// Authentication
auth.initialize(server);

// Initializing next app before express server
app.prepare()
  .then(() => {
    // Configuring next routes with express
    const handleUrl = (req, res) => {
      const parsedUrl = parse(req.url, true);
      return handle(req, res, parsedUrl);
    };

    // Redirecting data to data/explore
    // TODO: create data page
    server.get('/data', (req, res) => res.redirect('/data/explore'));

    // Authentication
    server.get('/auth', auth.authenticate({ failureRedirect: '/login' }), (req, res) => {
      if (req.user.role === 'ADMIN' && /admin/.test(req.session.referrer)) return res.redirect('/admin');
      const authRedirect = req.cookies.authUrl || '/myrw';

      if (req.cookies.authUrl) {
        res.clearCookie('authUrl');
      }

      return res.redirect(authRedirect);
    });

    // Authenticate specific service, and set authUrl cookie so we remember where we where
    server.get('/auth/:service', (req, res) => {
      const { service } = req.params;

      // Returning user data
      if (service === 'user') return res.json(req.user || {});

      if (!/facebook|google|twitter/.test(service)) {
        return res.redirect('/');
      }

      if (req.cookies.authUrl) {
        res.clearCookie('authUrl');
      }

      // save the current url for redirect if successfull, set it to expire in 5 min
      res.cookie('authUrl', req.headers.referer, { maxAge: 3E5, httpOnly: true });
      return res.redirect(`${process.env.CONTROL_TOWER_URL}/auth/${service}?callbackUrl=${process.env.CALLBACK_URL}&applications=rw&token=true&origin=rw`);
    });

    server.get('/login', auth.login);
    server.get('/logout', (req, res) => {
      req.session.destroy();
      req.logout();
      res.redirect('back');
    });

    // Routes with required authentication
    server.get('/myrw-detail*?', isAuthenticated, handleUrl); // TODO: review these routes
    server.get('/myrw*?', isAuthenticated, handleUrl);
    server.get('/admin*?', isAuthenticated, isAdmin, handleUrl);

    server.use(handle);

    server.listen(port, (err) => {
      if (err) throw err;
      console.info(`> Ready on http://localhost:${port} [${process.env.NODE_ENV || 'development'}]`);
    });
  });
<|endoftext|>


<commit_before>var stream  = require('stream');
var   util  = require('util');
var buffers = require('buffers');
var assert  = require('assert');

// creates new shaped trough stream
var ShapeStream = function (byteRate, chunkRate, lowWatermark, highWatermark) {
    this.rate = byteRate; // float number!
    if (!chunkRate)
        chunkRate = 10;
    if (!lowWatermark)
        lowWatermark = 0;
    if (!highWatermark)
        highWatermark = 0;

    this.lowWatermark = lowWatermark;
    this.highWatermark = highWatermark;
    this.checkInterval = 1000/chunkRate;
    this.buffer = buffers();
    this.startTime = Date.now();
    this.totalWritten = 0;
    this.writable = true;
    this.readable = true;
    this.sendTimer = null;
}
util.inherits(ShapeStream, stream.Stream);

ShapeStream.prototype.expectedWritten = function() {
    return parseInt(this.rate*(Date.now() - this.startTime)/1000);
}

ShapeStream.prototype.processBuffer = function() {
    var expected = this.expectedWritten();
    if (expected > this.totalWritten) {
        var lengthToWrite = expected - this.totalWritten;
        var chunk = this.buffer.splice(0, lengthToWrite);
        this.doWrite(chunk.toBuffer());
    }
    if (this.buffer.length <= this.lowWatermark && !this.stopping)
         this.emit('drain');

    if (this.buffer.length == 0) {
        this.sendTimer = null;
        if (this.stopping)
            this.emit('close');
    } else
        this.sendTimer = setTimeout(this.processBuffer.bind(this), this.checkInterval);
}

ShapeStream.prototype.doWrite = function(chunk) {
    this.totalWritten += chunk.length;
    //this.emit('data', cihunk);
};

ShapeStream.prototype.write = function(chunk, encoding) {
    if (typeof chunk === 'string')
        chunk = Buffer(chunk, encoding);
    var expected = this.expectedWritten();
    if (this.totalWritten + chunk.length < this.expectedWritten() && !this.paused)
    {
        this.doWrite(chunk);
        return true;
    }
    this.buffer.push(chunk);
    if (!this.paused && !this.sendTimer) // don't process buffer if it is already scheduled
        this.processBuffer();

    return this.buffer.length < this.highWatermark;
};

ShapeStream.prototype.end = function(chunk, encoding) {
    this.stopping = true;
    if (chunk)
        this.write(chunk, encoding);
    else
        this.processBuffer();
};

ShapeStream.prototype.pause = function() {
    this.pauseCount++;
    this.paused = true;
};

ShapeStream.prototype.resume = function() {
    this.pauseCount--;
    if (this.pauseCount == 0) {
        this.paused = false;
        this.processBuffer();
    }
};

ShapeStream.prototype.destroy = function() {
    // do nothing
}

ShapeStream.prototype.destroySoon = function() {
    // do nothing
}

module.exports = function(byteRate, chunkRate) {
   return new ShapeStream(byteRate, chunkRate);
}
<commit_msg>uncomment emitting data<commit_after>var stream  = require('stream');
var   util  = require('util');
var buffers = require('buffers');
var assert  = require('assert');

// creates new shaped trough stream
var ShapeStream = function (byteRate, chunkRate, lowWatermark, highWatermark) {
    this.rate = byteRate; // float number!
    if (!chunkRate)
        chunkRate = 10;
    if (!lowWatermark)
        lowWatermark = 0;
    if (!highWatermark)
        highWatermark = 0;

    this.lowWatermark = lowWatermark;
    this.highWatermark = highWatermark;
    this.checkInterval = 1000/chunkRate;
    this.buffer = buffers();
    this.startTime = Date.now();
    this.totalWritten = 0;
    this.writable = true;
    this.readable = true;
    this.sendTimer = null;
}
util.inherits(ShapeStream, stream.Stream);

ShapeStream.prototype.expectedWritten = function() {
    return parseInt(this.rate*(Date.now() - this.startTime)/1000);
}

ShapeStream.prototype.processBuffer = function() {
    var expected = this.expectedWritten();
    if (expected > this.totalWritten) {
        var lengthToWrite = expected - this.totalWritten;
        var chunk = this.buffer.splice(0, lengthToWrite);
        this.doWrite(chunk.toBuffer());
    }
    if (this.buffer.length <= this.lowWatermark && !this.stopping)
         this.emit('drain');

    if (this.buffer.length == 0) {
        this.sendTimer = null;
        if (this.stopping)
            this.emit('close');
    } else
        this.sendTimer = setTimeout(this.processBuffer.bind(this), this.checkInterval);
}

ShapeStream.prototype.doWrite = function(chunk) {
    this.totalWritten += chunk.length;
    this.emit('data', chunk);
};

ShapeStream.prototype.write = function(chunk, encoding) {
    if (typeof chunk === 'string')
        chunk = Buffer(chunk, encoding);
    var expected = this.expectedWritten();
    if (this.totalWritten + chunk.length < this.expectedWritten() && !this.paused)
    {
        this.doWrite(chunk);
        return true;
    }
    this.buffer.push(chunk);
    if (!this.paused && !this.sendTimer) // don't process buffer if it is already scheduled
        this.processBuffer();

    return this.buffer.length < this.highWatermark;
};

ShapeStream.prototype.end = function(chunk, encoding) {
    this.stopping = true;
    if (chunk)
        this.write(chunk, encoding);
    else
        this.processBuffer();
};

ShapeStream.prototype.pause = function() {
    this.pauseCount++;
    this.paused = true;
};

ShapeStream.prototype.resume = function() {
    this.pauseCount--;
    if (this.pauseCount == 0) {
        this.paused = false;
        this.processBuffer();
    }
};

ShapeStream.prototype.destroy = function() {
    // do nothing
}

ShapeStream.prototype.destroySoon = function() {
    // do nothing
}

module.exports = function(byteRate, chunkRate) {
   return new ShapeStream(byteRate, chunkRate);
}
<|endoftext|>


<commit_before><commit_msg>[fix] push notifications: fcm cron auto-snooze for 15 min, instead of deleting.<commit_after><|endoftext|>


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

const leagueBA = 0.255 + 0.11;

var content = fs.readFileSync("2016-standard-batting.json");
var batting_stats = JSON.parse(content);

var playerObj = _.find(batting_stats, { 'Name': "Cal Ripkin"});

//console.log(playerObj['2B']);
//console.log(somAst(playerObj));

var player = playerObj;

var testNumb = somW(player) + somHBP(player) + somH(player) + (somD(player)/20) + (somT(player)/20) + (somHR(player)/20) + somK(player) + somGBA(player) + somGBB(player);
console.log("\n" + player.Name, "\n===========================\n",
	"walk chances: " + somW(player) + "\n\n",
	"hit by pitch chances: " + somHBP(player) + "\n\n",
	"hit chances: " + somH(player) + "\n\n",
	"double chances: " + (somD(player)/20) + " | subchances: " + somD(player) + "\n\n",
	"triple chances: " + (somT(player)/20) + " | subchances: " + somT(player) + "\n\n",
	"home run chances: " + (somHR(player)/20) + " | subchances: " + somHR(player) + "\n\n",
	"strikeout chances: " + somK(player) + "\n\n",
	"ground ball A chances: " + somGBA(player) + "\n\n",
	"ground ball B chances: " + somGBB(player) + "\n\n"
	);
console.log(testNumb);

//som's own plate appearance number, testing only
function somPA(player) {
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	return ( AB + ( W - IW ) + HBP );
}

//batter's walk. returns chances
function somW(player) {
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var AB = _.toFinite(player.AB);
	var HBP = _.toFinite(player.HBP);

	var walk = (((W - IW) * 216) / (AB + ( W - IW) + HBP)) - 9;

	return walk;
}

//batter's hit by pitch. returns chances
function somHBP(player) {
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var AB = _.toFinite(player.AB);
	var HBP = _.toFinite(player.HBP);

	var hit_by_pitch = ((HBP * 216) / (AB + (W - IW) + HBP));

	return hit_by_pitch;
}

//batter's hit. returns chances
function somH(player) {

	var W = somW(player);
	var HBP = somHBP(player);
	var BA = _.toFinite(player.BA);

	var hit = (( BA - leagueBA ) + BA ) * ( 108 - ( W + HBP ));

	return hit;
}

//batter's double. returns subchances
function somD(player) {
	var second_bases = _.toFinite(player['2B']);
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	var doubles = ( 4320 * second_bases ) / ( AB + ( W - IW ) + HBP ) - 90;

	if (doubles < 0) {
		doubles = 0;
	}

	return doubles;
}

//batter's triple. returns subchances
function somT(player) {
	var third_bases = _.toFinite(player['3B']);
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	var triples = ( 4320 * third_bases ) / ( AB + ( W - IW ) + HBP ) - 15;

	if (triples < 0) {
		triples = 0;
	}

	return triples;
}

//batter's home run
function somHR(player) {
	var HR = _.toFinite(player.HR);
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	var home_runs = ( 4320 * HR ) / ( AB + ( W - IW ) + HBP ) - 50;

	if (home_runs < 0) {
		home_runs = 0;
	}

	return home_runs;
}

//batter's strike out. returns chances
function somK(player) {
	var K = _.toFinite(player.SO);
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	var strike_out = (( K * 216 ) / ( AB + ( W - IW ) + HBP )) - 17;

	//can't have negative chances on a card.
	if (strike_out < 0) {
		strike_out = 0;
	}

	return strike_out;
}

//batter's ground ball A. returns chances
function somGBA(player) {
	var DP = _.toFinite(player.GDP);
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	var ground_ball_A = ( 1140 * DP ) / ( AB + ( W - IW ) + HBP );

	return ground_ball_A;
}

//batter's ground ball B. returns chances.
function somGBB(player) {
	var GBA = somGBA(player);

	var ground_ball_B = 31 - GBA;

	if (ground_ball_B < 0) {
		ground_ball_B = 0;
	}

	return ground_ball_B;
}

//runner's first stolen base. returns upper value of a d20 roll
function som1SB(player) {
	var SB = _.toFinite(player.SB);
	var CS = _.toFinite(player.CS);

	if (SB == 0 && CS == 0) {
		var first_stolen_base = 0.13 * 20;
	} else {
		var first_stolen_base = (( SB / ( SB + CS )) + 0.13 ) * 20;
	}

	if (first_stolen_base > 20) {
		first_stolen_base = 19;
	}

	first_stolen_base = _.round(first_stolen_base);

	//returns the ceiling of a 1d20 roll. e.g. 15 is a 1-15 success
	return first_stolen_base;
}

//runner's second stolen base. returns upper value of a d20 roll
function som2SB(player) {
	var SB1 = som1SB(player);

	var second_stolen_base = (SB1 - ( SB1 / 3 )) + 1;

	second_stolen_base = _.round(second_stolen_base);

	return second_stolen_base;
}

//runner's stolen base lead
function somSBLead(player) {
	var SB = _.toFinite(player.SB);
	var CS = _.toFinite(player.CS);
	var H = _.toFinite(player.H);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);
	var second_bases = _.toFinite(player['2B']);
	var third_bases = _.toFinite(player['3B']);
	var HR = _.toFinite(player.HR);

	var lead_chances = (36 * ( SB + CS )) / ((( H + ( W - IW ) + HBP ) * .85 ) - ( second_bases + third_bases + HR ));

	return lead_chances;
}

//runner's asterisk. returns boolean
function somAst(player) {
	var SB1 = som1SB(player);
	var SBLead = somSBLead(player);

	if ((SB1 + SBLead) > 24) {
		//console.log(SB1 + SBLead);
		return true;
	} else {
		//console.log(SB1 + SBLead);
		return false;
	}
}

<commit_msg>use correct league batting average<commit_after>var fs = require("fs");
var _ = require('lodash');

//the league's average calculated each year.
//The ".011" added reflects the frequency that Groundball A++ will also become hits.
//2016 stats
const NLBA = 0.254 + 0.011;
const ALBA = 0.257 + 0.011;
const MLBBA = 0.255 + 0.011; // just use this for now
const testBA = 0.265 + 0.011; // for Cal Ripkin testing only

var content = fs.readFileSync("2016-standard-batting.json");
var batting_stats = JSON.parse(content);

var player_stats = _.find(batting_stats, { 'Name': "Mike Trout"});

//console.log(playerObj['2B']);
//console.log(somAst(playerObj));

var player = player_stats;

//format a stat block in the console
var testNumb = somW(player) + somHBP(player) + somH(player) + (somD(player)/20) + (somT(player)/20) + (somHR(player)/20) + somK(player) + somGBA(player) + somGBB(player);
console.log("\n" + player.Name, "\n===========================\n",
	"walk chances: " + somW(player) + "\n\n",
	"hit by pitch chances: " + somHBP(player) + "\n\n",
	"hit chances: " + somH(player) + "\n\n",
	"double chances: " + (somD(player)/20) + " | subchances: " + somD(player) + "\n\n",
	"triple chances: " + (somT(player)/20) + " | subchances: " + somT(player) + "\n\n",
	"home run chances: " + (somHR(player)/20) + " | subchances: " + somHR(player) + "\n\n",
	"strikeout chances: " + somK(player) + "\n\n",
	"ground ball A chances: " + somGBA(player) + "\n\n",
	"ground ball B chances: " + somGBB(player) + "\n\n"
	);
console.log(testNumb);

//som's own "plate appearance" number, testing only, not for use
function somPA(player) {
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	return ( AB + ( W - IW ) + HBP );
}

//batter's walk. returns chances
function somW(player) {
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var AB = _.toFinite(player.AB);
	var HBP = _.toFinite(player.HBP);

	var walk = (((W - IW) * 216) / (AB + ( W - IW) + HBP)) - 9;

	return walk;
}

//batter's hit by pitch. returns chances
function somHBP(player) {
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var AB = _.toFinite(player.AB);
	var HBP = _.toFinite(player.HBP);

	var hit_by_pitch = ((HBP * 216) / (AB + (W - IW) + HBP));

	return hit_by_pitch;
}

//batter's hit. returns chances
function somH(player) {
	var W = somW(player);
	var HBP = somHBP(player);
	var BA = _.toFinite(player.BA);
	var LG = player.Lg;
	var leagueBA = MLBBA;

	//find the right batting average
	if (LG == "NL") {
		leagueBA = NLBA;
	} else if (LG == "AL") {
		leagueBA = ALBA;
	}

	console.log("battin avg. ", LG, leagueBA);

	var hit = (( BA - leagueBA ) + BA ) * ( 108 - ( W + HBP ));

	return hit;
}

//batter's double. returns subchances
function somD(player) {
	var second_bases = _.toFinite(player['2B']);
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	var doubles = ( 4320 * second_bases ) / ( AB + ( W - IW ) + HBP ) - 90;

	//can't have negative chances on a card.
	if (doubles < 0) {
		doubles = 0;
	}

	return doubles;
}

//batter's triple. returns subchances
function somT(player) {
	var third_bases = _.toFinite(player['3B']);
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	var triples = ( 4320 * third_bases ) / ( AB + ( W - IW ) + HBP ) - 15;

	//can't have negative chances on a card.
	if (triples < 0) {
		triples = 0;
	}

	return triples;
}

//batter's home run. returns subchances
function somHR(player) {
	var HR = _.toFinite(player.HR);
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	var home_runs = ( 4320 * HR ) / ( AB + ( W - IW ) + HBP ) - 50;

	//can't have negative chances on a card.
	if (home_runs < 0) {
		home_runs = 0;
	}

	return home_runs;
}

//batter's strike out. returns chances
function somK(player) {
	var K = _.toFinite(player.SO);
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	var strike_out = (( K * 216 ) / ( AB + ( W - IW ) + HBP )) - 17;

	//can't have negative chances on a card.
	if (strike_out < 0) {
		strike_out = 0;
	}

	return strike_out;
}

//batter's ground ball A. returns chances
function somGBA(player) {
	var DP = _.toFinite(player.GDP);
	var AB = _.toFinite(player.AB);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);

	var ground_ball_A = ( 1140 * DP ) / ( AB + ( W - IW ) + HBP );

	return ground_ball_A;
}

//batter's ground ball B. returns chances.
function somGBB(player) {
	var GBA = somGBA(player);

	var ground_ball_B = 31 - GBA;

	if (ground_ball_B < 0) {
		ground_ball_B = 0;
	}

	return ground_ball_B;
}

//runner's first stolen base. returns upper value of a d20 roll
function som1SB(player) {
	var SB = _.toFinite(player.SB);
	var CS = _.toFinite(player.CS);

	if (SB == 0 && CS == 0) {
		var first_stolen_base = 0.13 * 20;
	} else {
		var first_stolen_base = (( SB / ( SB + CS )) + 0.13 ) * 20;
	}

	//always room for error. 5% in fact
	if (first_stolen_base > 20) {
		first_stolen_base = 19;
	}

	first_stolen_base = _.round(first_stolen_base);

	//returns the ceiling of a 1d20 roll. e.g. 15 is a 1-15 success
	return first_stolen_base;
}

//runner's second stolen base. returns upper value of a d20 roll
function som2SB(player) {
	var SB1 = som1SB(player);

	var second_stolen_base = (SB1 - ( SB1 / 3 )) + 1;

	second_stolen_base = _.round(second_stolen_base);

	return second_stolen_base;
}

//runner's stolen base lead
function somSBLead(player) {
	var SB = _.toFinite(player.SB);
	var CS = _.toFinite(player.CS);
	var H = _.toFinite(player.H);
	var W = _.toFinite(player.BB);
	var IW = _.toFinite(player.IBB);
	var HBP = _.toFinite(player.HBP);
	var second_bases = _.toFinite(player['2B']);
	var third_bases = _.toFinite(player['3B']);
	var HR = _.toFinite(player.HR);

	var lead_chances = (36 * ( SB + CS )) / ((( H + ( W - IW ) + HBP ) * .85 ) - ( second_bases + third_bases + HR ));

	return lead_chances;
}

//runner's asterisk. returns boolean
function somAst(player) {
	var SB1 = som1SB(player);
	var SBLead = somSBLead(player);

	if ((SB1 + SBLead) > 24) {
		//console.log(SB1 + SBLead);
		return true;
	} else {
		//console.log(SB1 + SBLead);
		return false;
	}
}

<|endoftext|>