<commit_before>/* jshint -W097 */// jshint strict:false
/*jslint node: true */

"use strict";

var utils   = require(__dirname + '/lib/utils'); // Get common adapter utils

var channels = [];
var iopkg;

var adapter = utils.adapter({
    name: 'feiertage',
    useFormatDate: true,
    /*
    unload: function (callback) {
        adapter.log.info("adapter feiertage is unloading");
    },
    discover: function (callback) {
        adapter.log.info("adapter feiertage discovered");
    },
    install: function (callback) {
        adapter.log.info("adapter feiertage installed");
    },
    uninstall: function (callback) {
        adapter.log.info("adapter feiertage UN-installed");
    }, */
    ready: function () {
        adapter.log.debug("Adapter feiertage got 'Ready' Signal");
        adapter.log.debug("adapter feiertage initializing objects");
        checkHolidays();
        adapter.log.info("adapter feiertage objects written");

        setTimeout(function () {
            adapter.log.info('force terminating after 4 minutes');
            adapter.stop();
        }, 240000);
    }
});

// Script ermittelt, ob heute oder morgen ein Feiertag ist
var sj;                 // Schaltjahr
var ostern;             // Ostersonntag: Tag im Jahr

// Regional nicht relevante Feiertage auskommentieren oder löschen !!
function feiertag(day) {
    var Name = '';
    if (day == 1) Name = 'Neujahr';
    else if (day == 6) Name = 'Heilige Drei Könige (BW,BY,ST)';
    else if (sj + 121 == day) Name = 'Maifeiertag';
    else if (day == sj + 227) Name = 'Maria Himmelfahrt (BY (nicht überall), SL)';
    else if (day == sj + 276) Name = 'Tag der dt. Einheit';
    else if (day == sj + 304) Name = 'Reformationstag (BB, MV, SA, ST,TH)';
    else if (day == sj + 305) Name = 'Allerheiligen (BW, BY, NW, RP, SL)';
    else if (day == sj + 358) Name = 'Heiligabend';
    else if (day == sj + 359) Name = '1. Weihnachtstag';
    else if (day == sj + 360) Name = '2. Weihnachtstag';
    else if (day == sj + 365) Name = 'Silvester';

    else if (day == ostern - 48) Name = 'Rosenmontag';
    else if (day == ostern -  2) Name = 'Karfreitag';
    else if (day == ostern)      Name = 'Ostersonntag';
    else if (day == ostern +  1) Name = 'Ostermontag';
    else if (day == ostern + 39) Name = 'Christi Himmelfahrt';
    else if (day == ostern + 49) Name = 'Pfingstsonntag';
    else if (day == ostern + 50) Name = 'Pfingstmontag';
    else if (day == ostern + 60) Name = 'Fronleichnam (BW, BY, HE, NW, RP, SL (SA, TH nicht überall))';
    else Name = '';
    return (Name);

}

function tagdesjahresZudatum (day) {
    var day_ms = (day - sj) * 24 * 60 * 60 * 1000;                              // Tag des Jahres in Millisekunden seit Neujahr Mitternacht
    var jetzt = new Date();
    var Jahr = jetzt.getFullYear();
    var neujahr = new Date(Jahr,0,1,0,0,0,0);                                   // Dies Jahr Neujahr Mitternacht
    var neujahr_ms = neujahr.getTime();

    var datum = new Date();
    datum.setTime(neujahr_ms + day_ms);                                         // Addition Neujahr in ms plus Tag des Jahres in ms = gesuchtes Datum in ms
    return(datum);
}

// auf Feiertag testen
function checkHolidays() {
   var jetzt = new Date();
   var Jahr = jetzt.getFullYear();
   sj = (Jahr % 4 === 0) ? 1 : 0;

// Die modifizierte Gauss-Formel nach Lichtenberg, gültig bis 2048
    var A = 120 + (19 * (Jahr % 19) + 24) % 30;
    var B = (A + parseInt(5 * Jahr / 4)) % 7;
    ostern = A - B - 33 + sj;

// Tag des Jahres
   var heutestart = new Date(jetzt.setHours(0,0,0,0));
   var neujahr = new Date(Jahr,0,1);
   var difftage = (heutestart - neujahr) / (24*60*60*1000) + 1;
   var tag = Math.ceil(difftage);

   // heute
   var istFeiertag;
   adapter.setState("heute.Name", {ack: true, val: feiertag(tag)});
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("heute.boolean", {ack: true, val: istFeiertag});

   // morgen
   tag = tag + 1;
   if (tag > 365 + sj) tag = 1;
   adapter.setState("morgen.Name", {ack: true, val: feiertag(tag)});
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("morgen.boolean", {ack: true, val: istFeiertag});

   // übermorgen
   tag = tag + 1;
   if (tag > 365 + sj) tag = 1;
   adapter.setState("uebermorgen.Name", {ack: true, val: feiertag(tag)});
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("uebermorgen.boolean", {ack: true, val: istFeiertag});

   // nächster Feiertag
   var noch = 0;
   tag = tag - 2; // zurück setzen auf heute
   while (feiertag(tag).length < 2) {
       tag = tag + 1;
       noch = noch + 1;
       istFeiertag = (feiertag(tag).length < 2) ? false : true;
       if (istFeiertag) {
           var datum_tdj = tagdesjahresZudatum(tag);
           adapter.setState("naechster.Name", {ack: true, val: feiertag(tag)});

           // Workaround für formatDate
           var next_ft_jahr = datum_tdj.getFullYear();
           var next_ft_monat = ( (datum_tdj.getMonth() + 1) < 10) ? '0' + (datum_tdj.getMonth() + 1) : (datum_tdj.getMonth() + 1);
           var next_ft_tag = ( datum_tdj.getDate() < 10) ? '0' + datum_tdj.getDate() : datum_tdj.getDate();
           var next_ft = next_ft_tag + '.' + next_ft_monat + '.' + next_ft_jahr;
           adapter.log.info('Nächster Feiertag: '  + feiertag(tag) + ' in ' + noch + ' Tagen am ' + next_ft);
           adapter.setState("naechster.Datum", {ack: true, val: next_ft});
           // Ende Workaround

           //adapter.setState("naechster.Datum", formatDate(datum_tdj));
           //adapter.log.info('Nächster Feiertag: '  + feiertag(tag) + ' in ' + noch + ' Tagen am ' + formatDate(datum_tdj));
           adapter.setState("naechster.Dauer", {ack: true, val: noch});
       }
   }
}
<commit_msg>Settings eingearbeitet<commit_after>/* jshint -W097 */// jshint strict:false
/*jslint node: true */

"use strict";

var utils   = require(__dirname + '/lib/utils'); // Get common adapter utils

var channels = [];
var iopkg;

var adapter = utils.adapter({
    name: 'feiertage',
    useFormatDate: true,
    /*
    unload: function (callback) {
        adapter.log.info("adapter feiertage is unloading");
    },
    discover: function (callback) {
        adapter.log.info("adapter feiertage discovered");
    },
    install: function (callback) {
        adapter.log.info("adapter feiertage installed");
    },
    uninstall: function (callback) {
        adapter.log.info("adapter feiertage UN-installed");
    }, */
    ready: function () {
        adapter.log.debug("Adapter feiertage got 'Ready' Signal");
        adapter.log.debug("adapter feiertage initializing objects");
        checkHolidays();
        adapter.log.info("adapter feiertage objects written");

        setTimeout(function () {
            adapter.log.info('force terminating after 4 minutes');
            adapter.stop();
        }, 240000);
    }
});

// Script ermittelt, ob heute oder morgen ein Feiertag ist
var sj;                 // Schaltjahr
var ostern;             // Ostersonntag: Tag im Jahr

// Regional nicht relevante Feiertage auskommentieren oder löschen !!
function feiertag(day) {
    var Name = '';
         if (day == 1        && adapter.config.enable_neujahr)          Name = 'Neujahr';
    else if (day == 6        && adapter.config.enable_dreikoenige)      Name = 'Heilige Drei Könige (BW,BY,ST)';
    else if (sj + 121 == day && adapter.config.enable_maifeiertag)      Name = 'Maifeiertag';
    else if (day == sj + 227 && adapter.config.enable_mhimmelfahrt)     Name = 'Maria Himmelfahrt (BY (nicht überall), SL)';
    else if (day == sj + 276 && adapter.config.enable_einheitstag)      Name = 'Tag der dt. Einheit';
    else if (day == sj + 304 && adapter.config.enable_reformationstag)  Name = 'Reformationstag (BB, MV, SA, ST,TH)';
    else if (day == sj + 305 && adapter.config.enable_allerheiligen)    Name = 'Allerheiligen (BW, BY, NW, RP, SL)';
    else if (day == sj + 358 && adapter.config.enable_heiligabend)      Name = 'Heiligabend';
    else if (day == sj + 359 && adapter.config.enable_weihnachtstag1)   Name = '1. Weihnachtstag';
    else if (day == sj + 360 && adapter.config.enable_weihnachtstag2)   Name = '2. Weihnachtstag';
    else if (day == sj + 365 && adapter.config.enable_silvester)        Name = 'Silvester';

    else if (day == ostern - 48 && adapter.config.enable_rosenmontag)    Name = 'Rosenmontag';
    else if (day == ostern -  2 && adapter.config.enable_karfreitag)     Name = 'Karfreitag';
    else if (day == ostern      && adapter.config.enable_ostersonntag)   Name = 'Ostersonntag';
    else if (day == ostern +  1 && adapter.config.enable_ostermontag)    Name = 'Ostermontag';
    else if (day == ostern + 39 && adapter.config.enable_chimmelfahrt)   Name = 'Christi Himmelfahrt';
    else if (day == ostern + 49 && adapter.config.enable_pfingstsonntag) Name = 'Pfingstsonntag';
    else if (day == ostern + 50 && adapter.config.enable_pfingstmontag)  Name = 'Pfingstmontag';
    else if (day == ostern + 60 && adapter.config.enable_fronleichnam)   Name = 'Fronleichnam (BW, BY, HE, NW, RP, SL (SA, TH nicht überall))';
    else Name = '';
    return (Name);

}

function tagdesjahresZudatum (day) {
    var day_ms = (day - sj) * 24 * 60 * 60 * 1000;                              // Tag des Jahres in Millisekunden seit Neujahr Mitternacht
    var jetzt = new Date();
    var Jahr = jetzt.getFullYear();
    var neujahr = new Date(Jahr,0,1,0,0,0,0);                                   // Dies Jahr Neujahr Mitternacht
    var neujahr_ms = neujahr.getTime();

    var datum = new Date();
    datum.setTime(neujahr_ms + day_ms);                                         // Addition Neujahr in ms plus Tag des Jahres in ms = gesuchtes Datum in ms
    return(datum);
}

// auf Feiertag testen
function checkHolidays() {
   var jetzt = new Date();
   var Jahr = jetzt.getFullYear();
   sj = (Jahr % 4 === 0) ? 1 : 0;

// Die modifizierte Gauss-Formel nach Lichtenberg, gültig bis 2048
    var A = 120 + (19 * (Jahr % 19) + 24) % 30;
    var B = (A + parseInt(5 * Jahr / 4)) % 7;
    ostern = A - B - 33 + sj;

// Tag des Jahres
   var heutestart = new Date(jetzt.setHours(0,0,0,0));
   var neujahr = new Date(Jahr,0,1);
   var difftage = (heutestart - neujahr) / (24*60*60*1000) + 1;
   var tag = Math.ceil(difftage);

   // heute
   var istFeiertag;
   adapter.setState("heute.Name", {ack: true, val: feiertag(tag)});
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("heute.boolean", {ack: true, val: istFeiertag});

   // morgen
   tag = tag + 1;
   if (tag > 365 + sj) tag = 1;
   adapter.setState("morgen.Name", {ack: true, val: feiertag(tag)});
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("morgen.boolean", {ack: true, val: istFeiertag});

   // übermorgen
   tag = tag + 1;
   if (tag > 365 + sj) tag = 1;
   adapter.setState("uebermorgen.Name", {ack: true, val: feiertag(tag)});
   istFeiertag = (feiertag(tag).length < 2) ? false : true;
   adapter.setState("uebermorgen.boolean", {ack: true, val: istFeiertag});

   // nächster Feiertag
   var noch = 0;
   tag = tag - 2; // zurück setzen auf heute
   while (feiertag(tag).length < 2) {
       tag = tag + 1;
       noch = noch + 1;
       istFeiertag = (feiertag(tag).length < 2) ? false : true;
       if (istFeiertag) {
           var datum_tdj = tagdesjahresZudatum(tag);
           adapter.setState("naechster.Name", {ack: true, val: feiertag(tag)});

           // Workaround für formatDate
           var next_ft_jahr = datum_tdj.getFullYear();
           var next_ft_monat = ( (datum_tdj.getMonth() + 1) < 10) ? '0' + (datum_tdj.getMonth() + 1) : (datum_tdj.getMonth() + 1);
           var next_ft_tag = ( datum_tdj.getDate() < 10) ? '0' + datum_tdj.getDate() : datum_tdj.getDate();
           var next_ft = next_ft_tag + '.' + next_ft_monat + '.' + next_ft_jahr;
           adapter.log.info('Nächster Feiertag: '  + feiertag(tag) + ' in ' + noch + ' Tagen am ' + next_ft);
           adapter.setState("naechster.Datum", {ack: true, val: next_ft});
           // Ende Workaround

           //adapter.setState("naechster.Datum", formatDate(datum_tdj));
           //adapter.log.info('Nächster Feiertag: '  + feiertag(tag) + ' in ' + noch + ' Tagen am ' + formatDate(datum_tdj));
           adapter.setState("naechster.Dauer", {ack: true, val: noch});
       }
   }
}
<|endoftext|>


<commit_before>/**
 * Function composer
 * https://github.com/josdejong/function-composer
 */
(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define([], factory);
  } else if (typeof exports === 'object') {
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like environments that support module.exports,
    // like Node.
    module.exports = factory();
  } else {
    // Browser globals (root is window)
    root.compose = factory();
  }
}(this, function () {
  'use strict';

  // order types
  // anytype (*) will be ordered last, and then object, as other types may be
  // an object too.
  function compareTypes(a, b) {
    if (a === '*') return 1;
    if (b === '*') return -1;

    if (a === 'Object') return 1;
    if (b === 'Object') return -1;

    return 0;
  }

  // order numbers
  function compareNumbers(a, b) {
    return a > b;
  }

  /**
   * Collection with function definitions (local shortcuts to functions)
   * @constructor
   */
  function Defs() {}

  /**
   * Add a function definition.
   * @param {function} fn
   * @param {string} [type='fn']
   * @returns {string} Returns the function name, for example 'fn0' or 'signature2'
   */
  Defs.prototype.add = function (fn, type) {
    type = type || 'fn';
    if (!this[type]) this[type] = [];

    var index = this[type].indexOf(fn);
    if (index == -1) {
      index = this[type].length;
      this[type].push(fn);
    }
    return type + index;
  };

  /**
   * Create code lines for all definitions
   * @param [name='defs']
   * @returns {Array} Returns the code lines containing all function definitions
   */
  Defs.prototype.code = function (name) {
    var me = this;
    var code = [];
    name = name || 'defs';

    Object.keys(this).forEach(function (type) {
      var def = me[type];
      def.forEach(function (def, index) {
        code.push('var ' + type + index + ' = ' + name + '[\'' + type + '\'][' + index + '];');
      });
    });

    return code;
  };

  /**
   * split all raw signatures into an array with splitted params
   * @param {Object.<string, function>} rawSignatures
   * @return {Array.<{params: Array.<string>, fn: function}>} Returns splitted signatures
   */
  function splitSignatures(rawSignatures) {
    return Object.keys(rawSignatures).map(function (rawSignature) {
      var fn = rawSignatures[rawSignature];
      var params = (rawSignature !== '') ? rawSignature.split(',').map(function (param) {
        return param.trim();
      }) : [];

      return {
        fn: fn,
        params: params
      };
    });

    // TODO: split params containing an '|' into multiple entries
  }

  /**
   * create a map with normalized signatures as key and the function as value
   * @param {Array.<{params: Array.<string>, fn: function}>} signatures   An array with splitted signatures
   * @return {{}} Returns a map with normalized signatures
   */
  function normalizeSignatures(signatures) {
    var normalized = {};

    signatures.map(function (entry) {
      var signature = entry.params.join(',');
      if (signature in normalized) {
        throw new Error('Error: signature "' + signature + '" defined twice');
      }
      normalized[signature] = entry.fn;
    });

    return normalized
  }

  /**
   * create an array with for every parameter an array with possible types
   * @param {Array.<{params: Array.<string>, fn: function}>} signatures   An array with splitted signatures
   * @return {Array.<Array.<string>>} Returns an array with allowed types per parameter
   */
  function splitTypes(signatures) {
    var types = [];

    signatures.forEach(function (entry) {
      entry.params.forEach(function (param, i) {
        if (!types[i]) {
          types[i] = [];
        }
        if (types[i].indexOf(param) == -1) {
          types[i].push(param);
        }
      });
    });

    return types;
  }

  /**
   * create a recursive tree for traversing the number and type of arguments
   * @param {Array.<{params: Array.<string>, fn: function}>} signatures   An array with splitted signatures
   * @returns {{}}
   */
  function createArgumentsTree(signatures) {
    var tree = {};

    signatures.forEach(function (entry) {
      var params = entry.params.concat([]);

      // get the tree entry for the current number of arguments
      var obj = tree[params.length];
      if (!obj) {
        obj = tree[params.length] = {
          signature: [],
          fn: null,
          types: {}
        };
      }

      // loop over all parameters, create a nested structure
      while(params.length > 0) {
        var param = params.shift();
        if (!obj.types[param]) {
          obj.types[param] = {
            signature: obj.signature.concat(param),
            fn: null,
            types: {}
          };
        }
        obj = obj.types[param];
      }

      // add the function as leaf
      obj.fn = entry.fn;
    });

    return tree;
  }

  /**
   * Compose a function from sub-functions each handling a single type signature.
   * @param {string} [name]  An optional name for the function
   * @param {Object.<string, function>} signatures
   *            A map with the type signature as key and the sub-function as value
   * @return {function} Returns the composed function
   */
  function compose(name, signatures) {
    // handle arguments
    if (!signatures) {
      signatures = name;
      name = null;
    }

    var defs = new Defs();
    var structure = splitSignatures(signatures);

    function switchTypes(signature, args, prefix) {
      var code = [];

      if (signature.fn !== null) {
        var def = defs.add(signature.fn, 'signature');
        code.push(prefix + 'return ' + def + '(' + args.join(', ') +'); // signature: ' + signature.signature);
      }
      else {
        // add entries for the provided types
        Object.keys(signature.types)
            .sort(compareTypes)
            .forEach(function (type, index) {
              var arg = 'arg' + args.length;

              var before;
              var after;
              var nextPrefix = prefix + '  ';
              if (type == '*') {
                before = (index > 0 ? 'else {' : '');
                after  = (index > 0 ? '}' : '');
                if (index == 0) {nextPrefix = prefix;}
              }
              else {
                var def = defs.add(getTest(type), 'test') + '(' + arg + ')';
                before = 'if (' + def + ') { // type: ' + type;
                after  = '}';
              }

              if (before) code.push(prefix + before);
              code = code.concat(switchTypes(signature.types[type], args.concat(arg), nextPrefix));
              if (after) code.push(prefix + after);
            });

        // add entries for type conversions
        var added = {};
        compose.conversions
            .filter(function (conversion) {
              return signature.types[conversion.to] &&
                  !signature.types[conversion.from];
            })
            .forEach(function (conversion) {
              if (!added[conversion.from]) {
                added[conversion.from] = true;

                var arg = 'arg' + args.length;
                var test = defs.add(getTest(conversion.from), 'test') + '(' + arg + ')';
                var convert = defs.add(conversion.convert, 'convert') + '(' + arg + ')';

                code.push(prefix + 'if (' + test + ') { // type: ' + conversion.from + ', convert to ' + conversion.to);
                code = code.concat(switchTypes(signature.types[conversion.to], args.concat(convert), prefix + '  '));
                code.push(prefix + '}');
              }
            });
      }

      return code;
    }

    var types = splitTypes(structure);
    var params = [];
    for (var i = 0; i < types.length; i++) { // we can't use .map here, some entries may be undefined
      params.push('arg' + i);
    }

    var code = [];
    var tree = createArgumentsTree(structure);
    var paramCounts = Object.keys(tree);
    code.push('return function ' + (name || '') + '(' + params.join(', ') + ') {');
    paramCounts
        .sort(compareNumbers)
        .forEach(function (count, index) {
          var signature = tree[count];
          var args = [];
          var statement = (index == 0) ? 'if' : 'else if';
          code.push('  ' + statement + ' (arguments.length == ' + count +  ') {');
          code = code.concat(switchTypes(signature, args, '    '));

          code.push('  }');
          if (index == paramCounts.length - 1) {
            code.push('  else {');
            code.push('    throw new TypeError(\'Wrong number of arguments\');'); // TODO: output the allowed numbers
            code.push('  }');
          }
        });
    code.push('  throw new TypeError(\'Wrong function signature\');');  // TODO: output the actual signature
    code.push('}');

    var factory = [];
    factory.push('(function (defs) {');
    factory = factory.concat(defs.code('defs'));
    factory = factory.concat(code);
    factory.push('})');

    var fn = eval(factory.join('\n'))(defs);

    // attach the signatures with sub-functions to the constructed function
    fn.signatures = normalizeSignatures(structure); // normalized signatures

    return fn;
  }

  // data type tests
  compose.types = {
    'null':     function (x) {return x === null},
    'boolean':  function (x) {return typeof x === 'boolean'},
    'number':   function (x) {return typeof x === 'number'},
    'string':   function (x) {return typeof x === 'string'},
    'function': function (x) {return typeof x === 'function'},
    'Array':    function (x) {return Array.isArray(x)},
    'Date':     function (x) {return x instanceof Date},
    'RegExp':   function (x) {return x instanceof RegExp},
    'Object':   function (x) {return typeof x === 'object'}
  };

  function getTest(type) {
    var test = compose.types[type];
    if (!test) {
      var matches = Object.keys(compose.types)
          .filter(function (t) {
            return t.toLowerCase() == type.toLowerCase();
          })
          .map(function (t) {
            return '"' + t + '"';
          });
      throw new Error('Unknown type "' + type + '"' +
      (matches.length ? ('. Did you mean ' + matches.join(', or ') + '?') : ''));
    }
    return test;
  }

  // type conversions
  // order is important
  compose.conversions = [];

  return compose;
}));

<commit_msg>Created prototype Signature (needed later on)<commit_after>/**
 * Function composer
 * https://github.com/josdejong/function-composer
 */
(function (root, factory) {
  if (typeof define === 'function' && define.amd) {
    // AMD. Register as an anonymous module.
    define([], factory);
  } else if (typeof exports === 'object') {
    // Node. Does not work with strict CommonJS, but
    // only CommonJS-like environments that support module.exports,
    // like Node.
    module.exports = factory();
  } else {
    // Browser globals (root is window)
    root.compose = factory();
  }
}(this, function () {
  'use strict';

  // order types
  // anytype (*) will be ordered last, and then object, as other types may be
  // an object too.
  function compareTypes(a, b) {
    if (a === '*') return 1;
    if (b === '*') return -1;

    if (a === 'Object') return 1;
    if (b === 'Object') return -1;

    return 0;
  }

  // order numbers
  function compareNumbers(a, b) {
    return a > b;
  }

  /**
   * Collection with function definitions (local shortcuts to functions)
   * @constructor
   */
  function Defs() {}

  /**
   * Add a function definition.
   * @param {function} fn
   * @param {string} [type='fn']
   * @returns {string} Returns the function name, for example 'fn0' or 'signature2'
   */
  Defs.prototype.add = function (fn, type) {
    type = type || 'fn';
    if (!this[type]) this[type] = [];

    var index = this[type].indexOf(fn);
    if (index == -1) {
      index = this[type].length;
      this[type].push(fn);
    }
    return type + index;
  };

  /**
   * Create code lines for all definitions
   * @param [name='defs']
   * @returns {Array} Returns the code lines containing all function definitions
   */
  Defs.prototype.code = function (name) {
    var me = this;
    var code = [];
    name = name || 'defs';

    Object.keys(this).forEach(function (type) {
      var def = me[type];
      def.forEach(function (def, index) {
        code.push('var ' + type + index + ' = ' + name + '[\'' + type + '\'][' + index + '];');
      });
    });

    return code;
  };

  /**
   * A function signature
   * @param {string | Array.<string>} params  Array with the type(s) of each parameter,
   *                                          or a comma separated string with types
   * @param {function} fn                     The actual function
   * @constructor
   */
  function Signature(params, fn) {
    if (typeof params === 'string') {
      this.params = (params !== '') ? params.split(',').map(function (param) {
        return param.trim();
      }) : [];
    }
    else {
      this.params = params;
    }
    this.fn = fn;
  }

  // TODO: implement function Signature.split
  // TODO: implement function Signature.merge
  // TODO: implement function Signature.toString

  /**
   * split all raw signatures into an array with splitted params
   * @param {Object.<string, function>} rawSignatures
   * @return {Array.<{params: Array.<string>, fn: function}>} Returns splitted signatures
   */
  function splitSignatures(rawSignatures) {
    return Object.keys(rawSignatures).map(function (params) {
      var fn = rawSignatures[params];
      return new Signature(params, fn);
    });

    // TODO: split params containing an '|' into multiple entries
  }

  /**
   * create a map with normalized signatures as key and the function as value
   * @param {Array.<{params: Array.<string>, fn: function}>} signatures   An array with splitted signatures
   * @return {{}} Returns a map with normalized signatures
   */
  function normalizeSignatures(signatures) {
    var normalized = {};

    signatures.map(function (entry) {
      var signature = entry.params.join(',');
      if (signature in normalized) {
        throw new Error('Error: signature "' + signature + '" defined twice');
      }
      normalized[signature] = entry.fn;
    });

    return normalized
  }

  /**
   * create an array with for every parameter an array with possible types
   * @param {Array.<{params: Array.<string>, fn: function}>} signatures   An array with splitted signatures
   * @return {Array.<Array.<string>>} Returns an array with allowed types per parameter
   */
  function splitTypes(signatures) {
    var types = [];

    signatures.forEach(function (entry) {
      entry.params.forEach(function (param, i) {
        if (!types[i]) {
          types[i] = [];
        }
        if (types[i].indexOf(param) == -1) {
          types[i].push(param);
        }
      });
    });

    return types;
  }

  /**
   * create a recursive tree for traversing the number and type of parameters
   * @param {Array.<{params: Array.<string>, fn: function}>} signatures   An array with splitted signatures
   * @returns {{}}
   */
  function createParamsTree(signatures) {
    var tree = {};

    signatures.forEach(function (entry) {
      var params = entry.params.concat([]);

      // get the tree entry for the current number of arguments
      var obj = tree[params.length];
      if (!obj) {
        obj = tree[params.length] = {
          signature: [],
          fn: null,
          types: {}
        };
      }

      // loop over all parameters, create a nested structure
      while(params.length > 0) {
        var param = params.shift();
        if (!obj.types[param]) {
          obj.types[param] = {
            signature: obj.signature.concat(param),
            fn: null,
            types: {}
          };
        }
        obj = obj.types[param];
      }

      // add the function as leaf
      obj.fn = entry.fn;
    });

    return tree;
  }

  /**
   * Compose a function from sub-functions each handling a single type signature.
   * @param {string} [name]  An optional name for the function
   * @param {Object.<string, function>} signatures
   *            A map with the type signature as key and the sub-function as value
   * @return {function} Returns the composed function
   */
  function compose(name, signatures) {
    // handle arguments
    if (!signatures) {
      signatures = name;
      name = null;
    }

    var defs = new Defs();
    var structure = splitSignatures(signatures);

    function switchTypes(signature, args, prefix) {
      var code = [];

      if (signature.fn !== null) {
        var def = defs.add(signature.fn, 'signature');
        code.push(prefix + 'return ' + def + '(' + args.join(', ') +'); // signature: ' + signature.signature);
      }
      else {
        // add entries for the provided types
        Object.keys(signature.types)
            .sort(compareTypes)
            .forEach(function (type, index) {
              var arg = 'arg' + args.length;

              var before;
              var after;
              var nextPrefix = prefix + '  ';
              if (type == '*') {
                before = (index > 0 ? 'else {' : '');
                after  = (index > 0 ? '}' : '');
                if (index == 0) {nextPrefix = prefix;}
              }
              else {
                var def = defs.add(getTest(type), 'test') + '(' + arg + ')';
                before = 'if (' + def + ') { // type: ' + type;
                after  = '}';
              }

              if (before) code.push(prefix + before);
              code = code.concat(switchTypes(signature.types[type], args.concat(arg), nextPrefix));
              if (after) code.push(prefix + after);
            });

        // add entries for type conversions
        var added = {};
        compose.conversions
            .filter(function (conversion) {
              return signature.types[conversion.to] &&
                  !signature.types[conversion.from];
            })
            .forEach(function (conversion) {
              if (!added[conversion.from]) {
                added[conversion.from] = true;

                var arg = 'arg' + args.length;
                var test = defs.add(getTest(conversion.from), 'test') + '(' + arg + ')';
                var convert = defs.add(conversion.convert, 'convert') + '(' + arg + ')';

                code.push(prefix + 'if (' + test + ') { // type: ' + conversion.from + ', convert to ' + conversion.to);
                code = code.concat(switchTypes(signature.types[conversion.to], args.concat(convert), prefix + '  '));
                code.push(prefix + '}');
              }
            });
      }

      return code;
    }

    var types = splitTypes(structure);
    var params = [];
    for (var i = 0; i < types.length; i++) { // we can't use .map here, some entries may be undefined
      params.push('arg' + i);
    }

    var code = [];
    var tree = createParamsTree(structure);
    var paramCounts = Object.keys(tree);
    code.push('return function ' + (name || '') + '(' + params.join(', ') + ') {');
    paramCounts
        .sort(compareNumbers)
        .forEach(function (count, index) {
          var signature = tree[count];
          var args = [];
          var statement = (index == 0) ? 'if' : 'else if';
          code.push('  ' + statement + ' (arguments.length == ' + count +  ') {');
          code = code.concat(switchTypes(signature, args, '    '));

          code.push('  }');
          if (index == paramCounts.length - 1) {
            code.push('  else {');
            code.push('    throw new TypeError(\'Wrong number of arguments\');'); // TODO: output the allowed numbers
            code.push('  }');
          }
        });
    code.push('  throw new TypeError(\'Wrong function signature\');');  // TODO: output the actual signature
    code.push('}');

    var factory = [];
    factory.push('(function (defs) {');
    factory = factory.concat(defs.code('defs'));
    factory = factory.concat(code);
    factory.push('})');

    var fn = eval(factory.join('\n'))(defs);

    // attach the signatures with sub-functions to the constructed function
    fn.signatures = normalizeSignatures(structure); // normalized signatures

    return fn;
  }

  // data type tests
  compose.types = {
    'null':     function (x) {return x === null},
    'boolean':  function (x) {return typeof x === 'boolean'},
    'number':   function (x) {return typeof x === 'number'},
    'string':   function (x) {return typeof x === 'string'},
    'function': function (x) {return typeof x === 'function'},
    'Array':    function (x) {return Array.isArray(x)},
    'Date':     function (x) {return x instanceof Date},
    'RegExp':   function (x) {return x instanceof RegExp},
    'Object':   function (x) {return typeof x === 'object'}
  };

  function getTest(type) {
    var test = compose.types[type];
    if (!test) {
      var matches = Object.keys(compose.types)
          .filter(function (t) {
            return t.toLowerCase() == type.toLowerCase();
          })
          .map(function (t) {
            return '"' + t + '"';
          });
      throw new Error('Unknown type "' + type + '"' +
      (matches.length ? ('. Did you mean ' + matches.join(', or ') + '?') : ''));
    }
    return test;
  }

  // type conversions
  // order is important
  compose.conversions = [];

  return compose;
}));

<|endoftext|>


<commit_before>var html = require('choo/html')
var header = require('./header')

function layout (state, emit, view) {
  return html`

fruitful.js

        ${header(state, emit)}

        ${view()}

  `
}

module.exports = layout
<commit_msg>add a footer<commit_after>var html = require('choo/html')
var header = require('./header')

function layout (state, emit, view) {
  return html`

fruitful.js

        ${header(state, emit)}

        ${view()}

          You can improve this website on GitHub.
          Built with choo and love.

  `
}

module.exports = layout
<|endoftext|>


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

var test = require('util/test');
var log = require('util/log');

var async = require('extern/async');

var tcp_check = require('health/checks/tcp');
var CheckResult = require('health').CheckResult;
var CheckStatus = require('health').CheckStatus;

var response_dictionary = {
  'hello': {
    'type': 'string',
    'response': 'Hello World\nTesting server'
  },
  'stats': {
    'type': 'string',
    'response': 'KEYS 5\nKEYSIZE 2058\nEND'
  }
};

exports['test invalid ip address'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;
  var check = new tcp_check.TCPCheck({'ip_address': '999.99.99.99', 'port': port, 'type': tcp_check.config.types.CONNECTION_CHECK,
                                     'idle_timeout': 2000});

  check.run(function(result) {
    n++;
    assert.equal(result.status, CheckStatus.ERROR);
    assert.match(result.details, /domain name not found/i);
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};

exports['test check connection failure'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;
  var check = new tcp_check.TCPCheck({'ip_address': '127.0.0.1', 'port': port, 'type': tcp_check.config.types.CONNECTION_CHECK});

  check.run(function(result) {
    n++;
    assert.equal(result.status, CheckStatus.ERROR);
    assert.match(result.details, /(connection refused|connection timed out|ETIMEDOUT)/i);
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};

exports['test check connection timeout'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;
  var check = new tcp_check.TCPCheck({'ip_address': '74.125.39.104', 'port': port, 'type': tcp_check.config.types.CONNECTION_CHECK,
                                      'connect_timeout': 2000});

  check.run(function(result) {
    n++;
    assert.equal(result.status, CheckStatus.ERROR);
    assert.match(result.details, /connection timed out/i);
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};

exports['test check connection success'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;

  test.run_test_tcp_server('127.0.0.1', port, response_dictionary, true, function() {
    var self = this;
    var check = new tcp_check.TCPCheck({'ip_address': '127.0.0.1', 'port': port, 'type': tcp_check.config.types.CONNECTION_CHECK});

    check.run(function(result) {
      n++;
      assert.equal(result.status, CheckStatus.SUCCESS);
      assert.match(result.details, /established connection to /i);

      self.close();
    });
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};

exports['test check response regex match error'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;

  var tcp_server = test.run_test_tcp_server('127.0.0.1', port, response_dictionary, true, function() {
    var self = this;
    var check = new tcp_check.TCPCheck({'ip_address': '127.0.0.1', 'port': port, 'type': tcp_check.config.types.RESPONSE_REGEX_MATCH,
                                        'match_value': /blah/i});

    check.run(function(result) {
      n++;
      assert.equal(result.status, CheckStatus.ERROR);
      assert.match(result.details, /didn.?t match the regular/i);

      self.close();
    });
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};

exports['test check response regex match success'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;

  test.run_test_tcp_server('127.0.0.1', port, response_dictionary, true, function() {
    var self = this;
    var check = new tcp_check.TCPCheck({'ip_address': '127.0.0.1', 'port': port, 'type': tcp_check.config.types.RESPONSE_REGEX_MATCH,
                                       'command': 'hello', 'match_value': /.*hello world.*/i});

    check.run(function(result) {
      n++;
      assert.equal(result.status, CheckStatus.SUCCESS);
      assert.match(result.details, /matched the regular/i);

      self.close();
    });
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};
<commit_msg>Add another test for TCP check.<commit_after>/*
 * Licensed to Cloudkick, Inc ('Cloudkick') under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * Cloudkick licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var test = require('util/test');
var log = require('util/log');

var async = require('extern/async');
var sprintf = require('extern/sprintf').sprintf;

var tcp_check = require('health/checks/tcp');
var CheckResult = require('health').CheckResult;
var CheckStatus = require('health').CheckStatus;

var response_dictionary = {
  'hello': {
    'type': 'string',
    'response': 'Hello World\nTesting server'
  },
  'stats (\\d+)': {
    'type': 'regexp',
    'response': function(matches) { return sprintf('KEYS %s\nEND', matches[1]); }
  }
};

exports['test invalid ip address'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;
  var check = new tcp_check.TCPCheck({'ip_address': '999.99.99.99', 'port': port, 'type': tcp_check.config.types.CONNECTION_CHECK,
                                     'idle_timeout': 2000});

  check.run(function(result) {
    n++;
    assert.equal(result.status, CheckStatus.ERROR);
    assert.match(result.details, /domain name not found/i);
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};

exports['test check connection failure'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;
  var check = new tcp_check.TCPCheck({'ip_address': '127.0.0.1', 'port': port, 'type': tcp_check.config.types.CONNECTION_CHECK});

  check.run(function(result) {
    n++;
    assert.equal(result.status, CheckStatus.ERROR);
    assert.match(result.details, /(connection refused|connection timed out|ETIMEDOUT)/i);
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};

exports['test check connection timeout'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;
  var check = new tcp_check.TCPCheck({'ip_address': '74.125.39.104', 'port': port, 'type': tcp_check.config.types.CONNECTION_CHECK,
                                      'connect_timeout': 2000});

  check.run(function(result) {
    n++;
    assert.equal(result.status, CheckStatus.ERROR);
    assert.match(result.details, /connection timed out/i);
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};

exports['test check connection success'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;

  test.run_test_tcp_server('127.0.0.1', port, response_dictionary, true, function() {
    var self = this;
    var check = new tcp_check.TCPCheck({'ip_address': '127.0.0.1', 'port': port, 'type': tcp_check.config.types.CONNECTION_CHECK});

    check.run(function(result) {
      n++;
      assert.equal(result.status, CheckStatus.SUCCESS);
      assert.match(result.details, /established connection to /i);

      self.close();
    });
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};

exports['test check response regex match error'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;

  var tcp_server = test.run_test_tcp_server('127.0.0.1', port, response_dictionary, true, function() {
    var self = this;
    var check = new tcp_check.TCPCheck({'ip_address': '127.0.0.1', 'port': port, 'type': tcp_check.config.types.RESPONSE_REGEX_MATCH,
                                        'match_value': /blah/i});

    check.run(function(result) {
      n++;
      assert.equal(result.status, CheckStatus.ERROR);
      assert.match(result.details, /didn.?t match the regular/i);

      self.close();
    });
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};

exports['test check response regex match success 1'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;

  test.run_test_tcp_server('127.0.0.1', port, response_dictionary, true, function() {
    var self = this;
    var check = new tcp_check.TCPCheck({'ip_address': '127.0.0.1', 'port': port, 'type': tcp_check.config.types.RESPONSE_REGEX_MATCH,
                                       'command': 'hello', 'match_value': /.*hello world.*/i});

    check.run(function(result) {
      n++;
      assert.equal(result.status, CheckStatus.SUCCESS);
      assert.match(result.details, /matched the regular/i);

      self.close();
    });
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};

exports['test check response regex match success 2'] = function(assert, beforeExit) {
  var port = test.get_port();
  var n = 0;

  test.run_test_tcp_server('127.0.0.1', port, response_dictionary, true, function() {
    var self = this;
    var check = new tcp_check.TCPCheck({'ip_address': '127.0.0.1', 'port': port, 'type': tcp_check.config.types.RESPONSE_REGEX_MATCH,
                                       'command': 'stats 12345', 'match_value': /.*keys 12345.*/i});

    check.run(function(result) {
      n++;
      assert.equal(result.status, CheckStatus.SUCCESS);
      assert.match(result.details, /matched the regular/i);

      self.close();
    });
  });

  beforeExit(function() {
    assert.equal(1, n, 'Check run callback called');
  });
};
<|endoftext|>


<commit_before>import chai from 'chai';
import nock from 'nock';
import path from 'path';

import images from '../../src/commands/fun/images';

chai.should();
const res_fixture_cat = require(path.join(__dirname, '../fixtures/cat.json'));
const res_fixture_pug = require(path.join(__dirname, '../fixtures/pug.json'));
const res_fixture_snake = require(path.join(__dirname, '../fixtures/snake.json'));
const res_fixture_pugbomb = require(path.join(__dirname, '../fixtures/pugbomb.json'));

describe('images', () => {
  describe('cat', () => {
    it('should return cat images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal('http://random.cat/i/7VnxKqw.jpg');
        done();
      }

      nock.cleanAll();
      nock('http://random.cat')
        .get('/meow.php')
        .reply(200, res_fixture_cat);

      images.cat({sendMessage}, {channel: 'test'});
    });

    it('should return 5 cat images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal(`http://random.cat/i/7VnxKqw.jpg
http://random.cat/i/7VnxKqw.jpg
http://random.cat/i/7VnxKqw.jpg
http://random.cat/i/7VnxKqw.jpg
http://random.cat/i/7VnxKqw.jpg`);
        done();
      }

      nock.cleanAll();
      nock('http://random.cat')
        .get('/meow.php')
        .times(5)
        .reply(200, res_fixture_cat);

      images.cat({sendMessage}, {channel: 'test'}, 'bomb 5');
    });
  });

  describe('pug', () => {
    it('should return pug images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal(`http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg`);
        done();
      }

      nock.cleanAll();
      nock('https://pugme.herokuapp.com')
        .get('/bomb?count=1')
        .reply(200, res_fixture_pug);

      images.pug({sendMessage}, {channel: 'test'});
    });

    it('should return 5 pug images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal(`http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg
http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg
http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg
http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg
http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg`);
        done();
      }

      nock.cleanAll();
      nock('https://pugme.herokuapp.com')
        .get('/bomb?count=5')
        .reply(200, res_fixture_pugbomb);

      images.pug({sendMessage}, {channel: 'test'}, 'bomb 5');
    });
  });

  describe('snake', () => {
    it('should return snake images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal('http://fur.im/snek/61.png');
        done();
      }

      nock.cleanAll();
      nock('http://fur.im/snek')
        .get('/snek.php')
        .reply(200, res_fixture_snake);

      images.snake({sendMessage}, {channel: 'test'});
    });

    it('should return 5 snake images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal(`http://fur.im/snek/61.png
http://fur.im/snek/61.png
http://fur.im/snek/61.png
http://fur.im/snek/61.png
http://fur.im/snek/61.png`);
        done();
      }

      nock.cleanAll();
      nock('http://fur.im/snek')
        .get('/snek.php')
        .times(5)
        .reply(200, res_fixture_snake);

      images.snake({sendMessage}, {channel: 'test'}, 'bomb 5');
    });
  });
});
<commit_msg>Update images.js<commit_after>import chai from 'chai';
import nock from 'nock';
import path from 'path';

import images from '../../src/commands/fun/images';

chai.should();
const res_fixture_cat = require(path.join(__dirname, '../fixtures/cat.json'));
const res_fixture_pug = require(path.join(__dirname, '../fixtures/pug.json'));
const res_fixture_snake = require(path.join(__dirname, '../fixtures/snake.json'));
const res_fixture_pugbomb = require(path.join(__dirname, '../fixtures/pugbomb.json'));

describe('images', () => {
  describe('cat', () => {
    it('should return cat images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal('http://random.cat/i/7VnxKqw.jpg');
        done();
      }

      nock.cleanAll();
      nock('http://random.cat')
        .get('/meow.php')
        .reply(200, res_fixture_cat);

      images.cat({sendMessage}, {channel: 'test'});
    });

    it('should return 5 cat images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal(`http://random.cat/i/7VnxKqw.jpg
http://random.cat/i/7VnxKqw.jpg
http://random.cat/i/7VnxKqw.jpg
http://random.cat/i/7VnxKqw.jpg
http://random.cat/i/7VnxKqw.jpg`);
        done();
      }

      nock.cleanAll();
      nock('http://random.cat')
        .get('/meow.php')
        .times(5)
        .reply(200, res_fixture_cat);

      images.cat({sendMessage}, {channel: 'test'}, 'bomb 5');
    });
  });

  describe('pug', () => {
    it('should return pug images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal(`http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg`);
        done();
      }

      nock.cleanAll();
      nock('https://pugme.herokuapp.com')
        .get('/bomb?count=1')
        .reply(200, res_fixture_pug);

      images.pug({sendMessage}, {channel: 'test'});
    });

    it('should return 5 pug images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal(`http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg
http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg
http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg
http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg
http://30.media.tumblr.com/tumblr_lj50gs8rAX1qaa50yo1_500.jpg`);
        done();
      }

      nock.cleanAll();
      nock('https://pugme.herokuapp.com')
        .get('/bomb?count=5')
        .reply(200, res_fixture_pugbomb);

      images.pug({sendMessage}, {channel: 'test'}, 'bomb 5');
    });
  });

  describe('snake', () => {
    it('should return snake images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal('http://fur.im/snek/61.png');
        done();
      }

      nock.cleanAll();
      nock('http://fur.im/snek')
        .get('/snek.php')
        .reply(200, res_fixture_snake);

      images.snake({sendMessage}, {channel: 'test'});
    });

    it('should return 5 snake images', done => {
      function sendMessage(channel, res) {
        channel.should.equal('test');
        res.should.equal(`http://fur.im/snek/61.png
http://fur.im/snek/61.png
http://fur.im/snek/61.png
http://fur.im/snek/61.png
http://fur.im/snek/61.png`);
        done();
      }

      nock.cleanAll();
      nock('http://fur.im/snek')
        .get('/snek.php')
        .times(5)
        .reply(200, res_fixture_snake);

      images.snake({sendMessage}, {channel: 'test'}, 'bomb 5');
    });
  });
});
<|endoftext|>


<commit_before>(function(e,t){if(typeof exports==="object"){module.exports=t(require("moment"))}else if(typeof define==="function"&&define.amd){define("moment-range",["moment"],t)}else{e.moment=t(e.moment)}})(this,function(e){var t,n;n={year:true,month:true,week:true,day:true,hour:true,minute:true,second:true};t=function(){function t(t,n){this.start=e(t);this.end=e(n)}t.prototype.contains=function(e){if(e instanceof t){return this.start<=e.start&&this.end>=e.end}else{return this.start<=e&&e<=this.end}};t.prototype._by_string=function(t,n){var r,i;r=e(this.start);i=[];while(this.contains(r)){n.call(this,r.clone());i.push(r.add(t,1))}return i};t.prototype._by_range=function(t,n){var r,i,s,o;i=Math.round(this/t);if(i===Infinity){return this}o=[];for(r=s=0;0<=i?s<=i:s>=i;r=0<=i?++s:--s){o.push(n.call(this,e(this.start.valueOf()+t.valueOf()*r)))}return o};t.prototype.overlaps=function(e){return this.intersect(e)!==null};t.prototype.intersect=function(e){var n,r,i,s,o,u,a,f;if(this.start<=(r=e.start)&&r<(n=this.end)&&n<e.end){return new t(e.start,this.end)}else if(e.start<(s=this.start)&&s<(i=e.end)&&i<=this.end){return new t(this.start,e.end)}else if(e.start<(u=this.start)&&u<(o=this.end)&&o<e.end){return this}else if(this.start<=(f=e.start)&&f<(a=e.end)&&a<=this.end){return e}else{return null}};t.prototype.subtract=function(e){var n,r,i,s,o,u,a,f;if(this.intersect(e)===null){return[this]}else if(e.start<=(r=this.start)&&r<(n=this.end)&&n<=e.end){return[]}else if(e.start<=(s=this.start)&&s<(i=e.end)&&i<this.end){return[new t(e.end,this.end)]}else if(this.start<(u=e.start)&&u<(o=this.end)&&o<=e.end){return[new t(this.start,e.start)]}else if(this.start<(f=e.start)&&f<(a=e.end)&&a<this.end){return[new t(this.start,e.start),new t(e.end,this.end)]}};t.prototype.by=function(e,t){if(typeof e==="string"){this._by_string(e,t)}else{this._by_range(e,t)}return this};t.prototype.valueOf=function(){return this.end-this.start};t.prototype.toDate=function(){return[this.start.toDate(),this.end.toDate()]};t.prototype.isSame=function(e){return this.start.isSame(e.start)&&this.end.isSame(e.end)};t.prototype.diff=function(e){if(e==null){e=void 0}return this.end.diff(this.start,e)};return t}();e.fn.range=function(r,i){if(r in n){return new t(e(this).startOf(r),e(this).endOf(r))}else{return new t(r,i)}};e.range=function(e,n){return new t(e,n)};e.fn.within=function(e){return e.contains(this._d)};return e})

//Options for the toast notifications
toastr.options.closeButton = true;
toastr.options.showMethod = 'slideDown';
toastr.options.hideMethod = 'slideUp';
toastr.options.positionClass = 'toast-bottom-left'

//Chart generation function
function respChart(selector, data) {

    var options = {
        scaleOverlay: false,
        scaleOverride: false,
        scaleSteps: null,
        scaleStepWidth: null,
        scaleStartValue: null,
        scaleLineColor: "rgba(0,0,0,.1)",
        scaleLineWidth: 1,
        scaleShowLabels: true,
        scaleLabel: "<%=value%>",
        scaleFontFamily: "arial",
        scaleFontSize: 10,
        scaleFontStyle: "normal",
        scaleFontColor: "#909090",
        scaleShowGridLines: true,
        scaleGridLineColor: "rgba(0,0,0,.05)",
        scaleGridLineWidth: 1,
        bezierCurve: false,
        pointDot: true,
        pointDotRadius: 3,
        pointDotStrokeWidth: 1,
        datasetStroke: true,
        datasetStrokeWidth: 2,
        datasetFill: true,
        animation: true,
        animationSteps: 60,
        animationEasing: "easeOutQuart",
        onAnimationComplete: null,
        legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%>
<span style=\"background-color:<%=datasets[i].lineColor%>\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
<%}%>
"
    }

    var ctx = selector.get(0).getContext("2d");

    var container = $(selector).parent();

    $(window).resize(generateChart);

	function generateChart() {

        var ww = selector.attr('width', $(container).width());
        new Chart(ctx).Line(data, options);
    };

    generateChart();
}

//Get selection and display chart
function getSelection () {

	if (firstSelection) {
		//Check if first date selected
		error = true;
		beforeDate.css("border", "3px solid rgb(255, 0, 0)");
		toastr.error('Please fill out all required options.', 'Error');
		return null
	}

	userMetricItems = $(".item");
	tempUserMetric = null;

	//Add selected metrics
	for(var i = 0; i < userMetricItems.length; i++) {
		tempUserMetric = $(userMetricItems[i]);
		if (tempUserMetric.attr('data-sel') == "true") {
			selectedMetrics.push(tempUserMetric.attr('data-metric'));
		}
	}

	beforePickedDate = eval(beforeDate.pickadate('picker').get('select', 'yyyymmdd'));
	afterPickedDate = eval(afterDate.pickadate('picker').get('select', 'yyyymmdd'));

	error = false;
	if (afterPickedDate == undefined) {

		//Check if error condition has been met
		error = true;

		//Set color of item border
		afterDate.css("border", "3px solid rgb(255, 0, 0)");
	}
	if (beforePickedDate == undefined) {

		//Check if error condition has been met
		error = true;

		//Set color of item border
		beforeDate.css("border", "3px solid rgb(255, 0, 0)");
	}
	if (selectedMetrics.length == 0) {

		//Check if error condition has been met
		error = true;

		//Set color of item border
		$(".item").css("border", "3px solid rgb(255, 0, 0)");
	}

	if (error == true) {
		//send error
		toastr.error('Please fill out all required options.', 'Error');
		return null
	} else {
		//send success
		toastr.success("Generating graph.", "Success")
		return [beforePickedDate, afterPickedDate, selectedMetrics]
	}

}

function makeGraph(selectionInformation) {

	beforePickedDate = selectionInformation[0];
	afterPickedDate = selectionInformation[1];
	selectedMetrics = selectionInformation[2];
	var metDesc = "";
	var graphTemplate = ['

',
		'

',
		'

<canvas class="metchart ',
		'"></canvas>
'];

	requestedDates = [];
	graphArr = [];
	chartArr = [];

	//Add dates to labels

	var beforeDateObj = moment(beforePickedDate, "YYYYMMDD");
	var afterDateObj = moment(afterPickedDate, "YYYYMMDD");
	var dateRange = moment().range(beforeDateObj, afterDateObj);

	dateRange.by('days', function(moment) {
	  requestedDates.push(moment.format("YYYYMMDD"));
	});

	for (var i = 0; i < selectedMetrics.length; i++) {
		var chartData =  {
			labels : [],
            datasets : [ {
            	fillColor: 'rgba(31, 162, 222, 0.5)',
                label: "My First dataset",
                pointColor: 'rgba(31, 162, 222, 0.5)',
                pointHighlightFill: "#fff",
                pointHighlightStroke: 'rgba(31, 162, 222, 0.5)',
                pointStrokeColor: "#fff",
                strokeColor: "rgba(220,220,220,1)",
                data : []
            }]
        };

		for (var j = 0; j < requestedDates.length; j++) {
			chartData['labels'].push(requestedDates[j]);
			var dataTemplate =  "http://vps.ritwikd.com:8081/" + requestedUserName + '?type=data&date=' + requestedDates[j] + '&metric='  + selectedMetrics[i];
			var returnedValue = getJSON(dataTemplate)['value'];
			switch (requestedUserMetrics[selectedMetrics[i]]['format'][0]) {
				case 'percentage':
					if (returnedValue === 'null') {
						chartData['datasets'][0]['data'].push(0);
					} else {
						chartData['datasets'][0]['data'].push(eval(returnedValue));
					}
					metDesc = requestedUserMetrics[selectedMetrics[i]]['format']['2'];
					break;
				case 'graph':
					if (returnedValue === 'null') {
						chartData['datasets'][0]['data'].push(0);
					} else {
						var finalNum = 0;
						for (var k = 0; k < returnedValue.length; k++) {
							finalNum += eval(returnedValue[k]);
						}
						finalNum /= returnedValue.length;
						chartData['datasets'][0]['data'].push(finalNum);
					}
					metDesc = requestedUserMetrics[selectedMetrics[i]]['format']['1'];
			}
		}

		$(".graph-container").append(graphTemplate[0] + selectedMetrics[i] +
			graphTemplate[1] + selectedMetrics[i] +
			graphTemplate[2] + selectedMetrics[i] +
			graphTemplate[3] + selectedMetrics[i] +
			graphTemplate[4] + metDesc +
			graphTemplate[5] + selectedMetrics[i] +
			graphTemplate[6]);

		respChart($(".metchart." + selectedMetrics[i]), chartData);
	}

}

function getQuery() {
	Pace.restart();
	//Run all components
	$(".graph-container").html('');
	selectedMetrics = [];
	selectionInformation = getSelection();
	if (selectionInformation != null) {
		makeGraph(selectionInformation);
	}
}

var metricMenuTemplate = ['
', '
']

var requestedUserName = localStorage.getItem('username');
var requestedUser = getUser(requestedUserName);
var requestedUserMetrics = requestedUser['metrics']

var tempMetricObject = {};
var tempUserMetric = null;
var currentDateObject = new Date();
var firstSelection = true;
var currentlySelectedColors = {};

var legendTemplate = ['

',
			 ')

'];
var legendItem = "";

var userMetricItems = $(".item");

var chartData = { labels: [], datasets: []};
var selectedMetrics = [];
var currentlyUsedColors = [];

var error = false;
var beforePickedDate = null;
var afterPickedDate = null;

var returnedDataTemplate = [ "http://vps.ritwikd.com:8081/" + requestedUserName + "?type=data&metric=", "&date=" ];
var requestedDates = [];
var graphUserData = {};
var dataRequestTempURL = "";

var finalGraphValue = 0;

var legendUnit = "";
var currentLegendColor = "";

var selectionInformation = [];

var colorIndex = 0;

var notAllowed = ['picture', 'raw'];

//Get list of options
$(".menbot").append('

Choose items to compare:

');
$.each(requestedUserMetrics, function(requestedUserMetric) {
	tempMetricObject = requestedUserMetrics[requestedUserMetric];
	if (notAllowed.indexOf(tempMetricObject['format'][0])== -1) {
		$(".menbot").append(metricMenuTemplate[0] + requestedUserMetric + metricMenuTemplate[1] + requestedUserMetric + metricMenuTemplate[2]);
	}
});

//Add datepickers
$(".menbot").append('

Choose a starting date:

');
$(".menbot").append('<input id="beforeDate" class="pickbox pickadate">');
var afterDate = $("#afterDate");
var beforeDate = $("#beforeDate").pickadate(  {
	max : currentDateObject,
	onSet : function() {
		$("#beforeDate").attr("class", $("#beforeDate").attr("class") + " used");
		if (firstSelection) {
			//Create second datepicker on selection
			$(".menbot").append('

Choose an ending date:

');
			$(".menbot").append('<input id="afterDate" class="pickbox pickadate">');
			afterDate = $("#afterDate").pickadate({
				min : this.get('select'),
				max : currentDateObject,
				onSet : function() {
					$("#afterDate").css("border", "3px solid rgb(72, 154, 247) !important");
				}
			});
			firstSelection = false;
		} else {
			afterDate.pickadate('picker').set('min', this.get('select'), { muted : true});
		}

	}
});

//Cool colors
$(".item").on('click', function() {
	var item = $(this);
	if (item.attr("data-sel") == "false") {
		item.attr("data-sel", "true");
		$(item).css("border", "3px solid rgb(72, 154, 247)");
	} else {
		item.attr("data-sel", "false");
		$(item).css("border", "3px solid #CCC");
	}
});<commit_msg>Adding stuff.<commit_after>(function(e,t){if(typeof exports==="object"){module.exports=t(require("moment"))}else if(typeof define==="function"&&define.amd){define("moment-range",["moment"],t)}else{e.moment=t(e.moment)}})(this,function(e){var t,n;n={year:true,month:true,week:true,day:true,hour:true,minute:true,second:true};t=function(){function t(t,n){this.start=e(t);this.end=e(n)}t.prototype.contains=function(e){if(e instanceof t){return this.start<=e.start&&this.end>=e.end}else{return this.start<=e&&e<=this.end}};t.prototype._by_string=function(t,n){var r,i;r=e(this.start);i=[];while(this.contains(r)){n.call(this,r.clone());i.push(r.add(t,1))}return i};t.prototype._by_range=function(t,n){var r,i,s,o;i=Math.round(this/t);if(i===Infinity){return this}o=[];for(r=s=0;0<=i?s<=i:s>=i;r=0<=i?++s:--s){o.push(n.call(this,e(this.start.valueOf()+t.valueOf()*r)))}return o};t.prototype.overlaps=function(e){return this.intersect(e)!==null};t.prototype.intersect=function(e){var n,r,i,s,o,u,a,f;if(this.start<=(r=e.start)&&r<(n=this.end)&&n<e.end){return new t(e.start,this.end)}else if(e.start<(s=this.start)&&s<(i=e.end)&&i<=this.end){return new t(this.start,e.end)}else if(e.start<(u=this.start)&&u<(o=this.end)&&o<e.end){return this}else if(this.start<=(f=e.start)&&f<(a=e.end)&&a<=this.end){return e}else{return null}};t.prototype.subtract=function(e){var n,r,i,s,o,u,a,f;if(this.intersect(e)===null){return[this]}else if(e.start<=(r=this.start)&&r<(n=this.end)&&n<=e.end){return[]}else if(e.start<=(s=this.start)&&s<(i=e.end)&&i<this.end){return[new t(e.end,this.end)]}else if(this.start<(u=e.start)&&u<(o=this.end)&&o<=e.end){return[new t(this.start,e.start)]}else if(this.start<(f=e.start)&&f<(a=e.end)&&a<this.end){return[new t(this.start,e.start),new t(e.end,this.end)]}};t.prototype.by=function(e,t){if(typeof e==="string"){this._by_string(e,t)}else{this._by_range(e,t)}return this};t.prototype.valueOf=function(){return this.end-this.start};t.prototype.toDate=function(){return[this.start.toDate(),this.end.toDate()]};t.prototype.isSame=function(e){return this.start.isSame(e.start)&&this.end.isSame(e.end)};t.prototype.diff=function(e){if(e==null){e=void 0}return this.end.diff(this.start,e)};return t}();e.fn.range=function(r,i){if(r in n){return new t(e(this).startOf(r),e(this).endOf(r))}else{return new t(r,i)}};e.range=function(e,n){return new t(e,n)};e.fn.within=function(e){return e.contains(this._d)};return e})

//Options for the toast notifications
toastr.options.closeButton = true;
toastr.options.showMethod = 'slideDown';
toastr.options.hideMethod = 'slideUp';
toastr.options.positionClass = 'toast-bottom-left'

//Chart generation function
function respChart(selector, data) {

    var options = {
        scaleOverlay: false,
        scaleOverride: false,
        scaleSteps: null,
        scaleStepWidth: null,
        scaleStartValue: null,
        scaleLineColor: "rgba(0,0,0,.1)",
        scaleLineWidth: 1,
        scaleShowLabels: true,
        scaleLabel: "<%=value%>",
        scaleFontFamily: "arial",
        scaleFontSize: 10,
        scaleFontStyle: "normal",
        scaleFontColor: "#909090",
        scaleShowGridLines: true,
        scaleGridLineColor: "rgba(0,0,0,.05)",
        scaleGridLineWidth: 1,
        bezierCurve: false,
        pointDot: true,
        pointDotRadius: 3,
        pointDotStrokeWidth: 1,
        datasetStroke: true,
        datasetStrokeWidth: 2,
        datasetFill: true,
        animation: true,
        animationSteps: 60,
        animationEasing: "easeOutQuart",
        onAnimationComplete: null,
        legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%>
<span style=\"background-color:<%=datasets[i].lineColor%>\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%>
<%}%>
"
    }

    var ctx = selector.get(0).getContext("2d");

    var container = $(selector).parent();

    $(window).resize(generateChart);

	function generateChart() {

        var ww = selector.attr('width', $(container).width());
        new Chart(ctx).Line(data, options);
    };

    generateChart();
}

//Get selection and display chart
function getSelection () {

	if (firstSelection) {
		//Check if first date selected
		error = true;
		beforeDate.css("border", "3px solid rgb(255, 0, 0)");
		toastr.error('Please fill out all required options.', 'Error');
		return null
	}

	userMetricItems = $(".item");
	tempUserMetric = null;

	//Add selected metrics
	for(var i = 0; i < userMetricItems.length; i++) {
		tempUserMetric = $(userMetricItems[i]);
		if (tempUserMetric.attr('data-sel') == "true") {
			selectedMetrics.push(tempUserMetric.attr('data-metric'));
		}
	}

	beforePickedDate = eval(beforeDate.pickadate('picker').get('select', 'yyyymmdd'));
	afterPickedDate = eval(afterDate.pickadate('picker').get('select', 'yyyymmdd'));

	error = false;
	if (afterPickedDate == undefined) {

		//Check if error condition has been met
		error = true;

		//Set color of item border
		afterDate.css("border", "3px solid rgb(255, 0, 0)");
	}
	if (beforePickedDate == undefined) {

		//Check if error condition has been met
		error = true;

		//Set color of item border
		beforeDate.css("border", "3px solid rgb(255, 0, 0)");
	}
	if (selectedMetrics.length == 0) {

		//Check if error condition has been met
		error = true;

		//Set color of item border
		$(".item").css("border", "3px solid rgb(255, 0, 0)");
	}

	if (error == true) {
		//send error
		toastr.error('Please fill out all required options.', 'Error');
		return null
	} else {
		//send success
		toastr.success("Generating graph.", "Success")
		return [beforePickedDate, afterPickedDate, selectedMetrics]
	}

}

function makeGraph(selectionInformation) {

	beforePickedDate = selectionInformation[0];
	afterPickedDate = selectionInformation[1];
	selectedMetrics = selectionInformation[2];
	var metDesc = "";
	var graphTemplate = ['

',
		'

',
		'

<canvas class="metchart ',
		'"></canvas>
'];

	requestedDates = [];
	graphArr = [];
	chartArr = [];

	//Add dates to labels
	var beforeDateObj = moment(beforePickedDate, "YYYYMMDD");
	var afterDateObj = moment(afterPickedDate, "YYYYMMDD");
	var dateRange = moment().range(beforeDateObj, afterDateObj);

	dateRange.by('days', function(moment) {
	  requestedDates.push(moment.format("YYYYMMDD"));
	});

	for (var i = 0; i < selectedMetrics.length; i++) {
		var chartData =  {
			labels : [],
            datasets : [ {
            	fillColor: 'rgba(31, 162, 222, 0.5)',
                label: "My First dataset",
                pointColor: 'rgba(31, 162, 222, 0.5)',
                pointHighlightFill: "#fff",
                pointHighlightStroke: 'rgba(31, 162, 222, 0.5)',
                pointStrokeColor: "#fff",
                strokeColor: "rgba(220,220,220,1)",
                data : []
            }]
        };

		for (var j = 0; j < requestedDates.length; j++) {
			chartData['labels'].push(requestedDates[j]);
			var dataTemplate =  "http://vps.ritwikd.com:8081/" + requestedUserName + '?type=data&date=' + requestedDates[j] + '&metric='  + selectedMetrics[i];
			var returnedValue = getJSON(dataTemplate)['value'];
			switch (requestedUserMetrics[selectedMetrics[i]]['format'][0]) {
				case 'percentage':
					if (returnedValue === 'null') {
						chartData['datasets'][0]['data'].push(0);
					} else {
						chartData['datasets'][0]['data'].push(eval(returnedValue));
					}
					metDesc = requestedUserMetrics[selectedMetrics[i]]['format']['2'];
					break;
				case 'graph':
					if (returnedValue === 'null') {
						chartData['datasets'][0]['data'].push(0);
					} else {
						var finalNum = 0;
						for (var k = 0; k < returnedValue.length; k++) {
							finalNum += eval(returnedValue[k]);
						}
						finalNum /= returnedValue.length;
						chartData['datasets'][0]['data'].push(finalNum);
					}
					metDesc = requestedUserMetrics[selectedMetrics[i]]['format']['1'];
			}
		}

		$(".graph-container").append(graphTemplate[0] + selectedMetrics[i] +
			graphTemplate[1] + selectedMetrics[i] +
			graphTemplate[2] + selectedMetrics[i] +
			graphTemplate[3] + selectedMetrics[i] +
			graphTemplate[4] + metDesc +
			graphTemplate[5] + selectedMetrics[i] +
			graphTemplate[6]);

		respChart($(".metchart." + selectedMetrics[i]), chartData);
	}

}

function getQuery() {
	Pace.restart();
	//Run all components
	$(".graph-container").html('');
	selectedMetrics = [];
	selectionInformation = getSelection();
	if (selectionInformation != null) {
		makeGraph(selectionInformation);
	}
}

var metricMenuTemplate = ['
', '
']

var requestedUserName = localStorage.getItem('username');
var requestedUser = getUser(requestedUserName);
var requestedUserMetrics = requestedUser['metrics']

var tempMetricObject = {};
var tempUserMetric = null;
var currentDateObject = new Date();
var firstSelection = true;
var currentlySelectedColors = {};

var legendTemplate = ['

',
			 ')

'];
var legendItem = "";

var userMetricItems = $(".item");

var chartData = { labels: [], datasets: []};
var selectedMetrics = [];
var currentlyUsedColors = [];

var error = false;
var beforePickedDate = null;
var afterPickedDate = null;

var returnedDataTemplate = [ "http://vps.ritwikd.com:8081/" + requestedUserName + "?type=data&metric=", "&date=" ];
var requestedDates = [];
var graphUserData = {};
var dataRequestTempURL = "";

var finalGraphValue = 0;

var legendUnit = "";
var currentLegendColor = "";

var selectionInformation = [];

var colorIndex = 0;

var notAllowed = ['picture', 'raw'];

//Get list of options
$(".menbot").append('

Choose items to compare:

');
$.each(requestedUserMetrics, function(requestedUserMetric) {
	tempMetricObject = requestedUserMetrics[requestedUserMetric];
	if (notAllowed.indexOf(tempMetricObject['format'][0])== -1) {
		$(".menbot").append(metricMenuTemplate[0] + requestedUserMetric + metricMenuTemplate[1] + requestedUserMetric + metricMenuTemplate[2]);
	}
});

//Add datepickers
$(".menbot").append('

Choose a starting date:

');
$(".menbot").append('<input id="beforeDate" class="pickbox pickadate">');
var afterDate = $("#afterDate");
var beforeDate = $("#beforeDate").pickadate(  {
	max : currentDateObject,
	onSet : function() {
		$("#beforeDate").attr("class", $("#beforeDate").attr("class") + " used");
		if (firstSelection) {
			//Create second datepicker on selection
			$(".menbot").append('

Choose an ending date:

');
			$(".menbot").append('<input id="afterDate" class="pickbox pickadate">');
			afterDate = $("#afterDate").pickadate({
				min : this.get('select'),
				max : currentDateObject,
				onSet : function() {
					$("#afterDate").css("border", "3px solid rgb(72, 154, 247) !important");
				}
			});
			firstSelection = false;
		} else {
			afterDate.pickadate('picker').set('min', this.get('select'), { muted : true});
		}

	}
});

//Cool colors
$(".item").on('click', function() {
	var item = $(this);
	if (item.attr("data-sel") == "false") {
		item.attr("data-sel", "true");
		$(item).css("border", "3px solid rgb(72, 154, 247)");
	} else {
		item.attr("data-sel", "false");
		$(item).css("border", "3px solid #CCC");
	}
});<|endoftext|>


<commit_before>
var phantom = require("phantomjs")
,   execFile = require("child_process").execFile
,   jn = require("path").join
,   u = require("url")
,   r2hPath = jn(__dirname, "../node_modules/respec/tools/respec2html.js")
;

exports.generate = function (url, params, cb) {
    url = u.parse(url, true);
    for (var k in params) if (params.hasOwnProperty(k)) url.query[k] = params[k];
    url = u.format(url);
    console.log("Generating", url);
    // Phantom's own timeouts are never reaching us for some reason, so we do our own
    var timedout = false;
    setTimeout(
        function () {
            timedout = true;
            cb({ status: 500, message: "Processing timed out." });
        }
    ,   10000
    );
    execFile(
        phantom.path
    ,   ["--ssl-protocol=any", r2hPath, url]
    ,   function (err, stdout, stderr) {
            if (timedout) return;
            // note: Phantom prints error on stdout even when you use console.error()
            if (err) return cb({ status: 500, message: err + "\n" + (stderr || stdout || "") });
            cb(null, stdout);
        }
    );
};
<commit_msg>don't always timeout; use stderr only close #2<commit_after>
var phantom = require("phantomjs")
,   execFile = require("child_process").execFile
,   jn = require("path").join
,   u = require("url")
,   r2hPath = jn(__dirname, "../node_modules/respec/tools/respec2html.js")
;

exports.generate = function (url, params, cb) {
    url = u.parse(url, true);
    for (var k in params) if (params.hasOwnProperty(k)) url.query[k] = params[k];
    url = u.format(url);
    console.log("Generating", url);
    // Phantom's own timeouts are never reaching us for some reason, so we do our own
    var timedout = false;
    var tickingBomb = setTimeout(
        function () {
            timedout = true;
            cb({ status: 500, message: "Processing timed out." });
        }
    ,   10000
    );
    execFile(
        phantom.path
    ,   ["--ssl-protocol=any", r2hPath, url]
    ,   function (err, stdout, stderr) {
            if (timedout) return;
            clearTimeout(tickingBomb);
            if (err) return cb({ status: 500, message: err + "\n" + (stderr || "") });
            cb(null, stdout);
        }
    );
};
<|endoftext|>


<commit_before>import './../src';

import './helpers';
import './runs';
import './types';
import './wrappers';

// mock console warn (we don't need no education - from formly ;] )
console.warn = function consoleWarn() {};
<commit_msg>refactor: remove mocking console.warn<commit_after>import './../src';

import './helpers';
import './runs';
import './types';
import './wrappers';
<|endoftext|>


<commit_before>'use strict'

const Test = require('tape')
const Mock = require('mock-fs')
const ReadFile = require('fs').readFile

const Punc = require('../')

/* TESTS */
Test('Punc: exists?', t => {
  t.plan(1)
  t.equal(typeof Punc, 'function', 'it exists')
})

Test('Punc: handles null filePath argument?', t => {
  t.plan(1)
  t.throws(_ => Punc(), 'error throws')
})

Test('Punc: returns a Promise?', t => {
  t.plan(2)
  let module = Punc('tests/books/alice.txt')
  t.ok(module.then, 'is then-able')
  t.ok(module.catch, 'is catch-able')
})

Test('Punc: punctuation count', t => {
  t.plan(1)
  let punctuationMap = { ';': 2
    , ':': 0
    , '\'': 1
    , '"': 2
    , ',': 2
    , '!': 0
    , '?': 0
    , '.': 2
    , '(': 1
    , ')': 0
    , '-': 3
  }

  Punc('tests/books/alice.txt')
    .then(book => {
      t.ok(book.count, 'count property exists on returned object')
      for (let key in book.count) {

        if (!punctuationMap.hasOwnProperty(key)) {
          return t.fail(`Key not found: ${key}`)
        }

        if (punctuationMap[key] !== book.count[key]) {
          return t.fail(`Value mismatch.\n\
            Punctuation: ${key}\n\
            Expected: ${punctuationMap[key]}.\n\
            Actual: ${book.count[key]}`)
        }
      }
    })
    .catch(err => t.fail(err))
})

Test('Punc: punctuation body', t => {
  t.plan(2)
  Punc('tests/books/alice.txt')
    .then(book => {
      t.ok(book.body, 'body property exists on returned object')
      t.equals(book.body, '-;,.\'(-;-.,""')
    })
    .catch(err => t.fail(err))
})

Test('Punc: words per sentence', t => {
  t.plan(2)
  Punc('tests/books/word_count.txt')
    .then(book => {
      t.ok(book.wordsPerSentence, 'wordCount property exists on returned object')
      t.equals(book.wordsPerSentence, 2.5)
    })
    .catch(err => t.fail(err))
})

Test('Punc: spaced out text', t => {
  t.plan(2)
  Punc('tests/books/word_count.txt')
    .then(book => {
      t.ok(book.spaced, 'spaced property exists on returned object')
      t.equals(book.spaced, ' .    !      ?        .')
    })
})

Test('Punc.createPDF: method exists?', t => {
  t.equals(typeof Punc.createPDF, 'function', 'createPDF method exists.')
  t.end()
})

Test('Punc.createPDF: creates PDF file', t => {
  t.plan(2)

  let filePath = 'tests/books/dream_speech';

  Punc.createPDF(filePath)
    .then(success => {
      t.pass('Punc returns success message')

      ReadFile(filePath, (err, data) => {
        if (err) return reject(err)
        if (data) t.pass('pdf file exists')
      })
    })
    .catch(err => t.fail(err))
})
<commit_msg>removes debugging code<commit_after>'use strict'

const Test = require('tape')
const ReadFile = require('fs').readFile

const Punc = require('../')

/* TESTS */
Test('Punc: exists?', t => {
  t.plan(1)
  t.equal(typeof Punc, 'function', 'it exists')
})

Test('Punc: handles null filePath argument?', t => {
  t.plan(1)
  t.throws(_ => Punc(), 'error throws')
})

Test('Punc: returns a Promise?', t => {
  t.plan(2)
  let module = Punc('tests/books/alice.txt')
  t.ok(module.then, 'is then-able')
  t.ok(module.catch, 'is catch-able')
})

Test('Punc: punctuation count', t => {
  t.plan(1)
  let punctuationMap = { ';': 2
    , ':': 0
    , '\'': 1
    , '"': 2
    , ',': 2
    , '!': 0
    , '?': 0
    , '.': 2
    , '(': 1
    , ')': 0
    , '-': 3
  }

  Punc('tests/books/alice.txt')
    .then(book => {
      t.ok(book.count, 'count property exists on returned object')
      for (let key in book.count) {

        if (!punctuationMap.hasOwnProperty(key)) {
          return t.fail(`Key not found: ${key}`)
        }

        if (punctuationMap[key] !== book.count[key]) {
          return t.fail(`Value mismatch.\n\
            Punctuation: ${key}\n\
            Expected: ${punctuationMap[key]}.\n\
            Actual: ${book.count[key]}`)
        }
      }
    })
    .catch(err => t.fail(err))
})

Test('Punc: punctuation body', t => {
  t.plan(2)
  Punc('tests/books/alice.txt')
    .then(book => {
      t.ok(book.body, 'body property exists on returned object')
      t.equals(book.body, '-;,.\'(-;-.,""')
    })
    .catch(err => t.fail(err))
})

Test('Punc: words per sentence', t => {
  t.plan(2)
  Punc('tests/books/word_count.txt')
    .then(book => {
      t.ok(book.wordsPerSentence, 'wordCount property exists on returned object')
      t.equals(book.wordsPerSentence, 2.5)
    })
    .catch(err => t.fail(err))
})

Test('Punc: spaced out text', t => {
  t.plan(2)
  Punc('tests/books/word_count.txt')
    .then(book => {
      t.ok(book.spaced, 'spaced property exists on returned object')
      t.equals(book.spaced, ' .    !      ?        .')
    })
})

Test('Punc.createPDF: method exists?', t => {
  t.equals(typeof Punc.createPDF, 'function', 'createPDF method exists.')
  t.end()
})

Test('Punc.createPDF: creates PDF file', t => {
  t.plan(2)

  let filePath = 'tests/books/dream_speech';

  Punc.createPDF(filePath)
    .then(success => {
      t.pass('Punc returns success message')

      ReadFile(filePath, (err, data) => {
        if (err) return reject(err)
        if (data) t.pass('pdf file exists')
      })
    })
    .catch(err => t.fail(err))
})
<|endoftext|>


<commit_before>"use strict";
var fs = require('fs');
var test = require('tap').test;
var scoParser = require('../index.js');
var testFolder = 'testFiles/unpackScoZipTests';
var pathToExtractZip = 'testFiles/unpackScoZipTests/extractFolder';
var rmrf = require('rimraf');

test('Successfully unpacks SCO zip file and validates imsmanifest.xml', function(t) {
	t.test('Should extract SCO zip file and validate imsmanifest.xml', function (t) {
		var params = {
			pathToScoZip: testFolder + '/articulate_sco_with_quiz.zip',
			pathToExtractZip: pathToExtractZip
		};
		scoParser(params).validate(function (err, result) {
			t.notOk(err, 'Should not error');
			t.ok(fs.existsSync(pathToExtractZip), 'Should have created path in which to extract zip');
			t.ok(result, 'Should receive XML JSONified');
			t.equal(result.manifest.resources[0].resource[0].$.href, 'index_lms.html', 'Should find the main html file');
			t.end();
		});
	});

	t.test('Deletes folder in which to unzip the files', function (t) {
		rmrf(pathToExtractZip, function(err, result) {
			t.notOk(err, "failed to remove directory where files were unzipped to");
			t.end();
		});
	});
});
<commit_msg>Added more to integration tests.<commit_after>"use strict";
var fs = require('fs');
var test = require('tap').test;
var scoParserIndex = require('../index.js');
var testFolder = 'testFiles/unpackScoZipTests';
var pathToExtractZip = 'testFiles/unpackScoZipTests/extractFolder';
var rmrf = require('rimraf');

var params = {
	pathToScoZip: testFolder + '/articulate_sco_with_quiz.zip',
	pathToExtractZip: pathToExtractZip
};

test('Successfully unpacks SCO zip file, validates imsmanifest.xml, and parses it for information', function(t) {
	var params = {
		pathToScoZip: testFolder + '/articulate_sco_with_quiz.zip',
		pathToExtractZip: pathToExtractZip
	};
	var scoParser = scoParserIndex(params);
	t.test('Should extract SCO zip file and validate imsmanifest.xml', function (t) {
		scoParser.validate(function (err, result) {
			t.notOk(err, 'Should not error');
			t.ok(fs.existsSync(pathToExtractZip), 'Should have created path in which to extract zip');
			t.ok(result, 'Should receive XML JSONified');
			t.end();
		});
	});

	t.test('Should parse imsmanifest.xml to find base html file', function(t) {
		scoParser.parse(function (err, result) {
			t.notOk(err, 'Should not error');
			t.ok(result, 'Should receive information parsed from the manifest XML');
			t.equal(result.scoHtmlHref, 'index_lms.html', 'Should receive the SCO\'s start-up HTML file from the manifest');
			t.end();
		})
	});

	t.test('Deletes folder in which to unzip the files', function (t) {
		rmrf(pathToExtractZip, function(err, result) {
			t.notOk(err, "failed to remove directory where files were unzipped to");
			t.end();
		});
	});
});<|endoftext|>


<commit_before>// Mocha
if (parent.mocha) {
    // BDD or QUnit
    window.before = parent.before;
    window.after = parent.after;
    window.beforeEach = parent.beforeEach;
    window.afterEach = parent.afterEach;
    window.run = parent.run;

    // BDD
    window.describe = parent.describe;
    window.it = parent.it;
    window.xit = parent.xit;

    // QUnit
    window.suite = parent.suite;
    window.test = parent.test;

    // TDD
    window.setup = parent.setup;
    window.teardown = parent.teardown;
    window.suiteSetup = parent.suiteSetup;
    window.suiteTeardown = parent.suiteTeardown;
}

if (parent.chai) {
    // Chai
    window.AssertionError = parent.chai.AssertionError;
    window.should = parent.should;
    window.expect = parent.expect;
    window.assert = parent.assert;
}<commit_msg>Expose mocha and Mocha globals from parent page<commit_after>// Mocha
if (parent.mocha) {
    window.mocha = parent.mocha;
    window.Mocha = parent.Mocha;

    // BDD or QUnit
    window.before = parent.before;
    window.after = parent.after;
    window.beforeEach = parent.beforeEach;
    window.afterEach = parent.afterEach;
    window.run = parent.run;

    // BDD
    window.describe = parent.describe;
    window.it = parent.it;
    window.xit = parent.xit;

    // QUnit
    window.suite = parent.suite;
    window.test = parent.test;

    // TDD
    window.setup = parent.setup;
    window.teardown = parent.teardown;
    window.suiteSetup = parent.suiteSetup;
    window.suiteTeardown = parent.suiteTeardown;
}

if (parent.chai) {
    // Chai
    window.AssertionError = parent.chai.AssertionError;
    window.should = parent.should;
    window.expect = parent.expect;
    window.assert = parent.assert;
}<|endoftext|>


<commit_before>module("List.js standard");
var theList
    , ryah = {
        id: 4
        , name: "Ryan Dahl"
        , feature: "Node"
    }
    , tj = {
        id: 5
        , name: "TJ Holowaychuk"
        , feature: "Node"
    }
    , jonny = {
        id: 6
        , name: "Jonny Strömberg"
        , feature: "List.js"
    };
test('Create List.js from existing list', function() {
    var templates = {
        valueNames: ['id', 'name', 'feature']
    };
    theList = new List('list', templates);
    ok(true, "list created" );
});

test('Count items', function(){
   equals(theList.size(), 3);
});

test('Add one item', function(){
    theList.add(ryah);
    equals(theList.size(), 4);
});
test('Add two items', function(){
    theList.add([tj, jonny]);
    equals(theList.size(), 6);
});

test('Remove one item', function() {
    var found = theList.remove('id', 6);

    equals(found, true, "Item was note found");
    equals(theList.size(), 5, 'List is not one item shorter');
});

test('Try remove one item that not exists', function() {
    var found = theList.remove('id', 9);

    equals(found, false, 'An item was found');
    equals(theList.size(), 5, 'List are not 5 items long');
});

test('Get one item', function() {
    var item = theList.get('id', 4);
    deepEqual(item.getValues(), ryah);
});

test('Get two items', function() {
    var items = theList.get('feature', 'Node');
    items = [
        items[0].getValues(),
        items[1].getValues()
    ];
    deepEqual(items, [ryah, tj], "Say woot");
});

test('Get item that doen not exist', function() {
    var item = theList.get('id', 200);
    equals(item, null);
});

test('Search', function() {
    var items = theList.search('Node');
    equals(items.length, 2);
    items = [
        items[0].getValues(),
        items[1].getValues()
    ];
    deepEqual(items, [ryah, tj]);
   theList.search('');
});

test('Filter', function() {
    var visibleItems = theList.filter(function(values) {
        if (+values.id < 3) {
            return true;
        } else {
            return false;
        }
    });
    equals(visibleItems.length, 2);
    equals(visibleItems[0].getValues().id, 1);
    equals(visibleItems[1].getValues().id, 2);
});

test('Restore from filter', function() {
   var visibleItems = theList.filter(false);
   equals(visibleItems.length, 5);
});
<commit_msg>Indenting fix<commit_after>module("List.js standard");
var theList
    , ryah = {
        id: 4
        , name: "Ryan Dahl"
        , feature: "Node"
    }
    , tj = {
        id: 5
        , name: "TJ Holowaychuk"
        , feature: "Node"
    }
    , jonny = {
        id: 6
        , name: "Jonny Strömberg"
        , feature: "List.js"
    };
test('Create List.js from existing list', function() {
    var templates = {
        valueNames: ['id', 'name', 'feature']
    };
    theList = new List('list', templates);
    ok(true, "list created" );
});

test('Count items', function(){
   equals(theList.size(), 3);
});

test('Add one item', function(){
    theList.add(ryah);
    equals(theList.size(), 4);
});
test('Add two items', function(){
    theList.add([tj, jonny]);
    equals(theList.size(), 6);
});

test('Remove one item', function() {
    var found = theList.remove('id', 6);

    equals(found, true, "Item was note found");
    equals(theList.size(), 5, 'List is not one item shorter');
});

test('Try remove one item that not exists', function() {
    var found = theList.remove('id', 9);

    equals(found, false, 'An item was found');
    equals(theList.size(), 5, 'List are not 5 items long');
});

test('Get one item', function() {
    var item = theList.get('id', 4);
    deepEqual(item.getValues(), ryah);
});

test('Get two items', function() {
    var items = theList.get('feature', 'Node');
    items = [
        items[0].getValues(),
        items[1].getValues()
    ];
    deepEqual(items, [ryah, tj], "Say woot");
});

test('Get item that doen not exist', function() {
    var item = theList.get('id', 200);
    equals(item, null);
});

test('Search', function() {
    var items = theList.search('Node');
    equals(items.length, 2);
    items = [
        items[0].getValues(),
        items[1].getValues()
    ];
    deepEqual(items, [ryah, tj]);
   theList.search('');
});

test('Filter', function() {
    var visibleItems = theList.filter(function(values) {
        if (+values.id < 3) {
            return true;
        } else {
            return false;
        }
    });
    equals(visibleItems.length, 2);
    equals(visibleItems[0].getValues().id, 1);
    equals(visibleItems[1].getValues().id, 2);
});

test('Restore from filter', function() {
    var visibleItems = theList.filter(false);
    equals(visibleItems.length, 5);
});
<|endoftext|>


<commit_before>var editor = {
    debug: function(str)
    {
    },

    getHTMLError: function(message)
    {
    },

    getHTMLResponse: function(html)
    {
    },

    jsInterfaceInitError: function(error)
    {
    },

    jsInterfaceInitFinished: function()
    {
    },

    setOutline: function(outline)
    {
    },

    setStyles: function(styles)
    {
    },

    setCursor: function(x,y,width,height)
    {
    },

    setSelectionHandles: function(x1,y1,height1,x2,y2,height2)
    {
    },

    clearSelectionHandlesAndCursor: function()
    {
    },

    setSelectionBounds: function(left,top,right,bottom)
    {
    },

    sayHello: function(name)
    {
    }
};
<commit_msg>Removed more obsolete code - this time some callback methods from the Android days<commit_after>var editor = {
    debug: function(str)
    {
    },

    jsInterfaceInitError: function(error)
    {
    },

    jsInterfaceInitFinished: function() {
    },

    setOutline: function(outline)
    {
    },

    setStyles: function(styles)
    {
    },

    setCursor: function(x,y,width,height)
    {
    },

    setSelectionHandles: function(x1,y1,height1,x2,y2,height2)
    {
    },

    clearSelectionHandlesAndCursor: function()
    {
    },

    setSelectionBounds: function(left,top,right,bottom)
    {
    },

    reportJSError: function(error)
    {
    },

};
<|endoftext|>


<commit_before><commit_msg>Fix job notes<commit_after><|endoftext|>