<commit_before>var fs = require('fs');
var path = require('path');
var urlParse = require('url').parse;
var format = require('util').format;
var tcp = require('js-git/net/tcp-node');
var tcpTransport = require('js-git/net/transport-tcp')(tcp);
var request = require('../lib/js-git-node-request');
var httpTransport = require('js-git/net/transport-http')(request);
var fetchPackProtocol = require('js-git/net/git-fetch-pack');
var modes = require('js-git/lib/modes');
var archiver = require('archiver');
var utils = require('../lib/utils');

module.exports = {
  remote: function(repoUrl) {
    repoUrl = utils.fixUrl(repoUrl);
    var parsedUrl = urlParse(repoUrl);
    var transport, transportName;

    if (parsedUrl.protocol == 'git:') {
      transport = tcpTransport(
        parsedUrl.pathname,
        parsedUrl.hostname,
        parsedUrl.port
      );
      transportName = 'tcp';
    } else {
      transport = httpTransport(repoUrl);
      transportName = 'http';
    }

    var api = fetchPackProtocol(transport);

    // add helpers
    api.url = parsedUrl;
    api.transport = transportName;
    api.done = function() {
      this.put({ done: true });
      this.put();
    };

    return api;
  },
  repo: function(rootPath, mirror) {
      var repo = {};
      var fsDb = require('../lib/js-git-fs-db');
      require('js-git/mixins/fs-db')(repo, fsDb);
      require('js-git/mixins/read-combiner')(repo);
      require('js-git/mixins/pack-ops')(repo);
      require('js-git/mixins/walkers')(repo);
      require('js-git/mixins/formats')(repo);

      if (!rootPath) rootPath = process.cwd();
      if (!mirror) rootPath += '/.git';
      repo.rootPath = rootPath;

      return repo;
  },
  ls: function(remote, callback, keepalive) {
    remote.take(function(err, refs) {
      if (remote.transport == 'tcp' && !keepalive) {
        remote.done();
      }
      callback(err, refs);
    });
  },
  clone: function(remote, targetPath, options, callback) {
    var self = this;
    targetPath = targetPath || path.basename(remote.url.pathname, '.git');

    if (options.onProgress) {
      var progress;
      if (options.mirror) {
        progress = "Cloning '%s' into bare repository '%s'...";
      } else {
        progress = "Cloning '%s' into '%s'...";
      }
      options.onProgress(format(progress, remote.url.href, targetPath));
    }

    var repo = this.repo(targetPath, options.mirror);
    var branch = options.branch || 'refs/heads/master';
    if (!branch.startsWith('refs/') && branch[0] != '/') {
      branch = '/' + branch;
    }

    var ref, hash;
    this.ls(remote, select, /*keepalive*/true);

    function select(err, refs) {
      if (err) return callback(err);

      ref = Object.keys(refs).filter(function(ref) {
        return ref.endsWith(branch);
      })[0];
      hash = refs[ref];
      remote.put({ want: hash });

      if (options.depth) {
        remote.put({ deepen: parseInt(options.depth, 10) });
      }

      remote.put(null);
      remote.done();
      remote.take(unpack);
    }

    function unpack(err, channels) {
      if (err) return callback(err);

      var packOpts = {
        onError: callback,
        onProgress: function(progress) {
          if (options.onProgress) {
            options.onProgress(progress);
          }
          // Quick hack for "repo.unpack callback is never called using HTTP transport"
          // issue https://github.com/creationix/js-git/issues/120
          if (remote.transport == 'http') {
            var statsRegex = /\((\d+)\/(\d+)\)/;
            var stats = statsRegex.exec(progress);

            if (stats[1] == stats[2] - 1) {
              if (options.onProgress) {
                progress = 'Receiving objects: 100% (' + stats[2] + '/' + stats[2] + ')\r\n';
                options.onProgress(progress);
              }
              return addRef();
            }
          }
        }
      };

      repo.unpack(channels.pack, packOpts, addRef);
    }

    function addRef(err) {
      if (err) return callback(err);
      repo.updateRef(ref, hash, function(err) {
        if (err) return callback(err);
        var headPath = path.join(repo.rootPath, 'HEAD');
        fs.writeFile(headPath, 'ref: ' + ref, createConfig);
      });
    }

    function createConfig(err) {
      if (err) return callback(err);

      var configPath = path.join(repo.rootPath, 'config');
      var config = '[remote "origin"]\r\n\turl = ' + remote.url.href;

      fs.writeFile(configPath, config, function(err) {
        if (err) return callback(err);

        if (!options.mirror) {
          return self.checkout(repo, ref, options, callback);
        } else {
          return callback();
        }
      });
    }
  },
  loadTree: function(repo, ref, callback) {
    repo.readRef(ref, loadCommit);

    function loadCommit(err, hash) {
      if (err) {
        if (err.code == 'ENOENT') {
          hash = ref; // maybe ref is hash
        } else {
          return callback(err);
        }
      }

      repo.loadAs('commit', hash, readTree);
    }

    function readTree(err, commit) {
      if (err) return callback(err);
      repo.treeWalk(commit.tree, callback);
    }
  },
  checkout: function(repo, ref, options, callback) {
    this.loadTree(repo, ref, function(err, tree) {
      if (err) return callback(err);

      var repoPath = repo.rootPath;
      if (path.basename(repoPath) == '.git') {
        repoPath = path.dirname(repoPath);
      }

      tree.read(onEntry);

      function onEntry(err, entry) {
        if (err) return callback(err);
        if (!entry) return callback();

        if (entry.path == '/') {
          return nextEntry();
        }

        var entryPath = path.join(repoPath, entry.path);

        if (options.onProgress) {
          var colorPath = '\x1B[34m' +
            entryPath.replace(/\//g, '\x1B[1;34m/\x1B[0;34m') + '\x1B[0m';
          options.onProgress(entry.hash + ' ' + colorPath);
        }

        if (entry.mode == modes.tree) {
          return fs.mkdir(entryPath, nextEntry);
        }
        if (entry.mode == modes.blob) {
          return repo.loadAs('blob', entry.hash, function(err, blob) {
            if (err) return callback(err);
            return fs.writeFile(entryPath, blob, nextEntry);
          });
        }

        return nextEntry();
      }

      function nextEntry(err) {
        if (err) return callback(err);
        return tree.read(onEntry);
      }
    });
  },
  archive: function(repo, ref, options, callback) {
    this.loadTree(repo, ref, function(err, tree) {
      if (err) return callback(err);

      var archive = archiver(options.format || 'tar');
      archive.pipe(options.pipe || process.stdout);
      archive.on('error', callback);

      tree.read(onEntry);

      function onEntry(err, entry) {
        if (err) return callback(err);
        if (!entry) {
          archive.finalize();
          return callback();
        }

        if (entry.path == '/') {
          return nextEntry();
        }

        var prefixedPath = path.join(options.prefix || '', entry.path);

        if (entry.mode == modes.blob) {
          return repo.loadAs('blob', entry.hash, function(err, blob) {
            if (err) return callback(err);
            archive.append(blob, { name: prefixedPath });
            nextEntry();
          });
        }

        return nextEntry();
      }

      function nextEntry(err) {
        if (err) return callback(err);
        return tree.read(onEntry);
      }
    });
  }
};<commit_msg>Fix clone for tag<commit_after>var fs = require('fs');
var path = require('path');
var urlParse = require('url').parse;
var format = require('util').format;
var tcp = require('js-git/net/tcp-node');
var tcpTransport = require('js-git/net/transport-tcp')(tcp);
var request = require('../lib/js-git-node-request');
var httpTransport = require('js-git/net/transport-http')(request);
var fetchPackProtocol = require('js-git/net/git-fetch-pack');
var modes = require('js-git/lib/modes');
var archiver = require('archiver');
var utils = require('../lib/utils');

module.exports = {
  remote: function(repoUrl) {
    repoUrl = utils.fixUrl(repoUrl);
    var parsedUrl = urlParse(repoUrl);
    var transport, transportName;

    if (parsedUrl.protocol == 'git:') {
      transport = tcpTransport(
        parsedUrl.pathname,
        parsedUrl.hostname,
        parsedUrl.port
      );
      transportName = 'tcp';
    } else {
      transport = httpTransport(repoUrl);
      transportName = 'http';
    }

    var api = fetchPackProtocol(transport);

    // add helpers
    api.url = parsedUrl;
    api.transport = transportName;
    api.done = function() {
      this.put({ done: true });
      this.put();
    };

    return api;
  },
  repo: function(rootPath, mirror) {
      var repo = {};
      var fsDb = require('../lib/js-git-fs-db');
      require('js-git/mixins/fs-db')(repo, fsDb);
      require('js-git/mixins/read-combiner')(repo);
      require('js-git/mixins/pack-ops')(repo);
      require('js-git/mixins/walkers')(repo);
      require('js-git/mixins/formats')(repo);

      if (!rootPath) rootPath = process.cwd();
      if (!mirror) rootPath += '/.git';
      repo.rootPath = rootPath;

      return repo;
  },
  ls: function(remote, callback, keepalive) {
    remote.take(function(err, refs) {
      if (remote.transport == 'tcp' && !keepalive) {
        remote.done();
      }
      callback(err, refs);
    });
  },
  clone: function(remote, targetPath, options, callback) {
    var self = this;
    targetPath = targetPath || path.basename(remote.url.pathname, '.git');

    if (options.onProgress) {
      var progress;
      if (options.mirror) {
        progress = "Cloning '%s' into bare repository '%s'...";
      } else {
        progress = "Cloning '%s' into '%s'...";
      }
      options.onProgress(format(progress, remote.url.href, targetPath));
    }

    var repo = this.repo(targetPath, options.mirror);
    var branch = options.branch || 'refs/heads/master';
    if (!branch.startsWith('refs/') && branch[0] != '/') {
      branch = '/' + branch;
    }

    var ref, hash;
    this.ls(remote, select, /*keepalive*/true);

    function select(err, refs) {
      if (err) return callback(err);

      ref = Object.keys(refs).filter(function(ref) {
        return ref.endsWith(branch);
      })[0];
      hash = refs[ref];
      remote.put({ want: hash });

      if (options.depth) {
        remote.put({ deepen: parseInt(options.depth, 10) });
      }

      remote.put(null);
      remote.done();
      remote.take(unpack);
    }

    function unpack(err, channels) {
      if (err) return callback(err);

      var packOpts = {
        onError: callback,
        onProgress: function(progress) {
          if (options.onProgress) {
            options.onProgress(progress);
          }
          // Quick hack for "repo.unpack callback is never called using HTTP transport"
          // issue https://github.com/creationix/js-git/issues/120
          if (remote.transport == 'http') {
            var statsRegex = /\((\d+)\/(\d+)\)/;
            var stats = statsRegex.exec(progress);

            if (stats[1] == stats[2] - 1) {
              if (options.onProgress) {
                progress = 'Receiving objects: 100% (' + stats[2] + '/' + stats[2] + ')\r\n';
                options.onProgress(progress);
              }
              return addRef();
            }
          }
        }
      };

      repo.unpack(channels.pack, packOpts, addRef);
    }

    function addRef(err) {
      if (err) return callback(err);
      repo.updateRef(ref, hash, function(err) {
        if (err) return callback(err);
        var headPath = path.join(repo.rootPath, 'HEAD');
        fs.writeFile(headPath, 'ref: ' + ref, createConfig);
      });
    }

    function createConfig(err) {
      if (err) return callback(err);

      var configPath = path.join(repo.rootPath, 'config');
      var config = '[remote "origin"]\r\n\turl = ' + remote.url.href;

      fs.writeFile(configPath, config, function(err) {
        if (err) return callback(err);

        if (!options.mirror) {
          return self.checkout(repo, ref, options, callback);
        } else {
          return callback();
        }
      });
    }
  },
  loadTree: function(repo, ref, callback) {
    repo.readRef(ref, function (err, hash) {
      if (err) {
        if (err.code == 'ENOENT') {
          hash = ref; // maybe ref is hash
        } else {
          return callback(err);
        }
      }

      if (ref.startsWith('refs/tags/')) {
        loadTag(err, hash);
      } else {
        loadCommit(err, hash);
      }
    });

    function loadTag(err, hash) {
      if (err) return callback(err);
      repo.loadAs('tag', hash, function(err, tag) {
        loadCommit(err, tag.object);
      });
    }

    function loadCommit(err, hash) {
      if (err) return callback(err);
      repo.loadAs('commit', hash, readTree);
    }

    function readTree(err, commit) {
      if (err) return callback(err);
      repo.treeWalk(commit.tree, callback);
    }
  },
  checkout: function(repo, ref, options, callback) {
    this.loadTree(repo, ref, function(err, tree) {
      if (err) return callback(err);

      var repoPath = repo.rootPath;
      if (path.basename(repoPath) == '.git') {
        repoPath = path.dirname(repoPath);
      }

      tree.read(onEntry);

      function onEntry(err, entry) {
        if (err) return callback(err);
        if (!entry) return callback();

        if (entry.path == '/') {
          return nextEntry();
        }

        var entryPath = path.join(repoPath, entry.path);

        if (options.onProgress) {
          var colorPath = '\x1B[34m' +
            entryPath.replace(/\//g, '\x1B[1;34m/\x1B[0;34m') + '\x1B[0m';
          options.onProgress(entry.hash + ' ' + colorPath);
        }

        if (entry.mode == modes.tree) {
          return fs.mkdir(entryPath, nextEntry);
        }
        if (entry.mode == modes.blob) {
          return repo.loadAs('blob', entry.hash, function(err, blob) {
            if (err) return callback(err);
            return fs.writeFile(entryPath, blob, nextEntry);
          });
        }

        return nextEntry();
      }

      function nextEntry(err) {
        if (err) return callback(err);
        return tree.read(onEntry);
      }
    });
  },
  archive: function(repo, ref, options, callback) {
    this.loadTree(repo, ref, function(err, tree) {
      if (err) return callback(err);

      var archive = archiver(options.format || 'tar');
      archive.pipe(options.pipe || process.stdout);
      archive.on('error', callback);

      tree.read(onEntry);

      function onEntry(err, entry) {
        if (err) return callback(err);
        if (!entry) {
          archive.finalize();
          return callback();
        }

        if (entry.path == '/') {
          return nextEntry();
        }

        var prefixedPath = path.join(options.prefix || '', entry.path);

        if (entry.mode == modes.blob) {
          return repo.loadAs('blob', entry.hash, function(err, blob) {
            if (err) return callback(err);
            archive.append(blob, { name: prefixedPath });
            nextEntry();
          });
        }

        return nextEntry();
      }

      function nextEntry(err) {
        if (err) return callback(err);
        return tree.read(onEntry);
      }
    });
  }
};<|endoftext|>


<commit_before>// ------------------------------------
// Status updater class
// ------------------------------------
//
// Update a status on command line for
// the current program.
//
// ------------------------------------
var Status = function() {

}

Status.prototype._status = {};

// status.update({title: 'My task title', action: 'Current action', subaction: 'Current subaction'});
Status.prototype.update = function(newStatus) {
	newStatus = newStatus || {};

	if(newStatus.title && newStatus.title != this._status.title && !newStatus.action) {
		newStatus.action = null;
	}

	if(newStatus.action && newStatus.action != this._status.action && !newStatus.subaction) {
		newStatus.subaction = null;
	}

	extend(this._status, newStatus);

	clearConsole();

	console.log('--------------------------------------------');
	console.log(' '+this._status.title);
	if(this._status.action && this._status.action != '-') { console.log(' -> '+ this._status.action); }
	if(this._status.subaction && this._status.subaction != '-') { console.log('    -> '+ this._status.subaction); }
	console.log('--------------------------------------------');
};

var extend = function(target) {
    var sources = [].slice.call(arguments, 1);
    sources.forEach(function (source) {
        for (var prop in source) {
            target[prop] = source[prop];
        }
    });
    return target;
};

var clearConsole = function() {
	if(process.platform.indexOf('win') == -1) {
		// Unix
		console.log('\033[2J');
	} else {
		// Windows
		process.stdout.write('\033c');
	}
};

module.exports = new Status();<commit_msg>Bugfix: Clear subaction when title is redefined<commit_after>// ------------------------------------
// Status updater class
// ------------------------------------
//
// Update a status on command line for
// the current program.
//
// ------------------------------------
var Status = function() {

}

Status.prototype._status = {};

// status.update({title: 'My task title', action: 'Current action', subaction: 'Current subaction'});
Status.prototype.update = function(newStatus) {
	newStatus = newStatus || {};

	var hasNew = {
		title: newStatus.title && newStatus.title != this._status.title,
		action: newStatus.action && newStatus.action != this._status.action,
		subaction: newStatus.subaction && newStatus.subaction != this._status.subaction
	}

	// If new action is not set, but we change the title, we will clear the action
	if(!newStatus.action && hasNew.title) {
		newStatus.action = null;
	}

	// If new subaction is not set, but we change the title or action, we will clear the action
	if(!newStatus.subaction && (hasNew.action || hasNew.title)) {
		newStatus.subaction = null;
	}

	extend(this._status, newStatus);

	clearConsole();

	console.log('--------------------------------------------');
	console.log(' '+this._status.title);
	if(this._status.action && this._status.action != '-') { console.log(' -> '+ this._status.action); }
	if(this._status.subaction && this._status.subaction != '-') { console.log('    -> '+ this._status.subaction); }
	console.log('--------------------------------------------');
};

var extend = function(target) {
    var sources = [].slice.call(arguments, 1);
    sources.forEach(function (source) {
        for (var prop in source) {
            target[prop] = source[prop];
        }
    });
    return target;
};

var clearConsole = function() {
	if(process.platform.indexOf('win') == -1) {
		// Unix
		console.log('\033[2J');
	} else {
		// Windows
		process.stdout.write('\033c');
	}
};

module.exports = new Status();<|endoftext|>


<commit_before>var redis = require('./redis');
var queue = require('./queue');
//var updateNames = require('./tasks/updateNames');
var buildSets = require('./buildSets');
var utility = require('./utility');
var getData = utility.getData;
var getMMStats = require("./getMMStats");
var invokeInterval = utility.invokeInterval;
var numCPUs = require('os').cpus().length;
var config = require('./config');
var async = require('async');
var queries = require('./queries');
var db = require('./db');
var async = require('async');
var insertPlayer = queries.insertPlayer;
var insertMatch = queries.insertMatch;
console.log("[WORKER] starting worker");
invokeInterval(function(cb) {
    buildSets(db, redis, cb);
}, 60 * 1000);
invokeInterval(function(cb) {
    getMMStats(redis, cb);
}, config.MMSTATS_DATA_INTERVAL * 60 * 1000 || 60000); //Sample every 3 minutes
invokeInterval(function(cb) {
    //clean old jobs from queue older than 1 day
    for (var key in queue) {
        queue[key].clean(24 * 60 * 60 * 1000, 'completed');
        queue[key].clean(24 * 60 * 60 * 1000, 'failed');
    }
}, 60 * 60 * 1000);
//process requests (api call, waits for parse to complete)
queue.request.process(numCPUs, processApi);
//updatenames queues an api request, probably should have name updating occur in a separate service
//jobs.process('api', processApi);
//invokeInterval(updateNames, 60 * 1000);
//invokeInterval(constants, 15 * 60 * 1000);
function processApi(job, cb) {
    var payload = job.data.payload;
    getData(job.data.url, function(err, body) {
        if (err) {
            //couldn't get data from api, non-retryable
            return cb(JSON.stringify(err));
        }
        else if (body.response) {
            //player summaries response
            async.each(body.response.players, function(player, cb) {
                insertPlayer(db, player, cb);
            }, cb);
        }
        else if (payload.match_id) {
            //match details response
            var match = body.result;
            if (job.data.request) {
                match.parse_status = 0;
            }
            insertMatch(db, redis, queue, match, {
                type: "api",
                attempts: job.data.request ? 1 : undefined
            }, function(err, job2) {
                //job2 is the parse job
                if (job.data.request && job2) {
                    //TODO set timeout?
                    var poll = setInterval(function() {
                        queue.parse.getJob(job2.jobId).then(function(job) {
                            if (job) {
                                job.getState().then(function(state) {
                                    if (state === "completed") {
                                        clearInterval(poll);
                                        return cb();
                                    }
                                    if (state === "failed") {
                                        clearInterval(poll);
                                        return cb("failed");
                                    }
                                });
                            }
                        });
                    }, 3000);
                }
                else {
                    cb(err);
                }
            });
        }
        else {
            return cb("unknown response");
        }
    });
}
<commit_msg>request polling stuck fix<commit_after>var redis = require('./redis');
var queue = require('./queue');
//var updateNames = require('./tasks/updateNames');
var buildSets = require('./buildSets');
var utility = require('./utility');
var getData = utility.getData;
var getMMStats = require("./getMMStats");
var invokeInterval = utility.invokeInterval;
var numCPUs = require('os').cpus().length;
var config = require('./config');
var async = require('async');
var queries = require('./queries');
var db = require('./db');
var async = require('async');
var insertPlayer = queries.insertPlayer;
var insertMatch = queries.insertMatch;
console.log("[WORKER] starting worker");
invokeInterval(function(cb) {
    buildSets(db, redis, cb);
}, 60 * 1000);
invokeInterval(function(cb) {
    getMMStats(redis, cb);
}, config.MMSTATS_DATA_INTERVAL * 60 * 1000 || 60000); //Sample every 3 minutes
invokeInterval(function(cb) {
    //clean old jobs from queue older than 1 day
    for (var key in queue) {
        queue[key].clean(24 * 60 * 60 * 1000, 'completed');
        queue[key].clean(24 * 60 * 60 * 1000, 'failed');
    }
}, 60 * 60 * 1000);
//process requests (api call, waits for parse to complete)
queue.request.process(numCPUs, processApi);
//updatenames queues an api request, probably should have name updating occur in a separate service
//jobs.process('api', processApi);
//invokeInterval(updateNames, 60 * 1000);
//invokeInterval(constants, 15 * 60 * 1000);
function processApi(job, cb) {
    var payload = job.data.payload;
    getData(job.data.url, function(err, body) {
        if (err) {
            //couldn't get data from api, non-retryable
            return cb(JSON.stringify(err));
        }
        else if (body.response) {
            //player summaries response
            async.each(body.response.players, function(player, cb) {
                insertPlayer(db, player, cb);
            }, cb);
        }
        else if (payload.match_id) {
            //match details response
            var match = body.result;
            if (job.data.request) {
                match.parse_status = 0;
            }
            insertMatch(db, redis, queue, match, {
                type: "api",
                attempts: job.data.request ? 1 : undefined
            }, function(err, job2) {
                //job2 is the parse job
                if (job.data.request && job2) {
                    var poll = setInterval(function() {
                        queue.parse.getJob(job2.jobId).then(function(job) {
                            if (job) {
                                job.getState().then(function(state) {
                                    if (state === "completed") {
                                        clearInterval(poll);
                                        return cb();
                                    }
                                    if (state === "failed") {
                                        clearInterval(poll);
                                        return cb("failed");
                                    }
                                });
                            }
                            else {
                                clearInterval(poll);
                                return cb("failed");
                            }
                        });
                    }, 3000);
                }
                else {
                    cb(err);
                }
            });
        }
        else {
            return cb("unknown response");
        }
    });
}
<|endoftext|>


<commit_before><commit_msg>Forgot to remove this<commit_after><|endoftext|>


<commit_before>'use strict';

const { existsSync, unlinkSync, renameSync } = require('fs');
const path = require('path');
const tar = require('tar');
const validatePackageName = require('validate-npm-package-name');
const { sync: writePkg } = require('write-pkg');
const { sync: readPkg } = require('load-json-file');
const pm = require('./package-manager');

function mergePackageManifest(newManifest, oldManifest) {
  return Object.assign({}, newManifest, oldManifest, {
    dependencies: Object.assign(
      newManifest.dependencies,
      oldManifest.dependencies
    ),
    devDependencies: Object.assign(
      newManifest.devDependencies,
      oldManifest.devDependencies
    ),
  });
}

function getValidatedTemplateName(name, root) {
  if (name.indexOf('@') > -1) {
    if (!existsSync(path.resolve(root, name))) {
      return name;
    }
  }
  const validationResult = validatePackageName(name);
  if (
    !(
      validationResult.validForNewPackages ||
      validationResult.validForOldPackages
    )
  ) {
    return path.resolve(root, name);
  } else if (name.indexOf('hops-template') === 0) {
    return name;
  }
  return null;
}

function renameDotFiles(root, files) {
  files.forEach(dotFile => {
    if (existsSync(path.join(root, dotFile))) {
      renameSync(
        path.join(root, dotFile),
        path.join(root, '.' + dotFile.slice(1))
      );
    }
  });
}

function deleteFiles(root, files) {
  files.forEach(fileName => {
    const file = path.isAbsolute(fileName)
      ? fileName
      : path.join(root, fileName);
    if (existsSync(file)) {
      unlinkSync(file);
    }
  });
}

function init(root, appName, options) {
  const appRoot = path.resolve(root, appName);
  const template = getValidatedTemplateName(options.template, root);
  const pathToPackageManifest = path.resolve(appRoot, 'package.json');
  const oldPackageManifest = readPkg(pathToPackageManifest);
  let tarball = null;
  options.npm = options.npm || !pm.hasBeenInstalledViaYarn(appRoot);

  if (template) {
    tarball = pm.getTarball(template, options);
  } else {
    console.error(
      'Could not find a hops-template with the specified name:',
      options.template
    );
    process.exit(1);
  }

  if (tarball) {
    tar
      .extract({
        file: tarball,
        strip: 1,
      })
      .then(() => {
        deleteFiles([tarball, 'CHANGELOG.md', 'LICENSE.txt']);
        renameDotFiles(appRoot, ['_gitignore', '_npmrc']);

        writePkg(
          pathToPackageManifest,
          mergePackageManifest(
            readPkg(pathToPackageManifest),
            oldPackageManifest
          )
        );
        pm.installPackages([], null, options);

        console.log('Hooray \\o/');
        console.log('Your project has been successfully created.');
        console.log(
          `You should \`cd ${appName}\` to change into its directory and execute`,
          '`' + (pm.hasBeenInstalledViaYarn(appRoot) ? 'yarn' : 'npm'),
          'start`',
          'to fire up a development server with hot module reloading.'
        );
        console.log(
          'To see a list of available commands through Hops presets execute:',
          pm.hasBeenInstalledViaYarn(appRoot)
            ? '`yarn hops`'
            : '`npx hops@' + options.hopsVersion + '`'
        );
      })
      .catch(error => {
        console.error('Error while unpacking tar archive:', tarball);
        console.error(error);
      });
  } else {
    console.error('Could not download tarball for:', template);
    process.exit(1);
  }
}
module.exports = { init };
<commit_msg>fix(create-hops-app): provide root path to deleteFiles function<commit_after>'use strict';

const { existsSync, unlinkSync, renameSync } = require('fs');
const path = require('path');
const tar = require('tar');
const validatePackageName = require('validate-npm-package-name');
const { sync: writePkg } = require('write-pkg');
const { sync: readPkg } = require('load-json-file');
const pm = require('./package-manager');

function mergePackageManifest(newManifest, oldManifest) {
  return Object.assign({}, newManifest, oldManifest, {
    dependencies: Object.assign(
      newManifest.dependencies,
      oldManifest.dependencies
    ),
    devDependencies: Object.assign(
      newManifest.devDependencies,
      oldManifest.devDependencies
    ),
  });
}

function getValidatedTemplateName(name, root) {
  if (name.indexOf('@') > -1) {
    if (!existsSync(path.resolve(root, name))) {
      return name;
    }
  }
  const validationResult = validatePackageName(name);
  if (
    !(
      validationResult.validForNewPackages ||
      validationResult.validForOldPackages
    )
  ) {
    return path.resolve(root, name);
  } else if (name.indexOf('hops-template') === 0) {
    return name;
  }
  return null;
}

function renameDotFiles(root, files) {
  files.forEach(dotFile => {
    if (existsSync(path.join(root, dotFile))) {
      renameSync(
        path.join(root, dotFile),
        path.join(root, '.' + dotFile.slice(1))
      );
    }
  });
}

function deleteFiles(root, files) {
  files.forEach(fileName => {
    const file = path.isAbsolute(fileName)
      ? fileName
      : path.join(root, fileName);
    if (existsSync(file)) {
      unlinkSync(file);
    }
  });
}

function init(root, appName, options) {
  const appRoot = path.resolve(root, appName);
  const template = getValidatedTemplateName(options.template, root);
  const pathToPackageManifest = path.resolve(appRoot, 'package.json');
  const oldPackageManifest = readPkg(pathToPackageManifest);
  let tarball = null;
  options.npm = options.npm || !pm.hasBeenInstalledViaYarn(appRoot);

  if (template) {
    tarball = pm.getTarball(template, options);
  } else {
    console.error(
      'Could not find a hops-template with the specified name:',
      options.template
    );
    process.exit(1);
  }

  if (tarball) {
    tar
      .extract({
        file: tarball,
        strip: 1,
      })
      .then(() => {
        deleteFiles(appRoot, [tarball, 'CHANGELOG.md', 'LICENSE.txt']);
        renameDotFiles(appRoot, ['_gitignore', '_npmrc']);

        writePkg(
          pathToPackageManifest,
          mergePackageManifest(
            readPkg(pathToPackageManifest),
            oldPackageManifest
          )
        );
        pm.installPackages([], null, options);

        console.log('Hooray \\o/');
        console.log('Your project has been successfully created.');
        console.log(
          `You should \`cd ${appName}\` to change into its directory and execute`,
          '`' + (pm.hasBeenInstalledViaYarn(appRoot) ? 'yarn' : 'npm'),
          'start`',
          'to fire up a development server with hot module reloading.'
        );
        console.log(
          'To see a list of available commands through Hops presets execute:',
          pm.hasBeenInstalledViaYarn(appRoot)
            ? '`yarn hops`'
            : '`npx hops@' + options.hopsVersion + '`'
        );
      })
      .catch(error => {
        console.error('Error while unpacking tar archive:', tarball);
        console.error(error);
      });
  } else {
    console.error('Could not download tarball for:', template);
    process.exit(1);
  }
}
module.exports = { init };
<|endoftext|>


<commit_before>'use strict';
var React = require('react');
var collection = require('./collection');
var fetched = require('./fetched');
var globals = require('./globals');
var audit = require('./audit');
var form = require('./form');
var _ = require('underscore');
var cx = require('react/lib/cx');
var panel = require('../libs/bootstrap/panel');
var AuditIndicators = audit.AuditIndicators;
var AuditDetail = audit.AuditDetail;
var AuditMixin = audit.AuditMixin;
var JSONSchemaForm = form.JSONSchemaForm;
var Table = collection.Table;
var {Panel, PanelBody, PanelHeading} = panel;

var Fallback = module.exports.Fallback = React.createClass({
    contextTypes: {
        location_href: React.PropTypes.string
    },

    render: function() {
        var url = require('url');
        var context = this.props.context;
        var title = typeof context.title == "string" ? context.title : url.parse(this.context.location_href).path;
        return (

{title}

                {typeof context.description == "string" ?
{context.description}
 : null}

{JSON.stringify(context, null, 4)}

        );
    }
});

var Item = module.exports.Item = React.createClass({
    mixins: [AuditMixin],
    render: function() {
        var context = this.props.context;
        var itemClass = globals.itemClass(context, 'view-item');
        var title = globals.listing_titles.lookup(context)({context: context});
        var IPanel = globals.panel_views.lookup(context);

        // Make string of alternate accessions
        var altacc = context.alternate_accessions ? context.alternate_accessions.join(', ') : undefined;

        return (

{title}

                        {altacc ?
Replaces {altacc}
 : null}

                            <AuditIndicators context={context} key="biosample-audit" />

                <AuditDetail context={context} key="biosample-audit" />

                    <fetched.FetchedData>
                        <fetched.Param name="schemas" url="/profiles/" />
                        <IPanel {...this.props} />
                    </fetched.FetchedData>

        );
    }
});

globals.content_views.register(Item, 'Item');

// Also use this view as a fallback for anything we haven't registered
globals.content_views.fallback = function () {
    return Fallback;
};

var IPanel = module.exports.IPanel = React.createClass({
    render: function() {
        var schemas = this.props.schemas;
        var context = this.props.context;
        var itemClass = globals.itemClass(context, 'view-detail panel');
        var title = globals.listing_titles.lookup(context)({context: context});
        var sortKeys = Object.keys(context).sort();
        var tips = tipsFromSchema(schemas, context);
        return (

            <Panel addClasses="data-display">
                <PanelBody addClasses="panel-body-with-header">

{title}

                                {sortKeys.map(function(ikey, val){
                                    return (

                                          {formKey(tips,ikey)}

{formValue(schemas,context[ikey])}

                                    );
                                })}

                </PanelBody>
            </Panel>

        );
    }
});

globals.panel_views.register(IPanel, 'Item');

// Also use this view as a fallback for anything we haven't registered
globals.panel_views.fallback = function () {
    return IPanel;
};

var title = module.exports.title = function (props) {
    var context = props.context;
    return context.title || context.name || context.accession || context['@id'];
};

globals.listing_titles.register(title, 'Item');

// Also use this view as a fallback for anything we haven't registered
globals.listing_titles.fallback = function () {
    return title;
};

var ItemEdit = module.exports.ItemEdit = React.createClass({
    contextTypes: {
        navigate: React.PropTypes.func
    },

    render: function() {
        var context = this.props.context;
        var itemClass = globals.itemClass(context, 'view-item');
        var title = globals.listing_titles.lookup(context)({context: context});
        var action, form, schemaUrl, type;
        if (context['@type'][0].indexOf('Collection') !== -1) {  // add form
            type = context['@type'][0].substr(0, context['@type'][0].length - 10);
            title = title + ': Add';
            action = context['@id'];
            form = (
                <fetched.FetchedData>
                    <fetched.Param name="schemas" url="/profiles/" />
                    <JSONSchemaForm type={type} action={action} method="POST" onFinish={this.finished}
                                    showReadOnly={false} />
                </fetched.FetchedData>
            );
        } else {  // edit form
            type = context['@type'][0];
            title = 'Edit ' + title;
            var id = this.props.context['@id'];
            var url = id + '?frame=edit';
            form = (
                <fetched.FetchedData>
                    <fetched.Param name="context" url={url} etagName="etag" />
                    <fetched.Param name="schemas" url="/profiles/" />
                    <JSONSchemaForm id={id} type={type} action={id} method="PUT" onFinish={this.finished} />
                </fetched.FetchedData>
            );
        }
        return (

{title}

                {form}

        );
    },
    finished: function(data) {
      var url = data['@graph'][0]['@id'];
      this.context.navigate(url);
    }
});

globals.content_views.register(ItemEdit, 'Item', 'edit');
globals.content_views.register(ItemEdit, 'Collection', 'add');

var FetchedRelatedItems = React.createClass({
    getDefaultProps: function() {
        return {Component: Table};
    },

    render: function() {
        var {Component, context, title, url, ...props} = this.props;
        if (context === undefined) return null;
        var items = context['@graph'];
        if (!items.length) return null;

        return (
            <Component {...props} title={title} context={context} total={context.total} items={items} url={url} showControls={false} />
        );
    },

});

var RelatedItems = module.exports.RelatedItems = React.createClass({
    getDefaultProps: function() {
        return {limit: 5};
    },

    render: function() {
        var url = this.props.url + '&status!=deleted&status!=revoked&status!=replaced';
        var limited_url = url + '&limit=' + this.props.limit;
        var unlimited_url = url + '&limit=all';
        return (
            <fetched.FetchedData>
                <fetched.Param name="context" url={limited_url} />
                <FetchedRelatedItems {...this.props} url={unlimited_url} />
            </fetched.FetchedData>
        );
    },
});

// Formats the correct display for each metadata field
var formValue = function (schemas, item) {
    var toReturn = [];
    if(Array.isArray(item)) {
        for (var i=0; i < item.length; i++){
            toReturn.push(formValue(schemas, item[i]));
        }
    }else if (typeof item === 'object') {
        if(item['@type']){
            var type = item['@type'][0];
        }
        toReturn.push(<SubIPannel schemas={schemas} content={item}/>);
    }else{
        if (typeof item === 'string' && item.charAt(0) === '/') {
            toReturn.push({item})
        }else{
            toReturn.push(item);
        }
    }
    return(

{toReturn}

    );
};

var SubIPannel = React.createClass({
    getInitialState: function() {
    	return {isOpen: false};
    },
    handleToggle: function (e) {
      e.preventDefault();
      this.setState({
  		  isOpen: !this.state.isOpen,
  	  });
    },
    render: function() {
        var schemas = this.props.schemas;
        var item = this.props.content;
        // TODO: make this process generic using lookup with registry
        if (item.hasOwnProperty("accession")){
            var title = item.accession;
        }else if (item.hasOwnProperty("name")){
            var title = item.name;
        }else if (item.hasOwnProperty("title")){
            var title = item.title;
        }else{
            var title = "Open";
        }
        var toggleRender;
        var toggleLink;
        if (!this.state.isOpen) {
            toggleLink = {title}
            toggleRender = ;
        }else{
            toggleLink = Close
            toggleRender = <Subview schemas={schemas} content={item}/>;
        }
        return (

                  {toggleLink}

              {toggleRender}

        );
        },
});

var Subview = React.createClass({
    render: function(){
        var schemas = this.props.schemas;
        var item = this.props.content;
        console.log(item);
        console.log(schemas);
        var tips = tipsFromSchema(schemas, item);
        return(

              <Panel addClasses="data-display">
                  <PanelBody addClasses="panel-body-with-header">

                                  {Object.keys(item).map(function(ikey, val){
                                      return (

                                          {formKey(tips,ikey)}

{formValue(schemas, item[ikey])}

                                      );
                                  })}

                  </PanelBody>
              </Panel>

        );
    }
});

//Return the properties dictionary from a schema for use as tooltips
var tipsFromSchema = function(schemas, context){
    var tips = {};
    if(context['@type']){
        var type = context['@type'][0];
        tips = schemas[type]['properties'];
    }
    return tips;
};

var formKey =  function(tips, key){
    var tooltip = '';
    if (tips[key]){
        var info = tips[key];
        if(info['description']){
            tooltip = info['description'];
        }
    }
    return(
        <DescriptorField field={key} description={tooltip}/>
    );
};

// Display the item field with a tooltip showing the field description from
// schema, if available
var DescriptorField = React.createClass({
    propTypes: {
        field: React.PropTypes.string.isRequired,
        description: React.PropTypes.string.isRequired
    },
    getInitialState: function() {
        return {
            active: false
        };
    },

    handleHover: function(b) {
        this.setState({active: b});
    },

    render: function() {
        var {field, description} = this.props;
        var active = this.state.active;
        var header;
        if (description === ""){
            header = {field};
        }else{
            header = (

                    {field}

                            {description}

            );
        }
        return (
{header}
);
    }
});
<commit_msg>added robust title lookup in item.js<commit_after>'use strict';
var React = require('react');
var collection = require('./collection');
var fetched = require('./fetched');
var globals = require('./globals');
var audit = require('./audit');
var form = require('./form');
var _ = require('underscore');
var cx = require('react/lib/cx');
var panel = require('../libs/bootstrap/panel');
var AuditIndicators = audit.AuditIndicators;
var AuditDetail = audit.AuditDetail;
var AuditMixin = audit.AuditMixin;
var JSONSchemaForm = form.JSONSchemaForm;
var Table = collection.Table;
var {Panel, PanelBody, PanelHeading} = panel;

var Fallback = module.exports.Fallback = React.createClass({
    contextTypes: {
        location_href: React.PropTypes.string
    },

    render: function() {
        var url = require('url');
        var context = this.props.context;
        var title = typeof context.title == "string" ? context.title : url.parse(this.context.location_href).path;
        return (

{title}

                {typeof context.description == "string" ?
{context.description}
 : null}

{JSON.stringify(context, null, 4)}

        );
    }
});

var Item = module.exports.Item = React.createClass({
    mixins: [AuditMixin],
    render: function() {
        var context = this.props.context;
        var itemClass = globals.itemClass(context, 'view-item');
        var title = globals.listing_titles.lookup(context)({context: context});
        var IPanel = globals.panel_views.lookup(context);

        // Make string of alternate accessions
        var altacc = context.alternate_accessions ? context.alternate_accessions.join(', ') : undefined;

        return (

{title}

                        {altacc ?
Replaces {altacc}
 : null}

                            <AuditIndicators context={context} key="biosample-audit" />

                <AuditDetail context={context} key="biosample-audit" />

                    <fetched.FetchedData>
                        <fetched.Param name="schemas" url="/profiles/" />
                        <IPanel {...this.props} />
                    </fetched.FetchedData>

        );
    }
});

globals.content_views.register(Item, 'Item');

// Also use this view as a fallback for anything we haven't registered
globals.content_views.fallback = function () {
    return Fallback;
};

var IPanel = module.exports.IPanel = React.createClass({
    render: function() {
        var schemas = this.props.schemas;
        var context = this.props.context;
        var itemClass = globals.itemClass(context, 'view-detail panel');
        var title = globals.listing_titles.lookup(context)({context: context});
        var sortKeys = Object.keys(context).sort();
        var tips = tipsFromSchema(schemas, context);
        return (

            <Panel addClasses="data-display">
                <PanelBody addClasses="panel-body-with-header">

{title}

                                {sortKeys.map(function(ikey, val){
                                    return (

                                          {formKey(tips,ikey)}

{formValue(schemas,context[ikey])}

                                    );
                                })}

                </PanelBody>
            </Panel>

        );
    }
});

globals.panel_views.register(IPanel, 'Item');

// Also use this view as a fallback for anything we haven't registered
globals.panel_views.fallback = function () {
    return IPanel;
};

var title = module.exports.title = function (props) {
    var context = props.context;
    return context.title || context.name || context.accession || context['@id'];
};

globals.listing_titles.register(title, 'Item');

// Also use this view as a fallback for anything we haven't registered
globals.listing_titles.fallback = function () {
    return title;
};

var ItemEdit = module.exports.ItemEdit = React.createClass({
    contextTypes: {
        navigate: React.PropTypes.func
    },

    render: function() {
        var context = this.props.context;
        var itemClass = globals.itemClass(context, 'view-item');
        var title = globals.listing_titles.lookup(context)({context: context});
        var action, form, schemaUrl, type;
        if (context['@type'][0].indexOf('Collection') !== -1) {  // add form
            type = context['@type'][0].substr(0, context['@type'][0].length - 10);
            title = title + ': Add';
            action = context['@id'];
            form = (
                <fetched.FetchedData>
                    <fetched.Param name="schemas" url="/profiles/" />
                    <JSONSchemaForm type={type} action={action} method="POST" onFinish={this.finished}
                                    showReadOnly={false} />
                </fetched.FetchedData>
            );
        } else {  // edit form
            type = context['@type'][0];
            title = 'Edit ' + title;
            var id = this.props.context['@id'];
            var url = id + '?frame=edit';
            form = (
                <fetched.FetchedData>
                    <fetched.Param name="context" url={url} etagName="etag" />
                    <fetched.Param name="schemas" url="/profiles/" />
                    <JSONSchemaForm id={id} type={type} action={id} method="PUT" onFinish={this.finished} />
                </fetched.FetchedData>
            );
        }
        return (

{title}

                {form}

        );
    },
    finished: function(data) {
      var url = data['@graph'][0]['@id'];
      this.context.navigate(url);
    }
});

globals.content_views.register(ItemEdit, 'Item', 'edit');
globals.content_views.register(ItemEdit, 'Collection', 'add');

var FetchedRelatedItems = React.createClass({
    getDefaultProps: function() {
        return {Component: Table};
    },

    render: function() {
        var {Component, context, title, url, ...props} = this.props;
        if (context === undefined) return null;
        var items = context['@graph'];
        if (!items.length) return null;

        return (
            <Component {...props} title={title} context={context} total={context.total} items={items} url={url} showControls={false} />
        );
    },

});

var RelatedItems = module.exports.RelatedItems = React.createClass({
    getDefaultProps: function() {
        return {limit: 5};
    },

    render: function() {
        var url = this.props.url + '&status!=deleted&status!=revoked&status!=replaced';
        var limited_url = url + '&limit=' + this.props.limit;
        var unlimited_url = url + '&limit=all';
        return (
            <fetched.FetchedData>
                <fetched.Param name="context" url={limited_url} />
                <FetchedRelatedItems {...this.props} url={unlimited_url} />
            </fetched.FetchedData>
        );
    },
});

// Formats the correct display for each metadata field
var formValue = function (schemas, item) {
    var toReturn = [];
    if(Array.isArray(item)) {
        for (var i=0; i < item.length; i++){
            toReturn.push(formValue(schemas, item[i]));
        }
    }else if (typeof item === 'object') {
        if(item['@type']){
            var type = item['@type'][0];
        }
        toReturn.push(<SubIPannel schemas={schemas} content={item}/>);
    }else{
        if (typeof item === 'string' && item.charAt(0) === '/') {
            toReturn.push({item})
        }else{
            toReturn.push(item);
        }
    }
    return(

{toReturn}

    );
};

var SubIPannel = React.createClass({
    getInitialState: function() {
    	return {isOpen: false};
    },
    handleToggle: function (e) {
      e.preventDefault();
      this.setState({
  		  isOpen: !this.state.isOpen,
  	  });
    },
    render: function() {
        var schemas = this.props.schemas;
        var item = this.props.content;
        // TODO: make this process generic using lookup with registry
        var title = item.title || item.name || item.accession || item['@id'] || "Open";
        var toggleRender;
        var toggleLink;
        if (!this.state.isOpen) {
            toggleLink = {title}
            toggleRender = ;
        }else{
            toggleLink = Close
            toggleRender = <Subview schemas={schemas} content={item}/>;
        }
        return (

                  {toggleLink}

              {toggleRender}

        );
        },
});

var Subview = React.createClass({
    render: function(){
        var schemas = this.props.schemas;
        var item = this.props.content;
        var tips = tipsFromSchema(schemas, item);
        return(

              <Panel addClasses="data-display">
                  <PanelBody addClasses="panel-body-with-header">

                                  {Object.keys(item).map(function(ikey, val){
                                      return (

                                          {formKey(tips,ikey)}

{formValue(schemas, item[ikey])}

                                      );
                                  })}

                  </PanelBody>
              </Panel>

        );
    }
});

//Return the properties dictionary from a schema for use as tooltips
var tipsFromSchema = function(schemas, context){
    var tips = {};
    if(context['@type']){
        var type = context['@type'][0];
        tips = schemas[type]['properties'];
    }
    return tips;
};

var formKey =  function(tips, key){
    var tooltip = '';
    if (tips[key]){
        var info = tips[key];
        if(info['description']){
            tooltip = info['description'];
        }
    }
    return(
        <DescriptorField field={key} description={tooltip}/>
    );
};

// Display the item field with a tooltip showing the field description from
// schema, if available
var DescriptorField = React.createClass({
    propTypes: {
        field: React.PropTypes.string.isRequired,
        description: React.PropTypes.string.isRequired
    },
    getInitialState: function() {
        return {
            active: false
        };
    },

    handleHover: function(b) {
        this.setState({active: b});
    },

    render: function() {
        var {field, description} = this.props;
        var active = this.state.active;
        var header;
        if (description === ""){
            header = {field};
        }else{
            header = (

                    {field}

                            {description}

            );
        }
        return (
{header}
);
    }
});
<|endoftext|>


<commit_before>(function() {

var PHOTO_RESPONSE_ALL = -42; // used as key for all response counts
var PHOTO_RESPONSE_UNANSWERED = 0;
var PHOTO_RESPONSE_INCOMPLETE = 1;
var PHOTO_RESPONSE_COMPLETE = 2;
var PHOTO_RESPONSE_PHOTO_PROBLEM = 0x10;

var useQuicksand = false;

$.widget('ui.bInfoList', {

	_init: function() {
	    // Options are being extended with defaults (except for items that should not be cloned)
	    var items = this.options.items || [];
	    this.options.items = null;
        this.options = _.extend({
            sortMode: 'id',
            items: [],
            dblclickAction: null,
            customizeItem: null,
            mouseHoverDelay: 50,
            currentId: null,
            highlightedIds: null,
            disableThumbnails: true,
            sortModes: ['id', 'completed', 'problems']
        }, this.options);
        this.options.items = items;
        var defaultCurrentId = this.options.currentId;
        var defaultHighlightedIds = this.options.highlightedIds;

        var w = {
				_self: this,
				$element: this.element,
				options: this.options
			};
		this.w = w;

        w.$percentage = $('<div/>').addClass('b-infolist__percentage');
		w.$sorters = $('<ul/>').addClass("b-infolist__sorters").disableSelection();
		_.each(w.options.sortModes, function(sortMode) {
		    w.$sorters.append($('<li/>').addClass('b-infolist__sorter').attr('data-mode', sortMode).append($('<i/>').text(sortMode)));
		});
		w.$items = $('<ul/>').addClass("b-infolist__items");
		w.$resizeBlind = $('<div/>').addClass("b-infolist__resize-blind");
		w.$hint = $('<div/>').addClass('b-infolist__hint');
		w.itemsMap = {};
		w.$itemsMap = {};
		w.options.currentId = null;
        w.mouseId = null;
		w.mouseIdChangerHash = null;
		w.$currentItem = null;
		w.$highlightedItems = null;

		// Sorters events

		w.$sorters.children().click(function() {
		    var $this = $(this);
		    w._self.sortItemsBy($this.data('mode'));
		});

		// Item events
		//// Changes mouse id when hover
		var triggerMouseoveritemWithDelay = function(id) {
		    if (w.mouseId === id && id !== null)
		        return;
		    var mouseIdChangerHash = Math.random();
		    w.mouseIdChangerHash = mouseIdChangerHash;
		    setTimeout(function() {
		        if (w.mouseIdChangerHash === mouseIdChangerHash) {
		            w._self._trigger("hoveroveritem", null, {id: id, itemData: w.itemsMap[id]});
		            w.mouseId = id;
		            w._self._updateHintUsingMouseData();
		        }
		    }, w.options.mouseHoverDelay);

		    // updates percentage
            setTimeout(function() {
                if (w.mouseId === id)
                    return;
                if (id === null) {
                    w.$percentage.text('');
                } else {
                    var itemsTotal = _.size(w.$itemsMap);
                    var currentIndex = w.$itemsMap[id].index();
                    w.$percentage.text(Math.floor((currentIndex + 1)/itemsTotal*100) + '%');
                }
            }, 20);
		};

		//// Hover over
		var onItemHoverOver = function() {
            var $this = $(this);
            triggerMouseoveritemWithDelay($this.data('id'));
		};

		//// Hover out
		var onItemHoverOut = function() {
            triggerMouseoveritemWithDelay(null);
		};

		// Click
		var onItemClick = function() {
		    var $this = $(this);
		    w._self.setCurrentItemId($this.data('id'));
        };

        // Double click
        var onItemDblClick = function() {
        };

        // Populate items
		_.each(w.options.items, function(itemData) {
		    var id = itemData.id;
		    var $item = $('<li/>').addClass('b-infolist__item');
		    var addItem = true;
		    $item.click(onItemClick);
		    $item.mouseenter(onItemHoverOver);
		    $item.mouseleave(onItemHoverOut);
		    if (_.isFunction(w.options.dblclickAction)) {
		        $item.dblclick(w.options.dblclickAction);
		    }

		    $item.attr('data-id', id);
		    $item.data('data', itemData);
		    if (_.isFunction(w.options.customizeItem)) {
		        if (false === w.options.customizeItem($item, id, itemData)) {
		            addItem = false;
		        }
		    }
		    if (addItem) {
		        $item.appendTo(w.$items);
		        w.itemsMap[id] = itemData;
		        w.$itemsMap[id] = $item;
		    }
		});

		// sort items
		w._self.sortItemsBy(w.options.sortMode, false, true);

		// Make the element resizable with constraints taken from css
		w.$element.resizable({
		    maxHeight: w.$element.css('maxHeight'),
		    maxWidth: w.$element.width(),
		    minHeight: w.$element.css('minHeight'),
		    minWidth: w.$element.width(),
		    handles: 's',
		    start: function() {
		        w.$resizeBlind.appendTo('body');
		    },
		    stop: function() {
		        w.$resizeBlind.detach();
		    }
		});

        w._self.setCurrentItemId(defaultCurrentId);
        w._self.setHighlightedItemIds(defaultHighlightedIds);
        w._self.setDisableThumbnails(w.options.disableThumbnails);

        w.$element.append(w.$percentage, w.$sorters, w.$items, w.$hint);

        w._self._updateHintPos();
	},

	sortItemsBy: function(mode, isDescending, forceNoAnimation) {
	    var w = this.w;

	    var currentIsDescending = null;

	    // Check whether sort mode has been changed, update interface if needed and exit otherwise
	    var $currentModeNode = w.$sorters.find('.ascending, .descending');
	    if ($currentModeNode.length) {
	        currentIsDescending = $currentModeNode.hasClass('descending');
	        $currentModeNode.removeClass('ascending descending');
	        if (_.isUndefined(isDescending)) {
	            if ($currentModeNode.data('mode') == mode) {
	                isDescending = !currentIsDescending;
	            } else {
	                isDescending = false;
	            }
	        } else {
	            if ($currentModeNode.data('mode') == mode && $currentModeNode == $currentModeNode) {
	                return;
	            }
	        }
	    }

	    var $newModeNode = w.$sorters.find('[data-mode="' + mode + '"]');
	    $newModeNode.addClass(isDescending ? 'descending' : 'ascending');

        // Get list of new ids, if the sequence matches the old one, exit
	    var oldIds = _.map(w.options.items, function(item) {
	        return item.id;
	    });

	    var newItems = _.sortBy(w.options.items, function(item) {
	       var id = item.id < 0 ? 9999 : parseInt(item.id, 10);
	       switch (mode) {
	       case "completed":
	           return item.photoResponseCounts[PHOTO_RESPONSE_COMPLETE] * 10000 + id;

	       case "problems":
               return item.photoResponseCounts[PHOTO_RESPONSE_PHOTO_PROBLEM] * -10000 + id;

           case "unread":
               return (item.isUnread ? -10000 : 0) + id;

           case "suitability":
               return (item.isUnread ? -10000 : 0) + id;

           case "id":
	       default:
	           return id;

	       }
	    });

	    if (isDescending) {
	        newItems.reverse();
	    }

	    var newIds = _.map(newItems, function(item) {
            return item.id;
        });

	    if (_.isEqual(oldIds, newIds))
	        return;

	    // Sort using quicksand
	    if (useQuicksand) {
	        // Generate a list of new ui objects to then pass them to sandbox
	        var $newItems = $();
	        _.each(newIds, function(id) {
	            if (!w.$itemsMap[id])
	                return;
	            $newItems = $newItems.add($('<li/>').addClass('b-infolist__item-placeholder').attr('data-id', id));
	        });

	        w.$items.quicksand($newItems, {
	            //atomic: true,
	            useScaling: false,
	            adjustHeight: false,
	            adjustWidth: false
	        });

	    } else {
	        var oldScrollTop = w.$items.scrollTop();
	        //w.$items.empty();
	        w.$items.detach();
	        _.each(newIds, function(id) {
                if (!w.$itemsMap[id])
                    return;
	            w.$items.append(w.$itemsMap[id]);
	        });
	        w.$items.appendTo(w.$element);
	        w.$items.scrollTop(oldScrollTop);
	    }
	    w.options.items = newItems;
	},

	/** Update items
	 */
	updateItems: function(ids) {
		var w = this.w;

		if (!_.isArray(ids)) {
		    ids = _.keys(w.options.items);
		}

		w.$items.detach();
        if (_.isFunction(w.options.customizeItem)) {
            _.each(ids, function(id) {
                var $item = w.$itemsMap[id];
                w.options.customizeItem($item, id, w.itemsMap[id]);
            });
        }

        w.$items.appendTo(w.$element);
	},

	setCurrentItemId: function(newId) {
		var w = this.w;

		if (newId == w.options.currentId)
			return false;

		if (w.$currentItem) {
			w.$currentItem.removeClass('current');
		}

		var $newCurrentItem = w.$itemsMap[newId];

		w.options.currentId = newId;
		if ($newCurrentItem) {
		    $newCurrentItem.addClass('current');
		    w.$currentItem = $newCurrentItem;
		    w.$currentItem.scrollintoview();
		}
		w._self._trigger("changeitem", null, {id: newId, itemData: w.itemsMap[newId]});
	},

    setHighlightedItemIds: function(newIds) {
        var w = this.w;

        if (_.isEqual(newIds, w.options.highlightedIds))
            return false;

        if (w.$highlightedItems) {
            w.$highlightedItems.removeClass('highlighted');
        }

        var $newHighlightedItemElements = [];
        _.each(newIds, function(id) {
            $newHighlightedItemElements.push(w.$itemsMap[id][0]);
        });
        var $newHighlightedItems = $($newHighlightedItemElements);
        $newHighlightedItems.addClass('highlighted');
        w.options.highlightedIds = newIds;
        w.$highlightedItems = $newHighlightedItems;
        w._self._trigger("highlightitems", null, {ids: newIds});
    },

	setDisableThumbnails: function(disableThumbnails) {
        var w = this.w;

        if (w.options.disableThumbnails == disableThumbnails)
            return;

	    w.options.disableThumbnails = disableThumbnails;
	    w.$element.toggleClass('b-infolist_thumbnails-enabled', !disableThumbnails);
	    w.$element.toggleClass('b-infolist_thumbnails-disabled', disableThumbnails);
	},

    _updateHintUsingMouseData: function() {
        var w = this.w;

        if (!w.mouseId) {
            w.$hint.text('');
        } else {
            w.$hint.text(w.$itemsMap[w.mouseId].data('hint'));
        }
    },

    _updateMouseHint: function() {
        var w = this.w;

        if (!w.mouseId) {
            w.$hint.text('');
        } else {
            w.$hint.text(w.$itemsMap[w.mouseId].data('hint'));
        }
    },

    setHeight: function(newHeight) {
        var w = this.w;

        if (w.$element.height() == newHeight) {
            return;
        }

        w.$element.height(newHeight);
        w._self._updateHintPos();
    },

	_updateHintPos: function() {
        var w = this.w;

	    if (w.$items.get(0).scrollHeight > w.$items.height()) {
	        w.$hint.css('top', w.$items.offset().top - w.$element.offset().top + w.$items.height());
	    } else {
	        var $lastLi = w.$items.children().last();
	        w.$hint.css('top', $lastLi.offset().top + $lastLi.outerHeight() - w.$element.offset().top);
	    }
	}
});
}());<commit_msg>Implement sorting by suitability of photos (based on avg)<commit_after>(function() {

var PHOTO_RESPONSE_ALL = -42; // used as key for all response counts
var PHOTO_RESPONSE_UNANSWERED = 0;
var PHOTO_RESPONSE_INCOMPLETE = 1;
var PHOTO_RESPONSE_COMPLETE = 2;
var PHOTO_RESPONSE_PHOTO_PROBLEM = 0x10;

var useQuicksand = false;

$.widget('ui.bInfoList', {

	_init: function() {
	    // Options are being extended with defaults (except for items that should not be cloned)
	    var items = this.options.items || [];
	    this.options.items = null;
        this.options = _.extend({
            sortMode: 'id',
            items: [],
            dblclickAction: null,
            customizeItem: null,
            mouseHoverDelay: 50,
            currentId: null,
            highlightedIds: null,
            disableThumbnails: true,
            sortModes: ['id', 'completed', 'problems']
        }, this.options);
        this.options.items = items;
        var defaultCurrentId = this.options.currentId;
        var defaultHighlightedIds = this.options.highlightedIds;

        var w = {
				_self: this,
				$element: this.element,
				options: this.options
			};
		this.w = w;

        w.$percentage = $('<div/>').addClass('b-infolist__percentage');
		w.$sorters = $('<ul/>').addClass("b-infolist__sorters").disableSelection();
		_.each(w.options.sortModes, function(sortMode) {
		    w.$sorters.append($('<li/>').addClass('b-infolist__sorter').attr('data-mode', sortMode).append($('<i/>').text(sortMode)));
		});
		w.$items = $('<ul/>').addClass("b-infolist__items");
		w.$resizeBlind = $('<div/>').addClass("b-infolist__resize-blind");
		w.$hint = $('<div/>').addClass('b-infolist__hint');
		w.itemsMap = {};
		w.$itemsMap = {};
		w.options.currentId = null;
        w.mouseId = null;
		w.mouseIdChangerHash = null;
		w.$currentItem = null;
		w.$highlightedItems = null;

		// Sorters events

		w.$sorters.children().click(function() {
		    var $this = $(this);
		    w._self.sortItemsBy($this.data('mode'));
		});

		// Item events
		//// Changes mouse id when hover
		var triggerMouseoveritemWithDelay = function(id) {
		    if (w.mouseId === id && id !== null)
		        return;
		    var mouseIdChangerHash = Math.random();
		    w.mouseIdChangerHash = mouseIdChangerHash;
		    setTimeout(function() {
		        if (w.mouseIdChangerHash === mouseIdChangerHash) {
		            w._self._trigger("hoveroveritem", null, {id: id, itemData: w.itemsMap[id]});
		            w.mouseId = id;
		            w._self._updateHintUsingMouseData();
		        }
		    }, w.options.mouseHoverDelay);

		    // updates percentage
            setTimeout(function() {
                if (w.mouseId === id)
                    return;
                if (id === null) {
                    w.$percentage.text('');
                } else {
                    var itemsTotal = _.size(w.$itemsMap);
                    var currentIndex = w.$itemsMap[id].index();
                    w.$percentage.text(Math.floor((currentIndex + 1)/itemsTotal*100) + '%');
                }
            }, 20);
		};

		//// Hover over
		var onItemHoverOver = function() {
            var $this = $(this);
            triggerMouseoveritemWithDelay($this.data('id'));
		};

		//// Hover out
		var onItemHoverOut = function() {
            triggerMouseoveritemWithDelay(null);
		};

		// Click
		var onItemClick = function() {
		    var $this = $(this);
		    w._self.setCurrentItemId($this.data('id'));
        };

        // Double click
        var onItemDblClick = function() {
        };

        // Populate items
		_.each(w.options.items, function(itemData) {
		    var id = itemData.id;
		    var $item = $('<li/>').addClass('b-infolist__item');
		    var addItem = true;
		    $item.click(onItemClick);
		    $item.mouseenter(onItemHoverOver);
		    $item.mouseleave(onItemHoverOut);
		    if (_.isFunction(w.options.dblclickAction)) {
		        $item.dblclick(w.options.dblclickAction);
		    }

		    $item.attr('data-id', id);
		    $item.data('data', itemData);
		    if (_.isFunction(w.options.customizeItem)) {
		        if (false === w.options.customizeItem($item, id, itemData)) {
		            addItem = false;
		        }
		    }
		    if (addItem) {
		        $item.appendTo(w.$items);
		        w.itemsMap[id] = itemData;
		        w.$itemsMap[id] = $item;
		    }
		});

		// sort items
		w._self.sortItemsBy(w.options.sortMode, false, true);

		// Make the element resizable with constraints taken from css
		w.$element.resizable({
		    maxHeight: w.$element.css('maxHeight'),
		    maxWidth: w.$element.width(),
		    minHeight: w.$element.css('minHeight'),
		    minWidth: w.$element.width(),
		    handles: 's',
		    start: function() {
		        w.$resizeBlind.appendTo('body');
		    },
		    stop: function() {
		        w.$resizeBlind.detach();
		    }
		});

        w._self.setCurrentItemId(defaultCurrentId);
        w._self.setHighlightedItemIds(defaultHighlightedIds);
        w._self.setDisableThumbnails(w.options.disableThumbnails);

        w.$element.append(w.$percentage, w.$sorters, w.$items, w.$hint);

        w._self._updateHintPos();
	},

	sortItemsBy: function(mode, isDescending, forceNoAnimation) {
	    var w = this.w;

	    var currentIsDescending = null;

	    // Check whether sort mode has been changed, update interface if needed and exit otherwise
	    var $currentModeNode = w.$sorters.find('.ascending, .descending');
	    if ($currentModeNode.length) {
	        currentIsDescending = $currentModeNode.hasClass('descending');
	        $currentModeNode.removeClass('ascending descending');
	        if (_.isUndefined(isDescending)) {
	            if ($currentModeNode.data('mode') == mode) {
	                isDescending = !currentIsDescending;
	            } else {
	                isDescending = false;
	            }
	        } else {
	            if ($currentModeNode.data('mode') == mode && $currentModeNode == $currentModeNode) {
	                return;
	            }
	        }
	    }

	    var $newModeNode = w.$sorters.find('[data-mode="' + mode + '"]');
	    $newModeNode.addClass(isDescending ? 'descending' : 'ascending');

        // Get list of new ids, if the sequence matches the old one, exit
	    var oldIds = _.map(w.options.items, function(item) {
	        return item.id;
	    });

	    var newItems = _.sortBy(w.options.items, function(item) {
	       var id = item.id < 0 ? 9999 : parseInt(item.id, 10);
	       switch (mode) {
	       case "completed":
	           return item.photoResponseCounts[PHOTO_RESPONSE_COMPLETE] * 10000 + id;

	       case "problems":
               return item.photoResponseCounts[PHOTO_RESPONSE_PHOTO_PROBLEM] * -10000 + id;

           case "unread":
               return (item.isUnread ? -10000 : 0) + id;

           case "suitability":
               var completeResponsesCount = 0;
               var sums = [];
               for (var i = pat.config.questions.length - 1; i >= 0; --i) {
                   sums.push(0);
               }
               for (var j = item.photoResponses.length - 1, pr = item.photoResponses[j]; j >=0; --j, pr = item.photoResponses[j]) {
                   if (pr.status == PHOTO_RESPONSE_COMPLETE) {
                       ++completeResponsesCount;
                       for (var i = pat.config.questions.length - 1; i >= 0; --i) {
                           var question = pat.config.questions[i];
                           sums[i] += _.indexOf(pat.getAnswerSeq(question), pr[question]);
                       };
                   }
               }
               if (completeResponsesCount == 0) {
                   return 100500; // photos with no responses are the least suitable (have a big number)
               } else {
                   var result = 0;
                   for (var i = pat.config.questions.length - 1; i >= 0; --i) {
                       result += sums[i] / completeResponsesCount;
                   }
                   return result;
               }

           case "id":
	       default:
	           return id;

	       }
	    });

	    if (isDescending) {
	        newItems.reverse();
	    }

	    var newIds = _.map(newItems, function(item) {
            return item.id;
        });

	    if (_.isEqual(oldIds, newIds))
	        return;

	    // Sort using quicksand
	    if (useQuicksand) {
	        // Generate a list of new ui objects to then pass them to sandbox
	        var $newItems = $();
	        _.each(newIds, function(id) {
	            if (!w.$itemsMap[id])
	                return;
	            $newItems = $newItems.add($('<li/>').addClass('b-infolist__item-placeholder').attr('data-id', id));
	        });

	        w.$items.quicksand($newItems, {
	            //atomic: true,
	            useScaling: false,
	            adjustHeight: false,
	            adjustWidth: false
	        });

	    } else {
	        var oldScrollTop = w.$items.scrollTop();
	        //w.$items.empty();
	        w.$items.detach();
	        _.each(newIds, function(id) {
                if (!w.$itemsMap[id])
                    return;
	            w.$items.append(w.$itemsMap[id]);
	        });
	        w.$items.appendTo(w.$element);
	        w.$items.scrollTop(oldScrollTop);
	    }
	    w.options.items = newItems;
	},

	/** Update items
	 */
	updateItems: function(ids) {
		var w = this.w;

		if (!_.isArray(ids)) {
		    ids = _.keys(w.options.items);
		}

		w.$items.detach();
        if (_.isFunction(w.options.customizeItem)) {
            _.each(ids, function(id) {
                var $item = w.$itemsMap[id];
                w.options.customizeItem($item, id, w.itemsMap[id]);
            });
        }

        w.$items.appendTo(w.$element);
	},

	setCurrentItemId: function(newId) {
		var w = this.w;

		if (newId == w.options.currentId)
			return false;

		if (w.$currentItem) {
			w.$currentItem.removeClass('current');
		}

		var $newCurrentItem = w.$itemsMap[newId];

		w.options.currentId = newId;
		if ($newCurrentItem) {
		    $newCurrentItem.addClass('current');
		    w.$currentItem = $newCurrentItem;
		    w.$currentItem.scrollintoview();
		}
		w._self._trigger("changeitem", null, {id: newId, itemData: w.itemsMap[newId]});
	},

    setHighlightedItemIds: function(newIds) {
        var w = this.w;

        if (_.isEqual(newIds, w.options.highlightedIds))
            return false;

        if (w.$highlightedItems) {
            w.$highlightedItems.removeClass('highlighted');
        }

        var $newHighlightedItemElements = [];
        _.each(newIds, function(id) {
            $newHighlightedItemElements.push(w.$itemsMap[id][0]);
        });
        var $newHighlightedItems = $($newHighlightedItemElements);
        $newHighlightedItems.addClass('highlighted');
        w.options.highlightedIds = newIds;
        w.$highlightedItems = $newHighlightedItems;
        w._self._trigger("highlightitems", null, {ids: newIds});
    },

	setDisableThumbnails: function(disableThumbnails) {
        var w = this.w;

        if (w.options.disableThumbnails == disableThumbnails)
            return;

	    w.options.disableThumbnails = disableThumbnails;
	    w.$element.toggleClass('b-infolist_thumbnails-enabled', !disableThumbnails);
	    w.$element.toggleClass('b-infolist_thumbnails-disabled', disableThumbnails);
	},

    _updateHintUsingMouseData: function() {
        var w = this.w;

        if (!w.mouseId) {
            w.$hint.text('');
        } else {
            w.$hint.text(w.$itemsMap[w.mouseId].data('hint'));
        }
    },

    _updateMouseHint: function() {
        var w = this.w;

        if (!w.mouseId) {
            w.$hint.text('');
        } else {
            w.$hint.text(w.$itemsMap[w.mouseId].data('hint'));
        }
    },

    setHeight: function(newHeight) {
        var w = this.w;

        if (w.$element.height() == newHeight) {
            return;
        }

        w.$element.height(newHeight);
        w._self._updateHintPos();
    },

	_updateHintPos: function() {
        var w = this.w;

	    if (w.$items.get(0).scrollHeight > w.$items.height()) {
	        w.$hint.css('top', w.$items.offset().top - w.$element.offset().top + w.$items.height());
	    } else {
	        var $lastLi = w.$items.children().last();
	        w.$hint.css('top', $lastLi.offset().top + $lastLi.outerHeight() - w.$element.offset().top);
	    }
	}
});
}());<|endoftext|>


<commit_before>#!/usr/bin/env node

/* eg. node bin/nearleythere.js examples/js/left.js --input "....."
   or, node bin/nearleythere.js examples/js/AycockHorspool.js --input "aa"
 */

var fs = require('fs');
var nearley = require('../lib/nearley.js');
var nomnom = require('nomnom');
var StreamWrapper = require('../lib/stream.js');

var opts = nomnom
    .script('nearley-test')
    .option('file', {
        position: 0,
        help: "A grammar .js file",
        required: true,
    })
    .option('input', {
        abbr: 'i',
        help: "An input string to parse (if not provided then read from stdin)",
        type: 'string',
    })
    .option('start', {
        abbr: 's',
        help: "An optional start symbol (if not provided then use the parser start symbol)",
    })
    .option('out', {
        abbr: 'o',
        help: "File to output to (defaults to stdout)",
    })
    .option('quiet', {
        abbr: 'q',
        flag: true,
        help: "Output parse results only (hide Earley table)",
    })
    .option('version', {
        abbr: 'v',
        flag: true,
        help: "Print version and exit",
        callback: function() {
            return require('../package.json').version;
        }
    })
    .parse();

var output = opts.out ? fs.createWriteStream(opts.out) : process.stdout;

var grammar = new require(require('path').resolve(opts.file));
var parser = new nearley.Parser(grammar.ParserRules, opts.start ? opts.start : grammar.ParserStart);

var writeTable = function (writeStream, parser) {
    writeStream.write("Table length: " + parser.table.length + "\n");
    writeStream.write("Number of parses: " + parser.results.length + "\n");
    writeStream.write("Parse Charts");
    var chartNumber = 0;
    parser.table.forEach(
        function (chart) {
            writeStream.write("\nChart: " + chartNumber++ + "\n");
            var stateNumber = 0;
            chart.forEach(
                function (state) {
                    writeStream.write(stateNumber++ + ": " + state.toString() + "\n");
                } )
        } )
    writeStream.write("\n\nParse results: \n");
}

var writeResults = function (writeStream, parser) {
    writeStream.write(require('util').inspect(parser.results, {colors: !opts.quiet, depth: null}));
    writeStream.write("\n");
}

if (typeof(opts.input) === "undefined") {
    process.stdin
        .pipe(new StreamWrapper(parser))
        .on('finish', function() {
            if (!opts.quiet) writeTable(output, parser);
            writeResults(output, parser);
        });
} else {
    parser.feed(opts.input);
    if (!opts.quiet) writeTable(output, parser);
    writeResults(output, parser);
}

<commit_msg>Fix nearley-test for Columns<commit_after>#!/usr/bin/env node

/* eg. node bin/nearleythere.js examples/js/left.js --input "....."
   or, node bin/nearleythere.js examples/js/AycockHorspool.js --input "aa"
 */

var fs = require('fs');
var nearley = require('../lib/nearley.js');
var nomnom = require('nomnom');
var StreamWrapper = require('../lib/stream.js');

var opts = nomnom
    .script('nearley-test')
    .option('file', {
        position: 0,
        help: "A grammar .js file",
        required: true,
    })
    .option('input', {
        abbr: 'i',
        help: "An input string to parse (if not provided then read from stdin)",
        type: 'string',
    })
    .option('start', {
        abbr: 's',
        help: "An optional start symbol (if not provided then use the parser start symbol)",
    })
    .option('out', {
        abbr: 'o',
        help: "File to output to (defaults to stdout)",
    })
    .option('quiet', {
        abbr: 'q',
        flag: true,
        help: "Output parse results only (hide Earley table)",
    })
    .option('version', {
        abbr: 'v',
        flag: true,
        help: "Print version and exit",
        callback: function() {
            return require('../package.json').version;
        }
    })
    .parse();

var output = opts.out ? fs.createWriteStream(opts.out) : process.stdout;

var grammar = new require(require('path').resolve(opts.file));
var parser = new nearley.Parser(grammar.ParserRules, opts.start ? opts.start : grammar.ParserStart);

var writeTable = function (writeStream, parser) {
    writeStream.write("Table length: " + parser.table.length + "\n");
    writeStream.write("Number of parses: " + parser.results.length + "\n");
    writeStream.write("Parse Charts");
    parser.table.forEach(
        function (column, chartNumber) {
            console.log(column);
            writeStream.write("\nChart: " + chartNumber++ + "\n");
            column.states.forEach(
                function (state, stateNumber) {
                    writeStream.write(stateNumber++ + ": " + state.toString() + "\n");
                } )
        } )
    writeStream.write("\n\nParse results: \n");
}

var writeResults = function (writeStream, parser) {
    writeStream.write(require('util').inspect(parser.results, {colors: !opts.quiet, depth: null}));
    writeStream.write("\n");
}

if (typeof(opts.input) === "undefined") {
    process.stdin
        .pipe(new StreamWrapper(parser))
        .on('finish', function() {
            if (!opts.quiet) writeTable(output, parser);
            writeResults(output, parser);
        });
} else {
    parser.feed(opts.input);
    if (!opts.quiet) writeTable(output, parser);
    writeResults(output, parser);
}

<|endoftext|>


<commit_before>const typeInfoRegex = /^:([a-z])(\((.+)\))?/;

class tag {
    constructor() {
        this.locale = 'en-US'
        this.currency = 'USD'
        this.translations = {}
        this.number = {}
        this.date = {}
        this._localizers = {
            s /*string*/: v => v.toLocaleString(this.locale),
            c /*currency*/: (v, currency) => (
                v.toLocaleString(this.locale, {
                    style: 'currency',
                    currency: currency || this.currency
                })
            ),
            n /*number*/: (v, fractionalDigits) => (
                v.toLocaleString(this.locale, (fractionalDigits) ?
                    Object.assign({}, this.number, { minimumFractionDigits: fractionalDigits, maximumFractionDigits: fractionalDigits }) :
                    Object.assign({}, this.number)
                )
            ),
            t /*date*/: (v) => (
                v.toLocaleString(this.locale, (this.date) ?
                    Object.assign({}, this.date) :
                    {}
                )
            )
        }
        this.i18n = this.i18n.bind(this)
        this.i18nConfig = this.i18nConfig.bind(this)
        this._localize = this._localize.bind(this)
    }

    i18nConfig({locale, currency, translations, number, date}) {
        this.locale = locale || this.locale
        this.currency = currency || this.currency
        this.translations = translations || this.translations
        this.number = number || this.number
        this.date = date || this.date
    }

    i18n(literals, ...values) {
        let translationKey = this._buildKey(literals);
        let translationString = this.translations[translationKey] || translationKey;
        let typeInfoForValues = literals.slice(1).map(this._extractTypeInfo);
        let localizedValues = values.map((v, i) => this._localize(v, typeInfoForValues[i]));
        return this._buildMessage(translationString, ...localizedValues);
    }

    _extractTypeInfo(literal) {
        let match = typeInfoRegex.exec(literal);
        if (match) {
            return { type: match[1], options: match[3] };
        } else {
            return { type: 's', options: '' };
        }
    }

    _localize(value, {type, options}) {
        return this._localizers[type](value, options);
    }

    // e.g. this._buildKey(['', ' has ', ':c in the']) == '{0} has {1} in the bank'
    _buildKey(literals) {
        let stripType = s => s.replace(typeInfoRegex, '');
        let lastPartialKey = stripType(literals[literals.length - 1]);
        let prependPartialKey = (memo, curr, i) => `${stripType(curr)}\${${i}}${memo}`;

        return literals.slice(0, -1).reduceRight(prependPartialKey, lastPartialKey);
    }

    // e.g. this._formatStrings('{0} {1}!', 'hello', 'world') == 'hello world!'
    _buildMessage(str, ...values) {
        return str.replace(/\${(\d)}/g, (_, index) => values[Number(index)]);
    }

}

var i18ntag = new tag()
var { i18n, i18nConfig } = i18ntag

export { i18n as default, i18nConfig }

<commit_msg>Added global window export<commit_after>const typeInfoRegex = /^:([a-z])(\((.+)\))?/;

class tag {
    constructor() {
        this.locale = 'en-US'
        this.currency = 'USD'
        this.translations = {}
        this.number = {}
        this.date = {}
        this._localizers = {
            s /*string*/: v => v.toLocaleString(this.locale),
            c /*currency*/: (v, currency) => (
                v.toLocaleString(this.locale, {
                    style: 'currency',
                    currency: currency || this.currency
                })
            ),
            n /*number*/: (v, fractionalDigits) => (
                v.toLocaleString(this.locale, (fractionalDigits) ?
                    Object.assign({}, this.number, { minimumFractionDigits: fractionalDigits, maximumFractionDigits: fractionalDigits }) :
                    Object.assign({}, this.number)
                )
            ),
            t /*date*/: (v) => (
                v.toLocaleString(this.locale, (this.date) ?
                    Object.assign({}, this.date) :
                    {}
                )
            )
        }
        this.i18n = this.i18n.bind(this)
        this.i18nConfig = this.i18nConfig.bind(this)
        this._localize = this._localize.bind(this)
    }

    i18nConfig({locale, currency, translations, number, date}) {
        this.locale = locale || this.locale
        this.currency = currency || this.currency
        this.translations = translations || this.translations
        this.number = number || this.number
        this.date = date || this.date
    }

    i18n(literals, ...values) {
        let translationKey = this._buildKey(literals);
        let translationString = this.translations[translationKey] || translationKey;
        let typeInfoForValues = literals.slice(1).map(this._extractTypeInfo);
        let localizedValues = values.map((v, i) => this._localize(v, typeInfoForValues[i]));
        return this._buildMessage(translationString, ...localizedValues);
    }

    _extractTypeInfo(literal) {
        let match = typeInfoRegex.exec(literal);
        if (match) {
            return { type: match[1], options: match[3] };
        } else {
            return { type: 's', options: '' };
        }
    }

    _localize(value, {type, options}) {
        return this._localizers[type](value, options);
    }

    // e.g. this._buildKey(['', ' has ', ':c in the']) == '{0} has {1} in the bank'
    _buildKey(literals) {
        let stripType = s => s.replace(typeInfoRegex, '');
        let lastPartialKey = stripType(literals[literals.length - 1]);
        let prependPartialKey = (memo, curr, i) => `${stripType(curr)}\${${i}}${memo}`;

        return literals.slice(0, -1).reduceRight(prependPartialKey, lastPartialKey);
    }

    // e.g. this._formatStrings('{0} {1}!', 'hello', 'world') == 'hello world!'
    _buildMessage(str, ...values) {
        return str.replace(/\${(\d)}/g, (_, index) => values[Number(index)]);
    }

}

var i18ntag = new tag()
var { i18n, i18nConfig } = i18ntag
if(window) {
    window.i18n = i18n
    window.i18nConfig = i18nConfig
}

export { i18n as default, i18nConfig }

<|endoftext|>


<commit_before>'use strict';

exports.lerp = function( a, b, t ) {
  return a + t * ( b - a );
};

exports.inverseLerp =  function( a, b, x ) {
  return ( x - a ) / ( b - a );
};

exports.clamp = function( x, min, max ) {
  return ( x < max ) ? x : ( ( x > max ) ? max : x );
};

exports.smoothstep = function( x, min, max ) {
  if ( x <= min ) return 0;
  if ( x >= min ) return 1;

  x = ( x - min ) / ( max - min );

  return x * x * ( 3 - 2 * x );
};

exports.smootherstep = function( x, min, max ) {
  if ( x <= min ) return 0;
  if ( x >= min ) return 1;

  x = ( x - min ) / ( max - min );

  return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
};

exports.randInt = function( low, high ) {
  return low + Math.floor( Math.random() * ( high - low + 1 ) );
};

exports.randFloat = function( low, high ) {
  return low + Math.random() * ( high - low );
};

exports.randFloatSpread = function( range ) {
  return range * ( 0.5 - Math.random() );
};

exports.extends = function( child, parent ) {
  child.prototype = Object.create( parent.prototype );
  child.prototype.constructor = child;
};
<commit_msg>Fix clamp() implementation in utils.js.<commit_after>'use strict';

exports.lerp = function( a, b, t ) {
  return a + t * ( b - a );
};

exports.inverseLerp =  function( a, b, x ) {
  return ( x - a ) / ( b - a );
};

exports.clamp = function( x, min, max ) {
  return ( x < min ) ? min : ( ( x > max ) ? max : x );
};

exports.smoothstep = function( x, min, max ) {
  if ( x <= min ) return 0;
  if ( x >= min ) return 1;

  x = ( x - min ) / ( max - min );

  return x * x * ( 3 - 2 * x );
};

exports.smootherstep = function( x, min, max ) {
  if ( x <= min ) return 0;
  if ( x >= min ) return 1;

  x = ( x - min ) / ( max - min );

  return x * x * x * ( x * ( x * 6 - 15 ) + 10 );
};

exports.randInt = function( low, high ) {
  return low + Math.floor( Math.random() * ( high - low + 1 ) );
};

exports.randFloat = function( low, high ) {
  return low + Math.random() * ( high - low );
};

exports.randFloatSpread = function( range ) {
  return range * ( 0.5 - Math.random() );
};

exports.extends = function( child, parent ) {
  child.prototype = Object.create( parent.prototype );
  child.prototype.constructor = child;
};
<|endoftext|>


<commit_before>function HighlightPlugin(bot) {
	var self = this;
	self.name = "highlight";
	self.help = "Highlight plugin";
	self.depend = ["cmd", "pushbullet"];

	self.highlights = {};
	/*
	nick : {
		level: online/away/offline
	}
	*/

	self.load = function(data) {
		if (data)
			self.highlights = data.highlights;

		for (var nick in self.highlights) {
			if (self.highlights[nick].online !== undefined) {
				self.highlights[nick].level = self.highlights[nick].online ? "online" : "offline";
				delete self.highlights[nick].online;
			}
		}
	};

	self.save = function() {
		return {
			"highlights": self.highlights
		};
	}

	self.stripcolors = function(text) {
		return text.replace(/\x1f|\x02|\x12|\x0f|\x16|\x03(?:\d{1,2}(?:,\d{1,2})?)?/g, "");
	}

	self.events = {
		"message": function(nick, to, text) {
			if (nick == to)
				return;

			for (var hinick in self.highlights) {
				var level = self.highlights[hinick].level;
				if (text.match(new RegExp("\\b" + hinick, "i")) && !(!(level == "online" || level == "away") && (hinick in bot.chans[to].users))) {
					text = self.stripcolors(text);
					switch (level) {
					case "online":
						bot.plugins.pushbullet.pushnote(hinick, "Highlighted in " + to, "<" + nick + "> " + text);
						break;
					case "offline":
						if (!(hinick in bot.chans[to].users)) {
							bot.plugins.pushbullet.pushnote(hinick, "Highlighted in " + to, "<" + nick + "> " + text);
						}
						break;
					case "away":
						if (!(hinick in bot.chans[to].users)) {
							bot.plugins.pushbullet.pushnote(hinick, "Highlighted in " + to, "<" + nick + "> " + text);
						}
						else {
							bot.whois(hinick, function(info) {
								if (info.away !== undefined) {
									bot.plugins.pushbullet.pushnote(hinick, "Highlighted in " + to, "<" + nick + "> " + text);
								}
							});
						}
						break;
					}
				}
			}
		},

		"cmd#sethighlight": function(nick, to, args) {
			if (nick in bot.plugins.pushbullet.emails) {
				switch (args[1]) {
				case "online":
				case "away":
				case "offline":
					if (!(nick in self.highlights))
						self.highlights[nick] = {};
					self.highlights[nick].level = args[1];
					bot.say(nick, "highlights set to " + args[1]);
					break;
				case "off":
					if (nick in self.highlights) {
						delete self.highlights[nick];
						bot.say(nick, "highlights turned off");
					}
					break;
				}
			}
			else
				bot.say(nick, "pushbullet must be set to use this feature");
		}
	}
}

module.exports = HighlightPlugin;
<commit_msg>Fix highlight for channels with uppercase letters in name<commit_after>function HighlightPlugin(bot) {
	var self = this;
	self.name = "highlight";
	self.help = "Highlight plugin";
	self.depend = ["cmd", "pushbullet"];

	self.highlights = {};
	/*
	nick : {
		level: online/away/offline
	}
	*/

	self.load = function(data) {
		if (data)
			self.highlights = data.highlights;

		for (var nick in self.highlights) {
			if (self.highlights[nick].online !== undefined) {
				self.highlights[nick].level = self.highlights[nick].online ? "online" : "offline";
				delete self.highlights[nick].online;
			}
		}
	};

	self.save = function() {
		return {
			"highlights": self.highlights
		};
	}

	self.stripcolors = function(text) {
		return text.replace(/\x1f|\x02|\x12|\x0f|\x16|\x03(?:\d{1,2}(?:,\d{1,2})?)?/g, "");
	}

	self.events = {
		"message": function(nick, to, text) {
			if (nick == to)
				return;

			for (var hinick in self.highlights) {
				var level = self.highlights[hinick].level;
				var tolow = to.toLowerCase();
				if (text.match(new RegExp("\\b" + hinick, "i")) && !(!(level == "online" || level == "away") && (hinick in bot.chans[tolow].users))) {
					text = self.stripcolors(text);
					switch (level) {
					case "online":
						bot.plugins.pushbullet.pushnote(hinick, "Highlighted in " + to, "<" + nick + "> " + text);
						break;
					case "offline":
						if (!(hinick in bot.chans[tolow].users)) {
							bot.plugins.pushbullet.pushnote(hinick, "Highlighted in " + to, "<" + nick + "> " + text);
						}
						break;
					case "away":
						if (!(hinick in bot.chans[tolow].users)) {
							bot.plugins.pushbullet.pushnote(hinick, "Highlighted in " + to, "<" + nick + "> " + text);
						}
						else {
							bot.whois(hinick, function(info) {
								if (info.away !== undefined) {
									bot.plugins.pushbullet.pushnote(hinick, "Highlighted in " + to, "<" + nick + "> " + text);
								}
							});
						}
						break;
					}
				}
			}
		},

		"cmd#sethighlight": function(nick, to, args) {
			if (nick in bot.plugins.pushbullet.emails) {
				switch (args[1]) {
				case "online":
				case "away":
				case "offline":
					if (!(nick in self.highlights))
						self.highlights[nick] = {};
					self.highlights[nick].level = args[1];
					bot.say(nick, "highlights set to " + args[1]);
					break;
				case "off":
					if (nick in self.highlights) {
						delete self.highlights[nick];
						bot.say(nick, "highlights turned off");
					}
					break;
				}
			}
			else
				bot.say(nick, "pushbullet must be set to use this feature");
		}
	}
}

module.exports = HighlightPlugin;
<|endoftext|>