<commit_before>/**
 * Copyright 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

'use strict';
/*eslint-disable no-undef*/
var assign = require('object-assign');
var visitors = require('../visitors');
var jstransform = require('./jstransform');
var typesSyntax = require('../visitors/type-syntax');
var inlineSourceMap = require('./inline-source-map');

var fs = require('fs');

var DEFAULT_OPTIONS = {
  react: false,
  es6: false,
  es7: false,
  harmony: false,
  utility: false,
  target: 'es5',
  stripTypes: false,
  sourceMap: false,
  sourceMapInline: false,
  sourceFilename: 'source.js',
  es6module: false,
  nonStrictEs6module: false
};
/**
 * Transforms the given code with the given options.
 *
 * @param {string} code
 * @param {object} options
 * @return {object}
 */
function transform(code, options) {
  options = assign({}, DEFAULT_OPTIONS, options);

  // Process options
  var transformOptions = {};

  if (options.sourceMap || options.sourceMapInline) {
    transformOptions.sourceMap = true;
    transformOptions.filename = options.sourceFilename || 'source.js';
  }

  if (options.es6module) {
    transformOptions.sourceType = 'module';
  }
  if (options.nonStrictEs6module) {
    transformOptions.sourceType = 'nonStrictModule';
  }

  // Instead of doing any fancy validation, only look for 'es3'. If we have
  // that, then use it. Otherwise use 'es5'.
  transformOptions.es3 = options.target === 'es3';
  transformOptions.es5 = !transformOptions.es3;

  // Determine visitors to use
  var visitorSets = [];

  if (options.react) {
    visitorSets.push('react');
  }

  if (options.harmony) {
    visitorSets.push('harmony');
  }

  if (options.es6) {
    visitorSets.push('es6');
  }

  if (options.es7) {
    visitorSets.push('es7');
  }

  if (options.utility) {
    visitorSets.push('utility');
  }

  if (options.target === 'es3') {
    visitorSets.push('target:es3');
  }

  if (options.stripTypes) {
    // Stripping types needs to happen before the other transforms
    // unfortunately, due to bad interactions. For example,
    // es6-rest-param-visitors conflict with stripping rest param type
    // annotation
    code = jstransform.transform(
      typesSyntax.visitorList,
      code,
      transformOptions
    ).code;
  }

  var visitorList = visitors.getVisitorsBySet(visitorSets);
  var result = jstransform.transform(visitorList, code, transformOptions);

  // Only copy some things off.
  var output = {
    code: result.code,
    sourceMap: null
  };

  // Convert sourceMap to JSON.
  var sourceMap;
  if (result.sourceMap) {
    sourceMap = result.sourceMap.toJSON();
    sourceMap.sources = transformOptions.filename;
    sourceMap.sourcesContent = [code];
  }

  // This differentiates options.sourceMap from options.sourceMapInline.
  if (options.sourceMap) {
    output.sourceMap = sourceMap;
  }

  if (options.sourceMapInline) {
    var map = inlineSourceMap(
      result.sourceMap,
      code,
      transformOptions.fileName
    );
    output.code = output.code + '\n' + map;
  }

  return output;
}

function transformFile(file, options, callback) {
  if (typeof options === 'function') {
    callback = options;
    options = {};
  }
  options = assign({sourceFilename: file}, options);

  fs.readFile(file, 'utf-8', function(err, contents) {
    if (err) {
      return callback(err, null);
    }

    var result = transform(contents, options);
    callback(null, result);
  });
}

function transformFileSync(file, options) {
  options = assign({sourceFilename: file}, options);
  var contents = fs.readFileSync(file, 'utf-8');
  return transform(contents, options);
}

module.exports = {
  transform: transform,
  transformFile: transformFile,
  transformFileSync: transformFileSync
};

<commit_msg>Fix transformOptions.filename<commit_after>/**
 * Copyright 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

'use strict';
/*eslint-disable no-undef*/
var assign = require('object-assign');
var visitors = require('../visitors');
var jstransform = require('./jstransform');
var typesSyntax = require('../visitors/type-syntax');
var inlineSourceMap = require('./inline-source-map');

var fs = require('fs');

var DEFAULT_OPTIONS = {
  react: false,
  es6: false,
  es7: false,
  harmony: false,
  utility: false,
  target: 'es5',
  stripTypes: false,
  sourceMap: false,
  sourceMapInline: false,
  sourceFilename: 'source.js',
  es6module: false,
  nonStrictEs6module: false
};
/**
 * Transforms the given code with the given options.
 *
 * @param {string} code
 * @param {object} options
 * @return {object}
 */
function transform(code, options) {
  options = assign({}, DEFAULT_OPTIONS, options);

  // Process options
  var transformOptions = {};

  if (options.sourceMap || options.sourceMapInline) {
    transformOptions.sourceMap = true;
    transformOptions.filename = options.sourceFilename || 'source.js';
  }

  if (options.es6module) {
    transformOptions.sourceType = 'module';
  }
  if (options.nonStrictEs6module) {
    transformOptions.sourceType = 'nonStrictModule';
  }

  // Instead of doing any fancy validation, only look for 'es3'. If we have
  // that, then use it. Otherwise use 'es5'.
  transformOptions.es3 = options.target === 'es3';
  transformOptions.es5 = !transformOptions.es3;

  // Determine visitors to use
  var visitorSets = [];

  if (options.react) {
    visitorSets.push('react');
  }

  if (options.harmony) {
    visitorSets.push('harmony');
  }

  if (options.es6) {
    visitorSets.push('es6');
  }

  if (options.es7) {
    visitorSets.push('es7');
  }

  if (options.utility) {
    visitorSets.push('utility');
  }

  if (options.target === 'es3') {
    visitorSets.push('target:es3');
  }

  if (options.stripTypes) {
    // Stripping types needs to happen before the other transforms
    // unfortunately, due to bad interactions. For example,
    // es6-rest-param-visitors conflict with stripping rest param type
    // annotation
    code = jstransform.transform(
      typesSyntax.visitorList,
      code,
      transformOptions
    ).code;
  }

  var visitorList = visitors.getVisitorsBySet(visitorSets);
  var result = jstransform.transform(visitorList, code, transformOptions);

  // Only copy some things off.
  var output = {
    code: result.code,
    sourceMap: null
  };

  // Convert sourceMap to JSON.
  var sourceMap;
  if (result.sourceMap) {
    sourceMap = result.sourceMap.toJSON();
    sourceMap.sources = transformOptions.filename;
    sourceMap.sourcesContent = [code];
  }

  // This differentiates options.sourceMap from options.sourceMapInline.
  if (options.sourceMap) {
    output.sourceMap = sourceMap;
  }

  if (options.sourceMapInline) {
    var map = inlineSourceMap(
      result.sourceMap,
      code,
      transformOptions.filename
    );
    output.code = output.code + '\n' + map;
  }

  return output;
}

function transformFile(file, options, callback) {
  if (typeof options === 'function') {
    callback = options;
    options = {};
  }
  options = assign({sourceFilename: file}, options);

  fs.readFile(file, 'utf-8', function(err, contents) {
    if (err) {
      return callback(err, null);
    }

    var result = transform(contents, options);
    callback(null, result);
  });
}

function transformFileSync(file, options) {
  options = assign({sourceFilename: file}, options);
  var contents = fs.readFileSync(file, 'utf-8');
  return transform(contents, options);
}

module.exports = {
  transform: transform,
  transformFile: transformFile,
  transformFileSync: transformFileSync
};

<|endoftext|>


<commit_before>/*
Copyright 2021 Google LLC

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

    https://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.
*/

let regions;
let carbonData;
let priceData;
let latencyData;
let details;

const normalizedSuffix = "_nornalized";
const cfeAttr = "carbon_free_percent";
const carbonIntensityAttr = "gCO2_kWh";
const priceAttr = "gce";
const distanceAttr = "distance";

async function fetchData() {
    await Promise.all([
        fetch("data/regions.json")
            .then(data => data.json())
            .then(json => regions = json),
        fetch("data/carbon/data/yearly/2019.csv")
            .then(data => data.text())
            .then(text => parseCarbonCSV(text)),
        fetch("data/prices.json")
            .then(data => data.json())
            .then(json => priceData = json),
        fetch("data/details.json")
            .then(data => data.json())
            .then(json => details = json)
    ]);
}

/**
 * Parse CSV file from https://github.com/GoogleCloudPlatform/region-carbon-info/
 * @param {String} text : CSV file as a string. First row is title, next rows are 'region', 'name', 'CFE', 'intensity'.
 */
function parseCarbonCSV(text) {
    // First split each newlines, then split comma.
    let rows = text.split('\r\n').map(row => row.split(','));

    carbonData = {};
    for(let r = 1; r < rows.length; r++) {
        let row = rows[r];

        let regionCarbonData = {};
        regionCarbonData[carbonIntensityAttr] = parseInt(row[3], 10)
        let cfe = parseFloat(row[2]);
        if(cfe){
            regionCarbonData[cfeAttr] = cfe;
        }

        carbonData[row[0]] = regionCarbonData;
    };
}

function normalizeData() {
    normalizeAttributes(carbonData, cfeAttr);
    normalizeAttributes(carbonData, carbonIntensityAttr);
    normalizeAttributes(priceData, priceAttr);
}

function distance(destination, origin) {
    // Thanks https://www.movable-type.co.uk/scripts/latlong.html
    const R = 6371e3; // metres
    const φ1 = origin.latitude * Math.PI/180; // φ, λ in radians
    const φ2 = destination.latitude * Math.PI/180;
    const Δφ = (destination.latitude - origin.latitude) * Math.PI/180;
    const Δλ = (destination.longitude - origin.longitude) * Math.PI/180;

    const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
            Math.cos(φ1) * Math.cos(φ2) *
            Math.sin(Δλ/2) * Math.sin(Δλ/2);
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

    return  R * c; // in metres
}

/**
 * Normalizes a certain attribute of the given region map.
 * Creates a new attribute "ATTRIBUTE_nornalized".
 * @param {Object} map: a map of <region, data>
 * @param {String} attribute: the attribute in data to normalize against
 */
function normalizeAttributes(map, attribute) {
    let min = Infinity;
    let max = -Infinity;
    for (const region in map) {
        let value = map[region][attribute];
        if(value > max) {
            max = value;
        }
        if(value < min) {
            min = value;
        }
    }
    for (const region in map) {
        if(map[region][attribute]) {
            map[region][attribute + normalizedSuffix] = (map[region][attribute] - min) / (max - min)
        }
    }
}

function rankRegions(inputs) {
    let results = [];

    // If latency is a criteria and some locations have been specified,
    // score each region based on proximity to locations.
    if(inputs.weights.latency > 0 && inputs.locations.length > 0) {
        latencyData = {};
        for(const region of regions) {
            let d = 0;
            for(const location of inputs.locations) {
                d += distance(location, details[region]);
            }
            latencyData[region] = {distance: d};
        }
        normalizeAttributes(latencyData, distanceAttr);
    }

    for(const region of regions) {
        let score = 0;
        // price: lower is better
        score += (1 - priceData[region]?.[priceAttr + normalizedSuffix]) * inputs.weights.price;
        // carbon
        if(carbonData[region]?.[cfeAttr] !== undefined) {
            // CFE: higher is better
            score+= carbonData[region]?.[cfeAttr + normalizedSuffix] * inputs.weights.carbon;
        } else {
            // Carbon Intensity: Lower is better
            score+= (1 - carbonData[region]?.[carbonIntensityAttr + normalizedSuffix]) * inputs.weights.carbon;
        }

        if(inputs.locations.length > 0) {
            // latency: lower is better
            score += (1 - latencyData?.[region]?.[distanceAttr + normalizedSuffix]) * inputs.weights.latency;
        }

        if(!isNaN(score))
        results.push({
            region: region,
            name: details[region].name,
            score: score,
        });
    }

    let resultSorted = results.sort(function(a, b) {
        return b.score - a.score;
    });

    return resultSorted;
}

/*
@param inputs: {
    weights: {
        latency: 0.5,
        price: 0.5
        carbon: 0.5
    },
    locations: [
        {latitude, longitude}
    ],
    currentLocationLatencies: {
        'us-central1': 0.2
    }
}
@return [{
        region: 'us-central1',
        name: ''
        score: 0.2
    }]
*/
async function regionOptimizer(inputs) {
    if(!regions || !!carbonData || !priceData) {
        await fetchData();
        normalizeData();
        console.log('Fetched and noralized data:')
        console.log({carbonData, priceData, regions, details});
    }

	console.log('Optimizing with inputs:');
    console.log(inputs);

    return rankRegions(inputs);
}

export {regionOptimizer}<commit_msg>fix bug leading to resouces being constantly fetched<commit_after>/*
Copyright 2021 Google LLC

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

    https://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.
*/

let regions;
let carbonData;
let priceData;
let latencyData;
let details;

const normalizedSuffix = "_nornalized";
const cfeAttr = "carbon_free_percent";
const carbonIntensityAttr = "gCO2_kWh";
const priceAttr = "gce";
const distanceAttr = "distance";

async function fetchData() {
    await Promise.all([
        fetch("data/regions.json")
            .then(data => data.json())
            .then(json => regions = json),
        fetch("data/carbon/data/yearly/2019.csv")
            .then(data => data.text())
            .then(text => parseCarbonCSV(text)),
        fetch("data/prices.json")
            .then(data => data.json())
            .then(json => priceData = json),
        fetch("data/details.json")
            .then(data => data.json())
            .then(json => details = json)
    ]);
}

/**
 * Parse CSV file from https://github.com/GoogleCloudPlatform/region-carbon-info/
 * @param {String} text : CSV file as a string. First row is title, next rows are 'region', 'name', 'CFE', 'intensity'.
 */
function parseCarbonCSV(text) {
    // First split each newlines, then split comma.
    let rows = text.split('\r\n').map(row => row.split(','));

    carbonData = {};
    for(let r = 1; r < rows.length; r++) {
        let row = rows[r];

        let regionCarbonData = {};
        regionCarbonData[carbonIntensityAttr] = parseInt(row[3], 10)
        let cfe = parseFloat(row[2]);
        if(cfe){
            regionCarbonData[cfeAttr] = cfe;
        }

        carbonData[row[0]] = regionCarbonData;
    };
}

function normalizeData() {
    normalizeAttributes(carbonData, cfeAttr);
    normalizeAttributes(carbonData, carbonIntensityAttr);
    normalizeAttributes(priceData, priceAttr);
}

function distance(destination, origin) {
    // Thanks https://www.movable-type.co.uk/scripts/latlong.html
    const R = 6371e3; // metres
    const φ1 = origin.latitude * Math.PI/180; // φ, λ in radians
    const φ2 = destination.latitude * Math.PI/180;
    const Δφ = (destination.latitude - origin.latitude) * Math.PI/180;
    const Δλ = (destination.longitude - origin.longitude) * Math.PI/180;

    const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
            Math.cos(φ1) * Math.cos(φ2) *
            Math.sin(Δλ/2) * Math.sin(Δλ/2);
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

    return  R * c; // in metres
}

/**
 * Normalizes a certain attribute of the given region map.
 * Creates a new attribute "ATTRIBUTE_nornalized".
 * @param {Object} map: a map of <region, data>
 * @param {String} attribute: the attribute in data to normalize against
 */
function normalizeAttributes(map, attribute) {
    let min = Infinity;
    let max = -Infinity;
    for (const region in map) {
        let value = map[region][attribute];
        if(value > max) {
            max = value;
        }
        if(value < min) {
            min = value;
        }
    }
    for (const region in map) {
        if(map[region][attribute]) {
            map[region][attribute + normalizedSuffix] = (map[region][attribute] - min) / (max - min)
        }
    }
}

function rankRegions(inputs) {
    let results = [];

    // If latency is a criteria and some locations have been specified,
    // score each region based on proximity to locations.
    if(inputs.weights.latency > 0 && inputs.locations.length > 0) {
        latencyData = {};
        for(const region of regions) {
            let d = 0;
            for(const location of inputs.locations) {
                d += distance(location, details[region]);
            }
            latencyData[region] = {distance: d};
        }
        normalizeAttributes(latencyData, distanceAttr);
    }

    for(const region of regions) {
        let score = 0;
        // price: lower is better
        score += (1 - priceData[region]?.[priceAttr + normalizedSuffix]) * inputs.weights.price;
        // carbon
        if(carbonData[region]?.[cfeAttr] !== undefined) {
            // CFE: higher is better
            score+= carbonData[region]?.[cfeAttr + normalizedSuffix] * inputs.weights.carbon;
        } else {
            // Carbon Intensity: Lower is better
            score+= (1 - carbonData[region]?.[carbonIntensityAttr + normalizedSuffix]) * inputs.weights.carbon;
        }

        if(inputs.locations.length > 0) {
            // latency: lower is better
            score += (1 - latencyData?.[region]?.[distanceAttr + normalizedSuffix]) * inputs.weights.latency;
        }

        if(!isNaN(score))
        results.push({
            region: region,
            name: details[region].name,
            score: score,
        });
    }

    let resultSorted = results.sort(function(a, b) {
        return b.score - a.score;
    });

    return resultSorted;
}

/*
@param inputs: {
    weights: {
        latency: 0.5,
        price: 0.5
        carbon: 0.5
    },
    locations: [
        {latitude, longitude}
    ],
    currentLocationLatencies: {
        'us-central1': 0.2
    }
}
@return [{
        region: 'us-central1',
        name: ''
        score: 0.2
    }]
*/
async function regionOptimizer(inputs) {
    if(!regions || !carbonData || !priceData) {
        await fetchData();
        normalizeData();
        console.log('Fetched and noralized data:')
        console.log({carbonData, priceData, regions, details});
    }

	console.log('Optimizing with inputs:');
    console.log(inputs);

    return rankRegions(inputs);
}

export {regionOptimizer}<|endoftext|>


<commit_before>'use strict';
const Effects = require('./effects.js').Effects;
const util = require('util');
const move = require('./commands').Commands.move;
const CommandUtil = require('./command_util').CommandUtil;

const l10n_dir = __dirname + '/../l10n/skills/';
let l10ncache = {};

/**
 * Localization helper
 * @return string
 */
const L = function(locale, cls, key /*, args... */ ) {
  var l10nFile = l10n_dir + cls + '.yml';
  var l10n = l10ncache[cls + locale] || require('./l10n')(l10nFile);
  l10n.setLocale(locale);
  return l10n.translate.apply(null, [].slice.call(arguments).slice(2));
};

// For activate functions:
// Command event passes in player, args, rooms, npcs, players.

exports.Skills = {

  dual: {
    id: "dual",
    cost: 2,
    name: "Dual Wield",
    description: "Your ability to use two (or more...) weapons at once.",
    usage: "Wield two one-handed weapons. Enjoy.",
    attribute: "stamina",
    type: "passive",
    activate: player => util.log(player.getName() + ' can dual wield.'),
  },

  //// Cleverness-related skills.
  pick: {
    id: "pick",
    cost: 2,
    name: "Lockpick",
    description: "Your ability to illicitly open locked doors or containers.",
    usage: "`pick [exit]`",
    attribute: "cleverness",
    type: "active",
    activate: (player, target, rooms, npcs, players) => {
      if (target) {
        const room = rooms.getAt(player.getLocation());
        const exits = room.getExits();
        const name = player.getName();
        const possibleTargets = exits
          .filter(e => e.direction.indexOf(target.toLowerCase()) > -1);

        util.log(name + ' is trying to pick a lock...');

        if (possibleTargets && possibleTargets.length === 1) {
          const exit = possibleTargets[0];
          const isDoor = exit.hasOwnProperty('door');
          const isLocked = isDoor && exit.door.locked;

          if (isLocked) {
            player.say("<yellow>You attempt to unlock the door...</yellow>");
            const lockpicking = player.getSkills('pick') + player.getAttribute('cleverness');
            const challenge = parseInt(exit.door.difficulty || 10, 10);
            const getExitDesc = locale => rooms.getAt(exit.location).getTitle(locale);

            if (lockpicking > challenge){
              player.say("<bold><cyan>You unlock the door!<cyan></bold>");
              players.eachIf(
                p => CommandUtil.inSameRoom(player, p),
                p => p.say(name + ' swiftly picks the lock to ' + getExitDesc(p.getLocale()) + '.')
              );
              exit.door.locked = false;
              move(exit, player, true);
            } else {
              util.log(name + " fails to pick lock.");
              player.say("<red>You fail to unlock the door.</red>");
              players.eachIf(
                p => CommandUtil.inSameRoom(player, p),
                p => p.say(name + ' tries to unlock the door to ' + getExitDesc(p.getLocale()) +', but fails to pick it.')
              );
              return;
            }
          } else if (isDoor) {
            player.say("That door is not locked.");
            return;
          } else {
            player.say("There is no door in that direction.");
            return;
          }
        } else if (possibleTarget.length) {
          player.say("Which door's lock do you want to pick?");
          return;
        } else {
          player.say("There doesn't seem to be an exit in that direction, much less a lock to pick.");
          return;
        }
      } else {
        player.say("Which door's lock do you want to pick?");
        return;
      }
    },
  }
};
<commit_msg>Add passive skills for different types of recovery.<commit_after>'use strict';
const Effects = require('./effects.js').Effects;
const util = require('util');
const move = require('./commands').Commands.move;
const CommandUtil = require('./command_util').CommandUtil;

const l10n_dir = __dirname + '/../l10n/skills/';
let l10ncache = {};

/**
 * Localization helper
 * @return string
 */
const L = function(locale, cls, key /*, args... */ ) {
  var l10nFile = l10n_dir + cls + '.yml';
  var l10n = l10ncache[cls + locale] || require('./l10n')(l10nFile);
  l10n.setLocale(locale);
  return l10n.translate.apply(null, [].slice.call(arguments).slice(2));
};

// For activate functions:
// Command event passes in player, args, rooms, npcs, players.

exports.Skills = {

  dual: {
    id: "dual",
    cost: 2,
    name: "Dual Wield",
    description: "Your ability to use two (or more...) weapons at once.",
    usage: "Wield two one-handed weapons. Enjoy.",
    attribute: "stamina",
    type: "passive",
    activate: player => util.log(player.getName() + ' can dual wield.'),
  },

  athletics: {
    id: "athletics",
    cost: 1,
    name: "Athletics",
    description: "You recover more quickly from physical exertion.",
    usage: "Try resting or meditating to recuperate your energy.",
    attribute: "stamina",
    type: "passive",
    activate: () => {},
  },

  concentration: {
    id: "concentration",
    cost: 1,
    name: "Concentration",
    description: "You recover more quickly from mental exertion.",
    usage: "Try meditating to increase focus and reduce stress.",
    attribute: "willpower",
    type: "passive",
    activate: () => {},
  },

  recovery: {
    id: "recovery",
    cost: 1,
    name: "Recovery",
    description: "Your wounds heal more quickly.",
    usage: "Try resting to recover from wounds or ailments.",
    attribute: "stamina",
    type: "passive",
    activate: () => {},
  },

  //// Cleverness-related skills.
  pick: {
    id: "pick",
    cost: 2,
    name: "Lockpick",
    description: "Your ability to illicitly open locked doors or containers.",
    usage: "`pick [exit]`",
    attribute: "cleverness",
    type: "active",
    activate: (player, target, rooms, npcs, players) => {
      if (target) {
        const room = rooms.getAt(player.getLocation());
        const exits = room.getExits();
        const name = player.getName();
        const possibleTargets = exits
          .filter(e => e.direction.indexOf(target.toLowerCase()) > -1);

        util.log(name + ' is trying to pick a lock...');

        if (possibleTargets && possibleTargets.length === 1) {
          const exit = possibleTargets[0];
          const isDoor = exit.hasOwnProperty('door');
          const isLocked = isDoor && exit.door.locked;

          if (isLocked) {
            player.say("<yellow>You attempt to unlock the door...</yellow>");
            const lockpicking = player.getSkills('pick') + player.getAttribute('cleverness');
            const challenge = parseInt(exit.door.difficulty || 10, 10);
            const getExitDesc = locale => rooms.getAt(exit.location).getTitle(locale);

            if (lockpicking > challenge){
              player.say("<bold><cyan>You unlock the door!<cyan></bold>");
              players.eachIf(
                p => CommandUtil.inSameRoom(player, p),
                p => p.say(name + ' swiftly picks the lock to ' + getExitDesc(p.getLocale()) + '.')
              );
              exit.door.locked = false;
              move(exit, player, true);
            } else {
              util.log(name + " fails to pick lock.");
              player.say("<red>You fail to unlock the door.</red>");
              players.eachIf(
                p => CommandUtil.inSameRoom(player, p),
                p => p.say(name + ' tries to unlock the door to ' + getExitDesc(p.getLocale()) +', but fails to pick it.')
              );
              return;
            }
          } else if (isDoor) {
            player.say("That door is not locked.");
            return;
          } else {
            player.say("There is no door in that direction.");
            return;
          }
        } else if (possibleTarget.length) {
          player.say("Which door's lock do you want to pick?");
          return;
        } else {
          player.say("There doesn't seem to be an exit in that direction, much less a lock to pick.");
          return;
        }
      } else {
        player.say("Which door's lock do you want to pick?");
        return;
      }
    },
  }
};
<|endoftext|>


<commit_before>'use strict';

var directiveModule = angular.module('angularjs-dropdown-multiselect', []);

directiveModule.directive('ngDropdownMultiselect', ['$filter', '$document', '$compile', '$parse', function ($filter, $document, $compile, $parse) {

	return {
		restrict: 'AE',
		scope:{
			selectedModel: '=',
			options: '=',
			extraSettings: '=',
			events: '=',
            translationTexts: '=',
			groupBy: '@'
		},
		template: function(element, attrs) {
			var checkboxes = attrs.checkboxes ? true : false;
			var groups = attrs.groupBy ? true : false;

			var template = '
';
			template +='<button type="button" class="dropdown-toggle" ng-class="settings.buttonClasses" ng-click="toggleDropdown()">{{getButtonText()}}</button>';
			template += '
';
			template += '
 0">  {{texts.checkAll}}';
			template += '
   {{texts.uncheckAll}}
';
			template += '
 0) && !settings.showUncheckAll" class="divider">
';
			template += '
<input type="text" class="form-control" ng-model="searchFilter" placeholder="{{texts.searchPlaceholder}}" />
';
			template += '

';

			if (groups)
			{
				template += '
{{ getGroupTitle(getPropertyForObject(option, settings.groupBy)) }}
';
				template += '
';
			}
			else
			{
				template += '
';
			}

			template += '';

			if(checkboxes) {
				template += '
<input class="checkboxInput" type="checkbox" ng-click="checkboxClick($event, getPropertyForObject(option,settings.idProp))" ng-checked="isChecked(getPropertyForObject(option,settings.idProp))" /> {{getPropertyForObject(option, settings.displayProp)}}
';
			}
			else {
				template += ' {{getPropertyForObject(option, settings.displayProp)}}';
			}

			template += '
';

			template += '
 1">
';
			template += '
 1">{{selectedModel.length}} {{texts.selectionOf}} {{settings.selectionLimit}} {{texts.selectionCount}}
';

			template += '
';
			template += '
';

			element.html(template);
		},
		link: function($scope, $element, $attrs){
			$scope.toggleDropdown = function()
			{
				$scope.open = !$scope.open;
			};

			$scope.checkboxClick = function($event, id)
			{
				$scope.setSelectedItem(id);
				$event.stopImmediatePropagation();
			};

			$scope.searchFilter = '';

			$scope.externalEvents = {
				onItemSelect: angular.noop,
				onItemDeselect: angular.noop,
				onSelectAll: angular.noop,
				onDeselectAll: angular.noop,
				onInitDone: angular.noop,
				onMaxSelectionReached: angular.noop
			};

			$scope.settings = {
				dynamicTitle: true,
				closeOnBlur: true,
				displayProp: 'label',
				idProp: 'id',
				externalIdProp: 'id',
				enableSearch: false,
				selectionLimit: 0,
                showCheckAll: true,
                showUncheckAll: true,
				closeOnSelect: false,
                buttonClasses: 'btn btn-default',
				closeOnDeselect: false,
				groupBy: $attrs.groupBy || undefined,
				groupByTextProvider: null
            };

            $scope.texts = {
                checkAll: 'Check All',
                uncheckAll: 'Uncheck All',
                selectionCount: 'checked',
                selectionOf: '/',
                searchPlaceholder: 'Search...',
                buttonDefaultText: 'Select',
                dynamicButtonTextSuffix: 'checked'
            };

			if (angular.isDefined($scope.settings.groupBy))
			{
				$scope.$watch('options', function(newValue) {
					if (angular.isDefined(newValue))
					{
						$scope.orderedItems = $filter('orderBy')(newValue, $scope.settings.groupBy);
					}
				});
			}

			angular.extend($scope.settings, $scope.extraSettings || []);
			angular.extend($scope.externalEvents, $scope.events || []);
            angular.extend($scope.texts, $scope.translationTexts);

			$scope.singleSelection = $scope.settings.selectionLimit === 1;

			function getFindObj(id)
			{
				var findObj = {};

				if ($scope.settings.externalIdProp === '')
				{
					findObj[$scope.settings.idProp] = id;
				}
				else {
					findObj[$scope.settings.externalIdProp] = id;
				}

				return findObj;
			}

			function clearObject(object)
			{
				for (var prop in object) {
					delete object[prop];
				}
			}

			if ($scope.singleSelection)
			{
				if (angular.isArray($scope.selectedModel) && $scope.selectedModel.length === 0)
				{
					clearObject($scope.selectedModel);
				}
			}

			if ($scope.settings.closeOnBlur) {
				$document.on('click', function (e) {
					var target = e.target.parentElement;
					var parentFound = false;

					while (angular.isDefined(target) && target !== null && !parentFound) {
						if (_.contains(target.classList, 'multiselect-parent') && !parentFound) {
							parentFound = true;
						}
						target = target.parentElement;
					}

					if (!parentFound) {
						$scope.$apply(function () {
							$scope.open = false;
						});
					}
				});
			}

			$scope.getGroupTitle = function(groupValue)
			{
				if ($scope.settings.groupByTextProvider !== null)
				{
					return $scope.settings.groupByTextProvider(groupValue);
				}

				return groupValue;
			};

			$scope.getButtonText = function()
			{
				if ($scope.settings.dynamicTitle)
				{
					var totalSelected;

					if ($scope.singleSelection)
					{
						totalSelected = ($scope.selectedModel !== null && angular.isDefined($scope.selectedModel[$scope.settings.idProp])) ? 1 : 0;
					}
					else
					{
						totalSelected = angular.isDefined($scope.selectedModel) ? $scope.selectedModel.length : 0;
					}

					if (totalSelected === 0)
					{
						return $scope.texts.buttonDefaultText;
					}
					else
					{
						return totalSelected + ' ' + $scope.texts.dynamicButtonTextSuffix;
					}
				}
				else
				{
					return $scope.texts.buttonDefaultText;
				}
			};

			$scope.getPropertyForObject = function(object, property)
			{
				if (angular.isDefined(object) && object.hasOwnProperty(property)) {
					return object[property];
				}

				return '';
			};

			$scope.selectAll = function () {
				$scope.deselectAll(false);
				$scope.externalEvents.onSelectAll();

				angular.forEach($scope.options, function(value)
				{
					$scope.setSelectedItem(value[$scope.settings.idProp], true);
				});
			};

			$scope.deselectAll = function(sendEvent) {
				sendEvent = sendEvent || true;

				if (sendEvent) {
					$scope.externalEvents.onDeselectAll();
				}

				if ($scope.singleSelection) {
					clearObject($scope.selectedModel);
				}
				else {
					$scope.selectedModel.splice(0, $scope.selectedModel.length);
				}
			};

			$scope.setSelectedItem = function(id, dontRemove){
				var findObj = getFindObj(id);
				var finalObj = null;

				if ($scope.settings.externalIdProp === '') {
					finalObj = _.find($scope.options, findObj);
				}
				else {
					finalObj = findObj;
				}

				if ($scope.singleSelection)
				{
					clearObject($scope.selectedModel);
					angular.extend($scope.selectedModel, finalObj);
					$scope.externalEvents.onItemSelect(finalObj);

					return;
				}

				dontRemove = dontRemove || false;

				var exists = _.findIndex($scope.selectedModel, findObj) !== -1;

				if (!dontRemove && exists) {
					$scope.selectedModel.splice(_.findIndex($scope.selectedModel, findObj), 1);
					$scope.externalEvents.onItemDeselect(findObj);
				} else if (!exists && ($scope.settings.selectionLimit === 0 || $scope.selectedModel.length < $scope.settings.selectionLimit)) {
					$scope.selectedModel.push(finalObj);
					$scope.externalEvents.onItemSelect(finalObj);
				}
			};

			$scope.isChecked = function (id) {
				if ($scope.singleSelection)
				{
					return $scope.selectedModel !== null && angular.isDefined($scope.selectedModel[$scope.settings.idProp]) && $scope.selectedModel[$scope.settings.idProp] === getFindObj(id)[$scope.settings.idProp];
				}

				return _.findIndex($scope.selectedModel, getFindObj(id)) !== -1;
			};

			$scope.externalEvents.onInitDone();
		}
	};
}]);
<commit_msg>Padding for search control.<commit_after>'use strict';

var directiveModule = angular.module('angularjs-dropdown-multiselect', []);

directiveModule.directive('ngDropdownMultiselect', ['$filter', '$document', '$compile', '$parse', function ($filter, $document, $compile, $parse) {

	return {
		restrict: 'AE',
		scope:{
			selectedModel: '=',
			options: '=',
			extraSettings: '=',
			events: '=',
            translationTexts: '=',
			groupBy: '@'
		},
		template: function(element, attrs) {
			var checkboxes = attrs.checkboxes ? true : false;
			var groups = attrs.groupBy ? true : false;

			var template = '
';
			template +='<button type="button" class="dropdown-toggle" ng-class="settings.buttonClasses" ng-click="toggleDropdown()">{{getButtonText()}}</button>';
			template += '
';
			template += '
 0">  {{texts.checkAll}}';
			template += '
   {{texts.uncheckAll}}
';
			template += '
 0) && !settings.showUncheckAll" class="divider">
';
			template += '

<input type="text" class="form-control" style="width: 100%;" ng-model="searchFilter" placeholder="{{texts.searchPlaceholder}}" />
';
			template += '

';

			if (groups)
			{
				template += '
{{ getGroupTitle(getPropertyForObject(option, settings.groupBy)) }}
';
				template += '
';
			}
			else
			{
				template += '
';
			}

			template += '';

			if(checkboxes) {
				template += '
<input class="checkboxInput" type="checkbox" ng-click="checkboxClick($event, getPropertyForObject(option,settings.idProp))" ng-checked="isChecked(getPropertyForObject(option,settings.idProp))" /> {{getPropertyForObject(option, settings.displayProp)}}
';
			}
			else {
				template += ' {{getPropertyForObject(option, settings.displayProp)}}';
			}

			template += '
';

			template += '
 1">
';
			template += '
 1">{{selectedModel.length}} {{texts.selectionOf}} {{settings.selectionLimit}} {{texts.selectionCount}}
';

			template += '
';
			template += '
';

			element.html(template);
		},
		link: function($scope, $element, $attrs){
			$scope.toggleDropdown = function()
			{
				$scope.open = !$scope.open;
			};

			$scope.checkboxClick = function($event, id)
			{
				$scope.setSelectedItem(id);
				$event.stopImmediatePropagation();
			};

			$scope.searchFilter = '';

			$scope.externalEvents = {
				onItemSelect: angular.noop,
				onItemDeselect: angular.noop,
				onSelectAll: angular.noop,
				onDeselectAll: angular.noop,
				onInitDone: angular.noop,
				onMaxSelectionReached: angular.noop
			};

			$scope.settings = {
				dynamicTitle: true,
				closeOnBlur: true,
				displayProp: 'label',
				idProp: 'id',
				externalIdProp: 'id',
				enableSearch: false,
				selectionLimit: 0,
                showCheckAll: true,
                showUncheckAll: true,
				closeOnSelect: false,
                buttonClasses: 'btn btn-default',
				closeOnDeselect: false,
				groupBy: $attrs.groupBy || undefined,
				groupByTextProvider: null
            };

            $scope.texts = {
                checkAll: 'Check All',
                uncheckAll: 'Uncheck All',
                selectionCount: 'checked',
                selectionOf: '/',
                searchPlaceholder: 'Search...',
                buttonDefaultText: 'Select',
                dynamicButtonTextSuffix: 'checked'
            };

			if (angular.isDefined($scope.settings.groupBy))
			{
				$scope.$watch('options', function(newValue) {
					if (angular.isDefined(newValue))
					{
						$scope.orderedItems = $filter('orderBy')(newValue, $scope.settings.groupBy);
					}
				});
			}

			angular.extend($scope.settings, $scope.extraSettings || []);
			angular.extend($scope.externalEvents, $scope.events || []);
            angular.extend($scope.texts, $scope.translationTexts);

			$scope.singleSelection = $scope.settings.selectionLimit === 1;

			function getFindObj(id)
			{
				var findObj = {};

				if ($scope.settings.externalIdProp === '')
				{
					findObj[$scope.settings.idProp] = id;
				}
				else {
					findObj[$scope.settings.externalIdProp] = id;
				}

				return findObj;
			}

			function clearObject(object)
			{
				for (var prop in object) {
					delete object[prop];
				}
			}

			if ($scope.singleSelection)
			{
				if (angular.isArray($scope.selectedModel) && $scope.selectedModel.length === 0)
				{
					clearObject($scope.selectedModel);
				}
			}

			if ($scope.settings.closeOnBlur) {
				$document.on('click', function (e) {
					var target = e.target.parentElement;
					var parentFound = false;

					while (angular.isDefined(target) && target !== null && !parentFound) {
						if (_.contains(target.classList, 'multiselect-parent') && !parentFound) {
							parentFound = true;
						}
						target = target.parentElement;
					}

					if (!parentFound) {
						$scope.$apply(function () {
							$scope.open = false;
						});
					}
				});
			}

			$scope.getGroupTitle = function(groupValue)
			{
				if ($scope.settings.groupByTextProvider !== null)
				{
					return $scope.settings.groupByTextProvider(groupValue);
				}

				return groupValue;
			};

			$scope.getButtonText = function()
			{
				if ($scope.settings.dynamicTitle)
				{
					var totalSelected;

					if ($scope.singleSelection)
					{
						totalSelected = ($scope.selectedModel !== null && angular.isDefined($scope.selectedModel[$scope.settings.idProp])) ? 1 : 0;
					}
					else
					{
						totalSelected = angular.isDefined($scope.selectedModel) ? $scope.selectedModel.length : 0;
					}

					if (totalSelected === 0)
					{
						return $scope.texts.buttonDefaultText;
					}
					else
					{
						return totalSelected + ' ' + $scope.texts.dynamicButtonTextSuffix;
					}
				}
				else
				{
					return $scope.texts.buttonDefaultText;
				}
			};

			$scope.getPropertyForObject = function(object, property)
			{
				if (angular.isDefined(object) && object.hasOwnProperty(property)) {
					return object[property];
				}

				return '';
			};

			$scope.selectAll = function () {
				$scope.deselectAll(false);
				$scope.externalEvents.onSelectAll();

				angular.forEach($scope.options, function(value)
				{
					$scope.setSelectedItem(value[$scope.settings.idProp], true);
				});
			};

			$scope.deselectAll = function(sendEvent) {
				sendEvent = sendEvent || true;

				if (sendEvent) {
					$scope.externalEvents.onDeselectAll();
				}

				if ($scope.singleSelection) {
					clearObject($scope.selectedModel);
				}
				else {
					$scope.selectedModel.splice(0, $scope.selectedModel.length);
				}
			};

			$scope.setSelectedItem = function(id, dontRemove){
				var findObj = getFindObj(id);
				var finalObj = null;

				if ($scope.settings.externalIdProp === '') {
					finalObj = _.find($scope.options, findObj);
				}
				else {
					finalObj = findObj;
				}

				if ($scope.singleSelection)
				{
					clearObject($scope.selectedModel);
					angular.extend($scope.selectedModel, finalObj);
					$scope.externalEvents.onItemSelect(finalObj);

					return;
				}

				dontRemove = dontRemove || false;

				var exists = _.findIndex($scope.selectedModel, findObj) !== -1;

				if (!dontRemove && exists) {
					$scope.selectedModel.splice(_.findIndex($scope.selectedModel, findObj), 1);
					$scope.externalEvents.onItemDeselect(findObj);
				} else if (!exists && ($scope.settings.selectionLimit === 0 || $scope.selectedModel.length < $scope.settings.selectionLimit)) {
					$scope.selectedModel.push(finalObj);
					$scope.externalEvents.onItemSelect(finalObj);
				}
			};

			$scope.isChecked = function (id) {
				if ($scope.singleSelection)
				{
					return $scope.selectedModel !== null && angular.isDefined($scope.selectedModel[$scope.settings.idProp]) && $scope.selectedModel[$scope.settings.idProp] === getFindObj(id)[$scope.settings.idProp];
				}

				return _.findIndex($scope.selectedModel, getFindObj(id)) !== -1;
			};

			$scope.externalEvents.onInitDone();
		}
	};
}]);
<|endoftext|>


<commit_before>(function () {
  'use strict';

  var toolsMenuPopup,
    moreToolsMenuPopup,
    prefs = {
      showWhenEmpty: false,
      toolsToKeep: '',
      toolsToMove: ''
    },
    itemsToKeep,
    nativeTools = 'activityManager|addonsManager|addonsmgr|addressBook|'
      + 'applyFilters|applyFiltersToSelection|browserToolsSeparator|'
      + 'cmd_switchprofile|deleteJunk|devToolsSeparator|downloadmgr|filtersCmd|'
      + 'image|javascriptConsole|menu_accountmgr|menu_cookieManager|'
      + 'menu_Filters|menu_imageManager|menu_import|menu_openAddons|'
      + 'menu_openDownloads|menu_openSavedFilesWnd|menu_pageInfo|'
      + 'menu_passwordManager|menu_popupManager|menu_preferences|menu_search|'
      + 'menu_search_addresses|menu_SearchAddresses|menu_SearchMail|'
      + 'menu_searchWeb|menu_translate|menu_validate|navBeginGlobalItems|popup|'
      + 'prefSep|privateBrowsingItem|runJunkControls|sanitizeItem|'
      + 'sanitizeSeparator|sep_switchprofile|sep_validate|sync-setup|'
      + 'sync-syncnowitem|tasksDataman|tasksMenuAddressBook|'
      + 'tasksMenuAfterAddressesSeparator|tasksMenuAfterApplySeparator|'
      + 'tasksMenuAfterDeleteSeparator|tasksMenuMail|webDeveloperMenu';

  String.prototype.trimPipes = function () {
    return this.replace(/\|{2,}/g, '|').replace(/^\||\|$/g, '');
  };

  function updateItemsToKeep() {
    var pattern;

    // Keep the native items.
    pattern = nativeTools;

    // Move the native items selected by the user.
    if (prefs.toolsToMove) {
      pattern = pattern.replace(new RegExp(
        '\\b' + prefs.toolsToMove.replace(/\|/g, '\\b|\\b') + '\\b',
        'g'
      ), '').trimPipes();
    }

    // Keep the extension items selected by the user.
    if (prefs.toolsToKeep) {
      pattern += '|' + prefs.toolsToKeep;
    }

    // Keep the items that doesn't have an id.
    pattern += '|';

    itemsToKeep = new RegExp('^(' + pattern + ')$');
  }

  function getMenu(node, type) {
    var  doc, xpath;

    function nsResolver() {
      return 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
    }

    doc = node.ownerDocument || node;
    if (type === 'tools') {
      xpath = '//xul:menupopup[@id="menu_ToolsPopup" or @id="taskPopup"]/*';
    } else if (type === 'moreTools') {
      xpath = '//xul:menupopup[@id="more-tools-menupopup"]/*';
    }
    return doc.evaluate(
      xpath,
      doc,
      nsResolver,
      XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
      null
    );
  }

  function toggleMoreTools() {
    var moreToolsMenuIsEmpty;

    moreToolsMenuIsEmpty = (moreToolsMenuPopup.childNodes.length === 2);

    if (moreToolsMenuIsEmpty) {
      document.getElementById('more-tools-label').setAttribute('hidden', false);
      document.getElementById('more-tools-sep').setAttribute('hidden', false);
    } else {
      document.getElementById('more-tools-label').setAttribute('hidden', true);
      document.getElementById('more-tools-sep').setAttribute('hidden', true);
    }

    if (moreToolsMenuIsEmpty && !prefs.showWhenEmpty) {
      document.getElementById('more-tools-menu').setAttribute('hidden', true);
    } else {
      document.getElementById('more-tools-menu').setAttribute('hidden', false);
    }
  }

  function moveTools() {
    var i, l, el, menu;

    // Move items to More Tools menu.
    menu = getMenu(document, 'tools');
    for (i = 0, l = menu.snapshotLength; i < l; i += 1) {
      el = menu.snapshotItem(i);
      if (!itemsToKeep.test(el.id)) {
        if (el.tagName === 'menuseparator') {
          toolsMenuPopup.removeChild(el);
        } else {
          moreToolsMenuPopup.appendChild(el);
        }
      }
    }

    // Move items back to Tools menu.
    menu = getMenu(document, 'moreTools');
    for (i = 0, l = menu.snapshotLength; i < l; i += 1) {
      el = menu.snapshotItem(i);
      if (itemsToKeep.test(el.id)) {
        if (el.tagName === 'menuseparator') {
          moreToolsMenuPopup.removeChild(el);
        } else {
          toolsMenuPopup.appendChild(el);
        }
      }
    }

    toggleMoreTools();
  }

  function dumpTools() {
    var i, l, el, menu, message;

    message = 'Items found in Tools menu at startup:\n';
    menu = getMenu(document, 'tools');
    for (i = 0, l = menu.snapshotLength; i < l; i += 1) {
      message += '\t' + menu.snapshotItem(i).id
        + '\t' + menu.snapshotItem(i).label + '\n';
    }
    Components.classes['@mozilla.org/consoleservice;1']
      .getService(Components.interfaces.nsIConsoleService)
      .logStringMessage(message);
  }

  function makePattern(s) {
    return s.replace(/(\-)/g, '\\$1').replace(/\s*[,|]\s*/g, '|').trimPipes();
  }

  function loadPrefs() {
    var prefBranch;

    prefBranch = Components.classes['@mozilla.org/preferences-service;1']
      .getService(Components.interfaces.nsIPrefService)
      .getBranch('extensions.moretools.');
    prefs.showWhenEmpty = prefBranch.getBoolPref('showWhenEmpty');
    prefs.toolsToMove = makePattern(prefBranch.getCharPref('toolsToMove'));
    prefs.toolsToKeep = makePattern(prefBranch.getCharPref('toolsToKeep'));
  }

  function observePrefs() {
    var prefBranch;

    prefBranch = Components.classes['@mozilla.org/preferences-service;1']
      .getService(Components.interfaces.nsIPrefBranch);
    prefBranch.QueryInterface(Components.interfaces.nsIPrefBranch2);
    prefBranch.addObserver('extensions.moretools.', {
      observe: function (aSubject, aTopic, aData) {
        if (aTopic === 'nsPref:changed') {
          loadPrefs();
          switch (aData) {
          case 'extensions.moretools.showWhenEmpty':
            toggleMoreTools();
            break;
          case 'extensions.moretools.toolsToMove':
          case 'extensions.moretools.toolsToKeep':
            updateItemsToKeep();
            moveTools();
            break;
          }
        }
      }
    }, false);
    prefBranch.QueryInterface(Components.interfaces.nsIPrefBranch);
  }

  window.addEventListener('load', function () {
    var i, l, el;

    // This line must be commented out to make the extension work properly.
    // return dumpTools();

    // Look up nodes now that getElementById() is safe.
    toolsMenuPopup =
      document.getElementById('menu_ToolsPopup') || // Firefox
      document.getElementById('taskPopup');         // Thunderbird, SeaMonkey
    moreToolsMenuPopup = document.getElementById('more-tools-menupopup');

    // Load user-configured options and monitor changes made to them.
    loadPrefs();
    observePrefs();

    // Update the list of items to be kept in Tools menu.
    updateItemsToKeep();

    // Move any tools not in the list of items to keep.
    moveTools();

    // Move tools that are added later.
    toolsMenuPopup.addEventListener('DOMNodeInserted', moveTools, true);
  }, true);
}());
<commit_msg>Code rewrite to be compatible with SeaMonkey and to allow user to choose which items to keep in Tools menu and which items to move to More Tools menu. It ain't broke for Firefox, but I can't make it work for SeaMonkey and Thunderbird without rewrite.<commit_after>(function () {
  'use strict';

  var toolsMenuPopup,
    moreToolsMenuPopup,
    prefs = {
      showWhenEmpty: false,
      toolsToKeep: '',
      toolsToMove: ''
    },
    itemsToKeep,
    nativeTools = 'activityManager|addonsManager|addonsmgr|addressBook|'
      + 'applyFilters|applyFiltersToSelection|browserToolsSeparator|'
      + 'cmd_switchprofile|deleteJunk|devToolsSeparator|downloadmgr|filtersCmd|'
      + 'image|javascriptConsole|menu_accountmgr|menu_cookieManager|'
      + 'menu_Filters|menu_imageManager|menu_import|menu_openAddons|'
      + 'menu_openDownloads|menu_openSavedFilesWnd|menu_pageInfo|'
      + 'menu_passwordManager|menu_popupManager|menu_preferences|menu_search|'
      + 'menu_search_addresses|menu_SearchAddresses|menu_SearchMail|'
      + 'menu_searchWeb|menu_translate|menu_validate|navBeginGlobalItems|popup|'
      + 'prefSep|privateBrowsingItem|runJunkControls|sanitizeItem|'
      + 'sanitizeSeparator|sep_switchprofile|sep_validate|sync-setup|'
      + 'sync-syncnowitem|tasksDataman|tasksMenuAddressBook|'
      + 'tasksMenuAfterAddressesSeparator|tasksMenuAfterApplySeparator|'
      + 'tasksMenuAfterDeleteSeparator|tasksMenuMail|webDeveloperMenu';

  String.prototype.trimPipes = function () {
    return this.replace(/\|{2,}/g, '|').replace(/^\||\|$/g, '');
  };

  function updateItemsToKeep() {
    var pattern;

    // Keep the native items.
    pattern = nativeTools;

    // Move the native items selected by the user.
    if (prefs.toolsToMove) {
      pattern = pattern.replace(new RegExp(
        '\\b' + prefs.toolsToMove.replace(/\|/g, '\\b|\\b') + '\\b',
        'g'
      ), '').trimPipes();
    }

    // Keep the extension items selected by the user.
    if (prefs.toolsToKeep) {
      pattern += '|' + prefs.toolsToKeep;
    }

    // Keep the items that doesn't have an id.
    pattern += '|';

    itemsToKeep = new RegExp('^(' + pattern + ')$');
  }

  function getMenu(node, type) {
    var  doc, xpath;

    function nsResolver() {
      return 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
    }

    doc = node.ownerDocument || node;
    if (type === 'tools') {
      xpath = '//xul:menupopup[@id="menu_ToolsPopup" or @id="taskPopup"]/*';
    } else if (type === 'moreTools') {
      xpath = '//xul:menupopup[@id="more-tools-menupopup"]/*';
    }
    return doc.evaluate(
      xpath,
      doc,
      nsResolver,
      XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
      null
    );
  }

  function toggleMoreTools() {
    var moreToolsMenuIsEmpty;

    moreToolsMenuIsEmpty = (moreToolsMenuPopup.childNodes.length === 2);

    if (moreToolsMenuIsEmpty) {
      document.getElementById('more-tools-label').setAttribute('hidden', false);
      document.getElementById('more-tools-sep').setAttribute('hidden', false);
    } else {
      document.getElementById('more-tools-label').setAttribute('hidden', true);
      document.getElementById('more-tools-sep').setAttribute('hidden', true);
    }

    if (moreToolsMenuIsEmpty && !prefs.showWhenEmpty) {
      document.getElementById('more-tools-menu').setAttribute('hidden', true);
    } else {
      document.getElementById('more-tools-menu').setAttribute('hidden', false);
    }
  }

  function toggleSeparators(menu) {
    var a, b, item, prevItem, nextItem;

    for (a = 0, b = menu.snapshotLength - 1; a <= b; a += 1) {
      item = menu.snapshotItem(a);
      if (item.tagName === 'menuseparator' && item.id) {
        prevItem = item.previousSibling;
        nextItem = item.nextSibling;
        if (prevItem && prevItem.tagName !== 'menuseparator' &&
            nextItem && nextItem.tagName !== 'menuseparator') {
          document.getElementById(item.id).setAttribute('hidden', false);
        } else {
          document.getElementById(item.id).setAttribute('hidden', true);
        }
      }
    }
  }

  function moveTools() {
    var a, b, menu, item, nextItem;

    // Move items to More Tools menu.
    menu = getMenu(document, 'tools');
    for (a = 0, b = menu.snapshotLength - 1; a <= b; a += 1) {
      item = menu.snapshotItem(a);
      if (!itemsToKeep.test(item.id)) {
        nextItem = item.nextSibling;
        if (nextItem) {
          item.setAttribute('nextItemID', nextItem.id);
        }
        moreToolsMenuPopup.appendChild(item);
      }
    }

    // Move items back to Tools menu.
    menu = getMenu(document, 'moreTools');
    for (a = menu.snapshotLength - 1, b = 0; a >= b; a -= 1) {
      item = menu.snapshotItem(a);
      if (itemsToKeep.test(item.id)) {
        if (item.hasAttribute('nextItemID')) {
          nextItem = document.getElementById(item.getAttribute('nextItemID'));
        } else {
          nextItem = null;
        }
        if (nextItem) {
          toolsMenuPopup.insertBefore(item, nextItem);
        } else {
          toolsMenuPopup.appendChild(item);
        }
      }
    }

    // Toggle visibility of the separators.
    toggleSeparators(getMenu(document, 'tools'));
    toggleSeparators(getMenu(document, 'moreTools'));

    toggleMoreTools();
  }

  function dumpTools() {
    var i, l, el, menu, message;

    message = 'Items found in Tools menu at startup:\n';
    menu = getMenu(document, 'tools');
    for (i = 0, l = menu.snapshotLength; i < l; i += 1) {
      message += '\t' + menu.snapshotItem(i).id
        + '\t' + menu.snapshotItem(i).label + '\n';
    }
    Components.classes['@mozilla.org/consoleservice;1']
      .getService(Components.interfaces.nsIConsoleService)
      .logStringMessage(message);
  }

  function makePattern(s) {
    return s.replace(/(\-)/g, '\\$1').replace(/\s*[,|]\s*/g, '|').trimPipes();
  }

  function loadPrefs() {
    var prefBranch;

    prefBranch = Components.classes['@mozilla.org/preferences-service;1']
      .getService(Components.interfaces.nsIPrefService)
      .getBranch('extensions.moretools.');
    prefs.showWhenEmpty = prefBranch.getBoolPref('showWhenEmpty');
    prefs.toolsToMove = makePattern(prefBranch.getCharPref('toolsToMove'));
    prefs.toolsToKeep = makePattern(prefBranch.getCharPref('toolsToKeep'));
  }

  function observePrefs() {
    var prefBranch;

    prefBranch = Components.classes['@mozilla.org/preferences-service;1']
      .getService(Components.interfaces.nsIPrefBranch);
    prefBranch.QueryInterface(Components.interfaces.nsIPrefBranch2);
    prefBranch.addObserver('extensions.moretools.', {
      observe: function (aSubject, aTopic, aData) {
        if (aTopic === 'nsPref:changed') {
          loadPrefs();
          switch (aData) {
          case 'extensions.moretools.showWhenEmpty':
            toggleMoreTools();
            break;
          case 'extensions.moretools.toolsToMove':
          case 'extensions.moretools.toolsToKeep':
            updateItemsToKeep();
            moveTools();
            break;
          }
        }
      }
    }, false);
    prefBranch.QueryInterface(Components.interfaces.nsIPrefBranch);
  }

  window.addEventListener('load', function () {
    var i, l, el;

    // This line must be commented out to make the extension work properly.
    // return dumpTools();

    // Look up nodes now that getElementById() is safe.
    toolsMenuPopup =
      document.getElementById('menu_ToolsPopup') || // Firefox
      document.getElementById('taskPopup');         // Thunderbird, SeaMonkey
    moreToolsMenuPopup = document.getElementById('more-tools-menupopup');

    // Load user-configured options and monitor changes made to them.
    loadPrefs();
    observePrefs();

    // Update the list of items to be kept in Tools menu.
    updateItemsToKeep();

    // Move any tools not in the list of items to keep.
    moveTools();

    // Move tools that are added later.
    toolsMenuPopup.addEventListener('DOMNodeInserted', moveTools, true);
  }, true);
}());
<|endoftext|>


<commit_before>"use strict";

const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const Syslog = require("../model/syslog-schema");
const qs = require("querystring");

/**
 * Mongoose Stuffs
 */
mongoose.connect(process.env.MONGODB_URI);
var db = mongoose.connection;

/**
 * Route Preprocess: Add JSON Header to reduce code dupe
 */
const pp_json_header = (req, res, next) => {
    res.setHeader("Content-Type", "application/json; charset=utf-8");
    next();
};

router.get("/*", (req, res, next) => {
    res.header("X-Timestamp", Date.now());
    next();
});

/**
 * GET All Syslog Records
 */
router.get("/", pp_json_header, (req, res, next) => {
    let index = 0;
    let stream = Syslog.find({}, null, {
        sort: {
            $natural: -1
        }
    }).lean().cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

/**
 * GET one record from Syslog Dataset
 * http://stackoverflow.com/questions/14992123/finding-a-mongodb-document-by-objectid-with-mongoose
 * NOTE: These two endpoint is buggy, caring required.
 */

router.get("/id", (req, res, next) => {
    Syslog.distinct("_id", (err, doc) => {
        if (err) return next(err);
        res.json(doc);
    });
});

router.get("/id/:id", (req, res, next) => {
    Syslog.findOne({
        "_id": qs.escape(req.params.id)
    }, (err, doc) => {
        if (err) return next(err);
        res.json(doc);
    });
});

/**
 * Get Tags of entries in the Syalog Collection
 * http://stackoverflow.com/questions/6043847/how-do-i-query-for-distinct-values-in-mongoose
 */
router.get("/tag", (req, res, next) => {
    let index = 0;
    let stream = Syslog.aggregate([{
        $group: {
            _id: "$tag", //$region is the column name in collection
            count: {
                $sum: 1
            }
        }
    }]).lean().cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

router.get("/tag/:tag", pp_json_header, (req, res, next) => {
    let index = 0;
    let stream = Syslog.find({
        "tag": qs.escape(req.params.tag)
    }, null, {
        sort: {
            $natural: -1
        }
    }).lean().cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

/**
 * GET records from Syslog Dataset by hostname
 */
router.get("/hostname", (req, res, next) => {
    let index = 0;
    let stream = Syslog.aggregate([{
        $group: {
            _id: "$hostname", //$region is the column name in collection
            count: {
                $sum: 1
            }
        }
    }]).lean().cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

router.get("/hostname/:hostname", pp_json_header, (req, res, next) => {
    let index = 0;
    res.setHeader("Content-Type", "application/json; charset=utf-8");
    let stream = Syslog.find({
        "hostname": req.params.hostname
    }, null, {
        sort: {
            $natural: -1
        }
    }).lean().cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

/**
 * Get Facilities of entries in the Syalog Collection
 */
router.get("/facility", (req, res, next) => {
    let index = 0;
    let stream = Syslog.aggregate([{
        $group: {
            _id: "$facility", //$region is the column name in collection
            count: {
                $sum: 1
            }
        }
    }]).lean().cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

router.get("/facility/:facility", pp_json_header, (req, res, next) => {
    let index = 0;
    let stream = Syslog.find({
        "facility": qs.escape(req.params.facility)
    }, null, {
        sort: {
            $natural: -1
        }
    }).lean().cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

/**
 * Get Serverity of entries in the Syalog Collection
 */
router.get("/severity", (req, res, next) => {
    let index = 0;
    let stream = Syslog.aggregate([{
        $group: {
            _id: "$severity", //$region is the column name in collection
            count: {
                $sum: 1
            }
        }
    }]).lean().cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

router.get("/severity/:severity", pp_json_header, (req, res, next) => {
    let index = 0;
    let stream = Syslog.find({
        "severity": qs.escape(req.params.severity)
    }, null, {
        sort: {
            $natural: -1
        }
    }).lean().cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

/**
 * GET DB Stat as Status Check
 */
router.get("/stats", (req, res, next) => {
    Syslog.collection.stats((err, doc) => {
        if (err) return next(err);
        // Remove useless Key from doc
        delete doc.wiredTiger;
        delete doc.indexDetails;
        // Render the result
        res.json(doc);
    });
});

module.exports = router;
<commit_msg>Don't be lazy<commit_after>"use strict";

const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const Syslog = require("../model/syslog-schema");
const qs = require("querystring");

/**
 * Mongoose Stuffs
 */
mongoose.connect(process.env.MONGODB_URI);
var db = mongoose.connection;

/**
 * Route Preprocess: Add JSON Header to reduce code dupe
 */
const pp_json_header = (req, res, next) => {
    res.setHeader("Content-Type", "application/json; charset=utf-8");
    next();
};

router.get("/*", (req, res, next) => {
    res.header("X-Timestamp", Date.now());
    next();
});

/**
 * GET All Syslog Records
 */
router.get("/", pp_json_header, (req, res, next) => {
    let index = 0;
    let stream = Syslog.find({}, null, {
        sort: {
            $natural: -1
        }
    }).cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

/**
 * GET one record from Syslog Dataset
 * http://stackoverflow.com/questions/14992123/finding-a-mongodb-document-by-objectid-with-mongoose
 * NOTE: These two endpoint is buggy, caring required.
 */

router.get("/id", (req, res, next) => {
    Syslog.distinct("_id", (err, doc) => {
        if (err) return next(err);
        res.json(doc);
    });
});

router.get("/id/:id", (req, res, next) => {
    Syslog.findOne({
        "_id": qs.escape(req.params.id)
    }, (err, doc) => {
        if (err) return next(err);
        res.json(doc);
    });
});

/**
 * Get Tags of entries in the Syalog Collection
 * http://stackoverflow.com/questions/6043847/how-do-i-query-for-distinct-values-in-mongoose
 */
router.get("/tag", (req, res, next) => {
    let index = 0;
    let stream = Syslog.aggregate([{
        $group: {
            _id: "$tag", //$region is the column name in collection
            count: {$sum: 1}
        }
    }]).cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

router.get("/tag/:tag", pp_json_header, (req, res, next) => {
    let index = 0;
    let stream = Syslog.find({
        "tag": qs.escape(req.params.tag)
    }, null, {
        sort: {
            $natural: -1
        }
    }).cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

/**
 * GET records from Syslog Dataset by hostname
 */
router.get("/hostname", (req, res, next) => {
    let index = 0;
    let stream = Syslog.aggregate([{
        $group: {
            _id: "$hostname", //$region is the column name in collection
            count: {
                $sum: 1
            }
        }
    }]).cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

router.get("/hostname/:hostname", pp_json_header, (req, res, next) => {
    let index = 0;
    res.setHeader("Content-Type", "application/json; charset=utf-8");
    let stream = Syslog.find({
        "hostname": req.params.hostname
    }, null, {
        sort: {
            $natural: -1
        }
    }).cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

/**
 * Get Facilities of entries in the Syalog Collection
 */
router.get("/facility", (req, res, next) => {
    let index = 0;
    let stream = Syslog.aggregate([{
        $group: {
            _id: "$facility", //$region is the column name in collection
            count: {
                $sum: 1
            }
        }
    }]).cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

router.get("/facility/:facility", pp_json_header, (req, res, next) => {
    let index = 0;
    let stream = Syslog.find({
        "facility": qs.escape(req.params.facility)
    }, null, {
        sort: {
            $natural: -1
        }
    }).cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

/**
 * Get Serverity of entries in the Syalog Collection
 */
router.get("/severity", (req, res, next) => {
    let index = 0;
    let stream = Syslog.aggregate([{
        $group: {
            _id: "$severity", //$region is the column name in collection
            count: {
                $sum: 1
            }
        }
    }]).cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

router.get("/severity/:severity", pp_json_header, (req, res, next) => {
    let index = 0;
    let stream = Syslog.find({
        "severity": qs.escape(req.params.severity)
    }, null, {
        sort: {
            $natural: -1
        }
    }).cursor();
    res.write("[");
    stream.on("data", (doc) => {
        res.write((!(index++) ? "" : ",") + JSON.stringify(doc));
    });
    stream.on("close", () => {
        res.write("]");
        res.end();
    });
    stream.on("error", (err) => {
        return next(err);
    });
});

/**
 * GET DB Stat as Status Check
 */
router.get("/stats", (req, res, next) => {
    Syslog.collection.stats((err, doc) => {
        if (err) return next(err);
        // Remove useless Key from doc
        delete doc.wiredTiger;
        delete doc.indexDetails;
        // Render the result
        res.json(doc);
    });
});

module.exports = router;
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var crypto = require('cryptofunc');
var cryptoUtils = require('cryptoUtils');
var voterClient = require('voterClient');
var csCore = require('../CollectingServer/src/csCore.js');
var mixCore = require('../MixServer/src/mixCore.js');
var mkdirp = require('mkdirp');

//////////////////////////////////////////////////////////////////////////////////////////
// Shortcuts

var pair = crypto.concatenate;
var unpair = crypto.deconcatenate;
var sign = crypto.sign;
var verif = crypto.verifsig;

//////////////////////////////////////////////////////////////////////////////////////////

// Parameters and keys

var TAG_VOTERS = '10';
var TAG_BALLOTS = '01';
//console.log('CWD:\t' + process.cwd());
var PARTIALRESULT_template = process.cwd() + '/data/partialResults';
var TIMEOUT = 100000;

var electionID = 'eeee';
var NMixServ = 5;
var NVoters = 10;
var voters = new Array(NVoters);

console.log('************ Initialisation');

// voters identifiers
for (var i=NVoters-1; i>=0; --i) {
    voters[i] = 'abc'  + i + '@ema.il';
}

// Keys
var colServSigKeys = crypto.sig_keygen();
var colServVerifKey = colServSigKeys.verificationKey;

var mixServPkeKeys = new Array(NMixServ);
var mixServSigKeys = new Array(NMixServ);
for(var i=0; i<NMixServ; i++) {
	mixServPkeKeys[i] = crypto.pke_keygen();
	mixServSigKeys[i] = crypto.sig_keygen();
}
var mixServEncKeys = mixServPkeKeys.map(function(k){ return k.encryptionKey; });
var mixServVerifKeys = mixServSigKeys.map(function(k){ return k.verificationKey; });

//////////////////////////////////////////////////////////////////////////////////////////
// Test cases

describe( 'Voting process', function()
{

	var cs = csCore.create(electionID, voters, colServSigKeys.signingKey);
    var receipts = new Array(voters.length);
    var voter = voterClient.create(electionID, colServVerifKey, mixServEncKeys, mixServVerifKeys);

    //console.log('Test: Current directory --> ' + process.cwd());

    // create the folder where the data processed
    // by the mix servers will be stored
    mkdirp('./data', function (err) {
        if (err)
        	console.error("Error: ", err);
//		else
//        	console.log("Folder '" + config.DATA_FOLDER + "' created.");
    });

    // Create mix servers
    var mixServer = new Array(NMixServ);
    for (i=0; i<NMixServ; ++i) {
        var precServVerifKey = (i==0 ? colServVerifKey : mixServSigKeys[i-1].verificationKey );
    	mixServer[i] = mixCore.create(	mixServPkeKeys[i].encryptionKey,
    									mixServPkeKeys[i].decryptionKey,
    									mixServSigKeys[i].verificationKey,
    									mixServSigKeys[i].signingKey,
    									precServVerifKey, electionID,
    									NVoters);
    }
    var intermediateResult = new Array(NMixServ);

    it ( 'eligibleVoters field works as expected', function()
    {
    	var listElVoters = Object.keys(cs.eligibleVoters);
    	expect(bijection(listElVoters, voters)).toBe(true);
    });

    it( 'Ballot creation works as expected', function()
    {
        console.log('************ Ballot creation');
    	for(i=voters.length-1; i>=0; --i){
            // create ballot (a receipt containing a ballot); i-th voter votes for i-th candidate:
    		receipts[i] = voter.createBallot(i);
    		expect (receipts[i].choice) .toBe(i);
        }
    });

    it( 'Ballot casting works as expected', function()
    {
        console.log('************ Ballot casting');

        for(i=voters.length-1; i>=0; --i){
            // submit the ballot
        	var csReply = cs.collectBallot(voters[i], receipts[i].ballot);
        	expect (csReply.ok).toBe(true);

            // check the acknowledgement (signature)
            receipts[i].signature = csReply.data;
            var receiptOK = voter.validateReceipt(receipts[i]);
            expect(receiptOK).toBe(true);
    	}
    });

    it( 'The collecting server produces correct list of voters', function()
    {
        console.log('************ Checking the list of voters');

		var signedVotersList = cs.getVotersList();
		var p = unpair(signedVotersList);
		var data = p.first; // tag,elID,voters
		var signature = p.second;
        // check the signature
		expect(verif(colServVerifKey, data, signature)) .toBe(true);

        var data = crypto.splitter(data);

		expect(data.nextMessage()) .toBe(TAG_VOTERS); // check the tag
		expect(data.nextMessage()) .toBe(electionID); // check the election id
        // The rest of data is a list of voterIDs.
        var votersBack = new Array(NVoters);
        for (var i=0; !data.empty(); ++i) {
        	votersBack[i] = cryptoUtils.messageToString(data.nextMessage());
        	//console.log('\t' + votersBack[i]);
        }
        expect(bijection(votersBack, voters)).toBe(true);
    });

    it( 'The collecting server produces correct list of ballots', function()
    {
        console.log('************ Checking the list of ballots');

		var signedBallots = cs.getResult();
		var p = unpair(signedBallots);
		var data = p.first; // tag,elID,voters
		var signature = p.second;
        // check the signature
		expect(verif(colServVerifKey, data, signature)) .toBe(true);

        var data = crypto.splitter(data);

		expect(data.nextMessage()) .toBe(voterClient.TAG_BALLOTS); // expected the tag
		expect(data.nextMessage()) .toBe(electionID);  // expected the election id

        // The rest of data is a list of ballots
        // Lets take this list
        var ballotsInResult = [];
        for (var i=0; !data.empty(); ++i) {
            ballotsInResult.push(data.nextMessage());
        }
        // It should be equal to the sorted list of cast ballots
        var castBallots = receipts.map(function(rec){ return rec.ballot }).sort();
		expect(castBallots.length).toBe(ballotsInResult.length);
		for(i=0; i<castBallots.length; ++i) {
			expect(ballotsInResult[i]).toBe(castBallots[i]);
		}
    });

    it( 'The first mix server process the data correctly', function()
    {
    	console.log('************ Testing a mix server with trash');

    	// let's first give him trash
    	var signedBallots = crypto.nonce(2000);
    	var inputFile_path = PARTIALRESULT_template + 'CRAP_input.msg';
    	dataToFile(signedBallots, inputFile_path);
    	var outputFile_path = PARTIALRESULT_template + 'CRAP_output.msg';
    	mixServer[0].processBallots(inputFile_path, outputFile_path,
    		function(err, stdout, stderr){
				expect (err===null) .toBe(false);
				expect (err.code) .toBe(1); // wrong signature
			},
			function (code) {
				expect (code) .toBe (1); // wrong signature
				//console.log("Program exited with code " + code);
			});

    }, TIMEOUT);

    it( 'The first mix server process the data correctly', function()
    {
    	console.log('************ Testing a mix server with correct data');
    	// now seriously
    	var signedBallots = cs.getResult();
    	// write the result on a file
    	var inputFile_path = PARTIALRESULT_template + '00_input.msg';
    	dataToFile(signedBallots, inputFile_path);
    	var outputFile_path = PARTIALRESULT_template + '00_output.msg';

    	// result to the first mix server
    	mixServer[0].processBallots(inputFile_path, outputFile_path,
    		function(err, stdout, stderr){
    			console.log(stdout);
    			console.log(stderr);
    			//console.log(outputFile_path);
    			dataFromFile(outputFile_path, function (err, data) {
    				if (err){
    		        	console.log('Problems with reading data from ', path);
    		            console.log('Error: ', err);
    		            return;
    		        }
    		        //console.log(data);
    		    });
    		},
    		function (code) {
    			expect (code) .toBe (0);
    			//console.log("Program exited with code " + code);
    		});
    }, TIMEOUT);

    it( 'Mixing works as expected', function(done)
    {
    	console.log('************ Testing a mix servers\' chain');
    	var data = cs.getResult();
    	mix(0, data, done);
    }, TIMEOUT); // timeout in ms

    function mix(i, inputData, done) {
        if (i >= NMixServ)  {
            done();
            return;
        }

        console.log('************ Mixing', i);

        var inputFile_path = PARTIALRESULT_template + '0' + i + '_input.msg';
    	dataToFile(inputData, inputFile_path);
    	var outputFile_path = PARTIALRESULT_template + '0' + i + '_output.msg';

    	mixServer[i].processBallots(inputFile_path, outputFile_path,
        	function(err, stdout, stderr){
				console.log(stdout);
				console.log(stderr);
			},
			function(code){
				expect(code) .toBe(0);
				intermediateResult[i] = dataFromFile(outputFile_path);
				//console.log(intermediateResult[i]);
				mix(i+1, intermediateResult[i], done);
			});
    }

    it( 'Final results as expected', function()
    {
    	console.log('************ Final Result');

    	var finalResult = intermediateResult[NMixServ-1];
    	var p = unpair(finalResult);
    	var tag_elID_ballots = p.first; 	// [tag, elID, ballotsAsAMessage]
		var signature = p.second;
        // check the signature
		expect(verif(mixServer[mixServer.length-1].verifKey, tag_elID_ballots, signature)) .toBe(true);

        var data = crypto.splitter(tag_elID_ballots);

		expect(data.nextMessage()) .toBe(TAG_BALLOTS); // expected the tag
		expect(data.nextMessage()) .toBe(electionID);  // expected the election id

        // The rest of data is a list of (electionID, receiptID,choice)
        // Lets take this list
        var receiptIDs = [];
        var choices = [];
        for (var i=0; !data.empty(); ++i) {
        	p = unpair(data.nextMessage());
        	expect(p.first).toBe(electionID);
        	var receipt_choice = p.second;
        	p = unpair(receipt_choice);
        	var receiptID = p.first;
        	var choice = crypto.hexStringToInt(p.second);
        	//console.log(receipt + "\t" + choice);
        	receiptIDs.push(receiptID);
            choices.push(choice);
        }
        originalReceiptIDs = receipts.map(function(rec){ return rec.receiptIDs });
        originalChoices = receipts.map(function(rec){ return rec.receiptID});

        expect(bijection(originalReceiptIDs, receiptIDs)) .toBe(true);
        expect(bijection(originalChoices, choices)) .toBe(true);
    });

    it( 'Voter verification works as expected', function()
    {
        console.log('************ Verification');

        // Voter who cast his ballot should verify that
        // everything went fine:
        var n = 1; // the index of the voter to check result
        var res = voter.checkColServerResult(cs.getResult(), receipts[n]);
        expect(res.ok).toBe(true);
        for (var i=0; i<NMixServ; ++i) {
            var res = voter.checkMixServerResult(i, intermediateResult[i], receipts[n]);
            expect(res.ok).toBe(true);
        }

        // The same, but now for wrong data:
        res = voter.checkColServerResult(intermediateResult[0], receipts[n]);
        expect(res.ok).toBe(false);
        expect(res.descr).toBe('Wrong signature');

        // Let us now take a voter whose ballot was ignored (was
        // not cast):
        var rec = voter.createBallot(i);
        var res = voter.checkColServerResult(cs.getResult(), rec);
        expect(res.ok).toBe(false);
        expect(res.descr).toBe('Ballot not found');
        for (var i=0; i<NMixServ; ++i) {
            var res = voter.checkMixServerResult(i, intermediateResult[i], rec);
            expect(res.ok).toBe(false);
            expect(res.descr).toBe('Ballot not found');
        }
    });

});

/* no callback: syncronous version */
function dataFromFile(path, callback){
	if(callback)
		fs.readFile(path, {encoding:'ascii'}, callback);
	/* function (err, data) {
	 * 		if (err) throw err;
	 *		  	console.log(data);
	 *	});
	 */
	else
		return fs.readFileSync(path, {encoding:'ascii'});
}

/* no callback: syncronous version */
function dataToFile(data, path, callback){
	if (callback)
		fs.writeFile(path, data, callback);
	/* 	function (err) {
     *   if (err)
     *       console.log('Problems with saving data in ', path);
     *   else
     *       console.log('Data written in ', path);
     *	});
     */
	else
		fs.writeFileSync(path, data);

}

function bijection(arr1, arr2){
	//if(!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length!=arr2.length)
	if(arr1.length!=arr2.length)
		return false;
	arr1.sort();
	arr2.sort();
	for(var i=0; i<arr1.sort(); ++i)
		if(arr1[i] === arr2[i])
			return false;
	return true;
}
<commit_msg>ascii ---> utf8<commit_after>var fs = require('fs');
var path = require('path');
var crypto = require('cryptofunc');
var cryptoUtils = require('cryptoUtils');
var voterClient = require('voterClient');
var csCore = require('../CollectingServer/src/csCore.js');
var mixCore = require('../MixServer/src/mixCore.js');
var mkdirp = require('mkdirp');

//////////////////////////////////////////////////////////////////////////////////////////
// Shortcuts

var pair = crypto.concatenate;
var unpair = crypto.deconcatenate;
var sign = crypto.sign;
var verif = crypto.verifsig;

//////////////////////////////////////////////////////////////////////////////////////////

// Parameters and keys

var TAG_VOTERS = '10';
var TAG_BALLOTS = '01';
//console.log('CWD:\t' + process.cwd());
var PARTIALRESULT_template = process.cwd() + '/data/partialResults';
var TIMEOUT = 100000;

var electionID = 'eeee';
var NMixServ = 5;
var NVoters = 10;
var voters = new Array(NVoters);

console.log('************ Initialisation');

// voters identifiers
for (var i=NVoters-1; i>=0; --i) {
    voters[i] = 'abc'  + i + '@ema.il';
}

// Keys
var colServSigKeys = crypto.sig_keygen();
var colServVerifKey = colServSigKeys.verificationKey;

var mixServPkeKeys = new Array(NMixServ);
var mixServSigKeys = new Array(NMixServ);
for(var i=0; i<NMixServ; i++) {
	mixServPkeKeys[i] = crypto.pke_keygen();
	mixServSigKeys[i] = crypto.sig_keygen();
}
var mixServEncKeys = mixServPkeKeys.map(function(k){ return k.encryptionKey; });
var mixServVerifKeys = mixServSigKeys.map(function(k){ return k.verificationKey; });

//////////////////////////////////////////////////////////////////////////////////////////
// Test cases

describe( 'Voting process', function()
{

	var cs = csCore.create(electionID, voters, colServSigKeys.signingKey);
    var receipts = new Array(voters.length);
    var voter = voterClient.create(electionID, colServVerifKey, mixServEncKeys, mixServVerifKeys);

    //console.log('Test: Current directory --> ' + process.cwd());

    // create the folder where the data processed
    // by the mix servers will be stored
    mkdirp('./data', function (err) {
        if (err)
        	console.error("Error: ", err);
//		else
//        	console.log("Folder '" + config.DATA_FOLDER + "' created.");
    });

    // Create mix servers
    var mixServer = new Array(NMixServ);
    for (i=0; i<NMixServ; ++i) {
        var precServVerifKey = (i==0 ? colServVerifKey : mixServSigKeys[i-1].verificationKey );
    	mixServer[i] = mixCore.create(	mixServPkeKeys[i].encryptionKey,
    									mixServPkeKeys[i].decryptionKey,
    									mixServSigKeys[i].verificationKey,
    									mixServSigKeys[i].signingKey,
    									precServVerifKey, electionID,
    									NVoters);
    }
    var intermediateResult = new Array(NMixServ);

    it ( 'eligibleVoters field works as expected', function()
    {
    	var listElVoters = Object.keys(cs.eligibleVoters);
    	expect(bijection(listElVoters, voters)).toBe(true);
    });

    it( 'Ballot creation works as expected', function()
    {
        console.log('************ Ballot creation');
    	for(i=voters.length-1; i>=0; --i){
            // create ballot (a receipt containing a ballot); i-th voter votes for i-th candidate:
    		receipts[i] = voter.createBallot(i);
    		expect (receipts[i].choice) .toBe(i);
        }
    });

    it( 'Ballot casting works as expected', function()
    {
        console.log('************ Ballot casting');

        for(i=voters.length-1; i>=0; --i){
            // submit the ballot
        	var csReply = cs.collectBallot(voters[i], receipts[i].ballot);
        	expect (csReply.ok).toBe(true);

            // check the acknowledgement (signature)
            receipts[i].signature = csReply.data;
            var receiptOK = voter.validateReceipt(receipts[i]);
            expect(receiptOK).toBe(true);
    	}
    });

    it( 'The collecting server produces correct list of voters', function()
    {
        console.log('************ Checking the list of voters');

		var signedVotersList = cs.getVotersList();
		var p = unpair(signedVotersList);
		var data = p.first; // tag,elID,voters
		var signature = p.second;
        // check the signature
		expect(verif(colServVerifKey, data, signature)) .toBe(true);

        var data = crypto.splitter(data);

		expect(data.nextMessage()) .toBe(TAG_VOTERS); // check the tag
		expect(data.nextMessage()) .toBe(electionID); // check the election id
        // The rest of data is a list of voterIDs.
        var votersBack = new Array(NVoters);
        for (var i=0; !data.empty(); ++i) {
        	votersBack[i] = cryptoUtils.messageToString(data.nextMessage());
        	//console.log('\t' + votersBack[i]);
        }
        expect(bijection(votersBack, voters)).toBe(true);
    });

    it( 'The collecting server produces correct list of ballots', function()
    {
        console.log('************ Checking the list of ballots');

		var signedBallots = cs.getResult();
		var p = unpair(signedBallots);
		var data = p.first; // tag,elID,voters
		var signature = p.second;
        // check the signature
		expect(verif(colServVerifKey, data, signature)) .toBe(true);

        var data = crypto.splitter(data);

		expect(data.nextMessage()) .toBe(voterClient.TAG_BALLOTS); // expected the tag
		expect(data.nextMessage()) .toBe(electionID);  // expected the election id

        // The rest of data is a list of ballots
        // Lets take this list
        var ballotsInResult = [];
        for (var i=0; !data.empty(); ++i) {
            ballotsInResult.push(data.nextMessage());
        }
        // It should be equal to the sorted list of cast ballots
        var castBallots = receipts.map(function(rec){ return rec.ballot }).sort();
		expect(castBallots.length).toBe(ballotsInResult.length);
		for(i=0; i<castBallots.length; ++i) {
			expect(ballotsInResult[i]).toBe(castBallots[i]);
		}
    });

    it( 'The first mix server process the data correctly', function()
    {
    	console.log('************ Testing a mix server with trash');

    	// let's first give him trash
    	var signedBallots = crypto.nonce(2000);
    	var inputFile_path = PARTIALRESULT_template + 'CRAP_input.msg';
    	dataToFile(signedBallots, inputFile_path);
    	var outputFile_path = PARTIALRESULT_template + 'CRAP_output.msg';
    	mixServer[0].processBallots(inputFile_path, outputFile_path,
    		function(err, stdout, stderr){
				expect (err===null) .toBe(false);
				expect (err.code) .toBe(1); // wrong signature
			},
			function (code) {
				expect (code) .toBe (1); // wrong signature
				//console.log("Program exited with code " + code);
			});

    }, TIMEOUT);

    it( 'The first mix server process the data correctly', function()
    {
    	console.log('************ Testing a mix server with correct data');
    	// now seriously
    	var signedBallots = cs.getResult();
    	// write the result on a file
    	var inputFile_path = PARTIALRESULT_template + '00_input.msg';
    	dataToFile(signedBallots, inputFile_path);
    	var outputFile_path = PARTIALRESULT_template + '00_output.msg';

    	// result to the first mix server
    	mixServer[0].processBallots(inputFile_path, outputFile_path,
    		function(err, stdout, stderr){
    			console.log(stdout);
    			console.log(stderr);
    			//console.log(outputFile_path);
    			dataFromFile(outputFile_path, function (err, data) {
    				if (err){
    		        	console.log('Problems with reading data from ', path);
    		            console.log('Error: ', err);
    		            return;
    		        }
    		        //console.log(data);
    		    });
    		},
    		function (code) {
    			expect (code) .toBe (0);
    			//console.log("Program exited with code " + code);
    		});
    }, TIMEOUT);

    it( 'Mixing works as expected', function(done)
    {
    	console.log('************ Testing a mix servers\' chain');
    	var data = cs.getResult();
    	mix(0, data, done);
    }, TIMEOUT); // timeout in ms

    function mix(i, inputData, done) {
        if (i >= NMixServ)  {
            done();
            return;
        }

        console.log('************ Mixing', i);

        var inputFile_path = PARTIALRESULT_template + '0' + i + '_input.msg';
    	dataToFile(inputData, inputFile_path);
    	var outputFile_path = PARTIALRESULT_template + '0' + i + '_output.msg';

    	mixServer[i].processBallots(inputFile_path, outputFile_path,
        	function(err, stdout, stderr){
				console.log(stdout);
				console.log(stderr);
			},
			function(code){
				expect(code) .toBe(0);
				intermediateResult[i] = dataFromFile(outputFile_path);
				//console.log(intermediateResult[i]);
				mix(i+1, intermediateResult[i], done);
			});
    }

    it( 'Final results as expected', function()
    {
    	console.log('************ Final Result');

    	var finalResult = intermediateResult[NMixServ-1];
    	var p = unpair(finalResult);
    	var tag_elID_ballots = p.first; 	// [tag, elID, ballotsAsAMessage]
		var signature = p.second;
        // check the signature
		expect(verif(mixServer[mixServer.length-1].verifKey, tag_elID_ballots, signature)) .toBe(true);

        var data = crypto.splitter(tag_elID_ballots);

		expect(data.nextMessage()) .toBe(TAG_BALLOTS); // expected the tag
		expect(data.nextMessage()) .toBe(electionID);  // expected the election id

        // The rest of data is a list of (electionID, receiptID,choice)
        // Lets take this list
        var receiptIDs = [];
        var choices = [];
        for (var i=0; !data.empty(); ++i) {
        	p = unpair(data.nextMessage());
        	expect(p.first).toBe(electionID);
        	var receipt_choice = p.second;
        	p = unpair(receipt_choice);
        	var receiptID = p.first;
        	var choice = crypto.hexStringToInt(p.second);
        	//console.log(receipt + "\t" + choice);
        	receiptIDs.push(receiptID);
            choices.push(choice);
        }
        originalReceiptIDs = receipts.map(function(rec){ return rec.receiptIDs });
        originalChoices = receipts.map(function(rec){ return rec.receiptID});

        expect(bijection(originalReceiptIDs, receiptIDs)) .toBe(true);
        expect(bijection(originalChoices, choices)) .toBe(true);
    });

    it( 'Voter verification works as expected', function()
    {
        console.log('************ Verification');

        // Voter who cast his ballot should verify that
        // everything went fine:
        var n = 1; // the index of the voter to check result
        var res = voter.checkColServerResult(cs.getResult(), receipts[n]);
        expect(res.ok).toBe(true);
        for (var i=0; i<NMixServ; ++i) {
            var res = voter.checkMixServerResult(i, intermediateResult[i], receipts[n]);
            expect(res.ok).toBe(true);
        }

        // The same, but now for wrong data:
        res = voter.checkColServerResult(intermediateResult[0], receipts[n]);
        expect(res.ok).toBe(false);
        expect(res.descr).toBe('Wrong signature');

        // Let us now take a voter whose ballot was ignored (was
        // not cast):
        var rec = voter.createBallot(i);
        var res = voter.checkColServerResult(cs.getResult(), rec);
        expect(res.ok).toBe(false);
        expect(res.descr).toBe('Ballot not found');
        for (var i=0; i<NMixServ; ++i) {
            var res = voter.checkMixServerResult(i, intermediateResult[i], rec);
            expect(res.ok).toBe(false);
            expect(res.descr).toBe('Ballot not found');
        }
    });

});

/* no callback: synchronous version */
function dataFromFile(path, callback){
	if(callback)
		fs.readFile(path, {encoding:'utf8'}, callback);
	/* function (err, data) {
	 * 		if (err) throw err;
	 *		  	console.log(data);
	 *	});
	 */
	else
		return fs.readFileSync(path, {encoding:'utf8'});
}

/* no callback: synchronous version */
function dataToFile(data, path, callback){
	if (callback)
		fs.writeFile(path, data, {encoding:'utf8'}, callback);
	/* 	function (err) {
     *   if (err)
     *       console.log('Problems with saving data in ', path);
     *   else
     *       console.log('Data written in ', path);
     *	});
     */
	else
		fs.writeFileSync(path, data, {encoding:'utf8'});
}

function bijection(arr1, arr2){
	//if(!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length!=arr2.length)
	if(arr1.length!=arr2.length)
		return false;
	arr1.sort();
	arr2.sort();
	for(var i=0; i<arr1.sort(); ++i)
		if(arr1[i] === arr2[i])
			return false;
	return true;
}
<|endoftext|>


<commit_before>

var rgb = function(r, g, b, a) {
	var a = a || 255;
	return ~~ a << 32 ^ ~~ r << 16 ^ ~~ g << 8 ^ ~~ b;
}
var hsv = function(h, s, v) {

}
var red = function(color) {

}
var
var hex = function(color) {
	return '#'+color.toString(16);
}

console.log(hex(rgb(0, 0, 255, 255)));
<commit_msg>Deleted color.js<commit_after><|endoftext|>