<commit_before>const fs = require("fs");
const path = require('path');

var args = process.argv.slice(2);
if(args.length < 2) {
  console.log("Please pass two arguments");
  console.log("First argument is the original images folder, input");
  console.log("Second argument is the optimized and/or compressed images folder to compare with, input");
  process.exit(1);
}

var source = args[0] || './image/';
var destination = args[1] || './optimized/';

var walk = function(dir, done) {
  var results = [];
  fs.readdir(dir, function(err, list) {
    if (err) return done(err);

    var pending = list.length;
    if (!pending) return done(null, results);

    list.forEach(function(file) {
      file = path.resolve(dir, file);
      fs.stat(file, function(err, stat) {
        if (stat && stat.isDirectory()) {
          walk(file, function(err, res) {
            results = results.concat(res);
            if (!--pending) done(null, results);
          });
        } else {
          var parsedPath = path.parse(file);
          if (parsedPath.ext === '.png' || parsedPath === '.PNG') {
            // we only build the map if the extension is png
            results.push(file);
          }
          if (!--pending) done(null, results);
        }
      });
    });
  });
};

var fileToSizeSet = {};
walk(source, function(err, results) {
  if (err) throw err;
  for(var i = 0 ; i < results.length; i++) {
    var stats = fs.statSync(results[i]);
    var fileSizeInBytes = stats["size"];
    //console.log("File size of image " + results[i] + " : " + fileSizeInBytes);
    var fileName = path.parse(results[i]).base;
    fileToSizeSet[fileName] = fileSizeInBytes;
  }

  var foundUncompressed = [];
  walk(destination, function(err, results) {
    for(var i = 0 ; i < results.length; i++) {
      var stats = fs.statSync(results[i]);
      var fileSizeInBytes = stats["size"];
      //console.log("File size of optimized " + results[i] + " : " + fileSizeInBytes);
      var fileName = path.parse(results[i]).base;
      if(fileToSizeSet[fileName] > fileSizeInBytes) {
        //console.log("original was not compressed: " + fileToSizeSet[fileName] + " > " + fileSizeInBytes);
        var uncompressedFile = { fileName : fileName, size: fileToSizeSet[fileName], compressedSize : fileSizeInBytes};
        foundUncompressed.push(uncompressedFile);
      } else {
        //console.log("original was compressed: " + fileToSizeSet[fileName] + " <= " + fileSizeInBytes);
      }
    }

    console.log("======== Found uncompressed ========");
    if(foundUncompressed.length === 0) {
      console.log("None");
    }
    for (var j = 0; j < foundUncompressed.length; j++) {
      console.log(foundUncompressed[j].fileName + " is " + foundUncompressed[j].size
        + " could be " + foundUncompressed[j].compressedSize + " bytes");
    }
    console.log("====================================");

  });

});

<commit_msg> Comparator output now displays percentage reduction<commit_after>const fs = require("fs");
const path = require('path');

var args = process.argv.slice(2);
if(args.length < 2) {
  console.log("Please pass two arguments");
  console.log("First argument is the original images folder, input");
  console.log("Second argument is the optimized and/or compressed images folder to compare with, input");
  process.exit(1);
}

var source = args[0] || './image/';
var destination = args[1] || './optimized/';

var walk = function(dir, done) {
  var results = [];
  fs.readdir(dir, function(err, list) {
    if (err) return done(err);

    var pending = list.length;
    if (!pending) return done(null, results);

    list.forEach(function(file) {
      file = path.resolve(dir, file);
      fs.stat(file, function(err, stat) {
        if (stat && stat.isDirectory()) {
          walk(file, function(err, res) {
            results = results.concat(res);
            if (!--pending) done(null, results);
          });
        } else {
          var parsedPath = path.parse(file);
          if (parsedPath.ext === '.png' || parsedPath === '.PNG') {
            // we only build the map if the extension is png
            results.push(file);
          }
          if (!--pending) done(null, results);
        }
      });
    });
  });
};

var fileToSizeSet = {};
walk(source, function(err, results) {
  if (err) throw err;
  for(var i = 0 ; i < results.length; i++) {
    var stats = fs.statSync(results[i]);
    var fileSizeInBytes = stats["size"];
    //console.log("File size of image " + results[i] + " : " + fileSizeInBytes);
    var fileName = path.parse(results[i]).base;
    fileToSizeSet[fileName] = fileSizeInBytes;
  }

  var foundUncompressed = [];
  walk(destination, function(err, results) {
    for(var i = 0 ; i < results.length; i++) {
      var stats = fs.statSync(results[i]);
      var fileSizeInBytes = stats["size"];
      //console.log("File size of optimized " + results[i] + " : " + fileSizeInBytes);
      var fileName = path.parse(results[i]).base;
      if(fileToSizeSet[fileName] > fileSizeInBytes) {
        //console.log("original was not compressed: " + fileToSizeSet[fileName] + " > " + fileSizeInBytes);
        var uncompressedFile = { fileName : fileName, size: fileToSizeSet[fileName], compressedSize : fileSizeInBytes};
        foundUncompressed.push(uncompressedFile);
      } else {
        //console.log("original was compressed: " + fileToSizeSet[fileName] + " <= " + fileSizeInBytes);
      }
    }

    console.log("======== Found uncompressed ========");
    if(foundUncompressed.length === 0) {
      console.log("None");
    }
    for (var j = 0; j < foundUncompressed.length; j++) {
      var percentDifference = (foundUncompressed[j].size - foundUncompressed[j].compressedSize) / foundUncompressed[j].size * 100;
      percentDifference = round(percentDifference, 2);
      console.log(foundUncompressed[j].fileName + " is " + foundUncompressed[j].size
        + " could be " + foundUncompressed[j].compressedSize + " bytes" + " (-" + percentDifference + "%)");
    }
    console.log("====================================");

  });

});

 var round = function(value, decimals) {
   // A bit hacky to round to 2 decimal.
   // I won't pull a library just for that.
   return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
};
<|endoftext|>


<commit_before>const builder = require("electron-builder")
const Platform = builder.Platform

var packageJson = require('./package.json');
var childProcess = require('child_process');

var exec = (cmd) => {
  return new Promise((resolve, reject) => {
    childProcess.exec(cmd, (err, stdout, stderr) => {
      if (err) {
        reject(err);
      } else {
        stdout.stderr = stderr;
        resolve(stdout);
      }
    });
  });
}

process.on('unhandledRejection', error => {
  // Will print "unhandledRejection err is not defined"
  console.log('unhandledRejection', error.message);
});

(async () => {

  let commitsCount = (await exec("git rev-list HEAD --count")).trim();
  let commitID = (await exec("git log --pretty=format:'%h' -n 1")).trim();

  let buildVersion = `${commitsCount} - ${commitID}`;
  console.log('build-version', buildVersion);

  await builder.build({
    //targets: Platform.MAC.createTarget(),
    config: {
      protocols: {
        name: "Postgres Database",
        schemes: ["postgres"],
        role: "Editor"
      },
      fileAssociations: [{
        ext: "sql",
        name: "SQL File",
        //icon: "SQL.icns"
      }],
      npmRebuild: false, // because we changed dependency paths postgres manually

      mac: {
        category: "public.app-category.developer-tools",
        target: "default",
        icon: "build_files/icon.icns",
        bundleVersion: buildVersion,
        bundleShortVersion: packageJson.version,
        minimumSystemVersion: "10.9.0",
        extendInfo: "build_files/Info.plist"
      },

      linux: {
        category: "Programming",
        target: [ "deb", "rpm" ]
      },

      nsis: {
        //target: [ "nsis", "portable" ],
        icon: "build_files/icon.icns",
      },

      portable: {

      }
    }
  })
})();
<commit_msg>Try to build for windows<commit_after>const builder = require("electron-builder")
const Platform = builder.Platform

var packageJson = require('./package.json');
var childProcess = require('child_process');

var exec = (cmd) => {
  return new Promise((resolve, reject) => {
    childProcess.exec(cmd, (err, stdout, stderr) => {
      if (err) {
        reject(err);
      } else {
        stdout.stderr = stderr;
        resolve(stdout);
      }
    });
  });
}

process.on('unhandledRejection', error => {
  // Will print "unhandledRejection err is not defined"
  console.log('unhandledRejection', error.message);
});

(async () => {

  let commitsCount = (await exec("git rev-list HEAD --count")).trim();
  let commitID = (await exec("git log --pretty=format:'%h' -n 1")).trim();

  let buildVersion = `${commitsCount} - ${commitID}`;
  console.log('build-version', buildVersion);

  await builder.build({
    //targets: Platform.MAC.createTarget(),
    config: {
      protocols: {
        name: "Postgres Database",
        schemes: ["postgres"],
        role: "Editor"
      },
      fileAssociations: [{
        ext: "sql",
        name: "SQL File",
        //icon: "SQL.icns"
      }],
      npmRebuild: false, // because we changed dependency paths postgres manually

      mac: {
        category: "public.app-category.developer-tools",
        target: "default",
        icon: "build_files/icon.icns",
        bundleVersion: buildVersion,
        bundleShortVersion: packageJson.version,
        minimumSystemVersion: "10.9.0",
        extendInfo: "build_files/Info.plist"
      },

      linux: {
        category: "Programming",
        target: [ "deb", "rpm" ]
      },

      nsis: {
        //target: [ "nsis", "portable" ],
        //icon: "build_files/icon.icns",
      },

      portable: {

      }
    }
  })
})();
<|endoftext|>


<commit_before>import {EventEmitter} from 'events';
import EventTypes from './EventTypes';

class NavigationService extends EventEmitter {

  constructor() {
    super();

    this.deferredTasks = [];

    // The only default is root, so it goes first no matter what
    this.definition = [
      { category: 'root', children: [] }
    ];

    this.on(
      EventTypes.NAVIGATION_CHANGE,
      this.processDeferred
    );
  }

  getDefinition() {
    return this.definition.slice(0);
  }

  processDeferred() {
    const tasks = this.deferredTasks.slice(0);
    this.deferredTasks = [];

    // If Task is unable to resolve at this point of time it will re-defer itself
    tasks.forEach(({method, args}) => {
      this[method].apply(this, args);
    });
  }

  defer(method, args) {
    this.deferredTasks.push({method, args});
  }

  registerCategory(category) {
    if (!this.definition.find((element) => element.category === category)) {
      this.definition.push({
        category,
        children: []
      });
    }

    this.emit(EventTypes.NAVIGATION_CHANGE);
  }

  registerPrimary(path, link, options = {}) {
    const {category = 'root'} = options;
    const categoryElement = this.definition
      .find((element) => element.category === category);

    if (!categoryElement) {
      return this.defer('registerPrimary', arguments);
    }

    const existingElement = categoryElement.children.find((element) => {
      return element.path === path;
    });

    if (existingElement) {
      return;
    }

    categoryElement.children.push({
      path,
      link,
      options,
      children: []
    });

    this.emit(EventTypes.NAVIGATION_CHANGE);
  }

  registerSecondary(parentPath, path, link, options = {}) {
    // flatten categories
    const primaryElements = this.definition.reduce((result, category) => {
      return result.concat(category.children);
    }, []);

    const parentElement = primaryElements
      .find((element) => element.path === parentPath);

    if (!parentElement) {
      return this.defer('registerSecondary', arguments);
    }

    const existingElement = parentElement.children.find((element) => {
      return element.path === path;
    });

    if (existingElement) {
      return;
    }

    parentElement.children.push({
      link,
      options,
      path: `${parentPath}/${path}`,
      children: []
    });

    this.emit(EventTypes.NAVIGATION_CHANGE);
  }
};

const service = new NavigationService();
export default service;
<commit_msg>import NAVIGATION_CHANGE constant instead of the whole object<commit_after>import {EventEmitter} from 'events';
import {NAVIGATION_CHANGE} from './EventTypes';

class NavigationService extends EventEmitter {

  constructor() {
    super();

    this.deferredTasks = [];

    // The only default is root, so it goes first no matter what
    this.definition = [
      { category: 'root', children: [] }
    ];

    this.on(
      NAVIGATION_CHANGE,
      this.processDeferred
    );
  }

  getDefinition() {
    return this.definition.slice(0);
  }

  processDeferred() {
    const tasks = this.deferredTasks.slice(0);
    this.deferredTasks = [];

    // If Task is unable to resolve at this point of time it will re-defer itself
    tasks.forEach(({method, args}) => {
      this[method].apply(this, args);
    });
  }

  defer(method, args) {
    this.deferredTasks.push({method, args});
  }

  registerCategory(category) {
    if (!this.definition.find((element) => element.category === category)) {
      this.definition.push({
        category,
        children: []
      });
    }

    this.emit(NAVIGATION_CHANGE);
  }

  registerPrimary(path, link, options = {}) {
    const {category = 'root'} = options;
    const categoryElement = this.definition
      .find((element) => element.category === category);

    if (!categoryElement) {
      return this.defer('registerPrimary', arguments);
    }

    const existingElement = categoryElement.children.find((element) => {
      return element.path === path;
    });

    if (existingElement) {
      return;
    }

    categoryElement.children.push({
      path,
      link,
      options,
      children: []
    });

    this.emit(NAVIGATION_CHANGE);
  }

  registerSecondary(parentPath, path, link, options = {}) {
    // flatten categories
    const primaryElements = this.definition.reduce((result, category) => {
      return result.concat(category.children);
    }, []);

    const parentElement = primaryElements
      .find((element) => element.path === parentPath);

    if (!parentElement) {
      return this.defer('registerSecondary', arguments);
    }

    const existingElement = parentElement.children.find((element) => {
      return element.path === path;
    });

    if (existingElement) {
      return;
    }

    parentElement.children.push({
      link,
      options,
      path: `${parentPath}/${path}`,
      children: []
    });

    this.emit(NAVIGATION_CHANGE);
  }
};

const service = new NavigationService();
export default service;
<|endoftext|>


<commit_before>var CursorMaintenanceDemo = (function () {
  'use strict';

  // This module requires CursorMaintainer and NoteExpander.

  var messages = {
        formatting: {
          off: '□formatting off',
          on: '■formatting on'
        }
      };

  function getCursorPosition(input) {
    return input.selectionStart;
  }

  function setCursorPosition(input, position) {
    input.setSelectionRange(position, position);
  }

  function setMaintainer(input, format, validate) {
    var saved = { text: null, cursor: 0 },
        formatted,
        toggleBox;
    function processInput() {
      var text,
          cursor,
          formatted;
      text = input.value;
      cursor = getCursorPosition(input);
      // If the input is invalid, restore the saved state and bail out.
      if (validate !== undefined && validate(text) !== true) {
        input.value = saved.text;
        setCursorPosition(input, saved.cursor);
        return;
      }
      // If formatting has been disabled, do nothing further.
      if (!input.status.formatting) {
        return;
      }
      // If the user has not changed the text, accept the user cursor.
      if (text === saved.text) {
        saved.cursor = cursor;
        return;
      }
      formatted = format(text, cursor);
      // If formatting leaves the user text unchanged, accept the user cursor.
      if (formatted.text === text) {
        saved.cursor = cursor;
        return;
      }
      input.value = saved.text = formatted.text;
      setCursorPosition(input, saved.cursor = formatted.cursor);
    }
    // Listen for events that can change the input value.
    [ 'change', 'keydown', 'keyup', 'click' ].forEach(function (eventName) {
      input.addEventListener(eventName, processInput);
    });
    // Add an element that allows the user to toggle formatting on and off.
    input.status = { formatting: false };
    toggleBox = document.createElement('div');
    toggleBox.className = 'toggle';
    toggleBox.onclick = function () {
      if (!input.status.formatting) {
        saved.text = null;
        input.status.formatting = true;
        this.className += ' active';
        toggleBox.innerHTML = messages.formatting.on;
        processInput();
      } else {
        input.status.formatting = false;
        this.className = this.className.replace(/\s*active\s*/, ' ');
        toggleBox.innerHTML = messages.formatting.off;
      }
      input.focus();
    };
    toggleBox.click();
    input.parentNode.insertBefore(toggleBox, input);
  }

  function commatizeValidator(text) {
    return /^[0-9,]*$/.test(text);
  }

  // makeFormatterFromInput reads user input from codeBox and evaluates it
  //  as JavaScript. It is generally thought to be unwise to evaluate
  //  user-provided code. In our case, the code is evaluated in the
  //  browser session in which the user entered the code. This incurs the
  //  same level of risk as the user executing arbitrary code in the
  //  browser's JavaScript console. In both cases, the code is entered
  //  voluntarily by the user and is executed only in the user's browser.
  function makeFormatterFromInput(codeBox) {
    var code = '',
        formatter = null,
        result;
    return function (text) {
      var error,
          okay = true;
      // Check for cached code.
      if (code !== codeBox.value) {
        code = codeBox.value;
        formatter = null;
        try {
          formatter = eval('(' + code + ')');
        } catch (error) {
          okay = false;
          console.log('error in evaluating input: ' + error);
        }
        if (typeof formatter !== 'function') {
          okay = false;
          formatter = null;
          console.log('input does not evaluate to a function');
        }
        if (okay) {
          codeBox.className = codeBox.className.replace(/\s+error\s*/, ' ');
        } else {
          codeBox.className += ' error';
        }
      }
      if (formatter === null) {
        result =  text;
      } else {
        result = formatter(text);
        if (typeof result !== 'string') {
          console.log('formatter does not yield a string: ' + result);
          result = text;
        }
      }
      return { text: result };
    };
  }

  function load() {
    var divs, i, notes, columns, content, snippet;

    // Meta version of commatize accompanied by an input validator.
    setMaintainer(document.getElementById('commatizeInput'),
        CursorMaintainer.meta.commatize, commatizeValidator);

    // Meta version of trimify. No input validation.
    setMaintainer(document.getElementById('trimifyInput'),
        CursorMaintainer.meta.trimify);

    // Retrospective approach with balanced frequencies applied to a
    //  user-defined formatting function. No input validation.
    console.log(CursorMaintainer.cost.balancedFrequencies);
    setMaintainer(document.getElementById('retrospectiveInput'),
        CursorMaintainer.retrospective.make(
          makeFormatterFromInput(document.getElementById('retrospectiveCode')),
          CursorMaintainer.cost.balancedFrequencies));

    // Layer approach applied to a user-defined formatting function.
    //  No input validation.
    //setMaintainer(document.getElementById('layerInput'),
    //    makeFlexibleMaintainer(document.getElementById('layerCode')));

    // Fill input and code box with sample content.
    document.getElementById('commatizeInput').value = '3171814';
    document.getElementById('commatizeInput').click();
    document.getElementById('trimifyInput').value =
        "\"Other maps are such shapes, with their islands and capes! / " +
        "   But we've got our brave Captain to thank\" / " +
        "(So the crew would protest) \"that he's bought us the best— / " +
        "   A perfect and absolute blank!\"";
    document.getElementById('trimifyInput').click();
    document.getElementById('retrospectiveCode').value = "function (s) {\n" +
        "  // Comma-separated dollar amount with unlimited cent precision.\n" +
        "  var decimalPos, whole, fraction, start, groups, i;\n" +
        "  s = s.replace(/[^0-9.]/g, '');\n" +
        "  s = s.replace(/^0+/, '0');\n" +
        "  if (s.length >= 2 && s.charAt(0) == '0' && s.charAt(1) != '.') {\n" +
        "    s = s.substring(1);\n" +
        "  }\n" +
        "  decimalPos = s.indexOf('.');\n" +
        "  s = s.replace(/[.]/g, '');\n" +
        "  whole = (decimalPos == -1 ? s : s.substring(0, decimalPos));\n" +
        "  start = whole.length % 3 || 3;\n" +
        "  groups = [ whole.substring(0, start) ];\n" +
        "  for (i = start; i < whole.length; i += 3) {\n" +
        "    groups.push(whole.substring(i, i + 3));\n" +
        "  }\n" +
        "  whole = groups.join(',');\n" +
        "  s = whole + (decimalPos == -1 ?\n" +
        "      '' : '.' + s.substring(decimalPos));\n" +
        "  return '$' + s;\n" +
        "}"
    document.getElementById('retrospectiveInput').value = '29031.925';
    document.getElementById('retrospectiveInput').click();
    document.getElementById('layerCode').value =
        document.getElementById('retrospectiveCode').value;
    document.getElementById('layerInput').value =
        document.getElementById('retrospectiveInput').value;
    document.getElementById('layerInput').click();
    document.getElementById('layerInput').blur();

    // The page position may have been changed by focus events as the input
    //  fields were initialized. Let's reset to the upper left corner.
    //scrollTo(0, 0);

    // Add expander widgets to note sections. Notes are collapsed by default.
    NoteExpander.enableByTagAndClass(document, 'div', 'notes');
  }

  return {
    load: load
  };
})();

onload = CursorMaintenanceDemo.load;
<commit_msg>Structure layer maker<commit_after>var CursorMaintenanceDemo = (function () {
  'use strict';

  // This module requires CursorMaintainer and NoteExpander.

  var messages = {
        formatting: {
          off: '□formatting off',
          on: '■formatting on'
        }
      };

  function getCursorPosition(input) {
    return input.selectionStart;
  }

  function setCursorPosition(input, position) {
    input.setSelectionRange(position, position);
  }

  function setMaintainer(input, format, validate) {
    var saved = { text: null, cursor: 0 },
        formatted,
        toggleBox;
    function processInput() {
      var text,
          cursor,
          formatted;
      text = input.value;
      cursor = getCursorPosition(input);
      // If the input is invalid, restore the saved state and bail out.
      if (validate !== undefined && validate(text) !== true) {
        input.value = saved.text;
        setCursorPosition(input, saved.cursor);
        return;
      }
      // If formatting has been disabled, do nothing further.
      if (!input.status.formatting) {
        return;
      }
      // If the user has not changed the text, accept the user cursor.
      if (text === saved.text) {
        saved.cursor = cursor;
        return;
      }
      formatted = format(text, cursor);
      // If formatting leaves the user text unchanged, accept the user cursor.
      if (formatted.text === text) {
        saved.cursor = cursor;
        return;
      }
      input.value = saved.text = formatted.text;
      setCursorPosition(input, saved.cursor = formatted.cursor);
    }
    // Listen for events that can change the input value.
    [ 'change', 'keydown', 'keyup', 'click' ].forEach(function (eventName) {
      input.addEventListener(eventName, processInput);
    });
    // Add an element that allows the user to toggle formatting on and off.
    input.status = { formatting: false };
    toggleBox = document.createElement('div');
    toggleBox.className = 'toggle';
    toggleBox.onclick = function () {
      if (!input.status.formatting) {
        saved.text = null;
        input.status.formatting = true;
        this.className += ' active';
        toggleBox.innerHTML = messages.formatting.on;
        processInput();
      } else {
        input.status.formatting = false;
        this.className = this.className.replace(/\s*active\s*/, ' ');
        toggleBox.innerHTML = messages.formatting.off;
      }
      input.focus();
    };
    toggleBox.click();
    input.parentNode.insertBefore(toggleBox, input);
  }

  function commatizeValidator(text) {
    return /^[0-9,]*$/.test(text);
  }

  // makeFormatterFromInput reads user input from codeBox and evaluates it
  //  as JavaScript. It is generally thought to be unwise to evaluate
  //  user-provided code. In our case, the code is evaluated in the
  //  browser session in which the user entered the code. This incurs the
  //  same level of risk as the user executing arbitrary code in the
  //  browser's JavaScript console. In both cases, the code is entered
  //  voluntarily by the user and is executed only in the user's browser.
  function makeFormatterFromInput(codeBox) {
    var code = '',
        formatter = null,
        result;
    return function (text) {
      var error,
          okay = true;
      // Check for cached code.
      if (code !== codeBox.value) {
        code = codeBox.value;
        formatter = null;
        try {
          formatter = eval('(' + code + ')');
        } catch (error) {
          okay = false;
          console.log('error in evaluating input: ' + error);
        }
        if (typeof formatter !== 'function') {
          okay = false;
          formatter = null;
          console.log('input does not evaluate to a function');
        }
        if (okay) {
          codeBox.className = codeBox.className.replace(/\s+error\s*/, ' ');
        } else {
          codeBox.className += ' error';
        }
      }
      if (formatter === null) {
        result =  text;
      } else {
        result = formatter(text);
        if (typeof result !== 'string') {
          console.log('formatter does not yield a string: ' + result);
          result = text;
        }
      }
      return { text: result };
    };
  }

  function getTesters() {
  }

  function getPreferRight() {
  }

  function load() {
    var divs, i, notes, columns, content, snippet;

    // Meta version of commatize accompanied by an input validator.
    setMaintainer(document.getElementById('commatizeInput'),
        CursorMaintainer.meta.commatize, commatizeValidator);

    // Meta version of trimify. No input validation.
    setMaintainer(document.getElementById('trimifyInput'),
        CursorMaintainer.meta.trimify);

    // Retrospective approach with balanced frequencies applied to a
    //  user-defined formatting function. No input validation.
    console.log(CursorMaintainer.cost.balancedFrequencies);
    setMaintainer(document.getElementById('retrospectiveInput'),
        CursorMaintainer.retrospective.make(
          makeFormatterFromInput(document.getElementById('retrospectiveCode')),
          CursorMaintainer.cost.balancedFrequencies));

    // Layer approach applied to a user-defined formatting function.
    //  No input validation.
    setMaintainer(document.getElementById('layerInput'),
        makeFormatterFromInput(document.getElementById('retrospectiveCode')),
        getTesters(),
        getPreferRight);

    // Fill input and code box with sample content.
    document.getElementById('commatizeInput').value = '3171814';
    document.getElementById('commatizeInput').click();
    document.getElementById('trimifyInput').value =
        "\"Other maps are such shapes, with their islands and capes! / " +
        "   But we've got our brave Captain to thank\" / " +
        "(So the crew would protest) \"that he's bought us the best— / " +
        "   A perfect and absolute blank!\"";
    document.getElementById('trimifyInput').click();
    document.getElementById('retrospectiveCode').value = "function (s) {\n" +
        "  // Comma-separated dollar amount with unlimited cent precision.\n" +
        "  var decimalPos, whole, fraction, start, groups, i;\n" +
        "  s = s.replace(/[^0-9.]/g, '');\n" +
        "  s = s.replace(/^0+/, '0');\n" +
        "  if (s.length >= 2 && s.charAt(0) == '0' && s.charAt(1) != '.') {\n" +
        "    s = s.substring(1);\n" +
        "  }\n" +
        "  decimalPos = s.indexOf('.');\n" +
        "  s = s.replace(/[.]/g, '');\n" +
        "  whole = (decimalPos == -1 ? s : s.substring(0, decimalPos));\n" +
        "  start = whole.length % 3 || 3;\n" +
        "  groups = [ whole.substring(0, start) ];\n" +
        "  for (i = start; i < whole.length; i += 3) {\n" +
        "    groups.push(whole.substring(i, i + 3));\n" +
        "  }\n" +
        "  whole = groups.join(',');\n" +
        "  s = whole + (decimalPos == -1 ?\n" +
        "      '' : '.' + s.substring(decimalPos));\n" +
        "  return '$' + s;\n" +
        "}"
    document.getElementById('retrospectiveInput').value = '29031.925';
    document.getElementById('retrospectiveInput').click();
    document.getElementById('layerCode').value =
        document.getElementById('retrospectiveCode').value;
    document.getElementById('layerInput').value =
        document.getElementById('retrospectiveInput').value;
    document.getElementById('layerInput').click();
    document.getElementById('layerInput').blur();

    // The page position may have been changed by focus events as the input
    //  fields were initialized. Let's reset to the upper left corner.
    //scrollTo(0, 0);

    // Add expander widgets to note sections. Notes are collapsed by default.
    NoteExpander.enableByTagAndClass(document, 'div', 'notes');
  }

  return {
    load: load
  };
})();

onload = CursorMaintenanceDemo.load;
<|endoftext|>


<commit_before>//
//Copyright (c) 2013, Priologic Software Inc.
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
//LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
var selfEasyrtcid = "";
var connectList = {};

function addToConversation(who, content) {
    // Escape html special characters, then add linefeeds.
    content = content.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
    content = content.replace(/\n/g, '
');
    document.getElementById('conversation').innerHTML +=
    "" + who + ": " + content + "
";
}

function connect() {
    easyRTC.enableDebug(false);
    easyRTC.enableDataChannels(true);
    easyRTC.enableVideo(false);
    easyRTC.enableAudio(false);

    easyRTC.setDataListener(addToConversation);
    easyRTC.setLoggedInListener(loggedInListener);
    easyRTC.connect("data_channel_im", loginSuccess, loginFailure);
}

function loggedInListener (data) {
    connectList = data;
    convertListToButtons(connectList);
}

function convertListToButtons (connectList) {

    otherClientDiv = document.getElementById('otherClients');
    while (otherClientDiv.hasChildNodes()) {
        otherClientDiv.removeChild(otherClientDiv.lastChild);
    }

    var label, button;
    for(var i in connectList) {
        var rowGroup = document.createElement("span");
        var rowLabel = document.createTextNode(easyRTC.idToName(i));
        rowGroup.appendChild(rowLabel);

        button = document.createElement('button');
        button.onclick = function(easyrtcid) {
            return function() {
                startCall(easyrtcid);
            }
        }(i);
        label = document.createTextNode("Connect");
        button.appendChild(label);
        rowGroup.appendChild(button);

        button = document.createElement('button');
        button.onclick = function(easyrtcid) {
            return function() {
                sendStuffP2P(easyrtcid);
            }
        }(i);
        label = document.createTextNode("Send Message");
        button.appendChild(label);
        rowGroup.appendChild(button);

        otherClientDiv.appendChild(rowGroup);
    }
    if( !otherClientDiv.hasChildNodes() ) {
        otherClientDiv.innerHTML = "Nobody else logged in to talk to...";
    }
}

function startCall(otherEasyrtcid) {
    if( easyRTC.getConnectStatus(otherEasyrtcid) == easyRTC.NOT_CONNECTED) {
        easyRTC.call(otherEasyrtcid,
            function(caller, media) { // success callback
                if( media == 'datachannel') {
                    console.log("made call succesfully");
                    connectList[otherEasyrtcid] = true;
                }
            },
            function(errText) {
                connectList[otherEasyrtcid] = false;
                easyRTC.showError("CALL-FAILURE", errText);
            },
            function(wasAccepted) {
                console.log("was accepted=" + wasAccepted);
            }
            );
    }
    else {
        easyRTC.showError("ALREADY-CONNECTED", "already connected to " + easyRTC.idToName(otherEasyrtcid));
    }
}

function sendStuffP2P(otherEasyrtcid) {
    var text = document.getElementById('sendMessageText').value;
    if(text.replace(/\s/g, "").length == 0) { // Don't send just whitespace
        return;
    }
    if( easyRTC.getConnectStatus(otherEasyrtcid) == easyRTC.IS_CONNECTED) {
        easyRTC.sendDataP2P(otherEasyrtcid, text);
    }
    else {
        easyRTC.showError("NOT-CONNECTED", "not connected to " + easyRTC.idToName(otherEasyrtcid) + " yet.");
    }
    addToConversation("Me", text);
    document.getElementById('sendMessageText').value = "";
}

function loginSuccess(easyRTCId) {
    selfEasyrtcid = easyRTCId;
    document.getElementById("iam").innerHTML = "I am " + easyRTCId;
}

function loginFailure(message) {
    easyRTC.showError("LOGIN-FAILURE", "failure to login");
}
<commit_msg>turned off debugging.<commit_after>//
//Copyright (c) 2013, Priologic Software Inc.
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions are met:
//
//    * Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
//LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
var selfEasyrtcid = "";
var connectList = {};

function addToConversation(who, content) {
    // Escape html special characters, then add linefeeds.
    content = content.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
    content = content.replace(/\n/g, '
');
    document.getElementById('conversation').innerHTML +=
    "" + who + ": " + content + "
";
}

function connect() {
    easyRTC.enableDebug(false);
    easyRTC.enableDataChannels(true);
    easyRTC.enableVideo(false);
    easyRTC.enableAudio(false);

    easyRTC.setPeerListener(addToConversation);
    easyRTC.setLoggedInListener(loggedInListener);
    easyRTC.connect("data_channel_im", loginSuccess, loginFailure);
}

function loggedInListener (data) {
    connectList = data;
    convertListToButtons(connectList);
}

function convertListToButtons (connectList) {

    otherClientDiv = document.getElementById('otherClients');
    while (otherClientDiv.hasChildNodes()) {
        otherClientDiv.removeChild(otherClientDiv.lastChild);
    }

    var label, button;
    for(var i in connectList) {
        var rowGroup = document.createElement("span");
        var rowLabel = document.createTextNode(easyRTC.idToName(i));
        rowGroup.appendChild(rowLabel);

        button = document.createElement('button');
        button.onclick = function(easyrtcid) {
            return function() {
                startCall(easyrtcid);
            }
        }(i);
        label = document.createTextNode("Connect");
        button.appendChild(label);
        rowGroup.appendChild(button);

        button = document.createElement('button');
        button.onclick = function(easyrtcid) {
            return function() {
                sendStuffP2P(easyrtcid);
            }
        }(i);
        label = document.createTextNode("Send Message");
        button.appendChild(label);
        rowGroup.appendChild(button);

        otherClientDiv.appendChild(rowGroup);
    }
    if( !otherClientDiv.hasChildNodes() ) {
        otherClientDiv.innerHTML = "Nobody else logged in to talk to...";
    }
}

function startCall(otherEasyrtcid) {
    if( easyRTC.getConnectStatus(otherEasyrtcid) == easyRTC.NOT_CONNECTED) {
        easyRTC.call(otherEasyrtcid,
            function(caller, media) { // success callback
                if( media == 'datachannel') {
                    console.log("made call succesfully");
                    connectList[otherEasyrtcid] = true;
                }
            },
            function(errText) {
                connectList[otherEasyrtcid] = false;
                easyRTC.showError("CALL-FAILURE", errText);
            },
            function(wasAccepted) {
                console.log("was accepted=" + wasAccepted);
            }
            );
    }
    else {
        easyRTC.showError("ALREADY-CONNECTED", "already connected to " + easyRTC.idToName(otherEasyrtcid));
    }
}

function sendStuffP2P(otherEasyrtcid) {
    var text = document.getElementById('sendMessageText').value;
    if(text.replace(/\s/g, "").length == 0) { // Don't send just whitespace
        return;
    }
    if( easyRTC.getConnectStatus(otherEasyrtcid) == easyRTC.IS_CONNECTED) {
        easyRTC.sendDataP2P(otherEasyrtcid, text);
    }
    else {
        easyRTC.showError("NOT-CONNECTED", "not connected to " + easyRTC.idToName(otherEasyrtcid) + " yet.");
    }
    addToConversation("Me", text);
    document.getElementById('sendMessageText').value = "";
}

function loginSuccess(easyRTCId) {
    selfEasyrtcid = easyRTCId;
    document.getElementById("iam").innerHTML = "I am " + easyRTCId;
}

function loginFailure(message) {
    easyRTC.showError("LOGIN-FAILURE", "failure to login");
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

importScript("../js/util/aUtil.js");
importScript("../js/util/aString.js");
importScript("owners.js");

var HIGHLIGHT=Color.blue.hue(60).multiply(0.6);

if (typeof OWNERS != 'undefined'){
	OWNERS = Map.zip(mapAllKey(OWNERS, function (k, v) {
		var manager;
		var owner;
		//PARSE THE <manager> "(" listOf(<assign_to>) ")" FORMAT
		if (v.indexOf("(") >= 0) {
			manager = v.left(v.indexOf("(")).trim();
			owner = v.between("(", ")").trim();
		} else {
			manager = v.trim();
			owner = "";
		}//endif

		var name = k.replaceLast(["::", ": ", ":"], "
");
		return [k.deformat(), {"name": name, "owner": {"name": owner, "manager": manager}}];
	}));
}//endif

function getComponentDetails(comp) {
	var output = OWNERS[comp.deformat()];
	if (output !== undefined) return output;

	var name = comp.replaceLast(["::", ": ", ":"], "
");
	output = {"name": name, "owner": {"name": "", "manager": ""}};
	OWNERS[comp.deformat()] = output;
	return output;
}//function

// SHOW BLOCKER COUNT FOR ONE COMPONENT
function showComponent(detail, showTYPE) {
	var TEMPLATE = new Template('
' +
		'
{{component}}
' +
		'
{{manager}}
' +
		'
{{owner}}
' +
		'{{projectDetail}}' +
		'
');

	var component = Map.copy(detail[0]);
	var meta =  getComponentDetails(component.component);
	component.component = meta.name;
	component.manager = meta.owner.manager;
	component.owner = meta.owner.name=="" ? "": "(" + meta.owner.name + ")";
	component.projectDetail = detail.map(function (project, i) {
		if (project.count > 0) {
			return showTYPE(project);
		}//endif
	}).join("");
	return TEMPLATE.replace(component)
}//function

// SHOW SUMMARY COUNT
function showSummary(type, team, detail, specialBugs, showTYPE) {

	var TEMPLATE = new Template(
		'
{{name}} {{type}}

' +
		'{{projectDetail}}' +
		'

' +
		'{{total}}' +
		'

' +
		'{{specialDetail}}' +
		'
');

	var total = aMath.sum.apply(undefined, detail.cube.select("count"));
	var component = {};

	if (team.length==0){
		component.name = "FxOS"
	}else{
		component.name = team.map(function(t){return t.name;}).join(", ")
	}//endif

	var numSummary=0;
	component.projectDetail = detail.cube.map(function (project, i) {
		project.project = detail.edges[0].domain.partitions[i].name;
		if (project.count > 0) {
			numSummary++;
			return showTYPE(project);
		}//endif
	}).join("");
	if (numSummary<2) component.projectDetail="";

	if (specialBugs){
		component.specialDetail = showTYPE(specialBugs);
	}else{
		component.specialDetail = "";
	}//endif

	component.total=showTYPE({
		"project":"Total",
		"count":aMath.sum.apply(undefined, detail.cube.select("count")),
		"unassignedCount":aMath.sum.apply(undefined, detail.cube.select("unassignedCount")),
		"age":aMath.max.apply(undefined, detail.cube.select("age")),
		"bugs":detail.from.list.select("bug_id"),
		"unassignedBugs": detail.from.list.filter(Mozilla.B2G.Unassigned.esfilter).select("bug_id"),
		"additionalClass": "project-summary"

	});
	component.type=type;

	return TEMPLATE.replace(component)
}//function

// SHOW TRIAGE COUNT FOR ONE COMPONENT, ONE PROJECT
function showNominations(detail) {
	detail.bugsList = detail.bugs.join(",");
	detail.bugsURL = Bugzilla.searchBugsURL(detail.bugs);
	detail.unassignedURL = Bugzilla.searchBugsURL(detail.unassignedBugs);
	detail.color = age2color(detail.age).toHTML();

	var TEMPLATE = new Template(
		'
' +
		'
{{project}}
' +
		'
{{count}}
' +
		'
');

	return TEMPLATE.replace(detail)
}//function

// SHOW BLOCKER COUNT FOR ONE COMPONENT, ONE PROJECT
function showBlocker(detail) {
	detail.bugsList=detail.bugs.join(", ");
	detail.bugsURL = Bugzilla.searchBugsURL(detail.bugs);
	detail.unassignedURL = Bugzilla.searchBugsURL(detail.unassignedBugs);
	detail.color = age2color(detail.age).toHTML();

	var TEMPLATE = new Template('
' +
		'
{{project}}
' +
		'
{{count}}
' +
		(detail.unassignedCount > 0 ? '
{{unassignedCount}}
' : '') +
		'
');

	return TEMPLATE.replace(detail)
}//function

// SHOW BLOCKER COUNT FOR ONE COMPONENT, ONE PROJECT
function showRegression(detail) {
	detail.bugsList = detail.bugs.join(",");
	detail.bugsURL = Bugzilla.searchBugsURL(detail.bugs);
	detail.unassignedURL = Bugzilla.searchBugsURL(detail.unassignedBugs);
	detail.color = age2color(detail.age).toHTML();

	var TEMPLATE = new Template('
' +
		'
{{project}}
' +
		'
{{count}}
' +
		(detail.unassignedCount > 0 ? '
{{unassignedCount}}
' : '') +
		'
');

	return TEMPLATE.replace(detail)
}//function

function addProjectClickers(cube) {
	$(".project").hover(function (e) {
		var old_color = $(this).attr("old_color");
		if (old_color == undefined) {
			old_color = $(this).css("background-color");
			$(this).attr("old_color", old_color);
		}//endif
		$(this).css("background-color", Color.newHTML(old_color).lighter().toHTML());
	},function (e) {
		var old_color = $(this).attr("old_color");
		$(this).css("background-color", old_color);
	}).click(function (e) {
		var link = $(this).attr("href");
		window.open(link);
	});

	$(".count_unassigned").click(function (e) {
		var link = $(this).attr("href");
		window.open(link);
		return false;
	});

	$(".project-summary").hover(function (e) {
		var self = $(this);
		var bugs = self.attr("bugsList").split(",").map(function (v) {
			return CNV.String2Integer(v.trim());
		});
		$(".project").filter(function(){
			var pro = $(this);

			if (pro.get(0)==self.get(0)) return true;
			if (pro.hasClass("project-summary")) return false;
			var thisBugs=pro.attr("bugsList").split(",").map(function(v){return CNV.String2Integer(v.trim());});
			return bugs.intersect(thisBugs).length>0;
		}).each(function(){
			var old_color = $(this).attr("old_color");
			if (old_color == undefined) {
				old_color = $(this).css("background-color");
				$(this).attr("old_color", old_color);
			}//endif
			$(this).css("background-color", HIGHLIGHT.toHTML());
		})
	},function (e) {
		$(".project").each(function(){
			var old_color = $(this).attr("old_color");
			$(this).css("background-color", old_color);
		});
	});
}//function

function age2color(age) {
	var green = Color.green.multiply(0.4);
	var color = green.hue(Math.min(1.0, age / 7) * 120);
	return color;
}//function

//JUNK FOR THE Blockers/Regressions/Nominations
function heatCommon() {
	$("body").css("display", "block");

	$('.sidebar_name').click(function () {
		var self = $(this);
		if (self.hasClass("selected")) {
			self.removeClass("selected");
			$("#sidebar").animate({"width": "0px"}, 500);
			$(".content").animate({"padding-left":"40px"}, 500);
		} else {
			self.addClass("selected");
			$("#sidebar").animate({"width": "300px"}, 500);
			$(".content").animate({"padding-left":"340px"}, 500);
		}//endif
	});
}

function refresher(func){
	Thread.run(function*() {
		while (true) {
			yield(Thread.sleep(5 * 60 * 1000));
			func();
		}//while
	});
}

<commit_msg>Simpler refresh loop<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

importScript("../js/util/aUtil.js");
importScript("../js/util/aString.js");
importScript("owners.js");

var HIGHLIGHT=Color.blue.hue(60).multiply(0.6);

if (typeof OWNERS != 'undefined'){
	OWNERS = Map.zip(mapAllKey(OWNERS, function (k, v) {
		var manager;
		var owner;
		//PARSE THE <manager> "(" listOf(<assign_to>) ")" FORMAT
		if (v.indexOf("(") >= 0) {
			manager = v.left(v.indexOf("(")).trim();
			owner = v.between("(", ")").trim();
		} else {
			manager = v.trim();
			owner = "";
		}//endif

		var name = k.replaceLast(["::", ": ", ":"], "
");
		return [k.deformat(), {"name": name, "owner": {"name": owner, "manager": manager}}];
	}));
}//endif

function getComponentDetails(comp) {
	var output = OWNERS[comp.deformat()];
	if (output !== undefined) return output;

	var name = comp.replaceLast(["::", ": ", ":"], "
");
	output = {"name": name, "owner": {"name": "", "manager": ""}};
	OWNERS[comp.deformat()] = output;
	return output;
}//function

// SHOW BLOCKER COUNT FOR ONE COMPONENT
function showComponent(detail, showTYPE) {
	var TEMPLATE = new Template('
' +
		'
{{component}}
' +
		'
{{manager}}
' +
		'
{{owner}}
' +
		'{{projectDetail}}' +
		'
');

	var component = Map.copy(detail[0]);
	var meta =  getComponentDetails(component.component);
	component.component = meta.name;
	component.manager = meta.owner.manager;
	component.owner = meta.owner.name=="" ? "": "(" + meta.owner.name + ")";
	component.projectDetail = detail.map(function (project, i) {
		if (project.count > 0) {
			return showTYPE(project);
		}//endif
	}).join("");
	return TEMPLATE.replace(component)
}//function

// SHOW SUMMARY COUNT
function showSummary(type, team, detail, specialBugs, showTYPE) {

	var TEMPLATE = new Template(
		'
{{name}} {{type}}

' +
		'{{projectDetail}}' +
		'

' +
		'{{total}}' +
		'

' +
		'{{specialDetail}}' +
		'
');

	var total = aMath.sum.apply(undefined, detail.cube.select("count"));
	var component = {};

	if (team.length==0){
		component.name = "FxOS"
	}else{
		component.name = team.map(function(t){return t.name;}).join(", ")
	}//endif

	var numSummary=0;
	component.projectDetail = detail.cube.map(function (project, i) {
		project.project = detail.edges[0].domain.partitions[i].name;
		if (project.count > 0) {
			numSummary++;
			return showTYPE(project);
		}//endif
	}).join("");
	if (numSummary<2) component.projectDetail="";

	if (specialBugs){
		component.specialDetail = showTYPE(specialBugs);
	}else{
		component.specialDetail = "";
	}//endif

	component.total=showTYPE({
		"project":"Total",
		"count":aMath.sum.apply(undefined, detail.cube.select("count")),
		"unassignedCount":aMath.sum.apply(undefined, detail.cube.select("unassignedCount")),
		"age":aMath.max.apply(undefined, detail.cube.select("age")),
		"bugs":detail.from.list.select("bug_id"),
		"unassignedBugs": detail.from.list.filter(Mozilla.B2G.Unassigned.esfilter).select("bug_id"),
		"additionalClass": "project-summary"

	});
	component.type=type;

	return TEMPLATE.replace(component)
}//function

// SHOW TRIAGE COUNT FOR ONE COMPONENT, ONE PROJECT
function showNominations(detail) {
	detail.bugsList = detail.bugs.join(",");
	detail.bugsURL = Bugzilla.searchBugsURL(detail.bugs);
	detail.unassignedURL = Bugzilla.searchBugsURL(detail.unassignedBugs);
	detail.color = age2color(detail.age).toHTML();

	var TEMPLATE = new Template(
		'
' +
		'
{{project}}
' +
		'
{{count}}
' +
		'
');

	return TEMPLATE.replace(detail)
}//function

// SHOW BLOCKER COUNT FOR ONE COMPONENT, ONE PROJECT
function showBlocker(detail) {
	detail.bugsList=detail.bugs.join(", ");
	detail.bugsURL = Bugzilla.searchBugsURL(detail.bugs);
	detail.unassignedURL = Bugzilla.searchBugsURL(detail.unassignedBugs);
	detail.color = age2color(detail.age).toHTML();

	var TEMPLATE = new Template('
' +
		'
{{project}}
' +
		'
{{count}}
' +
		(detail.unassignedCount > 0 ? '
{{unassignedCount}}
' : '') +
		'
');

	return TEMPLATE.replace(detail)
}//function

// SHOW BLOCKER COUNT FOR ONE COMPONENT, ONE PROJECT
function showRegression(detail) {
	detail.bugsList = detail.bugs.join(",");
	detail.bugsURL = Bugzilla.searchBugsURL(detail.bugs);
	detail.unassignedURL = Bugzilla.searchBugsURL(detail.unassignedBugs);
	detail.color = age2color(detail.age).toHTML();

	var TEMPLATE = new Template('
' +
		'
{{project}}
' +
		'
{{count}}
' +
		(detail.unassignedCount > 0 ? '
{{unassignedCount}}
' : '') +
		'
');

	return TEMPLATE.replace(detail)
}//function

function addProjectClickers(cube) {
	$(".project").hover(function (e) {
		var old_color = $(this).attr("old_color");
		if (old_color == undefined) {
			old_color = $(this).css("background-color");
			$(this).attr("old_color", old_color);
		}//endif
		$(this).css("background-color", Color.newHTML(old_color).lighter().toHTML());
	},function (e) {
		var old_color = $(this).attr("old_color");
		$(this).css("background-color", old_color);
	}).click(function (e) {
		var link = $(this).attr("href");
		window.open(link);
	});

	$(".count_unassigned").click(function (e) {
		var link = $(this).attr("href");
		window.open(link);
		return false;
	});

	$(".project-summary").hover(function (e) {
		var self = $(this);
		var bugs = self.attr("bugsList").split(",").map(function (v) {
			return CNV.String2Integer(v.trim());
		});
		$(".project").filter(function(){
			var pro = $(this);

			if (pro.get(0)==self.get(0)) return true;
			if (pro.hasClass("project-summary")) return false;
			var thisBugs=pro.attr("bugsList").split(",").map(function(v){return CNV.String2Integer(v.trim());});
			return bugs.intersect(thisBugs).length>0;
		}).each(function(){
			var old_color = $(this).attr("old_color");
			if (old_color == undefined) {
				old_color = $(this).css("background-color");
				$(this).attr("old_color", old_color);
			}//endif
			$(this).css("background-color", HIGHLIGHT.toHTML());
		})
	},function (e) {
		$(".project").each(function(){
			var old_color = $(this).attr("old_color");
			$(this).css("background-color", old_color);
		});
	});
}//function

function age2color(age) {
	var green = Color.green.multiply(0.4);
	var color = green.hue(Math.min(1.0, age / 7) * 120);
	return color;
}//function

//JUNK FOR THE Blockers/Regressions/Nominations
function heatCommon() {
	$("body").css("display", "block");

	$('.sidebar_name').click(function () {
		var self = $(this);
		if (self.hasClass("selected")) {
			self.removeClass("selected");
			$("#sidebar").animate({"width": "0px"}, 500);
			$(".content").animate({"padding-left":"40px"}, 500);
		} else {
			self.addClass("selected");
			$("#sidebar").animate({"width": "300px"}, 500);
			$(".content").animate({"padding-left":"340px"}, 500);
		}//endif
	});
}

function refresher(func){
	function callMe(){
		try{
			func()
		}catch(e){

		}
	}//method
	setInterval(callMe, 5*60*1000);
}

<|endoftext|>


<commit_before>'use strict';
/*
We can use tls module to get the certificate.  All the needed data is inthere, just need get it and work with it.

http://stackoverflow.com/questions/14599901/read-expiration-date-and-common-name-from-ssl-certificate-using-node-js
Loop through array: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

require('tls');
var cn = tls.connect(443, "www.surveysage.com");
// the cert is in json form
var cert = cn.getPeerCertifiacte;
var san = cert.subjectaltname.split(',');
// trim leading space up and remove the 'DNS:' prefix
for (var item in san) {
  san[item] = san[item].trim();
  san[item] = san[item].substr(4);
}

*/

const certf = require('./cert');
certf.getCert('tlswatch.com', function (err, cert) {
  // look for error types, if (err & err.type == 'no cert, invalid domain')
  // invalid domain seems to throw an exception
  if (err) {
    console.error('Error retrieving certificate:\n', err);
    return;
  }

  const jsonCert = JSON.stringify(cert);
  console.log('cert:\n', jsonCert.subject);
});
//test()
return;

function test() {
  var https = require('https');
  var options = {
    host: 'brettski.com',
    port: 443,
    method:'GET',
    rejectUnauthorized: false
  };
  var cert;
  var req = https.request(options, function(res) {
    console.log('statusCode: ', res.statusCode);
    //console.log('headers: ', res.headers);
    console.log('response: ', res);
    res.on('data', function(d) {
      console.log(res.connection.getPeerCertificate());
      console.log('response url: ', res.responseUrl);
    });
    //cert = res.connection.getPeerCertificate();
    // Need to do stuff with cert at this point
    //console.log('cert' + cert);
    //req.end();
  });

  console.log(cert);
  req.end();
  console.log(cert);
}
<commit_msg>mongo<commit_after>'use strict';
/*
We can use tls module to get the certificate.  All the needed data is inthere, just need get it and work with it.

http://stackoverflow.com/questions/14599901/read-expiration-date-and-common-name-from-ssl-certificate-using-node-js
Loop through array: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

require('tls');
var cn = tls.connect(443, "www.surveysage.com");
// the cert is in json form
var cert = cn.getPeerCertifiacte;
var san = cert.subjectaltname.split(',');
// trim leading space up and remove the 'DNS:' prefix
for (var item in san) {
  san[item] = san[item].trim();
  san[item] = san[item].substr(4);
}
*/

const certf = require('./cert');
certf.getCert('tlswatch.com', function (err, cert) {
  // look for error types, if (err & err.type == 'no cert, invalid domain')
  // invalid domain seems to throw an exception
  if (err) {
    console.error('Error retrieving certificate:\n', err);
    return;
  }

  console.log('cert:\n', cert.subject);
  //mongo(cert);
});

return;

function mongo(cert) {
  var MongoClient = require('mongodb').MongoClient;
  var assert = require('assert');
  var mongovar = require('./mongodb.env');
  var uri = mongovar.mongodb.uri;
  //console.log('values:\n', uri);

  var insertCertificate = function (db, callback) {
    var collection = db.collection('certificate');
    collection.insert(cert, function(err, result) {
      assert.equal(err, null);
      assert.equal(1, result.result.n);
      assert.equal(1, result.ops.length);
      console.log('Inserted the certificate into the database');
      callback(result);
    });
  }

  var findCertificate = function(db, callback) {
    var collection = db.collection('certificate');
    collection.find({}).toArray(function(err, certs) {
      assert.equal(err, null);
      console.log('Found the following certs');
      console.log(certs);
      callback(certs);
    })
  }

  MongoClient.connect(uri, function(err, db) {
    assert.equal(null, err);
    console.log('Connected successfully to server');

    insertCertificate(db, function() {
      findCertificate(db, function() {
        db.close();
      });
    });
  });
}

function test() {
  var https = require('https');
  var options = {
    host: 'brettski.com',
    port: 443,
    method:'GET',
    rejectUnauthorized: false
  };
  var cert;
  var req = https.request(options, function(res) {
    console.log('statusCode: ', res.statusCode);
    //console.log('headers: ', res.headers);
    console.log('response: ', res);
    res.on('data', function(d) {
      console.log(res.connection.getPeerCertificate());
      console.log('response url: ', res.responseUrl);
    });
    //cert = res.connection.getPeerCertificate();
    // Need to do stuff with cert at this point
    //console.log('cert' + cert);
    //req.end();
  });

  console.log(cert);
  req.end();
  console.log(cert);
}
<|endoftext|>


<commit_before>var path = require("path")

const PROJECT_ROOT = path.resolve(__dirname)

module.exports = {
  entry: [
    "./scripts/dash-spinner/bar.js",
    "./scripts/dash-spinner/foo.js",
    "./scripts/dash-spinner/foo.coffee"
  ],
  output: {
    path: "./dist",
    filename: "new-spinner.js"
  },
  module: {
    loaders:[
      {
        include: [
          path.join(PROJECT_ROOT, "scripts"),
          path.join(PROJECT_ROOT, "spec")
        ],
        loader: "babel-loader",
        test: /\.js$/
      }, {
        include: [
          path.join(PROJECT_ROOT, "scripts"),
          path.join(PROJECT_ROOT, "spec")
        ],
        loader: "babel!coffee",
        test: /\.coffee$/
      }
    ]
  },
  resolve: {
    alias: {
      "dash_spinner": path.join(PROJECT_ROOT, "scripts", "dash-spinner")
    }
  }
}
<commit_msg>Add support for Bower to Webpack<commit_after>var webpack = require("webpack");
var path = require("path")

const PROJECT_ROOT = path.resolve(__dirname)

module.exports = {
  entry: [
    "./bower_components/underscore/underscore.js",
    "./scripts/dash-spinner/bar.js",
    "./scripts/dash-spinner/foo.js",
    "./scripts/dash-spinner/foo.coffee"
  ],
  output: {
    path: "./dist",
    filename: "new-spinner.js"
  },
  module: {
    loaders:[
      {
        include: [
          path.join(PROJECT_ROOT, "scripts"),
          path.join(PROJECT_ROOT, "spec")
        ],
        loader: "babel-loader",
        test: /\.js$/
      }, {
        include: [
          path.join(PROJECT_ROOT, "scripts"),
          path.join(PROJECT_ROOT, "spec")
        ],
        loader: "babel!coffee",
        test: /\.coffee$/
      }
    ]
  },
  plugins: [
    new webpack.ResolverPlugin(
      new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin(".bower.json", ["main"])
    )
  ],
  resolve: {
    alias: {
      "dash_spinner": path.join(PROJECT_ROOT, "scripts", "dash-spinner")
    }
  }
}
<|endoftext|>


<commit_before>/*
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import Promise from 'bluebird';

import utils from '../../utils';

/**
 * Internal module. in-memory storage for e2e.
 *
 * @module
 */

/**
 * @implements {module:crypto/store/base~CryptoStore}
 */
export default class MemoryCryptoStore {
    constructor() {
        this._outgoingRoomKeyRequests = [];
    }

    /**
     * Delete all data from this store.
     *
     * @returns {Promise} Promise which resolves when the store has been cleared.
     */
    deleteAllData() {
        return Promise.resolve();
    }

    /**
     * Look for an existing outgoing room key request, and if none is found,
     * add a new one
     *
     * @param {module:crypto/store/base~OutgoingRoomKeyRequest} request
     *
     * @returns {Promise} resolves to
     *    {@link module:crypto/store/base~OutgoingRoomKeyRequest}: either the
     *    same instance as passed in, or the existing one.
     */
    getOrAddOutgoingRoomKeyRequest(request) {
        const requestBody = request.requestBody;

        // first see if we already have an entry for this request.
        return this.getOutgoingRoomKeyRequest(requestBody).then((existing) => {
            if (existing) {
                // this entry matches the request - return it.
                console.log(
                    `already have key request outstanding for ` +
                    `${requestBody.room_id} / ${requestBody.session_id}: ` +
                    `not sending another`,
                );
                return existing;
            }

            // we got to the end of the list without finding a match
            // - add the new request.
            console.log(
                `enqueueing key request for ${requestBody.room_id} / ` +
                requestBody.session_id,
            );
            this._outgoingRoomKeyRequests.push(request);
            return request;
        });
    }

    /**
     * Look for an existing room key request
     *
     * @param {module:crypto~RoomKeyRequestBody} requestBody
     *    existing request to look for
     *
     * @return {Promise} resolves to the matching
     *    {@link module:crypto/store/base~OutgoingRoomKeyRequest}, or null if
     *    not found
     */
    getOutgoingRoomKeyRequest(requestBody) {
        for (const existing of this._outgoingRoomKeyRequests) {
            if (utils.deepCompare(existing.requestBody, requestBody)) {
                return Promise.resolve(existing);
            }
        }
        return Promise.resolve(null);
    }

    /**
     * Look for room key requests by state
     *
     * @param {Array<Number>} wantedStates list of acceptable states
     *
     * @return {Promise} resolves to the a
     *    {@link module:crypto/store/base~OutgoingRoomKeyRequest}, or null if
     *    there are no pending requests in those states
     */
    getOutgoingRoomKeyRequestByState(wantedStates) {
        for (const req of this._outgoingRoomKeyRequests) {
            for (const state of wantedStates) {
                if (req.state === state) {
                    return Promise.resolve(req);
                }
            }
        }
        return Promise.resolve(null);
    }

    /**
     * Look for an existing room key request by id and state, and update it if
     * found
     *
     * @param {string} requestId      ID of request to update
     * @param {number} expectedState  state we expect to find the request in
     * @param {Object} updates        name/value map of updates to apply
     *
     * @returns {Promise} resolves to
     *    {@link module:crypto/store/base~OutgoingRoomKeyRequest}
     *    updated request, or null if no matching row was found
     */
    updateOutgoingRoomKeyRequest(requestId, expectedState, updates) {
        for (const req of this._outgoingRoomKeyRequests) {
            if (req.requestId !== requestId) {
                continue;
            }

            if (req.state != expectedState) {
                console.warn(
                    `Cannot update room key request from ${expectedState} ` +
                    `as it was already updated to ${req.state}`,
                );
                return Promise.resolve(null);
            }
            Object.assign(req, updates);
            return Promise.resolve(req);
        }

        return Promise.resolve(null);
    }

    /**
     * Look for an existing room key request by id and state, and delete it if
     * found
     *
     * @param {string} requestId      ID of request to update
     * @param {number} expectedState  state we expect to find the request in
     *
     * @returns {Promise} resolves once the operation is completed
     */
    deleteOutgoingRoomKeyRequest(requestId, expectedState) {
        for (let i = 0; i < this._outgoingRoomKeyRequests.length; i++) {
            const req = this._outgoingRoomKeyRequests[i];

            if (req.requestId !== requestId) {
                continue;
            }

            if (req.state != expectedState) {
                console.warn(
                    `Cannot delete room key request in state ${req.state} `
                    + `(expected ${expectedState})`,
                );
                return Promise.resolve(null);
            }

            this._outgoingRoomKeyRequests.splice(i, 1);
            return Promise.resolve(req);
        }

        return Promise.resolve(null);
    }
}
<commit_msg>Fix spamming of key-share-requests<commit_after>/*
Copyright 2017 Vector Creations Ltd

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import Promise from 'bluebird';

import utils from '../../utils';

/**
 * Internal module. in-memory storage for e2e.
 *
 * @module
 */

/**
 * @implements {module:crypto/store/base~CryptoStore}
 */
export default class MemoryCryptoStore {
    constructor() {
        this._outgoingRoomKeyRequests = [];
    }

    /**
     * Delete all data from this store.
     *
     * @returns {Promise} Promise which resolves when the store has been cleared.
     */
    deleteAllData() {
        return Promise.resolve();
    }

    /**
     * Look for an existing outgoing room key request, and if none is found,
     * add a new one
     *
     * @param {module:crypto/store/base~OutgoingRoomKeyRequest} request
     *
     * @returns {Promise} resolves to
     *    {@link module:crypto/store/base~OutgoingRoomKeyRequest}: either the
     *    same instance as passed in, or the existing one.
     */
    getOrAddOutgoingRoomKeyRequest(request) {
        const requestBody = request.requestBody;

        return Promise.try(() => {
            // first see if we already have an entry for this request.
            const existing = this._getOutgoingRoomKeyRequest(requestBody);

            if (existing) {
                // this entry matches the request - return it.
                console.log(
                    `already have key request outstanding for ` +
                    `${requestBody.room_id} / ${requestBody.session_id}: ` +
                    `not sending another`,
                );
                return existing;
            }

            // we got to the end of the list without finding a match
            // - add the new request.
            console.log(
                `enqueueing key request for ${requestBody.room_id} / ` +
                requestBody.session_id,
            );
            this._outgoingRoomKeyRequests.push(request);
            return request;
        });
    }

    /**
     * Look for an existing room key request
     *
     * @param {module:crypto~RoomKeyRequestBody} requestBody
     *    existing request to look for
     *
     * @return {Promise} resolves to the matching
     *    {@link module:crypto/store/base~OutgoingRoomKeyRequest}, or null if
     *    not found
     */
    getOutgoingRoomKeyRequest(requestBody) {
        return Promise.resolve(this._getOutgoingRoomKeyRequest(requestBody));
    }

    /**
     * Looks for existing room key request, and returns the result synchronously.
     *
     * @internal
     *
     * @param {module:crypto~RoomKeyRequestBody} requestBody
     *    existing request to look for
     *
     * @return {module:crypto/store/base~OutgoingRoomKeyRequest?}
     *    the matching request, or null if not found
     */
    _getOutgoingRoomKeyRequest(requestBody) {
        for (const existing of this._outgoingRoomKeyRequests) {
            if (utils.deepCompare(existing.requestBody, requestBody)) {
                return existing;
            }
        }
        return null;
    }

    /**
     * Look for room key requests by state
     *
     * @param {Array<Number>} wantedStates list of acceptable states
     *
     * @return {Promise} resolves to the a
     *    {@link module:crypto/store/base~OutgoingRoomKeyRequest}, or null if
     *    there are no pending requests in those states
     */
    getOutgoingRoomKeyRequestByState(wantedStates) {
        for (const req of this._outgoingRoomKeyRequests) {
            for (const state of wantedStates) {
                if (req.state === state) {
                    return Promise.resolve(req);
                }
            }
        }
        return Promise.resolve(null);
    }

    /**
     * Look for an existing room key request by id and state, and update it if
     * found
     *
     * @param {string} requestId      ID of request to update
     * @param {number} expectedState  state we expect to find the request in
     * @param {Object} updates        name/value map of updates to apply
     *
     * @returns {Promise} resolves to
     *    {@link module:crypto/store/base~OutgoingRoomKeyRequest}
     *    updated request, or null if no matching row was found
     */
    updateOutgoingRoomKeyRequest(requestId, expectedState, updates) {
        for (const req of this._outgoingRoomKeyRequests) {
            if (req.requestId !== requestId) {
                continue;
            }

            if (req.state != expectedState) {
                console.warn(
                    `Cannot update room key request from ${expectedState} ` +
                    `as it was already updated to ${req.state}`,
                );
                return Promise.resolve(null);
            }
            Object.assign(req, updates);
            return Promise.resolve(req);
        }

        return Promise.resolve(null);
    }

    /**
     * Look for an existing room key request by id and state, and delete it if
     * found
     *
     * @param {string} requestId      ID of request to update
     * @param {number} expectedState  state we expect to find the request in
     *
     * @returns {Promise} resolves once the operation is completed
     */
    deleteOutgoingRoomKeyRequest(requestId, expectedState) {
        for (let i = 0; i < this._outgoingRoomKeyRequests.length; i++) {
            const req = this._outgoingRoomKeyRequests[i];

            if (req.requestId !== requestId) {
                continue;
            }

            if (req.state != expectedState) {
                console.warn(
                    `Cannot delete room key request in state ${req.state} `
                    + `(expected ${expectedState})`,
                );
                return Promise.resolve(null);
            }

            this._outgoingRoomKeyRequests.splice(i, 1);
            return Promise.resolve(req);
        }

        return Promise.resolve(null);
    }
}
<|endoftext|>


<commit_before>'use strict';

/**
 * Mongoose plugin
 */
const _ = require('lodash');
const mongoose = require('mongoose');
const Promise = require('bluebird');

/**
 * Setup counter schema and model
 *
 * @type {mongoose}
 */
const CounterSchema = new mongoose.Schema({
  model: {
    type: String,
    require: true,
  },
  field: {
    type: String,
    require: true,
  },
  count: {
    type: Number,
    default: 0,
  },
});

CounterSchema.index(
  { field: 1, model: 1 },
  { unique: true, required: true, index: -1 }
);

const Counter = mongoose.model('_Counter', CounterSchema);

/**
 * Reset counter sequence start
 *
 * @param {Object} options Mongoose plugin options
 * @return {Promise} Promise fulfilled when sequence has been reset
 */
function resetSequence(options) {
  return Counter.findOneAndUpdate(
    { model: options.model, field: options.field },
    { count: options.start - options.increment },
    { new: true, upsert: true });
}

/**
 * Calculate the current count
 *
 * @param {Object} options Counter options
 * @param {Number} count current count increment
 * @param {Object} resource Mongoose model instance
 *
 * @return {Number} new count
 */
function calculateCount(options, count, resource) {
  let value = '';

  if (_.isFunction(options.prefix)) {
    value += options.prefix(resource);
  }
  else if(options.prefix) {
    value += options.prefix.toString();
  }

  value += count;

  if (options.hasVersion) {
    value += `${options.delimiterVersion}${options.startVersion}${options.delimiterVersion}`;
  }

  if (_.isFunction(options.suffix)) {
    value += options.suffix(resource);
  }
  else if(options.suffix) {
    value += options.suffix.toString();
  }

  return value;
}

/**
 * Retrieve the next sequence in the counter and update field
 *
 * @param {Object} options Counter options
 * @param {Object} resource Mongoose model instance
 * @param {Function} next Callback handler
 */
function nextCount(options, resource, next) {
  if (!resource.isNew || !_.isUndefined(resource[options.field])) {
    return next();
  }
  return Counter.findOne({
    model: options.model,
    field: options.field,
  }).then((item) => {
    let promise = Promise.resolve(item);
    if (!item) {
      promise = initCounter(options);
    }
    promise.then((counter) => {
      counter.count += options.increment;

      resource[options.field] = calculateCount(options, counter.count, resource);

      return counter.save(next);
    });
  }).catch(next);
}

/**
 * Parse the sequence to get the prefix, counter and suffix
 *
 * @param {Object} options Counter options
 *
 * @return {Object} sequence parsed
 */
function parseSequence(options) {
  const parsed = {
    prefix: '',
    counter: '',
    suffix: '',
  };

  if (_.isFunction(options.prefix)) {
    parsed.prefix = options.prefix(this);
  }
  else if(options.prefix) {
    parsed.prefix = options.prefix.toString();
  }

  if (_.isFunction(options.suffix)) {
    parsed.suffix = options.suffix(this);
  }
  else if(options.suffix) {
    parsed.suffix = options.suffix.toString();
  }

  parsed.counter = this[options.field].substring(parsed.prefix.length, this[options.field].length - parsed.suffix.length);

  if (options.hasVersion) {
    const tab = parsed.counter.split(options.delimiterVersion);

    parsed.counter = tab[0];
    parsed.version = tab[1];
  }

  return parsed;
}

/**
 * Retrieve the next sequence in the counter and update field
 *
 * @param {Object} options Counter options
 * @return {Promise} Promise fulfilled when increment field has been setted
 */
function nextSequence(options) {
  const resource = this;
  return new Promise((resolve, reject) => {
    nextCount(options, resource, (err) =>
      (err ? reject(err) : resolve())
    );
  });
}

/**
 * Set the next version from the current document version
 *
 * @param {Object} options Counter options
 * @return {Number} new version counter
 */
function nextVersion(options) {
  const opts = _.cloneDeep(options);
  const parsedSequence = this.parseSequence(options);

  opts.startVersion = Number(parsedSequence.version) + 1;

  this[options.field] = calculateCount(opts, parsedSequence.counter, this);

  return this[options.field];
}

/**
 * Create a new counter for the current model
 *
 * @param {Object} options Counter options
 * @return {Object} counter mongoose doc
 */
function initCounter(options) {
  const newCount = new Counter({
    model: options.model,
    field: options.field,
    count: options.start - options.increment,
  });

  return newCount.save();
}

/**
 * Mongoose plugin, adds a counter for a given `model` and `field`, also add
 * the autoincrement field into the schema.
 *
 * @param {Object} schema Mongoose schema
 * @param {Options} options Additional options for autoincremented field
 *   @property {String}           modelName   mongoose model name
 *   @property {String}           fieldName       mongoose increment field name
 *   @property {Integer}          [start]     start number for counter, default `1`
 *   @property {Integer}          [increment] number to increment counter, default `1`
 *   @property {String/Function}  [prefix]    counter prefix, default ``
 *   @property {String/Function}  [suffix]    counter suffix, default ``
 *   @property {Booleam}          [hasVersion]         has version, default `false`
 *   @property {Integer}          [startVersion]       start number for versiom, default `1`
 *   @property {String}           [delimiterVersion]   delimiter for version counter, default `-`
 */
function plugin(schema, options) {
  if (!_.isPlainObject(options)) {
    throw new Error('Mongoose Increment Plugin: require `options` parameter');
  }
  if (!_.isString(options.modelName)) {
    throw new Error('Mongoose Increment Plugin: require `options.modelName` parameter');
  }
  if (!_.isString(options.fieldName)) {
    throw new Error('Mongoose Increment Plugin: require `options.fieldName` parameter');
  }
  if (options.start && !_.isInteger(options.start)) {
    throw new Error('Mongoose Increment Plugin: require `options.start` parameter must be an integer');
  }
  if (options.increment && !_.isInteger(options.increment)) {
    throw new Error('Mongoose Increment Plugin: require `options.increment` parameter must be an integer');
  }
  if (options.startVersion && !_.isInteger(options.startVersion)) {
    throw new Error('Mongoose Increment Plugin: require `options.startVersion` parameter must be an integer');
  }

  const opts = {
    model: options.modelName,
    field: options.fieldName,
    start: options.start || 1,
    increment: options.increment || 1,
    prefix: options.prefix || '',
    suffix: options.suffix || '',
    type: options.type || Number,
    hasVersion: options.hasVersion || false,
    startVersion: options.startVersion || 1,
    delimiterVersion: options.delimiterVersion || '-',
  };

  const fieldSchema = {};

  fieldSchema[opts.field] = {
    type: opts.type,
    require: true,
    unique: true,
  };

  schema.add(fieldSchema);

  schema.methods.nextSequence = _.partial(nextSequence, opts);
  schema.methods.parseSequence = _.partial(parseSequence, opts);

  if (opts.hasVersion) {
    schema.methods.nextVersion = _.partial(nextVersion, opts);
  }

  schema.statics.resetSequence = _.partial(resetSequence, opts);

  schema.pre('save', function preSave(next) {
    nextCount(opts, this, next);
  });
}

module.exports = plugin;
<commit_msg>doc: correct comment syntax<commit_after>'use strict';

/**
 * Mongoose plugin
 */
const _ = require('lodash');
const mongoose = require('mongoose');
const Promise = require('bluebird');

/**
 * Setup counter schema and model
 *
 * @type {mongoose}
 */
const CounterSchema = new mongoose.Schema({
  model: {
    type: String,
    require: true,
  },
  field: {
    type: String,
    require: true,
  },
  count: {
    type: Number,
    default: 0,
  },
});

CounterSchema.index(
  { field: 1, model: 1 },
  { unique: true, required: true, index: -1 }
);

const Counter = mongoose.model('_Counter', CounterSchema);

/**
 * Reset counter sequence start
 *
 * @param {Object} options Mongoose plugin options
 * @return {Promise} Promise fulfilled when sequence has been reset
 */
function resetSequence(options) {
  return Counter.findOneAndUpdate(
    { model: options.model, field: options.field },
    { count: options.start - options.increment },
    { new: true, upsert: true });
}

/**
 * Calculate the current count
 *
 * @param {Object} options Counter options
 * @param {Number} count current count increment
 * @param {Object} resource Mongoose model instance
 *
 * @return {Number} new count
 */
function calculateCount(options, count, resource) {
  let value = '';

  if (_.isFunction(options.prefix)) {
    value += options.prefix(resource);
  }
  else if(options.prefix) {
    value += options.prefix.toString();
  }

  value += count;

  if (options.hasVersion) {
    value += `${options.delimiterVersion}${options.startVersion}${options.delimiterVersion}`;
  }

  if (_.isFunction(options.suffix)) {
    value += options.suffix(resource);
  }
  else if(options.suffix) {
    value += options.suffix.toString();
  }

  return value;
}

/**
 * Retrieve the next sequence in the counter and update field
 *
 * @param {Object} options Counter options
 * @param {Object} resource Mongoose model instance
 * @param {Function} next Callback handler
 */
function nextCount(options, resource, next) {
  if (!resource.isNew || !_.isUndefined(resource[options.field])) {
    return next();
  }
  return Counter.findOne({
    model: options.model,
    field: options.field,
  }).then((item) => {
    let promise = Promise.resolve(item);
    if (!item) {
      promise = initCounter(options);
    }
    promise.then((counter) => {
      counter.count += options.increment;

      resource[options.field] = calculateCount(options, counter.count, resource);

      return counter.save(next);
    });
  }).catch(next);
}

/**
 * Parse the sequence to get the prefix, counter and suffix
 *
 * @param {Object} options Counter options
 *
 * @return {Object} sequence parsed
 */
function parseSequence(options) {
  const parsed = {
    prefix: '',
    counter: '',
    suffix: '',
  };

  if (_.isFunction(options.prefix)) {
    parsed.prefix = options.prefix(this);
  }
  else if(options.prefix) {
    parsed.prefix = options.prefix.toString();
  }

  if (_.isFunction(options.suffix)) {
    parsed.suffix = options.suffix(this);
  }
  else if(options.suffix) {
    parsed.suffix = options.suffix.toString();
  }

  parsed.counter = this[options.field].substring(parsed.prefix.length, this[options.field].length - parsed.suffix.length);

  if (options.hasVersion) {
    const tab = parsed.counter.split(options.delimiterVersion);

    parsed.counter = tab[0];
    parsed.version = tab[1];
  }

  return parsed;
}

/**
 * Retrieve the next sequence in the counter and update field
 *
 * @param {Object} options Counter options
 * @return {Promise} Promise fulfilled when increment field has been setted
 */
function nextSequence(options) {
  const resource = this;
  return new Promise((resolve, reject) => {
    nextCount(options, resource, (err) =>
      (err ? reject(err) : resolve())
    );
  });
}

/**
 * Set the next version from the current document version
 *
 * @param {Object} options Counter options
 * @return {Number} new version counter
 */
function nextVersion(options) {
  const opts = _.cloneDeep(options);
  const parsedSequence = this.parseSequence(options);

  opts.startVersion = Number(parsedSequence.version) + 1;

  this[options.field] = calculateCount(opts, parsedSequence.counter, this);

  return this[options.field];
}

/**
 * Create a new counter for the current model
 *
 * @param {Object} options Counter options
 * @return {Object} counter mongoose doc
 */
function initCounter(options) {
  const newCount = new Counter({
    model: options.model,
    field: options.field,
    count: options.start - options.increment,
  });

  return newCount.save();
}

/**
 * Mongoose plugin, adds a counter for a given `model` and `field`, also add
 * the autoincrement field into the schema.
 *
 * @param {Object} schema Mongoose schema
 * @param {Options} options Additional options for autoincremented field
 *   @property {String}           modelName   mongoose model name
 *   @property {String}           fieldName       mongoose increment field name
 *   @property {Integer}          [start]     start number for counter, default `1`
 *   @property {Integer}          [increment] number to increment counter, default `1`
 *   @property {String/Function}  [prefix]    counter prefix, default ``
 *   @property {String/Function}  [suffix]    counter suffix, default ``
 *   @property {Boolean}          [hasVersion]         has version, default `false`
 *   @property {Integer}          [startVersion]       start number for version, default `1`
 *   @property {String}           [delimiterVersion]   delimiter for version counter, default `-`
 */
function plugin(schema, options) {
  if (!_.isPlainObject(options)) {
    throw new Error('Mongoose Increment Plugin: require `options` parameter');
  }
  if (!_.isString(options.modelName)) {
    throw new Error('Mongoose Increment Plugin: require `options.modelName` parameter');
  }
  if (!_.isString(options.fieldName)) {
    throw new Error('Mongoose Increment Plugin: require `options.fieldName` parameter');
  }
  if (options.start && !_.isInteger(options.start)) {
    throw new Error('Mongoose Increment Plugin: require `options.start` parameter must be an integer');
  }
  if (options.increment && !_.isInteger(options.increment)) {
    throw new Error('Mongoose Increment Plugin: require `options.increment` parameter must be an integer');
  }
  if (options.startVersion && !_.isInteger(options.startVersion)) {
    throw new Error('Mongoose Increment Plugin: require `options.startVersion` parameter must be an integer');
  }

  const opts = {
    model: options.modelName,
    field: options.fieldName,
    start: options.start || 1,
    increment: options.increment || 1,
    prefix: options.prefix || '',
    suffix: options.suffix || '',
    type: options.type || Number,
    hasVersion: options.hasVersion || false,
    startVersion: options.startVersion || 1,
    delimiterVersion: options.delimiterVersion || '-',
  };

  const fieldSchema = {};

  fieldSchema[opts.field] = {
    type: opts.type,
    require: true,
    unique: true,
  };

  schema.add(fieldSchema);

  schema.methods.nextSequence = _.partial(nextSequence, opts);
  schema.methods.parseSequence = _.partial(parseSequence, opts);

  if (opts.hasVersion) {
    schema.methods.nextVersion = _.partial(nextVersion, opts);
  }

  schema.statics.resetSequence = _.partial(resetSequence, opts);

  schema.pre('save', function preSave(next) {
    nextCount(opts, this, next);
  });
}

module.exports = plugin;
<|endoftext|>


<commit_before>var Discord = require('discord.js'),
    config = require('./config'),
    token = config.TOKEN,
    bot = new Discord.Client(),
    server,
    version,
    exec,
    stream = null,
    meta = null;

/* VERSION */
function getVersion(callback) {
    exec = exec || require('child_process').exec;

    exec('git rev-parse --short=4 HEAD', function (error, version) {
        if (error) {
            console.log('Error getting version', error);
            return callback('unknown');
        }

        callback(version.trim());
    });
}

/* BOT EVENTS */
bot.on('ready', function () {
    online();
    console.log('I am ready!');
    getVersion(function (v) {
        version = v;
        bot.user.setGame('version ' + version);

        if (config.DEBUG) bot.channels.find('id', config.TEXT_CH).sendMessage('I am ready, running version `' + version + '`!');
    });

    if (!bot.guilds.exists('id', config.SERVER_ID)) {
        console.log('Bot is not connected to the selected server!');
        process.exit();
    }

    server = bot.guilds.find('id', config.SERVER_ID);

    playRadio();
});

function playRadio() {
    const streamOptions = {volume: 0.05};

    var channel = server.channels.find('id', config.VOICE_CH);

    channel.join().then(function (connection) {
            var url = config.STREAM;

            const icy = require('icy');

            icy.get(url, function (res) {

                console.log(res.headers);

                res.on('metadata', function (metadata) {
                    meta = icy.parse(metadata);
                    bot.user.setGame(meta.StreamTitle);
                });

                connection.playStream(res, streamOptions);
            });

            stream = connection;
        })
        .catch(console.error);
}

function onMessage(message) {
    if (message.author.id == bot.user.id) {
        return;
    }

    if (message.channel.type == 'group') {
        return;
    }

    function handleCommand() {
        var match = /^[\/!]([a-zA-Z]+).*$/.exec(message.content);

        if (message.channel.type == 'dm') {
            match = /^[\/!]?([a-zA-Z]+).*$/.exec(message.content);
        }

        if (match) {
            var args = message.content.split(' ').splice(1);

            processCommand(message, match[1].toLowerCase(), args);
        }
    }

    if (server.channels.exists('id', message.channel.id)) {
        handleCommand();
    } else {
        if (server.members.exists('id', message.author.id)) {
            handleCommand();
        } else {
            return message.channel.sendMessage('You have to be member ' + server.name + '!');
        }
    }
}

bot.on('message', onMessage);

bot.on('messageUpdate', function (oldMessage, newMessage) {
    if (typeof newMessage.author === 'undefined')
        return;

    onMessage(newMessage);
});

function respond(message, response, mention, pm) {
    if (typeof mention === 'undefined') {
        mention = true;
    }

    if (typeof pm === 'undefined') {
        pm = false;
    }

    if (pm) {
        message.author.sendMessage(response);
    } else {
        if(mention) {
            message.reply(response);
        } else {
            message.channel.sendMessage(response);
        }
    }
}

/* COMMAND PROCESSING */
function processCommand(message, command, args) {
    switch (command) {
        case 'radio':
        case 'rv':
            (function () {
                respond(message, "Running DiscordRadio by DerAtrox, Version: `" + version + "`.\nAktuellster Commit: https://github.com/DerAtrox/DiscordRadio/commit/" + version);
            })();
            break;
        case 'nowplaying':
        case 'np':
            (function () {
                if(stream == null) {
                    respond(message, 'Der Stream ist aktuell nicht aktiv!', false);
                    return;
                }

                if(meta == null) {
                    respond(message, 'Keine Metadaten gefunden!', false);
                    return;
                }

                var metaS = meta.StreamTitle.split(' - ');
                if(metaS.length == 2) {
                    respond(message, 'Derzeit läuft **' + metaS[1] + '** von **' + metaS[0] + '**.', false);
                } else {
                    respond(message, 'Derzeit läuft **' + meta + '**.', false);
                }
            })();
            break;
    }
}

/* GENERAL APPLICATION STUFF */
process.on('exit', idle);

process.on('SIGINT', function () {
    idle();
    process.exit();

});

function idle() {
    bot.user.setStatus('idle');
}

function online() {
    bot.user.setStatus('online');
}

/* LOGIN */
bot.login(token);

<commit_msg>louder<commit_after>var Discord = require('discord.js'),
    config = require('./config'),
    token = config.TOKEN,
    bot = new Discord.Client(),
    server,
    version,
    exec,
    stream = null,
    meta = null;

/* VERSION */
function getVersion(callback) {
    exec = exec || require('child_process').exec;

    exec('git rev-parse --short=4 HEAD', function (error, version) {
        if (error) {
            console.log('Error getting version', error);
            return callback('unknown');
        }

        callback(version.trim());
    });
}

/* BOT EVENTS */
bot.on('ready', function () {
    online();
    console.log('I am ready!');
    getVersion(function (v) {
        version = v;
        bot.user.setGame('version ' + version);

        if (config.DEBUG) bot.channels.find('id', config.TEXT_CH).sendMessage('I am ready, running version `' + version + '`!');
    });

    if (!bot.guilds.exists('id', config.SERVER_ID)) {
        console.log('Bot is not connected to the selected server!');
        process.exit();
    }

    server = bot.guilds.find('id', config.SERVER_ID);

    playRadio();
});

function playRadio() {
    const streamOptions = {volume: 0.1};

    var channel = server.channels.find('id', config.VOICE_CH);

    channel.join().then(function (connection) {
            var url = config.STREAM;

            const icy = require('icy');

            icy.get(url, function (res) {

                console.log(res.headers);

                res.on('metadata', function (metadata) {
                    meta = icy.parse(metadata);
                    bot.user.setGame(meta.StreamTitle);
                });

                connection.playStream(res, streamOptions);
            });

            stream = connection;
        })
        .catch(console.error);
}

function onMessage(message) {
    if (message.author.id == bot.user.id) {
        return;
    }

    if (message.channel.type == 'group') {
        return;
    }

    function handleCommand() {
        var match = /^[\/!]([a-zA-Z]+).*$/.exec(message.content);

        if (message.channel.type == 'dm') {
            match = /^[\/!]?([a-zA-Z]+).*$/.exec(message.content);
        }

        if (match) {
            var args = message.content.split(' ').splice(1);

            processCommand(message, match[1].toLowerCase(), args);
        }
    }

    if (server.channels.exists('id', message.channel.id)) {
        handleCommand();
    } else {
        if (server.members.exists('id', message.author.id)) {
            handleCommand();
        } else {
            return message.channel.sendMessage('You have to be member ' + server.name + '!');
        }
    }
}

bot.on('message', onMessage);

bot.on('messageUpdate', function (oldMessage, newMessage) {
    if (typeof newMessage.author === 'undefined')
        return;

    onMessage(newMessage);
});

function respond(message, response, mention, pm) {
    if (typeof mention === 'undefined') {
        mention = true;
    }

    if (typeof pm === 'undefined') {
        pm = false;
    }

    if (pm) {
        message.author.sendMessage(response);
    } else {
        if(mention) {
            message.reply(response);
        } else {
            message.channel.sendMessage(response);
        }
    }
}

/* COMMAND PROCESSING */
function processCommand(message, command, args) {
    switch (command) {
        case 'radio':
        case 'rv':
            (function () {
                respond(message, "Running DiscordRadio by DerAtrox, Version: `" + version + "`.\nAktuellster Commit: https://github.com/DerAtrox/DiscordRadio/commit/" + version);
            })();
            break;
        case 'nowplaying':
        case 'np':
            (function () {
                if(stream == null) {
                    respond(message, 'Der Stream ist aktuell nicht aktiv!', false);
                    return;
                }

                if(meta == null) {
                    respond(message, 'Keine Metadaten gefunden!', false);
                    return;
                }

                var metaS = meta.StreamTitle.split(' - ');
                if(metaS.length == 2) {
                    respond(message, 'Derzeit läuft **' + metaS[1] + '** von **' + metaS[0] + '**.', false);
                } else {
                    respond(message, 'Derzeit läuft **' + meta + '**.', false);
                }
            })();
            break;
    }
}

/* GENERAL APPLICATION STUFF */
process.on('exit', idle);

process.on('SIGINT', function () {
    idle();
    process.exit();

});

function idle() {
    bot.user.setStatus('idle');
}

function online() {
    bot.user.setStatus('online');
}

/* LOGIN */
bot.login(token);

<|endoftext|>