<commit_before>"use strict";

var fs = require("fs");
var path = require("path");
var Sequelize = require("sequelize");
var config = {host: process.env.UEKPLAN_DB_HOST || 'localhost', dialect: 'mysql', logging: console.log};
var sequelize = new Sequelize('uekplan', process.env.UEKPLAN_DB_USERNAME, process.env.UEKPLAN_DB_PASSWORD, config);
var db = {};

fs
    .readdirSync(__dirname + "/models")
    .filter(function (file) {
        return (file.indexOf(".") !== 0);
    })
    .forEach(function (file) {
        var model = sequelize.import(path.join(__dirname + '/models', file));
        db[model.name] = model;
    });

Object.keys(db).forEach(function (modelName) {
    if ("associate" in db[modelName]) {
        db[modelName].associate(db);
    }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;<commit_msg>Use arrow function<commit_after>"use strict";

var fs = require("fs");
var path = require("path");
var Sequelize = require("sequelize");
var config = {host: process.env.UEKPLAN_DB_HOST || 'localhost', dialect: 'mysql', logging: console.log};
var sequelize = new Sequelize('uekplan', process.env.UEKPLAN_DB_USERNAME, process.env.UEKPLAN_DB_PASSWORD, config);
var db = {};

fs
    .readdirSync(__dirname + "/models")
    .filter((file)=> {
        return (file.indexOf(".") !== 0);
    })
    .forEach((file)=> {
        var model = sequelize.import(path.join(__dirname + '/models', file));
        db[model.name] = model;
    });

Object.keys(db).forEach((modelName) => {
    if ("associate" in db[modelName]) {
        db[modelName].associate(db);
    }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;<|endoftext|>


<commit_before>var postcss = require('postcss');

const DEBUG = false;
const SUPPORT_PROPS = ['float', 'clear', 'text-align', 'padding-inline-start', 'padding-inline-end',
    'border-inline-start', 'border-inline-end', 'border-inline-start-color', 'border-inline-end-color',
    'border-inline-start-style', 'border-inline-end-style',
    'border-inline-start-width', 'border-inline-end-width',
    'border-inline-start-top', 'border-inline-end-top',
    'border-top-inline-start-radius', 'border-top-inline-end-radius',
    'border-bottom-inline-start-radius', 'border-bottom-inline-end-radius',
    'margin-inline-start', 'margin-inline-end',
    'offset-inline-start', 'offset-inline-end'
];

function log(...args) {
    (args || []).forEach(arg => {
        if (DEBUG) console.log(JSON.stringify(arg, null, 2));
    });
}

function cloneItem(item) {
    let newRule = item.clone();
    newRule.raws.before = item.raws.before;
    newRule.raws.after = item.raws.after;
    newRule.raws.between = item.raws.between;
    return newRule;
}

// process LTR by default, process RTL when reverseFlag is set
function processProps(decl, reverseFlag) {
    let isDirty = true;
    let start = !reverseFlag ? 'left' : 'right';
    let end = !reverseFlag ? 'right' : 'left';
    switch (decl.prop.toLowerCase()) {
    case 'float':
    case 'clear':
    case 'text-align':
        if(['start', 'end'].indexOf(decl.value.toLowerCase()) !== -1) {
            if (decl.value.toLowerCase() === 'start') {
                decl.value = start;
            } else {
                decl.value = end;
            }
        }
        break;
    case 'padding-inline-start':
        decl.prop = 'padding-' + start;
        break;
    case 'padding-inline-end':
        decl.prop = 'padding-' + end;
        break;
    case 'border-inline-start':
        decl.prop = 'border-' + start;
        break;
    case 'border-inline-end':
        decl.prop = 'border-' + end;
        break;
    case 'border-inline-start-color':
        decl.prop = 'border-' + start + '-color';
        break;
    case 'border-inline-end-color':
        decl.prop = 'border-' + end + '-color';
        break;
    case 'border-inline-start-width':
        decl.prop = 'border-' + start + '-width';
        break;
    case 'border-inline-end-width':
        decl.prop = 'border-' + end + '-width';
        break;
    case 'border-inline-start-style':
        decl.prop = 'border-' + start + '-style';
        break;
    case 'border-inline-end-style':
        decl.prop = 'border-' + end + '-style';
        break;
    case 'border-top-inline-start-radius':
        decl.prop = 'border-top-' + start + '-radius';
        break;
    case 'border-top-inline-end-radius':
        decl.prop = 'border-top-' + end + '-radius';
        break;
    case 'border-bottom-inline-start-radius':
        decl.prop = 'border-bottom-' + start + '-radius';
        break;
    case 'border-bottom-inline-end-radius':
        decl.prop = 'border-bottom-' + end + '-radius';
        break;
    case 'margin-inline-start':
        decl.prop = 'margin-' + start;
        break;
    case 'margin-inline-end':
        decl.prop = 'margin-' + end;
        break;
    case 'offset-inline-start':
        decl.prop = start;
        break;
    case 'offset-inline-end':
        decl.prop = end;
        break;
    default:
        isDirty = false;
        break;
    }

    if (isDirty) log(decl.prop + ' : ' + decl.value);

    const newDecl = decl;
    return { newDecl, isDirty };
}

function isSupportedProps(decl) {
    if (SUPPORT_PROPS.indexOf(decl.prop.toLowerCase()) > -1) {
        return true;
    }
}

function updateRtlRule(item) {
    return item.rtlNodes.filter(decl => {
        const { newDecl, isDirty } = processProps(decl, true);
        if (isDirty) {
            return newDecl;
        }
    });
}

function updateLtrRule(item) {
    return item.ltrNodes.filter(decl => {
        const { newDecl, isDirty } = processProps(decl);
        if (isDirty) {
            return newDecl;
        }
    });
}

function updateRtlItem(item, reverseFlag) {
    let rule = reverseFlag ? item.ltrRule : item.rtlRule;
    for ( let i in rule ) {
        if ( !rule.hasOwnProperty(i) ) {
            continue;
        }

        if ( rule[i] instanceof Array ) {
            rule[i] = reverseFlag ? updateLtrRule(item) : updateRtlRule(item);
        }
    }

    return item;
}

function updateLtrItem(item) {
    return updateRtlItem(item, true);
}

function postcssBiDirection(opts) {
    opts = opts || {};
    const PATTERN = /\s*[,\n]+\s*/;

    // Work with options here

    return function (root) {
        let tree = [];
        let idx = 0;
        let currentIdx;

        // Rebuild tree for reuse
        root.walk(function (item) {
            if (item.type === 'rule') {
                tree[idx] = {
                    rule:     item,
                    nodes:    [],
                    ltrRule:  cloneItem(item),
                    ltrNodes: [],
                    rtlRule:  cloneItem(item),
                    rtlNodes: [],
                    isBiDi:   false
                };
                currentIdx = idx;
                idx += 1;
            } else if (item.type === 'decl') {
                tree[currentIdx].nodes.push(item);
                tree[currentIdx].ltrNodes.push(cloneItem(item));
                tree[currentIdx].rtlNodes.push(cloneItem(item));
            }
        });

        // Transform CSS AST here
        // Unefficient but works

        // default
        tree.forEach(item => {
            item.nodes = item.nodes.filter(decl => {
              if (isSupportedProps(decl)) {
                  item.isBiDi = true;
              }
              return decl;
            });
        });

        tree.forEach((item) => {
            if (item.isBiDi) {
                // LTR
                // modified from postcss internal clone method
                updateLtrItem(item, true);

                item.ltrRule.raws.before = "\n\n" + item.ltrRule.raws.before.replace(/^\n\n/,"");
                item.rule.parent.insertAfter(item.rule, item.ltrRule);

                // prefix each comma-separated selector
                item.ltrRule.selector = item.ltrRule.selector
                    .split(PATTERN)
                    .map(function(selector, i) {
                        return ("html[dir=\"ltr\"] " + selector);
                    })
                    .join(',\n');

                // RTL
                updateRtlItem(item);

                item.rtlRule.raws.before = "\n\n" + item.rtlRule.raws.before.replace(/^\n\n/,"");
                item.ltrRule.parent.insertAfter(item.ltrRule, item.rtlRule);

                // prefix each comma-separated selector
                item.rtlRule.selector = item.rtlRule.selector
                    .split(PATTERN)
                    .map(function(selector, i) {
                        return ("html[dir=\"rtl\"] " + selector);
                    })
                    .join(',\n');

                log('<', item.rule.raw.before,
                    '>', item.rtlRule.raw.before);
            }
        });
    };
}

module.exports = postcss.plugin('postcss-bidirection', postcssBiDirection);
<commit_msg>remove extrra space<commit_after>var postcss = require('postcss');

const DEBUG = false;
const SUPPORT_PROPS = ['float', 'clear', 'text-align', 'padding-inline-start', 'padding-inline-end',
    'border-inline-start', 'border-inline-end', 'border-inline-start-color', 'border-inline-end-color',
    'border-inline-start-style', 'border-inline-end-style',
    'border-inline-start-width', 'border-inline-end-width',
    'border-inline-start-top', 'border-inline-end-top',
    'border-top-inline-start-radius', 'border-top-inline-end-radius',
    'border-bottom-inline-start-radius', 'border-bottom-inline-end-radius',
    'margin-inline-start', 'margin-inline-end',
    'offset-inline-start', 'offset-inline-end'
];

function log(...args) {
    (args || []).forEach(arg => {
        if (DEBUG) console.log(JSON.stringify(arg, null, 2));
    });
}

function cloneItem(item) {
    let newRule = item.clone();
    newRule.raws.before = item.raws.before;
    newRule.raws.after = item.raws.after;
    newRule.raws.between = item.raws.between;
    return newRule;
}

// process LTR by default, process RTL when reverseFlag is set
function processProps(decl, reverseFlag) {
    let isDirty = true;
    let start = !reverseFlag ? 'left' : 'right';
    let end = !reverseFlag ? 'right' : 'left';
    switch (decl.prop.toLowerCase()) {
    case 'float':
    case 'clear':
    case 'text-align':
        if(['start', 'end'].indexOf(decl.value.toLowerCase()) !== -1) {
            if (decl.value.toLowerCase() === 'start') {
                decl.value = start;
            } else {
                decl.value = end;
            }
        }
        break;
    case 'padding-inline-start':
        decl.prop = 'padding-' + start;
        break;
    case 'padding-inline-end':
        decl.prop = 'padding-' + end;
        break;
    case 'border-inline-start':
        decl.prop = 'border-' + start;
        break;
    case 'border-inline-end':
        decl.prop = 'border-' + end;
        break;
    case 'border-inline-start-color':
        decl.prop = 'border-' + start + '-color';
        break;
    case 'border-inline-end-color':
        decl.prop = 'border-' + end + '-color';
        break;
    case 'border-inline-start-width':
        decl.prop = 'border-' + start + '-width';
        break;
    case 'border-inline-end-width':
        decl.prop = 'border-' + end + '-width';
        break;
    case 'border-inline-start-style':
        decl.prop = 'border-' + start + '-style';
        break;
    case 'border-inline-end-style':
        decl.prop = 'border-' + end + '-style';
        break;
    case 'border-top-inline-start-radius':
        decl.prop = 'border-top-' + start + '-radius';
        break;
    case 'border-top-inline-end-radius':
        decl.prop = 'border-top-' + end + '-radius';
        break;
    case 'border-bottom-inline-start-radius':
        decl.prop = 'border-bottom-' + start + '-radius';
        break;
    case 'border-bottom-inline-end-radius':
        decl.prop = 'border-bottom-' + end + '-radius';
        break;
    case 'margin-inline-start':
        decl.prop = 'margin-' + start;
        break;
    case 'margin-inline-end':
        decl.prop = 'margin-' + end;
        break;
    case 'offset-inline-start':
        decl.prop = start;
        break;
    case 'offset-inline-end':
        decl.prop = end;
        break;
    default:
        isDirty = false;
        break;
    }

    if (isDirty) log(decl.prop + ' : ' + decl.value);

    const newDecl = decl;
    return { newDecl, isDirty };
}

function isSupportedProps(decl) {
    if (SUPPORT_PROPS.indexOf(decl.prop.toLowerCase()) > -1) {
        return true;
    }
}

function updateRtlRule(item) {
    return item.rtlNodes.filter(decl => {
        const { newDecl, isDirty } = processProps(decl, true);
        if (isDirty) {
            return newDecl;
        }
    });
}

function updateLtrRule(item) {
    return item.ltrNodes.filter(decl => {
        const { newDecl, isDirty } = processProps(decl);
        if (isDirty) {
            return newDecl;
        }
    });
}

function updateRtlItem(item, reverseFlag) {
    let rule = reverseFlag ? item.ltrRule : item.rtlRule;
    for ( let i in rule ) {
        if ( !rule.hasOwnProperty(i) ) {
            continue;
        }

        if ( rule[i] instanceof Array ) {
            rule[i] = reverseFlag ? updateLtrRule(item) : updateRtlRule(item);
        }
    }

    return item;
}

function updateLtrItem(item) {
    return updateRtlItem(item, true);
}

function postcssBiDirection(opts) {
    opts = opts || {};
    const PATTERN = /\s*[,\n]+\s*/;

    // Work with options here

    return function (root) {
        let tree = [];
        let idx = 0;
        let currentIdx;

        // Rebuild tree for reuse
        root.walk(function (item) {
            if (item.type === 'rule') {
                tree[idx] = {
                    rule:     item,
                    nodes:    [],
                    ltrRule:  cloneItem(item),
                    ltrNodes: [],
                    rtlRule:  cloneItem(item),
                    rtlNodes: [],
                    isBiDi:   false
                };
                currentIdx = idx;
                idx += 1;
            } else if (item.type === 'decl') {
                tree[currentIdx].nodes.push(item);
                tree[currentIdx].ltrNodes.push(cloneItem(item));
                tree[currentIdx].rtlNodes.push(cloneItem(item));
            }
        });

        // Transform CSS AST here
        // Unefficient but works

        // default
        tree.forEach(item => {
            item.nodes = item.nodes.filter(decl => {
              if (isSupportedProps(decl)) {
                  item.isBiDi = true;
              }
              return decl;
            });
        });

        tree.forEach((item) => {
            if (item.isBiDi) {
                // LTR
                // modified from postcss internal clone method
                updateLtrItem(item, true);

                item.ltrRule.raws.before = "\n\n" + item.ltrRule.raws.before.replace(/^\n\n/,"");
                item.rule.parent.insertAfter(item.rule, item.ltrRule);

                // prefix each comma-separated selector
                item.ltrRule.selector = item.ltrRule.selector
                    .split(PATTERN)
                    .map(function(selector, i) {
                        return ("html[dir=\"ltr\"] " + selector);
                    })
                    .join(',\n');

                // RTL
                updateRtlItem(item);

                item.rtlRule.raws.before = "\n\n" + item.rtlRule.raws.before.replace(/^\n\n/,"");
                item.ltrRule.parent.insertAfter(item.ltrRule, item.rtlRule);

                // prefix each comma-separated selector
                item.rtlRule.selector = item.rtlRule.selector
                    .split(PATTERN)
                    .map(function(selector, i) {
                        return ("html[dir=\"rtl\"] " + selector);
                    })
                    .join(',\n');

                log('<', item.rule.raw.before,
                    '>', item.rtlRule.raw.before);
            }
        });
    };
}

module.exports = postcss.plugin('postcss-bidirection', postcssBiDirection);
<|endoftext|>


<commit_before>var through = require('through'),
    select = require('cssauron-falafel'),
    falafel = require('falafel'),
    fs = require('fs'),
    path = require('path'),
    CWD = process.cwd()

module.exports = jut

function jut(options) {
  var files = options.file || [],
      started = false,
      relative = /^\./,
      is_require = select('call id[name=require]:first-child + literal')

  return through(parse_files, noop)

  function parse_files(chunk) {
    var self = this
    files.push(chunk.toString())
    if (!started) {
      started = true
      read_file(files.shift())
    }

    function read_file(filename) {
      fs.readFile(path.resolve(CWD, filename), 'utf8', process_file)

      function process_file(err, data) {
        if (err) {
          process.exit(1)
        }

        var has_matched = false,
            required,
            req_string

        data = 'function _____() {\n' + data + '\n}'

        falafel(data, function(node) {
          required = is_require(node)
          if (!required) return

          req_string = required.value

          if (relative.test(req_string)) {
            req_string = path.resolve(CWD, req_string)
          }

          if (options.module.indexOf(req_string) > -1) {
            found_match(required.value)
          }
        })

        if (!files.length) return self.queue(null)
        read_file(files.shift())

        function found_match(module_name) {
          if (!has_matched) {
            has_matched = true

            self.queue(
              (options.fullpath ? path.resolve(CWD, filename) : filename) +
              '\n'
            )
          }

          if (options.justmatch) return

          self.queue('===\n' + module_name + '\n')
        }
      }
    }
  }
}

function noop() {}
<commit_msg>workingish<commit_after>var through = require('through'),
    select = require('cssauron-falafel'),
    falafel = require('falafel'),
    fs = require('fs'),
    path = require('path'),
    CWD = process.cwd()

module.exports = jut

function jut(options) {
  var files = options.file || [],
      started = false,
      relative = /^\./,
      is_require = select('call id[name=require]:first-child + literal')

  return through(parse_files, noop)

  function parse_files(chunk) {
    var self = this
    files.push(chunk.toString())
    if (!started) {
      started = true
      read_file(files.shift())
    }

    function read_file(filename) {
      fs.readFile(path.resolve(CWD, filename), 'utf8', process_file)

      function process_file(err, data) {
        if (err) {
          process.exit(1)
        }

        var has_matched = false,
            required,
            req_string

        data = data.replace(/^#!(.*?)\n/, '')

        data = 'function _____() {\n' + data + '\n}'

        falafel(data, function(node) {
          required = is_require(node)
          if (!required) return

          req_string = required.value

          if (relative.test(req_string)) {
            req_string = path.resolve(CWD, req_string)
          }

          if (options.module.indexOf(req_string) > -1) {
            found_match(required.value)
          }
        })

        if (!files.length) return self.queue(null)
        read_file(files.shift())

        function found_match(module_name) {
          if (!has_matched) {
            has_matched = true

            self.queue(
              (options.fullpath ? path.resolve(CWD, filename) :
                  path.relative(CWD, filename)) +
              '\n' + (options.justmatch ? '' : '===\n')
            )
          }

          if (options.justmatch) return

          self.queue(module_name + '\n')
        }
      }
    }
  }
}

function noop() {}
<|endoftext|>


<commit_before>
/**
 * Module dependencies
 */
var Resource      = require('deployd/lib/resource'),
    util          = require('util'),
    mongoose      = require('mongoose'),
    gcm           = require('node-gcm'),
    apn           = require('apn');

/**
 * Module setup.
 */
function Pushnotifications( options ) {
  Resource.apply(this, arguments);

  // see https://github.com/ToothlessGear/node-gcm
  // and https://github.com/argon/node-apn

  this.gcmSender = new gcm.Sender(this.config.gcmApiServerKey);

  var options = {
    "gateway": (this.config.apnGateway || "gateway.sandbox.push.apple.com"),
    "cert": (this.config.certPemLocation || __dirname + "/../../config/cert.pem"),
    "key": (this.config.keyPemLocation || __dirname + "/../../config/key.pem")
  };
  this.apnConnection = new apn.Connection(options);

  // mongodb connection string

  var connectionString = "mongodb://"
  if (process.env.MONGO_DB_USERNAME && process.env.MONGO_DB_PASSWORD) {
    connectionString += (process.env.MONGO_DB_USERNAME + ":" + process.env.MONGO_DB_PASSWORD + "@");
  }
  connectionString += (process.env.MONGO_DB_HOST || '127.0.0.1');
  if (process.env.MONGO_DB_PORT) {
    connectionString += ":" + Number(process.env.MONGO_DB_PORT)+1;
  }
  connectionString += "/";
  if (process.env.MONGO_DB_NAME) {
      connectionString += process.env.MONGO_DB_NAME;
  } else {
    if (process.env.NODE_ENV === 'development') {
      connectionString += this.config.developmentDbName;
    } else {
      connectionString += this.config.productionDbName;
    }
  }

  var db = mongoose.createConnection(connectionString);
  db.on('error', console.error.bind(console, 'connection error:'));
  db.once('open', function callback () {
    this.pushNotificationSchema = mongoose.Schema({
        title: String,
        message: String,
        registrationIds: Array,
        apnToken: String
    });
    this.pushNotificationModel = mongoose.model('PersistedPushNotification', this.pushNotificationSchema);
    this.pushNotificationModel.find(function (err, pushNotifications) {
      if (err) return console.error(err);
      console.log(pushNotifications);
    })

  });
}

util.inherits( Pushnotifications, Resource );

Pushnotifications.prototype.clientGeneration = true;

Pushnotifications.basicDashboard = {
  settings: [
    {
      name        : 'gcmApiServerKey',
      type        : 'string',
      description : 'GCM API Server Key'
    },
    {
      name        : 'apnGateway',
      type        : 'string',
      description : 'APN Gateway. Defaults to sandbox'
    },
    {
      name        : 'defaultTitle',
      type        : 'string',
      description : 'Default title of the push notification. Defaults to \'Notification\''
    },
    {
      name        : 'defaultMessage',
      type        : 'string',
      description : 'Default message of the push notification. Defaults to \'Hi, something came up!\''
    },
    {
      name        : 'defaultTTL',
      type        : 'number',
      description : 'Default time to live of the push notification. Defaults to 3000 seconds'
    },
    {
      name        : 'certPemLocation',
      type        : 'string',
      description : 'Location of the cert.pem-File. Defaults to file named cert.pem in the config-directory of the app.'
    },
    {
      name        : 'keyPemLocation',
      type        : 'string',
      description : 'Location of the key.pem-File. Defaults to file named key.pem in the config-directory of the app.'
    },
    {
      name        : "developmentDbName",
      type        : 'string',
      description : 'Name of the MongoDB in development environment.'
    },
    {
      name        : "productionDbName",
      type        : 'string',
      description : 'Name of the MongoDB in production environment.'
    }
  ]
};

/**
 * Module methodes
 */
Pushnotifications.prototype.handle = function ( ctx, next ) {

  if (ctx.body.gcmRegistrationIds) {
    var registrationIds = ctx.body.gcmRegistrationIds;

    // the payload data to send...
    var message = new gcm.Message();

    var titleData;
    if (ctx.body.title) {
      titleData = ctx.body.title;
    } else {
      titleData = this.config.defaultTitle || 'Notification';
    }
    message.addData('title', titleData);

    var messageData;
    if (ctx.body.message) {
      messageData = ctx.body.message;
    } else {
      messageData = this.config.defaultMessage || 'Hi, something came up!';
    }
    message.addData('message', messageData);

    if (ctx.body.timeToLive) {
      message.timeToLive = ctx.body.timeToLive;
    } else {
      message.timeToLive = this.config.defaultTTL || 3000;
    }

    if (ctx.body.msgcnt) {
      message.addData('msgcnt', ctx.body.msgcnt);
    }
    if (ctx.body.soundname) {
      message.addData('soundname', ctx.body.soundname);
    }
    if (ctx.body.collapseKey) {
      message.collapseKey = ctx.body.collapseKey;
    }
    if (ctx.body.delayWhileIdle) {
      message.delayWhileIdle = ctx.body.delayWhileIdle;
    }

    /**
     * Parameters: message-literal, registrationIds-array, No. of retries, callback-function
     */
    this.gcmSender.send(message, registrationIds, 4, function (err, result) {
      if (err) {
        ctx.done(err);
      } else {
        ctx.done(null, result);
      }
    });

    (new this.pushNotificationModel({ message: messageData, title: titleData })).save();
  }

  if (ctx.body.apnTokens) {
    var index = 0,
        token = "",
        device = {},
        note = {};
    for (; index < ctx.body.apnTokens.length; index++) {
      token = ctx.body.apnTokens[index];
      device = new apn.Device(token);
      note = new apn.Notification();

      if (ctx.body.timeToLive) {
        note.expiry = ctx.body.timeToLive;
      } else {
        note.expiry = this.config.defaultTTL || 3000;
      }

      if (ctx.body.msgcnt) {
        note.badge = ctx.body.msgcnt;
      } else {
        note.badge = 1;
      }

      if (ctx.body.soundname) {
        note.sound = ctx.body.soundname;
      }

      if (ctx.body.message) {
        note.alert = ctx.body.message;
      } else {
        note.alert = this.config.defaultMessage || 'Hi, something came up!';
      }
      //note.payload = {'messageFrom': 'Caroline'};

      this.apnConnection.pushNotification(note, device);

      (new this.pushNotificationModel({ message: note.alert, apnToken: token })).save();
    }
  }

};

/**
 * Module export
 */
module.exports = Pushnotifications;<commit_msg>debug schema and model<commit_after>
/**
 * Module dependencies
 */
var Resource = require('deployd/lib/resource'),
    util     = require('util'),
    mongoose = require('mongoose'),
    gcm      = require('node-gcm'),
    apn      = require('apn');

mongoose.model('PushNotification', new mongoose.Schema{
  title: String,
  message: String,
  registrationIds: Array,
  apnToken: String
});

/**
 * Module setup.
 */
function Pushnotifications( options ) {
  Resource.apply(this, arguments);

  // see https://github.com/ToothlessGear/node-gcm
  // and https://github.com/argon/node-apn

  this.gcmSender = new gcm.Sender(this.config.gcmApiServerKey);

  var options = {
    "gateway": (this.config.apnGateway || "gateway.sandbox.push.apple.com"),
    "cert": (this.config.certPemLocation || __dirname + "/../../config/cert.pem"),
    "key": (this.config.keyPemLocation || __dirname + "/../../config/key.pem")
  };
  this.apnConnection = new apn.Connection(options);

  // mongodb connection string

  var connectionString = "mongodb://"
  if (process.env.MONGO_DB_USERNAME && process.env.MONGO_DB_PASSWORD) {
    connectionString += (process.env.MONGO_DB_USERNAME + ":" + process.env.MONGO_DB_PASSWORD + "@");
  }
  connectionString += (process.env.MONGO_DB_HOST || '127.0.0.1');
  if (process.env.MONGO_DB_PORT) {
    connectionString += ":" + Number(process.env.MONGO_DB_PORT);
  }
  connectionString += "/";
  if (process.env.MONGO_DB_NAME) {
      connectionString += process.env.MONGO_DB_NAME;
  } else {
    if (process.env.NODE_ENV === 'development') {
      connectionString += this.config.developmentDbName;
    } else {
      connectionString += this.config.productionDbName;
    }
  }

  var db = mongoose.createConnection(connectionString);
  db.on('error', console.error.bind(console, 'connection error:'));
  db.once('open', function callback () {
    this.pushNotificationModel = db.model('PushNotification');
    this.pushNotificationModel.find(function (err, pushNotifications) {
      if (err) return console.error(err);
      console.log(pushNotifications);
    })

  });
}

util.inherits( Pushnotifications, Resource );

Pushnotifications.prototype.clientGeneration = true;

Pushnotifications.basicDashboard = {
  settings: [
    {
      name        : 'gcmApiServerKey',
      type        : 'string',
      description : 'GCM API Server Key'
    },
    {
      name        : 'apnGateway',
      type        : 'string',
      description : 'APN Gateway. Defaults to sandbox'
    },
    {
      name        : 'defaultTitle',
      type        : 'string',
      description : 'Default title of the push notification. Defaults to \'Notification\''
    },
    {
      name        : 'defaultMessage',
      type        : 'string',
      description : 'Default message of the push notification. Defaults to \'Hi, something came up!\''
    },
    {
      name        : 'defaultTTL',
      type        : 'number',
      description : 'Default time to live of the push notification. Defaults to 3000 seconds'
    },
    {
      name        : 'certPemLocation',
      type        : 'string',
      description : 'Location of the cert.pem-File. Defaults to file named cert.pem in the config-directory of the app.'
    },
    {
      name        : 'keyPemLocation',
      type        : 'string',
      description : 'Location of the key.pem-File. Defaults to file named key.pem in the config-directory of the app.'
    },
    {
      name        : "developmentDbName",
      type        : 'string',
      description : 'Name of the MongoDB in development environment.'
    },
    {
      name        : "productionDbName",
      type        : 'string',
      description : 'Name of the MongoDB in production environment.'
    }
  ]
};

/**
 * Module methodes
 */
Pushnotifications.prototype.handle = function ( ctx, next ) {

  if (ctx.body.gcmRegistrationIds) {
    var registrationIds = ctx.body.gcmRegistrationIds;

    // the payload data to send...
    var message = new gcm.Message();

    var titleData;
    if (ctx.body.title) {
      titleData = ctx.body.title;
    } else {
      titleData = this.config.defaultTitle || 'Notification';
    }
    message.addData('title', titleData);

    var messageData;
    if (ctx.body.message) {
      messageData = ctx.body.message;
    } else {
      messageData = this.config.defaultMessage || 'Hi, something came up!';
    }
    message.addData('message', messageData);

    if (ctx.body.timeToLive) {
      message.timeToLive = ctx.body.timeToLive;
    } else {
      message.timeToLive = this.config.defaultTTL || 3000;
    }

    if (ctx.body.msgcnt) {
      message.addData('msgcnt', ctx.body.msgcnt);
    }
    if (ctx.body.soundname) {
      message.addData('soundname', ctx.body.soundname);
    }
    if (ctx.body.collapseKey) {
      message.collapseKey = ctx.body.collapseKey;
    }
    if (ctx.body.delayWhileIdle) {
      message.delayWhileIdle = ctx.body.delayWhileIdle;
    }

    /**
     * Parameters: message-literal, registrationIds-array, No. of retries, callback-function
     */
    this.gcmSender.send(message, registrationIds, 4, function (err, result) {
      if (err) {
        ctx.done(err);
      } else {
        ctx.done(null, result);
      }
    });

    (new this.pushNotificationModel({ message: messageData, title: titleData })).save();
  }

  if (ctx.body.apnTokens) {
    var index = 0,
        token = "",
        device = {},
        note = {};
    for (; index < ctx.body.apnTokens.length; index++) {
      token = ctx.body.apnTokens[index];
      device = new apn.Device(token);
      note = new apn.Notification();

      if (ctx.body.timeToLive) {
        note.expiry = ctx.body.timeToLive;
      } else {
        note.expiry = this.config.defaultTTL || 3000;
      }

      if (ctx.body.msgcnt) {
        note.badge = ctx.body.msgcnt;
      } else {
        note.badge = 1;
      }

      if (ctx.body.soundname) {
        note.sound = ctx.body.soundname;
      }

      if (ctx.body.message) {
        note.alert = ctx.body.message;
      } else {
        note.alert = this.config.defaultMessage || 'Hi, something came up!';
      }
      //note.payload = {'messageFrom': 'Caroline'};

      this.apnConnection.pushNotification(note, device);

      (new this.pushNotificationModel({ message: note.alert, apnToken: token })).save();
    }
  }

};

/**
 * Module export
 */
module.exports = Pushnotifications;<|endoftext|>


<commit_before>/* module make possible connectoin thru socket.io on a server */

(function() {
    'use strict';

    var main            = global.cloudcmd.main,
        DIR             = main.DIR,
        SRVDIR          = main.SRVDIR,

        io              = main.require('socket.io'),
        update          = main.srvrequire('update'),

        exec            = main.child_process.exec,
        spawn           = main.child_process.spawn,

        Util            = main.util,
        path            = main.path,
        mainpackage     = main.mainpackage,
        equalPart       = Util.isContainStrAtBegin,
        CLOUDCMD        = mainpackage.name,
        ClientFuncs     = [],
        ClientDirs      = [],
        Clients         = [],
        INFO_LOG_LEVEL  = 2,
        ENV             = process.env,
        WIN32           = main.WIN32,
        HELP            = {
            stdout  : CLOUDCMD + ' exit     \n' +
                      CLOUDCMD + ' update   \n',
        },

        /* windows commands thet require
         * unicode charset on locales
         * different then English
         */
        Win32Commands   = ['ASSOC', 'AT', 'ATTRIB', 'BREAK', 'CACLS', 'CALL',
                            'CD', 'CHCP', 'CHDIR', 'CHKDSK', 'CHKNTFS', 'CLS',
                            'CMD', 'COLOR', 'COMP', 'COMPACT', 'CONVERT', 'COPY',
                            'DATE', 'DEL', 'DIR', 'DISKCOMP', 'DISKCOPY', 'DOSKEY',
                            'ECHO', 'ENDLOCAL', 'ERASE', 'EXIT', 'FC', 'FIND',
                            'FINDSTR', 'FOR', 'FORMAT', 'FTYPE', 'GOTO', 'GRAFTABL',
                            'HELP', 'IF', 'LABEL', 'MD', 'MKDIR', 'MODE', 'MORE',
                            'MOVE', 'PATH', 'PAUSE', 'POPD', 'PRINT', 'PROMPT',
                            'PUSHD', 'RD', 'RECOVER', 'REM', 'REN', 'RENAME',
                            'REPLACE', 'RMDIR', 'SET', 'SETLOCAL', 'SHIFT', 'SORT',
                            'START', 'SUBST', 'TIME', 'TITLE', 'TREE', 'TYPE',
                            'VER', 'VERIFY', 'VOL', 'XCOPY'];

    /**
     * function listen on servers port
     * @pServer {Object} started server object
     */
    exports.listen = function(pServer) {
        var lRet, lConnNum, lMsg;

        if (io) {
            io          = io.listen(pServer);
            lConnNum    = 0;

            io.set('log level', INFO_LOG_LEVEL);

            /*
             * on Win7 application is crashing,
             * when options below is used.
             *
             * https://github.com/LearnBoost/socket.io/issues/1314
             *
             */
            if (!WIN32) {
                io.enable('browser client minification');
                io.enable('browser client gzip');
                io.enable('browser client etag');
            }

            io.set('transports', [
              'websocket',
              'htmlfile',
              'xhr-polling',
              'jsonp-polling'
            ]);

            lRet = io.sockets.on('connection', function (socket) {
                var onDisconect, onConnect;

                ++lConnNum;

                if (!Clients[lConnNum]) {
                    lMsg    = log(lConnNum, 'connected\n');

                    jsonSend(socket, {
                        stdout : lMsg
                    });

                    Clients[lConnNum]   = true;
                    onConnect           = onMessage(lConnNum, socket);
                    onDisconect         = Util.retFunc(disconnect, lConnNum);

                    socket.on('message', onConnect);
                    socket.on('disconnect', function() {
                        socket.removeListener('message', onConnect);
                        socket.removeListener('disconnect', onDisconect);

                        socket = null;
                    });
                } else {
                    lMsg = log(lConnNum, ' in use. Reconnecting...');

                    jsonSend(socket, {
                        stdout: lMsg
                    });

                    socket.disconnect();
                }

            });
        }

        return lRet;
    };

    function disconnect(connNum) {
        OnMessageFuncs  [connNum]  =
        ClientFuncs     [connNum]  = null;

        log(connNum, 'disconnected');
    }

    /**
     * function gets onMessage function
     * that execute needed command
     *
     * @param pConnNum, pSocket
     */
    function onMessage(pConnNum, pSocket) {
        return function(pCommand) {
            var lMsg, lWinCommand, lExec_func, firstChar,
                connName,
                lError, lRet, lExecSymbols, isContain,
                dir, options = {};

            dir = ClientDirs[pConnNum];

            if (!dir)
                dir = ClientDirs[pConnNum] = DIR;

            connName = '#' + pConnNum + ': ';
            Util.log(connName + pCommand);

            if (equalPart(pCommand, CLOUDCMD))
                lRet = onCloudCmd(pCommand, function(json) {
                     jsonSend(pSocket, json);
                });
            else if (equalPart(pCommand, 'cd '))  {
                lRet = true;

                onCD(pCommand, dir, function(json) {
                    var error   = json.stderr,
                        stdout  = json.stdout;

                    if (error)
                        jsonSend(pSocket, json);
                    else
                        ClientDirs[pConnNum] = stdout;
                });
            }

            if (!lRet) {
                /* if we on windows and command is build in
                 * change code page to unicode becouse
                 * windows use unicode on non English versions
                 */
                if (WIN32) {
                    lWinCommand     = pCommand.toUpperCase();

                    if (Win32Commands.indexOf(lWinCommand) >= 0)
                        pCommand    = 'chcp 65001 |' + pCommand;
                }

                if (!ClientFuncs[pConnNum])
                    ClientFuncs[pConnNum] = getExec(function(json, pError, pStderr) {
                        log(pConnNum, pError, 'error');
                        log(pConnNum, pStderr, 'stderror');

                        jsonSend(pSocket, json);
                    });

                lExec_func      = ClientFuncs[pConnNum];
                lExecSymbols    = ['*', '&', '{', '}', '|', '\'', '"'];
                isContain       = Util.isContainStr(pCommand, lExecSymbols);
                firstChar       = pCommand[0];
                options.cwd     = dir;

                if (firstChar === '#') {
                    pCommand    = pCommand.slice(1);
                    pCommand    = connName + pCommand;
                    pCommand    = Util.addNewLine(pCommand);

                    lMsg    = Util.stringifyJSON({
                        stdout: pCommand
                    });

                    io.sockets.emit('message', lMsg);
                } else if (WIN32 || firstChar === ' ' || isContain)
                    exec(pCommand, options, lExec_func);
                else
                    getSpawn(pCommand, options, function(json) {
                        jsonSend(pSocket, json);
                    });
            }
        };
    }

    /**
     * function send result of command to client
     * @param pSocket
     */
    function getExec(callback) {
        return function(pError, pStdout, pStderr) {
            var lErrorStr, lExecStr, lExec,
                lError          = pStderr || pError;

            if (lError) {
                if (Util.isString(lError))
                    lErrorStr   = lError;
                else
                    lErrorStr   = lError.toString();

                lErrorStr = Util.addNewLine(lErrorStr);
            }

            lExec               = {
                stdout : pStdout,
                stderr : lErrorStr || lError
            };

            Util.exec(callback, lExec, pError, pStderr);
        };
    }

    function getSpawn(pCommand, options, callback) {
        var send, cmd,
            args    = pCommand.split(' ');

        pCommand    = args.shift();

        Util.tryCatchLog(function() {
            cmd         = spawn(pCommand, args, options);
        });

        if (cmd) {
            send        = function(error, data) {
                var exec    = {
                        stderr: error,
                        stdout: data
                    };

                Util.exec(callback, exec);
            };

            cmd.stdout.on('data', function(data) {
                send(null, data + '');
            });

            cmd.stderr.on('data', function(error) {
                send(error + '', null);
            });

            cmd.on('error', Util.retFalse);
            cmd.on('close', function (code) {
                cmd = null;
            });
        }
    }

    function onCloudCmd(pCommand, callback) {
        var lRet;

        pCommand = Util.removeStr(pCommand, CLOUDCMD);

        if (!equalPart(pCommand, ' ')) {
            lRet = true;
            Util.exec(callback, HELP);
        }
        else {
            pCommand = Util.removeStr(pCommand, ' ');

            if (equalPart(pCommand, 'update') && update) {
                lRet = true;
                update.get();

                Util.exec(callback, {
                    stdout: Util.addNewLine('update: ok')
                });
            }

            if (Util.strCmp(pCommand, 'exit'))
                process.exit();
        }

        return lRet;
    }

    function onCD(pCommand, currDir, callback) {
        var dir,
            getDir      = WIN32 ? 'chdir' : 'pwd',
            paramDir    = Util.removeStr(pCommand, 'cd ');

        if (equalPart(paramDir, ['/', '~']))
            dir = paramDir;
        else
            dir = path.join(currDir, paramDir);

        exec('cd ' + dir + ' && ' + getDir, function (error, stdout, stderr) {
            var lRet,
                lMsg    = '',
                lError = error || stderr;

            if (lError) {
                lError  = Util.stringifyJSON(lError);
                lMsg    = lError;
            }

            Util.exec(callback, {
                stderr  : lMsg,
                stdout  : Util.rmNewLine(stdout)
            });
        });
    }

    function log(pConnNum, pStr, pType) {
        var lRet,
            lType       = ' ';

        if (pStr) {

            if (pType)
                lType  += pType + ':';

            lRet        = 'client #' + pConnNum + lType + pStr;

            Util.log(lRet);
        }

        return lRet;
    }

    function jsonSend(socket, json) {
        var msg = Util.stringifyJSON(json);
        socket.send(msg);
    }
})();
<commit_msg>refactor(socket)add onConnection<commit_after>/* module make possible connectoin thru socket.io on a server */

(function() {
    'use strict';

    var main            = global.cloudcmd.main,
        DIR             = main.DIR,
        SRVDIR          = main.SRVDIR,

        io              = main.require('socket.io'),
        update          = main.srvrequire('update'),

        exec            = main.child_process.exec,
        spawn           = main.child_process.spawn,

        Util            = main.util,
        path            = main.path,
        mainpackage     = main.mainpackage,
        equalPart       = Util.isContainStrAtBegin,
        CLOUDCMD        = mainpackage.name,
        ClientFuncs     = [],
        ClientDirs      = [],
        Clients         = [],
        INFO_LOG_LEVEL  = 2,
        ENV             = process.env,
        WIN32           = main.WIN32,
        ConNum          = 0,
        HELP            = {
            stdout  : CLOUDCMD + ' exit     \n' +
                      CLOUDCMD + ' update   \n',
        },

        /* windows commands thet require
         * unicode charset on locales
         * different then English
         */
        Win32Commands   = ['ASSOC', 'AT', 'ATTRIB', 'BREAK', 'CACLS', 'CALL',
                            'CD', 'CHCP', 'CHDIR', 'CHKDSK', 'CHKNTFS', 'CLS',
                            'CMD', 'COLOR', 'COMP', 'COMPACT', 'CONVERT', 'COPY',
                            'DATE', 'DEL', 'DIR', 'DISKCOMP', 'DISKCOPY', 'DOSKEY',
                            'ECHO', 'ENDLOCAL', 'ERASE', 'EXIT', 'FC', 'FIND',
                            'FINDSTR', 'FOR', 'FORMAT', 'FTYPE', 'GOTO', 'GRAFTABL',
                            'HELP', 'IF', 'LABEL', 'MD', 'MKDIR', 'MODE', 'MORE',
                            'MOVE', 'PATH', 'PAUSE', 'POPD', 'PRINT', 'PROMPT',
                            'PUSHD', 'RD', 'RECOVER', 'REM', 'REN', 'RENAME',
                            'REPLACE', 'RMDIR', 'SET', 'SETLOCAL', 'SHIFT', 'SORT',
                            'START', 'SUBST', 'TIME', 'TITLE', 'TREE', 'TYPE',
                            'VER', 'VERIFY', 'VOL', 'XCOPY'];

    /**
     * function listen on servers port
     * @pServer {Object} started server object
     */
    exports.listen = function(pServer) {
        var ret;

        if (io) {
            io          = io.listen(pServer);

            io.set('log level', INFO_LOG_LEVEL);

            /*
             * on Win7 application is crashing,
             * when options below is used.
             *
             * https://github.com/LearnBoost/socket.io/issues/1314
             *
             */
            if (!WIN32) {
                io.enable('browser client minification');
                io.enable('browser client gzip');
                io.enable('browser client etag');
            }

            io.set('transports', [
              'websocket',
              'htmlfile',
              'xhr-polling',
              'jsonp-polling'
            ]);

            ret = io.sockets.on('connection', onConnection);
        }

        return lRet;
    };

    function onConnection(socket) {
        var msg, onDisconect, onConnect;

        ++ConNum;

        if (!Clients[ConNum]) {
            msg = log(ConNum, 'connected\n');

            jsonSend(socket, {
                stdout : msg
            });

            Clients[ConNum]   = true;
            onConnect           = onMessage(ConNum, socket);
            onDisconect         = Util.retFunc(disconnect, ConNum);

            socket.on('message', onConnect);
            socket.on('disconnect', function() {
                socket.removeListener('message', onConnect);
                socket.removeListener('disconnect', onDisconect);
            });
        } else {
            msg = log(ConNum, ' in use. Reconnecting...');

            jsonSend(socket, {
                stdout: msg
            });

            socket.disconnect();
        }
    }

    function disconnect(connNum) {
        OnMessageFuncs  [connNum]  =
        ClientFuncs     [connNum]  = null;

        log(connNum, 'disconnected');
    }

    /**
     * function gets onMessage function
     * that execute needed command
     *
     * @param pConnNum, pSocket
     */
    function onMessage(pConnNum, pSocket) {
        return function(pCommand) {
            var lMsg, lWinCommand, lExec_func, firstChar,
                connName,
                lError, lRet, lExecSymbols, isContain,
                dir, options = {};

            dir = ClientDirs[pConnNum];

            if (!dir)
                dir = ClientDirs[pConnNum] = DIR;

            connName = '#' + pConnNum + ': ';
            Util.log(connName + pCommand);

            if (equalPart(pCommand, CLOUDCMD))
                lRet = onCloudCmd(pCommand, function(json) {
                     jsonSend(pSocket, json);
                });
            else if (equalPart(pCommand, 'cd '))  {
                lRet = true;

                onCD(pCommand, dir, function(json) {
                    var error   = json.stderr,
                        stdout  = json.stdout;

                    if (error)
                        jsonSend(pSocket, json);
                    else
                        ClientDirs[pConnNum] = stdout;
                });
            }

            if (!lRet) {
                /* if we on windows and command is build in
                 * change code page to unicode becouse
                 * windows use unicode on non English versions
                 */
                if (WIN32) {
                    lWinCommand     = pCommand.toUpperCase();

                    if (Win32Commands.indexOf(lWinCommand) >= 0)
                        pCommand    = 'chcp 65001 |' + pCommand;
                }

                if (!ClientFuncs[pConnNum])
                    ClientFuncs[pConnNum] = getExec(function(json, pError, pStderr) {
                        log(pConnNum, pError, 'error');
                        log(pConnNum, pStderr, 'stderror');

                        jsonSend(pSocket, json);
                    });

                lExec_func      = ClientFuncs[pConnNum];
                lExecSymbols    = ['*', '&', '{', '}', '|', '\'', '"'];
                isContain       = Util.isContainStr(pCommand, lExecSymbols);
                firstChar       = pCommand[0];
                options.cwd     = dir;

                if (firstChar === '#') {
                    pCommand    = pCommand.slice(1);
                    pCommand    = connName + pCommand;
                    pCommand    = Util.addNewLine(pCommand);

                    lMsg    = Util.stringifyJSON({
                        stdout: pCommand
                    });

                    io.sockets.emit('message', lMsg);
                } else if (WIN32 || firstChar === ' ' || isContain)
                    exec(pCommand, options, lExec_func);
                else
                    getSpawn(pCommand, options, function(json) {
                        jsonSend(pSocket, json);
                    });
            }
        };
    }

    /**
     * function send result of command to client
     * @param pSocket
     */
    function getExec(callback) {
        return function(pError, pStdout, pStderr) {
            var lErrorStr, lExecStr, lExec,
                lError          = pStderr || pError;

            if (lError) {
                if (Util.isString(lError))
                    lErrorStr   = lError;
                else
                    lErrorStr   = lError.toString();

                lErrorStr = Util.addNewLine(lErrorStr);
            }

            lExec               = {
                stdout : pStdout,
                stderr : lErrorStr || lError
            };

            Util.exec(callback, lExec, pError, pStderr);
        };
    }

    function getSpawn(pCommand, options, callback) {
        var send, cmd,
            args    = pCommand.split(' ');

        pCommand    = args.shift();

        Util.tryCatchLog(function() {
            cmd         = spawn(pCommand, args, options);
        });

        if (cmd) {
            send        = function(error, data) {
                var exec    = {
                        stderr: error,
                        stdout: data
                    };

                Util.exec(callback, exec);
            };

            cmd.stdout.on('data', function(data) {
                send(null, data + '');
            });

            cmd.stderr.on('data', function(error) {
                send(error + '', null);
            });

            cmd.on('error', Util.retFalse);
            cmd.on('close', function (code) {
                cmd = null;
            });
        }
    }

    function onCloudCmd(pCommand, callback) {
        var lRet;

        pCommand = Util.removeStr(pCommand, CLOUDCMD);

        if (!equalPart(pCommand, ' ')) {
            lRet = true;
            Util.exec(callback, HELP);
        }
        else {
            pCommand = Util.removeStr(pCommand, ' ');

            if (equalPart(pCommand, 'update') && update) {
                lRet = true;
                update.get();

                Util.exec(callback, {
                    stdout: Util.addNewLine('update: ok')
                });
            }

            if (Util.strCmp(pCommand, 'exit'))
                process.exit();
        }

        return lRet;
    }

    function onCD(pCommand, currDir, callback) {
        var dir,
            getDir      = WIN32 ? 'chdir' : 'pwd',
            paramDir    = Util.removeStr(pCommand, 'cd ');

        if (equalPart(paramDir, ['/', '~']))
            dir = paramDir;
        else
            dir = path.join(currDir, paramDir);

        exec('cd ' + dir + ' && ' + getDir, function (error, stdout, stderr) {
            var lRet,
                lMsg    = '',
                lError = error || stderr;

            if (lError) {
                lError  = Util.stringifyJSON(lError);
                lMsg    = lError;
            }

            Util.exec(callback, {
                stderr  : lMsg,
                stdout  : Util.rmNewLine(stdout)
            });
        });
    }

    function log(pConnNum, pStr, pType) {
        var lRet,
            lType       = ' ';

        if (pStr) {

            if (pType)
                lType  += pType + ':';

            lRet        = 'client #' + pConnNum + lType + pStr;

            Util.log(lRet);
        }

        return lRet;
    }

    function jsonSend(socket, json) {
        var msg = Util.stringifyJSON(json);
        socket.send(msg);
    }
})();
<|endoftext|>


<commit_before>var fs = require('fs');
var {merge} = require('ringo/utils/objects');

var jar = fs.resolve(module.path, './jars/sqlite-jdbc-3.7.2.jar');
addToClasspath(jar);

var dm = java.sql.DriverManager;
dm.registerDriver(new org.sqlite.JDBC);

var Connection = function(path, options) {
    options = merge(options, {
        autocommit: true,
        column_names: true
    });

    this.column_names = options.column_names

    this.connection = dm.getConnection('jdbc:sqlite:' + path);
    this.connection.setAutoCommit(options.autocommit);
}

function prepare_statement(s, values) {
    values.forEach(function(value, index) {
        switch (typeof value) {
            case 'undefined':
                s.setNull(index + 1);
            case 'number':
                (parseFloat(value) == parseInt(value)) ?
                    s.setLong(index + 1, value) :
                    s.setDouble(index + 1, value);
                break;
            case 'boolean':
                s.setBoolean(index + 1, value);
                break;
            case 'object':
                if (value === null) {
                    s.setNull(index + 1);
                    break;
                }

                if (value instanceof Date) {
                    s.setDate(index + 1, new java.sql.Date(value));
                    break;
                }

                // otherwise, fall through to string default
            case 'string':
            default:
                s.setString(index + 1, value);
        }
    });
}

var {NULL, INTEGER, FLOAT, VARCHAR} = java.sql.Types;
function wrap_result(result_set, column_names) {
    var metadata = result_set.getMetaData();
    var column_count = metadata.getColumnCount();

    while (metadata.next()) {
        var row = [];

        for (var i = 1; i <= column_count; i++) {
            var type = metadata.getColumnType(i);
            var value = null;

            switch (type) {
                case NULL:
                    break;
                case INTEGER:
                    value = result_set.getLong(i);
                    break;
                case FLOAT:
                    value = result_set.getDouble(i);
                    break;
                case VARCHAR:
                default:
                    value = result_set.getString(i);
            }

            if (value !== null && result_set.wasNull())
                value = null;

            row.push(value);

            if (column_names) {
                var name = metadata.getColumnName(i);
                row[name] = value;
            }
        }

        yield row;
    }

    result_set.getStatement().close();
    yield null;
}

Connection.prototype.execute = function(query) {
    var statement = this.connection.prepareStatement(query);
    var args = Array.prototype.slice.call(arguments, 1);
    prepare_statement(statement, args);

    if (!statement.execute()) {
        // either an update or no result
        var count = statement.getUpdateCount();
        statement.close();
        return (count > -1) ? count : undefined;
    }

    var iterator = wrap_result(
        statement.getResultSet(),
        this.column_names
    );
    iterator.close = function() { statement.close(); }

    return iterator;
}

Connection.prototype.close = function() {
    this.connection.close();
}

Connection.prototype.commit = function() {
    this.connection.commit();
}

Connection.prototype.rollback = function() {
    this.connection.rollback();
}

Connection.prototype.all = function() {
    var args = Array.prototype.slice.call(arguments);
    var iterator = this.execute.apply(this, args);

    var rows = [];
    for (var row in iterator) {
        if (row !== null) rows.push(row);
    }

    return rows;
}

Connection.prototype.column = function() {
    var args = Array.prototype.slice.call(arguments);
    var iterator = this.execute.apply(this, args);

    var rows = [];
    for (var row in iterator) {
        if (row !== null) rows.push(row[0]);
    }

    return rows;
}

Connection.prototype.row = function() {
    var args = Array.prototype.slice.call(arguments);
    var iterator = this.execute.apply(this, args);

    var row = iterator.next();
    iterator.close();

    return row;
}

Connection.prototype.one = function() {
    var args = Array.prototype.slice.call(arguments);
    var iterator = this.execute.apply(this, args);

    var row = iterator.next() || [null];
    iterator.close();

    return row[0];
}

Connection.prototype.rowid = function() {
    return this.one('select last_insert_rowid()');
}

exports.open = function(path, options) {
    return new Connection(path, options);
}
<commit_msg>New JDBC jar doesn't have the simpler setNull call. Also, fix bug when value is undefined.<commit_after>var fs = require('fs');
var {merge} = require('ringo/utils/objects');

var jar = fs.resolve(module.path, './jars/sqlite-jdbc-3.7.2.jar');
addToClasspath(jar);

var dm = java.sql.DriverManager;
dm.registerDriver(new org.sqlite.JDBC);

var Connection = function(path, options) {
    options = merge(options, {
        autocommit: true,
        column_names: true
    });

    this.column_names = options.column_names

    this.connection = dm.getConnection('jdbc:sqlite:' + path);
    this.connection.setAutoCommit(options.autocommit);
}

function prepare_statement(s, values) {
    values.forEach(function(value, index) {
        switch (typeof value) {
            case 'undefined':
                s.setNull(index + 1, java.sql.Types.NULL);
                break;
            case 'number':
                (parseFloat(value) == parseInt(value)) ?
                    s.setLong(index + 1, value) :
                    s.setDouble(index + 1, value);
                break;
            case 'boolean':
                s.setBoolean(index + 1, value);
                break;
            case 'object':
                if (value === null) {
                    s.setNull(index + 1, java.sql.Types.NULL);
                    break;
                }

                if (value instanceof Date) {
                    s.setDate(index + 1, new java.sql.Date(value));
                    break;
                }

                // otherwise, fall through to string default
            case 'string':
            default:
                s.setString(index + 1, value);
        }
    });
}

var {NULL, INTEGER, FLOAT, VARCHAR} = java.sql.Types;
function wrap_result(result_set, column_names) {
    var metadata = result_set.getMetaData();
    var column_count = metadata.getColumnCount();

    while (metadata.next()) {
        var row = [];

        for (var i = 1; i <= column_count; i++) {
            var type = metadata.getColumnType(i);
            var value = null;

            switch (type) {
                case NULL:
                    break;
                case INTEGER:
                    value = result_set.getLong(i);
                    break;
                case FLOAT:
                    value = result_set.getDouble(i);
                    break;
                case VARCHAR:
                default:
                    value = result_set.getString(i);
            }

            if (value !== null && result_set.wasNull())
                value = null;

            row.push(value);

            if (column_names) {
                var name = metadata.getColumnName(i);
                row[name] = value;
            }
        }

        yield row;
    }

    result_set.getStatement().close();
    yield null;
}

Connection.prototype.execute = function(query) {
    var statement = this.connection.prepareStatement(query);
    var args = Array.prototype.slice.call(arguments, 1);
    prepare_statement(statement, args);

    if (!statement.execute()) {
        // either an update or no result
        var count = statement.getUpdateCount();
        statement.close();
        return (count > -1) ? count : undefined;
    }

    var iterator = wrap_result(
        statement.getResultSet(),
        this.column_names
    );
    iterator.close = function() { statement.close(); }

    return iterator;
}

Connection.prototype.close = function() {
    this.connection.close();
}

Connection.prototype.commit = function() {
    this.connection.commit();
}

Connection.prototype.rollback = function() {
    this.connection.rollback();
}

Connection.prototype.all = function() {
    var args = Array.prototype.slice.call(arguments);
    var iterator = this.execute.apply(this, args);

    var rows = [];
    for (var row in iterator) {
        if (row !== null) rows.push(row);
    }

    return rows;
}

Connection.prototype.column = function() {
    var args = Array.prototype.slice.call(arguments);
    var iterator = this.execute.apply(this, args);

    var rows = [];
    for (var row in iterator) {
        if (row !== null) rows.push(row[0]);
    }

    return rows;
}

Connection.prototype.row = function() {
    var args = Array.prototype.slice.call(arguments);
    var iterator = this.execute.apply(this, args);

    var row = iterator.next();
    iterator.close();

    return row;
}

Connection.prototype.one = function() {
    var args = Array.prototype.slice.call(arguments);
    var iterator = this.execute.apply(this, args);

    var row = iterator.next() || [null];
    iterator.close();

    return row[0];
}

Connection.prototype.rowid = function() {
    return this.one('select last_insert_rowid()');
}

exports.open = function(path, options) {
    return new Connection(path, options);
}
<|endoftext|>


<commit_before>/**
 * This is Barnes Hut simulation algorithm for 3d case. Implementation
 * is highly optimized (avoids recusion and gc pressure)
 *
 * http://www.cs.princeton.edu/courses/archive/fall03/cs126/assignments/barnes-hut.html
 *
 * NOTE: This module duplicates a lot of code from 2d case. Primary reason for
 * this is performance. Every time I tried to abstract away vector opertaions
 * I had negative impact on performance. So in this case I'm sacrifying code
 * reuse in favor of speed
 */

module.exports = function (options) {
  options = options || {};
  options.gravity = typeof options.gravity === 'number' ? options.gravity : -1;
  options.theta = typeof options.theta === 'number' ? options.theta : 0.8;

  // we require deterministic randomness here
  var random = require('ngraph.random').random(1984),
    Node = require('./node'),
    InsertStack = require('./insertStack'),
    isSamePosition = require('./isSamePosition');

  var gravity = options.gravity,
    updateQueue = [],
    insertStack = new InsertStack(),
    theta = options.theta,

    nodesCache = [],
    currentInCache = 0,
    newNode = function () {
      // To avoid pressure on GC we reuse nodes.
      var node = nodesCache[currentInCache];
      if (node) {
        node.quads[0] = null; node.quads[4] = null;
        node.quads[1] = null; node.quads[5] = null;
        node.quads[2] = null; node.quads[6] = null;
        node.quads[3] = null; node.quads[7] = null;
        node.body = null;
        node.mass = node.massX = node.massY = node.massZ = 0;
        node.left = node.right = node.top = node.bottom = node.front = node.back = 0;
      } else {
        node = new Node();
        nodesCache[currentInCache] = node;
      }

      ++currentInCache;
      return node;
    },

    root = newNode(),

    // Inserts body to the tree
    insert = function (newBody) {
      insertStack.reset();
      insertStack.push(root, newBody);

      while (!insertStack.isEmpty()) {
        var stackItem = insertStack.pop(),
          node = stackItem.node,
          body = stackItem.body;

        if (!node.body) {
          // This is internal node. Update the total mass of the node and center-of-mass.
          var x = body.pos.x;
          var y = body.pos.y;
          var z = body.pos.z;
          node.mass += body.mass;
          node.massX += body.mass * x;
          node.massY += body.mass * y;
          node.massZ += body.mass * z;

          // Recursively insert the body in the appropriate quadrant.
          // But first find the appropriate quadrant.
          var quadIdx = 0, // Assume we are in the 0's quad.
            left = node.left,
            right = (node.right + left) / 2,
            top = node.top,
            bottom = (node.bottom + top) / 2,
            back = node.back,
            front = (node.front + back) / 2;

          if (x > right) { // somewhere in the eastern part.
            quadIdx += 1;
            var oldLeft = left;
            left = right;
            right = right + (right - oldLeft);
          }
          if (y > bottom) { // and in south.
            quadIdx += 2;
            var oldTop = top;
            top = bottom;
            bottom = bottom + (bottom - oldTop);
          }
          if (z > front) { // and in frontal part
            quadIdx += 4;
            var oldBack = back;
            back = front;
            front = back + (back - oldBack);
          }

          var child = node.quads[quadIdx];
          if (!child) {
            // The node is internal but this quadrant is not taken. Add subnode to it.
            child = newNode();
            child.left = left;
            child.top = top;
            child.right = right;
            child.bottom = bottom;
            child.back = back;
            child.front = front;
            child.body = body;

            node.quads[quadIdx] = child;
          } else {
            // continue searching in this quadrant.
            insertStack.push(child, body);
          }
        } else {
          // We are trying to add to the leaf node.
          // We have to convert current leaf into internal node
          // and continue adding two nodes.
          var oldBody = node.body;
          node.body = null; // internal nodes do not cary bodies

          if (isSamePosition(oldBody.pos, body.pos)) {
            // Prevent infinite subdivision by bumping one node
            // anywhere in this quadrant
            if (node.right - node.left < 1e-8) {
              // This is very bad, we ran out of precision.
              // if we do not return from the method we'll get into
              // infinite loop here. So we sacrifice correctness of layout, and keep the app running
              // Next layout iteration should get larger bounding box in the first step and fix this
              return;
            }
            do {
              var offset = random.nextDouble();
              var dx = (node.right - node.left) * offset;
              var dy = (node.bottom - node.top) * offset;
              var dz = (node.front - node.back) * offset;

              oldBody.pos.x = node.left + dx;
              oldBody.pos.y = node.top + dy;
              oldBody.pos.z = node.back + dz;
              // Make sure we don't bump it out of the box. If we do, next iteration should fix it
            } while (isSamePosition(oldBody.pos, body.pos));

          }
          // Next iteration should subdivide node further.
          insertStack.push(node, oldBody);
          insertStack.push(node, body);
        }
      }
    },

    update = function (sourceBody) {
      var queue = updateQueue,
        v,
        dx, dy, dz,
        r, fx = 0, fy = 0, fz = 0,
        queueLength = 1,
        shiftIdx = 0,
        pushIdx = 1;

      queue[0] = root;

      while (queueLength) {
        var node = queue[shiftIdx],
          body = node.body;

        queueLength -= 1;
        shiftIdx += 1;
        // technically there should be external "if (body !== sourceBody) {"
        // but in practice it gives slightghly worse performance, and does not
        // have impact on layout correctness
        if (body && body !== sourceBody) {
          // If the current node is a leaf node (and it is not source body),
          // calculate the force exerted by the current node on body, and add this
          // amount to body's net force.
          dx = body.pos.x - sourceBody.pos.x;
          dy = body.pos.y - sourceBody.pos.y;
          dz = body.pos.z - sourceBody.pos.z;
          r = Math.sqrt(dx * dx + dy * dy + dz * dz);

          if (r === 0) {
            // Poor man's protection against zero distance.
            dx = (random.nextDouble() - 0.5) / 50;
            dy = (random.nextDouble() - 0.5) / 50;
            dz = (random.nextDouble() - 0.5) / 50;
            r = Math.sqrt(dx * dx + dy * dy + dz * dz);
          }

          // This is standard gravition force calculation but we divide
          // by r^3 to save two operations when normalizing force vector.
          v = gravity * body.mass * sourceBody.mass / (r * r * r);
          fx += v * dx;
          fy += v * dy;
          fz += v * dz;
        } else {
          // Otherwise, calculate the ratio s / r,  where s is the width of the region
          // represented by the internal node, and r is the distance between the body
          // and the node's center-of-mass
          dx = node.massX / node.mass - sourceBody.pos.x;
          dy = node.massY / node.mass - sourceBody.pos.y;
          dz = node.massZ / node.mass - sourceBody.pos.z;
          r = Math.sqrt(dx * dx + dy * dy + dz * dz);

          if (r === 0) {
            // Sorry about code duplucation. I don't want to create many functions
            // right away. Just want to see performance first.
            dx = (random.nextDouble() - 0.5) / 50;
            dy = (random.nextDouble() - 0.5) / 50;
            dz = (random.nextDouble() - 0.5) / 50;
            r = Math.sqrt(dx * dx + dy * dy + dz * dz);
          }
          // If s / r < θ, treat this internal node as a single body, and calculate the
          // force it exerts on sourceBody, and add this amount to sourceBody's net force.
          if ((node.right - node.left) / r < theta) {
            // in the if statement above we consider node's width only
            // because the region was squarified during tree creation.
            // Thus there is no difference between using width or height.
            v = gravity * node.mass * sourceBody.mass / (r * r * r);
            fx += v * dx;
            fy += v * dy;
            fz += v * dz;
          } else {
            // Otherwise, run the procedure recursively on each of the current node's children.

            // I intentionally unfolded this loop, to save several CPU cycles.
            if (node.quads[0]) { queue[pushIdx] = node.quads[0]; queueLength += 1; pushIdx += 1; }
            if (node.quads[1]) { queue[pushIdx] = node.quads[1]; queueLength += 1; pushIdx += 1; }
            if (node.quads[2]) { queue[pushIdx] = node.quads[2]; queueLength += 1; pushIdx += 1; }
            if (node.quads[3]) { queue[pushIdx] = node.quads[3]; queueLength += 1; pushIdx += 1; }
            if (node.quads[4]) { queue[pushIdx] = node.quads[4]; queueLength += 1; pushIdx += 1; }
            if (node.quads[5]) { queue[pushIdx] = node.quads[5]; queueLength += 1; pushIdx += 1; }
            if (node.quads[6]) { queue[pushIdx] = node.quads[6]; queueLength += 1; pushIdx += 1; }
            if (node.quads[7]) { queue[pushIdx] = node.quads[7]; queueLength += 1; pushIdx += 1; }
          }
        }
      }

      sourceBody.force.x += fx;
      sourceBody.force.y += fy;
      sourceBody.force.z += fz;
    },

    insertBodies = function (bodies) {
      var x1 = Number.MAX_VALUE,
        y1 = Number.MAX_VALUE,
        z1 = Number.MAX_VALUE,
        x2 = Number.MIN_VALUE,
        y2 = Number.MIN_VALUE,
        z2 = Number.MIN_VALUE,
        i,
        max = bodies.length;

      // To reduce quad tree depth we are looking for exact bounding box of all particles.
      i = max;
      while (i--) {
        var pos = bodies[i].pos;
        var x = pos.x;
        var y = pos.y;
        var z = pos.z;
        if (x < x1) { x1 = x; } if (x > x2) { x2 = x; }
        if (y < y1) { y1 = y; } if (y > y2) { y2 = y; }
        if (z < z1) { z1 = z; } if (z > z2) { z2 = z; }
      }

      // Squarify the bounds.
      var maxSide = Math.max(x2 - x1, Math.max(y2 - y1, z2 - z1));

      x2 = x1 + maxSide;
      y2 = y1 + maxSide;
      z2 = z1 + maxSide;

      currentInCache = 0;
      root = newNode();
      root.left = x1;
      root.right = x2;
      root.top = y1;
      root.bottom = y2;
      root.back = z1;
      root.front = z2;

      i = max - 1;
      if (i > 0) {
        root.body = bodies[i];
      }
      while (i--) {
        insert(bodies[i], root);
      }
    };

  return {
    insertBodies : insertBodies,
    updateBodyForce : update,
    options : function (newOptions) {
      if (newOptions) {
        if (typeof newOptions.gravity === 'number') { gravity = newOptions.gravity; }
        if (typeof newOptions.theta === 'number') { theta = newOptions.theta; }

        return this;
      }

      return {gravity : gravity, theta : theta};
    }
  };
};

<commit_msg>Formatting<commit_after>/**
 * This is Barnes Hut simulation algorithm for 3d case. Implementation
 * is highly optimized (avoids recusion and gc pressure)
 *
 * http://www.cs.princeton.edu/courses/archive/fall03/cs126/assignments/barnes-hut.html
 *
 * NOTE: This module duplicates a lot of code from 2d case. Primary reason for
 * this is performance. Every time I tried to abstract away vector opertaions
 * I had negative impact on performance. So in this case I'm sacrifying code
 * reuse in favor of speed
 */

module.exports = function(options) {
  options = options || {};
  options.gravity = typeof options.gravity === 'number' ? options.gravity : -1;
  options.theta = typeof options.theta === 'number' ? options.theta : 0.8;

  // we require deterministic randomness here
  var random = require('ngraph.random').random(1984),
    Node = require('./node'),
    InsertStack = require('./insertStack'),
    isSamePosition = require('./isSamePosition');

  var gravity = options.gravity,
    updateQueue = [],
    insertStack = new InsertStack(),
    theta = options.theta,

    nodesCache = [],
    currentInCache = 0,
    newNode = function() {
      // To avoid pressure on GC we reuse nodes.
      var node = nodesCache[currentInCache];
      if (node) {
        node.quads[0] = null;
        node.quads[4] = null;
        node.quads[1] = null;
        node.quads[5] = null;
        node.quads[2] = null;
        node.quads[6] = null;
        node.quads[3] = null;
        node.quads[7] = null;
        node.body = null;
        node.mass = node.massX = node.massY = node.massZ = 0;
        node.left = node.right = node.top = node.bottom = node.front = node.back = 0;
      } else {
        node = new Node();
        nodesCache[currentInCache] = node;
      }

      ++currentInCache;
      return node;
    },

    root = newNode(),

    // Inserts body to the tree
    insert = function(newBody) {
      insertStack.reset();
      insertStack.push(root, newBody);

      while (!insertStack.isEmpty()) {
        var stackItem = insertStack.pop(),
          node = stackItem.node,
          body = stackItem.body;

        if (!node.body) {
          // This is internal node. Update the total mass of the node and center-of-mass.
          var x = body.pos.x;
          var y = body.pos.y;
          var z = body.pos.z;
          node.mass += body.mass;
          node.massX += body.mass * x;
          node.massY += body.mass * y;
          node.massZ += body.mass * z;

          // Recursively insert the body in the appropriate quadrant.
          // But first find the appropriate quadrant.
          var quadIdx = 0, // Assume we are in the 0's quad.
            left = node.left,
            right = (node.right + left) / 2,
            top = node.top,
            bottom = (node.bottom + top) / 2,
            back = node.back,
            front = (node.front + back) / 2;

          if (x > right) { // somewhere in the eastern part.
            quadIdx += 1;
            var oldLeft = left;
            left = right;
            right = right + (right - oldLeft);
          }
          if (y > bottom) { // and in south.
            quadIdx += 2;
            var oldTop = top;
            top = bottom;
            bottom = bottom + (bottom - oldTop);
          }
          if (z > front) { // and in frontal part
            quadIdx += 4;
            var oldBack = back;
            back = front;
            front = back + (back - oldBack);
          }

          var child = node.quads[quadIdx];
          if (!child) {
            // The node is internal but this quadrant is not taken. Add subnode to it.
            child = newNode();
            child.left = left;
            child.top = top;
            child.right = right;
            child.bottom = bottom;
            child.back = back;
            child.front = front;
            child.body = body;

            node.quads[quadIdx] = child;
          } else {
            // continue searching in this quadrant.
            insertStack.push(child, body);
          }
        } else {
          // We are trying to add to the leaf node.
          // We have to convert current leaf into internal node
          // and continue adding two nodes.
          var oldBody = node.body;
          node.body = null; // internal nodes do not cary bodies

          if (isSamePosition(oldBody.pos, body.pos)) {
            // Prevent infinite subdivision by bumping one node
            // anywhere in this quadrant
            if (node.right - node.left < 1e-8) {
              // This is very bad, we ran out of precision.
              // if we do not return from the method we'll get into
              // infinite loop here. So we sacrifice correctness of layout, and keep the app running
              // Next layout iteration should get larger bounding box in the first step and fix this
              return;
            }
            do {
              var offset = random.nextDouble();
              var dx = (node.right - node.left) * offset;
              var dy = (node.bottom - node.top) * offset;
              var dz = (node.front - node.back) * offset;

              oldBody.pos.x = node.left + dx;
              oldBody.pos.y = node.top + dy;
              oldBody.pos.z = node.back + dz;
              // Make sure we don't bump it out of the box. If we do, next iteration should fix it
            } while (isSamePosition(oldBody.pos, body.pos));

          }
          // Next iteration should subdivide node further.
          insertStack.push(node, oldBody);
          insertStack.push(node, body);
        }
      }
    },

    update = function(sourceBody) {
      var queue = updateQueue,
        v,
        dx, dy, dz,
        r, fx = 0,
        fy = 0,
        fz = 0,
        queueLength = 1,
        shiftIdx = 0,
        pushIdx = 1;

      queue[0] = root;

      while (queueLength) {
        var node = queue[shiftIdx],
          body = node.body;

        queueLength -= 1;
        shiftIdx += 1;
        // technically there should be external "if (body !== sourceBody) {"
        // but in practice it gives slightghly worse performance, and does not
        // have impact on layout correctness
        if (body && body !== sourceBody) {
          // If the current node is a leaf node (and it is not source body),
          // calculate the force exerted by the current node on body, and add this
          // amount to body's net force.
          dx = body.pos.x - sourceBody.pos.x;
          dy = body.pos.y - sourceBody.pos.y;
          dz = body.pos.z - sourceBody.pos.z;
          r = Math.sqrt(dx * dx + dy * dy + dz * dz);

          if (r === 0) {
            // Poor man's protection against zero distance.
            dx = (random.nextDouble() - 0.5) / 50;
            dy = (random.nextDouble() - 0.5) / 50;
            dz = (random.nextDouble() - 0.5) / 50;
            r = Math.sqrt(dx * dx + dy * dy + dz * dz);
          }

          // This is standard gravition force calculation but we divide
          // by r^3 to save two operations when normalizing force vector.
          v = gravity * body.mass * sourceBody.mass / (r * r * r);
          fx += v * dx;
          fy += v * dy;
          fz += v * dz;
        } else {
          // Otherwise, calculate the ratio s / r,  where s is the width of the region
          // represented by the internal node, and r is the distance between the body
          // and the node's center-of-mass
          dx = node.massX / node.mass - sourceBody.pos.x;
          dy = node.massY / node.mass - sourceBody.pos.y;
          dz = node.massZ / node.mass - sourceBody.pos.z;
          r = Math.sqrt(dx * dx + dy * dy + dz * dz);

          if (r === 0) {
            // Sorry about code duplucation. I don't want to create many functions
            // right away. Just want to see performance first.
            dx = (random.nextDouble() - 0.5) / 50;
            dy = (random.nextDouble() - 0.5) / 50;
            dz = (random.nextDouble() - 0.5) / 50;
            r = Math.sqrt(dx * dx + dy * dy + dz * dz);
          }
          // If s / r < θ, treat this internal node as a single body, and calculate the
          // force it exerts on sourceBody, and add this amount to sourceBody's net force.
          if ((node.right - node.left) / r < theta) {
            // in the if statement above we consider node's width only
            // because the region was squarified during tree creation.
            // Thus there is no difference between using width or height.
            v = gravity * node.mass * sourceBody.mass / (r * r * r);
            fx += v * dx;
            fy += v * dy;
            fz += v * dz;
          } else {
            // Otherwise, run the procedure recursively on each of the current node's children.

            // I intentionally unfolded this loop, to save several CPU cycles.
            if (node.quads[0]) {
              queue[pushIdx] = node.quads[0];
              queueLength += 1;
              pushIdx += 1;
            }
            if (node.quads[1]) {
              queue[pushIdx] = node.quads[1];
              queueLength += 1;
              pushIdx += 1;
            }
            if (node.quads[2]) {
              queue[pushIdx] = node.quads[2];
              queueLength += 1;
              pushIdx += 1;
            }
            if (node.quads[3]) {
              queue[pushIdx] = node.quads[3];
              queueLength += 1;
              pushIdx += 1;
            }
            if (node.quads[4]) {
              queue[pushIdx] = node.quads[4];
              queueLength += 1;
              pushIdx += 1;
            }
            if (node.quads[5]) {
              queue[pushIdx] = node.quads[5];
              queueLength += 1;
              pushIdx += 1;
            }
            if (node.quads[6]) {
              queue[pushIdx] = node.quads[6];
              queueLength += 1;
              pushIdx += 1;
            }
            if (node.quads[7]) {
              queue[pushIdx] = node.quads[7];
              queueLength += 1;
              pushIdx += 1;
            }
          }
        }
      }

      sourceBody.force.x += fx;
      sourceBody.force.y += fy;
      sourceBody.force.z += fz;
    },

    insertBodies = function(bodies) {
      var x1 = Number.MAX_VALUE,
        y1 = Number.MAX_VALUE,
        z1 = Number.MAX_VALUE,
        x2 = Number.MIN_VALUE,
        y2 = Number.MIN_VALUE,
        z2 = Number.MIN_VALUE,
        i,
        max = bodies.length;

      // To reduce quad tree depth we are looking for exact bounding box of all particles.
      i = max;
      while (i--) {
        var pos = bodies[i].pos;
        var x = pos.x;
        var y = pos.y;
        var z = pos.z;
        if (x < x1) {
          x1 = x;
        }
        if (x > x2) {
          x2 = x;
        }
        if (y < y1) {
          y1 = y;
        }
        if (y > y2) {
          y2 = y;
        }
        if (z < z1) {
          z1 = z;
        }
        if (z > z2) {
          z2 = z;
        }
      }

      // Squarify the bounds.
      var maxSide = Math.max(x2 - x1, Math.max(y2 - y1, z2 - z1));

      x2 = x1 + maxSide;
      y2 = y1 + maxSide;
      z2 = z1 + maxSide;

      currentInCache = 0;
      root = newNode();
      root.left = x1;
      root.right = x2;
      root.top = y1;
      root.bottom = y2;
      root.back = z1;
      root.front = z2;

      i = max - 1;
      if (i > 0) {
        root.body = bodies[i];
      }
      while (i--) {
        insert(bodies[i], root);
      }
    };

  return {
    insertBodies: insertBodies,
    updateBodyForce: update,
    options: function(newOptions) {
      if (newOptions) {
        if (typeof newOptions.gravity === 'number') {
          gravity = newOptions.gravity;
        }
        if (typeof newOptions.theta === 'number') {
          theta = newOptions.theta;
        }

        return this;
      }

      return {
        gravity: gravity,
        theta: theta
      };
    }
  };
};
<|endoftext|>


<commit_before>'use strict';

module.exports = (function () {
	var self = {
		count: 0,
		edges: {},
		nodes: {}
	};

	self.link = function (source, target, weight) {
		weight = weight || 1;

		if (self.nodes.hasOwnProperty(source) !== true) {
			self.count++;
			self.nodes[source] = {
				weight: 0,
				outbound: 0
			};
		}

		self.nodes[source].outbound += weight;

		if (self.nodes.hasOwnProperty(target) !== true) {
			self.count++;
			self.nodes[target] = {
				weight: 0,
				outbound: 0
			};
		}

		if (self.edges.hasOwnProperty(source) !== true) {
			self.edges[source] = {};
		}

		if (self.edges[source].hasOwnProperty(target) !== true) {
			self.edges[source][target] = 0;
		}

		self.edges[source][target] += weight;
	};

	self.rank = function (alpha, epsilon, callback) {
		var delta = 1,
			inverse = 1 / self.count;

		forOwn(self.edges, function (source) {
			if (self.nodes[source].outbound > 0) {
				forOwn(self.edges[source], function (target) {
					self.edges[source][target] /= self.nodes[source].outbound;
				});
			}
		});

		forOwn(self.nodes, function (key) {
			self.nodes[key].weight = inverse;
		});

		while (delta > epsilon) {
			var leak = 0,
				nodes = {};

			forOwn(self.nodes, function (key, value) {
				nodes[key] = value.weight;

				if (value.outbound === 0) {
					leak += value.weight;
				}

				self.nodes[key].weight = 0;
			});

			leak *= alpha;

			forOwn(self.nodes, function (source) {
				forOwn(self.edges[source], function (target, weight) {
					self.nodes[target].weight += alpha * nodes[source] * weight;
				});

				self.nodes[source].weight += (1 - alpha) * inverse + leak * inverse;
			});

			delta = 0;

			forOwn(self.nodes, function (key, value) {
				delta += Math.abs(value.weight - nodes[key]);
			});
		}

		forOwn(self.nodes, function (key) {
			return callback(key, self.nodes[key].weight);
		});
	};

	self.reset = function () {
		self.count = 0;
		self.edges = {};
		self.nodes = {};
	};

	return self;
})();

function forOwn(object, callback) {
	if ((typeof object === 'object') && (typeof callback === 'function')) {
		for (var key in object) {
			if (object.hasOwnProperty(key) === true) {
				if (callback(key, object[key]) === false) {
					break;
				}
			}
		}
	}
}
<commit_msg>improved weight casting in link() method<commit_after>'use strict';

function forOwn(object, callback) {
	if ((typeof object === 'object') && (typeof callback === 'function')) {
		for (var key in object) {
			if (object.hasOwnProperty(key) === true) {
				if (callback(key, object[key]) === false) {
					break;
				}
			}
		}
	}
}

module.exports = (function () {
	var self = {
		count: 0,
		edges: {},
		nodes: {}
	};

	self.link = function (source, target, weight) {
		if (isFinite(weight) !== true) {
			weight = 1;
		}

		weight = parseFloat(weight);

		if (self.nodes.hasOwnProperty(source) !== true) {
			self.count++;
			self.nodes[source] = {
				weight: 0,
				outbound: 0
			};
		}

		self.nodes[source].outbound += weight;

		if (self.nodes.hasOwnProperty(target) !== true) {
			self.count++;
			self.nodes[target] = {
				weight: 0,
				outbound: 0
			};
		}

		if (self.edges.hasOwnProperty(source) !== true) {
			self.edges[source] = {};
		}

		if (self.edges[source].hasOwnProperty(target) !== true) {
			self.edges[source][target] = 0;
		}

		self.edges[source][target] += weight;
	};

	self.rank = function (alpha, epsilon, callback) {
		var delta = 1,
			inverse = 1 / self.count;

		forOwn(self.edges, function (source) {
			if (self.nodes[source].outbound > 0) {
				forOwn(self.edges[source], function (target) {
					self.edges[source][target] /= self.nodes[source].outbound;
				});
			}
		});

		forOwn(self.nodes, function (key) {
			self.nodes[key].weight = inverse;
		});

		while (delta > epsilon) {
			var leak = 0,
				nodes = {};

			forOwn(self.nodes, function (key, value) {
				nodes[key] = value.weight;

				if (value.outbound === 0) {
					leak += value.weight;
				}

				self.nodes[key].weight = 0;
			});

			leak *= alpha;

			forOwn(self.nodes, function (source) {
				forOwn(self.edges[source], function (target, weight) {
					self.nodes[target].weight += alpha * nodes[source] * weight;
				});

				self.nodes[source].weight += (1 - alpha) * inverse + leak * inverse;
			});

			delta = 0;

			forOwn(self.nodes, function (key, value) {
				delta += Math.abs(value.weight - nodes[key]);
			});
		}

		forOwn(self.nodes, function (key) {
			return callback(key, self.nodes[key].weight);
		});
	};

	self.reset = function () {
		self.count = 0;
		self.edges = {};
		self.nodes = {};
	};

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