<commit_before>var utility = require('./utility');
var retrievers = (process.env.RETRIEVER_HOST || "http://localhost:5100").split(",");
var async = require('async');
var db = utility.db;
var logger = utility.logger;
var fs = require('fs');
var moment = require('moment');
var getData = utility.getData;
var request = require('request');
var insertPlayer = utility.insertPlayer;
var insertMatch = utility.insertMatch;
var queueReq = utility.queueReq;
var spawn = require('child_process').spawn;
var replay_dir = process.env.REPLAY_DIR || "./replays/";
var domain = require('domain');

function processParse(job, cb) {
    var match_id = job.data.payload.match_id;
    var noRetry = job.toJSON().attempts.remaining <= 0;
    async.waterfall([
        async.apply(checkLocal, job),
        getReplayUrl,
        streamReplay,
    ], function(err, job2) {
        if (err === "replay expired" || noRetry) {
            logger.info("error %s, not retrying", err);
            return db.matches.update({
                match_id: match_id
            }, {
                $set: {
                    parse_status: 1
                }
            }, function(err2) {
                //nullify error if replay expired
                err = err === "replay expired" ? null : err;
                cb(err || err2);
            });
        }
        else if (err) {
            logger.info("error %s, retrying", err);
            return cb(err);
        }
        else {
            //todo do private/local lobbies have an id?
            //todo data won't get inserted if uploaded replay where match id=0, or match not available in api
            if (job2 && job2.data.payload.match_id) {
                //queue job for api to make sure it's in db
                queueReq("api_details", job2.data.payload, function(err) {
                    cb(err);
                });
            }
            else {
                return cb(err);
            }
        }
    });
}

function checkLocal(job, cb) {
    var match_id = job.data.payload.match_id;
    var fileName = job.data.fileName || replay_dir + match_id + ".dem";
    if (fs.existsSync(fileName)) {
        logger.info("[PARSER] %s, found local replay", match_id);
        job.data.fileName = fileName;
        job.update();
    }
    cb(null, job);
}

function getReplayUrl(job, cb) {
    if (job.data.url || job.data.fileName) {
        logger.info("has url or fileName");
        return cb(null, job);
    }
    var match = job.data.payload;
    if (match.start_time > moment().subtract(7, 'days').format('X')) {
        logger.info("requesting match from dota2");
        var urls = [];
        for (var i = 0; i < retrievers.length; i++) {
            urls[i] = retrievers[i] + "?match_id=" + job.data.payload.match_id;
        }
        getData(urls, function(err, body) {
            if (err || !body || !body.match) {
                return cb("invalid body or error");
            }
            var url = "http://replay" + body.match.cluster + ".valve.net/570/" + match.match_id + "_" + body.match.replaySalt + ".dem.bz2";
            job.data.url = url;
            job.update();
            return cb(null, job);
        });
    }
    /*
    else if (process.env.AWS_S3_BUCKET) {
        getS3Url(match.match_id, function(err, url) {
            if (!url) {
                return cb("replay expired");
            }
            job.data.url = url;
            job.update();
            return cb(err, job);
        });
    }
    */
    else {
        cb("replay expired");
    }
}

function streamReplay(job, cb) {
    var t1 = new Date();
    //var fileName = replay_dir + match_id + ".dem";
    //var archiveName = fileName + ".bz2";
    var match_id = job.data.payload.match_id;
    logger.info("[PARSER] streaming from %s", job.data.url || job.data.fileName);
    var d = domain.create();
    d.on('error', function(err) {
        logger.info(err);
        return cb(err);
    });
    d.run(function() {
        var parser_file = "parser/target/stats-0.1.0.jar";
        var output = "";
        var parser = spawn("java", ["-jar",
            parser_file
        ]);
        parser.stdout.on('data', function(data) {
            output += data;
        });
        parser.on('exit', function(code) {
            logger.info("[PARSER] exit code: %s", code);
            logger.info("[PARSER] parse time: %s", (new Date() - t1) / 1000);
            if (job.data.fileName) {
                fs.unlinkSync(job.data.fileName);
            }
            if (code) {
                return cb(code);
            }
            try {
                output = JSON.parse(output);
            }
            catch (err) {
                return cb(err);
            }
            match_id = match_id || output.match_id;
            job.data.payload.parsed_data = output;
            //todo get api data out of replay in case of private
            db.matches.update({
                match_id: match_id
            }, {
                $set: {
                    parsed_data: output,
                    parse_status: 2
                }
            }, function(err) {
                cb(err, job);
            });
        });
        if (job.data.fileName) {
            fs.createReadStream(job.data.fileName).pipe(parser.stdin);
        }
        else {
            var bz = spawn("bzcat");
            var downStream = request.get({
                url: job.data.url,
                encoding: null
            });
            downStream.pipe(bz.stdin);
            bz.stdout.pipe(parser.stdin);
        }
    });
}

function processApi(job, cb) {
    //process an api request
    var payload = job.data.payload;
    getData(job.data.url, function(err, data) {
        if (err) {
            return cb(err);
        }
        if (data.response) {
            logger.info("summaries response");
            async.map(data.response.players, insertPlayer, function(err) {
                cb(err);
            });
        }
        else if (payload.match_id) {
            logger.info("details response");
            var match = data.result;
            //join payload with match
            for (var prop in payload) {
                match[prop] = match[prop] ? match[prop] : payload[prop];
            }
            insertMatch(match, function(err) {
                cb(err);
            });
        }
        else {
            return cb("unknown response");
        }
    });
}

module.exports = {
    processParse: processParse,
    processApi: processApi
};<commit_msg>Update processors.js<commit_after>var utility = require('./utility');
var retrievers = (process.env.RETRIEVER_HOST || "http://localhost:5100").split(",");
var async = require('async');
var db = utility.db;
var logger = utility.logger;
var fs = require('fs');
var moment = require('moment');
var getData = utility.getData;
var request = require('request');
var insertPlayer = utility.insertPlayer;
var insertMatch = utility.insertMatch;
var queueReq = utility.queueReq;
var spawn = require('child_process').spawn;
var replay_dir = process.env.REPLAY_DIR || "./replays/";
var domain = require('domain');

function processParse(job, cb) {
    var match_id = job.data.payload.match_id;
    var noRetry = job.toJSON().attempts.remaining <= 1;
    async.waterfall([
        async.apply(checkLocal, job),
        getReplayUrl,
        streamReplay,
    ], function(err, job2) {
        if (err === "replay expired" || noRetry) {
            logger.info("error %s, not retrying", err);
            return db.matches.update({
                match_id: match_id
            }, {
                $set: {
                    parse_status: 1
                }
            }, function(err2) {
                //nullify error if replay expired
                err = err === "replay expired" ? null : err;
                cb(err || err2);
            });
        }
        else if (err) {
            logger.info("error %s, retrying", err);
            return cb(err);
        }
        else {
            //todo do private/local lobbies have an id?
            //todo data won't get inserted if uploaded replay where match id=0, or match not available in api
            if (job2 && job2.data.payload.match_id) {
                //queue job for api to make sure it's in db
                queueReq("api_details", job2.data.payload, function(err) {
                    cb(err);
                });
            }
            else {
                return cb(err);
            }
        }
    });
}

function checkLocal(job, cb) {
    var match_id = job.data.payload.match_id;
    var fileName = job.data.fileName || replay_dir + match_id + ".dem";
    if (fs.existsSync(fileName)) {
        logger.info("[PARSER] %s, found local replay", match_id);
        job.data.fileName = fileName;
        job.update();
    }
    cb(null, job);
}

function getReplayUrl(job, cb) {
    if (job.data.url || job.data.fileName) {
        logger.info("has url or fileName");
        return cb(null, job);
    }
    var match = job.data.payload;
    if (match.start_time > moment().subtract(7, 'days').format('X')) {
        logger.info("requesting match from dota2");
        var urls = [];
        for (var i = 0; i < retrievers.length; i++) {
            urls[i] = retrievers[i] + "?match_id=" + job.data.payload.match_id;
        }
        getData(urls, function(err, body) {
            if (err || !body || !body.match) {
                return cb("invalid body or error");
            }
            var url = "http://replay" + body.match.cluster + ".valve.net/570/" + match.match_id + "_" + body.match.replaySalt + ".dem.bz2";
            job.data.url = url;
            job.update();
            return cb(null, job);
        });
    }
    /*
    else if (process.env.AWS_S3_BUCKET) {
        getS3Url(match.match_id, function(err, url) {
            if (!url) {
                return cb("replay expired");
            }
            job.data.url = url;
            job.update();
            return cb(err, job);
        });
    }
    */
    else {
        cb("replay expired");
    }
}

function streamReplay(job, cb) {
    var t1 = new Date();
    //var fileName = replay_dir + match_id + ".dem";
    //var archiveName = fileName + ".bz2";
    var match_id = job.data.payload.match_id;
    logger.info("[PARSER] streaming from %s", job.data.url || job.data.fileName);
    var d = domain.create();
    d.on('error', function(err) {
        logger.info(err);
        return cb(err);
    });
    d.run(function() {
        var parser_file = "parser/target/stats-0.1.0.jar";
        var output = "";
        var parser = spawn("java", ["-jar",
            parser_file
        ]);
        parser.stdout.on('data', function(data) {
            output += data;
        });
        parser.on('exit', function(code) {
            logger.info("[PARSER] exit code: %s", code);
            logger.info("[PARSER] parse time: %s", (new Date() - t1) / 1000);
            if (job.data.fileName) {
                fs.unlinkSync(job.data.fileName);
            }
            if (code) {
                return cb(code);
            }
            try {
                output = JSON.parse(output);
            }
            catch (err) {
                return cb(err);
            }
            match_id = match_id || output.match_id;
            job.data.payload.parsed_data = output;
            //todo get api data out of replay in case of private
            db.matches.update({
                match_id: match_id
            }, {
                $set: {
                    parsed_data: output,
                    parse_status: 2
                }
            }, function(err) {
                cb(err, job);
            });
        });
        if (job.data.fileName) {
            fs.createReadStream(job.data.fileName).pipe(parser.stdin);
        }
        else {
            var bz = spawn("bzcat");
            var downStream = request.get({
                url: job.data.url,
                encoding: null
            });
            downStream.pipe(bz.stdin);
            bz.stdout.pipe(parser.stdin);
        }
    });
}

function processApi(job, cb) {
    //process an api request
    var payload = job.data.payload;
    getData(job.data.url, function(err, data) {
        if (err) {
            return cb(err);
        }
        if (data.response) {
            logger.info("summaries response");
            async.map(data.response.players, insertPlayer, function(err) {
                cb(err);
            });
        }
        else if (payload.match_id) {
            logger.info("details response");
            var match = data.result;
            //join payload with match
            for (var prop in payload) {
                match[prop] = match[prop] ? match[prop] : payload[prop];
            }
            insertMatch(match, function(err) {
                cb(err);
            });
        }
        else {
            return cb("unknown response");
        }
    });
}

module.exports = {
    processParse: processParse,
    processApi: processApi
};
<|endoftext|>


<commit_before>/*
Name:          nodejs-mollie
Description:   Node.js module to access the Mollie payments and MessageBird SMS APIs.
Source:        https://github.com/fvdm/nodejs-mollie
Feedback:      https://github.com/fvdm/nodejs-mollie/issues
License:       Public Domain / Unlicense (see UNLICENSE file)
*/

var httpreq = require ('httpreq');
var settings = {
  apikey: null,
  timeout: 5000
};

function talk (method, path, params, callback) {
  var options = {
    url: 'https://api.mollie.nl/v1' + path,
    method: method,
    parameters: params || null,
    timeout: parseInt (settings.timeout, 10) || 5000,
    headers: {
      'Accept': 'application/json',
      'Authorization': 'Bearer ' + settings.apikey,
      'User-Agent': 'mollie.js (https://www.npmjs.com/package/mollie)'
    }
  };

  httpreq.doRequest (options, function (err, res) {
    var data = res && res.body || null;
    var error = null;

    if (err) {
      error = new Error ('request failed');
      error.error = err;
      callback (error);
      return;
    }

    if (res && res.statusCode === 204) {
      callback (null, true);
      return;
    }

    if (method === 'DELETE' && res && res.statusCode === 404) {
      callback (null, false);
      return;
    }

    try {
      data = JSON.parse (data);
    } catch (e) {
      error = new Error ('invalid response');
      error.error = e;
      error.statusCode = res && res.statusCode || null;
    }

    if (data && data.error) {
      error = new Error ('API error');
      error.error = data.error;
      error.statusCode = res && res.statusCode || null;
      data = null;
    }

    callback (error, data);
  });
}

module.exports = function (config) {
  var ckey;

  if (typeof config !== 'object') {
    return null;
  }

  for (ckey in config) {
    settings [ckey] = config [ckey];
  }

  return {
    payments: {
      get: function (id, callback) {
        talk ('GET', '/payments/' + id, {}, callback);
      },

      list: function (params, callback) {
        if (typeof params === 'function') {
          callback = params;
          params = {};
        }
        talk ('GET', '/payments', params, callback);
      },

      create: function (params, callback) {
        var key;

        if (params.metadata instanceof Object) {
          for (key in params.metadata) {
            params ['metadata[' + key + ']'] = params.metadata [key];
          }

          delete params.metadata;
        }

        talk ('POST', '/payments', params, callback);
      }
    },

    refunds: {
      list: function (paymentId, params, callback) {
        if (typeof params === 'function') {
          callback = params;
          params = {};
        }
        talk ('GET', '/payments/' + paymentId + '/refunds', params, callback);
      },

      create: function (paymentId, amount, callback) {
        var params = {};

        if (typeof amount === 'function') {
          callback = amount;
          amount = null;
        }

        if (amount) {
          params.amount = amount;
        }

        talk ('POST', '/payments/' + paymentId + '/refunds', params, callback);
      },

      delete: function (paymentId, refundId, callback) {
        talk ('DELETE', '/payments/' + paymentId + '/refunds/' + refundId, {}, callback);
      }
    },

    issuers: {
      get: function (issuerId, callback) {
        talk ('GET', '/issuers/' + issuerId, {}, callback);
      },

      list: function (params, callback) {
        if (typeof params === 'function') {
          callback = params;
          params = {};
        }
        talk ('GET', '/issuers', params, callback);
      }
    },

    methods: {
      list: function (params, callback) {
        if (typeof params === 'function') {
          callback = params;
          params = {};
        }
        talk ('GET', '/methods', params, callback);
      }
    }
  };
};

<commit_msg>Reduced code complexity<commit_after>/*
Name:          nodejs-mollie
Description:   Node.js module to access the Mollie payments and MessageBird SMS APIs.
Source:        https://github.com/fvdm/nodejs-mollie
Feedback:      https://github.com/fvdm/nodejs-mollie/issues
License:       Public Domain / Unlicense (see UNLICENSE file)
*/

var httpreq = require ('httpreq');
var settings = {
  apikey: null,
  timeout: 5000
};

function talk (method, path, params, callback) {
  var options = {
    url: 'https://api.mollie.nl/v1' + path,
    method: method,
    parameters: params || null,
    timeout: parseInt (settings.timeout, 10) || 5000,
    headers: {
      'Accept': 'application/json',
      'Authorization': 'Bearer ' + settings.apikey,
      'User-Agent': 'mollie.js (https://www.npmjs.com/package/mollie)'
    }
  };

  httpreq.doRequest (options, function (err, res) {
    var data = null;
    var error = null;

    if (err) {
      error = new Error ('request failed');
      error.error = err;
      callback (error);
      return;
    }

    data = res.body;

    if (res.statusCode === 204) {
      callback (null, true);
      return;
    }

    if (method === 'DELETE' && res.statusCode === 404) {
      callback (null, false);
      return;
    }

    try {
      data = JSON.parse (data);
    } catch (e) {
      error = new Error ('invalid response');
      error.error = e;
      error.statusCode = res && res.statusCode || null;
    }

    if (data && data.error) {
      error = new Error ('API error');
      error.error = data.error;
      error.statusCode = res && res.statusCode || null;
      data = null;
    }

    callback (error, data);
  });
}

module.exports = function (config) {
  var ckey;

  if (typeof config !== 'object') {
    return null;
  }

  for (ckey in config) {
    settings [ckey] = config [ckey];
  }

  return {
    payments: {
      get: function (id, callback) {
        talk ('GET', '/payments/' + id, {}, callback);
      },

      list: function (params, callback) {
        if (typeof params === 'function') {
          callback = params;
          params = {};
        }
        talk ('GET', '/payments', params, callback);
      },

      create: function (params, callback) {
        var key;

        if (params.metadata instanceof Object) {
          for (key in params.metadata) {
            params ['metadata[' + key + ']'] = params.metadata [key];
          }

          delete params.metadata;
        }

        talk ('POST', '/payments', params, callback);
      }
    },

    refunds: {
      list: function (paymentId, params, callback) {
        if (typeof params === 'function') {
          callback = params;
          params = {};
        }
        talk ('GET', '/payments/' + paymentId + '/refunds', params, callback);
      },

      create: function (paymentId, amount, callback) {
        var params = {};

        if (typeof amount === 'function') {
          callback = amount;
          amount = null;
        }

        if (amount) {
          params.amount = amount;
        }

        talk ('POST', '/payments/' + paymentId + '/refunds', params, callback);
      },

      delete: function (paymentId, refundId, callback) {
        talk ('DELETE', '/payments/' + paymentId + '/refunds/' + refundId, {}, callback);
      }
    },

    issuers: {
      get: function (issuerId, callback) {
        talk ('GET', '/issuers/' + issuerId, {}, callback);
      },

      list: function (params, callback) {
        if (typeof params === 'function') {
          callback = params;
          params = {};
        }
        talk ('GET', '/issuers', params, callback);
      }
    },

    methods: {
      list: function (params, callback) {
        if (typeof params === 'function') {
          callback = params;
          params = {};
        }
        talk ('GET', '/methods', params, callback);
      }
    }
  };
};

<|endoftext|>


<commit_before>import _ from 'lodash';
import parse, {loopAssociater} from './parse';

const ADD = 0, RIGHT = 1,
  OUT = 2, IN = 3,
  OPEN = 4, CLOSE = 5,
  CLEAR = 6, MUL = 7,
  SCAN_LEFT = 8, SCAN_RIGHT = 9,
  MANY = 100;

function scanLeft(memory, dc) {
  while (memory[dc]) {
    dc--;
  }
  return dc;
}

function scanRight(memory, dc) {
  while (memory[dc]) {
    dc++;
  }
  return dc;
}

function manyfier(program) {
  const MAX_IN_MANY = 200;

  function* _manyfier(program) {
    let buffer = [];

    function* flush() {
      if (buffer.length > 1) {
        yield {type: MANY, items: buffer};
      } else {
        yield* buffer;
      }
      buffer = [];
    }

    for (let ins of program) {
      switch (buffer.length < MAX_IN_MANY && ins.type) {
        case ADD:
        case RIGHT:
        case OUT:
        case IN:
        case CLEAR:
        case MUL:
        case SCAN_LEFT:
        case SCAN_RIGHT:
          buffer.push(ins);
          break;
        default:
          yield* flush();
          yield ins;
      }
    }
    yield* flush();
  }

  return loopAssociater(_manyfier(program));
}

function compile(program, registers, memory, write, read, EOF) {
  // registers[0]: dc
  // registers[1]: pc
  function INS_CLEAR() {
    memory[registers[0]] = 0;
    return 1;
  }
  function INS_OUT() {
    write(memory[registers[0]]|0);
    return 1;
  }
  function INS_IN() {
    const value = read();
    memory[registers[0]] = value === null ? EOF : (value|0);
    return 1;
  }
  function INS_SCAN_LEFT() {
    registers[0] = scanLeft(memory, registers[0]);
    return 1;
  }
  function INS_SCAN_RIGHT() {
    registers[0] = scanRight(memory, registers[0]);
    return 1;
  }

  function newFn(src) {
    // jshint evil:true
    const fn = new Function(
      'registers', 'memory', 'program', 'write', 'read', 'EOF',
      'scanLeft', 'scanRight', src);
    return () =>
      fn(registers, memory, program, write, read, EOF, scanLeft, scanRight);
  }

  function toSrc(ins) {
    let x = ins.x|0;
    let y = ins.y|0;

    switch (ins.type) {
      case ADD:
        return `memory[registers[0]] += ${x};`;
      case CLEAR:
        return `memory[registers[0]] = 0;`;
      case MUL:
        return `memory[registers[0] + ${x}] += memory[registers[0]] * ${y};`;
      case RIGHT:
        return `registers[0] += ${x};`;
      case OUT:
        return `write(memory[registers[0]]|0);`;
      case IN:
        return `var value = read();\n` +
          `memory[registers[0]] = value === null ? EOF : (value|0);`;
      case SCAN_LEFT:
        return `registers[0] = scanLeft(memory, registers[0]);`;
      case SCAN_RIGHT:
        return `registers[0] = scanRight(memory, registers[0]);`;
      default:
        throw new Error("Not compilable type: "+ins.type);
    }
  }

  function mapper(ins) {
    const x = ins.x|0;
    const y = ins.y|0;
    const pair = ins.pair|0;

    switch (ins.type) {
      case ADD:
        return () => {
          memory[registers[0]] += x;
          return 1;
        };
      case CLEAR:
        return INS_CLEAR;
      case MUL:
        return () => {
          const dc = registers[0];
          memory[dc + x] += (memory[dc]|0) * y;
          return 1;
        };
      case RIGHT:
        return () => {
          registers[0] += x;
          return 1;
        };
      case OUT:
        return INS_OUT;
      case IN:
        return INS_IN;
      case SCAN_LEFT:
        return INS_SCAN_LEFT;
      case SCAN_RIGHT:
        return INS_SCAN_RIGHT;
      case OPEN:
        return () => {
          if (!memory[registers[0]]) {
            registers[1] = pair;
          }
          return 1;
        };
      case CLOSE:
        return () => {
          if (memory[registers[0]]) {
            registers[1] = pair;
          }
          return 1;
        };
      case MANY:
        return newFn(
          ins.items.map(toSrc)
            .concat([`return ${ins.items.length};`])
            .join('\n')
        );
      default:
        throw new Error("Unknown instruction type: "+ins.type);
    }
  }

  return program.map(mapper);
}

export default class Machine {
  constructor(programString, read, write, options={}) {
    if (read[Symbol.iterator]) {
      const iter = read[Symbol.iterator]();
      read = () => {
        const {value, done} = iter.next();
        return done ? null : value;
      };
    }

    this._cellSize = options.cellSize || 16;
    this._cellCount = options.cellCount || 4096;
    this._read = read;
    this._write = write;
    if (this._cellSize === 16) {
      this._memory = new Uint16Array(this._cellCount);
    } else if (this._cellSize === 8) {
      this._memory = new Uint8Array(this._cellCount);
    } else {
      throw new Error("Invalid cell size: "+this._cellSize);
    }
    this._registers = new Uint32Array(2);
    this._EOF = options.EOF|0;
    this._complete = false;
    this._program = compile(
      manyfier(parse(programString)), this._registers, this._memory,
      this._write, this._read, this._EOF
    );
  }

  get complete() {
    return this._complete;
  }

  run(steps=Infinity) {
    const program = this._program;
    const memory = this._memory;
    const registers = this._registers;

    const programLen = program.length;
    let step = 0;
    while (step < steps) {
      if (registers[1] >= programLen) {
        this._complete = true;
        break;
      }
      const ins = program[registers[1]];
      step += ins();
      registers[1]++;
    }

    return step;
  }
}
<commit_msg>correctness issue with jit and mul instruction<commit_after>import _ from 'lodash';
import parse, {loopAssociater} from './parse';

const ADD = 0, RIGHT = 1,
  OUT = 2, IN = 3,
  OPEN = 4, CLOSE = 5,
  CLEAR = 6, MUL = 7,
  SCAN_LEFT = 8, SCAN_RIGHT = 9,
  MANY = 100;

function scanLeft(memory, dc) {
  while (memory[dc]) {
    dc--;
  }
  return dc;
}

function scanRight(memory, dc) {
  while (memory[dc]) {
    dc++;
  }
  return dc;
}

function manyfier(program) {
  const MAX_IN_MANY = 200;

  function* _manyfier(program) {
    let buffer = [];

    function* flush() {
      if (buffer.length > 1) {
        yield {type: MANY, items: buffer};
      } else {
        yield* buffer;
      }
      buffer = [];
    }

    for (let ins of program) {
      switch (buffer.length < MAX_IN_MANY && ins.type) {
        case ADD:
        case RIGHT:
        case OUT:
        case IN:
        case CLEAR:
        case MUL:
        case SCAN_LEFT:
        case SCAN_RIGHT:
          buffer.push(ins);
          break;
        default:
          yield* flush();
          yield ins;
      }
    }
    yield* flush();
  }

  return loopAssociater(_manyfier(program));
}

function compile(program, registers, memory, write, read, EOF) {
  // registers[0]: dc
  // registers[1]: pc
  function INS_CLEAR() {
    memory[registers[0]] = 0;
    return 1;
  }
  function INS_OUT() {
    write(memory[registers[0]]|0);
    return 1;
  }
  function INS_IN() {
    const value = read();
    memory[registers[0]] = value === null ? EOF : (value|0);
    return 1;
  }
  function INS_SCAN_LEFT() {
    registers[0] = scanLeft(memory, registers[0]);
    return 1;
  }
  function INS_SCAN_RIGHT() {
    registers[0] = scanRight(memory, registers[0]);
    return 1;
  }

  function newFn(src) {
    // jshint evil:true
    const fn = new Function(
      'registers', 'memory', 'program', 'write', 'read', 'EOF',
      'scanLeft', 'scanRight', src);
    return () =>
      fn(registers, memory, program, write, read, EOF, scanLeft, scanRight);
  }

  function toSrc(ins) {
    let x = ins.x|0;
    let y = ins.y|0;

    switch (ins.type) {
      case ADD:
        return `memory[registers[0]] += ${x};`;
      case CLEAR:
        return `memory[registers[0]] = 0;`;
      case MUL:
        return `memory[registers[0] + ${x}] += (memory[registers[0]]|0)${y !== 1 ? ' * '+y : ''};`;
      case RIGHT:
        return `registers[0] += ${x};`;
      case OUT:
        return `write(memory[registers[0]]|0);`;
      case IN:
        return `var value = read();\n` +
          `memory[registers[0]] = value === null ? EOF : (value|0);`;
      case SCAN_LEFT:
        return `registers[0] = scanLeft(memory, registers[0]);`;
      case SCAN_RIGHT:
        return `registers[0] = scanRight(memory, registers[0]);`;
      default:
        throw new Error("Not compilable type: "+ins.type);
    }
  }

  function mapper(ins) {
    const x = ins.x|0;
    const y = ins.y|0;
    const pair = ins.pair|0;

    switch (ins.type) {
      case ADD:
        return () => {
          memory[registers[0]] += x;
          return 1;
        };
      case CLEAR:
        return INS_CLEAR;
      case MUL:
        return () => {
          const dc = registers[0];
          memory[dc + x] += (memory[dc]|0) * y;
          return 1;
        };
      case RIGHT:
        return () => {
          registers[0] += x;
          return 1;
        };
      case OUT:
        return INS_OUT;
      case IN:
        return INS_IN;
      case SCAN_LEFT:
        return INS_SCAN_LEFT;
      case SCAN_RIGHT:
        return INS_SCAN_RIGHT;
      case OPEN:
        return () => {
          if (!memory[registers[0]]) {
            registers[1] = pair;
          }
          return 1;
        };
      case CLOSE:
        return () => {
          if (memory[registers[0]]) {
            registers[1] = pair;
          }
          return 1;
        };
      case MANY:
        return newFn(
          ins.items.map(toSrc)
            .concat([`return ${ins.items.length};`])
            .join('\n')
        );
      default:
        throw new Error("Unknown instruction type: "+ins.type);
    }
  }

  return program.map(mapper);
}

export default class Machine {
  constructor(programString, read, write, options={}) {
    if (read[Symbol.iterator]) {
      const iter = read[Symbol.iterator]();
      read = () => {
        const {value, done} = iter.next();
        return done ? null : value;
      };
    }

    this._cellSize = options.cellSize || 16;
    this._cellCount = options.cellCount || 4096;
    this._read = read;
    this._write = write;
    if (this._cellSize === 16) {
      this._memory = new Uint16Array(this._cellCount);
    } else if (this._cellSize === 8) {
      this._memory = new Uint8Array(this._cellCount);
    } else {
      throw new Error("Invalid cell size: "+this._cellSize);
    }
    this._registers = new Uint32Array(2);
    this._EOF = options.EOF|0;
    this._complete = false;
    this._program = compile(
      manyfier(parse(programString)), this._registers, this._memory,
      this._write, this._read, this._EOF
    );
  }

  get complete() {
    return this._complete;
  }

  run(steps=Infinity) {
    const program = this._program;
    const memory = this._memory;
    const registers = this._registers;

    const programLen = program.length;
    let step = 0;
    while (step < steps) {
      if (registers[1] >= programLen) {
        this._complete = true;
        break;
      }
      const ins = program[registers[1]];
      step += ins();
      registers[1]++;
    }

    return step;
  }
}
<|endoftext|>


<commit_before>/* eslint-disable */
import template from './new.html';

function NewDashgroupCtrl($scope, $location, $http, toastr, currentUser, Events, Dashgroup) {
  Events.record('view', 'page', 'dashgroups/new');

  this.dashgroup_name = '';
  $scope.created = false;
  $scope.saveDashgroup = () => {
    if (!this.dashgroupForm.$valid || $scope.created) {
        return
    }
    Dashgroup.newDashgroup({name:this.dashgroup_name});
    $http.post('api/dashgroups/create', {
      dashgroup_name: this.dashgroup_name
    }).then(function(){
        $scope.created = true;
    });
  };
}

export default function (ngModule) {
  ngModule.controller('NewDashgroupCtrl', NewDashgroupCtrl);

  return {
    '/dashgroups/new': {
      template,
      controller: 'NewDashgroupCtrl',
      controllerAs: '$ctrl',
      bindToController: 'true',
    },
  };
}
<commit_msg>Removes useless code<commit_after>/* eslint-disable */
import template from './new.html';

function NewDashgroupCtrl($scope, $location, $http, toastr, currentUser, Events, Dashgroup) {
  Events.record('view', 'page', 'dashgroups/new');

  this.dashgroup_name = '';
  $scope.created = false;
  $scope.saveDashgroup = () => {
    if (!this.dashgroupForm.$valid || $scope.created) {
        return
    }
    $http.post('api/dashgroups/create', {
      dashgroup_name: this.dashgroup_name
    }).then(function(){
        $scope.created = true;
    });
  };
}

export default function (ngModule) {
  ngModule.controller('NewDashgroupCtrl', NewDashgroupCtrl);

  return {
    '/dashgroups/new': {
      template,
      controller: 'NewDashgroupCtrl',
      controllerAs: '$ctrl',
      bindToController: 'true',
    },
  };
}
<|endoftext|>


<commit_before>function load_songs(textarea) {
    var encoded_uri = textarea.value;
    var decoded = decodeURIComponent(encoded_uri);
    var without_protocol = decoded.replace("irealb://", "");
    var unsplitted = without_protocol.split("==0=0===");
    for(i in unsplitted) {
        song = unsplitted[i].split("=");
        title = song[0];
        author = song[1];
        localStorage[title + " (" + author + ")"] = unsplitted[i]
    }
}
function swap(splitted, i, j) {
    tmp = splitted[i];
    splitted[i] = splitted[j];
    splitted[j] = tmp;
}
function mirror_swap(str, start, size) {
    var splitted = str.split('');
    var count = Math.floor(size / 2);
    for(var i = 0; i < count; i++) {
        swap(splitted, start + i, size + start - i);
    }
    return splitted.join("");
}
function unwarble(warbled) {
    var unwarbled = warbled.replace('1r34LbKcu7', '');
    for(var i = 0; i + 51 < unwarbled.length; i += 50) {
        unwarbled = mirror_swap(mirror_swap(mirror_swap(unwarbled, i + 10, 29), i + 5, 39), i, 49)
    }
    return unwarbled.replace(/XyQ/g, "   ").replace(/Kcl/g, "| x").replace(/LZ/g, "|");
}
function get_sheet(unwarbled) {
    unwarbled = unwarbled.replace(/\*([ABC])/g, "$1");
    unwarbled = unwarbled.replace(/\[/g, " ");
    unwarbled = unwarbled.replace(/T(.)(.)/g, "$1$1");
    unwarbled = unwarbled.replace(/\^/g, "Δ");
    var splitted = unwarbled.split('');
    var open_div = "
";
    var close_div = "
";
    var open_span = "";
    var close_span = "";
    var out = open_div + open_span;
    var bars = 0;
    for(i = 0; i < splitted.length; i++) {
        var c = splitted[i];
        var add = "";
        if(c == "|") {
            c = close_span;
            bars += 1;
            if(bars < 4)
            {
                c += open_span
            }
        }
        else { if(c == "x") { c = "%"; } }
        if(bars == 4 || c == '}' || c == ']') {
            bars = 0;
            add = close_div + open_div + open_span;
        }
        out += c + add;
    }
    return out + close_span + close_div;
}
function line_to_mma_chords(line) {
    var chords = line.split(" ");
    if(chords.length == 2) {
        chords = [chords[0], "/", chords[1]];
    }
    return chords.join(" ");
}
var worker = new Worker("//rawgit.com/yazgoo/pypyjs-mma/master/worker.js")
function play_mma(mma) {
  worker.postMessage([mma]);
  console.log('Message posted to worker');
  worker.onmessage = function(e) {
    console.log('Message received from worker');
    console.log(btoa(e.data));
    data = e.data
      console.log("playing " + data);
    play(data);
  }
}
function play_song(unwarbled) {
    var previous = "";
    unwarbled = unwarbled.replace(/T../, '?Groove Swing\n')
        .replace(/\{/g, "\n?Repeat\n").replace(/}/g, "\n?RepeatEnd\n")
        .replace(/\*./g, "").replace(/N1/g, "\n?RepeatEnding\\2\n").replace("][", "")
        .replace("[", "\n")
        .replace(/N2/g, "").replace("Z", "").replace(/s/g, " ").replace(/,/g, " ")
        .replace(/-/g, "m").replace(/\^/g, "M").replace(/h/g, "dim")
        .replace(/\|/g, "\n").replace(/\]\[/g, "\n").replace(/\[/, "\n")
        .replace(/l/g, "\n").replace(/x/g, "").replace(/\([^\)]*\)/g, "")/* lets ignore stuff under () for now*/
    splitted = unwarbled.split("\n");
    var previous = "";
    k = 0;
    for(var i = 0; i < splitted.length; i++) {
        var line = splitted[i];
        if(line.length == 0 || line[0] == '?') previous += line.replace(/\?/g, "")
        else {
            previous += "" + k + " " + line_to_mma_chords(line);
            k += 1;
        }
        previous += "\n";
    }
    console.log(previous);
    play_mma(previous);
}
function show_song(title) {
    var song = localStorage[title];
    localStorage["last_song"] = song;
    var splitted = song.split("=");
    var title = splitted[0];
    var author = splitted[1];
    var unwarbled = unwarble(splitted[6]);
    set_content(""+title+" ("+author+")"
            + "<input type=button value='>' onclick=\"play_song('"+unwarbled+"')\"/>

"
            + get_sheet(unwarbled));
}
var songs_list_written;
var songs_list_div;
function add_songs_list() {
  var i;
  s = ""
    for(i = songs_list_written; i < (songs_list_written + 100) && i < localStorage.length; i++) {
        var title = localStorage.key(i);
        s += "" + title  + "
";
    }
  songs_list_div.innerHTML += s;
    songs_list_written += 100;
    if(i < localStorage.length) setTimeout(add_songs_list(), 500);
}
function show_songs_list(div) {
    songs_list_div = div;
    div.innerHTML = "";
    songs_list_written = 0;
    add_songs_list();
}
function set_content(str) {
    var content = document.getElementById("content");
    content.innerHTML = str;
}
function show_imports() {
    set_content("<input type=text onchange='load_songs(this)'/>");
}
function show_about() {
    set_content('Mooche is free software (as in freedom).
'
            +'This means it guarantees 4 fundamentals rights:
'
            +'
'
            +'
Freedom 0: The freedom to run the program for any purpose.
'
            +'
Freedom 1: The freedom to study how the program works, and change it to make it do what you wish.
'
            +'
Freedom 2: The freedom to redistribute and make copies so you can help your neighbor.
'
            +'
Freedom 3: The freedom to improve the program, and release your improvements (and modified versions in general) to the public, so that the whole community benefits.
'
            +'
'
            +'')
}
function show_songs() {
    show_songs_list(document.getElementById('content'));
}
function show_songs_or_last_song() {
    if(localStorage["last_song"] != null) {
        show_song("last_song");
    }
    else {
        show_songs();
    }
}

<commit_msg>preload mma<commit_after>function load_songs(textarea) {
    var encoded_uri = textarea.value;
    var decoded = decodeURIComponent(encoded_uri);
    var without_protocol = decoded.replace("irealb://", "");
    var unsplitted = without_protocol.split("==0=0===");
    for(i in unsplitted) {
        song = unsplitted[i].split("=");
        title = song[0];
        author = song[1];
        localStorage[title + " (" + author + ")"] = unsplitted[i]
    }
}
function swap(splitted, i, j) {
    tmp = splitted[i];
    splitted[i] = splitted[j];
    splitted[j] = tmp;
}
function mirror_swap(str, start, size) {
    var splitted = str.split('');
    var count = Math.floor(size / 2);
    for(var i = 0; i < count; i++) {
        swap(splitted, start + i, size + start - i);
    }
    return splitted.join("");
}
function unwarble(warbled) {
    var unwarbled = warbled.replace('1r34LbKcu7', '');
    for(var i = 0; i + 51 < unwarbled.length; i += 50) {
        unwarbled = mirror_swap(mirror_swap(mirror_swap(unwarbled, i + 10, 29), i + 5, 39), i, 49)
    }
    return unwarbled.replace(/XyQ/g, "   ").replace(/Kcl/g, "| x").replace(/LZ/g, "|");
}
function get_sheet(unwarbled) {
    unwarbled = unwarbled.replace(/\*([ABC])/g, "$1");
    unwarbled = unwarbled.replace(/\[/g, " ");
    unwarbled = unwarbled.replace(/T(.)(.)/g, "$1$1");
    unwarbled = unwarbled.replace(/\^/g, "Δ");
    var splitted = unwarbled.split('');
    var open_div = "
";
    var close_div = "
";
    var open_span = "";
    var close_span = "";
    var out = open_div + open_span;
    var bars = 0;
    for(i = 0; i < splitted.length; i++) {
        var c = splitted[i];
        var add = "";
        if(c == "|") {
            c = close_span;
            bars += 1;
            if(bars < 4)
            {
                c += open_span
            }
        }
        else { if(c == "x") { c = "%"; } }
        if(bars == 4 || c == '}' || c == ']') {
            bars = 0;
            add = close_div + open_div + open_span;
        }
        out += c + add;
    }
    return out + close_span + close_div;
}
function line_to_mma_chords(line) {
    var chords = line.split(" ");
    if(chords.length == 2) {
        chords = [chords[0], "/", chords[1]];
    }
    return chords.join(" ");
}
var worker = new Worker("//rawgit.com/yazgoo/pypyjs-mma/master/worker.js");
// preload mma by running it once with an empty file
worker.postMessage([""]);
function play_mma(mma) {
  worker.postMessage([mma]);
  console.log('Message posted to worker');
  worker.onmessage = function(e) {
    console.log('Message received from worker');
    console.log(btoa(e.data));
    data = e.data
      console.log("playing " + data);
    play(data);
  }
}
function play_song(unwarbled) {
    var previous = "";
    unwarbled = unwarbled.replace(/T../, '?Groove Swing\n')
        .replace(/\{/g, "\n?Repeat\n").replace(/}/g, "\n?RepeatEnd\n")
        .replace(/\*./g, "").replace(/N1/g, "\n?RepeatEnding\\2\n").replace("][", "")
        .replace("[", "\n")
        .replace(/N2/g, "").replace("Z", "").replace(/s/g, " ").replace(/,/g, " ")
        .replace(/-/g, "m").replace(/\^/g, "M").replace(/h/g, "dim")
        .replace(/\|/g, "\n").replace(/\]\[/g, "\n").replace(/\[/, "\n")
        .replace(/l/g, "\n").replace(/x/g, "").replace(/\([^\)]*\)/g, "")/* lets ignore stuff under () for now*/
    splitted = unwarbled.split("\n");
    var previous = "";
    k = 0;
    for(var i = 0; i < splitted.length; i++) {
        var line = splitted[i];
        if(line.length == 0 || line[0] == '?') previous += line.replace(/\?/g, "")
        else {
            previous += "" + k + " " + line_to_mma_chords(line);
            k += 1;
        }
        previous += "\n";
    }
    console.log(previous);
    play_mma(previous);
}
function show_song(title) {
    var song = localStorage[title];
    localStorage["last_song"] = song;
    var splitted = song.split("=");
    var title = splitted[0];
    var author = splitted[1];
    var unwarbled = unwarble(splitted[6]);
    set_content(""+title+" ("+author+")"
            + "<input type=button value='>' onclick=\"play_song('"+unwarbled+"')\"/>

"
            + get_sheet(unwarbled));
}
var songs_list_written;
var songs_list_div;
function add_songs_list() {
  var i;
  s = ""
    for(i = songs_list_written; i < (songs_list_written + 100) && i < localStorage.length; i++) {
        var title = localStorage.key(i);
        s += "" + title  + "
";
    }
  songs_list_div.innerHTML += s;
    songs_list_written += 100;
    if(i < localStorage.length) setTimeout(add_songs_list(), 500);
}
function show_songs_list(div) {
    songs_list_div = div;
    div.innerHTML = "";
    songs_list_written = 0;
    add_songs_list();
}
function set_content(str) {
    var content = document.getElementById("content");
    content.innerHTML = str;
}
function show_imports() {
    set_content("<input type=text onchange='load_songs(this)'/>");
}
function show_about() {
    set_content('Mooche is free software (as in freedom).
'
            +'This means it guarantees 4 fundamentals rights:
'
            +'
'
            +'
Freedom 0: The freedom to run the program for any purpose.
'
            +'
Freedom 1: The freedom to study how the program works, and change it to make it do what you wish.
'
            +'
Freedom 2: The freedom to redistribute and make copies so you can help your neighbor.
'
            +'
Freedom 3: The freedom to improve the program, and release your improvements (and modified versions in general) to the public, so that the whole community benefits.
'
            +'
'
            +'')
}
function show_songs() {
    show_songs_list(document.getElementById('content'));
}
function show_songs_or_last_song() {
    if(localStorage["last_song"] != null) {
        show_song("last_song");
    }
    else {
        show_songs();
    }
}

<|endoftext|>


<commit_before>define(['moment'], function(moment) {
	var eventStoreQueryBaseUrl = 'http://jgough.corp.versionone.net:2113/streams/asset-',
			eventStoryQueryParameters = '/head/backward/5?embed=content',
			templateUrl = 'http://v1commitstream.azurewebsites.net/assetDetailCommits.html';

	return function(selector, assetNumber) {
    var commits = [];
    var eventStoryQueryUrl = eventStoryQueryBaseUrl + assetNumber + eventStoryQueryParameters;

    $.getJSON(eventStoreQueryUrl).done(function(events) {
      $.each(events.entries, function(index, value) {
        var e = value.content.data;
        var c = {
          timeFormatted: moment(e.commit.committer.date).fromNow(),
          author: e.commit.committer.name,
          sha1Partial: e.commit.tree.sha.substring(0,6),
          action: "committed",
          message: e.commit.message,
          commitHref: e.html_url
        };
        commits.push(c);
      });
      var data = {
        commits: commits
      };
      if (commits.length > 0) {
        $.get(templateUrl).done(function(source) {
          var template = Handlebars.compile(source);
          var content = template(data);
          $(selector).html(content);
        });
      }
    });
  }
});
<commit_msg>S-47665 Correct variable names for api calls<commit_after>define(['moment'], function(moment) {
	var apiBaseUrl 	= 'http://jgough.corp.versionone.net:2113/streams/asset-',
			apiParams	 	= '/head/backward/5?embed=content',
			templateUrl	= 'http://v1commitstream.azurewebsites.net/assetDetailCommits.html';

	return function(selector, assetNumber) {
    var commits = [];
    var apiUrl = apiBaseUrl + assetNumber + apiParams;

    $.getJSON(apiUrl).done(function(events) {
      $.each(events.entries, function(index, value) {
        var e = value.content.data;
        var c = {
          timeFormatted: moment(e.commit.committer.date).fromNow(),
          author: e.commit.committer.name,
          sha1Partial: e.commit.tree.sha.substring(0,6),
          action: "committed",
          message: e.commit.message,
          commitHref: e.html_url
        };
        commits.push(c);
      });
      var data = {
        commits: commits
      };
      if (commits.length > 0) {
        $.get(templateUrl).done(function(source) {
          var template = Handlebars.compile(source);
          var content = template(data);
          $(selector).html(content);
        });
      }
    });
  }
});
<|endoftext|>


<commit_before>define(['exports'],
function(exports) {

  var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

  function encode(input) {
    var output = '';
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    while (i < input.length) {
      chr1 = input.charCodeAt(i++);
      chr2 = input.charCodeAt(i++);
      chr3 = input.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
        enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
        enc4 = 64;
      }

      output = output +
        keyStr.charAt(enc1) + keyStr.charAt(enc2) +
        keyStr.charAt(enc3) + keyStr.charAt(enc4);
    };

    return output;
  }

  function decode(input) {
    var output = '';
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    while (i < input.length) {
      enc1 = keyStr.indexOf(input.charAt(i++));
      enc2 = keyStr.indexOf(input.charAt(i++));
      enc3 = keyStr.indexOf(input.charAt(i++));
      enc4 = keyStr.indexOf(input.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64) {
        output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
        output = output + String.fromCharCode(chr3);
      }
    }

    return output;
  }

  exports.encode = encode;
  exports.decode = decode;
});
<commit_msg>Add documentation.<commit_after>/**
 * Module definition.
 *
 * Credits:
 *
 * This code is based on code originally written by Tyler Akins <http://rumkin.com/>,
 * as available here:
 *   http://rumkin.com/tools/cipher/js/base64.js
 *
 * Other implementations known derive from (or include verbatim) this lineage
 * include:
 *   https://github.com/ForbesLindesay/base64-encode
 *   https://github.com/ForbesLindesay/base64-decode
 *   https://github.com/metajack/strophejs/blob/master/src/base64.js
 */
define(['exports'],
function(exports) {

  var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

  /**
   * Creates a Base64 encoded ASCII string from a JavaScript string.
   *
   * Attempting to encode a Unicode string may result in invalid output.  To
   * avoid this, first UTF-8 encode the string and then Base64 encode it:
   *
   *     base64.encode(utf8.encode(str));
   *
   * @param {String} input
   * @return {String}
   * @api public
   */
  function encode(input) {
    var output = '';
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    while (i < input.length) {
      chr1 = input.charCodeAt(i++);
      chr2 = input.charCodeAt(i++);
      chr3 = input.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
        enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
        enc4 = 64;
      }

      output = output +
        keyStr.charAt(enc1) + keyStr.charAt(enc2) +
        keyStr.charAt(enc3) + keyStr.charAt(enc4);
    };

    return output;
  }

  /**
   * Decodes a string which has been encoded using Base64 encoding.
   *
   * @param {String} input
   * @return {String}
   * @api public
   */
  function decode(input) {
    var output = '';
    var chr1, chr2, chr3;
    var enc1, enc2, enc3, enc4;
    var i = 0;

    // remove all characters that are not A-Z, a-z, 0-9, +, /, or =
    input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    while (i < input.length) {
      enc1 = keyStr.indexOf(input.charAt(i++));
      enc2 = keyStr.indexOf(input.charAt(i++));
      enc3 = keyStr.indexOf(input.charAt(i++));
      enc4 = keyStr.indexOf(input.charAt(i++));

      chr1 = (enc1 << 2) | (enc2 >> 4);
      chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
      chr3 = ((enc3 & 3) << 6) | enc4;

      output = output + String.fromCharCode(chr1);

      if (enc3 != 64) {
        output = output + String.fromCharCode(chr2);
      }
      if (enc4 != 64) {
        output = output + String.fromCharCode(chr3);
      }
    }

    return output;
  }

  /**
   * Expose functions.
   */
  exports.encode = encode;
  exports.decode = decode;
});
<|endoftext|>


<commit_before>'use strict';

var http = require('http');
var https = require('https');
var path = require('path');
var when = require('when');

var utils = require('./utils');
var Error = require('./Error');

var hasOwn = {}.hasOwnProperty;

var BLACKLISTED_FINGERPRINTS = require('fs').readFileSync(
  path.join(__dirname, '../data/blacklisted_fingerprints'), 'utf8'
).replace(/^\s+|\s+$/g, '').split('\n');

// Provide extension mechanism for Stripe Resource Sub-Classes
StripeResource.extend = utils.protoExtend;

// Expose method-creator & prepared (basic) methods
StripeResource.method = require('./StripeMethod');
StripeResource.BASIC_METHODS = require('./StripeMethod.basic');

/**
 * Encapsulates request logic for a Stripe Resource
 */
function StripeResource(stripe, urlData) {

  this._stripe = stripe;
  this._urlData = urlData || {};

  this.basePath = utils.makeURLInterpolator(stripe.getApiField('basePath'));
  this.path = utils.makeURLInterpolator(this.path);

  if (this.includeBasic) {
    this.includeBasic.forEach(function(methodName) {
      this[methodName] = StripeResource.BASIC_METHODS[methodName];
    }, this);
  }

  this.initialize.apply(this, arguments);

}

StripeResource.prototype = {

  path: '',

  initialize: function() {},

  createFullPath: function(commandPath, urlData) {
    return path.join(
      this.basePath(urlData),
      this.path(urlData),
      typeof commandPath == 'function' ?
        commandPath(urlData) : commandPath
    ).replace(/\\/g, '/'); // ugly workaround for Windows
  },

  createUrlData: function() {
    var urlData = {};
    // Merge in baseData
    for (var i in this._urlData) {
      if (hasOwn.call(this._urlData, i)) {
        urlData[i] = this._urlData[i];
      }
    }
    return urlData;
  },

  createDeferred: function(callback) {
      var deferred = when.defer();

      if (callback) {
        // Callback, if provided, is a simply translated to Promise'esque:
        // (Ensure callback is called outside of promise stack)
        deferred.promise.then(function(res) {
          setTimeout(function(){ callback(null, res) }, 0);
        }, function(err) {
          setTimeout(function(){ callback(err, null); }, 0);
        });
      }

      return deferred;
  },

  _timeoutHandler: function(timeout, req, callback) {
    var self = this;
    return function() {
      var timeoutErr = new Error('ETIMEDOUT');
      timeoutErr.code = 'ETIMEDOUT';

      req._isAborted = true;
      req.abort();

      callback.call(
        self,
        new Error.StripeConnectionError({
          message: 'Request aborted due to timeout being reached (' + timeout + 'ms)',
          detail: timeoutErr
        }),
        null
      );
    }
  },

  _responseHandler: function(req, callback) {
    var self = this;
    return function(res) {
      var response = '';

      res.setEncoding('utf8');
      res.on('data', function(chunk) {
        response += chunk;
      });
      res.on('end', function() {
        try {
          response = JSON.parse(response);
          if (response.error) {
            var err;
            if (res.statusCode === 401) {
              err = new Error.StripeAuthenticationError(response.error);
            } else {
              err = Error.StripeError.generate(response.error);
            }
            return callback.call(self, err, null);
          }
        } catch (e) {
          return callback.call(
            self,
            new Error.StripeAPIError({
              message: 'Invalid JSON received from the Stripe API',
              response: response,
              exception: e
            }),
            null
          );
        }
        callback.call(self, null, response);
      });
    };
  },

  _errorHandler: function(req, callback) {
    var self = this;
    return function(error) {
      if (req._isAborted) return; // already handled
      callback.call(
        self,
        new Error.StripeConnectionError({
          message: 'An error occurred with our connection to Stripe',
          detail: error
        }),
        null
      );
    }
  },

  _request: function(method, path, data, auth, callback) {

    var requestData = utils.stringifyRequestData(data || {});
    var self = this;

    var apiVersion = this._stripe.getApiField('version');
    var headers = {
      // Use specified auth token or use default from this stripe instance:
      'Authorization': auth ?
        'Basic ' + new Buffer(auth + ':').toString('base64') :
        this._stripe.getApiField('auth'),
      'Accept': 'application/json',
      'Content-Type': 'application/x-www-form-urlencoded',
      'Content-Length': requestData.length,
      'User-Agent': 'Stripe/v1 NodeBindings/' + this._stripe.getConstant('PACKAGE_VERSION')
    };

    if (apiVersion) {
      headers['Stripe-Version'] = apiVersion;
    }

    // Grab client-user-agent before making the request:
    this._stripe.getClientUserAgent(function(cua) {
      headers['X-Stripe-Client-User-Agent'] = cua;
      makeRequest();
    });

    function makeRequest() {

      var timeout = self._stripe.getApiField('timeout');

      var req = (
        self._stripe.getApiField('protocol') == 'http' ? http : https
      ).request({
        host: self._stripe.getApiField('host'),
        port: self._stripe.getApiField('port'),
        path: path,
        method: method,
        headers: headers
      });

      req.setTimeout(timeout, self._timeoutHandler(timeout, req, callback));
      req.on('response', self._responseHandler(req, callback));
      req.on('error', self._errorHandler(req, callback));

      req.on('socket', function(socket) {
        socket.on('secureConnect', function() {
          if (BLACKLISTED_FINGERPRINTS.indexOf(socket.getPeerCertificate().fingerprint) > -1) {
            req.abort();
            return callback.call(self,
              new Error.StripeError({
                message: 'Blaclisted SSL Cert fingerprint',
                detail: 'See <link to blog post?>'
              })
            );
          }
          // Send payload; we're safe:
          req.write(requestData);
          req.end();
        });
      });

    }

  }

};

module.exports = StripeResource;
<commit_msg>prettier revoked-ssl err message<commit_after>'use strict';

var http = require('http');
var https = require('https');
var path = require('path');
var when = require('when');

var utils = require('./utils');
var Error = require('./Error');

var hasOwn = {}.hasOwnProperty;

var BLACKLISTED_FINGERPRINTS = require('fs').readFileSync(
  path.join(__dirname, '../data/blacklisted_fingerprints'), 'utf8'
).replace(/^\s+|\s+$/g, '').split('\n');

// Provide extension mechanism for Stripe Resource Sub-Classes
StripeResource.extend = utils.protoExtend;

// Expose method-creator & prepared (basic) methods
StripeResource.method = require('./StripeMethod');
StripeResource.BASIC_METHODS = require('./StripeMethod.basic');

/**
 * Encapsulates request logic for a Stripe Resource
 */
function StripeResource(stripe, urlData) {

  this._stripe = stripe;
  this._urlData = urlData || {};

  this.basePath = utils.makeURLInterpolator(stripe.getApiField('basePath'));
  this.path = utils.makeURLInterpolator(this.path);

  if (this.includeBasic) {
    this.includeBasic.forEach(function(methodName) {
      this[methodName] = StripeResource.BASIC_METHODS[methodName];
    }, this);
  }

  this.initialize.apply(this, arguments);

}

StripeResource.prototype = {

  path: '',

  initialize: function() {},

  createFullPath: function(commandPath, urlData) {
    return path.join(
      this.basePath(urlData),
      this.path(urlData),
      typeof commandPath == 'function' ?
        commandPath(urlData) : commandPath
    ).replace(/\\/g, '/'); // ugly workaround for Windows
  },

  createUrlData: function() {
    var urlData = {};
    // Merge in baseData
    for (var i in this._urlData) {
      if (hasOwn.call(this._urlData, i)) {
        urlData[i] = this._urlData[i];
      }
    }
    return urlData;
  },

  createDeferred: function(callback) {
      var deferred = when.defer();

      if (callback) {
        // Callback, if provided, is a simply translated to Promise'esque:
        // (Ensure callback is called outside of promise stack)
        deferred.promise.then(function(res) {
          setTimeout(function(){ callback(null, res) }, 0);
        }, function(err) {
          setTimeout(function(){ callback(err, null); }, 0);
        });
      }

      return deferred;
  },

  _timeoutHandler: function(timeout, req, callback) {
    var self = this;
    return function() {
      var timeoutErr = new Error('ETIMEDOUT');
      timeoutErr.code = 'ETIMEDOUT';

      req._isAborted = true;
      req.abort();

      callback.call(
        self,
        new Error.StripeConnectionError({
          message: 'Request aborted due to timeout being reached (' + timeout + 'ms)',
          detail: timeoutErr
        }),
        null
      );
    }
  },

  _responseHandler: function(req, callback) {
    var self = this;
    return function(res) {
      var response = '';

      res.setEncoding('utf8');
      res.on('data', function(chunk) {
        response += chunk;
      });
      res.on('end', function() {
        try {
          response = JSON.parse(response);
          if (response.error) {
            var err;
            if (res.statusCode === 401) {
              err = new Error.StripeAuthenticationError(response.error);
            } else {
              err = Error.StripeError.generate(response.error);
            }
            return callback.call(self, err, null);
          }
        } catch (e) {
          return callback.call(
            self,
            new Error.StripeAPIError({
              message: 'Invalid JSON received from the Stripe API',
              response: response,
              exception: e
            }),
            null
          );
        }
        callback.call(self, null, response);
      });
    };
  },

  _errorHandler: function(req, callback) {
    var self = this;
    return function(error) {
      if (req._isAborted) return; // already handled
      callback.call(
        self,
        new Error.StripeConnectionError({
          message: 'An error occurred with our connection to Stripe',
          detail: error
        }),
        null
      );
    }
  },

  _request: function(method, path, data, auth, callback) {

    var requestData = utils.stringifyRequestData(data || {});
    var self = this;

    var apiVersion = this._stripe.getApiField('version');
    var headers = {
      // Use specified auth token or use default from this stripe instance:
      'Authorization': auth ?
        'Basic ' + new Buffer(auth + ':').toString('base64') :
        this._stripe.getApiField('auth'),
      'Accept': 'application/json',
      'Content-Type': 'application/x-www-form-urlencoded',
      'Content-Length': requestData.length,
      'User-Agent': 'Stripe/v1 NodeBindings/' + this._stripe.getConstant('PACKAGE_VERSION')
    };

    if (apiVersion) {
      headers['Stripe-Version'] = apiVersion;
    }

    // Grab client-user-agent before making the request:
    this._stripe.getClientUserAgent(function(cua) {
      headers['X-Stripe-Client-User-Agent'] = cua;
      makeRequest();
    });

    function makeRequest() {

      var timeout = self._stripe.getApiField('timeout');

      var req = (
        self._stripe.getApiField('protocol') == 'http' ? http : https
      ).request({
        host: self._stripe.getApiField('host'),
        port: self._stripe.getApiField('port'),
        path: path,
        method: method,
        headers: headers
      });

      req.setTimeout(timeout, self._timeoutHandler(timeout, req, callback));
      req.on('response', self._responseHandler(req, callback));
      req.on('error', self._errorHandler(req, callback));

      req.on('socket', function(socket) {
        socket.on('secureConnect', function() {
          if (BLACKLISTED_FINGERPRINTS.indexOf(socket.getPeerCertificate().fingerprint) > -1) {
            req.abort();
            return callback.call(self,
              new Error.StripeError({
                message: 'Revoked SSL Certificate',
                detail: 'Invalid server certificate. You tried to connect to a server that has a revoked SSL certificate, which means we cannot securely send data to that server. Please email support@stripe.com if you need help connecting to the correct API server.'
              })
            );
          }
          // Send payload; we're safe:
          req.write(requestData);
          req.end();
        });
      });

    }

  }

};

module.exports = StripeResource;
<|endoftext|>


<commit_before>import { _ } from 'meteor/underscore';
import { Match } from 'meteor/check';
import { BasicCollection } from '../utils/BasicCollection';
import { BasicModel } from '../utils/BasicModel';
import { CardModel } from '../card/cardModel';
import { AttackResultModel } from './attackResultModel';
import { useServantCollection } from '../servant/useServantModel';
import { useEnemyCollection } from '../enemy/useEnemyModel';
import { rTargetUseEnemyId } from '../enemy/useEnemyList';

export class CombatResultModel extends BasicModel {
  get collection() {
    return combatResultCollection;
  }
  get schema() {
    return {
      id: Match.Integer,
      cardList: [CardModel],
      resultList: [AttackResultModel],
      result: {
        damage: {
          expect: Match.Integer,
          best: Match.Integer,
          worst: Match.Integer
        },
        gainNpHash: {
          expect: {
            'servant1': Match.Integer,
            'servant2': Match.Integer,
            'servant3': Match.Integer
          },
          best: {
            'servant1': Match.Integer,
            'servant2': Match.Integer,
            'servant3': Match.Integer
          },
          worst: {
            'servant1': Match.Integer,
            'servant2': Match.Integer,
            'servant3': Match.Integer
          }
        },
        starDrop: {
          expect: Match.Integer,
          best: Match.Integer,
          worst: Match.Integer
        }
      }
    };
  }
  get defaults() {
    return {
      resultList: [],
      result: {
        damage: {
          expect: 0,
          best: 0,
          worst: 0
        },
        gainNpHash: {
          expect: {
            'servant1': 0,
            'servant2': 0,
            'servant3': 0
          },
          best: {
            'servant1': 0,
            'servant2': 0,
            'servant3': 0
          },
          worst: {
            'servant1': 0,
            'servant2': 0,
            'servant3': 0
          }
        },
        starDrop: {
          expect: 0,
          best: 0,
          worst: 0
        }
      }
    };
  }
  computeResult() {
    const cardList = _.clone(this.cardList);
    const resultList = this.resultList;
    const result = this.result;
    // 判斷是否有extra attack即chain boost
    const firstCard = cardList[0];
    const firstCardType = firstCard.type;
    let chainBoost = firstCardType;
    const firstAttackerId = firstCard.useServantId;
    let hasExtraAttack = true;
    _.each(cardList, (cardData) => {
      if (cardData.type !== chainBoost) {
        chainBoost = false;
      }
      if (firstAttackerId !== cardData.useServantId) {
        hasExtraAttack = false;
      }
    });
    // 若有extra card，放進額外的指令卡到cardList中
    if (hasExtraAttack) {
      const cardData = new CardModel({
        id: 3,
        useServantId: firstAttackerId,
        type: 'extra',
        star: 0,
        isWeapon: false,
        sequence: 4
      });
      cardList.push(cardData);
    }
    // 取得當前英靈NP量
    const eachServantNpHash = {};
    useServantCollection.each((useServantData) => {
      eachServantNpHash[useServantData.id] = useServantData.currentNp;
    });
    const servantNpHash = {
      expect: _.clone(eachServantNpHash),
      best: _.clone(eachServantNpHash),
      worst: _.clone(eachServantNpHash)
    };
    // 取得當前瞄準敵人
    const targetEnemyId = rTargetUseEnemyId.get();
    // 取得當前敵人hp
    const eachEnemyHpHash = {};
    useEnemyCollection.each((useEnemyData) => {
      eachEnemyHpHash[useEnemyData.id] = useEnemyData.currentHp;
    });
    const enemyHpHash = {
      expect: _.clone(eachEnemyHpHash),
      best: _.clone(eachEnemyHpHash),
      worst: _.clone(eachEnemyHpHash)
    };
    const interimServantBuffHash = {
      expect: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      },
      best: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      },
      worst: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      }
    };
    const interimEnemyDebuffHash = {
      expect: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      },
      best: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      },
      worst: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      }
    };
    let weaponChainChargeBoost = 0;
    _.each(cardList, (cardData, index, cardList) => {
      const previousCard = cardList[index - 1] || null;
      const attackResultArgs = {
        id: index,
        combatResultData: this,
        firstCardType: firstCardType,
        chainBoost: chainBoost,
        weaponChainChargeBoost: weaponChainChargeBoost,
        cardData: cardData,
        servantNpHash: servantNpHash,
        interimServantBuffHash: interimServantBuffHash,
        canChangeTarget: (
          cardData.isWeapon ||
          ! previousCard ||
          ! previousCard.isWeapon ||
          previousCard.useServantId !== cardData.useServantId
        ),
        targetEnemyId: targetEnemyId,
        enemyHpHash: enemyHpHash,
        interimEnemyDebuffHash: interimEnemyDebuffHash
      };
      if (cardData.isWeapon) {
        weaponChainChargeBoost += 1;
      }
      else {
        weaponChainChargeBoost = 0;
      }
      const attackResultData = new AttackResultModel(attackResultArgs);
      resultList.push(attackResultData);
      attackResultData.computeResult();
      _.each(attackResultData.resultHash, (possibleResultData, resultType) => {
        const possibleResult = possibleResultData.result;
        _.each(possibleResult.servantNpHash, (servantNp, servantId) => {
          servantNpHash[resultType][servantId] = servantNp;
        });
        _.each(possibleResult.enemyHpHash, (enemyHp, enemyId) => {
          enemyHpHash[resultType][enemyId] = enemyHp;
        });
        _.each(possibleResult.interimServantBuffHash, (buffNumber, buffKey) => {
          interimServantBuffHash[resultType][buffKey] = buffNumber;
        });
        _.each(possibleResult.interimEnemyDebuffHash, (debuffNumber, debuffKey) => {
          interimEnemyDebuffHash[resultType][debuffKey] = debuffNumber;
        });

        result.damage[resultType] += possibleResult.damage;
        _.each(possibleResult.gainNpHash, (gainNp, servantId) => {
          result.gainNpHash[resultType]['servant' + servantId] += gainNp;
        });
        result.starDrop[resultType] += possibleResult.starDrop;
      });
    });

    return this;
  }
}

export const combatResultCollection = new BasicCollection();

function generateNewBuffHash() {
  return {
    addArts: 0,
    addBuster: 0,
    addQuick: 0,
    addAttack: 0,
    addWeapon: 0,
    addDamage: 0,
    addCritical: 0,
    addStarDrop: 0,
    addNpGain: 0,
    decreaseDefense: 0,
    addBeHitDamage: 0,
    addSpecialAttribute: [],
    specialBoost: []
  };
}
<commit_msg>修正前一次攻擊為寶具時下一次攻擊未能切換敵人的bug。<commit_after>import { _ } from 'meteor/underscore';
import { Match } from 'meteor/check';
import { BasicCollection } from '../utils/BasicCollection';
import { BasicModel } from '../utils/BasicModel';
import { CardModel } from '../card/cardModel';
import { AttackResultModel } from './attackResultModel';
import { useServantCollection } from '../servant/useServantModel';
import { useEnemyCollection } from '../enemy/useEnemyModel';
import { rTargetUseEnemyId } from '../enemy/useEnemyList';

export class CombatResultModel extends BasicModel {
  get collection() {
    return combatResultCollection;
  }
  get schema() {
    return {
      id: Match.Integer,
      cardList: [CardModel],
      resultList: [AttackResultModel],
      result: {
        damage: {
          expect: Match.Integer,
          best: Match.Integer,
          worst: Match.Integer
        },
        gainNpHash: {
          expect: {
            'servant1': Match.Integer,
            'servant2': Match.Integer,
            'servant3': Match.Integer
          },
          best: {
            'servant1': Match.Integer,
            'servant2': Match.Integer,
            'servant3': Match.Integer
          },
          worst: {
            'servant1': Match.Integer,
            'servant2': Match.Integer,
            'servant3': Match.Integer
          }
        },
        starDrop: {
          expect: Match.Integer,
          best: Match.Integer,
          worst: Match.Integer
        }
      }
    };
  }
  get defaults() {
    return {
      resultList: [],
      result: {
        damage: {
          expect: 0,
          best: 0,
          worst: 0
        },
        gainNpHash: {
          expect: {
            'servant1': 0,
            'servant2': 0,
            'servant3': 0
          },
          best: {
            'servant1': 0,
            'servant2': 0,
            'servant3': 0
          },
          worst: {
            'servant1': 0,
            'servant2': 0,
            'servant3': 0
          }
        },
        starDrop: {
          expect: 0,
          best: 0,
          worst: 0
        }
      }
    };
  }
  computeResult() {
    const cardList = _.clone(this.cardList);
    const resultList = this.resultList;
    const result = this.result;
    // 判斷是否有extra attack即chain boost
    const firstCard = cardList[0];
    const firstCardType = firstCard.type;
    let chainBoost = firstCardType;
    const firstAttackerId = firstCard.useServantId;
    let hasExtraAttack = true;
    _.each(cardList, (cardData) => {
      if (cardData.type !== chainBoost) {
        chainBoost = false;
      }
      if (firstAttackerId !== cardData.useServantId) {
        hasExtraAttack = false;
      }
    });
    // 若有extra card，放進額外的指令卡到cardList中
    if (hasExtraAttack) {
      const cardData = new CardModel({
        id: 3,
        useServantId: firstAttackerId,
        type: 'extra',
        star: 0,
        isWeapon: false,
        sequence: 4
      });
      cardList.push(cardData);
    }
    // 取得當前英靈NP量
    const eachServantNpHash = {};
    useServantCollection.each((useServantData) => {
      eachServantNpHash[useServantData.id] = useServantData.currentNp;
    });
    const servantNpHash = {
      expect: _.clone(eachServantNpHash),
      best: _.clone(eachServantNpHash),
      worst: _.clone(eachServantNpHash)
    };
    // 取得當前瞄準敵人
    const targetEnemyId = rTargetUseEnemyId.get();
    // 取得當前敵人hp
    const eachEnemyHpHash = {};
    useEnemyCollection.each((useEnemyData) => {
      eachEnemyHpHash[useEnemyData.id] = useEnemyData.currentHp;
    });
    const enemyHpHash = {
      expect: _.clone(eachEnemyHpHash),
      best: _.clone(eachEnemyHpHash),
      worst: _.clone(eachEnemyHpHash)
    };
    const interimServantBuffHash = {
      expect: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      },
      best: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      },
      worst: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      }
    };
    const interimEnemyDebuffHash = {
      expect: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      },
      best: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      },
      worst: {
        '1': generateNewBuffHash(),
        '2': generateNewBuffHash(),
        '3': generateNewBuffHash()
      }
    };
    let weaponChainChargeBoost = 0;
    _.each(cardList, (cardData, index, cardList) => {
      const previousCard = cardList[index - 1] || null;
      const attackResultArgs = {
        id: index,
        combatResultData: this,
        firstCardType: firstCardType,
        chainBoost: chainBoost,
        weaponChainChargeBoost: weaponChainChargeBoost,
        cardData: cardData,
        servantNpHash: servantNpHash,
        interimServantBuffHash: interimServantBuffHash,
        canChangeTarget: (
          cardData.isWeapon ||
          (! previousCard) ||
          previousCard.isWeapon ||
          (previousCard.useServantId !== cardData.useServantId)
        ),
        targetEnemyId: targetEnemyId,
        enemyHpHash: enemyHpHash,
        interimEnemyDebuffHash: interimEnemyDebuffHash
      };
      if (cardData.isWeapon) {
        weaponChainChargeBoost += 1;
      }
      else {
        weaponChainChargeBoost = 0;
      }
      const attackResultData = new AttackResultModel(attackResultArgs);
      resultList.push(attackResultData);
      attackResultData.computeResult();
      _.each(attackResultData.resultHash, (possibleResultData, resultType) => {
        const possibleResult = possibleResultData.result;
        _.each(possibleResult.servantNpHash, (servantNp, servantId) => {
          servantNpHash[resultType][servantId] = servantNp;
        });
        _.each(possibleResult.enemyHpHash, (enemyHp, enemyId) => {
          enemyHpHash[resultType][enemyId] = enemyHp;
        });
        _.each(possibleResult.interimServantBuffHash, (buffNumber, buffKey) => {
          interimServantBuffHash[resultType][buffKey] = buffNumber;
        });
        _.each(possibleResult.interimEnemyDebuffHash, (debuffNumber, debuffKey) => {
          interimEnemyDebuffHash[resultType][debuffKey] = debuffNumber;
        });

        result.damage[resultType] += possibleResult.damage;
        _.each(possibleResult.gainNpHash, (gainNp, servantId) => {
          result.gainNpHash[resultType]['servant' + servantId] += gainNp;
        });
        result.starDrop[resultType] += possibleResult.starDrop;
      });
    });

    return this;
  }
}

export const combatResultCollection = new BasicCollection();

function generateNewBuffHash() {
  return {
    addArts: 0,
    addBuster: 0,
    addQuick: 0,
    addAttack: 0,
    addWeapon: 0,
    addDamage: 0,
    addCritical: 0,
    addStarDrop: 0,
    addNpGain: 0,
    decreaseDefense: 0,
    addBeHitDamage: 0,
    addSpecialAttribute: [],
    specialBoost: []
  };
}
<|endoftext|>