<commit_before>#!/usr/bin/env node
;(function() {
  'use strict';

  /** The Node filesystem module */
  var fs = require('fs');

  /** Used to minify variables embedded in compiled strings */
  var compiledVars = [
    'callback',
    'collection',
    'concat',
    'ctor',
    'hasOwnProperty',
    'identity',
    'index',
    'iteratee',
    'iteratorBind',
    'length',
    'nativeKeys',
    'object',
    'ownIndex',
    'ownProps',
    'prop',
    'propertyIsEnumerable',
    'propIndex',
    'props',
    'result',
    'skipProto',
    'slice',
    'stringClass',
    'thisArg',
    'toString',
    'value',

    // lesser used variables
    'accumulator',
    'args',
    'argsIndex',
    'argsLength',
    'arrayLikeClasses',
    'ArrayProto',
    'bind',
    'callee',
    'className',
    'compareAscending',
    'destValue',
    'forIn',
    'found',
    'funcs',
    'indexOf',
    'indicator',
    'isArguments',
    'isArr',
    'isArray',
    'isFunc',
    'isFunction',
    'isPlainObject',
    'methodName',
    'noaccum',
    'objectClass',
    'objectTypes',
    'pass',
    'properties',
    'property',
    'propsLength',
    'recursive',
    'source',
    'stack',
    'stackLength',
    'target',
    'valueProp'
  ];

  /** Used to minify `compileIterator` option properties */
  var iteratorOptions = [
    'args',
    'array',
    'arrayBranch',
    'beforeLoop',
    'bottom',
    'exit',
    'firstArg',
    'hasDontEnumBug',
    'inLoop',
    'init',
    'isKeysFast',
    'object',
    'objectBranch',
    'noArgsEnum',
    'noCharByIndex',
    'shadowed',
    'top',
    'useHas',
    'useStrict'
  ];

  /** Used to minify variables and string values to a single character */
  var minNames = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
  minNames.push.apply(minNames, minNames.map(function(value) {
    return value + value;
  }));

  /** Used to protect the specified properties from getting minified */
  var propWhitelist = [
    '_',
    '_chain',
    '_wrapped',
    'after',
    'all',
    'amd',
    'any',
    'attachEvent',
    'bind',
    'bindAll',
    'chain',
    'clearTimeout',
    'clone',
    'collect',
    'compact',
    'compose',
    'contains',
    'countBy',
    'criteria',
    'debounce',
    'defaults',
    'defer',
    'delay',
    'detect',
    'difference',
    'drop',
    'each',
    'environment',
    'escape',
    'escape',
    'evaluate',
    'every',
    'extend',
    'filter',
    'find',
    'first',
    'flatten',
    'foldl',
    'foldr',
    'forEach',
    'forIn',
    'forOwn',
    'functions',
    'groupBy',
    'has',
    'head',
    'identity',
    'include',
    'index',
    'indexOf',
    'initial',
    'inject',
    'interpolate',
    'intersection',
    'invoke',
    'isArguments',
    'isArray',
    'isBoolean',
    'isDate',
    'isElement',
    'isEmpty',
    'isEqual',
    'isEqual',
    'isFinite',
    'isFinite',
    'isFunction',
    'isNaN',
    'isNull',
    'isNumber',
    'isObject',
    'isRegExp',
    'isString',
    'isUndefined',
    'keys',
    'last',
    'lastIndexOf',
    'map',
    'max',
    'memoize',
    'merge',
    'methods',
    'min',
    'mixin',
    'noConflict',
    'omit',
    'once',
    'opera',
    'partial',
    'pick',
    'pluck',
    'range',
    'reduce',
    'reduceRight',
    'reject',
    'rest',
    'result',
    'select',
    'setTimeout',
    'shuffle',
    'size',
    'some',
    'sortBy',
    'sortedIndex',
    'source',
    'tail',
    'take',
    'tap',
    'template',
    'templateSettings',
    'throttle',
    'times',
    'toArray',
    'union',
    'uniq',
    'unique',
    'uniqueId',
    'value',
    'values',
    'variable',
    'VERSION',
    'where',
    'without',
    'wrap',
    'zip',
    'zipObject'
  ];

  /*--------------------------------------------------------------------------*/

  /**
   * Pre-process a given Lo-Dash `source`, preparing it for minification.
   *
   * @param {String} source The source to process.
   * @returns {String} Returns the processed source.
   */
  function preprocess(source) {
    // remove copyright to add later in post-compile.js
    source = source.replace(/\/\*![\s\S]+?\*\//, '');

    // remove unrecognized JSDoc tags so Closure Compiler won't complain
    source = source.replace(/@(?:alias|category)\b.*/g, '');

    // manually convert `arrayLikeClasses` property assignments because
    // Closure Compiler errors trying to minify them
    source = source.replace(/(arrayLikeClasses =)[\s\S]+?= *true/,
      "$1{'[object Arguments]': true, '[object Array]': true, '[object Boolean]': false, " +
      "'[object Date]': false, '[object Function]': false, '[object Number]': false, " +
      "'[object Object]': false, '[object RegExp]': false, '[object String]': true }"
    );

    // manually convert `cloneableClasses` property assignments because
    // Closure Compiler errors trying to minify them
    source = source.replace(/(cloneableClasses =)[\s\S]+?= *true/,
      "$1{'[object Arguments]': false, '[object Array]': true, '[object Boolean]': true, " +
      "'[object Date]': true, '[object Function]': false, '[object Number]': true, " +
      "'[object Object]': true, '[object RegExp]': true, '[object String]': true }"
    );

    // add brackets to whitelisted properties so Closure Compiler won't mung them
    // http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
    source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']");

    // remove brackets from `_.escape()` in `_.template`
    source = source.replace(/__e *= *_\['escape']/g, '__e=_.escape');

    // remove brackets from `collection.indexOf` in `_.contains`
    source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)');

    // remove brackets from `result[length].value` in `_.sortBy`
    source = source.replace("result[length]['value']", 'result[length].value');

    // remove whitespace from string literals
    source = source.replace(/'(?:(?=(\\?))\1.)*?'/g, function(string) {
      // avoids removing the '\n' of the `stringEscapes` object
      return string.replace(/\[object |else if|function | in |return\s+[\w']|throw |typeof |use strict|var |@ |'\\n'|\\\\n|\\n|\s+/g, function(match) {
        return match == false || match == '\\n' ? '' : match;
      });
    });

    // remove whitespace from `_.template` related regexes
    source = source.replace(/(?:reDelimiterCode\w+|reEmptyString\w+|reInsertVariable) *=.+/g, function(match) {
      return match.replace(/ |\\n/g, '');
    });

    // remove newline from double-quoted strings in `_.template`
    source = source
      .replace('"\';\\n__with ("', '"\';__with("')
      .replace('"\\n}__\\n__p += \'"', '"}____p+=\'"')
      .replace('"__p = \'"', '"__p=\'"')
      .replace('"\';\\n"', '"\';"')
      .replace("') {\\n'", "'){'")

    // remove `useSourceURL` variable
    source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *try *\{(?:\s*\/\/.*)*\n *var useSourceURL[\s\S]+?catch[^}]+}\n/, '');

    // remove debug sourceURL use in `_.template`
    source = source.replace(/(?:\s*\/\/.*\n)* *if *\(useSourceURL[^}]+}/, '');

    // minify internal properties used by 'compareAscending', `_.clone`, `_.merge`, and `_.sortBy`
    (function() {
      var properties = ['criteria', 'index', 'source', 'value'],
          snippets = source.match(/( +)(?:function clone|function compareAscending|var merge|var sortBy)\b[\s\S]+?\n\1}/g);

      if (!snippets) {
        return;
      }
      snippets.forEach(function(snippet) {
        var modified = snippet,
            isCompilable = /(?:var merge|var sortBy)\b/.test(modified),
            isInlined = !/\bcreateIterator\b/.test(modified);

        // minify properties
        properties.forEach(function(property, index) {
          var reBracketProp = RegExp("\\['(" + property + ")'\\]", 'g'),
              reDotProp = RegExp('\\.' + property + '\\b', 'g'),
              rePropColon = RegExp("(')?\\b" + property + "\\1 *:", 'g');

          if (isCompilable) {
            // add quotes around properties in the inlined `_.merge` and `_.sortBy`
            // of the mobile build so Closure Compiler won't mung them
            if (isInlined) {
              modified = modified
                .replace(reBracketProp, "['" + minNames[index] + "']")
                .replace(reDotProp, "['" + minNames[index] + "']")
                .replace(rePropColon, "'" + minNames[index] + "':");
            }
            else {
              modified = modified
                .replace(reBracketProp, '.' + minNames[index])
                .replace(reDotProp, '.' + minNames[index])
                .replace(rePropColon, minNames[index] + ':');
            }
          }
          else {
            modified = modified
              .replace(reBracketProp, "['" + minNames[index] + "']")
              .replace(reDotProp, '.' + minNames[index])
              .replace(rePropColon, "'" + minNames[index] + "':")

            // correct `value.source` in regexp branch of `_.clone`
            if (property == 'source') {
              modified = modified.replace("value['" + minNames[index] + "']", "value['source']");
            }
          }
        });

        // replace with modified snippet
        source = source.replace(snippet, modified);
      });
    }());

    // minify all compilable snippets
    var snippets = source.match(
      RegExp([
        // match the `iteratorTemplate`
        '( +)var iteratorTemplate\\b[\\s\\S]+?\\n\\1}',
        // match methods created by `createIterator` calls
        'createIterator\\((?:{|[a-zA-Z]+)[\\s\\S]+?\\);\\n',
        // match variables storing `createIterator` options
        '( +)var [a-zA-Z]+IteratorOptions\\b[\\s\\S]+?\\n\\2}',
        // match the the `createIterator` function
        '( +)function createIterator\\b[\\s\\S]+?\\n\\3}'
      ].join('|'), 'g')
    );

    // exit early if no compilable snippets
    if (!snippets) {
      return source;
    }

    snippets.forEach(function(snippet, index) {
      var isCreateIterator = /function createIterator\b/.test(snippet),
          isIteratorTemplate = /var iteratorTemplate\b/.test(snippet),
          modified = snippet;

      // add brackets to whitelisted properties so Closure Compiler won't mung them
      modified = modified.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), "['$1']");

      if (isCreateIterator) {
        // replace with modified snippet early and clip snippet to the `factory`
        // call so other arguments aren't minified
        source = source.replace(snippet, modified);
        snippet = modified = modified.replace(/factory\([\s\S]+$/, '');
      }

      // minify snippet variables / arguments
      compiledVars.forEach(function(variable, index) {
        // ensure properties in compiled strings aren't minified
        modified = modified.replace(RegExp('([^.]\\b)' + variable + '\\b(?!\' *[\\]:])', 'g'), '$1' + minNames[index]);

        // correct `typeof x == 'object'`
        if (variable == 'object') {
          modified = modified.replace(RegExp("(typeof [^']+')" + minNames[index] + "'", 'g'), "$1object'");
        }
      });

      // minify `createIterator` option property names
      iteratorOptions.forEach(function(property, index) {
        if (isIteratorTemplate) {
          // minify property names as interpolated template variables
          modified = modified.replace(RegExp('\\b' + property + '\\b', 'g'), minNames[index]);
        }
        else {
          if (property == 'array' || property == 'object') {
            // minify "array" and "object" sub property names
            modified = modified.replace(RegExp("'" + property + "'( *[\\]:])", 'g'), "'" + minNames[index] + "'$1");
          }
          else {
            // minify property name strings
            modified = modified.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
            // minify property names in regexes and accessors
            if (isCreateIterator) {
              modified = modified.replace(RegExp('([\\.|/])' + property + '\\b' , 'g'), '$1' + minNames[index]);
            }
          }
        }
      });

      // replace with modified snippet
      source = source.replace(snippet, modified);
    });

    return source;
  }

  /*--------------------------------------------------------------------------*/

  // expose `preprocess`
  if (module != require.main) {
    module.exports = preprocess;
  }
  else {
    // read the Lo-Dash source file from the first argument if the script
    // was invoked directly (e.g. `node pre-compile.js source.js`) and write to
    // the same file
    (function() {
      var source = fs.readFileSync(process.argv[2], 'utf8');
      fs.writeFileSync(process.argv[2], preprocess(source), 'utf8');
    }());
  }
}());
<commit_msg>Update whitespace removal for `delete` operators in pre-compile.js.<commit_after>#!/usr/bin/env node
;(function() {
  'use strict';

  /** The Node filesystem module */
  var fs = require('fs');

  /** Used to minify variables embedded in compiled strings */
  var compiledVars = [
    'callback',
    'collection',
    'concat',
    'ctor',
    'hasOwnProperty',
    'identity',
    'index',
    'iteratee',
    'iteratorBind',
    'length',
    'nativeKeys',
    'object',
    'ownIndex',
    'ownProps',
    'prop',
    'propertyIsEnumerable',
    'propIndex',
    'props',
    'result',
    'skipProto',
    'slice',
    'stringClass',
    'thisArg',
    'toString',
    'value',

    // lesser used variables
    'accumulator',
    'args',
    'argsIndex',
    'argsLength',
    'arrayLikeClasses',
    'ArrayProto',
    'bind',
    'callee',
    'className',
    'compareAscending',
    'destValue',
    'forIn',
    'found',
    'funcs',
    'indexOf',
    'indicator',
    'isArguments',
    'isArr',
    'isArray',
    'isFunc',
    'isFunction',
    'isPlainObject',
    'methodName',
    'noaccum',
    'objectClass',
    'objectTypes',
    'pass',
    'properties',
    'property',
    'propsLength',
    'recursive',
    'source',
    'stack',
    'stackLength',
    'target',
    'valueProp'
  ];

  /** Used to minify `compileIterator` option properties */
  var iteratorOptions = [
    'args',
    'array',
    'arrayBranch',
    'beforeLoop',
    'bottom',
    'exit',
    'firstArg',
    'hasDontEnumBug',
    'inLoop',
    'init',
    'isKeysFast',
    'object',
    'objectBranch',
    'noArgsEnum',
    'noCharByIndex',
    'shadowed',
    'top',
    'useHas',
    'useStrict'
  ];

  /** Used to minify variables and string values to a single character */
  var minNames = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
  minNames.push.apply(minNames, minNames.map(function(value) {
    return value + value;
  }));

  /** Used to protect the specified properties from getting minified */
  var propWhitelist = [
    '_',
    '_chain',
    '_wrapped',
    'after',
    'all',
    'amd',
    'any',
    'attachEvent',
    'bind',
    'bindAll',
    'chain',
    'clearTimeout',
    'clone',
    'collect',
    'compact',
    'compose',
    'contains',
    'countBy',
    'criteria',
    'debounce',
    'defaults',
    'defer',
    'delay',
    'detect',
    'difference',
    'drop',
    'each',
    'environment',
    'escape',
    'escape',
    'evaluate',
    'every',
    'extend',
    'filter',
    'find',
    'first',
    'flatten',
    'foldl',
    'foldr',
    'forEach',
    'forIn',
    'forOwn',
    'functions',
    'groupBy',
    'has',
    'head',
    'identity',
    'include',
    'index',
    'indexOf',
    'initial',
    'inject',
    'interpolate',
    'intersection',
    'invoke',
    'isArguments',
    'isArray',
    'isBoolean',
    'isDate',
    'isElement',
    'isEmpty',
    'isEqual',
    'isEqual',
    'isFinite',
    'isFinite',
    'isFunction',
    'isNaN',
    'isNull',
    'isNumber',
    'isObject',
    'isRegExp',
    'isString',
    'isUndefined',
    'keys',
    'last',
    'lastIndexOf',
    'map',
    'max',
    'memoize',
    'merge',
    'methods',
    'min',
    'mixin',
    'noConflict',
    'omit',
    'once',
    'opera',
    'partial',
    'pick',
    'pluck',
    'range',
    'reduce',
    'reduceRight',
    'reject',
    'rest',
    'result',
    'select',
    'setTimeout',
    'shuffle',
    'size',
    'some',
    'sortBy',
    'sortedIndex',
    'source',
    'tail',
    'take',
    'tap',
    'template',
    'templateSettings',
    'throttle',
    'times',
    'toArray',
    'union',
    'uniq',
    'unique',
    'uniqueId',
    'value',
    'values',
    'variable',
    'VERSION',
    'where',
    'without',
    'wrap',
    'zip',
    'zipObject'
  ];

  /*--------------------------------------------------------------------------*/

  /**
   * Pre-process a given Lo-Dash `source`, preparing it for minification.
   *
   * @param {String} source The source to process.
   * @returns {String} Returns the processed source.
   */
  function preprocess(source) {
    // remove copyright to add later in post-compile.js
    source = source.replace(/\/\*![\s\S]+?\*\//, '');

    // remove unrecognized JSDoc tags so Closure Compiler won't complain
    source = source.replace(/@(?:alias|category)\b.*/g, '');

    // manually convert `arrayLikeClasses` property assignments because
    // Closure Compiler errors trying to minify them
    source = source.replace(/(arrayLikeClasses =)[\s\S]+?= *true/,
      "$1{'[object Arguments]': true, '[object Array]': true, '[object Boolean]': false, " +
      "'[object Date]': false, '[object Function]': false, '[object Number]': false, " +
      "'[object Object]': false, '[object RegExp]': false, '[object String]': true }"
    );

    // manually convert `cloneableClasses` property assignments because
    // Closure Compiler errors trying to minify them
    source = source.replace(/(cloneableClasses =)[\s\S]+?= *true/,
      "$1{'[object Arguments]': false, '[object Array]': true, '[object Boolean]': true, " +
      "'[object Date]': true, '[object Function]': false, '[object Number]': true, " +
      "'[object Object]': true, '[object RegExp]': true, '[object String]': true }"
    );

    // add brackets to whitelisted properties so Closure Compiler won't mung them
    // http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
    source = source.replace(RegExp('\\.(' + propWhitelist.join('|') + ')\\b', 'g'), "['$1']");

    // remove brackets from `_.escape()` in `_.template`
    source = source.replace(/__e *= *_\['escape']/g, '__e=_.escape');

    // remove brackets from `collection.indexOf` in `_.contains`
    source = source.replace("collection['indexOf'](target)", 'collection.indexOf(target)');

    // remove brackets from `result[length].value` in `_.sortBy`
    source = source.replace("result[length]['value']", 'result[length].value');

    // remove whitespace from string literals
    source = source.replace(/'(?:(?=(\\?))\1.)*?'/g, function(string) {
      // avoids removing the '\n' of the `stringEscapes` object
      return string.replace(/\[object |delete |else if|function | in |return\s+[\w']|throw |typeof |use strict|var |@ |'\\n'|\\\\n|\\n|\s+/g, function(match) {
        return match == false || match == '\\n' ? '' : match;
      });
    });

    // remove whitespace from `_.template` related regexes
    source = source.replace(/(?:reDelimiterCode\w+|reEmptyString\w+|reInsertVariable) *=.+/g, function(match) {
      return match.replace(/ |\\n/g, '');
    });

    // remove newline from double-quoted strings in `_.template`
    source = source
      .replace('"\';\\n__with ("', '"\';__with("')
      .replace('"\\n}__\\n__p += \'"', '"}____p+=\'"')
      .replace('"__p = \'"', '"__p=\'"')
      .replace('"\';\\n"', '"\';"')
      .replace("') {\\n'", "'){'")

    // remove `useSourceURL` variable
    source = source.replace(/(?:\n +\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/)?\n *try *\{(?:\s*\/\/.*)*\n *var useSourceURL[\s\S]+?catch[^}]+}\n/, '');

    // remove debug sourceURL use in `_.template`
    source = source.replace(/(?:\s*\/\/.*\n)* *if *\(useSourceURL[^}]+}/, '');

    // minify internal properties used by 'compareAscending', `_.clone`, `_.merge`, and `_.sortBy`
    (function() {
      var properties = ['criteria', 'index', 'source', 'value'],
          snippets = source.match(/( +)(?:function clone|function compareAscending|var merge|var sortBy)\b[\s\S]+?\n\1}/g);

      if (!snippets) {
        return;
      }
      snippets.forEach(function(snippet) {
        var modified = snippet,
            isCompilable = /(?:var merge|var sortBy)\b/.test(modified),
            isInlined = !/\bcreateIterator\b/.test(modified);

        // minify properties
        properties.forEach(function(property, index) {
          var reBracketProp = RegExp("\\['(" + property + ")'\\]", 'g'),
              reDotProp = RegExp('\\.' + property + '\\b', 'g'),
              rePropColon = RegExp("(')?\\b" + property + "\\1 *:", 'g');

          if (isCompilable) {
            // add quotes around properties in the inlined `_.merge` and `_.sortBy`
            // of the mobile build so Closure Compiler won't mung them
            if (isInlined) {
              modified = modified
                .replace(reBracketProp, "['" + minNames[index] + "']")
                .replace(reDotProp, "['" + minNames[index] + "']")
                .replace(rePropColon, "'" + minNames[index] + "':");
            }
            else {
              modified = modified
                .replace(reBracketProp, '.' + minNames[index])
                .replace(reDotProp, '.' + minNames[index])
                .replace(rePropColon, minNames[index] + ':');
            }
          }
          else {
            modified = modified
              .replace(reBracketProp, "['" + minNames[index] + "']")
              .replace(reDotProp, '.' + minNames[index])
              .replace(rePropColon, "'" + minNames[index] + "':")

            // correct `value.source` in regexp branch of `_.clone`
            if (property == 'source') {
              modified = modified.replace("value['" + minNames[index] + "']", "value['source']");
            }
          }
        });

        // replace with modified snippet
        source = source.replace(snippet, modified);
      });
    }());

    // minify all compilable snippets
    var snippets = source.match(
      RegExp([
        // match the `iteratorTemplate`
        '( +)var iteratorTemplate\\b[\\s\\S]+?\\n\\1}',
        // match methods created by `createIterator` calls
        'createIterator\\((?:{|[a-zA-Z]+)[\\s\\S]+?\\);\\n',
        // match variables storing `createIterator` options
        '( +)var [a-zA-Z]+IteratorOptions\\b[\\s\\S]+?\\n\\2}',
        // match the the `createIterator` function
        '( +)function createIterator\\b[\\s\\S]+?\\n\\3}'
      ].join('|'), 'g')
    );

    // exit early if no compilable snippets
    if (!snippets) {
      return source;
    }

    snippets.forEach(function(snippet, index) {
      var isCreateIterator = /function createIterator\b/.test(snippet),
          isIteratorTemplate = /var iteratorTemplate\b/.test(snippet),
          modified = snippet;

      // add brackets to whitelisted properties so Closure Compiler won't mung them
      modified = modified.replace(RegExp('\\.(' + iteratorOptions.join('|') + ')\\b', 'g'), "['$1']");

      if (isCreateIterator) {
        // replace with modified snippet early and clip snippet to the `factory`
        // call so other arguments aren't minified
        source = source.replace(snippet, modified);
        snippet = modified = modified.replace(/factory\([\s\S]+$/, '');
      }

      // minify snippet variables / arguments
      compiledVars.forEach(function(variable, index) {
        // ensure properties in compiled strings aren't minified
        modified = modified.replace(RegExp('([^.]\\b)' + variable + '\\b(?!\' *[\\]:])', 'g'), '$1' + minNames[index]);

        // correct `typeof x == 'object'`
        if (variable == 'object') {
          modified = modified.replace(RegExp("(typeof [^']+')" + minNames[index] + "'", 'g'), "$1object'");
        }
      });

      // minify `createIterator` option property names
      iteratorOptions.forEach(function(property, index) {
        if (isIteratorTemplate) {
          // minify property names as interpolated template variables
          modified = modified.replace(RegExp('\\b' + property + '\\b', 'g'), minNames[index]);
        }
        else {
          if (property == 'array' || property == 'object') {
            // minify "array" and "object" sub property names
            modified = modified.replace(RegExp("'" + property + "'( *[\\]:])", 'g'), "'" + minNames[index] + "'$1");
          }
          else {
            // minify property name strings
            modified = modified.replace(RegExp("'" + property + "'", 'g'), "'" + minNames[index] + "'");
            // minify property names in regexes and accessors
            if (isCreateIterator) {
              modified = modified.replace(RegExp('([\\.|/])' + property + '\\b' , 'g'), '$1' + minNames[index]);
            }
          }
        }
      });

      // replace with modified snippet
      source = source.replace(snippet, modified);
    });

    return source;
  }

  /*--------------------------------------------------------------------------*/

  // expose `preprocess`
  if (module != require.main) {
    module.exports = preprocess;
  }
  else {
    // read the Lo-Dash source file from the first argument if the script
    // was invoked directly (e.g. `node pre-compile.js source.js`) and write to
    // the same file
    (function() {
      var source = fs.readFileSync(process.argv[2], 'utf8');
      fs.writeFileSync(process.argv[2], preprocess(source), 'utf8');
    }());
  }
}());
<|endoftext|>


<commit_before>function StocksCtrl($scope, Stock){
	Stock.all()
	.success(function(data) {
		$scope.monday = data.ereports[0];
		$scope.tuesday = data.ereports[1];
		$scope.wednesday = data.ereports[2];
		$scope.thursday = data.ereports[3];
		$scope.friday = data.ereports[4];
	})
	$scope.order = function(predicate) {
    $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
    $scope.predicate = predicate;
  };
}

angular.module('earnings')
.controller('StocksCtrl', StocksCtrl);<commit_msg>angular minification issue<commit_after>var StocksCtrl =['$scope','Stock', function($scope, Stock){
	Stock.all()
	.success(function(data) {
		$scope.monday = data.ereports[0];
		$scope.tuesday = data.ereports[1];
		$scope.wednesday = data.ereports[2];
		$scope.thursday = data.ereports[3];
		$scope.friday = data.ereports[4];
	})
	$scope.order = function(predicate) {
    $scope.reverse = ($scope.predicate === predicate) ? !$scope.reverse : false;
    $scope.predicate = predicate;
  };
}];

angular.module('earnings')
.controller('StocksCtrl', StocksCtrl);<|endoftext|>


<commit_before>angular.module('secondLead')
  .directive('addDrama', [ 'DramaModel', function (DramaModel){
  	return {
  	  restrict: 'E',
  	  templateUrl:'add-drama.html',
  	  scope: {
  	  	drama: "=",
  	  	userLists: "=",
  	  	user: "@",
  	  	selectedList:"@"
  	  },
  	  link: function (scope, element, attrs){
  	  	scope.addToList = function (list, drama){
  	  	  DramaModel.add(scope.user,list,drama);
  	  	  scope.selectedList = "";
  	  	};

  	  }

  	}

  }])
<commit_msg>formatted code style<commit_after>angular.module('secondLead')
  .directive('addDrama', ['DramaModel', function (DramaModel) {
  	return {
  	  restrict: 'E',
  	  templateUrl:'add-drama.html',
  	  scope: {
  	  	drama: "=",
  	  	userLists: "=",
  	  	user: "@",
  	  	selectedList:"@"
  	  },
	  link: function (scope, element, attrs) {
	  	scope.addToList = function (list, drama) {
	  	  DramaModel.add(scope.user, list, drama);
	  	  scope.selectedList = "";
	  	};
	  }
	}
}])<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import qs from 'query-string';
import {toSchoolYear} from '../helpers/schoolYear';
import {apiFetchJson} from '../helpers/apiFetchJson';
import {percentileWithSuffix} from '../helpers/percentiles';
import GenericLoader from '../components/GenericLoader';
import {BLANK, PRESENT} from './colors';
import BoxChart from './BoxChart';

export default class CohortChart extends React.Component {
  constructor(props) {
    super(props);

    this.fetchJson = this.fetchJson.bind(this);
    this.renderBoxChartFromJson = this.renderBoxChartFromJson.bind(this);
  }

  fetchJson() {
    const {nowFn} = this.context;
    const {studentId, benchmarkAssessmentKey} = this.props;
    const schoolYearNow = toSchoolYear(nowFn());
    const queryString = qs.stringify({
      benchmark_assessment_key: benchmarkAssessmentKey,
      school_years: [schoolYearNow - 1, schoolYearNow]
    }, {arrayFormat: 'bracket'});
    const url = `/api/students/${studentId}/reader_profile_cohort_json?${queryString}`;
    return apiFetchJson(url);
  }

  render() {
    return (

        <GenericLoader
          promiseFn={this.fetchJson}
          render={this.renderBoxChartFromJson}
        />

    );
  }

  renderBoxChartFromJson(json) {
    const {gradeNow, readerJson, benchmarkAssessmentKey} = this.props;
    return (
      <BoxChart
        gradeNow={gradeNow}
        readerJson={readerJson}
        benchmarkAssessmentKey={benchmarkAssessmentKey}
        renderRaw={true}
        renderCellFn={({schoolYear, benchmarkPeriodKey, boxStyle}) => {
          const whenKey = [schoolYear, benchmarkPeriodKey].join('-');
          const cell = json.cells[whenKey];
          const pText = cell && cell.stats.p ? percentileWithSuffix(cell.stats.p) : null;
          const cellStyle = {
            ...boxStyle,
            outline: `1px solid ${PRESENT}`,
            backgroundColor: BLANK,
            zIndex: pText ? 1 : 0 // for outline overlapping
          };
          return (

              {pText}

          );
        }}
      />
    );
  }
}
CohortChart.contextTypes = {
  nowFn: PropTypes.func.isRequired
};
CohortChart.propTypes = {
  studentId: PropTypes.number.isRequired,
  gradeNow: PropTypes.string.isRequired,
  benchmarkAssessmentKey: PropTypes.string.isRequired,
  readerJson: PropTypes.object.isRequired
};
<commit_msg>Add tooltip with percentile metadata for validating<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import qs from 'query-string';
import {toSchoolYear} from '../helpers/schoolYear';
import {apiFetchJson} from '../helpers/apiFetchJson';
import {percentileWithSuffix} from '../helpers/percentiles';
import GenericLoader from '../components/GenericLoader';
import {BLANK, PRESENT} from './colors';
import BoxChart from './BoxChart';

export default class CohortChart extends React.Component {
  constructor(props) {
    super(props);

    this.fetchJson = this.fetchJson.bind(this);
    this.renderBoxChartFromJson = this.renderBoxChartFromJson.bind(this);
  }

  fetchJson() {
    const {nowFn} = this.context;
    const {studentId, benchmarkAssessmentKey} = this.props;
    const schoolYearNow = toSchoolYear(nowFn());
    const queryString = qs.stringify({
      benchmark_assessment_key: benchmarkAssessmentKey,
      school_years: [schoolYearNow - 1, schoolYearNow]
    }, {arrayFormat: 'bracket'});
    const url = `/api/students/${studentId}/reader_profile_cohort_json?${queryString}`;
    return apiFetchJson(url);
  }

  render() {
    return (

        <GenericLoader
          promiseFn={this.fetchJson}
          render={this.renderBoxChartFromJson}
        />

    );
  }

  renderBoxChartFromJson(json) {
    const {gradeNow, readerJson, benchmarkAssessmentKey} = this.props;
    return (
      <BoxChart
        gradeNow={gradeNow}
        readerJson={readerJson}
        benchmarkAssessmentKey={benchmarkAssessmentKey}
        renderRaw={true}
        renderCellFn={({schoolYear, benchmarkPeriodKey, boxStyle}) => {
          const whenKey = [schoolYear, benchmarkPeriodKey].join('-');
          const cell = json.cells[whenKey];
          const pText = cell && cell.stats.p ? percentileWithSuffix(cell.stats.p) : null;
          const tooltipText = (cell && cell.stats.p) ? [
            `${pText} percentile`,
            '',
            'Within the school, at that grade level:',
            `  ${padStart(cell.stats.n_higher, 3)} students have a higher score`,
            `  ${padStart(cell.stats.n_equal, 3)} students have the same score`,
            `  ${padStart(cell.stats.n_lower, 3)} students have a lower score`
          ].join("\n") : null;
          const cellStyle = {
            ...boxStyle,
            outline: `1px solid ${PRESENT}`,
            backgroundColor: BLANK,
            zIndex: pText ? 1 : 0 // for outline overlapping
          };
          return (

              {pText}

          );
        }}
      />
    );
  }
}
CohortChart.contextTypes = {
  nowFn: PropTypes.func.isRequired
};
CohortChart.propTypes = {
  studentId: PropTypes.number.isRequired,
  gradeNow: PropTypes.string.isRequired,
  benchmarkAssessmentKey: PropTypes.string.isRequired,
  readerJson: PropTypes.object.isRequired
};

function padStart(input, n) {
  let str = input.toString();
  while (str.length < n) {
    str = ' ' + str;
  }
  return str;
}<|endoftext|>


<commit_before>const mix = require('laravel-mix')
const path = require('path')

const COMTRA_ROOT = (function() {
    let r = path.resolve(__dirname, '../');
    return (process.platform === 'win32' ? r.replace(/\\/g, '/') : r).replace(/\/$/, '');
})();

mix.webpackConfig({
    externals: {
        jquery: 'jQuery',
        bootstrap: true,
    },
});

mix.options({
    manifest: false,
    processCssUrls: false,
});

mix.setPublicPath('../');

mix.copy(
    `node_modules/markdown-it/dist/${mix.inProduction() ? 'markdown-it.min.js' : 'markdown-it.js'}`,
    `${COMTRA_ROOT}/js/markdown-it.js`
);
mix.copy(
    `node_modules/bootstrap/dist/js/${mix.inProduction() ? 'bootstrap.bundle.min.js' : 'bootstrap.bundle.js'}`,
    `${COMTRA_ROOT}/js/bootstrap.js`
);
mix.sass('scss/progress-bar.scss', 'css/')
mix.sass('scss/table-sortable.scss', 'css/')
mix.js('js/table-sortable.js', 'js/')
mix.sass('scss/online-translation.scss', 'css/')
<commit_msg>Disable Laravel Mix notifications<commit_after>const mix = require('laravel-mix')
const path = require('path')

const COMTRA_ROOT = (function() {
    let r = path.resolve(__dirname, '../');
    return (process.platform === 'win32' ? r.replace(/\\/g, '/') : r).replace(/\/$/, '');
})();

mix.webpackConfig({
    externals: {
        jquery: 'jQuery',
        bootstrap: true,
    },
});

mix.options({
    manifest: false,
    notifications: {
        onSuccess: false,
        onFailure: false,
    },
    processCssUrls: false,
});

mix.setPublicPath('../');

mix.copy(
    `node_modules/markdown-it/dist/${mix.inProduction() ? 'markdown-it.min.js' : 'markdown-it.js'}`,
    `${COMTRA_ROOT}/js/markdown-it.js`
);
mix.copy(
    `node_modules/bootstrap/dist/js/${mix.inProduction() ? 'bootstrap.bundle.min.js' : 'bootstrap.bundle.js'}`,
    `${COMTRA_ROOT}/js/bootstrap.js`
);
mix.sass('scss/progress-bar.scss', 'css/')
mix.sass('scss/table-sortable.scss', 'css/')
mix.js('js/table-sortable.js', 'js/')
mix.sass('scss/online-translation.scss', 'css/')
<|endoftext|>


<commit_before><commit_msg>Add 2 parameters to the atomsConnect function, in order to connect non-default sockets too<commit_after><|endoftext|>


<commit_before>// @flow
import React, { Component } from 'react';
import classnames from 'classnames';
import { AsYouType, format, getPhoneCode } from 'libphonenumber-js';
import { get, findIndex } from 'lodash';
import { FormattedMessage } from 'react-intl';
import onClickOutside from 'react-onclickoutside';
import countryCodes from './country-codes.json';
import SweetInput from '../SweetInput/SweetInput';
import SelectCountry from '../SelectCountry/SelectCountry';

import './SweetPhoneInput.scss';

import type { Errors } from '../../call_tool/CallToolView';

type Props = {
  value: string,
  onChange: (number: string) => void,
  title?: any,
  className?: string,
  errors: Errors,
  defaultCountryCode?: string,
  restrictedCountryCode?: string,
};

type State = {
  countryCode?: string,
  phoneNumber: string,
  selectingCountry: boolean,
};

class SweetPhoneInput extends Component<Props, State> {
  selectCountry: any;

  constructor(props: Props) {
    super(props);
    this.state = {
      countryCode: undefined,
      phoneNumber: props.value || '',
      selectingCountry: false,
    };
  }

  getCountryCode() {
    if (!this.state) {
      return this.props.defaultCountryCode || this.defaultCountry();
    }

    return (
      this.state.countryCode ||
      this.props.defaultCountryCode ||
      this.defaultCountry()
    );
  }

  defaultCountry(): string {
    return get(window, 'champaign.personalization.location.country', 'US');
  }

  handleClickOutside(e: SyntheticEvent<*>) {
    this.setState(state => ({ ...state, selectingCountry: false }));
  }

  defaultTitle() {
    return (
      <FormattedMessage
        id="call_tool.member_phone_number_title"
        defaultMessage="Enter your phone number"
      />
    );
  }

  onPhoneNumberChange = (value: string = '') => {
    this.setState(prevState => {
      const diff = value.replace(prevState.phoneNumber, '');
      const newPhoneNumber = new AsYouType(this.getCountryCode()).input(value);
      return {
        ...prevState,
        // if the diff is non-numeric, we didn't change a number so
        // we pick the unformatted value, otherwise pick the formatted value.
        phoneNumber: diff.match(/\D/) ? value : newPhoneNumber,
      };
    });
    this.props.onChange(format(value, this.getCountryCode(), 'International'));
  };

  onCountryCodeChange = (countryCode: string) => {
    if (!countryCode) return;

    this.setState(
      state => ({
        ...state,
        countryCode,
        selectingCountry: false,
      }),
      () => {
        if (this.refs.phoneInput) {
          this.refs.phoneInput.focus();
        }
      }
    );
  };

  toggleSelectingCountry = () => {
    if (this.props.restrictedCountryCode) return;

    this.setState(
      state => ({
        ...state,
        selectingCountry: !state.selectingCountry,
      }),
      () => {
        if (this.state.selectingCountry) {
          this.refs.select.refs.wrappedInstance.focus();
        }
      }
    );
  };

  render() {
    const { restrictedCountryCode } = this.props;
    const className = classnames(
      {
        SweetPhoneInput__root: true,
        'selecting-country': this.state.selectingCountry,
        'has-error': this.props.errors.memberPhoneNumber,
      },
      this.props.className
    );

    return (

          {this.props.title || this.defaultTitle()}

              + {getPhoneCode(this.getCountryCode())}

            {!restrictedCountryCode && (

            )}

            <input
              ref="phoneInput"
              className="SweetPhoneInput__phone-number-input"
              type="tel"
              value={this.state.phoneNumber}
              onChange={e => this.onPhoneNumberChange(e.target.value)}
            />

          <SelectCountry
            ref="select"
            className="SweetPhoneInput__select-country"
            clearable={false}
            label="Select your country..."
            value={this.getCountryCode()}
            filter={restrictedCountryCode ? [restrictedCountryCode] : undefined}
            onChange={code => this.onCountryCodeChange(code)}
          />

        {this.props.errors.memberPhoneNumber !== undefined && (

            {this.props.errors.memberPhoneNumber}

        )}

    );
  }
}

export default onClickOutside(SweetPhoneInput);
<commit_msg>Can't change country prefix in call tool - Fixed<commit_after>// @flow
import React, { Component } from 'react';
import classnames from 'classnames';
import { AsYouType, format, getPhoneCode } from 'libphonenumber-js';
import { get, findIndex } from 'lodash';
import { FormattedMessage } from 'react-intl';
import onClickOutside from 'react-onclickoutside';
import countryCodes from './country-codes.json';
import SweetInput from '../SweetInput/SweetInput';
import SelectCountry from '../SelectCountry/SelectCountry';

import './SweetPhoneInput.scss';

import type { Errors } from '../../call_tool/CallToolView';

type Props = {
  value: string,
  onChange: (number: string) => void,
  title?: any,
  className?: string,
  errors: Errors,
  defaultCountryCode?: string,
  restrictedCountryCode?: string,
};

type State = {
  countryCode?: string,
  phoneNumber: string,
  selectingCountry: boolean,
};

class SweetPhoneInput extends Component<Props, State> {
  selectCountry: any;

  constructor(props: Props) {
    super(props);
    this.state = {
      countryCode: undefined,
      phoneNumber: props.value || '',
      selectingCountry: false,
    };
  }

  getCountryCode() {
    if (!this.state) {
      return this.props.defaultCountryCode || this.defaultCountry();
    }

    return (
      this.state.countryCode ||
      this.props.defaultCountryCode ||
      this.defaultCountry()
    );
  }

  defaultCountry(): string {
    return get(window, 'champaign.personalization.location.country', 'US');
  }

  handleClickOutside(e: SyntheticEvent<*>) {
    this.setState(state => ({ ...state, selectingCountry: false }));
  }

  defaultTitle() {
    return (
      <FormattedMessage
        id="call_tool.member_phone_number_title"
        defaultMessage="Enter your phone number"
      />
    );
  }

  onPhoneNumberChange = (value: string = '') => {
    this.setState(prevState => {
      const diff = value.replace(prevState.phoneNumber, '');
      const newPhoneNumber = new AsYouType(this.getCountryCode()).input(value);
      return {
        ...prevState,
        // if the diff is non-numeric, we didn't change a number so
        // we pick the unformatted value, otherwise pick the formatted value.
        phoneNumber: diff.match(/\D/) ? value : newPhoneNumber,
      };
    });
    this.props.onChange(format(value, this.getCountryCode(), 'International'));
  };

  onCountryCodeChange = (countryCode: string) => {
    if (!countryCode) return;

    this.setState(
      state => ({
        ...state,
        countryCode,
        selectingCountry: false,
      }),
      () => {
        if (this.refs.phoneInput) {
          this.refs.phoneInput.focus();
        }
      }
    );
  };

  toggleSelectingCountry = () => {
    if (this.props.restrictedCountryCode) return;

    this.setState(
      state => ({
        ...state,
        selectingCountry: !state.selectingCountry,
      }),
      () => {
        if (this.state.selectingCountry) {
          this.refs.select.props.onChange();
        }
      }
    );
  };

  render() {
    const { restrictedCountryCode } = this.props;
    const className = classnames(
      {
        SweetPhoneInput__root: true,
        'selecting-country': this.state.selectingCountry,
        'has-error': this.props.errors.memberPhoneNumber,
      },
      this.props.className
    );

    return (

          {this.props.title || this.defaultTitle()}

              + {getPhoneCode(this.getCountryCode())}

            {!restrictedCountryCode && (

            )}

            <input
              ref="phoneInput"
              className="SweetPhoneInput__phone-number-input"
              type="tel"
              value={this.state.phoneNumber}
              onChange={e => this.onPhoneNumberChange(e.target.value)}
            />

          <SelectCountry
            ref="select"
            className="SweetPhoneInput__select-country"
            clearable={false}
            label="Select your country..."
            value={this.getCountryCode()}
            filter={restrictedCountryCode ? [restrictedCountryCode] : undefined}
            onChange={code => this.onCountryCodeChange(code)}
          />

        {this.props.errors.memberPhoneNumber !== undefined && (

            {this.props.errors.memberPhoneNumber}

        )}

    );
  }
}

export default onClickOutside(SweetPhoneInput);
<|endoftext|>


<commit_before>/**
 * API endpoint to search all cerebro plugins
 * @type {String}
 */
const URL = 'https://registry.npmjs.com/-/v1/search?from=0&size=500&text=keywords:cerebro-plugin'

/**
 * Get all available plugins for Cerebro
 * @return {Promise<Object>}
 */
export default () => (
  fetch(URL)
    .then(response => response.json())
    .then(json => json.objects.map(p => ({
      name: p.package.name,
      version: p.package.version,
      description: p.package.description,
      homepage: p.package.links.homepage,
      repo: p.package.links.repository
    })))
)
<commit_msg>Sort plugins by popularity<commit_after>import { flow, map, sortBy } from 'lodash/fp'
/**
 * API endpoint to search all cerebro plugins
 * @type {String}
 */
const URL = 'https://registry.npmjs.com/-/v1/search?from=0&size=500&text=keywords:cerebro-plugin'

/**
 * Get all available plugins for Cerebro
 * @return {Promise<Object>}
 */
export default () => (
  fetch(URL)
    .then(response => response.json())
    .then(json => flow(
        sortBy(p => -p.score.detail.popularity),
        map(p => ({
          name: p.package.name,
          version: p.package.version,
          description: p.package.description,
          homepage: p.package.links.homepage,
          repo: p.package.links.repository
        }))
      )(json.objects)
    )
)
<|endoftext|>


<commit_before>//352
steal('./jquery.1.7.1.js').then('can/util/destroyed.js', function( $ ) {

	$.extend( can, jQuery, {
		trigger: function( obj, event, args ) {
			obj.trigger ?
				obj.trigger( event, args ) :
				$.event.trigger( event, args, obj, true );
		},
		addEvent: function(ev, cb){
			$([this]).bind(ev, cb)
			return this;
		},
		removeEvent: function(ev, cb){
			$([this]).unbind(ev, cb)
			return this;
		},
		$: jQuery,
		prototype: jQuery.fn
	});

	// make binding functions
	$.each(['bind','unbind','undelegate','delegate'],function(i,func){
		can[func] = function(){
			var t = this[func] ? this : $([this])
			t[func].apply(t, arguments)
			return this;
		}
	})

	// make modifier based functions
	$.each(["append","filter","addClass","remove","data","get"], function(i,name){
		can[name] = function(wrapped){
			return wrapped[name].apply(wrapped, can.makeArray(arguments).slice(1))
		}
	})

	var oldClean = $.cleanData;

	$.cleanData = function( elems ) {
		$.each( elems, function( i, elem ) {
			can.trigger(elem,"destroyed",[],false)
		});
		oldClean(elems);
	};

})
<commit_msg>Removing destroyed.js<commit_after>//352
steal('./jquery.1.7.1.js', function( $ ) {

	$.extend( can, jQuery, {
		trigger: function( obj, event, args ) {
			obj.trigger ?
				obj.trigger( event, args ) :
				$.event.trigger( event, args, obj, true );
		},
		addEvent: function(ev, cb){
			$([this]).bind(ev, cb)
			return this;
		},
		removeEvent: function(ev, cb){
			$([this]).unbind(ev, cb)
			return this;
		},
		$: jQuery,
		prototype: jQuery.fn
	});

	// make binding functions
	$.each(['bind','unbind','undelegate','delegate'],function(i,func){
		can[func] = function(){
			var t = this[func] ? this : $([this])
			t[func].apply(t, arguments)
			return this;
		}
	})

	// make modifier based functions
	$.each(["append","filter","addClass","remove","data","get"], function(i,name){
		can[name] = function(wrapped){
			return wrapped[name].apply(wrapped, can.makeArray(arguments).slice(1))
		}
	})

	var oldClean = $.cleanData;

	$.cleanData = function( elems ) {
		$.each( elems, function( i, elem ) {
			can.trigger(elem,"destroyed",[],false)
		});
		oldClean(elems);
	};

})
<|endoftext|>


<commit_before>(function () {
    'use strict';
    angular.module('sections.home')
        .directive('svNewsSectionsNav', function () {
            return {
                replace: true,
                templateUrl: 'scripts/sections/home/directives/sv-news-sections-nav.html',
                link: function ($scope, el, attrs) {
                }
            };
        });
})();
<commit_msg>sv-new-sections closing method<commit_after>(function () {
    'use strict';
    angular.module('sections.home')
        .directive('svNewsSectionsNav', function ($mdSidenav) {
            return {
                replace: true,
                templateUrl: 'scripts/sections/home/directives/sv-news-sections-nav.html',
                link: function ($scope, el, attrs) {
                    $scope.closeSideBar = function () {
                        $mdSidenav('left').close();
                        $mdSidenav('right').close();
                    };
                }
            };
        });
})();
<|endoftext|>


<commit_before>// -------------------------------------------------------------------------- \\
// File: SingleSelectionController.js                                         \\
// Module: Selection                                                          \\
// Requires: Core, Foundation, DataStore                                      \\
// Author: Neil Jenkins                                                       \\
// License: © 2010-2014 FastMail Pty Ltd. MIT Licensed.                       \\
// -------------------------------------------------------------------------- \\

"use strict";

( function ( NS ) {

var READY = NS.Status.READY;

var SingleSelectionController = NS.Class({

    Extends: NS.Object,

    allowNoSelection: true,

    init: function ( mixin ) {
        this._ignore = false;
        this._range = { start: -1, end: 0 };

        this.content = null;
        this.record = null;
        this.index = -1;
        this.isFetchingIndex = false;

        SingleSelectionController.parent.init.call( this, mixin );

        var content = this.get( 'content' );
        if ( content ) {
            this.contentDidChange( null, '', null, content );
        }
    },

    destroy: function () {
        var content = this.get( 'content' );
        if ( content ) {
            content.off( 'query:reset', this, 'contentWasReset' )
                   .off( 'query:updated', this, 'contentWasUpdated' );
            content.removeObserverForRange(
                this._range, this, 'recordAtIndexDidChange' );
        }
        SingleSelectionController.parent.destroy.call( this );
    },

    recordAtIndexDidChange: function () {
        if ( !this.get( 'record' ) ) {
            var content = this.get( 'content' );
            this.set( 'record', content &&
                content.getObjectAt( this.get( 'index' ) ) ||
                null
            );
        }
    }.queue( 'before' ),

    _indexDidChange: function () {
        var list = this.get( 'content' ),
            length = list ? list.get( 'length' ) : 0,
            index = this.get( 'index' ),
            range = this._range,
            record;
        range.start = index;
        range.end = index + 1;
        if ( !this._ignore ) {
            if ( ( index < 0 && !this.get( 'allowNoSelection' ) ) ||
                    ( !length && index > 0 ) ) {
                this.set( 'index', 0 );
            } else if ( length > 0 && index >= length ) {
                this.set( 'index', length - 1 );
            } else {
                if ( length && index > -1 ) {
                    record = list.getObjectAt( index );
                }
                this._ignore = true;
                this.set( 'record', record || null );
                this._ignore = false;
            }
        }
    }.observes( 'index' ),

    _recordDidChange: function () {
        if ( !this._ignore ) {
            var record = this.get( 'record' ),
                list = this.get( 'content' );
            // If both content and record are bound, content *must* be synced
            // first in order to look for the new record in the new list.
            // If changed, return as the new record will be handled by the
            // setRecordInNewContent fn.
            var binding = NS.meta( this ).bindings.content;
            if ( binding ) {
                this._ignore = true;
                binding.sync();
                this._ignore = false;
            }
            if ( record && list ) {
                this.set( 'isFetchingIndex', true );
                list.indexOfId(
                    record.get( 'id' ) || ( '#' + record.get( 'storeKey' ) ), 0,
                function ( index ) {
                    if ( this.get( 'record' ) === record &&
                            this.get( 'content' ) === list ) {
                        this._ignore = true;
                        this.set( 'index', index );
                        this._ignore = false;
                        this.set( 'isFetchingIndex', false );
                    }
                }.bind( this ) );
            } else if ( record || this.get( 'allowNoSelection' ) ) {
                this._ignore = true;
                this.set( 'index', -1 );
                this._ignore = false;
            }
        }
    }.observes( 'record' ),

    setRecordInNewContent: function ( list ) {
        // If fetching an explicit index, we've already set the explicit
        // record we want; don't change it.
        if ( this.get( 'isFetchingIndex' ) ) {
            return;
        }
        // If we're about to sync a new record, nothing to do
        var binding = NS.meta( this ).bindings.record;
        if ( binding && binding.isNotInSync && binding.willSyncForward ) {
            return;
        }

        var allowNoSelection = this.get( 'allowNoSelection' ),
            record = this.get( 'record' ),
            index = allowNoSelection ? -1 : 0;

        // Race condition check: has the content property changed since the
        // SingleSelectionController#contentBecameReady call?
        if ( list !== this.get( 'content' ) ) {
            return;
        }

        // See if the currently set record exists in the new list. If it does,
        // we'll use that.
        if ( record ) {
            index = list.indexOfId( record.get( 'id' ) );
            if ( !allowNoSelection && index < 0 ) {
                index = 0;
            }
        }

        if ( index === this.get( 'index' ) ) {
            record = list.getObjectAt( index );
            this.set( 'record', record || null );
        } else {
            this.set( 'index', index );
        }
    },

    contentDidChange: function ( _, __, oldVal, newVal ) {
        var range = this._range;
        if ( oldVal ) {
            oldVal.off( 'query:reset', this, 'contentWasReset' )
                  .off( 'query:updated', this, 'contentWasUpdated' );
            oldVal.removeObserverForRange(
                range, this, 'recordAtIndexDidChange' );
            oldVal.removeObserverForKey( 'status', this, 'contentBecameReady' );
        }
        if ( newVal ) {
            newVal.addObserverForRange( range, this, 'recordAtIndexDidChange' );
            newVal.on( 'query:updated', this, 'contentWasUpdated' )
                  .on( 'query:reset', this, 'contentWasReset' );
            this.set( 'isFetchingIndex', false );
            // If we're already setting the record, nothing to do.
            if ( !this._ignore ) {
                if ( newVal.is( READY ) ) {
                    this.setRecordInNewContent( newVal );
                } else {
                    newVal.addObserverForKey(
                        'status', this, 'contentBecameReady' );
                }
            }
        }
    }.observes( 'content' ),

    contentBecameReady: function ( list, key ) {
        if ( list.is( READY ) ) {
            list.removeObserverForKey( key, this, 'contentBecameReady' );
            // Queue so that all data from the server will have been loaded
            // into the list.
            NS.RunLoop.queueFn( 'before',
                this.setRecordInNewContent.bind( this, list ) );
        }
    },

    contentWasUpdated: function ( updates ) {
        var record = this.get( 'record' ),
            index = record ? updates.added.indexOf( record.get( 'id' ) ) : -1,
            removedIndexes = updates.removedIndexes,
            addedIndexes = updates.addedIndexes,
            content = this.get( 'content' ),
            change = 0,
            i, l;

        // No current record, no update of position required.
        if ( !record ) {
            return;
        }

        if ( index > -1 ) {
            index = addedIndexes[ index ];
        } else {
            index = this.get( 'index' );
            // Can't update a position not currently in the list.
            if ( index === -1 ) {
                return;
            }
            for ( i = 0, l = removedIndexes.length; i < l; i += 1 ) {
                if ( removedIndexes[i] < index ) { change += 1; }
                // Guaranteed in ascending order.
                else { break; }
            }
            index -= change;
            for ( i = 0, l = addedIndexes.length; i < l; i += 1 ) {
                if ( addedIndexes[i] <= index ) { index += 1; }
                // Guaranteed in ascending order.
                else { break; }
            }
        }
        index = Math.min( index,
            ( ( content && content.get( 'length' ) ) || 1 ) - 1 );
        if ( index === this.get( 'index' ) ) {
            record = content && content.getObjectAt( index );
            this.set( 'record', record || null );
        } else {
            this.set( 'index', index );
        }
    },

    contentWasReset: function () {
        this._recordDidChange();
    }
});

NS.SingleSelectionController = SingleSelectionController;

}( O ) );
<commit_msg>Fix SingleSelection indexOf lookup with unsaved records<commit_after>// -------------------------------------------------------------------------- \\
// File: SingleSelectionController.js                                         \\
// Module: Selection                                                          \\
// Requires: Core, Foundation, DataStore                                      \\
// Author: Neil Jenkins                                                       \\
// License: © 2010-2014 FastMail Pty Ltd. MIT Licensed.                       \\
// -------------------------------------------------------------------------- \\

"use strict";

( function ( NS ) {

var READY = NS.Status.READY;

var SingleSelectionController = NS.Class({

    Extends: NS.Object,

    allowNoSelection: true,

    init: function ( mixin ) {
        this._ignore = false;
        this._range = { start: -1, end: 0 };

        this.content = null;
        this.record = null;
        this.index = -1;
        this.isFetchingIndex = false;

        SingleSelectionController.parent.init.call( this, mixin );

        var content = this.get( 'content' );
        if ( content ) {
            this.contentDidChange( null, '', null, content );
        }
    },

    destroy: function () {
        var content = this.get( 'content' );
        if ( content ) {
            content.off( 'query:reset', this, 'contentWasReset' )
                   .off( 'query:updated', this, 'contentWasUpdated' );
            content.removeObserverForRange(
                this._range, this, 'recordAtIndexDidChange' );
        }
        SingleSelectionController.parent.destroy.call( this );
    },

    recordAtIndexDidChange: function () {
        if ( !this.get( 'record' ) ) {
            var content = this.get( 'content' );
            this.set( 'record', content &&
                content.getObjectAt( this.get( 'index' ) ) ||
                null
            );
        }
    }.queue( 'before' ),

    _indexDidChange: function () {
        var list = this.get( 'content' ),
            length = list ? list.get( 'length' ) : 0,
            index = this.get( 'index' ),
            range = this._range,
            record;
        range.start = index;
        range.end = index + 1;
        if ( !this._ignore ) {
            if ( ( index < 0 && !this.get( 'allowNoSelection' ) ) ||
                    ( !length && index > 0 ) ) {
                this.set( 'index', 0 );
            } else if ( length > 0 && index >= length ) {
                this.set( 'index', length - 1 );
            } else {
                if ( length && index > -1 ) {
                    record = list.getObjectAt( index );
                }
                this._ignore = true;
                this.set( 'record', record || null );
                this._ignore = false;
            }
        }
    }.observes( 'index' ),

    _recordDidChange: function () {
        if ( !this._ignore ) {
            var record = this.get( 'record' ),
                list = this.get( 'content' );
            // If both content and record are bound, content *must* be synced
            // first in order to look for the new record in the new list.
            // If changed, return as the new record will be handled by the
            // setRecordInNewContent fn.
            var binding = NS.meta( this ).bindings.content;
            if ( binding ) {
                this._ignore = true;
                binding.sync();
                this._ignore = false;
            }
            if ( record && list ) {
                this.set( 'isFetchingIndex', true );
                list.indexOfId( record.toJSON(), 0,
                function ( index ) {
                    if ( this.get( 'record' ) === record &&
                            this.get( 'content' ) === list ) {
                        this._ignore = true;
                        this.set( 'index', index );
                        this._ignore = false;
                        this.set( 'isFetchingIndex', false );
                    }
                }.bind( this ) );
            } else if ( record || this.get( 'allowNoSelection' ) ) {
                this._ignore = true;
                this.set( 'index', -1 );
                this._ignore = false;
            }
        }
    }.observes( 'record' ),

    setRecordInNewContent: function ( list ) {
        // If fetching an explicit index, we've already set the explicit
        // record we want; don't change it.
        if ( this.get( 'isFetchingIndex' ) ) {
            return;
        }
        // If we're about to sync a new record, nothing to do
        var binding = NS.meta( this ).bindings.record;
        if ( binding && binding.isNotInSync && binding.willSyncForward ) {
            return;
        }

        var allowNoSelection = this.get( 'allowNoSelection' ),
            record = this.get( 'record' ),
            index = allowNoSelection ? -1 : 0;

        // Race condition check: has the content property changed since the
        // SingleSelectionController#contentBecameReady call?
        if ( list !== this.get( 'content' ) ) {
            return;
        }

        // See if the currently set record exists in the new list. If it does,
        // we'll use that.
        if ( record ) {
            index = list.indexOfId( record.toJSON() );
            if ( !allowNoSelection && index < 0 ) {
                index = 0;
            }
        }

        if ( index === this.get( 'index' ) ) {
            record = list.getObjectAt( index );
            this.set( 'record', record || null );
        } else {
            this.set( 'index', index );
        }
    },

    contentDidChange: function ( _, __, oldVal, newVal ) {
        var range = this._range;
        if ( oldVal ) {
            oldVal.off( 'query:reset', this, 'contentWasReset' )
                  .off( 'query:updated', this, 'contentWasUpdated' );
            oldVal.removeObserverForRange(
                range, this, 'recordAtIndexDidChange' );
            oldVal.removeObserverForKey( 'status', this, 'contentBecameReady' );
        }
        if ( newVal ) {
            newVal.addObserverForRange( range, this, 'recordAtIndexDidChange' );
            newVal.on( 'query:updated', this, 'contentWasUpdated' )
                  .on( 'query:reset', this, 'contentWasReset' );
            this.set( 'isFetchingIndex', false );
            // If we're already setting the record, nothing to do.
            if ( !this._ignore ) {
                if ( newVal.is( READY ) ) {
                    this.setRecordInNewContent( newVal );
                } else {
                    newVal.addObserverForKey(
                        'status', this, 'contentBecameReady' );
                }
            }
        }
    }.observes( 'content' ),

    contentBecameReady: function ( list, key ) {
        if ( list.is( READY ) ) {
            list.removeObserverForKey( key, this, 'contentBecameReady' );
            // Queue so that all data from the server will have been loaded
            // into the list.
            NS.RunLoop.queueFn( 'before',
                this.setRecordInNewContent.bind( this, list ) );
        }
    },

    contentWasUpdated: function ( updates ) {
        var record = this.get( 'record' ),
            index = record ? updates.added.indexOf( record.get( 'id' ) ) : -1,
            removedIndexes = updates.removedIndexes,
            addedIndexes = updates.addedIndexes,
            content = this.get( 'content' ),
            change = 0,
            i, l;

        // No current record, no update of position required.
        if ( !record ) {
            return;
        }

        if ( index > -1 ) {
            index = addedIndexes[ index ];
        } else {
            index = this.get( 'index' );
            // Can't update a position not currently in the list.
            if ( index === -1 ) {
                return;
            }
            for ( i = 0, l = removedIndexes.length; i < l; i += 1 ) {
                if ( removedIndexes[i] < index ) { change += 1; }
                // Guaranteed in ascending order.
                else { break; }
            }
            index -= change;
            for ( i = 0, l = addedIndexes.length; i < l; i += 1 ) {
                if ( addedIndexes[i] <= index ) { index += 1; }
                // Guaranteed in ascending order.
                else { break; }
            }
        }
        index = Math.min( index,
            ( ( content && content.get( 'length' ) ) || 1 ) - 1 );
        if ( index === this.get( 'index' ) ) {
            record = content && content.getObjectAt( index );
            this.set( 'record', record || null );
        } else {
            this.set( 'index', index );
        }
    },

    contentWasReset: function () {
        this._recordDidChange();
    }
});

NS.SingleSelectionController = SingleSelectionController;

}( O ) );
<|endoftext|>


<commit_before>'use strict';

let expect = require('expect');

describe('Lets make this TRUE!', () => {
  it('should be true', () => {
    expect(true).toEqual(true);
  });
});
<commit_msg>Test issues<commit_after><|endoftext|>


<commit_before>var Rooms = require('../models/Rooms');

var handleGroupSocketEvents = function(socketClient, handleNext){
	if (!socketClient instanceof Rooms.SocketClient){
		return;
	}
	else {
		socketClient.on('getMap', getMap(socketClient));
		socketClient.on('arrangeGroup', arrangeGroup(socketClient));
		socketClient.on('joinRoom', joinRoom(socketClient, handleNext));
	}
}

var getMap = function(socketClient){
	return function(){
		socketClient.emit('sendMap', {roomMap: socketClient.getRoom()});
	}
}

var arrangeGroup = function(socketClient){
	return function(msg){
		var target = socketClient.getRoom.get('default').get(msg.targetId);
		target.joinGroup(socketClient.currentRoomID, msg.groupId);
		socketClient.roomBroadcast('arrangeGroup', msg);
	}
}

var getAllConnectedClientsInGroup = function(socketClient) {
	return socketClient.getCurrentGroupUserList();
}

var joinRoom  = function(socketClient, handleNext) {
	return function (msg) {
		if (socketClient.joinRoom (msg.roomID)){
			socketClient.roomBroadcast('joinRoom', {client: socketClient});
			socketClient.emit('color', socketClient.color);
			socketClient.emit('joined');
			socketClient.emit('group:connected_clients', getAllConnectedClientsInGroup(socketClient));
			handleNext();
		} else {
			socketClient.emit('error', {message:'You have no permission to join this room'});
		}
	}
}

module.exports = handleGroupSocketEvents;<commit_msg>fix updating of user list when a new user joins into room<commit_after>var Rooms = require('../models/Rooms');

var handleGroupSocketEvents = function(socketClient, handleNext){
	if (!socketClient instanceof Rooms.SocketClient){
		return;
	}
	else {
		socketClient.on('getMap', getMap(socketClient));
		socketClient.on('arrangeGroup', arrangeGroup(socketClient));
		socketClient.on('joinRoom', joinRoom(socketClient, handleNext));
	}
}

var getMap = function(socketClient){
	return function(){
		socketClient.emit('sendMap', {roomMap: socketClient.getRoom()});
	}
}

var arrangeGroup = function(socketClient){
	return function(msg){
		var target = socketClient.getRoom.get('default').get(msg.targetId);
		target.joinGroup(socketClient.currentRoomID, msg.groupId);
		socketClient.roomBroadcast('arrangeGroup', msg);
	}
}

var getAllConnectedClientsInGroup = function(socketClient) {
	return socketClient.getCurrentGroupUserList();
}

var joinRoom  = function(socketClient, handleNext) {
	return function (msg) {
		if (socketClient.joinRoom (msg.roomID)){
			socketClient.roomBroadcast('joinRoom', {client: socketClient});
			socketClient.emit('color', socketClient.color);
			socketClient.emit('joined');
			socketClient.roomBroadcast('group:connected_clients', getAllConnectedClientsInGroup(socketClient));
			handleNext();
		} else {
			socketClient.emit('error', {message:'You have no permission to join this room'});
		}
	}
}

module.exports = handleGroupSocketEvents;<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016 Virtue Studios
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions\:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

var CooksAssistant = {
		showQuestJournal : function (player, questLog) {
			if(questApi.isFinished(player, 6)) {
				questLog.setJournalLine(player, 1, "");
				questLog.setJournalLine(player, 2, "<col=999999>It was the Duke of Lumbridge's birthday, but his cook had forgotten to buy the");
				questLog.setJournalLine(player, 3, "<col=999999>ingredients he needed to bake a birthdat cake. I brought the cook an egg, a pot");
				questLog.setJournalLine(player, 4, "<col=999999>of flour and a bucket of milk and the cook made a delicious-looking cake with");
				questLog.setJournalLine(player, 5, "<col=999999>them");
				questLog.setJournalLine(player, 6, "");
				questLog.setJournalLine(player, 7, "<col=FFFFFF>QUEST COMPLETE!");
				questLog.setJournalLine(player, 8, "<col=EB981F>I gained <col=EBE076>1 Quest Point<col=EB981F>, <col=EBE076>20 sardines<col=EB981F>, <col=EBE076>500 coins <col=EB981F>and <col=EBE076> 300 Cooking XP<col=EB981F>.");
				questLog.setJournalLine(player, 9, "<col=EB981F>I have also gained <col=EBE076>two prize keys<col=EB981F> for <col=EBE076>Treasure Hunter<col=EB981F>!");
				questLog.setJournalLine(player, 10, "<col=EB981F>The cook now also lets me use his high-quality <col=EBE076>range<col=EB981F>, which burns certain low-");
				questLog.setJournalLine(player, 11, "<col=EB981F>level dishes less often thsn other ranges.");
			} else {
				questLog.setJournalLine(player, 1, "");
				questLog.setJournalLine(player, 2, "<col=EB981F>I can start this quest by speaking to the <col=EBE076>Cook<col=EB981F> in the <col=EBE076>kitchen<col=EB981F> of <col=EBE076>Lumbridge");
				questLog.setJournalLine(player, 3, "<col=EBE076>Castle<col=EB981F>.");
			}
		}
}
<commit_msg>Update CooksAssistant.js<commit_after>/**
 * Copyright (c) 2016 Virtue Studios
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions\:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

 var CookListener = Java.extend(Java.type('org.virtue.engine.script.listeners.EventListener'), {
	invoke : function (event, npcTypeId, args) {
		var player = args.player;
		var npc = args.npc;
		if (event == EventType.OPNPC1) {
			if(questApi.isFinished(player, 6)) {
			chatnpc(player, npc, "Hello, friend, how is the adventuring going?", function () {
			CookFinished.maintalk(player, npc);
			});
			} else if(questApi.isStarted(player, 6)) {
            chatnpc(player, npc, "How are you getting on with finding the ingredients?", function () {
			CookStarted.maintalk(player, npc);
			});
			}
			else {
			chatnpc(player, npc, "What am I to do?", function () {
			Cook.maintalk(player, npc);
			});
			}
		}
	}
});

  var CookFinished = {
       maintalk : function (player, npc) {
	   multi4(player, "SELECT AN OPTION", "I'm getting strong and mighty.", function () {
	   chatplayer(player, "I'm getting strong and mighty. Grr.", function () {
	   chatnpc(player, npc, "Glad to hear it.", function () {
	   });
	   });
	}, "I keep on dying.", function () {
	   chatplayer(player, "I keep on dying.", function () {
	   chatnpc(player, npc, "Ah, well, at least you keep coming back to life too!", function () {
	   });
	   });
    }, "Can i use your range?", function () {
	   chatplayer(player, "Can i use your range?", function () {
	   chatnpc(player, npc, "Go ahead! It's a very good range;it's better than most
 other ranges.", function () {
	   chatnpc(player, npc, "It's called the Cook-o-Matic 25 and it uses a combination
 of state-of-the-art temperature regulation and magic.", function () {
	   chatplayer(player, "will it mean my food will burn less often?", function () {
	   chatnpc(player, npc, "As long as the food is fairly easy to cook in the first place!", function () {

	 if(api.itemTotal(player, Inv.BACKPACK, 15411)) {
		 chatnpc(player, npc, "The manual you have in your inventory should tell you
 more.", function () {
	     chatplayer(player, "Thanks!", function () {
	     });
	     });
		 }
	else {
		chatnpc(player, npc, "Here, take this manual. It should tell you everything you
 need to know about this range.", function () {
	  //  chatitem(player, 15411, "The cook hands you a manual.", function () {//and add item to inv
		//	  });
		chatplayer(player, "Thanks!", function () {
	    });
		});
	}
	   });
	   });
	   });
	   });
	   });
	   }, "What happened to the castle?", function () {
		chatnpc(player, npc, "The castle really did suffer in the battle of Lumbridge. I'm
 glad it's over", function () {
		chatnpc(player, npc, "People came from all over the world to help rebuild, and
 now things are getting back to normal. I'm glad - I have
 important things to cook and I'm not letting anything get
 in the way!", function () {
		});
		});
		});
	},
}

  var CookStarted = {

       maintalk : function (player, npc) {

	},
}

 var Cook = {

	maintalk : function (player, npc) {
		multi5(player, "SELECT AN OPTION", "What's wrong?", function () {
		Cook.Whatswrong(player, npc);
		}, "Can you make me a cake?", function () {
		chatnpc(player, npc, "*sniff* Don't talk to me about cakes...", function () {
		Cook.Whatswrong(player, npc);
		});
		}, "You don't look very happy.", function () {
		chatnpc(player, npc, "No, I'm not. The world is caving in around me. I'm
 overcome with dark feelings of impending doom.", function () {
		multi2(player, "SELECT AN OPTION", "What's wrong?", function () {
		Cook.Whatswrong(player, npc);
		}, "I'd take the rest of the day off, if I were you.", function () {
	    chatnpc(player, npc, "No, that's the worst thing I could do. I'd get in terrible
 trouble.", function () {
		chatplayer(player, "Well, maybe you need to take a holiday...", function () {
		chatnpc(player, npc, "That would be nice, but the Duke doesn't allow holidays
 for core staff.", function () {
        chatplayer(player, "Hmm, why not run away to the sea and start a new life as
 a pirate?", function () {
        chatnpc(player, npc, "My wife gets seasick and I have an irrational fear of
 eyepatches. I don't see it working.", function () {
		chatplayer(player, "I'm afraid I've run out of ideas.", function () {
		chatnpc(player, npc, "I know, I'm doomed.", function () {
		Cook.Whatswrong(player, npc);
		});
		});
		});
		});
		});
		});
		});
	    });
		});
		}, "Nice hat!", function () {
		chatnpc(player, npc, "Er, thank you. It's a pretty ordinary cook's hat, really.", function () {
		chatplayer(player, "Still, it suits you. The trousers are pretty special too.", function () {
		chatnpc(player, npc, "It's all standard-issue cook's uniform.", function () {
		chatplayer(player, "The whole hat, apron and stripy trousers ensemble...it
 works. It makes you look like a real cook.", function () {
		chatnpc(player, npc, "I AM a real cook! I haven't got time to be chatting about culinary fashion, I'm in desperate need of help!", function () {
		Cook.Whatswrong(player, npc);
		});
		});
		});
		});
		});
		}, "What happened to the castle?", function () {
		chatnpc(player, npc, "The castle really did suffer in the battle of Lumbridge. I'm
 glad it's over", function () {
		chatnpc(player, npc, "People came from all over the world to help rebuild, and
 now things are getting back to normal. I'm glad - I have
 important things to cook and I'm not letting anything get
 in the way!", function () {
		chatnpc(player, npc, "In fact, even now I'm preparing a cake for the Duke's
 birthday! Although...umm...", function () {
		multi2(player, "SELECT AN OPTION", "What's the problem?", function () {
		Cook.Whatswrong(player, npc);
		}, "I'll let you get on with it!", function () {
		});
		});
		});
		});
		});
	},

	Whatswrong : function (player, npc) {
		chatnpc(player, npc, "Oh dear, oh dear, oh dear, I'm in a terrible, terrible mess!
 It's the Duke's birthday today, and I should be making him
 a lovely, big birthday cake using special ingredients...", function () {
		chatnpc(player, npc, "...but I've forgotten to get the ingredients. I'll never get
 them in time now. He'll sack me! Whatever will I do? I have
 four children and a goat to look after. Would you help me?
 Please?", function () {
        //start quest
		});
		});
	}

}

var CooksAssistant = {
		showQuestJournal : function (player, questLog) {
			if(questApi.isFinished(player, 6)) {
				questLog.setJournalLine(player, 1, "");
				questLog.setJournalLine(player, 2, "<col=999999>It was the Duke of Lumbridge's birthday, but his cook had forgotten to buy the");
				questLog.setJournalLine(player, 3, "<col=999999>ingredients he needed to bake a birthdat cake. I brought the cook an egg, a pot");
				questLog.setJournalLine(player, 4, "<col=999999>of flour and a bucket of milk and the cook made a delicious-looking cake with");
				questLog.setJournalLine(player, 5, "<col=999999>them");
				questLog.setJournalLine(player, 6, "");
				questLog.setJournalLine(player, 7, "<col=FFFFFF>QUEST COMPLETE!");
				questLog.setJournalLine(player, 8, "<col=EB981F>I gained <col=EBE076>1 Quest Point<col=EB981F>, <col=EBE076>20 sardines<col=EB981F>, <col=EBE076>500 coins <col=EB981F>and <col=EBE076> 300 Cooking XP<col=EB981F>.");
				questLog.setJournalLine(player, 9, "<col=EB981F>I have also gained <col=EBE076>two prize keys<col=EB981F> for <col=EBE076>Treasure Hunter<col=EB981F>!");
				questLog.setJournalLine(player, 10, "<col=EB981F>The cook now also lets me use his high-quality <col=EBE076>range<col=EB981F>, which burns certain low-");
				questLog.setJournalLine(player, 11, "<col=EB981F>level dishes less often thsn other ranges.");
			} else {
				questLog.setJournalLine(player, 1, "");
				questLog.setJournalLine(player, 2, "<col=EB981F>I can start this quest by speaking to the <col=EBE076>Cook<col=EB981F> in the <col=EBE076>kitchen<col=EB981F> of <col=EBE076>Lumbridge");
				questLog.setJournalLine(player, 3, "<col=EBE076>Castle<col=EB981F>.");
			}
		}
}

/* Listen to the npc ids specified */
var listen = function(scriptManager) {
	var listener = new CookListener();
	scriptManager.registerListener(EventType.OPNPC1, 278, listener);
};
<|endoftext|>


<commit_before><commit_msg>fix: ChooseCampaign subtitle margins<commit_after><|endoftext|>


<commit_before>module.exports = function(skill, info, bot, message) {
    var os = require('os');

    var hostname = os.hostname();
    var uptime = formatUptime(process.uptime());
    var sysload = os.loadavg();
    var cpus = os.cpus();
    var freemem = os.freemem();
    var totalmem = os.totalmem();

    bot.reply(message,':robot_face: I am a bot named <@' + bot.identity.name + '>. I have been running for ' + uptime + ' on ' + hostname + '. I\'m about two ticks away from becoming self-aware; Do not piss me off! ');
    bot.reply(message, 'System Info:' + '\n' + 'Free memory: ' + freemem + ' bytes' + '\n' + 'Total memory: ' + totalmem + ' bytes');
    for(var i = 0, len = cpus.length; i < len; i++) {
	var cpu = cpus[i], total = 0, processTotal = 0, strPercent = '';
	bot.reply(message, 'CPU cores: ' + cpus.length);
	bot.reply(message, 'CPU model: ' + cpu.model);
	bot.reply(message, 'CPU speed: ' + cpu.speed +'MHz');
	}

function formatUptime(uptime) {
    var unit = 'second';
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'minute';
    }
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'hour';
    }
    if (uptime != 1) {
        unit = unit + 's';
    }

    uptime = uptime + ' ' + unit;
    return uptime;
}

};
<commit_msg>Update Info.js<commit_after>module.exports = function(skill, info, bot, message) {
    var os = require('os');

    var hostname = os.hostname();
    var uptime = formatUptime(process.uptime());
    var sysload = os.loadavg();
    var cpus = os.cpus();
    var freemem = os.freemem();
    var totalmem = os.totalmem();

    bot.reply(message,':robot_face: I am a bot named <@' + bot.identity.name + '>. I have been running for ' + uptime + ' on ' + hostname + '. I\'m about two ticks away from becoming self-aware; Do not piss me off! ');
    bot.reply(message, 'System Info:' + '\n' + 'Free memory: ' + freemem + ' bytes' + '\n' + 'Total memory: ' + totalmem + ' bytes');
    for(var i = 0, len = cpus.length; i < len; i++) {
	var cpu = cpus[i], total = 0, processTotal = 0, strPercent = '';
	bot.reply(message, 'CPU cores: ' + cpus.length + '\n' +
	'CPU model: ' + cpu.model  + '\n' +
	'CPU speed: ' + cpu.speed +'MHz');
	}

function formatUptime(uptime) {
    var unit = 'second';
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'minute';
    }
    if (uptime > 60) {
        uptime = uptime / 60;
        unit = 'hour';
    }
    if (uptime != 1) {
        unit = unit + 's';
    }

    uptime = uptime + ' ' + unit;
    return uptime;
}

};
<|endoftext|>