<commit_before>// Copyright 2014 Flávio Ribeiro <flavio@bem.tv>.
// All rights reserved.
// Use of this source code is governed by a Apache
// license that can be found in the LICENSE file.

var BaseObject = require('base_object');
var BufferedChannel = require('rtc-bufferedchannel');
var Peer = require('./peer')
var Settings = require('./settings')
var _ = require('underscore')
var log = require('./log');

class Swarm extends BaseObject {
  initialize() {
    this.peers = []
    this.satisfyCandidate = undefined
    this.chunksSent = 0
    this.chokedClients = 0
    this.avgSegmentSize = 0
  }

  size() {
    return this.peers.length
  }

  addPeer(id, dataChannel) {
    log.info("join: " + id)
    var bufferedChannel = BufferedChannel(dataChannel, {calcCharSize: false})
    var peer = new Peer({ident: id, dataChannel: bufferedChannel, swarm: this})
    this.peers.push(peer)
    this.trigger('swarm:sizeupdate', {swarmSize: this.size()})
  }

  removePeer(id) {
    var peer = this.findPeer(id)
    this.peers = _.without(this.peers, peer)
    log.info("quit: " + id + " (remains: " + this.size() + ")")
    this.trigger('swarm:sizeupdate', {swarmSize: this.size()})
  }

  findPeer(id) {
    return _.find(this.peers, function (peer) {
      return (peer.ident === id)
    }, this)
  }

  get partners() {
    var activePeers = _.filter(this.peers, function (p) { return p.active })
    var orderedPeers = _.sortBy(activePeers, function (p) { return p.score }).reverse()
    if (this.peers.length > Settings.maxPartners) {
      return orderedPeers.slice(0, Settings.maxPartners)
    } else {
      return orderedPeers
    }
  }

  sendTo(recipients, command, resource, content='') {
    /* recipients: all, partners or peer ident
    command: interested, contain, request, satisfy */
    log.debug("sending _" + command + "_ to " + recipients)
    if (recipients === 'partners') {
      _.each(this.partners, function(peer) { peer.send(command, resource, content) }, this)
    } else if (recipients === 'all') {
      _.each(this.peers, function(peer) { peer.send(command, resource, content) }, this)
    } else {
      var peer = this.findPeer(recipients)
      peer.send(command, resource, content);
    }
  }

  sendInterested(resource, callbackSuccess, callbackFail) {
    this.externalCallbackFail = callbackFail
    this.externalCallbackSuccess = callbackSuccess
    this.interestedFailID = setTimeout(this.callbackFail.bind(this), this.getTimeoutFor('interested'))
    this.currentResource = resource
    this.sendTo('partners', 'interested', resource)
  }

  chokeReceived(resource) {
    if (this.currentResource === resource) {
      this.chokedClients += 1
      if (this.chokedClients === this.partners.length) {
        log.warn("all partners choked, getting from cdn")
        this.callbackFail()
      }
    }
  }

  containReceived(peerId, resource) {
    if (this.satisfyCandidate || this.currentResource !== resource) return //TODO #46
    if (this.interestedFailID) {
      this.clearInterestedFailInterval()
      this.requestFailID = setTimeout(this.callbackFail.bind(this), this.getTimeoutFor('request'))
    }
    this.satisfyCandidate = peerId
    this.sendTo(this.satisfyCandidate, 'request', resource)
  }

  getTimeoutFor(command) {
    var segmentSize = this.avgSegmentSize > 0? this.avgSegmentSize * 1000: 1000
    if (command === 'interested') {
      return (segmentSize / 4)
    } else if (command === 'request') {
      return (segmentSize / 2)
    }
  }

  resourceReceived(peer, resource, chunk) {
    if (this.satisfyCandidate === peer && this.currentResource === resource) {
      this.externalCallbackSuccess(chunk, "p2p")
      if (this.satisfyCandidate) {
        var successPeer = this.findPeer(this.satisfyCandidate)
        successPeer.score += Settings.points
        log.warn("Adding " + Settings.points + " to " + successPeer.ident + ". Current score: " + successPeer.score)
      }
      this.rebootRoundVars()
      this.clearRequestFailInterval()
    }
  }

  callbackFail() {
    _.each(this.partners, function(peer) {
      peer.score -= Settings.points
      log.warn("Removing " + Settings.points + " from " + peer.ident + ". Current score: " + peer.score)
    }, this)
    this.rebootRoundVars()
    this.clearInterestedFailInterval()
    this.clearRequestFailInterval()
    this.externalCallbackFail()
  }

  rebootRoundVars() {
    this.currentResource = undefined
    this.satisfyCandidate = undefined
    this.chokedClients = 0
  }

  clearInterestedFailInterval() {
    clearInterval(this.interestedFailID)
    this.interestedFailID = 0
  }

  clearRequestFailInterval() {
    clearInterval(this.requestFailID)
    this.requestFailID = 0
  }
}

module.exports = Swarm
<commit_msg>swarm: move getTimeoutFor() position<commit_after>// Copyright 2014 Flávio Ribeiro <flavio@bem.tv>.
// All rights reserved.
// Use of this source code is governed by a Apache
// license that can be found in the LICENSE file.

var BaseObject = require('base_object');
var BufferedChannel = require('rtc-bufferedchannel');
var Peer = require('./peer')
var Settings = require('./settings')
var _ = require('underscore')
var log = require('./log');

class Swarm extends BaseObject {
  initialize() {
    this.peers = []
    this.satisfyCandidate = undefined
    this.chunksSent = 0
    this.chokedClients = 0
    this.avgSegmentSize = 0
  }

  size() {
    return this.peers.length
  }

  addPeer(id, dataChannel) {
    log.info("join: " + id)
    var bufferedChannel = BufferedChannel(dataChannel, {calcCharSize: false})
    var peer = new Peer({ident: id, dataChannel: bufferedChannel, swarm: this})
    this.peers.push(peer)
    this.trigger('swarm:sizeupdate', {swarmSize: this.size()})
  }

  removePeer(id) {
    var peer = this.findPeer(id)
    this.peers = _.without(this.peers, peer)
    log.info("quit: " + id + " (remains: " + this.size() + ")")
    this.trigger('swarm:sizeupdate', {swarmSize: this.size()})
  }

  findPeer(id) {
    return _.find(this.peers, function (peer) {
      return (peer.ident === id)
    }, this)
  }

  get partners() {
    var activePeers = _.filter(this.peers, function (p) { return p.active })
    var orderedPeers = _.sortBy(activePeers, function (p) { return p.score }).reverse()
    if (this.peers.length > Settings.maxPartners) {
      return orderedPeers.slice(0, Settings.maxPartners)
    } else {
      return orderedPeers
    }
  }

  sendTo(recipients, command, resource, content='') {
    /* recipients: all, partners or peer ident
    command: interested, contain, request, satisfy */
    log.debug("sending _" + command + "_ to " + recipients)
    if (recipients === 'partners') {
      _.each(this.partners, function(peer) { peer.send(command, resource, content) }, this)
    } else if (recipients === 'all') {
      _.each(this.peers, function(peer) { peer.send(command, resource, content) }, this)
    } else {
      var peer = this.findPeer(recipients)
      peer.send(command, resource, content);
    }
  }

  sendInterested(resource, callbackSuccess, callbackFail) {
    this.externalCallbackFail = callbackFail
    this.externalCallbackSuccess = callbackSuccess
    this.interestedFailID = setTimeout(this.callbackFail.bind(this), this.getTimeoutFor('interested'))
    this.currentResource = resource
    this.sendTo('partners', 'interested', resource)
  }

  chokeReceived(resource) {
    if (this.currentResource === resource) {
      this.chokedClients += 1
      if (this.chokedClients === this.partners.length) {
        log.warn("all partners choked, getting from cdn")
        this.callbackFail()
      }
    }
  }

  containReceived(peerId, resource) {
    if (this.satisfyCandidate || this.currentResource !== resource) return //TODO #46
    if (this.interestedFailID) {
      this.clearInterestedFailInterval()
      this.requestFailID = setTimeout(this.callbackFail.bind(this), this.getTimeoutFor('request'))
    }
    this.satisfyCandidate = peerId
    this.sendTo(this.satisfyCandidate, 'request', resource)
  }

  resourceReceived(peer, resource, chunk) {
    if (this.satisfyCandidate === peer && this.currentResource === resource) {
      this.externalCallbackSuccess(chunk, "p2p")
      if (this.satisfyCandidate) {
        var successPeer = this.findPeer(this.satisfyCandidate)
        successPeer.score += Settings.points
        log.warn("Adding " + Settings.points + " to " + successPeer.ident + ". Current score: " + successPeer.score)
      }
      this.rebootRoundVars()
      this.clearRequestFailInterval()
    }
  }

  callbackFail() {
    _.each(this.partners, function(peer) {
      peer.score -= Settings.points
      log.warn("Removing " + Settings.points + " from " + peer.ident + ". Current score: " + peer.score)
    }, this)
    this.rebootRoundVars()
    this.clearInterestedFailInterval()
    this.clearRequestFailInterval()
    this.externalCallbackFail()
  }

  getTimeoutFor(command) {
    var segmentSize = this.avgSegmentSize > 0? this.avgSegmentSize * 1000: 1000
    if (command === 'interested') {
      return (segmentSize / 4)
    } else if (command === 'request') {
      return (segmentSize / 2)
    }
  }

  rebootRoundVars() {
    this.currentResource = undefined
    this.satisfyCandidate = undefined
    this.chokedClients = 0
  }

  clearInterestedFailInterval() {
    clearInterval(this.interestedFailID)
    this.interestedFailID = 0
  }

  clearRequestFailInterval() {
    clearInterval(this.requestFailID)
    this.requestFailID = 0
  }
}

module.exports = Swarm
<|endoftext|>


<commit_before>var w = Ti.UI.currentWindow;
var v = Ti.UI.createView();
var tv = Ti.UI.createTableView({
	top:0,
	height:280,
	borderWidth:1,
	borderColor:"black"
});
var l = Ti.UI.createLabel({
	text:"running",
	width:"auto",
	height:"auto",
	bottom:15
});
v.add(tv);
v.add(l);
w.add(v);

var count = 500;
var ts = new Date;

var data = [];

for (var c=0;c<count;c++)
{
	var row = Ti.UI.createTableViewRow({title:"Row "+(c+1)});
	data[c] = row;
}

tv.data = data;

var ts2 = new Date;
var duration = ts2.getTime() - ts.getTime();
var each = count / duration;
l.text = "Executed: "+count+" iterations\nTook: " + duration +" ms\n" + each.toFixed(2) + " ms/row";
<commit_msg>divide duration by count to get the per row perf time [#2063]<commit_after>var w = Ti.UI.currentWindow;
var v = Ti.UI.createView();
var tv = Ti.UI.createTableView({
	top:0,
	height:280,
	borderWidth:1,
	borderColor:"black"
});
var l = Ti.UI.createLabel({
	text:"running",
	width:"auto",
	height:"auto",
	bottom:15
});
v.add(tv);
v.add(l);
w.add(v);

var count = 500;
var ts = new Date;

var data = [];

for (var c=0;c<count;c++)
{
	var row = Ti.UI.createTableViewRow({title:"Row "+(c+1)});
	data[c] = row;
}

tv.data = data;

var ts2 = new Date;
var duration = ts2.getTime() - ts.getTime();
var each = duration / count;
l.text = "Executed: "+count+" iterations\nTook: " + duration +" ms\n" + each.toFixed(2) + " ms/row";
<|endoftext|>


<commit_before>var net = require('net');
var os = require('os');
var tcpm = require('./tcpm.js');
var udpm = require('./udpm.js');
var pool = require('./pool.js');

prepare();

// 【函数】预处理用户参数
function prepare() {
    var eh = get_external_host();
    var options_default = {
        lh: eh,
        lp: '1080',
        rh: 'localhost',
        rp: '1080',
        eh: eh
    };
    var argv = process.argv.splice(2);
    for(var key in argv) {
        var kv = argv[key].split('=');
        if(kv.length === 2) {
            options_default[kv[0]] = kv[1];
        }
    }
    console.log(options_default);
    start({
        host: options_default.lh,
        port: parseInt(options_default.lp)
    }, {
        host: options_default.rh,
        port: parseInt(options_default.rp)
    }, options_default.eh);

    function get_external_host () {
        var list = os.networkInterfaces()
        for(var key1 in list) {
            for(var key2 in list[key1]) {
                var info = list[key1][key2];
                if(info.family === 'IPv4' && info.internal === false && info.address !== '127.0.0.1') {
                    return info.address;
                }
            }
        }
        return '0.0.0.0';
    }
}

// 【函数】启动
function start (local_options, remote_options, external_host) {

    // create tcp connection manager
    var tcm = new tcpm_manager(remote_options, external_host);
    // create server
    var server = net.createServer(function(c) {
        tcm.add(c);
    });
    server.listen(local_options, function() {});
    server.on('error', function () {});
    server.on('close', function () {
        tcm.close();
    });
}

// tcp连接管理类
function tcpm_manager (remote_options, external_host) {
    var self = this;

    self.remote_options = remote_options;
    self.external_host = external_host;
    self.new_pool = new pool(remote_options);
    self.mappings = {}
}
tcpm_manager.prototype.add = function (c) {
    var self = this;

    var key = c.remoteAddress + ':' + c.remotePort;
    if(self.mappings[key]) {
        self.mappings[key].close();
    }
    // create tcp mapping
    var remote_socket = self.new_pool.get();
    var new_udpm = new udpm(self.remote_options.host, self.external_host);
    self.mappings[key] = new tcpm(c, remote_socket, new_udpm);
    self.mappings[key].on('close', function () {
        delete self.mappings[key];
    });
}
tcpm_manager.prototype.close = function () {
    var self = this;
    for(var key in self.mappings) {
        self.mappings[key].close();
    }
}<commit_msg>准备修改 cool5.js<commit_after>// [config]
// local  -> {host: <string>, port: <number>}
// remote -> {host: <string>, port: <number>}

var net = require('net');
var os = require('os');
var config = require('./config.js');
var log = require('./log.js');
var tcpm = require('./tcpm.js');
var udpm = require('./udpm.js');
var pool = require('./pool.js');

prepare();

// 【函数】预处理用户参数
function prepare() {
    var eh = get_external_host();
    var options_default = {
        lh: eh,
        lp: '1080',
        rh: 'localhost',
        rp: '1080',
        eh: eh
    };
    var argv = process.argv.splice(2);
    for(var key in argv) {
        var kv = argv[key].split('=');
        if(kv.length === 2) {
            options_default[kv[0]] = kv[1];
        }
    }
    console.log(options_default);
    start({
        host: options_default.lh,
        port: parseInt(options_default.lp)
    }, {
        host: options_default.rh,
        port: parseInt(options_default.rp)
    }, options_default.eh);

    function get_external_host () {
        var list = os.networkInterfaces()
        for(var key1 in list) {
            for(var key2 in list[key1]) {
                var info = list[key1][key2];
                if(info.family === 'IPv4' && info.internal === false && info.address !== '127.0.0.1') {
                    return info.address;
                }
            }
        }
        return '0.0.0.0';
    }
}

// 【函数】启动
function start (local_options, remote_options, external_host) {

    // create tcp connection manager
    var tcm = new tcpm_manager(remote_options, external_host);
    // create server
    var server = net.createServer(function(c) {
        tcm.add(c);
    });
    server.listen(local_options, function() {});
    server.on('error', function () {});
    server.on('close', function () {
        tcm.close();
    });
}

// tcp连接管理类
function tcpm_manager (remote_options, external_host) {
    var self = this;

    self.remote_options = remote_options;
    self.external_host = external_host;
    self.new_pool = new pool(remote_options);
    self.mappings = {}
}
tcpm_manager.prototype.add = function (c) {
    var self = this;

    var key = c.remoteAddress + ':' + c.remotePort;
    if(self.mappings[key]) {
        self.mappings[key].close();
    }
    // create tcp mapping
    var remote_socket = self.new_pool.get();
    var new_udpm = new udpm(self.remote_options.host, self.external_host);
    self.mappings[key] = new tcpm(c, remote_socket, new_udpm);
    self.mappings[key].on('close', function () {
        delete self.mappings[key];
    });
}
tcpm_manager.prototype.close = function () {
    var self = this;
    for(var key in self.mappings) {
        self.mappings[key].close();
    }
}<|endoftext|>


<commit_before>function hello(name) {
	return add_one('Hello'+name);
}
function add_one(argument) {
	return argument+'_one';
}
alert(hello('John Doe')

(function( $ ){

  $.fn.maxHeight = function() {

    var max = 0;

    this.each(function() {
      max = Math.max( max, $(this).height() );
    });

    return maxed;
  };
})( jQuery );
$('div').maxHeight();
alerts('test');<commit_msg>Removed javascript error from test file: JSC_PARSE_ERROR - Parse error. missing ) after argument list - Line 21<commit_after>function hello(name) {
	return add_one('Hello'+name);
}
function add_one(argument) {
	return argument+'_one';
}
alert(hello('John Doe'));

(function( $ ){

  $.fn.maxHeight = function() {

    var max = 0;

    this.each(function() {
      max = Math.max( max, $(this).height() );
    });

    return maxed;
  }

})( jQuery );
$('div').maxHeight();
alerts('test');<|endoftext|>


<commit_before>import MemberManager from './MemberManager';

export class ShapeManager {
  constructor(question, chain, path, name, args) {
    this.question = question;
    this.chain = chain;
    this.path = path;
    this.name = name;
    this.args = args;
    this.question.set(this.path, {});
  }

  init(values) {
    return this._set(values, 'init');
  }

  set(values) {
    return this._set(values, 'set');
  }

  _set(values, method) {
    this.question.set(this.path, {});
    for (let k in values) {
      if (values.hasOwnProperty(k)) {
        if (!this.args.hasOwnProperty(k)) {
          throw new Error(`Key '${k}' is not valid for object '${this.name}'`);
        }
        let path = this.path.concat([k]);
        if (this.chain[k] === undefined) {
          this.chain[k] = new MemberManager(this.question, this, path, k, this.args[k]);
        }
        this.chain[k][method](values[k]);
      }
    }
  }

  _validate() {
    for (let k in this) {
      if (this.hasOwnProperty(k) && this[k] instanceof MemberManager && this[k].isBound) {
        this[k]._validate();
      }
    }
    this.errors = [];
  }
}
<commit_msg>Fix ShapeManager chaining<commit_after>import MemberManager from './MemberManager';

export class ShapeManager {
  constructor(question, chain, path, name, args) {
    this.question = question;
    this.chain = chain;
    this.path = path;
    this.name = name;
    this.args = args;
    this.question.set(this.path, {});
  }

  init(values) {
    return this._set(values, 'init');
  }

  set(values) {
    return this._set(values, 'set');
  }

  _set(values, method) {
    this.question.set(this.path, {});
    for (let k in values) {
      if (values.hasOwnProperty(k)) {
        if (!this.args.hasOwnProperty(k)) {
          throw new Error(`Key '${k}' is not valid for object '${this.name}'`);
        }
        let path = this.path.concat([k]);
        if (this[k] === undefined) {
          this[k] = new MemberManager(this.question, this, path, k, this.args[k]);
        }
        this.chain[k] = this[k];
        this[k][method](values[k]);
      }
    }
  }

  _validate() {
    for (let k in this) {
      if (this.hasOwnProperty(k) && this[k] instanceof MemberManager && this[k].isBound) {
        this[k]._validate();
      }
    }
    this.errors = [];
  }
}
<|endoftext|>


<commit_before>'use strict';

const parseSDF = require('sdf-parser');
const Papa = require('papaparse');

const getMoleculeCreators = require('./moleculeCreators');

module.exports = function (OCL) {
    const Molecule = OCL.Molecule;

    const moleculeCreators = getMoleculeCreators(Molecule);

    const defaultDBOptions = {
        length: 0,
        computeProperties: false
    };

    const defaultSDFOptions = {
        onStep: function (/*current, total*/) {
            // empty function
        }
    };

    const defaultCSVOptions = {
        header: true,
        dynamicTyping: true,
        skipEmptyLines: true,
        onStep: function (/*current, total*/) {
            // empty function
        }
    };

    const defaultSearchOptions = {
        format: 'oclid',
        mode: 'substructure',
        limit: 0
    };

    class MoleculeDB {
        constructor(options) {
            options = Object.assign({}, defaultDBOptions, options);
            this.data = new Array(options.length);
            this.molecules = new Array(options.length);
            this.statistics = null;
            this.length = 0;
            this.computeProperties = !!options.computeProperties;
            this.searcher = null;
        }

        static parseSDF(sdf, options) {
            if (typeof sdf !== 'string') {
                throw new TypeError('sdf must be a string');
            }
            options = Object.assign({}, defaultSDFOptions, options);
            return new Promise(function (resolve, reject) {
                const parsed = parseSDF(sdf);
                const molecules = parsed.molecules;
                const db = new MoleculeDB(options);
                db.statistics = parsed.statistics;
                let i = 0;
                const l = molecules.length;
                parseNext();
                function parseNext() {
                    if (i === l) {
                        resolve(db);
                        return;
                    }
                    try {
                        db.push(Molecule.fromMolfile(molecules[i].molfile), molecules[i]);
                    } catch (e) {
                        reject(e);
                        return;
                    }
                    options.onStep(++i, l);
                    setImmediate(parseNext);
                }
            });
        }

        static parseCSV(csv, options) {
            if (typeof csv !== 'string') {
                throw new TypeError('csv must be a string');
            }
            options = Object.assign({}, defaultCSVOptions, options);
            return new Promise(function (resolve, reject) {
                const parsed = Papa.parse(csv, options);
                const fields = parsed.meta.fields;
                const stats = new Array(fields.length);
                const firstElement = parsed.data[0];
                let datatype, datafield;
                for (let i = 0; i < fields.length; i++) {
                    stats[i] = {
                        label: fields[i],
                        isNumeric: typeof firstElement[fields[i]] === 'number'
                    };
                    const lowerField = fields[i].toLowerCase();
                    if (moleculeCreators.has(lowerField)) {
                        datatype = moleculeCreators.get(lowerField);
                        datafield = fields[i];
                    }
                }
                if (!datatype) {
                    throw new Error('this document does not contain any molecule field');
                }
                const db = new MoleculeDB(options);
                db.statistics = stats;

                let i = 0;
                const l = parsed.data.length;
                parseNext();
                function parseNext() {
                    if (i === l) {
                        resolve(db);
                        return;
                    }
                    try {
                        db.push(datatype(parsed.data[i][datafield]), parsed.data[i]);
                    } catch (e) {
                        reject(e);
                        return;
                    }
                    options.onStep(++i, l);
                    setImmediate(parseNext);
                }
            });
        }

        push(molecule, data) {
            if (data === undefined) data = {};
            this.molecules[this.length] = molecule;
            // ensure helper arrays needed for substructure search
            molecule.ensureHelperArrays(3);
            let molecularFormula;
            if (!molecule.index) {
                molecule.index = molecule.getIndex();
            }
            if (!molecule.idcode) {
                molecule.idcode = molecule.getIDCode();
            }
            if (!molecule.mw) {
                molecularFormula = molecule.getMolecularFormula();
                molecule.mw = molecularFormula.relativeWeight;
            }
            this.data[this.length++] = data;
            if (this.computeProperties) {
                if (!molecularFormula) {
                    molecularFormula = molecule.getMolecularFormula();
                }
                const properties = new OCL.MoleculeProperties(molecule);
                data.properties = {
                    absoluteWeight: molecularFormula.absoluteWeight,
                    relativeWeight: molecule.mw,
                    formula: molecularFormula.formula,
                    acceptorCount: properties.acceptorCount,
                    donorCount: properties.donorCount,
                    logP: properties.logP,
                    logS: properties.logS,
                    polarSurfaceArea: properties.polarSurfaceArea,
                    rotatableBondCount: properties.rotatableBondCount,
                    stereoCenterCount: properties.stereoCenterCount
                };
            }
        }

        search(query, options) {
            options = Object.assign({}, defaultSearchOptions, options);

            if (typeof query === 'string') {
                query = moleculeCreators.get(options.format.toLowerCase())(query);
            } else if (!(query instanceof Molecule)) {
                throw new TypeError('toSearch must be a Molecule or string');
            }

            let result;
            switch (options.mode.toLowerCase()) {
                case 'exact':
                    result = this.exactSearch(query, options.limit);
                    break;
                case 'substructure':
                    result = this.subStructureSearch(query, options.limit);
                    break;
                case 'similarity':
                    result = this.similaritySearch(query, options.limit);
                    break;
                default:
                    throw new Error('unknown search mode: ' + options.mode);
            }
            return result;
        }

        exactSearch(query, limit) {
            const queryIdcode = query.getIDCode();
            const result = new MoleculeDB();
            limit = limit || Number.MAX_SAFE_INTEGER;
            for (let i = 0; i < this.length; i++) {
                if (this.molecules[i].idcode === queryIdcode) {
                    result.push(this.molecules[i], this.data[i]);
                    if (result.length >= limit) break;
                }
            }
            return result;
        }

        subStructureSearch(query, limit) {
            let needReset = false;
            if (!query.isFragment()) {
                needReset = true;
                query.setFragment(true);
            }

            const queryIndex = query.getIndex();
            const queryMW = query.getMolecularFormula().relativeWeight;
            const searcher = this.getSearcher();

            searcher.setFragment(query, queryIndex);
            const searchResult = [];
            for (let i = 0; i < this.length; i++) {
                searcher.setMolecule(this.molecules[i], this.molecules[i].index);
                if (searcher.isFragmentInMolecule()) {
                    searchResult.push([this.molecules[i], i]);
                }
            }
            searchResult.sort(function (a, b) {
                return Math.abs(queryMW - a[0].mw) - Math.abs(queryMW - b[0].mw);
            });

            const length = Math.min(limit || searchResult.length, searchResult.length);
            const result = new MoleculeDB({length: length});
            for (let i = 0; i < length; i++) {
                result.push(this.molecules[searchResult[i][1]], this.data[searchResult[i][1]]);
            }

            if (needReset) {
                query.setFragment(false);
            }
            return result;
        }

        similaritySearch(query, limit) {
            const queryIndex = query.getIndex();
            const queryMW = query.getMolecularFormula().relativeWeight;
            const queryIDCode = query.getIDCode();

            const searchResult = new Array(this.length);
            let similarity;
            for (let i = 0; i < this.length; i++) {
                if (this.molecules[i].idcode === queryIDCode) {
                    similarity = 1e10;
                } else {
                    similarity = OCL.SSSearcherWithIndex.getSimilarityTanimoto(queryIndex, this.molecules[i].index)
                        * 100000 - Math.abs(queryMW - this.molecules[i].mw) / 1000;
                }
                searchResult[i] = [similarity, i];
            }
            searchResult.sort(function (a, b) {
                return b[0] - a[0];
            });

            const length = Math.min(limit || searchResult.length, searchResult.length);
            const result = new MoleculeDB({length: length});
            for (let i = 0; i < length; i++) {
                result.push(this.molecules[searchResult[i][1]], this.data[searchResult[i][1]]);
            }
            return result;
        }

        getSearcher() {
            return this.searcher || (this.searcher = new OCL.SSSearcherWithIndex());
        }
    }

    return MoleculeDB;
};
<commit_msg>use MW from exact molecule<commit_after>'use strict';

const parseSDF = require('sdf-parser');
const Papa = require('papaparse');

const getMoleculeCreators = require('./moleculeCreators');

module.exports = function (OCL) {
    const cHelperRings = OCL.Molecule.cHelperRings;
    const Molecule = OCL.Molecule;

    const moleculeCreators = getMoleculeCreators(Molecule);

    const defaultDBOptions = {
        length: 0,
        computeProperties: false
    };

    const defaultSDFOptions = {
        onStep: function (/*current, total*/) {
            // empty function
        }
    };

    const defaultCSVOptions = {
        header: true,
        dynamicTyping: true,
        skipEmptyLines: true,
        onStep: function (/*current, total*/) {
            // empty function
        }
    };

    const defaultSearchOptions = {
        format: 'oclid',
        mode: 'substructure',
        limit: 0
    };

    class MoleculeDB {
        constructor(options) {
            options = Object.assign({}, defaultDBOptions, options);
            this.data = new Array(options.length);
            this.molecules = new Array(options.length);
            this.statistics = null;
            this.length = 0;
            this.computeProperties = !!options.computeProperties;
            this.searcher = null;
        }

        static parseSDF(sdf, options) {
            if (typeof sdf !== 'string') {
                throw new TypeError('sdf must be a string');
            }
            options = Object.assign({}, defaultSDFOptions, options);
            return new Promise(function (resolve, reject) {
                const parsed = parseSDF(sdf);
                const molecules = parsed.molecules;
                const db = new MoleculeDB(options);
                db.statistics = parsed.statistics;
                let i = 0;
                const l = molecules.length;
                parseNext();
                function parseNext() {
                    if (i === l) {
                        resolve(db);
                        return;
                    }
                    try {
                        db.push(Molecule.fromMolfile(molecules[i].molfile), molecules[i]);
                    } catch (e) {
                        reject(e);
                        return;
                    }
                    options.onStep(++i, l);
                    setImmediate(parseNext);
                }
            });
        }

        static parseCSV(csv, options) {
            if (typeof csv !== 'string') {
                throw new TypeError('csv must be a string');
            }
            options = Object.assign({}, defaultCSVOptions, options);
            return new Promise(function (resolve, reject) {
                const parsed = Papa.parse(csv, options);
                const fields = parsed.meta.fields;
                const stats = new Array(fields.length);
                const firstElement = parsed.data[0];
                let datatype, datafield;
                for (let i = 0; i < fields.length; i++) {
                    stats[i] = {
                        label: fields[i],
                        isNumeric: typeof firstElement[fields[i]] === 'number'
                    };
                    const lowerField = fields[i].toLowerCase();
                    if (moleculeCreators.has(lowerField)) {
                        datatype = moleculeCreators.get(lowerField);
                        datafield = fields[i];
                    }
                }
                if (!datatype) {
                    throw new Error('this document does not contain any molecule field');
                }
                const db = new MoleculeDB(options);
                db.statistics = stats;

                let i = 0;
                const l = parsed.data.length;
                parseNext();
                function parseNext() {
                    if (i === l) {
                        resolve(db);
                        return;
                    }
                    try {
                        db.push(datatype(parsed.data[i][datafield]), parsed.data[i]);
                    } catch (e) {
                        reject(e);
                        return;
                    }
                    options.onStep(++i, l);
                    setImmediate(parseNext);
                }
            });
        }

        push(molecule, data) {
            if (data === undefined) data = {};
            this.molecules[this.length] = molecule;
            // ensure helper arrays needed for substructure search
            molecule.ensureHelperArrays(cHelperRings);
            let molecularFormula;
            if (!molecule.index) {
                molecule.index = molecule.getIndex();
            }
            if (!molecule.idcode) {
                molecule.idcode = molecule.getIDCode();
            }
            if (!molecule.mw) {
                molecularFormula = molecule.getMolecularFormula();
                molecule.mw = molecularFormula.relativeWeight;
            }
            this.data[this.length++] = data;
            if (this.computeProperties) {
                if (!molecularFormula) {
                    molecularFormula = molecule.getMolecularFormula();
                }
                const properties = new OCL.MoleculeProperties(molecule);
                data.properties = {
                    absoluteWeight: molecularFormula.absoluteWeight,
                    relativeWeight: molecule.mw,
                    formula: molecularFormula.formula,
                    acceptorCount: properties.acceptorCount,
                    donorCount: properties.donorCount,
                    logP: properties.logP,
                    logS: properties.logS,
                    polarSurfaceArea: properties.polarSurfaceArea,
                    rotatableBondCount: properties.rotatableBondCount,
                    stereoCenterCount: properties.stereoCenterCount
                };
            }
        }

        search(query, options) {
            options = Object.assign({}, defaultSearchOptions, options);

            if (typeof query === 'string') {
                query = moleculeCreators.get(options.format.toLowerCase())(query);
            } else if (!(query instanceof Molecule)) {
                throw new TypeError('toSearch must be a Molecule or string');
            }

            let result;
            switch (options.mode.toLowerCase()) {
                case 'exact':
                    result = this.exactSearch(query, options.limit);
                    break;
                case 'substructure':
                    result = this.subStructureSearch(query, options.limit);
                    break;
                case 'similarity':
                    result = this.similaritySearch(query, options.limit);
                    break;
                default:
                    throw new Error('unknown search mode: ' + options.mode);
            }
            return result;
        }

        exactSearch(query, limit) {
            const queryIdcode = query.getIDCode();
            const result = new MoleculeDB();
            limit = limit || Number.MAX_SAFE_INTEGER;
            for (let i = 0; i < this.length; i++) {
                if (this.molecules[i].idcode === queryIdcode) {
                    result.push(this.molecules[i], this.data[i]);
                    if (result.length >= limit) break;
                }
            }
            return result;
        }

        subStructureSearch(query, limit) {
            let needReset = false;

            if (!query.isFragment()) {
                needReset = true;
                query.setFragment(true);
            }

            const queryMW = getMW(query);

            const queryIndex = query.getIndex();
            const searcher = this.getSearcher();

            searcher.setFragment(query, queryIndex);
            const searchResult = [];
            for (let i = 0; i < this.length; i++) {
                searcher.setMolecule(this.molecules[i], this.molecules[i].index);
                if (searcher.isFragmentInMolecule()) {
                    searchResult.push([this.molecules[i], i]);
                }
            }
            searchResult.sort(function (a, b) {
                return Math.abs(queryMW - a[0].mw) - Math.abs(queryMW - b[0].mw);
            });

            const length = Math.min(limit || searchResult.length, searchResult.length);
            const result = new MoleculeDB({length: length});
            for (let i = 0; i < length; i++) {
                result.push(this.molecules[searchResult[i][1]], this.data[searchResult[i][1]]);
            }

            if (needReset) {
                query.setFragment(false);
            }
            return result;
        }

        similaritySearch(query, limit) {
            const queryIndex = query.getIndex();

            const queryMW = getMW(query);
            const queryIDCode = query.getIDCode();

            const searchResult = new Array(this.length);
            let similarity;
            for (let i = 0; i < this.length; i++) {
                if (this.molecules[i].idcode === queryIDCode) {
                    similarity = 1e10;
                } else {
                    similarity = OCL.SSSearcherWithIndex.getSimilarityTanimoto(queryIndex, this.molecules[i].index)
                        * 100000 - Math.abs(queryMW - this.molecules[i].mw) / 1000;
                }
                searchResult[i] = [similarity, i];
            }
            searchResult.sort(function (a, b) {
                return b[0] - a[0];
            });

            const length = Math.min(limit || searchResult.length, searchResult.length);
            const result = new MoleculeDB({length: length});
            for (let i = 0; i < length; i++) {
                result.push(this.molecules[searchResult[i][1]], this.data[searchResult[i][1]]);
            }
            return result;
        }

        getSearcher() {
            return this.searcher || (this.searcher = new OCL.SSSearcherWithIndex());
        }
    }

    return MoleculeDB;
};

function getMW(query) {
    let copy = query.getCompactCopy();
    copy.setFragment(false);
    return copy.getMolecularFormula().relativeWeight;
}
<|endoftext|>


<commit_before>/* Helpers for debuging */

var debug = module.exports = {};

Object.defineProperty(debug, '__stack', {
	get: function(){
		var orig = Error.prepareStackTrace;
		try {
			Error.prepareStackTrace = function(_, stack){ return stack; };
			var err = new Error();
			Error.captureStackTrace(err, arguments.callee);
			var stack = err.stack;
		} finally {
			Error.prepareStackTrace = orig;
		}
		return stack;
	}
});

Object.defineProperty(debug, '__line', {
	get: function(){
		return debug.__stack[1].getLineNumber();
	}
});

debug.isProduction = function () {
    return (prosess.env.NODE_ENV === "production");
}

debug.log = function () {
    if(!debug.isProduction()) {
        var args = Array.prototype.slice.call(arguments);

        util.debug.apply(util, args);
    }
}

/* EOF */
<commit_msg>debuggia<commit_after>/* Helpers for debuging */

var debug = module.exports = {};
var util = require("util");

Object.defineProperty(debug, '__stack', {
	get: function(){
		var orig = Error.prepareStackTrace;
		try {
			Error.prepareStackTrace = function(_, stack){ return stack; };
			var err = new Error();
			Error.captureStackTrace(err, arguments.callee);
			var stack = err.stack;
		} finally {
			Error.prepareStackTrace = orig;
		}
		return stack;
	}
});

Object.defineProperty(debug, '__line', {
	get: function(){
		return debug.__stack[1].getLineNumber();
	}
});

debug.isProduction = function () {
    return (process.env.NODE_ENV === "production");
}

debug.log = function () {
    if(!debug.isProduction()) {
        var args = Array.prototype.slice.call(arguments);

        util.debug.apply(util, args);
    }
}

/* EOF */
<|endoftext|>


<commit_before>/**
 * Dense - Device pixel ratio aware images
 *
 * @link    http://dense.rah.pw
 * @license MIT
 */

/*
 * Copyright (C) 2013 Jukka Svahn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @name jQuery
 * @class
 */

/**
 * @name fn
 * @class
 * @memberOf jQuery
 */

;(function (factory)
{
	if (typeof define === 'function' && define.amd)
	{
		define(['jquery'], factory);
	}
	else
	{
		factory(jQuery);
	}
}(function ($)
{
    /**
     * An array of checked image URLs.
     */

    var pathStack = [],

    /**
     * Methods.
     */

    methods = {},

    /**
     * Regular expression to check whether the URL has a protocol.
     *
     * Is used to check whether the image URL is external.
     */

    regexProtocol = /^https?:\/\//,

    /**
     * Regular expression that split extensions from the file.
     *
     * Is used to inject the DPR suffix to the name.
     */

    regexSuffix = /\.\w+$/,

    /**
     * Device pixel ratio.
     */

    devicePixelRatio,

    /**
     * An array of accepted content-types.
     *
     * Basically contains an array of raster image formats.
     */

    acceptedTypes =
    [
        'image/jpg',
        'image/jpeg',
        'image/png',
        'image/gif',
        'image/bmp'
    ],

    /**
     * Skipped image file extensions.
     *
     * Vectors don't need automatic pixel ratio support.
     */

    skipExtensions =
    [
        'svg'
    ];

    /**
     * Init is the default method responsible for rendering
     * a pixel-ratio-aware images.
     *
     * This method is used to select the images that
     * should display retina-size images on high pixel ratio
     * devices. Dense defaults to the init method if no
     * method is specified.
     *
     * When attached to an image, the correct image variation is
     * selected based on the device's pixel ratio. If the image element
     * defines data-{ratio}x attributes (e.g. data-1x, data-2x, data-3x),
     * the most appropriate of those is selected.
     *
     * If no data-ratio attributes are defined, the retina image is
     * constructed from the src attribute.
     * The searched high pixel ratio images follows
     * a {imageName}_{ratio}x.{ext} naming convention.
     * For an image found in /path/to/images/image.jpg, the 2x retina
     * image would be looked from /path/to/images/image_2x.jpg.
     *
     * When image is constructed from the src, the image existance is
     * verified using HTTP HEAD request. The check makes sure no
     * HTTP error code is returned, and that the received content-type
     * is either image/jpg, image/png,
     * image/gif or image/bmp. Vector image
     * formats, like svg, are skipped.
     *
     * This method can also be used to load image in semi-lazy fashion,
     * and avoid larger extra HTTP requests due to retina replacements.
     * The data-1x attribute can be used to supstitute the src, making
     * sure the browser doesn't try to download the normal image variation
     * before the JavaScript driven behaviour kicks in.
     *
     * @param    {Object}  [options={}]                  Options
     * @param    {Boolean} [options.ping=true]           A prefix added to the generated links
     * @param    {String}  [options.dimensions=preserve] What to do with the width and height attributes. Either update, remove or preserve
     * @return   {Object}  this
     * @method   init
     * @memberof jQuery.fn.dense
     * @fires    jQuery.fn.dense#dense-retina-loaded
     * @example
     * $('img.retina').dense({
     *  'ping'      : false,
     *  'dimension' : true
     * });
     */

    methods.init = function (options)
    {
        options = $.extend({
            ping       : true,
            dimensions : 'preserve'
        }, options);

        this.filter('img').not('.dense').addClass('dense dense-loading').each(function ()
        {
            var $this = $(this),
                image = methods.getImageAttribute.call(this),
                originalImage = $this.attr('src'),
                ping = false,
                updateImage;

            if (!image)
            {
                if (!originalImage || devicePixelRatio == 1 || $.inArray(image.split('.').pop().split(/[\?\#]/).shift(), skipExtensions))
                {
                    return;
                }

                image = originalImage.replace(regexSuffix, function (extension)
                {
                    return '_' + devicePixelRatio + 'x' + extension;
                });

                ping = options.ping && $.inArray(image, pathStack) === -1 && (regexProtocol.test(image) === false || image.indexOf('://' + document.domain) !== -1);
            }

            updateImage = function ()
            {
                var readyImage = function ()
                {
                    $this.removeClass('dense-loading').addClass('dense-ready').trigger('dense-retina-loaded');
                };

                $this.attr('src', image).data('dense-original', originalImage);

                if (options.dimensions == 'update')
                {
                    $this.dense('updateDimensions').one('dense-dimensions-updated', readyImage);
                }
                else
                {
                    if (options.dimensions == 'remove')
                    {
                        $this.removeAttr('width height');
                    }

                    readyImage();
                }
            };

            if (ping)
            {
                $.ajax({
                    url  : image,
                    type : 'HEAD'
                })
                    .done(function (data, textStatus, jqXHR)
                    {
                        var type = jqXHR.getResponseHeader('Content-type');

                        if (jqXHR.status === 200 && (type === null || $.inArray(type.split(';').shift(), acceptedTypes) !== -1))
                        {
                            pathStack.push(image);
                            updateImage();
                        }
                    });
            }
            else
            {
                updateImage();
            }
        });

        return this;
    };

    /**
     * Sets an image's width and height attributes to its native values.
     *
     * Updates an img element's dimensions to the source image's
     * real values. This method is asynchronous, so you can not directly
     * return its values. Instead, use the 'dense-dimensions-updated'
     * event to detect when the action is done.
     *
     * @return   {Object} this
     * @method   updateDimensions
     * @memberof jQuery.fn.dense
     * @fires    jQuery.fn.dense#dense-dimensions-updated
     * @example
     * var image = $('img').dense('updateDimensions');
     */

    methods.updateDimensions = function ()
    {
        return this.each(function ()
        {
            var img, $this = $(this), src = $this.attr('src');

            if (src)
            {
                img = new Image();
                img.src = src;

                $(img).on('load.dense', function ()
                {
                    $this.attr('width', img.width).attr('height', img.height);
                    $this.trigger('dense-dimensions-updated');
                });
            }
        });
    };

    /**
     * Gets device pixel ratio rounded up to the closest integer.
     *
     * @return   {Integer} The pixel ratio
     * @method   devicePixelRatio
     * @memberof jQuery.fn.dense
     * @example
     * var ratio = $(window).dense('devicePixelRatio');
     * alert(ratio);
     */

    methods.devicePixelRatio = function ()
    {
        var pixelRatio = 1;

        if ($.type(window.devicePixelRatio) !== 'undefined')
        {
            pixelRatio = window.devicePixelRatio;
        }
        else if ($.type(window.matchMedia) !== 'undefined')
        {
            $.each([1.3, 1.5, 2, 3, 4, 5, 6], function (key, ratio)
            {
                var mediaQuery = [
                    '(-webkit-min-device-pixel-ratio: '+ratio+')',
                    '(min--moz-device-pixel-ratio: '+ratio+')',
                    '(-o-min-device-pixel-ratio: '+ratio+')',
                    '(min-resolution: '+ratio+'dppx)'
                ].join(',');

                if (!window.matchMedia(mediaQuery).matches)
                {
                    pixelRatio = ratio;
                    return false;
                }
            });
        }

        return Math.ceil(pixelRatio);
    };

    /**
     * Gets an appropriate URL for the pixel ratio from the data attribute list.
     *
     * Selects the most appropriate data-{ratio}x attribute from
     * the given element's attributes. If the devices pixel ratio is greater
     * than the largest specified image, the largest one of the available is used.
     *
     * @return   {String|Boolean} The attribute value
     * @method   getImageAttribute
     * @memberof jQuery.fn.dense
     * @example
     * var image = $('
').dense('getImageAttribute');
     * $('body').css('background-image', 'url(' + image + ')');
     */

    methods.getImageAttribute = function ()
    {
        var $this = $(this).eq(0), image = false, url;

        for (var i = 1; i <= devicePixelRatio; i++)
        {
            url = $this.attr('data-' + i + 'x');

            if (url)
            {
                image = url;
            }
        }

        return image;
    };

    devicePixelRatio = methods.devicePixelRatio();

    /**
     * Dense offers few methods and options that can be used to both customize the
     * plugin's functionality and return resulting values. All interaction is done through
     * the $.fn.dense() method, that accepts a called method and its options
     * object as its arguments. Both arguments are optional, and either one can be omitted.
     *
     * @param    {String}  [method=init] The called method
     * @param    {Object}  [options={}]  Options passed to the method
     * @class    dense
     * @memberof jQuery.fn
     */

    $.fn.dense = function (method, options)
    {
        if ($.type(method) !== 'string' || $.type(methods[method]) !== 'function')
        {
            options = method;
            method = 'init';
        }

        return methods[method].call(this, options);
    };

    /**
     * Initialize automatically when document is ready.
     *
     * Dense is initialized automatically if the body element
     * has a dense-retina class.
     */

    $(document).ready(function ()
    {
        $('body.dense-retina img').dense();
    });

    /**
     * This event is invoked when an retina image has finished loading.
     *
     * @event    jQuery.fn.dense#dense-retina-loaded
     * @type     {Object}
     */

    /**
     * This event is invoked when an image's dimensions are
     * have been updated by the updateDimensions
     * method.
     *
     * @event    jQuery.fn.dense#dense-dimensions-updated
     * @type     {Object}
     */
}));<commit_msg>Streamline accepted image types.<commit_after>/**
 * Dense - Device pixel ratio aware images
 *
 * @link    http://dense.rah.pw
 * @license MIT
 */

/*
 * Copyright (C) 2013 Jukka Svahn
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/**
 * @name jQuery
 * @class
 */

/**
 * @name fn
 * @class
 * @memberOf jQuery
 */

;(function (factory)
{
	if (typeof define === 'function' && define.amd)
	{
		define(['jquery'], factory);
	}
	else
	{
		factory(jQuery);
	}
}(function ($)
{
    /**
     * An array of checked image URLs.
     */

    var pathStack = [],

    /**
     * Methods.
     */

    methods = {},

    /**
     * Regular expression to check whether the URL has a protocol.
     *
     * Is used to check whether the image URL is external.
     */

    regexProtocol = /^https?:\/\//,

    /**
     * Regular expression that split extensions from the file.
     *
     * Is used to inject the DPR suffix to the name.
     */

    regexSuffix = /\.\w+$/,

    /**
     * Device pixel ratio.
     */

    devicePixelRatio,

    /**
     * An array of accepted content-types.
     *
     * Basically contains an array of raster image formats.
     */

    acceptedTypes =
    [
        'image/jpeg',
        'image/png',
        'image/gif'
    ],

    /**
     * Skipped image file extensions.
     *
     * Vectors don't need automatic pixel ratio support.
     */

    skipExtensions =
    [
        'svg'
    ];

    /**
     * Init is the default method responsible for rendering
     * a pixel-ratio-aware images.
     *
     * This method is used to select the images that
     * should display retina-size images on high pixel ratio
     * devices. Dense defaults to the init method if no
     * method is specified.
     *
     * When attached to an image, the correct image variation is
     * selected based on the device's pixel ratio. If the image element
     * defines data-{ratio}x attributes (e.g. data-1x, data-2x, data-3x),
     * the most appropriate of those is selected.
     *
     * If no data-ratio attributes are defined, the retina image is
     * constructed from the src attribute.
     * The searched high pixel ratio images follows
     * a {imageName}_{ratio}x.{ext} naming convention.
     * For an image found in /path/to/images/image.jpg, the 2x retina
     * image would be looked from /path/to/images/image_2x.jpg.
     *
     * When image is constructed from the src, the image existance is
     * verified using HTTP HEAD request. The check makes sure no
     * HTTP error code is returned, and that the received content-type
     * is either image/jpeg, image/png or
     * image/gif. Vector image formats, like svg, are skipped.
     *
     * This method can also be used to load image in semi-lazy fashion,
     * and avoid larger extra HTTP requests due to retina replacements.
     * The data-1x attribute can be used to supstitute the src, making
     * sure the browser doesn't try to download the normal image variation
     * before the JavaScript driven behaviour kicks in.
     *
     * @param    {Object}  [options={}]                  Options
     * @param    {Boolean} [options.ping=true]           A prefix added to the generated links
     * @param    {String}  [options.dimensions=preserve] What to do with the width and height attributes. Either update, remove or preserve
     * @return   {Object}  this
     * @method   init
     * @memberof jQuery.fn.dense
     * @fires    jQuery.fn.dense#dense-retina-loaded
     * @example
     * $('img.retina').dense({
     *  'ping'      : false,
     *  'dimension' : true
     * });
     */

    methods.init = function (options)
    {
        options = $.extend({
            ping       : true,
            dimensions : 'preserve'
        }, options);

        this.filter('img').not('.dense').addClass('dense dense-loading').each(function ()
        {
            var $this = $(this),
                image = methods.getImageAttribute.call(this),
                originalImage = $this.attr('src'),
                ping = false,
                updateImage;

            if (!image)
            {
                if (!originalImage || devicePixelRatio == 1 || $.inArray(image.split('.').pop().split(/[\?\#]/).shift(), skipExtensions))
                {
                    return;
                }

                image = originalImage.replace(regexSuffix, function (extension)
                {
                    return '_' + devicePixelRatio + 'x' + extension;
                });

                ping = options.ping && $.inArray(image, pathStack) === -1 && (regexProtocol.test(image) === false || image.indexOf('://' + document.domain) !== -1);
            }

            updateImage = function ()
            {
                var readyImage = function ()
                {
                    $this.removeClass('dense-loading').addClass('dense-ready').trigger('dense-retina-loaded');
                };

                $this.attr('src', image).data('dense-original', originalImage);

                if (options.dimensions == 'update')
                {
                    $this.dense('updateDimensions').one('dense-dimensions-updated', readyImage);
                }
                else
                {
                    if (options.dimensions == 'remove')
                    {
                        $this.removeAttr('width height');
                    }

                    readyImage();
                }
            };

            if (ping)
            {
                $.ajax({
                    url  : image,
                    type : 'HEAD'
                })
                    .done(function (data, textStatus, jqXHR)
                    {
                        var type = jqXHR.getResponseHeader('Content-type');

                        if (jqXHR.status === 200 && (type === null || $.inArray(type.split(';').shift(), acceptedTypes) !== -1))
                        {
                            pathStack.push(image);
                            updateImage();
                        }
                    });
            }
            else
            {
                updateImage();
            }
        });

        return this;
    };

    /**
     * Sets an image's width and height attributes to its native values.
     *
     * Updates an img element's dimensions to the source image's
     * real values. This method is asynchronous, so you can not directly
     * return its values. Instead, use the 'dense-dimensions-updated'
     * event to detect when the action is done.
     *
     * @return   {Object} this
     * @method   updateDimensions
     * @memberof jQuery.fn.dense
     * @fires    jQuery.fn.dense#dense-dimensions-updated
     * @example
     * var image = $('img').dense('updateDimensions');
     */

    methods.updateDimensions = function ()
    {
        return this.each(function ()
        {
            var img, $this = $(this), src = $this.attr('src');

            if (src)
            {
                img = new Image();
                img.src = src;

                $(img).on('load.dense', function ()
                {
                    $this.attr('width', img.width).attr('height', img.height);
                    $this.trigger('dense-dimensions-updated');
                });
            }
        });
    };

    /**
     * Gets device pixel ratio rounded up to the closest integer.
     *
     * @return   {Integer} The pixel ratio
     * @method   devicePixelRatio
     * @memberof jQuery.fn.dense
     * @example
     * var ratio = $(window).dense('devicePixelRatio');
     * alert(ratio);
     */

    methods.devicePixelRatio = function ()
    {
        var pixelRatio = 1;

        if ($.type(window.devicePixelRatio) !== 'undefined')
        {
            pixelRatio = window.devicePixelRatio;
        }
        else if ($.type(window.matchMedia) !== 'undefined')
        {
            $.each([1.3, 1.5, 2, 3, 4, 5, 6], function (key, ratio)
            {
                var mediaQuery = [
                    '(-webkit-min-device-pixel-ratio: '+ratio+')',
                    '(min--moz-device-pixel-ratio: '+ratio+')',
                    '(-o-min-device-pixel-ratio: '+ratio+')',
                    '(min-resolution: '+ratio+'dppx)'
                ].join(',');

                if (!window.matchMedia(mediaQuery).matches)
                {
                    pixelRatio = ratio;
                    return false;
                }
            });
        }

        return Math.ceil(pixelRatio);
    };

    /**
     * Gets an appropriate URL for the pixel ratio from the data attribute list.
     *
     * Selects the most appropriate data-{ratio}x attribute from
     * the given element's attributes. If the devices pixel ratio is greater
     * than the largest specified image, the largest one of the available is used.
     *
     * @return   {String|Boolean} The attribute value
     * @method   getImageAttribute
     * @memberof jQuery.fn.dense
     * @example
     * var image = $('
').dense('getImageAttribute');
     * $('body').css('background-image', 'url(' + image + ')');
     */

    methods.getImageAttribute = function ()
    {
        var $this = $(this).eq(0), image = false, url;

        for (var i = 1; i <= devicePixelRatio; i++)
        {
            url = $this.attr('data-' + i + 'x');

            if (url)
            {
                image = url;
            }
        }

        return image;
    };

    devicePixelRatio = methods.devicePixelRatio();

    /**
     * Dense offers few methods and options that can be used to both customize the
     * plugin's functionality and return resulting values. All interaction is done through
     * the $.fn.dense() method, that accepts a called method and its options
     * object as its arguments. Both arguments are optional, and either one can be omitted.
     *
     * @param    {String}  [method=init] The called method
     * @param    {Object}  [options={}]  Options passed to the method
     * @class    dense
     * @memberof jQuery.fn
     */

    $.fn.dense = function (method, options)
    {
        if ($.type(method) !== 'string' || $.type(methods[method]) !== 'function')
        {
            options = method;
            method = 'init';
        }

        return methods[method].call(this, options);
    };

    /**
     * Initialize automatically when document is ready.
     *
     * Dense is initialized automatically if the body element
     * has a dense-retina class.
     */

    $(document).ready(function ()
    {
        $('body.dense-retina img').dense();
    });

    /**
     * This event is invoked when an retina image has finished loading.
     *
     * @event    jQuery.fn.dense#dense-retina-loaded
     * @type     {Object}
     */

    /**
     * This event is invoked when an image's dimensions are
     * have been updated by the updateDimensions
     * method.
     *
     * @event    jQuery.fn.dense#dense-dimensions-updated
     * @type     {Object}
     */
}));<|endoftext|>


<commit_before>var objectUtils = require('./objectUtils');
exports.applyRoute = function(app, route, obj) {
  var server = app.server;
  if (objectUtils.isObject(obj)) {
    /*if (obj.get) {
      if (app.isDebug) {
        console.log('[route] GET ' + route);
      }
      server.get(route, obj.get);
    }

    if (obj.post) {
      if (app.isDebug) {
        console.log('[route] POST ' + route);
      }
      server.post(route, obj.post);
    }
    */
    applyVerbs(app, route, obj, ["get", "put", "post", "delete", "options", "all"]);
  } else if (objectUtils.isFunction(obj) || objectUtils.isArray(obj)) {

    if (app.isDebug) {
      console.log('[route] ALL ' + route);
    }
    server.all(route, obj);

  } else {
    throw new Error('Unsupported route object.');
  }

}

function applyVerbs(app, route, obj, verbs) {
  var server = app.server;
  for (var i in verbs) {
    var verb = verbs[i];
    if (obj[verb]) {

      if (obj.isRegexp) {
        if (app.isDebug) {
          console.log('[route regex] %s %s', verb, route);
        }
        var flags = route.replace(/.*\/([gimy]*)$/, '$1');
        var pattern = route.replace(new RegExp('^/(.*?)/'+flags+'$'), '$1');
        route = new RegExp(pattern, flags);
        //var match = route.match(new RegExp('/^\/(.*?)\/([gim]*)$/'));
        //route = new RegExp(route);

      } else {
        if (app.isDebug) {
          console.log('[route] %s %s', verb, route);
        }
      }

      server[verb](route, obj[verb]);
    }
  }
}<commit_msg>cleaned<commit_after>var objectUtils = require('./objectUtils');
exports.applyRoute = function(app, route, obj) {
  var server = app.server;
  if (objectUtils.isObject(obj)) {
    applyVerbs(app, route, obj, ["get", "put", "post", "delete", "options", "all"]);
  } else if (objectUtils.isFunction(obj) || objectUtils.isArray(obj)) {

    if (app.isDebug) {
      console.log('[route] ALL ' + route);
    }
    server.all(route, obj);

  } else {
    throw new Error('Unsupported route object.');
  }

}

function applyVerbs(app, route, obj, verbs) {
  var server = app.server;
  for (var i in verbs) {
    var verb = verbs[i];
    if (obj[verb]) {

      if (obj.isRegexp) {
        if (app.isDebug) {
          console.log('[route regex] %s %s', verb, route);
        }
        var flags = route.replace(/.*\/([gimy]*)$/, '$1');
        var pattern = route.replace(new RegExp('^/(.*?)/'+flags+'$'), '$1');
        route = new RegExp(pattern, flags);
        //var match = route.match(new RegExp('/^\/(.*?)\/([gim]*)$/'));
        //route = new RegExp(route);

      } else {
        if (app.isDebug) {
          console.log('[route] %s %s', verb, route);
        }
      }

      server[verb](route, obj[verb]);
    }
  }
}<|endoftext|>


<commit_before>var frame = 0, // is an animation frame pending?
    timeout = 0, // is a timeout pending?
    interval = 0, // are any timers active?
    maxDelay = 5000, // the longest we’ll sleep if there are active timers
    taskHead,
    taskTail,
    clockLast = 0,
    clockNow = 0,
    clock = typeof performance === "object" ? performance : Date,
    setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(callback) { return setTimeout(callback, 17); };

export function now() {
  return clockNow || (setFrame(clearNow), clockNow = clock.now());
}

function clearNow() {
  clockNow = 0;
}

function Timer() {
  this._call =
  this._time =
  this._next = null;
}

Timer.prototype = timer.prototype = {
  restart: function(callback, delay, time) {
    if (typeof callback !== "function") throw new TypeError("callback is not a function");
    time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
    if (!this._call) {
      if (taskTail) taskTail._next = this;
      else taskHead = this;
      taskTail = this;
    }
    this._call = callback;
    this._time = time;
    sleep();
  },
  stop: function() {
    if (this._call) {
      this._call = null;
      this._time = Infinity;
      sleep();
    }
  }
};

export function timer(callback, delay, time) {
  var t = new Timer;
  t.restart(callback, delay, time);
  return t;
}

export function timerOnce(callback, delay, time) {
  var t = new Timer;
  t.restart(function(elapsed) { t.stop(); callback(elapsed); }, delay, time);
  return t;
}

export function timerFlush() {
  now(); // Get the current time, if not already set.
  ++frame; // Pretend we’ve set an alarm, if we haven’t already.
  var t = taskHead;
  while (t) {
    if (clockNow >= t._time) t._call.call(null, clockNow - t._time);
    t = t._next;
  }
  --frame;
}

function wake(time) {
  clockLast = clockNow = time || clock.now();
  frame = timeout = 0;
  try {
    timerFlush();
  } finally {
    frame = 0;
    nap();
    clockNow = 0;
  }
}

function poke() {
  if (clock.now() - clockLast > maxDelay) {
    wake();
  }
}

function nap() {
  var t0, t1 = taskHead, time = Infinity;
  while (t1) {
    if (t1._call) {
      if (time > t1._time) time = t1._time;
      t1 = (t0 = t1)._next;
    } else {
      t1 = t0 ? t0._next = t1._next : taskHead = t1._next;
    }
  }
  taskTail = t0;
  sleep(time);
}

function sleep(time) {
  if (frame) return; // Soonest alarm already set, or will be.
  if (timeout) timeout = clearTimeout(timeout);
  var delay = time - clockNow;
  if (delay > 24) {
    if (time < Infinity) timeout = setTimeout(wake, delay);
    else if (interval) interval = clearInterval(interval);
  } else {
    if (!interval) interval = setInterval(poke, maxDelay);
    frame = 1, setFrame(wake);
  }
}
<commit_msg>Micro-optimize.<commit_after>var frame = 0, // is an animation frame pending?
    timeout = 0, // is a timeout pending?
    interval = 0, // are any timers active?
    maxDelay = 5000, // the longest we’ll sleep if there are active timers
    taskHead,
    taskTail,
    clockLast = 0,
    clockNow = 0,
    clock = typeof performance === "object" ? performance : Date,
    setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(callback) { return setTimeout(callback, 17); };

export function now() {
  return clockNow || (setFrame(clearNow), clockNow = clock.now());
}

function clearNow() {
  clockNow = 0;
}

function Timer() {
  this._call =
  this._time =
  this._next = null;
}

Timer.prototype = timer.prototype = {
  restart: function(callback, delay, time) {
    if (typeof callback !== "function") throw new TypeError("callback is not a function");
    time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
    if (!this._call) {
      if (taskTail) taskTail._next = this;
      else taskHead = this;
      taskTail = this;
    }
    this._call = callback;
    this._time = time;
    sleep();
  },
  stop: function() {
    if (this._call) {
      this._call = null;
      this._time = Infinity;
      sleep();
    }
  }
};

export function timer(callback, delay, time) {
  var t = new Timer;
  t.restart(callback, delay, time);
  return t;
}

export function timerOnce(callback, delay, time) {
  var t = new Timer;
  t.restart(function(elapsed) { t.stop(); callback(elapsed); }, delay, time);
  return t;
}

export function timerFlush() {
  now(); // Get the current time, if not already set.
  ++frame; // Pretend we’ve set an alarm, if we haven’t already.
  var t = taskHead, e;
  while (t) {
    if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
    t = t._next;
  }
  --frame;
}

function wake(time) {
  clockLast = clockNow = time || clock.now();
  frame = timeout = 0;
  try {
    timerFlush();
  } finally {
    frame = 0;
    nap();
    clockNow = 0;
  }
}

function poke() {
  if (clock.now() - clockLast > maxDelay) {
    wake();
  }
}

function nap() {
  var t0, t1 = taskHead, time = Infinity;
  while (t1) {
    if (t1._call) {
      if (time > t1._time) time = t1._time;
      t1 = (t0 = t1)._next;
    } else {
      t1 = t0 ? t0._next = t1._next : taskHead = t1._next;
    }
  }
  taskTail = t0;
  sleep(time);
}

function sleep(time) {
  if (frame) return; // Soonest alarm already set, or will be.
  if (timeout) timeout = clearTimeout(timeout);
  var delay = time - clockNow;
  if (delay > 24) {
    if (time < Infinity) timeout = setTimeout(wake, delay);
    else if (interval) interval = clearInterval(interval);
  } else {
    if (!interval) interval = setInterval(poke, maxDelay);
    frame = 1, setFrame(wake);
  }
}
<|endoftext|>


<commit_before>'use strict';

const util = require('util');
const _    = require('./helpers');
const CommandUtil = require('./command_util').CommandUtil;

/*
 * Door-related helper functions.
 */

// Returns an array of exits that match the provided direction string.
const findExit = (room, dir) => room.getExits()
  .filter(exit => exit.direction.includes(dir));

// Takes a callback to use on the destination room.
const updateDestination = (player, dest, callback) => dest
  .getExits()
  .filter(exit => exit.location === player.getLocation())
  .forEach(callback);

/* Dealing with locked/unlocked states */
const changeDoorLockState = isLocked => exit => exit.door.locked = isLocked;
const lockDoor   = changeDoorLockState(true);
const unlockDoor = changeDoorLockState(false);

const isLocked = exit => exit.door && exit.door.locked;
const defaultDifficulty = 5;
const getLockDifficulty = exit => parseInt(exit.door.difficulty || defaultDifficulty, 10);

/* Dealing with npc passage */
const isMobLocked   = exit => isDoor(exit) && exit.door.mob_locked && exit.door.mob_locked === true;
const isNpcPassable = exit => !(isMobLocked(exit) || isLocked(exit));

/* Dealing with open/closed states */
const isDoor = exit => exit && exit.hasOwnProperty('door');
const isOpen = exit => exit.door ? exit.door.open : true;

const useKeyToUnlock = useKey.bind(null, 'unlock');
const useKeyToLock   = useKey.bind(null, 'lock');

const openDoor  = openOrClose.bind(null, 'open');
const closeDoor = openOrClose.bind(null, 'close');

//TODO: Refactor to use the bound functions in external code.
exports.Doors = {
  updateDestination,
  useKeyToLock,
  useKeyToUnlock,
  getLockDifficulty,
  findExit,  openOrClose,
  lockDoor,  unlockDoor,
  useKey,    isMobLocked,
  isLocked,  isOpen,
  isDoor,    isNpcPassable,
  openDoor,  closeDoor,
};

/* useKey && openOrClose
 * both take a verb string along with args, player, players, rooms dependencies.
 * useKey verb:       'lock' | 'unlock'
 * openOrClose verb:  'open' | 'close'
 * This is because the code is more or less the same for each command, and this
 * helps keep things dry.
 */

function openOrClose(verb, args, player, players, rooms) {

  const isOpen = verb === 'open';

  player.emit('action', 0);

  if (player.isInCombat()) {
    return player.say('You are too busy for that right now.');
  }

  if (!args) {
    return player.say("Which door do you want to " + verb + "?");
  }

  args = args.toLowerCase().split(' ');

  const room  = rooms.getAt(player.getLocation());
  const dir   = args[0];
  const exits = findExit(room, dir);

  if (exits.length !== 1) {
    return player.say('Be more specific...');
  }

  const exit = exits[0];

  if (!exit.door) {
    return player.say('There is no door.');
  }

  if (exit.door.open === isOpen) {
    const pastTense = isOpen ? 'opened' : 'closed';
    return player.say('That door is already ' + pastTense +'.');
  }

  const dest = rooms.getAt(exit.location);

  const srcTitle  = room.getTitle('en');
  const destTitle = dest.getTitle('en');

  player.say('You ' + verb + ' the door to ' + destTitle + '.');
  exit.door.open = isOpen;

  updateDestination(player, dest,
    exit => {
      exit.door.open = isOpen;

      const nounPhrase = isOpen ? 'swings open' : 'slams shut';
      players.eachIf(
        p => p.getLocation() === dest.getLocation(),
        p => p.say('The door to ' + srcTitle + ' ' + nounPhrase + '.'));
    });

  players.eachIf(
    p => CommandUtil.inSameRoom(p, player),
    p => p.say(player.getName() + ' ' + verb + 's the door to ' + destTitle + '.'));

}

function useKey(verb, args, player, players, rooms) {
  util.log('USING KEY....')
  const isLocking = verb === 'lock';

  player.emit('action');

  if (player.isInCombat()) {
    return player.say('You are too busy for that right now.');
  }

  args = args.toLowerCase().split(' ');

  if (!args) {
    return player.say("Which door do you want to " + verb + "?");
  }

  const room  = rooms.getAt(player.getLocation());
  const dir   = args[0];
  const exits = findExit(room, dir);

  if (exits.length !== 1) {
    return player.say('Be more specific...');
  }

  const exit = exits[0];

  if (!exit.door) {
    return player.say('There is no door.');
  }

  if (exit.door.open === true && isLocking) {
    player.say('You close the door.');
    exit.door.open = false;
  }

  if (exit.door.locked === isLocking) {
    return player.say('That door is already ' + verb + 'ed.');
  }

  const key = CommandUtil.findItemInInventory(exit.door.key, player, true);

  if (!key) {
    return player.say('You are missing the key.');
  }

  const dest       = rooms.getAt(exit.location);
  const srcTitle   = room.getTitle('en');
  const destTitle  = dest.getTitle('en');

  player.say('You ' + verb + ' the door.');
  exit.door.locked = isLocking;

  const lockOrUnlock = isLocking ? lockDoor : unlockDoor;
  updateDestination(player, dest, lockOrUnlock);

  players.eachIf(
    p => CommandUtil.inSameRoom(p, player),
    p => p.say(player.getName() + ' pulls out a key and ' + verb + 's the door to ' + destTitle + '.'));

  players.eachIf(
    p => p.getLocation() === exit.location,
    p => p.say('You hear a click from the direction of ' + srcTitle + '.'));
}
<commit_msg>Fix issue with doors. Using open command would bypass having to unlock. Woops.<commit_after>'use strict';

const util = require('util');
const _    = require('./helpers');
const CommandUtil = require('./command_util').CommandUtil;

/*
 * Door-related helper functions.
 */

// Returns an array of exits that match the provided direction string.
const findExit = (room, dir) => room.getExits()
  .filter(exit => exit.direction.includes(dir));

// Takes a callback to use on the destination room.
const updateDestination = (player, dest, callback) => dest
  .getExits()
  .filter(exit => exit.location === player.getLocation())
  .forEach(callback);

/* Dealing with locked/unlocked states */
const changeDoorLockState = isLocked => exit => exit.door.locked = isLocked;
const lockDoor   = changeDoorLockState(true);
const unlockDoor = changeDoorLockState(false);

const isLocked = exit => exit.door && exit.door.locked;
const defaultDifficulty = 5;
const getLockDifficulty = exit => parseInt(exit.door.difficulty || defaultDifficulty, 10);

/* Dealing with npc passage */
const isMobLocked   = exit => isDoor(exit) && exit.door.mob_locked && exit.door.mob_locked === true;
const isNpcPassable = exit => !(isMobLocked(exit) || isLocked(exit));

/* Dealing with open/closed states */
const isDoor = exit => exit && exit.hasOwnProperty('door');
const isOpen = exit => exit.door ? exit.door.open : true;

const useKeyToUnlock = useKey.bind(null, 'unlock');
const useKeyToLock   = useKey.bind(null, 'lock');

const openDoor  = openOrClose.bind(null, 'open');
const closeDoor = openOrClose.bind(null, 'close');

//TODO: Refactor to use the bound functions in external code.
exports.Doors = {
  updateDestination,
  useKeyToLock,
  useKeyToUnlock,
  getLockDifficulty,
  findExit,  openOrClose,
  lockDoor,  unlockDoor,
  useKey,    isMobLocked,
  isLocked,  isOpen,
  isDoor,    isNpcPassable,
  openDoor,  closeDoor,
};

/* useKey && openOrClose
 * both take a verb string along with args, player, players, rooms dependencies.
 * useKey verb:       'lock' | 'unlock'
 * openOrClose verb:  'open' | 'close'
 * This is because the code is more or less the same for each command, and this
 * helps keep things dry.
 */

function openOrClose(verb, args, player, players, rooms) {

  const isOpen = verb === 'open';

  player.emit('action', 0);

  if (player.isInCombat()) {
    return player.say('You are too busy for that right now.');
  }

  if (!args) {
    return player.say("Which door do you want to " + verb + "?");
  }

  args = args.toLowerCase().split(' ');

  const room  = rooms.getAt(player.getLocation());
  const dir   = args[0];
  const exits = findExit(room, dir);

  if (exits.length !== 1) {
    return player.say('Be more specific...');
  }

  const exit = exits[0];

  if (!exit.door) {
    return player.say('There is no door.');
  }

  if (exit.door.open === isOpen) {
    const pastTense = isOpen ? 'opened' : 'closed';
    return player.say('That door is already ' + pastTense +'.');
  }

  if (isOpen && isLocked(exit)) {
    return player.say('That door is locked.');
  }

  const dest = rooms.getAt(exit.location);

  const srcTitle  = room.getTitle('en');
  const destTitle = dest.getTitle('en');

  player.say('You ' + verb + ' the door to ' + destTitle + '.');
  exit.door.open = isOpen;

  updateDestination(player, dest,
    exit => {
      exit.door.open = isOpen;

      const nounPhrase = isOpen ? 'swings open' : 'slams shut';
      players.eachIf(
        p => p.getLocation() === dest.getLocation(),
        p => p.say('The door to ' + srcTitle + ' ' + nounPhrase + '.'));
    });

  players.eachIf(
    p => CommandUtil.inSameRoom(p, player),
    p => p.say(player.getName() + ' ' + verb + 's the door to ' + destTitle + '.'));

}

function useKey(verb, args, player, players, rooms) {
  util.log('USING KEY....')
  const isLocking = verb === 'lock';

  player.emit('action');

  if (player.isInCombat()) {
    return player.say('You are too busy for that right now.');
  }

  args = args.toLowerCase().split(' ');

  if (!args) {
    return player.say("Which door do you want to " + verb + "?");
  }

  const room  = rooms.getAt(player.getLocation());
  const dir   = args[0];
  const exits = findExit(room, dir);

  if (exits.length !== 1) {
    return player.say('Be more specific...');
  }

  const exit = exits[0];

  if (!exit.door) {
    return player.say('There is no door.');
  }

  if (exit.door.open === true && isLocking) {
    player.say('You close the door.');
    exit.door.open = false;
  }

  if (exit.door.locked === isLocking) {
    return player.say('That door is already ' + verb + 'ed.');
  }

  const key = CommandUtil.findItemInInventory(exit.door.key, player, true);

  if (!key) {
    return player.say('You are missing the key.');
  }

  const dest       = rooms.getAt(exit.location);
  const srcTitle   = room.getTitle('en');
  const destTitle  = dest.getTitle('en');

  player.say('You ' + verb + ' the door.');
  exit.door.locked = isLocking;

  const lockOrUnlock = isLocking ? lockDoor : unlockDoor;
  updateDestination(player, dest, lockOrUnlock);

  players.eachIf(
    p => CommandUtil.inSameRoom(p, player),
    p => p.say(player.getName() + ' pulls out a key and ' + verb + 's the door to ' + destTitle + '.'));

  players.eachIf(
    p => p.getLocation() === exit.location,
    p => p.say('You hear a click from the direction of ' + srcTitle + '.'));
}
<|endoftext|>


<commit_before>(function()
{
    if (!window.requestAnimationFrame)
    {
        window.requestAnimationFrame = window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame    ||
        window.oRequestAnimationFrame      ||
        window.msRequestAnimationFrame     ||

        function(callback, element)
        {
            window.setTimeout(callback, 1000 / FRAME_RATE);
        }
    }
})();

var canvas = document.getElementById("canvas");
console.log("Canvas loaded.");
var context = (check(canvas)) ? canvas.getContext("2d") : null;
console.log("Context loaded.");
check(context);

canvas.style.background = "rgb(52, 55, 60)";
console.log("Background colour set to " + canvas.style.background + ".");

var boxes = [];
var heldKeys = [];
const FRAMERATE = 60;
const BOX_SIZE = 20;
const GRAVITY = 9.68;
const JUMP_VELOCITY = 100;
const SPEED = 5;
const ACCELERATION = 1;
const FRICTION = 0.8;
console.log("Values set for properties.");

function check(object) {
   if(!object || object === null) {
      console.error(object.constructor.name + " is NULL.");
      return false;
   } else {
      //console.group("Properties of " + object.constructor.name + ": ");
      console.log(object.constructor.name + " has been created.")
      return true;
   }
}

var collisionChecker= {
    quickBoxTest: function(boxA, boxB) {
        if(boxA.x < boxB.x + boxB.width && boxA.x + boxA.width > boxB.x && boxA.y < boxB.y + boxB.height && boxA.height + boxA.y > boxB.y)
         return true;

      return false;
    }
}

var input = {
   getKeyDown: function(keyToCheck) {
      if(heldKeys[keyToCheck] === true)
         return true
      else
   return false;
   }
}
<commit_msg>Added full game<commit_after>(function()
{
    if (!window.requestAnimationFrame)
    {
        window.requestAnimationFrame = window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame    ||
        window.oRequestAnimationFrame      ||
        window.msRequestAnimationFrame     ||

        function(callback, element)
        {
            window.setTimeout(callback, 1000 / FRAME_RATE);
        }
    }
})();
console.log("Animation frame requested.");

var canvas = document.getElementById("canvas");
console.log("Canvas loaded.");
var context = (check(canvas)) ? canvas.getContext("2d") : null;
console.log("Context loaded.");
check(context);

canvas.style.background = "rgb(52, 55, 60)";
console.log("Background colour set to " + canvas.style.background + ".");

var boxes = [];
var heldKeys = [];
const FRAMERATE = 60;
const BOX_SIZE = 20;
const GRAVITY = 0.9;
const JUMP_VELOCITY = 10;
const SPEED = 10;
const ACCELERATION = 1;
const FRICTION = 0.9;

var playerSpawnX, playerSpawnY;
playerSpawnX = playerSpawnY = 0;
console.log("Values set for properties.");

player = new Player(0, 0, BOX_SIZE, BOX_SIZE, "white");
console.log("Player created.");
player.toString();
check(player);

for(var i = 0; i < 20; i++) {
   box = new Box(Math.floor((Math.random() * (canvas.width - BOX_SIZE))), Math.floor((Math.random() * (canvas.height - BOX_SIZE))), BOX_SIZE, BOX_SIZE, "red");
}

function Player(xPos, yPos, _width, _height, _renderColour) {
   this.x = xPos;
   this.y = yPos;
   this.width = _width;
   this.height = _height;
   this.colour = _renderColour;
   this.xVelocity = 0;
   this.yVelocity = 0;
   this.grounded = false;
   this.jumping = false;

   this.toString = function() {
      console.log("Player's position: (" + this.x + ", " + this.y + ")");
      console.log("Player's dimensions: (" + this.width + ", " + this.height + ")");
      console.log("Player's colour: " + this.colour);
      console.log("Player's velocity: (" + this.xVelocity + ", " + this.yVelocity + ")");
   }

   this.respawn = function() {
      this.x = playerSpawnX;
      this.y = playerSpawnY;
   }

   this.respawn = function(x, y) {
      this.x = x;
      this.y = y;
   }

   this.setVelocity = function(x, y) {
      this.xVelocity = x;
      this.yVelocity = y;
   }

   this.calculateVelocity = function() {
      if(input.getKeyDown(keyCode.upArrow) && this.grounded)
         this.setVelocity(0, -SPEED);

      if(input.getKeyDown(keyCode.rightArrow))
         this.setVelocity(SPEED, 0);

      if(input.getKeyDown(keyCode.leftArrow))
         this.setVelocity(-SPEED, 0);
   }

   this.adjustVelocityByCollision = function(toTest) {
      if((collisionChecker.testCollision(this, toTest) === "b") || this.y === canvas.height - BOX_SIZE) {
         this.setVelocity(this.xVelocity, 0);
         this.grounded = true;
         this.jumping = false;
      }
   }

   this.applyVelocity = function() {
      this.x += this.xVelocity;
      this.y += this.yVelocity;
      this.y += GRAVITY;
   }

   this.resetVelocity = function() {
      this.xVelocity = 0;
      this.yVelocity = 0;
   }

   this.constrain = function() {
      this.x = clamp(this.x, 0, canvas.width - BOX_SIZE);
      this.y = clamp(this.y, 0, canvas.height - BOX_SIZE);
   }

   this.update = function() {
      this.resetVelocity();
      this.calculateVelocity();
      this.applyVelocity();
      this.constrain();
      this.resetVelocity();
   }

   this.render = function() {
      context.fillStyle = this.colour;
      context.fillRect(this.x, this.y, this.width, this.height);
   }
}

function Box(xPos, yPos, _width, _height, _renderColour) {
   this.x = xPos;
   this.y = yPos;
   this.width = _width;
   this.height = _height;
   this.colour = _renderColour;

   boxes.push(this);

   this.toString = function() {
      console.log("Box's position: (" + this.x + ", " + this.y + ")");
      console.log("Box's dimensions: (" + this.width + ", " + this.height + ")");
      console.log("Box's colour: " + this.colour);
   }

   this.constrain = function() {
      this.x = clamp(this.x, 0, canvas.width - BOX_SIZE);
      this.y = clamp(this.y, 0, canvas.height - BOX_SIZE);
   }

   this.render = function() {
      context.fillStyle = this.colour;
      context.fillRect(this.x, this.y, this.width, this.height);
   }
}

function onKeyDown(key) {
    if(key.target == document.body) {
        key.preventDefault();
        heldKeys[key.keyCode] = true;
    }
}
window.addEventListener("keydown", onKeyDown, false);
console.log("keydown Event Listener set.");

function onKeyUp(key) {
   delete heldKeys[key.keyCode];
}
window.addEventListener("keyup", onKeyUp, false);
console.log("keyup Event Listener set.");

console.log("About to render first frame!");
function update() {
   context.clearRect(0, 0, canvas.width, canvas.height);

   for(var i = 0; i < boxes.length; i++)
      boxes[i].render();

   //player.update();
   /*
   for(var i =0; i < boxes.length; i++)
      player.adjustVelocityByCollision(boxes[i]);
   */

   if(input.getKeyDown(keyCode.upArrow) || input.getKeyDown(keyCode.spacebarKey)) {
      if(!player.jumping && player.grounded) {
         player.yVelocity = -JUMP_VELOCITY;
         player.grounded = false;
         player.jumping = true;
      }
   }

   if(input.getKeyDown(keyCode.leftArrow) && player.xVelocity > -SPEED)
      player.xVelocity -= ACCELERATION;

   if(input.getKeyDown(keyCode.rightArrow) && player.xVelocity < SPEED)
      player.xVelocity += ACCELERATION;

   player.xVelocity *= FRICTION;
   player.yVelocity += GRAVITY;

   player.y += player.yVelocity;
   player.x += player.xVelocity;

   context.clearRect(0, 0, canvas.width, canvas.height);

   for(var i = 0; i < boxes.length; i++) {

      player.grounded = false;

      var collDir = collisionChecker.testCollision(player, boxes[i]);

      if(collDir === "r" || collDir === "l") {
         player.xVelocity = 0;
         player.jumping = false;
         console.log("Player received a collision on the " + ((collDir === "r") ? "right" : "left") + "!");
      } else if(collDir === "b") {
         player.grounded = true;
         player.yVelocity = 0;
         player.jumping = false;
         console.log("Player received a collision on the bottom!");
      } else if(collDir === "t") {
         player.yVelocity = 0;
      }
      render(boxes[i]);
   }
   render(player);
}

function game() {
   update();
   requestAnimationFrame(game);
}
window.addEventListener("load", game);

function clamp(value, min, max) {
   if(value > max)
      return max;
   else if(value < min)
      return min

   return value;
}

function render(object) {
   object.x = clamp(object.x, 0, canvas.width - BOX_SIZE);
   object.y = clamp(object.y, 0, canvas.height - BOX_SIZE);
   context.fillStyle = object.colour;
   context.fillRect(object.x, object.y, object.width, object.height, object.colour);
}

function check(object) {
   if(!object || object === null) {
      console.error(object.constructor.name + " is NULL.");
      return false;
   } else {
      //console.group("Properties of " + object.constructor.name + ": ");
      console.log(object.constructor.name + " has been created.")
      return true;
   }
}

var collisionChecker = {
   quickBoxTest: function(boxA, boxB) {
      if(boxA.x < boxB.x + boxB.width && boxA.x + boxA.width > boxB.x && boxA.y < boxB.y + boxB.height && boxA.height + boxA.y > boxB.y)
         return true;

      return false;
   },

   testCollision: function(objectA, objectB) {
    //Find the collision vectors
    var vectorX = (objectA.x + (objectA.width / 2)) - (objectB.x + (objectB.width / 2));
    var vectorY = (objectA.y + (objectA.height / 2)) - (objectB.y + (objectB.height / 2));

    //Find the distance between the two objects
    var deltaWidth = (objectA.width / 2) + (objectB.width / 2);
    var deltaHeight = (objectA.height / 2) + (objectB.height / 2);

    //Stores the direction of collision
    var collisionDir = null;

    //Check if the two objects are intersecting on the x and y axis
    if(Math.abs(vectorX) < deltaWidth && Math.abs(vectorY) < deltaHeight)
    {
        //The direction of collision
        var directionX = deltaWidth - Math.abs(vectorX);
        var directionY = deltaHeight - Math.abs(vectorY);

        //Check for vertical collision
        if(directionX >= directionY)
        {
            //Check for collisions from the top
            if(vectorY > 0)
            {
                objectA.y += directionY;
                collisionDir = "t";
            }

            //Collisions form the botttom
            else
            {
                objectA.y -= directionY;
                collisionDir = "b";
            }
        }
        else
        {
            //Check for collisions from the left
            if(vectorX > 0)
            {
                objectA.x += directionX;
                collisionDir = "l";
            }

            //Collisions form the right side
            else
            {
                objectA.x -= directionX;
                collisionDir = "r";
            }
        }
    }

    //Return the direction.
    return collisionDir;
   }
}

var input = {
   getKeyDown: function(keyToCheck) {
      if(heldKeys[keyToCheck] === true)
         return true
      else
   return false;
   }
}

var keyCode = {
   upArrow: 38,
   downArrow: 40,
   leftArrow: 37,
   rightArrow: 39,

   wKey: 87,
   aKey: 65,
   sKey: 83,
   dKey: 68,

   spacebarKey: 32
}
<|endoftext|>


<commit_before>'use strict';

const bulk = require('bulk-require');
const types = bulk(__dirname, 'types/*.js');

module.exports = {
    getType(type, custom) {
        return Object.assign({}, lib.types.default, lib.types[type], custom);
    },

    getAllTypes(custom) {
        var all = [];

        for(var type in lib.types) {
            if(type !== 'default') {
                all.push(module.exports.getType(type, custom));
            }
        }
        return all;
    }
};<commit_msg>re-fix<commit_after>'use strict';

const bulk = require('bulk-require');
const lib = bulk(__dirname, 'types/*.js');

module.exports = {
    getType(type, custom) {
        return Object.assign({}, lib.types.default, lib.types[type], custom);
    },

    getAllTypes(custom) {
        var all = [];

        for(var type in lib.types) {
            if(type !== 'default') {
                all.push(module.exports.getType(type, custom));
            }
        }
        return all;
    }
};<|endoftext|>