<commit_before>let http = require('follow-redirects').http;
let https = require('follow-redirects').https;
const {canonicalHost} = require('./host');

const balanceRegex = /([0-9]+) ?([a-zA-Z]*)/;

function joinPath() {
  const path = require('path');
  return path.join.apply(path.join, arguments);
}

function dirname() {
  const path = require('path');
  return path.dirname.apply(path.dirname, arguments);
}

function filesMatchingPattern(files) {
  const globule = require('globule');
  return globule.find(files, {nonull: true});
}

function fileMatchesPattern(patterns, intendedPath) {
  const globule = require('globule');
  return globule.isMatch(patterns, intendedPath);
}

function recursiveMerge(target, source) {
  const merge = require('merge');
  return merge.recursive(target, source);
}

function checkIsAvailable(url, callback) {
  http.get(url, function (_res) {
    callback(true);
  }).on('error', function (_res) {
    callback(false);
  });
}

function httpGetRequest(httpObj, url, callback) {
  httpObj.get(url, function (res) {
    let body = '';
    res.on('data', function (d) {
      body += d;
    });
    res.on('end', function () {
      callback(null, body);
    });
  }).on('error', function (err) {
    callback(err);
  });
}

function httpGet(url, callback) {
  httpGetRequest(http, url, callback);
}

function httpsGet(url, callback) {
  httpGetRequest(https, url, callback);
}

function httpGetJson(url, callback) {
  httpGetRequest(http, url, function (err, body) {
    try {
      let parsed = JSON.parse(body);
      return callback(err, parsed);
    } catch (e) {
      return callback(e);
    }
  });
}

function httpsGetJson(url, callback) {
  httpGetRequest(https, url, function (err, body) {
    try {
      let parsed = JSON.parse(body);
      return callback(err, parsed);
    } catch (e) {
      return callback(e);
    }
  });
}

function getJson(url, cb) {
  if (url.indexOf('https') === 0) {
    return httpsGetJson(url, cb);
  }
  httpGetJson(url, cb);
}

function pingEndpoint(host, port, type, protocol, origin, callback) {
  const options = {
    protocolVersion: 13,
    perMessageDeflate: true,
    origin: origin,
    host: host,
    port: port
  };
  if (type === 'ws') {
    options.headers = {
      'Sec-WebSocket-Version': 13,
      Connection: 'Upgrade',
      Upgrade: 'websocket',
      'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
      Origin: origin
    };
  }
  let req;
  // remove trailing api key from infura, ie rinkeby.infura.io/nmY8WtT4QfEwz2S7wTbl
  if (options.host.indexOf('/') > -1) {
    options.host = options.host.split('/')[0];
  }
  if (protocol === 'https') {
    req = require('https').get(options);
  } else {
    req = require('http').get(options);
  }

  req.on('error', (err) => {
    callback(err);
  });

  req.on('response', (_response) => {
    callback();
  });

  req.on('upgrade', (_res, _socket, _head) => {
    callback();
  });
}

function runCmd(cmd, options, callback) {
  const shelljs = require('shelljs');
  options = Object.assign({silent: true, exitOnError: true}, options);
  let result = shelljs.exec(cmd);
  if (result.code !== 0) {
    console.log("error doing.. " + cmd);
    console.log(result.output);
    if (result.stderr !== undefined) {
      console.log(result.stderr);
    }
    if (typeof callback === 'function') {
      return callback(result, null);
    }
    if (options.exitOnError) {
      exit();
    }
  }
  callback(null, result);
}

function cd(folder) {
  const shelljs = require('shelljs');
  shelljs.cd(folder);
}

function sed(file, pattern, replace) {
  const shelljs = require('shelljs');
  shelljs.sed('-i', pattern, replace, file);
}

function exit(code) {
  process.exit(code);
}

function downloadFile(url, dest, cb) {
  const o_fs = require('fs-extra');
  var file = o_fs.createWriteStream(dest);
  (url.substring(0, 5) === 'https' ? https : http).get(url, function (response) {
    response.pipe(file);
    file.on('finish', function () {
      file.close(cb);
    });
  }).on('error', function (err) {
    o_fs.unlink(dest);
    if (cb) cb(err.message);
  });
}

function extractTar(filename, packageDirectory, cb) {
  const o_fs = require('fs-extra');
  const tar = require('tar');
  o_fs.createReadStream(filename).pipe(
    tar.x({
      strip: 1,
      C: packageDirectory
    }).on('end', function () {
      cb();
    })
  );
}

function extractZip(filename, packageDirectory, opts, cb) {
  const decompress = require('decompress');

  decompress(filename, packageDirectory, opts).then((_files) => {
    cb();
  });
}

function proposeAlternative(word, _dictionary, _exceptions) {
  const propose = require('propose');
  let exceptions = _exceptions || [];
  let dictionary = _dictionary.filter((entry) => {
    return exceptions.indexOf(entry) < 0;
  });
  return propose(word, dictionary, {threshold: 0.3});
}

function getExternalContractUrl(file) {
  const constants = require('../constants');
  let url;
  const RAW_URL = 'https://raw.githubusercontent.com/';
  const MALFORMED_ERROR = 'Malformed Github URL for ';
  if (file.startsWith('https://github')) {
    const match = file.match(/https:\/\/github\.[a-z]+\/(.*)/);
    if (!match) {
      console.error(MALFORMED_ERROR + file);
      return null;
    }
    url = `${RAW_URL}${match[1].replace('blob/', '')}`;
  } else if (file.startsWith('git')) {
    // Match values
    // [0] entire input
    // [1] git://
    // [2] user
    // [3] repository
    // [4] path
    // [5] branch
    const match = file.match(
      /(git:\/\/)?github\.[a-z]+\/([-a-zA-Z0-9@:%_+.~#?&=]+)\/([-a-zA-Z0-9@:%_+.~#?&=]+)\/([-a-zA-Z0-9@:%_+.~?\/&=]+)#?([a-zA-Z0-9\/_.-]*)?/
    );
    if (!match) {
      console.error(MALFORMED_ERROR + file);
      return null;
    }
    let branch = match[5];
    if (!branch) {
      branch = 'master';
    }
    url = `${RAW_URL}${match[2]}/${match[3]}/${branch}/${match[4]}`;
  } else if (file.startsWith('http')) {
    url = file;
  } else {
    return null;
  }
  const match = url.match(
    /\.[a-z]+\/([-a-zA-Z0-9@:%_+.~#?&\/=]+)/
  );
  return {
    url,
    filePath: constants.httpContractsDirectory + match[1]
  };
}

function hexToNumber(hex) {
  const Web3 = require('web3');
  return Web3.utils.hexToNumber(hex);
}

function isHex(hex) {
  const Web3 = require('web3');
  return Web3.utils.isHex(hex);
}

function hashTo32ByteHexString(hash) {
  if (isHex(hash)) {
    if (!hash.startsWith('0x')) {
      hash = '0x' + hash;
    }
    return hash;
  }
  const multihash = require('multihashes');
  let buf = multihash.fromB58String(hash);
  let digest = multihash.decode(buf).digest;
  return '0x' + multihash.toHexString(digest);
}

function isValidDomain(domain) {
  const isValidDomain = require('is-valid-domain');
  return isValidDomain(domain);
}

function isValidEthDomain(ethDomain) {
  if (!isValidDomain(ethDomain)) {
    return false;
  }
  return ethDomain.substring(ethDomain.lastIndexOf('.'), ethDomain.length) === '.eth';
}

function decodeParams(typesArray, hexString) {
  var Web3EthAbi = require('web3-eth-abi');
  return Web3EthAbi.decodeParameters(typesArray, hexString);
}

function toChecksumAddress(address) {
  const Web3 = require('web3');
  return Web3.utils.toChecksumAddress(address);
}

function sha3(arg) {
  const Web3 = require('web3');
  return Web3.utils.sha3(arg);
}

function soliditySha3(arg) {
  const Web3 = require('web3');
  return Web3.utils.soliditySha3(arg);
}

function normalizeInput(input) {
  let args = Object.values(input);
  if (args.length === 0) {
    return "";
  }
  if (args.length === 1) {
    if (Array.isArray(args[0])) {
      return args[0].join(',');
    }
    return args[0] || "";
  }
  return ('[' + args.map((x) => {
    if (x === null) {
      return "null";
    }
    if (x === undefined) {
      return "undefined";
    }
    if (Array.isArray(x)) {
      return x.join(',');
    }
    return x;
  }).toString() + ']');
}

/**
 * Builds a URL
 *
 * @param {string} protocol
 *  The URL protocol, defaults to http.
 * @param {string} host
 *  The URL host, required.
 * @param {string} port
 *  The URL port, default to empty string.
 * @param {string} [type]
 *  Type of connection
 * @returns {string} the constructued URL, with defaults
 */
function buildUrl(protocol, host, port, type) {
  if (!host) throw new Error('utils.buildUrl: parameter \'host\' is required');
  if (port) port = ':' + port;
  else port = '';
  if (!protocol) {
    protocol = type === 'ws' ? 'ws' : 'http';
  }
  return `${protocol}://${host}${port}`;
}

/**
 * Builds a URL
 *
 * @param {object} configObj Object containing protocol, host, and port to be used to construct the url.
 *      * protocol      {String}    (optional) The URL protocol, defaults to http.
 *      * host          {String}    (required) The URL host.
 *      * port          {String}    (optional) The URL port, default to empty string.
 * @returns {string} the constructued URL, with defaults
 */
function buildUrlFromConfig(configObj) {
  if (!configObj) throw new Error('[utils.buildUrlFromConfig]: config object must cannot be null');
  if (!configObj.host) throw new Error('[utils.buildUrlFromConfig]: object must contain a \'host\' property');
  return this.buildUrl(configObj.protocol, canonicalHost(configObj.host), configObj.port, configObj.type);
}

function deconstructUrl(endpoint) {
  const matches = endpoint.match(/(ws|https?):\/\/([a-zA-Z0-9_.-]*):?([0-9]*)?/);
  return {
    protocol: matches[1],
    host: matches[2],
    port: matches[3],
    type: matches[1] === 'ws' ? 'ws' : 'rpc'
  };
}

function getWeiBalanceFromString(balanceString, web3){
  if(!web3){
    throw new Error(__('[utils.getWeiBalanceFromString]: Missing parameter \'web3\''));
  }
  if (!balanceString) {
    return 0;
  }
  const match = balanceString.match(balanceRegex);
  if (!match) {
    throw new Error(__('Unrecognized balance string "%s"', balanceString));
  }
  if (!match[2]) {
    return web3.utils.toHex(parseInt(match[1], 10));
  }

  return web3.utils.toWei(match[1], match[2]);
}

function getHexBalanceFromString(balanceString, web3) {
  if(!web3){
    throw new Error(__('[utils.getWeiBalanceFromString]: Missing parameter \'web3\''));
  }
  if (!balanceString) {
    return 0xFFFFFFFFFFFFFFFFFF;
  }
  if (web3.utils.isHexStrict(balanceString)) {
    return balanceString;
  }
  const match = balanceString.match(balanceRegex);
  if (!match) {
    throw new Error(__('Unrecognized balance string "%s"', balanceString));
  }
  if (!match[2]) {
    return web3.utils.toHex(parseInt(match[1], 10));
  }

  return web3.utils.toHex(web3.utils.toWei(match[1], match[2]));
}

function compact(array) {
  return array.filter(n => n);
}

function groupBy(array, key) {
  return array.reduce(function (rv, x) {
    (rv[x[key]] = rv[x[key]] || []).push(x);
    return rv;
  }, {});
}

function sample(array) {
  return array[Math.floor(Math.random() * array.length)];
}

function last(array) {
  return array[array.length - 1];
}

function interceptLogs(consoleContext, logger) {
  let context = {};
  context.console = consoleContext;

  context.console.log = function () {
    logger.info(normalizeInput(arguments));
  };
  context.console.warn = function () {
    logger.warn(normalizeInput(arguments));
  };
  context.console.info = function () {
    logger.info(normalizeInput(arguments));
  };
  context.console.debug = function () {
    // TODO: ue JSON.stringify
    logger.debug(normalizeInput(arguments));
  };
  context.console.trace = function () {
    logger.trace(normalizeInput(arguments));
  };
  context.console.dir = function () {
    logger.dir(normalizeInput(arguments));
  };
}

function errorMessage(e) {
  if (typeof e === 'string') {
    return e;
  } else if (e && e.message) {
    return e.message;
  }
  return e;
}

module.exports = {
  joinPath,
  dirname,
  filesMatchingPattern,
  fileMatchesPattern,
  recursiveMerge,
  checkIsAvailable,
  httpGet,
  httpsGet,
  httpGetJson,
  httpsGetJson,
  getJson,
  hexToNumber,
  isHex,
  hashTo32ByteHexString,
  isValidDomain,
  isValidEthDomain,
  pingEndpoint,
  decodeParams,
  runCmd,
  cd,
  sed,
  exit,
  downloadFile,
  extractTar,
  extractZip,
  proposeAlternative,
  getExternalContractUrl,
  toChecksumAddress,
  sha3,
  soliditySha3,
  normalizeInput,
  buildUrl,
  buildUrlFromConfig,
  deconstructUrl,
  getWeiBalanceFromString,
  getHexBalanceFromString,
  compact,
  groupBy,
  sample,
  last,
  interceptLogs,
  errorMessage
};
<commit_msg>fix runCmd<commit_after>let http = require('follow-redirects').http;
let https = require('follow-redirects').https;
const {canonicalHost} = require('./host');

const balanceRegex = /([0-9]+) ?([a-zA-Z]*)/;

function joinPath() {
  const path = require('path');
  return path.join.apply(path.join, arguments);
}

function dirname() {
  const path = require('path');
  return path.dirname.apply(path.dirname, arguments);
}

function filesMatchingPattern(files) {
  const globule = require('globule');
  return globule.find(files, {nonull: true});
}

function fileMatchesPattern(patterns, intendedPath) {
  const globule = require('globule');
  return globule.isMatch(patterns, intendedPath);
}

function recursiveMerge(target, source) {
  const merge = require('merge');
  return merge.recursive(target, source);
}

function checkIsAvailable(url, callback) {
  http.get(url, function (_res) {
    callback(true);
  }).on('error', function (_res) {
    callback(false);
  });
}

function httpGetRequest(httpObj, url, callback) {
  httpObj.get(url, function (res) {
    let body = '';
    res.on('data', function (d) {
      body += d;
    });
    res.on('end', function () {
      callback(null, body);
    });
  }).on('error', function (err) {
    callback(err);
  });
}

function httpGet(url, callback) {
  httpGetRequest(http, url, callback);
}

function httpsGet(url, callback) {
  httpGetRequest(https, url, callback);
}

function httpGetJson(url, callback) {
  httpGetRequest(http, url, function (err, body) {
    try {
      let parsed = JSON.parse(body);
      return callback(err, parsed);
    } catch (e) {
      return callback(e);
    }
  });
}

function httpsGetJson(url, callback) {
  httpGetRequest(https, url, function (err, body) {
    try {
      let parsed = JSON.parse(body);
      return callback(err, parsed);
    } catch (e) {
      return callback(e);
    }
  });
}

function getJson(url, cb) {
  if (url.indexOf('https') === 0) {
    return httpsGetJson(url, cb);
  }
  httpGetJson(url, cb);
}

function pingEndpoint(host, port, type, protocol, origin, callback) {
  const options = {
    protocolVersion: 13,
    perMessageDeflate: true,
    origin: origin,
    host: host,
    port: port
  };
  if (type === 'ws') {
    options.headers = {
      'Sec-WebSocket-Version': 13,
      Connection: 'Upgrade',
      Upgrade: 'websocket',
      'Sec-WebSocket-Extensions': 'permessage-deflate; client_max_window_bits',
      Origin: origin
    };
  }
  let req;
  // remove trailing api key from infura, ie rinkeby.infura.io/nmY8WtT4QfEwz2S7wTbl
  if (options.host.indexOf('/') > -1) {
    options.host = options.host.split('/')[0];
  }
  if (protocol === 'https') {
    req = require('https').get(options);
  } else {
    req = require('http').get(options);
  }

  req.on('error', (err) => {
    callback(err);
  });

  req.on('response', (_response) => {
    callback();
  });

  req.on('upgrade', (_res, _socket, _head) => {
    callback();
  });
}

function runCmd(cmd, options, callback) {
  const shelljs = require('shelljs');
  options = Object.assign({silent: true, exitOnError: true}, options || {});
  let result = shelljs.exec(cmd);
  if (result.code !== 0) {
    console.log("error doing.. " + cmd);
    console.log(result.output);
    if (result.stderr !== undefined) {
      console.log(result.stderr);
    }
    if (typeof callback === 'function') {
      return callback(result, null);
    }
    if (options.exitOnError) {
      exit();
    }
  }
  callback(null, result);
}

function cd(folder) {
  const shelljs = require('shelljs');
  shelljs.cd(folder);
}

function sed(file, pattern, replace) {
  const shelljs = require('shelljs');
  shelljs.sed('-i', pattern, replace, file);
}

function exit(code) {
  process.exit(code);
}

function downloadFile(url, dest, cb) {
  const o_fs = require('fs-extra');
  var file = o_fs.createWriteStream(dest);
  (url.substring(0, 5) === 'https' ? https : http).get(url, function (response) {
    response.pipe(file);
    file.on('finish', function () {
      file.close(cb);
    });
  }).on('error', function (err) {
    o_fs.unlink(dest);
    if (cb) cb(err.message);
  });
}

function extractTar(filename, packageDirectory, cb) {
  const o_fs = require('fs-extra');
  const tar = require('tar');
  o_fs.createReadStream(filename).pipe(
    tar.x({
      strip: 1,
      C: packageDirectory
    }).on('end', function () {
      cb();
    })
  );
}

function extractZip(filename, packageDirectory, opts, cb) {
  const decompress = require('decompress');

  decompress(filename, packageDirectory, opts).then((_files) => {
    cb();
  });
}

function proposeAlternative(word, _dictionary, _exceptions) {
  const propose = require('propose');
  let exceptions = _exceptions || [];
  let dictionary = _dictionary.filter((entry) => {
    return exceptions.indexOf(entry) < 0;
  });
  return propose(word, dictionary, {threshold: 0.3});
}

function getExternalContractUrl(file) {
  const constants = require('../constants');
  let url;
  const RAW_URL = 'https://raw.githubusercontent.com/';
  const MALFORMED_ERROR = 'Malformed Github URL for ';
  if (file.startsWith('https://github')) {
    const match = file.match(/https:\/\/github\.[a-z]+\/(.*)/);
    if (!match) {
      console.error(MALFORMED_ERROR + file);
      return null;
    }
    url = `${RAW_URL}${match[1].replace('blob/', '')}`;
  } else if (file.startsWith('git')) {
    // Match values
    // [0] entire input
    // [1] git://
    // [2] user
    // [3] repository
    // [4] path
    // [5] branch
    const match = file.match(
      /(git:\/\/)?github\.[a-z]+\/([-a-zA-Z0-9@:%_+.~#?&=]+)\/([-a-zA-Z0-9@:%_+.~#?&=]+)\/([-a-zA-Z0-9@:%_+.~?\/&=]+)#?([a-zA-Z0-9\/_.-]*)?/
    );
    if (!match) {
      console.error(MALFORMED_ERROR + file);
      return null;
    }
    let branch = match[5];
    if (!branch) {
      branch = 'master';
    }
    url = `${RAW_URL}${match[2]}/${match[3]}/${branch}/${match[4]}`;
  } else if (file.startsWith('http')) {
    url = file;
  } else {
    return null;
  }
  const match = url.match(
    /\.[a-z]+\/([-a-zA-Z0-9@:%_+.~#?&\/=]+)/
  );
  return {
    url,
    filePath: constants.httpContractsDirectory + match[1]
  };
}

function hexToNumber(hex) {
  const Web3 = require('web3');
  return Web3.utils.hexToNumber(hex);
}

function isHex(hex) {
  const Web3 = require('web3');
  return Web3.utils.isHex(hex);
}

function hashTo32ByteHexString(hash) {
  if (isHex(hash)) {
    if (!hash.startsWith('0x')) {
      hash = '0x' + hash;
    }
    return hash;
  }
  const multihash = require('multihashes');
  let buf = multihash.fromB58String(hash);
  let digest = multihash.decode(buf).digest;
  return '0x' + multihash.toHexString(digest);
}

function isValidDomain(domain) {
  const isValidDomain = require('is-valid-domain');
  return isValidDomain(domain);
}

function isValidEthDomain(ethDomain) {
  if (!isValidDomain(ethDomain)) {
    return false;
  }
  return ethDomain.substring(ethDomain.lastIndexOf('.'), ethDomain.length) === '.eth';
}

function decodeParams(typesArray, hexString) {
  var Web3EthAbi = require('web3-eth-abi');
  return Web3EthAbi.decodeParameters(typesArray, hexString);
}

function toChecksumAddress(address) {
  const Web3 = require('web3');
  return Web3.utils.toChecksumAddress(address);
}

function sha3(arg) {
  const Web3 = require('web3');
  return Web3.utils.sha3(arg);
}

function soliditySha3(arg) {
  const Web3 = require('web3');
  return Web3.utils.soliditySha3(arg);
}

function normalizeInput(input) {
  let args = Object.values(input);
  if (args.length === 0) {
    return "";
  }
  if (args.length === 1) {
    if (Array.isArray(args[0])) {
      return args[0].join(',');
    }
    return args[0] || "";
  }
  return ('[' + args.map((x) => {
    if (x === null) {
      return "null";
    }
    if (x === undefined) {
      return "undefined";
    }
    if (Array.isArray(x)) {
      return x.join(',');
    }
    return x;
  }).toString() + ']');
}

/**
 * Builds a URL
 *
 * @param {string} protocol
 *  The URL protocol, defaults to http.
 * @param {string} host
 *  The URL host, required.
 * @param {string} port
 *  The URL port, default to empty string.
 * @param {string} [type]
 *  Type of connection
 * @returns {string} the constructued URL, with defaults
 */
function buildUrl(protocol, host, port, type) {
  if (!host) throw new Error('utils.buildUrl: parameter \'host\' is required');
  if (port) port = ':' + port;
  else port = '';
  if (!protocol) {
    protocol = type === 'ws' ? 'ws' : 'http';
  }
  return `${protocol}://${host}${port}`;
}

/**
 * Builds a URL
 *
 * @param {object} configObj Object containing protocol, host, and port to be used to construct the url.
 *      * protocol      {String}    (optional) The URL protocol, defaults to http.
 *      * host          {String}    (required) The URL host.
 *      * port          {String}    (optional) The URL port, default to empty string.
 * @returns {string} the constructued URL, with defaults
 */
function buildUrlFromConfig(configObj) {
  if (!configObj) throw new Error('[utils.buildUrlFromConfig]: config object must cannot be null');
  if (!configObj.host) throw new Error('[utils.buildUrlFromConfig]: object must contain a \'host\' property');
  return this.buildUrl(configObj.protocol, canonicalHost(configObj.host), configObj.port, configObj.type);
}

function deconstructUrl(endpoint) {
  const matches = endpoint.match(/(ws|https?):\/\/([a-zA-Z0-9_.-]*):?([0-9]*)?/);
  return {
    protocol: matches[1],
    host: matches[2],
    port: matches[3],
    type: matches[1] === 'ws' ? 'ws' : 'rpc'
  };
}

function getWeiBalanceFromString(balanceString, web3){
  if(!web3){
    throw new Error(__('[utils.getWeiBalanceFromString]: Missing parameter \'web3\''));
  }
  if (!balanceString) {
    return 0;
  }
  const match = balanceString.match(balanceRegex);
  if (!match) {
    throw new Error(__('Unrecognized balance string "%s"', balanceString));
  }
  if (!match[2]) {
    return web3.utils.toHex(parseInt(match[1], 10));
  }

  return web3.utils.toWei(match[1], match[2]);
}

function getHexBalanceFromString(balanceString, web3) {
  if(!web3){
    throw new Error(__('[utils.getWeiBalanceFromString]: Missing parameter \'web3\''));
  }
  if (!balanceString) {
    return 0xFFFFFFFFFFFFFFFFFF;
  }
  if (web3.utils.isHexStrict(balanceString)) {
    return balanceString;
  }
  const match = balanceString.match(balanceRegex);
  if (!match) {
    throw new Error(__('Unrecognized balance string "%s"', balanceString));
  }
  if (!match[2]) {
    return web3.utils.toHex(parseInt(match[1], 10));
  }

  return web3.utils.toHex(web3.utils.toWei(match[1], match[2]));
}

function compact(array) {
  return array.filter(n => n);
}

function groupBy(array, key) {
  return array.reduce(function (rv, x) {
    (rv[x[key]] = rv[x[key]] || []).push(x);
    return rv;
  }, {});
}

function sample(array) {
  return array[Math.floor(Math.random() * array.length)];
}

function last(array) {
  return array[array.length - 1];
}

function interceptLogs(consoleContext, logger) {
  let context = {};
  context.console = consoleContext;

  context.console.log = function () {
    logger.info(normalizeInput(arguments));
  };
  context.console.warn = function () {
    logger.warn(normalizeInput(arguments));
  };
  context.console.info = function () {
    logger.info(normalizeInput(arguments));
  };
  context.console.debug = function () {
    // TODO: ue JSON.stringify
    logger.debug(normalizeInput(arguments));
  };
  context.console.trace = function () {
    logger.trace(normalizeInput(arguments));
  };
  context.console.dir = function () {
    logger.dir(normalizeInput(arguments));
  };
}

function errorMessage(e) {
  if (typeof e === 'string') {
    return e;
  } else if (e && e.message) {
    return e.message;
  }
  return e;
}

module.exports = {
  joinPath,
  dirname,
  filesMatchingPattern,
  fileMatchesPattern,
  recursiveMerge,
  checkIsAvailable,
  httpGet,
  httpsGet,
  httpGetJson,
  httpsGetJson,
  getJson,
  hexToNumber,
  isHex,
  hashTo32ByteHexString,
  isValidDomain,
  isValidEthDomain,
  pingEndpoint,
  decodeParams,
  runCmd,
  cd,
  sed,
  exit,
  downloadFile,
  extractTar,
  extractZip,
  proposeAlternative,
  getExternalContractUrl,
  toChecksumAddress,
  sha3,
  soliditySha3,
  normalizeInput,
  buildUrl,
  buildUrlFromConfig,
  deconstructUrl,
  getWeiBalanceFromString,
  getHexBalanceFromString,
  compact,
  groupBy,
  sample,
  last,
  interceptLogs,
  errorMessage
};
<|endoftext|>


<commit_before>'use strict';

let angular = require('angular');

module.exports = angular.module('spinnaker.core.deploymentStrategy.custom.customStrategySelectorController', [
    ])
    .controller('CustomStrategySelectorController', function($scope, pipelineConfigService, applicationReader, _) {

        if(!$scope.command.strategyApplication){
            $scope.command.strategyApplication = $scope.command.application;
        }

        $scope.viewState = {
            mastersLoaded: false,
            mastersRefreshing: false,
            mastersLastRefreshed: null,
            pipelinesLoaded : false,
            jobsRefreshing: false,
            jobsLastRefreshed: null,
            infiniteScroll: {
                numToAdd: 20,
                currentItems: 20,
            },
        };

        this.addMoreItems = function() {
            $scope.viewState.infiniteScroll.currentItems += $scope.viewState.infiniteScroll.numToAdd;
        };

        applicationReader.listApplications().then(function(applications) {
            $scope.applications = _.pluck(applications, 'name').sort();
            initializeMasters();
        });

        function initializeMasters() {
            if ($scope.command.application) {
                pipelineConfigService.getStrategiesForApplication($scope.command.application).then(function (pipelines) {
                    $scope.pipelines = pipelines;
                    if (!_.find( pipelines, function(pipeline) { return pipeline.id === $scope.command.strategyPipeline; })) {
                        $scope.command.strategyPipeline = null;
                    }
                    $scope.viewState.pipelinesLoaded = true;
                    updatePipelineConfig();
                });
            }
        }

        function updatePipelineConfig() {
            if ($scope.command && $scope.command.strategyApplication && $scope.command.strategyPipeline) {
                var config = _.find( $scope.pipelines, function(pipeline){ return pipeline.id === $scope.command.strategyPipeline; } );
                if(config && config.parameterConfig) {
                    if (!$scope.command.pipelineParameters) {
                        $scope.command.pipelineParameters = {};
                    }
                    $scope.pipelineParameters = config.parameterConfig;
                    $scope.userSuppliedParameters = $scope.command.pipelineParameters;
                    $scope.useDefaultParameters = {};
                    _.each($scope.pipelineParameters, function (property) {
                        if (!(property.name in $scope.command.pipelineParameters) && (property.default !== null)) {
                            $scope.useDefaultParameters[property.name] = true;
                        }
                    });
                } else {
                    clearParams();
                }
            } else {
                clearParams();
            }
        }

        function clearParams() {
            $scope.pipelineParameters = {};
            $scope.useDefaultParameters = {};
            $scope.userSuppliedParameters = {};
        }

        $scope.useDefaultParameters = {};
        $scope.userSuppliedParameters = {};

        this.updateParam = function(parameter){
            if($scope.useDefaultParameters[parameter] === true){
                delete $scope.userSuppliedParameters[parameter];
                delete $scope.command.parameters[parameter];
            } else if($scope.userSuppliedParameters[parameter]){
                $scope.command.pipelineParameters[parameter] = $scope.userSuppliedParameters[parameter];
            }
        };

        $scope.$watch('command.strategyApplication', initializeMasters);
        $scope.$watch('command.strategyPipeline', updatePipelineConfig);

    });
<commit_msg>fix bug where list of strategies was listing application strategies rather than the one for the application selected<commit_after>'use strict';

let angular = require('angular');

module.exports = angular.module('spinnaker.core.deploymentStrategy.custom.customStrategySelectorController', [
    ])
    .controller('CustomStrategySelectorController', function($scope, pipelineConfigService, applicationReader, _) {

        if(!$scope.command.strategyApplication){
            $scope.command.strategyApplication = $scope.command.application;
        }

        $scope.viewState = {
            mastersLoaded: false,
            mastersRefreshing: false,
            mastersLastRefreshed: null,
            pipelinesLoaded : false,
            jobsRefreshing: false,
            jobsLastRefreshed: null,
            infiniteScroll: {
                numToAdd: 20,
                currentItems: 20,
            },
        };

        this.addMoreItems = function() {
            $scope.viewState.infiniteScroll.currentItems += $scope.viewState.infiniteScroll.numToAdd;
        };

        applicationReader.listApplications().then(function(applications) {
            $scope.applications = _.pluck(applications, 'name').sort();
            initializeMasters();
        });

        function initializeMasters() {
            if ($scope.command.application) {
                pipelineConfigService.getStrategiesForApplication($scope.command.strategyApplication).then(function (pipelines) {
                    $scope.pipelines = pipelines;
                    if (!_.find( pipelines, function(pipeline) { return pipeline.id === $scope.command.strategyPipeline; })) {
                        $scope.command.strategyPipeline = null;
                    }
                    $scope.viewState.pipelinesLoaded = true;
                    updatePipelineConfig();
                });
            }
        }

        function updatePipelineConfig() {
            if ($scope.command && $scope.command.strategyApplication && $scope.command.strategyPipeline) {
                var config = _.find( $scope.pipelines, function(pipeline){ return pipeline.id === $scope.command.strategyPipeline; } );
                if(config && config.parameterConfig) {
                    if (!$scope.command.pipelineParameters) {
                        $scope.command.pipelineParameters = {};
                    }
                    $scope.pipelineParameters = config.parameterConfig;
                    $scope.userSuppliedParameters = $scope.command.pipelineParameters;
                    $scope.useDefaultParameters = {};
                    _.each($scope.pipelineParameters, function (property) {
                        if (!(property.name in $scope.command.pipelineParameters) && (property.default !== null)) {
                            $scope.useDefaultParameters[property.name] = true;
                        }
                    });
                } else {
                    clearParams();
                }
            } else {
                clearParams();
            }
        }

        function clearParams() {
            $scope.pipelineParameters = {};
            $scope.useDefaultParameters = {};
            $scope.userSuppliedParameters = {};
        }

        $scope.useDefaultParameters = {};
        $scope.userSuppliedParameters = {};

        this.updateParam = function(parameter){
            if($scope.useDefaultParameters[parameter] === true){
                delete $scope.userSuppliedParameters[parameter];
                delete $scope.command.parameters[parameter];
            } else if($scope.userSuppliedParameters[parameter]){
                $scope.command.pipelineParameters[parameter] = $scope.userSuppliedParameters[parameter];
            }
        };

        $scope.$watch('command.strategyApplication', initializeMasters);
        $scope.$watch('command.strategyPipeline', updatePipelineConfig);

    });
<|endoftext|>


<commit_before>const cheerio = require("cheerio")
const fs = require("fs")
const axios = require("axios")
const urls = require("./urls")
const folder = require("./folder")
const file = require("./file")
const format = require("./format")
const error = require("./error")
const wait = require("./wait")

class Course {e
  constructor(id, acronym, name) {
    this.id = id
    this.acronym = acronym
    this.name = name
    this.url = urls.courseURL(id)
    this.folders = {}
    this.files = {}
  }

  async scrap() {
    this.folders = {}
    this.files = {}
    await this.scrapFolder(this)
  }

  async scrapFolder(folder, repeat = 0) {
    try {
      const html = (await axios.get(folder.url)).data
      console.log(`Parsing ${folder.name} (r:${repeat})`)
      const newFolders = this.searchFoldersAndFiles(html, folder)
      await newFolders.reduce(async (promise, folder) => {
        await promise
        wait()
        return this.scrapFolder(folder)
      }, Promise.resolve())
    } catch (err) {
      if (err.response.status === 500 && repeat < 5) {
        for (let i = 0; i < repeat; i++) {
          wait()
        }
        return this.scrapFolder(folder, repeat + 1)
      }
      const message = `\n
       name: ${folder.name}
       url: ${folder.url}
       repeat: ${repeat}`
      error(err.message + message, "scrapFolder")
    }
  }

  searchFoldersAndFiles(html, parent) {
    const $ = cheerio.load(html)
    const newFolders = []
    $("a").each((i, l) => {
      const link = $(l).attr("href")
      const name = $(l).text()
      if (link.indexOf("acc_carp") !== -1) {
        const linkId = link.match(/id_carpeta=\d+/g)[0].split("=")[1]
        if (this.folders[linkId]) {
          return
        }
        const newFolder = new folder(
          linkId,
          name,
          urls.courseFolderURL(link),
          parent
        )
        newFolders.push(newFolder)
        this.folders[linkId] = newFolder
      } else if (link.indexOf("id_archivo") !== -1) {
        const linkId = link.match(/id_archivo=\d+/g)[0].split("=")[1]
        if (this.files[linkId]) {
          return
        }
        const newFile = new file(linkId, name, urls.courseFileURL(link), parent)
        this.files[linkId] = newFile
      }
    })
    return newFolders
  }

  path(path = "") {
    const parentPath = (path !== "" && path + "/") || ""
    return parentPath + this.acronym + " " + format.nameCleaned(this.name)
  }

  createFolder(path) {
    try {
      fs.mkdirSync(this.path(path))
    } catch (err) {
      if (err.code === "EEXIST") {
        return // Do nothing
      }
      error(err, "Creating course folder")
    }
  }
}

module.exports = Course
<commit_msg>Fix miss click<commit_after>const cheerio = require("cheerio")
const fs = require("fs")
const axios = require("axios")
const urls = require("./urls")
const folder = require("./folder")
const file = require("./file")
const format = require("./format")
const error = require("./error")
const wait = require("./wait")

class Course {
  constructor(id, acronym, name) {
    this.id = id
    this.acronym = acronym
    this.name = name
    this.url = urls.courseURL(id)
    this.folders = {}
    this.files = {}
  }

  async scrap() {
    this.folders = {}
    this.files = {}
    await this.scrapFolder(this)
  }

  async scrapFolder(folder, repeat = 0) {
    try {
      const html = (await axios.get(folder.url)).data
      console.log(`Parsing ${folder.name} (r:${repeat})`)
      const newFolders = this.searchFoldersAndFiles(html, folder)
      await newFolders.reduce(async (promise, folder) => {
        await promise
        wait()
        return this.scrapFolder(folder)
      }, Promise.resolve())
    } catch (err) {
      if (err.response.status === 500 && repeat < 5) {
        for (let i = 0; i < repeat; i++) {
          wait()
        }
        return this.scrapFolder(folder, repeat + 1)
      }
      const message = `\n
       name: ${folder.name}
       url: ${folder.url}
       repeat: ${repeat}`
      error(err.message + message, "scrapFolder")
    }
  }

  searchFoldersAndFiles(html, parent) {
    const $ = cheerio.load(html)
    const newFolders = []
    $("a").each((i, l) => {
      const link = $(l).attr("href")
      const name = $(l).text()
      if (link.indexOf("acc_carp") !== -1) {
        const linkId = link.match(/id_carpeta=\d+/g)[0].split("=")[1]
        if (this.folders[linkId]) {
          return
        }
        const newFolder = new folder(
          linkId,
          name,
          urls.courseFolderURL(link),
          parent
        )
        newFolders.push(newFolder)
        this.folders[linkId] = newFolder
      } else if (link.indexOf("id_archivo") !== -1) {
        const linkId = link.match(/id_archivo=\d+/g)[0].split("=")[1]
        if (this.files[linkId]) {
          return
        }
        const newFile = new file(linkId, name, urls.courseFileURL(link), parent)
        this.files[linkId] = newFile
      }
    })
    return newFolders
  }

  path(path = "") {
    const parentPath = (path !== "" && path + "/") || ""
    return parentPath + this.acronym + " " + format.nameCleaned(this.name)
  }

  createFolder(path) {
    try {
      fs.mkdirSync(this.path(path))
    } catch (err) {
      if (err.code === "EEXIST") {
        return // Do nothing
      }
      error(err, "Creating course folder")
    }
  }
}

module.exports = Course
<|endoftext|>


<commit_before>//
// パズル固有スクリプト部 ろーま版 roma.js v3.4.0
//
pzpr.createCustoms('roma', {
//---------------------------------------------------------
// マウス入力系
MouseEvent:{
	mouseinput : function(){
		if(this.owner.playmode){
			if(this.mousestart || this.mousemove){
				this.inputarrow_cell();
			}
			else if(this.mouseend && this.notInputted()){
				this.inputqnum();
			}
		}
		else if(this.owner.editmode){
			if(this.mousestart || this.mousemove){
				if(this.isBorderMode()){ this.inputborder();}
				else                   { this.inputarrow_cell();}
			}
			else if(this.mouseend && this.notInputted()){
				this.inputqnum();
			}
		}
	},
	inputRed : function(){ this.dispRoad();},

	dispRoad : function(){
		var cell = this.getcell();
		if(cell.isnull){ return;}

		var ldata = [], bd=this.owner.board;
		for(var c=0;c<bd.cellmax;c++){ ldata[c]=-1;}
		bd.trackBall1(cell.id,ldata);
		for(var c=0;c<bd.cellmax;c++){
			if     (ldata[c]===1){ bd.cell[c].seterr(2);}
			else if(ldata[c]===2){ bd.cell[c].seterr(3);}
		}
		bd.haserror = true;
		this.owner.redraw();
	}
},

//---------------------------------------------------------
// キーボード入力系
KeyEvent:{
	enablemake : true,
	moveTarget : function(ca){
		if(this.isSHIFT){ return false;}
		return this.moveTCell(ca);
	},

	keyinput : function(ca){
		this.key_roma(ca);
	},
	key_roma : function(ca){
		if     (ca==='1'||(this.isSHIFT && ca===this.KEYUP)){ ca='1';}
		else if(ca==='2'||(this.isSHIFT && ca===this.KEYRT)){ ca='4';}
		else if(ca==='3'||(this.isSHIFT && ca===this.KEYDN)){ ca='2';}
		else if(ca==='4'||(this.isSHIFT && ca===this.KEYLT)){ ca='3';}
		else if(ca==='q')                                   { ca='5';}
		else if(this.owner.editmode && (ca==='5'||ca==='-')){ ca='s1';}
		else if(ca==='6'||ca===' ')                         { ca=' ';}
		this.key_inputqnum(ca);
	}
},

//---------------------------------------------------------
// 盤面管理系
Cell:{
	numberAsObject : true,

	nummaxfunc : function(){
		return (this.owner.editmode?5:4);
	}
},
Board:{
	qcols : 8,
	qrows : 8,

	hasborder : 1,

	trackBall1 : function(startcc, ldata){
		var startcell = this.cell[startcc], pos = startcell.getaddr();
		var dir=startcell.getNum(), result=(dir===5);
		ldata[startcell.id]=0;

		while(dir>=1 && dir<=4){
			pos.movedir(dir,2);

			var cell = pos.getc();
			if(cell.isnull){ break;}
			if(ldata[cell.id]!==-1){ result=(ldata[cell.id]===2); break;}

			ldata[cell.id]=0;

			dir=cell.getNum();
			if(dir===5){ result=true;}
		}

		var stack=[startcell];
		while(stack.length>0){
			var cell2=stack.pop();
			if(cell2!==startcell && ldata[cell2.id]!==-1){ continue;}
			ldata[cell2.id]=0;
			var tcell, dir=cell2.getNum();
			tcell=cell2.up(); if( dir!==1 && !tcell.isnull && ldata[tcell.id]===-1 && tcell.getNum()===2 ){ stack.push(tcell);}
			tcell=cell2.dn(); if( dir!==2 && !tcell.isnull && ldata[tcell.id]===-1 && tcell.getNum()===1 ){ stack.push(tcell);}
			tcell=cell2.lt(); if( dir!==3 && !tcell.isnull && ldata[tcell.id]===-1 && tcell.getNum()===4 ){ stack.push(tcell);}
			tcell=cell2.rt(); if( dir!==4 && !tcell.isnull && ldata[tcell.id]===-1 && tcell.getNum()===3 ){ stack.push(tcell);}
		}

		for(var c=0;c<this.cellmax;c++){
			if(ldata[c]===0){ ldata[c] = (result?2:1)}
		}
		return result;
	}
},
BoardExec:{
	adjustBoardData : function(key,d){
		this.adjustCellArrow(key,d);
	}
},

AreaRoomManager:{
	enabled : true
},

//---------------------------------------------------------
// 画像表示系
Graphic:{
	initialize : function(){
		this.Common.prototype.initialize.call(this);

		this.gridcolor = this.gridcolor_LIGHT;
		this.dotcolor = this.dotcolor_PINK;
		this.errbcolor2 = "rgb(255, 224, 192)";
		this.errbcolor3 = "rgb(192, 192, 255)";
	},
	paint : function(){
		this.drawBGCells();
		this.drawGrid();
		this.drawBorders();

		this.drawCellArrows();
		this.drawGoals();
		this.drawHatenas();

		this.drawChassis();

		this.drawCursor();
	},

	getBGCellColor : function(cell){
		if     (cell.error===1){ return this.errbcolor1;}
		else if(cell.error===2){ return this.errbcolor2;}
		else if(cell.error===3){ return this.errbcolor3;}
		return null;
	},

	drawGoals : function(){
		var g = this.vinc('cell_circle', 'auto');

		var rsize = this.cw*this.circleratio[0];
		var header = "c_cir_";
		var clist = this.range.cells;
		for(var i=0;i<clist.length;i++){
			var cell = clist[i];
			if(cell.qnum===5){
				g.fillStyle = (cell.error===1 ? this.errcolor1 : this.cellcolor);
				if(this.vnop(header+cell.id,this.FILL)){
					g.fillCircle((cell.bx*this.bw), (cell.by*this.bh), rsize);
				}
			}
			else{ this.vhide(header+cell.id);}
		}
	}
},

//---------------------------------------------------------
// URLエンコード/デコード処理
Encode:{
	decodePzpr : function(type){
		this.decodeBorder();
		this.decodeNumber10();
	},
	encodePzpr : function(type){
		this.encodeBorder();
		this.encodeNumber10();
	}
},
//---------------------------------------------------------
FileIO:{
	decodeData : function(){
		this.decodeAreaRoom();
		this.decodeCellQnum();
		this.decodeCellAnumsub();
	},
	encodeData : function(){
		this.encodeAreaRoom();
		this.encodeCellQnum();
		this.encodeCellAnumsub();
	}
},

//---------------------------------------------------------
// 正解判定処理実行部
AnsCheck:{
	checkAns : function(){

		if( !this.checkSingleArrowInArea() ){ return 'bkDupNum';}
		if( !this.checkBalls() ){ return 'stopHalfway';}

		return null;
	},

	checkSingleArrowInArea : function(){
		var rinfo = this.owner.board.getRoomInfo();
		return this.checkDifferentNumberInRoom(rinfo, function(cell){ var n=cell.getNum(); return ((n>=1&&n<=4)?n:-1);});
	},

	checkBalls : function(){
		var ldata = [], bd=this.owner.board;
		for(var c=0;c<bd.cellmax;c++){ ldata[c]=(bd.cell[c].getNum()===5?2:-1);}
		for(var c=0;c<bd.cellmax;c++){
			if(ldata[c]!==-1){ continue;}
			if(!bd.trackBall1(c,ldata) && this.checkOnly){ return false;}
		}

		var result = true;
		for(var c=0;c<bd.cellmax;c++){
			if(ldata[c]===1){ bd.cell[c].seterr(1); result=false;}
		}
		return result;
	}
},

FailCode:{
	bkDupNum : ["1つの領域に2つ以上の同じ矢印が入っています。","An area has plural same arrows."],
	stopHalfway : ["ゴールにたどり着かないセルがあります。","A cell cannot reach a goal."]
}
});
<commit_msg>roma: 通る道をチェックした時に矢印が入力されてしまわないようにしました<commit_after>//
// パズル固有スクリプト部 ろーま版 roma.js v3.4.0
//
pzpr.createCustoms('roma', {
//---------------------------------------------------------
// マウス入力系
MouseEvent:{
	mouseinput : function(){
		if(this.owner.playmode){
			if(this.mousestart || this.mousemove){
				this.inputarrow_cell();
			}
			else if(this.mouseend && this.notInputted()){
				this.inputqnum();
			}
		}
		else if(this.owner.editmode){
			if(this.mousestart || this.mousemove){
				if(this.isBorderMode()){ this.inputborder();}
				else                   { this.inputarrow_cell();}
			}
			else if(this.mouseend && this.notInputted()){
				this.inputqnum();
			}
		}
	},
	inputRed : function(){ this.dispRoad();},

	dispRoad : function(){
		var cell = this.getcell();
		if(cell.isnull){ return;}

		var ldata = [], bd=this.owner.board;
		for(var c=0;c<bd.cellmax;c++){ ldata[c]=-1;}
		bd.trackBall1(cell.id,ldata);
		for(var c=0;c<bd.cellmax;c++){
			if     (ldata[c]===1){ bd.cell[c].seterr(2);}
			else if(ldata[c]===2){ bd.cell[c].seterr(3);}
		}
		bd.haserror = true;
		this.owner.redraw();
		this.mousereset();
	}
},

//---------------------------------------------------------
// キーボード入力系
KeyEvent:{
	enablemake : true,
	moveTarget : function(ca){
		if(this.isSHIFT){ return false;}
		return this.moveTCell(ca);
	},

	keyinput : function(ca){
		this.key_roma(ca);
	},
	key_roma : function(ca){
		if     (ca==='1'||(this.isSHIFT && ca===this.KEYUP)){ ca='1';}
		else if(ca==='2'||(this.isSHIFT && ca===this.KEYRT)){ ca='4';}
		else if(ca==='3'||(this.isSHIFT && ca===this.KEYDN)){ ca='2';}
		else if(ca==='4'||(this.isSHIFT && ca===this.KEYLT)){ ca='3';}
		else if(ca==='q')                                   { ca='5';}
		else if(this.owner.editmode && (ca==='5'||ca==='-')){ ca='s1';}
		else if(ca==='6'||ca===' ')                         { ca=' ';}
		this.key_inputqnum(ca);
	}
},

//---------------------------------------------------------
// 盤面管理系
Cell:{
	numberAsObject : true,

	nummaxfunc : function(){
		return (this.owner.editmode?5:4);
	}
},
Board:{
	qcols : 8,
	qrows : 8,

	hasborder : 1,

	trackBall1 : function(startcc, ldata){
		var startcell = this.cell[startcc], pos = startcell.getaddr();
		var dir=startcell.getNum(), result=(dir===5);
		ldata[startcell.id]=0;

		while(dir>=1 && dir<=4){
			pos.movedir(dir,2);

			var cell = pos.getc();
			if(cell.isnull){ break;}
			if(ldata[cell.id]!==-1){ result=(ldata[cell.id]===2); break;}

			ldata[cell.id]=0;

			dir=cell.getNum();
			if(dir===5){ result=true;}
		}

		var stack=[startcell];
		while(stack.length>0){
			var cell2=stack.pop();
			if(cell2!==startcell && ldata[cell2.id]!==-1){ continue;}
			ldata[cell2.id]=0;
			var tcell, dir=cell2.getNum();
			tcell=cell2.up(); if( dir!==1 && !tcell.isnull && ldata[tcell.id]===-1 && tcell.getNum()===2 ){ stack.push(tcell);}
			tcell=cell2.dn(); if( dir!==2 && !tcell.isnull && ldata[tcell.id]===-1 && tcell.getNum()===1 ){ stack.push(tcell);}
			tcell=cell2.lt(); if( dir!==3 && !tcell.isnull && ldata[tcell.id]===-1 && tcell.getNum()===4 ){ stack.push(tcell);}
			tcell=cell2.rt(); if( dir!==4 && !tcell.isnull && ldata[tcell.id]===-1 && tcell.getNum()===3 ){ stack.push(tcell);}
		}

		for(var c=0;c<this.cellmax;c++){
			if(ldata[c]===0){ ldata[c] = (result?2:1)}
		}
		return result;
	}
},
BoardExec:{
	adjustBoardData : function(key,d){
		this.adjustCellArrow(key,d);
	}
},

AreaRoomManager:{
	enabled : true
},

//---------------------------------------------------------
// 画像表示系
Graphic:{
	initialize : function(){
		this.Common.prototype.initialize.call(this);

		this.gridcolor = this.gridcolor_LIGHT;
		this.dotcolor = this.dotcolor_PINK;
		this.errbcolor2 = "rgb(255, 224, 192)";
		this.errbcolor3 = "rgb(192, 192, 255)";
	},
	paint : function(){
		this.drawBGCells();
		this.drawGrid();
		this.drawBorders();

		this.drawCellArrows();
		this.drawGoals();
		this.drawHatenas();

		this.drawChassis();

		this.drawCursor();
	},

	getBGCellColor : function(cell){
		if     (cell.error===1){ return this.errbcolor1;}
		else if(cell.error===2){ return this.errbcolor2;}
		else if(cell.error===3){ return this.errbcolor3;}
		return null;
	},

	drawGoals : function(){
		var g = this.vinc('cell_circle', 'auto');

		var rsize = this.cw*this.circleratio[0];
		var header = "c_cir_";
		var clist = this.range.cells;
		for(var i=0;i<clist.length;i++){
			var cell = clist[i];
			if(cell.qnum===5){
				g.fillStyle = (cell.error===1 ? this.errcolor1 : this.cellcolor);
				if(this.vnop(header+cell.id,this.FILL)){
					g.fillCircle((cell.bx*this.bw), (cell.by*this.bh), rsize);
				}
			}
			else{ this.vhide(header+cell.id);}
		}
	}
},

//---------------------------------------------------------
// URLエンコード/デコード処理
Encode:{
	decodePzpr : function(type){
		this.decodeBorder();
		this.decodeNumber10();
	},
	encodePzpr : function(type){
		this.encodeBorder();
		this.encodeNumber10();
	}
},
//---------------------------------------------------------
FileIO:{
	decodeData : function(){
		this.decodeAreaRoom();
		this.decodeCellQnum();
		this.decodeCellAnumsub();
	},
	encodeData : function(){
		this.encodeAreaRoom();
		this.encodeCellQnum();
		this.encodeCellAnumsub();
	}
},

//---------------------------------------------------------
// 正解判定処理実行部
AnsCheck:{
	checkAns : function(){

		if( !this.checkSingleArrowInArea() ){ return 'bkDupNum';}
		if( !this.checkBalls() ){ return 'stopHalfway';}

		return null;
	},

	checkSingleArrowInArea : function(){
		var rinfo = this.owner.board.getRoomInfo();
		return this.checkDifferentNumberInRoom(rinfo, function(cell){ var n=cell.getNum(); return ((n>=1&&n<=4)?n:-1);});
	},

	checkBalls : function(){
		var ldata = [], bd=this.owner.board;
		for(var c=0;c<bd.cellmax;c++){ ldata[c]=(bd.cell[c].getNum()===5?2:-1);}
		for(var c=0;c<bd.cellmax;c++){
			if(ldata[c]!==-1){ continue;}
			if(!bd.trackBall1(c,ldata) && this.checkOnly){ return false;}
		}

		var result = true;
		for(var c=0;c<bd.cellmax;c++){
			if(ldata[c]===1){ bd.cell[c].seterr(1); result=false;}
		}
		return result;
	}
},

FailCode:{
	bkDupNum : ["1つの領域に2つ以上の同じ矢印が入っています。","An area has plural same arrows."],
	stopHalfway : ["ゴールにたどり着かないセルがあります。","A cell cannot reach a goal."]
}
});
<|endoftext|>


<commit_before>/*jshint maxlen:1000 */
var fs = require('fs'),
    pth = require('path'),
    chalk = require('chalk'),
    _ = require('lodash'),
    buffer = [],
    startTime = Date.now();

function getTypos(data, code) {
    var typos = [];
    data.forEach(function(el) {
        if(el.code !== code) {
            return;
        }

        typos.push(el);
    });

    return typos;
}

function hasManyErrors(data) {
    return data.some(function(el) {
        return el.code === 4; // ERROR_TOO_MANY_ERRORS
    });
}

function makeLink(resource) {
    var res = resource;
    if(resource.search(/^https?:/) === -1) {
        res = 'file://localhost' + (resource.search(/^\//) === -1 ? '/' : '') + resource.replace(/\\/g, '/');
    }

    return '' + _.escape(resource) + '';
}

module.exports = {
    oneach: function(err, data) {
        var html = [];
        if(err) {
            html.push('
' + data + '
');
        } else {
            html.push('
');
            if(hasManyErrors(data.data)) {
                html.push('
Too many errors
');
            }

            [
                {
                    code: 1, // ERROR_UNKNOWN_WORD
                    title: 'Typos'
                }, {
                    code: 2, // ERROR_REPEAT_WORD
                    title: 'Repeat words'
                }, {
                    code: 3, // ERROR_CAPITALIZATION
                    title: 'Capitalization'
                }
            ].forEach(function(el) {
                var typos = getTypos(data.data, el.code);
                if(typos.length) {
                    html.push('

' + el.title + '
');
                    html.push('
Num.	' +
                        'Typo	' +
                        'Count	' +
                        'Suggest	' +
                        'Comment
');
                    typos.forEach(function(el, i) {
                        var comment = [],
                            word = el.word;

                        if(word.search(/[a-z]/i) > -1 && word.search(/[а-яё]/i) > -1) {
                            comment.push('en: ' + _.escape(word.replace(/[а-яё]/gi, '*')) + '');
                            comment.push('ru: ' + _.escape(word.replace(/[a-z]/gi, '*')) + '');
                        }

                        html.push('
');
                        html.push('' + (i + 1) + '.	');
                        html.push('' + _.escape(el.word) + '	');
                        html.push('' + el.count + '	');
                        html.push('' + (el.suggest ? (el.suggest.map(function(w) {
                            return '' + _.escape(w) + '';
                        }).join(', ')) : '') + '	');
                        html.push('' + (comment.length ? comment.join('
') : '') + '	');
                        html.push('
');
                    });

                    html.push('
');
                }
            });

            var time = data.time ? '' + data.time + ' ms' : '';
            if(data.data && data.data.length) {
                html.unshift('
χ' + makeLink(data.resource) + time + '
');
            } else {
                html.unshift('
✓' + makeLink(data.resource) + time + '
');
            }

            html.push('
');
        }

        buffer.push(html.join('\n'));
    },
    onend: function(data) {
        var total = 0,
            err = 0,
            ok = 0;

        data.forEach(function(el) {
            total++;
            if(el[0] || (!el[0] && el[1].data && el[1].data.length)) {
                err++;
            } else {
                ok++;
            }
        });

        var template = fs.readFileSync(pth.join(__dirname, 'template.html')).toString(),
            filename = 'yaspeller_report.html',
            html = '
Processed resources: ' + total +
                ' (χ– ' + err +
                ', ✓– ' + ok + ')
' +
                'Checking finished: ' + ((+new Date() - startTime) / 1000) + ' sec.
' +
                buffer.join('');

        try {
            fs.writeFileSync(filename, template.replace(/\{\{content\}\}/, html));
            console.log(chalk.cyan('HTML report: ./' + filename));
        } catch(e) {
            console.error(e);
        }
    }
};
<commit_msg>CI: short links in html report<commit_after>/*jshint maxlen:1000 */
var fs = require('fs'),
    pth = require('path'),
    chalk = require('chalk'),
    _ = require('lodash'),
    buffer = [],
    startTime = Date.now();

function getTypos(data, code) {
    var typos = [];
    data.forEach(function(el) {
        if(el.code !== code) {
            return;
        }

        typos.push(el);
    });

    return typos;
}

function hasManyErrors(data) {
    return data.some(function(el) {
        return el.code === 4; // ERROR_TOO_MANY_ERRORS
    });
}

function makeLink(resource) {
    var href = resource,
        relativeFile = resource;
    if(resource.search(/^https?:/) === -1) {
        relativeFile = pth.relative('.', resource);
        // CI: short links
        if(relativeFile.indexOf('..') !== -1) {
            relativeFile = resource;
        }

        href = fileUrl(href);
    }

    return '' +
            _.escape(relativeFile) + '';
}

function fileUrl(file) {
    return 'file://localhost' +
        (file.search(/^\//) === -1 ? '/' : '') +
        file.replace(/\\/g, '/');
}

module.exports = {
    oneach: function(err, data) {
        var html = [];
        if(err) {
            html.push('
' + data + '
');
        } else {
            html.push('
');
            if(hasManyErrors(data.data)) {
                html.push('
Too many errors
');
            }

            [
                {
                    code: 1, // ERROR_UNKNOWN_WORD
                    title: 'Typos'
                }, {
                    code: 2, // ERROR_REPEAT_WORD
                    title: 'Repeat words'
                }, {
                    code: 3, // ERROR_CAPITALIZATION
                    title: 'Capitalization'
                }
            ].forEach(function(el) {
                var typos = getTypos(data.data, el.code);
                if(typos.length) {
                    html.push('

' + el.title + '
');
                    html.push('
Num.	' +
                        'Typo	' +
                        'Count	' +
                        'Suggest	' +
                        'Comment
');
                    typos.forEach(function(el, i) {
                        var comment = [],
                            word = el.word;

                        if(word.search(/[a-z]/i) > -1 && word.search(/[а-яё]/i) > -1) {
                            comment.push('en: ' + _.escape(word.replace(/[а-яё]/gi, '*')) + '');
                            comment.push('ru: ' + _.escape(word.replace(/[a-z]/gi, '*')) + '');
                        }

                        html.push('
');
                        html.push('' + (i + 1) + '.	');
                        html.push('' + _.escape(el.word) + '	');
                        html.push('' + el.count + '	');
                        html.push('' + (el.suggest ? (el.suggest.map(function(w) {
                            return '' + _.escape(w) + '';
                        }).join(', ')) : '') + '	');
                        html.push('' + (comment.length ? comment.join('
') : '') + '	');
                        html.push('
');
                    });

                    html.push('
');
                }
            });

            var time = data.time ? '' + data.time + ' ms' : '';
            if(data.data && data.data.length) {
                html.unshift('
χ' + makeLink(data.resource) + time + '
');
            } else {
                html.unshift('
✓' + makeLink(data.resource) + time + '
');
            }

            html.push('
');
        }

        buffer.push(html.join('\n'));
    },
    onend: function(data) {
        var total = 0,
            err = 0,
            ok = 0;

        data.forEach(function(el) {
            total++;
            if(el[0] || (!el[0] && el[1].data && el[1].data.length)) {
                err++;
            } else {
                ok++;
            }
        });

        var template = fs.readFileSync(pth.join(__dirname, 'template.html')).toString(),
            filename = 'yaspeller_report.html',
            html = '
Processed resources: ' + total +
                ' (χ– ' + err +
                ', ✓– ' + ok + ')
' +
                'Checking finished: ' + ((+new Date() - startTime) / 1000) + ' sec.
' +
                buffer.join('');

        try {
            fs.writeFileSync(filename, template.replace(/\{\{content\}\}/, html));
            console.log(chalk.cyan('HTML report: ./' + filename));
        } catch(e) {
            console.error(e);
        }
    }
};
<|endoftext|>


<commit_before>module.exports = function (router, bodyParser) {
    var fs = require('fs');
    var path= require('path');
    var jsonParser = bodyParser.json();

    fs.readdir(__dirname + '/../model/', function (err, files) {
        if(err) {
           console.error(err);
           return;
        }else {
          var Task = new Array();
          files.forEach(function (file) {
             var filePath = path.normalize(__dirname + '/../model/' + file);
             // console.log('The file is: ' , file);
             fs.stat(filePath, function (err, stat) {
                if(stat.isFile()) {
                   var apipath = file.substr(0,file.length-5);
                   router.route('/'+apipath+'/').get(function (req, res) {
                     var Task = require.main.require("./lib/task.js");
                     var modelpro = JSON.parse(fs.readFileSync(__dirname + '/../model/' + file,'utf-8'));
                     var params = new Array();
                     var j=0;
                     for (var key in modelpro) {
                        params[j]=key;
                        j ++;
                     }
                     Task.getAll(apipath,params,function (err, results) {
                       if (!err) res.send(results);
                       else res.send({"error": "select tasks list failed with error code: "+err.code});
                     });
                   }).post(jsonParser, function (req, res) {
                     if (!req.body) return res.sendStatus(400);
                     var Task = require.main.require("./lib/task.js");
                     Task.create(req.body.name, req.body.is_done, function (err, results) {
                       if (!err) res.send(results);
                       else res.send({"error": "create task failed with error code: "+err.code});
                     });
                   });

                   router.route('/'+apipath+'/:task_id').get(function (req, res) {
                     var Task = require.main.require("./lib/task.js");
                     Task.getById(req.params.task_id, apipath,function (err, results) {
                       if (!err) res.send(results);
                       else res.send({"error": "select task failed with error code: "+err.code});
                     });
                   }).put(jsonParser, function (req, res) {
                     if (!req.body) return res.sendStatus(400);
                     var params = {};
                     if (req.body.name) params.name = req.body.name;
                     if (req.body.is_done) params.is_done = req.body.is_done;
                     var Task = require.main.require("./lib/task.js");
                     Task.update(req.params.task_id, params, function (err, results) {
                       if (!err) res.send(results);
                       else res.send({"error": "Update task failed with error code: "+err.code});
                     });
                   }).delete(function (req, res) {
                     var Task = require.main.require("./lib/task.js");
                     Task.remove(req.params.task_id, function (err, results) {
                     if (!err)
                        res.send(results);
                     else
                        res.send({"error": "delete task failed with error code: "+err.code});
                     });
                   });
                }
                if(stat.isDirectory()) {
                   console.log(filePath + ' is: ' + 'dir');
                }

             });
          });

        }
    });

};
<commit_msg>Update tasklist.js<commit_after>module.exports = function (router, bodyParser) {
    var fs = require('fs');
    var path= require('path');
    var jsonParser = bodyParser.json();

    fs.readdir(__dirname + '/../model/', function (err, files) {
        if(err) {
           console.error(err);
           return;
        }else {
          files.forEach(function (file) {
            var filePath = path.normalize(__dirname + '/../model/' + file);
             // console.log('The file is: ' , file);
            fs.stat(filePath, function (err, stat) {
                if(stat.isDirectory()) {
                   fs.readdir(filePath, function (err, files2) {
                     files2.forEach(function (file2) {
                        var apipath = file2.substr(0,file2.length-5);
                        router.route('/'+file+'/'+apipath+'/').get(function (req, res) {
                          var Task = require.main.require("./lib/task.js");
                          var modelpro = JSON.parse(fs.readFileSync(filePath +'/'+file2,'utf-8'));
                          var params = new Array();
                          var j=0;
                          for (var key in modelpro) {
                             params[j]=key;
                             j ++;
                          }
                          Task.getAll(file,apipath,params,function (err, results) {
                            if (!err) res.send(results);
                            else res.send({"error": "select tasks list failed with error code: "+err.code});
                          });
                        }).post(jsonParser, function (req, res) {
                          if (!req.body) return res.sendStatus(400);
                          var Task = require.main.require("./lib/task.js");
                          Task.create(req.body.name, req.body.is_done, function (err, results) {
                            if (!err) res.send(results);
                            else res.send({"error": "create task failed with error code: "+err.code});
                          });

                        });

                        router.route('/'+apipath+'/:task_id').get(function (req, res) {
                          var Task = require.main.require("./lib/task.js");
                          Task.getById(req.params.task_id, apipath,function (err, results) {
                             if (!err) res.send(results);
                             else res.send({"error": "select task failed with error code: "+err.code});
                          });
                        }).put(jsonParser, function (req, res) {
                           if (!req.body) return res.sendStatus(400);
                           var params = {};
                           if (req.body.name) params.name = req.body.name;
                           if (req.body.is_done) params.is_done = req.body.is_done;
                           var Task = require.main.require("./lib/task.js");
                           Task.update(req.params.task_id, params, function (err, results) {
                              if (!err) res.send(results);
                              else res.send({"error": "Update task failed with error code: "+err.code});
                            });
                        }).delete(function (req, res) {
                           var Task = require.main.require("./lib/task.js");
                           Task.remove(req.params.task_id, function (err, results) {
                              if (!err) res.send(results);
                              else res.send({"error": "delete task failed with error code: "+err.code});
                           });
                        });
                      });
                    });

                }

             });
          });

        }
    });

};
<|endoftext|>


<commit_before>// -------------------------
// Fetch data from cartodb
// -------------------------

// general function to fetch data given a url
function fetchTrackingData(url) {
    var result = jQuery.get(url, function(data) {
        jQuery('.result').html(data);
    });
    return result;
}

// function to fetch all birds in the bird_tracking_devices table
function fetchBirdData() {
    query = "SELECT bird_name, device_info_serial, sex, scientific_name from bird_tracking_devices";
    var url = "https://lifewatch-inbo.cartodb.com/api/v2/sql?q=" + query;
    return fetchTrackingData(url);
}

// -------------------------
// Add data to DOM
// -------------------------

// -------------------------
// app function will contain
// all functionality for the
// app
// -------------------------
var app = function() {
    var birds_call = fetchBirdData();
    var birds = [];
    birds_call.done(function(data) {
        birds = _.sortBy(data.rows, function(bird) {return bird.scientific_name + bird.bird_name});
        addBirdsToSelect()
    })

    function addBirdsToSelect() {
        // create optgroups per species
        all_species = _.map(birds, function(bird){ return bird.scientific_name });
        species = _.uniq(all_species, true);
        opt_groups = {};
        _.each(species, function(spec_name){ opt_groups[spec_name] = "<optgroup label=\"" + spec_name +"\">"});

        // append bird names to the correct optgroups
        for (var i=0;i<birds.length;i++) {
            opt = "<option value\"" + i + "\">" + birds[i].bird_name + "</option>";
            opt_groups[birds[i].scientific_name] += opt;
        }

        // create one html text with all the optgroups and their options
        optgrp_html = "";
        _.each(opt_groups, function(optgrp, spec_name){ optgrp_html += optgrp + "</optgroup>"});

        // append the optgroups html to the select-bird element
        $("#select-bird").append(optgrp_html);
    }
}();
<commit_msg>Remove DOM comment<commit_after>// -------------------------
// Fetch data from cartodb
// -------------------------

// general function to fetch data given a url
function fetchTrackingData(url) {
    var result = jQuery.get(url, function(data) {
        jQuery('.result').html(data);
    });
    return result;
}

// function to fetch all birds in the bird_tracking_devices table
function fetchBirdData() {
    query = "SELECT bird_name, device_info_serial, sex, scientific_name from bird_tracking_devices";
    var url = "https://lifewatch-inbo.cartodb.com/api/v2/sql?q=" + query;
    return fetchTrackingData(url);
}

// -------------------------
// app function will contain
// all functionality for the
// app
// -------------------------
var app = function() {
    var birds_call = fetchBirdData();
    var birds = [];
    birds_call.done(function(data) {
        birds = _.sortBy(data.rows, function(bird) {return bird.scientific_name + bird.bird_name});
        addBirdsToSelect()
    })

    function addBirdsToSelect() {
        // create optgroups per species
        all_species = _.map(birds, function(bird){ return bird.scientific_name });
        species = _.uniq(all_species, true);
        opt_groups = {};
        _.each(species, function(spec_name){ opt_groups[spec_name] = "<optgroup label=\"" + spec_name +"\">"});

        // append bird names to the correct optgroups
        for (var i=0;i<birds.length;i++) {
            opt = "<option value\"" + i + "\">" + birds[i].bird_name + "</option>";
            opt_groups[birds[i].scientific_name] += opt;
        }

        // create one html text with all the optgroups and their options
        optgrp_html = "";
        _.each(opt_groups, function(optgrp, spec_name){ optgrp_html += optgrp + "</optgroup>"});

        // append the optgroups html to the select-bird element
        $("#select-bird").append(optgrp_html);
    }
}();
<|endoftext|>


<commit_before>exports.Validatable = Validatable;

function Validatable() {
    // validatable class
};

Validatable.validatesPresenceOf = getConfigurator('presence');
Validatable.validatesLengthOf = getConfigurator('length');
Validatable.validatesNumericalityOf = getConfigurator('numericality');
Validatable.validatesInclusionOf = getConfigurator('inclusion');
Validatable.validatesExclusionOf = getConfigurator('exclusion');
Validatable.validatesFormatOf = getConfigurator('format');
Validatable.validate = getConfigurator('custom');
Validatable.validateAsync = getConfigurator('custom', {async: true});
Validatable.validatesUniquenessOf = getConfigurator('uniqueness', {async: true});

// implementation of validators
var validators = {
    presence: function (attr, conf, err) {
        if (blank(this[attr])) {
            err();
        }
    },
    length: function (attr, conf, err) {
        if (nullCheck.call(this, attr, conf, err)) return;

        var len = this[attr].length;
        if (conf.min && len < conf.min) {
            err('min');
        }
        if (conf.max && len > conf.max) {
            err('max');
        }
        if (conf.is && len !== conf.is) {
            err('is');
        }
    },
    numericality: function (attr, conf, err) {
        if (nullCheck.call(this, attr, conf, err)) return;

        if (typeof this[attr] !== 'number') {
            return err('number');
        }
        if (conf.int && this[attr] !== Math.round(this[attr])) {
            return err('int');
        }
    },
    inclusion: function (attr, conf, err) {
        if (nullCheck.call(this, attr, conf, err)) return;

        if (!~conf.in.indexOf(this[attr])) {
            err()
        }
    },
    exclusion: function (attr, conf, err) {
        if (nullCheck.call(this, attr, conf, err)) return;

        if (~conf.in.indexOf(this[attr])) {
            err()
        }
    },
    format: function (attr, conf, err) {
        if (nullCheck.call(this, attr, conf, err)) return;

        if (typeof this[attr] === 'string') {
            if (!this[attr].match(conf['with'])) {
                err();
            }
        } else {
            err();
        }
    },
    custom: function (attr, conf, err, done) {
        conf.customValidator.call(this, err, done);
    },
    uniqueness: function (attr, conf, err, done) {
        var cond = {where: {}};
        cond.where[attr] = this[attr];
        this.constructor.all(cond, function (error, found) {
            if (found.length > 1) {
                err();
            } else if (found.length === 1 && found[0].id !== this.id) {
                err();
            }
            done();
        }.bind(this));
    }
};

function getConfigurator(name, opts) {
    return function () {
        configure(this, name, arguments, opts);
    };
}

Validatable.prototype.isValid = function (callback) {
    var valid = true, inst = this, wait = 0, async = false;

    // exit with success when no errors
    if (!this.constructor._validations) {
        cleanErrors(this);
        if (callback) {
            callback(valid);
        }
        return valid;
    }

    Object.defineProperty(this, 'errors', {
        enumerable: false,
        configurable: true,
        value: new Errors
    });

    this.trigger('validation', function (validationsDone) {
        var inst = this;
        this.constructor._validations.forEach(function (v) {
            if (v[2] && v[2].async) {
                valid = false;
                async = true;
                wait += 1;
                validationFailed(inst, v, done);
            } else {
                if (validationFailed(inst, v)) {
                    valid = false;
                }
            }

        });

        var asyncFail = false;
        function done(fail) {
            asyncFail = asyncFail || fail;
            if (--wait === 0 && callback) {
                validationsDone.call(inst, function () {
                    callback(!asyncFail);
                });
            }
        }

    });

    if (valid) cleanErrors(this);
    if (!async && callback) callback(valid);

    return valid;
};

function cleanErrors(inst) {
    Object.defineProperty(inst, 'errors', {
        enumerable: false,
        configurable: true,
        value: false
    });
}

function validationFailed(inst, v, cb) {
    var attr = v[0];
    var conf = v[1];
    var opts = v[2] || {};

    if (typeof attr !== 'string') return false;

    // here we should check skip validation conditions (if, unless)
    // that can be specified in conf
    if (skipValidation(inst, conf, 'if')) return false;
    if (skipValidation(inst, conf, 'unless')) return false;

    var fail = false;
    var validator = validators[conf.validation];
    var validatorArguments = [];
    validatorArguments.push(attr);
    validatorArguments.push(conf);
    validatorArguments.push(function onerror(kind) {
        var message;
        if (conf.message) {
            message = conf.message;
        }
        if (!message && defaultMessages[conf.validation]) {
            message = defaultMessages[conf.validation];
        }
        if (!message) {
            message = 'is invalid';
        }
        if (kind) {
            if (message[kind]) {
                // get deeper
                message = message[kind];
            } else if (defaultMessages.common[kind]) {
                message = defaultMessages.common[kind];
            }
        }
        inst.errors.add(attr, message);
        fail = true;
    });
    if (cb) {
        validatorArguments.push(function () {
            cb(fail);
        });
    }
    validator.apply(inst, validatorArguments);
    return fail;
}

function skipValidation(inst, conf, kind) {
    var doValidate = true;
    if (typeof conf[kind] === 'function') {
        doValidate = conf[kind].call(inst);
        if (kind === 'unless') doValidate = !doValidate;
    } else if (typeof conf[kind] === 'string') {
        if (inst.hasOwnProperty(conf[kind])) {
            doValidate = inst[conf[kind]];
            if (kind === 'unless') doValidate = !doValidate;
        } else if (typeof inst[conf[kind]] === 'function') {
            doValidate = inst[conf[kind]].call(inst);
            if (kind === 'unless') doValidate = !doValidate;
        } else {
            doValidate = kind === 'if';
        }
    }
    return !doValidate;
}

var defaultMessages = {
    presence: 'can\'t be blank',
    length: {
        min: 'too short',
        max: 'too long',
        is: 'length is wrong'
    },
    common: {
        blank: 'is blank',
        'null': 'is null'
    },
    numericality: {
        'int': 'is not an integer',
        'number': 'is not a number'
    },
    inclusion: 'is not included in the list',
    exclusion: 'is reserved',
    uniqueness: 'is not unique'
};

function nullCheck(attr, conf, err) {
    var isNull = this[attr] === null || !(attr in this);
    if (isNull) {
        if (!conf.allowNull) {
            err('null');
        }
        return true;
    } else {
        if (blank(this[attr])) {
            if (!conf.allowBlank) {
                err('blank');
            }
            return true;
        }
    }
    return false;
}

function blank(v) {
    if (typeof v === 'undefined') return true;
    if (v instanceof Array && v.length === 0) return true;
    if (v === null) return true;
    if (typeof v == 'string' && v === '') return true;
    return false;
}

function configure(cls, validation, args, opts) {
    if (!cls._validations) {
        Object.defineProperty(cls, '_validations', {
            writable: true,
            configurable: true,
            enumerable: false,
            value: []
        });
    }
    args = [].slice.call(args);
    var conf;
    if (typeof args[args.length - 1] === 'object') {
        conf = args.pop();
    } else {
        conf = {};
    }
    if (validation === 'custom' && typeof args[args.length - 1] === 'function') {
        conf.customValidator = args.pop();
    }
    conf.validation = validation;
    args.forEach(function (attr) {
        cls._validations.push([attr, conf, opts]);
    });
}

function Errors() {
}

Errors.prototype.add = function (field, message) {
    if (!this[field]) {
        this[field] = [message];
    } else {
        this[field].push(message);
    }
};

<commit_msg>Async validations should not trump previous validations. Previous validations should be true as well as async validations<commit_after>exports.Validatable = Validatable;

function Validatable() {
    // validatable class
};

Validatable.validatesPresenceOf = getConfigurator('presence');
Validatable.validatesLengthOf = getConfigurator('length');
Validatable.validatesNumericalityOf = getConfigurator('numericality');
Validatable.validatesInclusionOf = getConfigurator('inclusion');
Validatable.validatesExclusionOf = getConfigurator('exclusion');
Validatable.validatesFormatOf = getConfigurator('format');
Validatable.validate = getConfigurator('custom');
Validatable.validateAsync = getConfigurator('custom', {async: true});
Validatable.validatesUniquenessOf = getConfigurator('uniqueness', {async: true});

// implementation of validators
var validators = {
    presence: function (attr, conf, err) {
        if (blank(this[attr])) {
            err();
        }
    },
    length: function (attr, conf, err) {
        if (nullCheck.call(this, attr, conf, err)) return;

        var len = this[attr].length;
        if (conf.min && len < conf.min) {
            err('min');
        }
        if (conf.max && len > conf.max) {
            err('max');
        }
        if (conf.is && len !== conf.is) {
            err('is');
        }
    },
    numericality: function (attr, conf, err) {
        if (nullCheck.call(this, attr, conf, err)) return;

        if (typeof this[attr] !== 'number') {
            return err('number');
        }
        if (conf.int && this[attr] !== Math.round(this[attr])) {
            return err('int');
        }
    },
    inclusion: function (attr, conf, err) {
        if (nullCheck.call(this, attr, conf, err)) return;

        if (!~conf.in.indexOf(this[attr])) {
            err()
        }
    },
    exclusion: function (attr, conf, err) {
        if (nullCheck.call(this, attr, conf, err)) return;

        if (~conf.in.indexOf(this[attr])) {
            err()
        }
    },
    format: function (attr, conf, err) {
        if (nullCheck.call(this, attr, conf, err)) return;

        if (typeof this[attr] === 'string') {
            if (!this[attr].match(conf['with'])) {
                err();
            }
        } else {
            err();
        }
    },
    custom: function (attr, conf, err, done) {
        conf.customValidator.call(this, err, done);
    },
    uniqueness: function (attr, conf, err, done) {
        var cond = {where: {}};
        cond.where[attr] = this[attr];
        this.constructor.all(cond, function (error, found) {
            if (found.length > 1) {
                err();
            } else if (found.length === 1 && found[0].id !== this.id) {
                err();
            }
            done();
        }.bind(this));
    }
};

function getConfigurator(name, opts) {
    return function () {
        configure(this, name, arguments, opts);
    };
}

Validatable.prototype.isValid = function (callback) {
    var valid = true, inst = this, wait = 0, async = false;

    // exit with success when no errors
    if (!this.constructor._validations) {
        cleanErrors(this);
        if (callback) {
            callback(valid);
        }
        return valid;
    }

    Object.defineProperty(this, 'errors', {
        enumerable: false,
        configurable: true,
        value: new Errors
    });

    this.trigger('validation', function (validationsDone) {
        var inst = this;
        this.constructor._validations.forEach(function (v) {
            if (v[2] && v[2].async) {
                valid = false;
                async = true;
                wait += 1;
                validationFailed(inst, v, done);
            } else {
                if (validationFailed(inst, v)) {
                    valid = false;
                }
            }

        });

        var asyncFail = false;
        function done(fail) {
            asyncFail = asyncFail || fail;
            if (--wait === 0 && callback) {
                validationsDone.call(inst, function () {
                    callback(valid && !asyncFail);
                });
            }
        }

    });

    if (valid) cleanErrors(this);
    if (!async && callback) callback(valid);

    return valid;
};

function cleanErrors(inst) {
    Object.defineProperty(inst, 'errors', {
        enumerable: false,
        configurable: true,
        value: false
    });
}

function validationFailed(inst, v, cb) {
    var attr = v[0];
    var conf = v[1];
    var opts = v[2] || {};

    if (typeof attr !== 'string') return false;

    // here we should check skip validation conditions (if, unless)
    // that can be specified in conf
    if (skipValidation(inst, conf, 'if')) return false;
    if (skipValidation(inst, conf, 'unless')) return false;

    var fail = false;
    var validator = validators[conf.validation];
    var validatorArguments = [];
    validatorArguments.push(attr);
    validatorArguments.push(conf);
    validatorArguments.push(function onerror(kind) {
        var message;
        if (conf.message) {
            message = conf.message;
        }
        if (!message && defaultMessages[conf.validation]) {
            message = defaultMessages[conf.validation];
        }
        if (!message) {
            message = 'is invalid';
        }
        if (kind) {
            if (message[kind]) {
                // get deeper
                message = message[kind];
            } else if (defaultMessages.common[kind]) {
                message = defaultMessages.common[kind];
            }
        }
        inst.errors.add(attr, message);
        fail = true;
    });
    if (cb) {
        validatorArguments.push(function () {
            cb(fail);
        });
    }
    validator.apply(inst, validatorArguments);
    return fail;
}

function skipValidation(inst, conf, kind) {
    var doValidate = true;
    if (typeof conf[kind] === 'function') {
        doValidate = conf[kind].call(inst);
        if (kind === 'unless') doValidate = !doValidate;
    } else if (typeof conf[kind] === 'string') {
        if (inst.hasOwnProperty(conf[kind])) {
            doValidate = inst[conf[kind]];
            if (kind === 'unless') doValidate = !doValidate;
        } else if (typeof inst[conf[kind]] === 'function') {
            doValidate = inst[conf[kind]].call(inst);
            if (kind === 'unless') doValidate = !doValidate;
        } else {
            doValidate = kind === 'if';
        }
    }
    return !doValidate;
}

var defaultMessages = {
    presence: 'can\'t be blank',
    length: {
        min: 'too short',
        max: 'too long',
        is: 'length is wrong'
    },
    common: {
        blank: 'is blank',
        'null': 'is null'
    },
    numericality: {
        'int': 'is not an integer',
        'number': 'is not a number'
    },
    inclusion: 'is not included in the list',
    exclusion: 'is reserved',
    uniqueness: 'is not unique'
};

function nullCheck(attr, conf, err) {
    var isNull = this[attr] === null || !(attr in this);
    if (isNull) {
        if (!conf.allowNull) {
            err('null');
        }
        return true;
    } else {
        if (blank(this[attr])) {
            if (!conf.allowBlank) {
                err('blank');
            }
            return true;
        }
    }
    return false;
}

function blank(v) {
    if (typeof v === 'undefined') return true;
    if (v instanceof Array && v.length === 0) return true;
    if (v === null) return true;
    if (typeof v == 'string' && v === '') return true;
    return false;
}

function configure(cls, validation, args, opts) {
    if (!cls._validations) {
        Object.defineProperty(cls, '_validations', {
            writable: true,
            configurable: true,
            enumerable: false,
            value: []
        });
    }
    args = [].slice.call(args);
    var conf;
    if (typeof args[args.length - 1] === 'object') {
        conf = args.pop();
    } else {
        conf = {};
    }
    if (validation === 'custom' && typeof args[args.length - 1] === 'function') {
        conf.customValidator = args.pop();
    }
    conf.validation = validation;
    args.forEach(function (attr) {
        cls._validations.push([attr, conf, opts]);
    });
}

function Errors() {
}

Errors.prototype.add = function (field, message) {
    if (!this[field]) {
        this[field] = [message];
    } else {
        this[field].push(message);
    }
};

<|endoftext|>


<commit_before>/* jslint node: true */
/* global before, afterEach, after, featureFile, scenarios, steps */
"use strict";
var path = require('path');
var Yadda = require('yadda');
Yadda.plugins.mocha.AsyncStepLevelPlugin.init();

//creating a path that works for locations, Yaddas calls is not as good as node's require and you need
//to be in the folder itself
var featureFilePath = path.resolve(__dirname, '../features/AddPlayer.feature');
featureFile(featureFilePath, function(feature) {

    var library = require('./AddPlayer');
    var yadda = new Yadda.Yadda(library);

    before(function(done) {
        done();
    });

    scenarios(feature.scenarios, function(scenario) {
        var scenario_context = { teamname: null, year: null, dob: null, firstname: null, surname: null, address: null, suburb: null, postcode: null, email: null, Error: null };
        steps(scenario.steps, function(step, done) {

            yadda.yadda(step, { ctx: scenario_context }, done);

        });
    });

    after(function(done) {
        // ensure a clean environment
        // clear down the players storage using our API.  Let's try this out but I'm not feeling that great about this.
        // But we are enacting the principle: Simplicity -- the art of maximising the work not done
        // we should be in a state of preparedness to make the refactoring if and when needed
        // maybe a feature request for Yadda here.  Maybe we pull down the Yadda code and submit a code change ourselves!
console.log('Processing after');
        var Pms = require('../../lib/PlayerManagementService'); // The library that you wish to test
        var pms = new Pms();
	    pms.Open(null, null);
        // Question: Do we really want such an API!!!
        pms.DeletePlayers(function(err) {
            if (err)
                console.log('Error in deleting %s', err);
            done();
        });
    });
});
<commit_msg>Testing the build<commit_after>/* jslint node: true */
/* global before, afterEach, after, featureFile, scenarios, steps */
"use strict";
var path = require('path');
var Yadda = require('yadda');
Yadda.plugins.mocha.AsyncStepLevelPlugin.init();

//creating a path that works for locations, Yaddas calls is not as good as node's require and you need
//to be in the folder itself
var featureFilePath = path.resolve(__dirname, '../features/AddPlayer.feature');
featureFile(featureFilePath, function(feature) {

    var library = require('./AddPlayer');
    var yadda = new Yadda.Yadda(library);

    before(function(done) {
        done();
    });

    scenarios(feature.scenarios, function(scenario) {
        var scenario_context = { teamname: null, year: null, dob: null, firstname: null, surname: null, address: null, suburb: null, postcode: null, email: null, Error: null };
        steps(scenario.steps, function(step, done) {

            yadda.yadda(step, { ctx: scenario_context }, done);

        });
    });

    after(function(done) {
        // ensure a clean environment
        // clear down the players storage using our API.  Let's try this out but I'm not feeling that great about this.
        // But we are enacting the principle: Simplicity -- the art of maximising the work not done
        // we should be in a state of preparedness to make the refactoring if and when needed
        // maybe a feature request for Yadda here.  Maybe we pull down the Yadda code and submit a code change ourselves!
console.log('Processing after');
        var Pms = require('../../lib/PlayerManagementService'); // The library that you wish to test
        var pms = new Pms();
	    pms.Open(null, null);
        // Question: Do we really want such an API!!!
        pms.DeletePlayers(function(err) {
            if (err)
                console.log('Error in deleting %s', err);

                console.log('Processing done');
            done();
        });
    });
});
<|endoftext|>


<commit_before>var spawn = require('child_process').spawn;
var logger = require('../lib/logger');

/**
 * Normalizes arguments for csscss. It will for examle remove backlisted
 * arguments.
 */
function normalizeArguments(argv) {
  var blacklist = ['browser', 'port', '_'];
  var args = Object.keys(argv)
    .map(function getPairs(key) {
      if (blacklist.indexOf(key) !== -1) {
        return [key, null];
      }
      return [key, argv[key]];
    })
    .filter(function filterFalsy(pair) {
      return pair[1];
    })
    .map(function toArgument(pair) {
      if (typeof pair[1] === 'boolean') {
        return '--' + pair[0];
      }
      return '--' + pair[0] + '=' + pair[1];
    });

  return args;
}

/**
 * Executes csscss and returns the result as json.
 */
function executeCSSCSS(files, options, cb) {
  var stdout = '';
  var args = files.concat(normalizeArguments(options));
  var programm = process.platform === 'win32' ? 'csscss.bat' : 'csscss';
  // allways require json format
  args.push('--json');

  if (!files || files.length === 0) {
    cb(null, []);
    return;
  }

  spawn(programm, args)
    .stdout.on('data', function onData(data) {
      stdout += data;
    })
    .on('close', function onClose() {
      cb(null, stdout ? JSON.parse(stdout) : []);
    })
    .on('error', cb);
}

module.exports = {
  execute: executeCSSCSS,
};
<commit_msg>Remove unnused module import<commit_after>var spawn = require('child_process').spawn;

/**
 * Normalizes arguments for csscss. It will for examle remove backlisted
 * arguments.
 */
function normalizeArguments(argv) {
  var blacklist = ['browser', 'port', '_'];
  var args = Object.keys(argv)
    .map(function getPairs(key) {
      if (blacklist.indexOf(key) !== -1) {
        return [key, null];
      }
      return [key, argv[key]];
    })
    .filter(function filterFalsy(pair) {
      return pair[1];
    })
    .map(function toArgument(pair) {
      if (typeof pair[1] === 'boolean') {
        return '--' + pair[0];
      }
      return '--' + pair[0] + '=' + pair[1];
    });

  return args;
}

/**
 * Executes csscss and returns the result as json.
 */
function executeCSSCSS(files, options, cb) {
  var stdout = '';
  var args = files.concat(normalizeArguments(options));
  var programm = process.platform === 'win32' ? 'csscss.bat' : 'csscss';
  // allways require json format
  args.push('--json');

  if (!files || files.length === 0) {
    cb(null, []);
    return;
  }

  spawn(programm, args)
    .stdout.on('data', function onData(data) {
      stdout += data;
    })
    .on('close', function onClose() {
      cb(null, stdout ? JSON.parse(stdout) : []);
    })
    .on('error', cb);
}

module.exports = {
  execute: executeCSSCSS,
};
<|endoftext|>


<commit_before>reportCategories = [
  {
    name: 'traffic',
    textcolor: 'amber-text darken-2',
    icon: 'mdi-alert-warning',
  },
  {
    name: 'control',
    color: 'light-blue-text',
    icon: 'mdi-action-visibility',
  }
];

allReportTypes = [
  {
    category: 'traffic',
    name: 'Pociąg stoi',
    color: 'amber darken-2',
    icon: 'mdi-av-pause-circle-fill'
  },
  {
    category: 'traffic',
    name: 'Pociąg jedzie powoli',
    color: 'amber darken-2',
    icon: 'mdi-image-timelapse'
  },
  {
    category: 'traffic',
    name: 'Pociąg jest zatłoczony',
    color: 'amber darken-2',
    icon: 'mdi-social-people'
  },
  {
    category: 'traffic',
    name: 'Pociąg uległ awarii',
    color: 'amber darken-2',
    icon: 'mdi-image-flash-on'
  },
  {
    category: 'traffic',
    name: 'Pociąg jest opóźniony',
    color: 'amber darken-2',
    icon: 'mdi-hardware-watch'
  },
  {
    category: 'control',
    name: 'Kontroler na stacji',
    color: 'light-blue',
    icon: 'mdi-action-accessibility'
  },
  {
    category: 'control',
    name: 'Kontroler wsiadł do pociągu',
    color: 'light-blue',
    icon: 'mdi-action-visibility'
  },
  {
    category: 'other',
    name: 'Zgłoś coś innego…',
    color: 'amber',
    icon: 'mdi-alert-warning'
  }
];

reportTypes = {
  common: allReportTypes.slice(0, 3).concat(allReportTypes.slice(-1)),
  metro: allReportTypes.slice(0, 4).concat(allReportTypes.slice(-3, -1)),
  wkd: allReportTypes.slice(0, 5),
  skm: allReportTypes.slice(0, 5),
  km: allReportTypes.slice(0, 5)
};
<commit_msg>change common<commit_after>reportCategories = [
  {
    name: 'traffic',
    textcolor: 'amber-text darken-2',
    icon: 'mdi-alert-warning',
  },
  {
    name: 'control',
    color: 'light-blue-text',
    icon: 'mdi-action-visibility',
  }
];

allReportTypes = [
  {
    category: 'traffic',
    name: 'Pociąg stoi',
    color: 'amber darken-2',
    icon: 'mdi-av-pause-circle-fill'
  },
  {
    category: 'traffic',
    name: 'Pociąg jedzie powoli',
    color: 'amber darken-2',
    icon: 'mdi-image-timelapse'
  },
  {
    category: 'traffic',
    name: 'Pociąg jest zatłoczony',
    color: 'amber darken-2',
    icon: 'mdi-social-people'
  },
  {
    category: 'traffic',
    name: 'Pociąg uległ awarii',
    color: 'amber darken-2',
    icon: 'mdi-image-flash-on'
  },
  {
    category: 'traffic',
    name: 'Pociąg jest opóźniony',
    color: 'amber darken-2',
    icon: 'mdi-hardware-watch'
  },
  {
    category: 'control',
    name: 'Kontroler na stacji',
    color: 'light-blue',
    icon: 'mdi-action-accessibility'
  },
  {
    category: 'control',
    name: 'Kontroler wsiadł do pociągu',
    color: 'light-blue',
    icon: 'mdi-action-visibility'
  },
  {
    category: 'other',
    name: 'Zgłoś coś innego…',
    color: 'amber',
    icon: 'mdi-alert-warning'
  }
];

reportTypes = {
  common: [
    allReportTypes[0],
    allReportTypes[1],
    allReportTypes[4],
    allReportTypes[7]
  ],
  metro: allReportTypes.slice(0, 4).concat(allReportTypes.slice(-3, -1)),
  wkd: allReportTypes.slice(0, 5),
  skm: allReportTypes.slice(0, 5),
  km: allReportTypes.slice(0, 5)
};
<|endoftext|>