<commit_before>const EventEmitter = require('events').EventEmitter;
const constants = require('./constants');
const stdDbusIfaces = require('./stdifaces');
const introspect = require('./introspect');

module.exports = function bus(conn, opts) {
  if (!(this instanceof bus)) {
    return new bus(conn);
  }
  if (!opts) opts = {};

  var self = this;
  this.connection = conn;
  this.serial = 1;
  this.cookies = {}; // TODO: rename to methodReturnHandlers
  this.methodCallHandlers = {};
  this.signals = new EventEmitter();
  this.exportedObjects = {};

  this.invoke = function(msg, callback) {
    if (!msg.type) msg.type = constants.messageType.methodCall;
    msg.serial = self.serial;
    self.serial++;
    this.cookies[msg.serial] = callback;
    self.connection.message(msg);
  };

  this.invokeDbus = function(msg, callback) {
    if (!msg.path) msg.path = '/org/freedesktop/DBus';
    if (!msg.destination) msg.destination = 'org.freedesktop.DBus';
    if (!msg['interface']) msg['interface'] = 'org.freedesktop.DBus';
    self.invoke(msg, callback);
  };

  this.mangle = function(path, iface, member) {
    var obj = {};
    if (typeof path === 'object') {
      // handle one argumant case mangle(msg)
      obj.path = path.path;
      obj['interface'] = path['interface'];
      obj.member = path.member;
    } else {
      obj.path = path;
      obj['interface'] = iface;
      obj.member = member;
    }
    return JSON.stringify(obj);
  };

  this.sendSignal = function(path, iface, name, signature, args) {
    var signalMsg = {
      type: constants.messageType.signal,
      serial: self.serial,
      interface: iface,
      path: path,
      member: name
    };
    if (signature) {
      signalMsg.signature = signature;
      signalMsg.body = args;
    }
    self.connection.message(signalMsg);
  };

  // Warning: errorName must respect the same rules as interface names (must contain a dot)
  this.sendError = function(msg, errorName, errorText) {
    var reply = {
      type: constants.messageType.error,
      replySerial: msg.serial,
      destination: msg.sender,
      errorName: errorName,
      signature: 's',
      body: [errorText]
    };
    this.connection.message(reply);
  };

  this.sendReply = function(msg, signature, body) {
    var reply = {
      type: constants.messageType.methodReturn,
      replySerial: msg.serial,
      destination: msg.sender,
      signature: signature,
      body: body
    };
    this.connection.message(reply);
  };

  // route reply/error
  this.connection.on('message', function(msg) {
    var handler;
    if (
      msg.type === constants.messageType.methodReturn ||
      msg.type === constants.messageType.error
    ) {
      handler = self.cookies[msg.replySerial];
      if (handler) {
        delete self.cookies[msg.replySerial];
        var props = {
          connection: self.connection,
          bus: self,
          message: msg,
          signature: msg.signature
        };
        var args = msg.body || [];
        if (msg.type === constants.messageType.methodReturn) {
          args = [null].concat(args); // first argument - no errors, null
          handler.apply(props, args); // body as array of arguments
        } else {
          handler.call(props, args); // body as first argument
        }
      }
    } else if (msg.type === constants.messageType.signal) {
      self.signals.emit(self.mangle(msg), msg.body, msg.signature);
    } else {
      // methodCall

      if (stdDbusIfaces(msg, self)) return;

      // exported interfaces handlers
      var obj, iface, impl;
      if ((obj = self.exportedObjects[msg.path])) {
        if ((iface = obj[msg['interface']])) {
          // now we are ready to serve msg.member
          impl = iface[1];
          var func = impl[msg.member];
          if (!func) {
            // TODO: respond with standard dbus error
            console.error(`Method ${msg.member} is not implemented `);
            throw new Error(`Method ${msg.member} is not implemented `);
          }
          var methodReturnResult;
          try {
            methodReturnResult = func.apply(impl, msg.body);
          } catch (e) {
            console.error(
              'Caught exception while trying to execute handler: ',
              e
            );
            throw e;
          }
          // TODO safety check here
          var resultSignature = iface[0].methods[msg.member][1];
          var methodReturnReply = {
            type: constants.messageType.methodReturn,
            destination: msg.sender,
            replySerial: msg.serial
          };
          if (methodReturnResult !== null) {
            methodReturnReply.signature = resultSignature;
            methodReturnReply.body = [methodReturnResult];
          }
          self.connection.message(methodReturnReply);
          return;
        } else {
          console.error(`Interface ${msg['interface']} is not supported`);
          // TODO: respond with standard dbus error
        }
      }
      // setMethodCall handlers
      handler = self.methodCallHandlers[self.mangle(msg)];
      if (handler) {
        var methodCallResult;
        try {
          methodCallResult = handler[0].apply(null, msg.body);
        } catch (e) {
          console.error(
            'Caught exception while trying to execute handler: ',
            e
          );
          self.sendError(e.message, e.description);
          return;
        }
        var methodCallReply = {
          type: constants.messageType.methodReturn,
          destination: msg.sender,
          replySerial: msg.serial
        };
        if (methodCallResult) {
          methodCallReply.signature = handler[1];
          methodCallReply.body = methodCallResult;
        }
        self.connection.message(methodCallReply);
      } else {
        self.sendError(
          msg,
          'org.freedesktop.DBus.Error.UnknownService',
          'Uh oh oh'
        );
      }
    }
  });

  this.setMethodCallHandler = function(objectPath, iface, member, handler) {
    var key = self.mangle(objectPath, iface, member);
    self.methodCallHandlers[key] = handler;
  };

  this.exportInterface = function(obj, path, iface) {
    var entry;
    if (!self.exportedObjects[path]) {
      entry = self.exportedObjects[path] = {};
    } else {
      entry = self.exportedObjects[path];
    }
    entry[iface.name] = [iface, obj];
    // monkey-patch obj.emit()
    if (typeof obj.emit === 'function') {
      var oldEmit = obj.emit;
      obj.emit = function() {
        var args = Array.prototype.slice.apply(arguments);
        var signalName = args[0];
        if (!signalName) throw new Error('Trying to emit undefined signa');

        //send signal to bus
        var signal;
        if (iface.signals && iface.signals[signalName]) {
          signal = iface.signals[signalName];
          var signalMsg = {
            type: constants.messageType.signal,
            serial: self.serial,
            interface: iface.name,
            path: path,
            member: signalName
          };
          if (signal[0]) {
            signalMsg.signature = signal[0];
            signalMsg.body = args.slice(1);
          }
          self.connection.message(signalMsg);
          self.serial++;
        }
        // note that local emit is likely to be called before signal arrives
        // to remote subscriber
        oldEmit.apply(obj, args);
      };
    }
    // TODO: emit ObjectManager's InterfaceAdded
  };

  // register name
  if (opts.direct !== true) {
    this.invokeDbus({ member: 'Hello' }, function(err, name) {
      if (err) throw new Error(err);
      self.name = name;
    });
  } else {
    self.name = null;
  }

  function DBusObject(name, service) {
    this.name = name;
    this.service = service;
    this.as = function(name) {
      return this.proxy[name];
    };
  }

  function DBusService(name, bus) {
    this.name = name;
    this.bus = bus;
    this.getObject = function(name, callback) {
      var obj = new DBusObject(name, this);
      introspect(obj, function(err, ifaces, nodes) {
        if (err) return callback(err);
        obj.proxy = ifaces;
        obj.nodes = nodes;
        callback(null, obj);
      });
    };

    this.getInterface = function(objName, ifaceName, callback) {
      this.getObject(objName, function(err, obj) {
        if (err) return callback(err);
        callback(null, obj.as(ifaceName));
      });
    };
  }

  this.getService = function(name) {
    return new DBusService(name, this);
  };

  this.getObject = function(path, name, callback) {
    var service = this.getService(path);
    return service.getObject(name, callback);
  };

  this.getInterface = function(path, objname, name, callback) {
    return this.getObject(path, objname, function(err, obj) {
      if (err) return callback(err);
      callback(null, obj.as(name));
    });
  };

  // TODO: refactor

  // bus meta functions
  this.addMatch = function(match, callback) {
    this.invokeDbus(
      { member: 'AddMatch', signature: 's', body: [match] },
      callback
    );
  };

  this.removeMatch = function(match, callback) {
    this.invokeDbus(
      { member: 'RemoveMatch', signature: 's', body: [match] },
      callback
    );
  };

  this.getId = function(callback) {
    this.invokeDbus({ member: 'GetId' }, callback);
  };

  this.requestName = function(name, flags, callback) {
    this.invokeDbus(
      { member: 'RequestName', signature: 'su', body: [name, flags] },
      function(err, name) {
        if (callback) callback(err, name);
      }
    );
  };

  this.releaseName = function(name, callback) {
    this.invokeDbus(
      { member: 'ReleaseName', signature: 's', body: [name] },
      callback
    );
  };

  this.listNames = function(callback) {
    this.invokeDbus({ member: 'ListNames' }, callback);
  };

  this.listActivatableNames = function(callback) {
    this.invokeDbus({ member: 'ListActivatableNames' }, callback);
  };

  this.updateActivationEnvironment = function(env, callback) {
    this.invokeDbus(
      {
        member: 'UpdateActivationEnvironment',
        signature: 'a{ss}',
        body: [env]
      },
      callback
    );
  };

  this.startServiceByName = function(name, flags, callback) {
    this.invokeDbus(
      { member: 'StartServiceByName', signature: 'su', body: [name, flags] },
      callback
    );
  };

  this.getConnectionUnixUser = function(name, callback) {
    this.invokeDbus(
      { member: 'GetConnectionUnixUser', signature: 's', body: [name] },
      callback
    );
  };

  this.getConnectionUnixProcessId = function(name, callback) {
    this.invokeDbus(
      { member: 'GetConnectionUnixProcessID', signature: 's', body: [name] },
      callback
    );
  };

  this.getNameOwner = function(name, callback) {
    this.invokeDbus(
      { member: 'GetNameOwner', signature: 's', body: [name] },
      callback
    );
  };

  this.nameHasOwner = function(name, callback) {
    this.invokeDbus(
      { member: 'NameHasOwner', signature: 's', body: [name] },
      callback
    );
  };
};
<commit_msg>Reply with standard DBus error on unknown method<commit_after>const EventEmitter = require('events').EventEmitter;
const constants = require('./constants');
const stdDbusIfaces = require('./stdifaces');
const introspect = require('./introspect');

module.exports = function bus(conn, opts) {
  if (!(this instanceof bus)) {
    return new bus(conn);
  }
  if (!opts) opts = {};

  var self = this;
  this.connection = conn;
  this.serial = 1;
  this.cookies = {}; // TODO: rename to methodReturnHandlers
  this.methodCallHandlers = {};
  this.signals = new EventEmitter();
  this.exportedObjects = {};

  this.invoke = function(msg, callback) {
    if (!msg.type) msg.type = constants.messageType.methodCall;
    msg.serial = self.serial;
    self.serial++;
    this.cookies[msg.serial] = callback;
    self.connection.message(msg);
  };

  this.invokeDbus = function(msg, callback) {
    if (!msg.path) msg.path = '/org/freedesktop/DBus';
    if (!msg.destination) msg.destination = 'org.freedesktop.DBus';
    if (!msg['interface']) msg['interface'] = 'org.freedesktop.DBus';
    self.invoke(msg, callback);
  };

  this.mangle = function(path, iface, member) {
    var obj = {};
    if (typeof path === 'object') {
      // handle one argumant case mangle(msg)
      obj.path = path.path;
      obj['interface'] = path['interface'];
      obj.member = path.member;
    } else {
      obj.path = path;
      obj['interface'] = iface;
      obj.member = member;
    }
    return JSON.stringify(obj);
  };

  this.sendSignal = function(path, iface, name, signature, args) {
    var signalMsg = {
      type: constants.messageType.signal,
      serial: self.serial,
      interface: iface,
      path: path,
      member: name
    };
    if (signature) {
      signalMsg.signature = signature;
      signalMsg.body = args;
    }
    self.connection.message(signalMsg);
  };

  // Warning: errorName must respect the same rules as interface names (must contain a dot)
  this.sendError = function(msg, errorName, errorText) {
    var reply = {
      type: constants.messageType.error,
      replySerial: msg.serial,
      destination: msg.sender,
      errorName: errorName,
      signature: 's',
      body: [errorText]
    };
    this.connection.message(reply);
  };

  this.sendReply = function(msg, signature, body) {
    var reply = {
      type: constants.messageType.methodReturn,
      replySerial: msg.serial,
      destination: msg.sender,
      signature: signature,
      body: body
    };
    this.connection.message(reply);
  };

  // route reply/error
  this.connection.on('message', function(msg) {
    var handler;
    if (
      msg.type === constants.messageType.methodReturn ||
      msg.type === constants.messageType.error
    ) {
      handler = self.cookies[msg.replySerial];
      if (handler) {
        delete self.cookies[msg.replySerial];
        var props = {
          connection: self.connection,
          bus: self,
          message: msg,
          signature: msg.signature
        };
        var args = msg.body || [];
        if (msg.type === constants.messageType.methodReturn) {
          args = [null].concat(args); // first argument - no errors, null
          handler.apply(props, args); // body as array of arguments
        } else {
          handler.call(props, args); // body as first argument
        }
      }
    } else if (msg.type === constants.messageType.signal) {
      self.signals.emit(self.mangle(msg), msg.body, msg.signature);
    } else {
      // methodCall

      if (stdDbusIfaces(msg, self)) return;

      // exported interfaces handlers
      var obj, iface, impl;
      if ((obj = self.exportedObjects[msg.path])) {
        if ((iface = obj[msg['interface']])) {
          // now we are ready to serve msg.member
          impl = iface[1];
          var func = impl[msg.member];
          if (!func) {
            self.sendError(
              msg,
              'org.freedesktop.DBus.Error.UnknownMethod',
              `Method "${msg.member}" on interface "${msg.interface}" doesn't exist`
            );
            return;
          }
          var methodReturnResult;
          try {
            methodReturnResult = func.apply(impl, msg.body);
          } catch (e) {
            console.error(
              'Caught exception while trying to execute handler: ',
              e
            );
            throw e;
          }
          // TODO safety check here
          var resultSignature = iface[0].methods[msg.member][1];
          var methodReturnReply = {
            type: constants.messageType.methodReturn,
            destination: msg.sender,
            replySerial: msg.serial
          };
          if (methodReturnResult !== null) {
            methodReturnReply.signature = resultSignature;
            methodReturnReply.body = [methodReturnResult];
          }
          self.connection.message(methodReturnReply);
          return;
        } else {
          console.error(`Interface ${msg['interface']} is not supported`);
          // TODO: respond with standard dbus error
        }
      }
      // setMethodCall handlers
      handler = self.methodCallHandlers[self.mangle(msg)];
      if (handler) {
        var methodCallResult;
        try {
          methodCallResult = handler[0].apply(null, msg.body);
        } catch (e) {
          console.error(
            'Caught exception while trying to execute handler: ',
            e
          );
          self.sendError(e.message, e.description);
          return;
        }
        var methodCallReply = {
          type: constants.messageType.methodReturn,
          destination: msg.sender,
          replySerial: msg.serial
        };
        if (methodCallResult) {
          methodCallReply.signature = handler[1];
          methodCallReply.body = methodCallResult;
        }
        self.connection.message(methodCallReply);
      } else {
        self.sendError(
          msg,
          'org.freedesktop.DBus.Error.UnknownService',
          'Uh oh oh'
        );
      }
    }
  });

  this.setMethodCallHandler = function(objectPath, iface, member, handler) {
    var key = self.mangle(objectPath, iface, member);
    self.methodCallHandlers[key] = handler;
  };

  this.exportInterface = function(obj, path, iface) {
    var entry;
    if (!self.exportedObjects[path]) {
      entry = self.exportedObjects[path] = {};
    } else {
      entry = self.exportedObjects[path];
    }
    entry[iface.name] = [iface, obj];
    // monkey-patch obj.emit()
    if (typeof obj.emit === 'function') {
      var oldEmit = obj.emit;
      obj.emit = function() {
        var args = Array.prototype.slice.apply(arguments);
        var signalName = args[0];
        if (!signalName) throw new Error('Trying to emit undefined signa');

        //send signal to bus
        var signal;
        if (iface.signals && iface.signals[signalName]) {
          signal = iface.signals[signalName];
          var signalMsg = {
            type: constants.messageType.signal,
            serial: self.serial,
            interface: iface.name,
            path: path,
            member: signalName
          };
          if (signal[0]) {
            signalMsg.signature = signal[0];
            signalMsg.body = args.slice(1);
          }
          self.connection.message(signalMsg);
          self.serial++;
        }
        // note that local emit is likely to be called before signal arrives
        // to remote subscriber
        oldEmit.apply(obj, args);
      };
    }
    // TODO: emit ObjectManager's InterfaceAdded
  };

  // register name
  if (opts.direct !== true) {
    this.invokeDbus({ member: 'Hello' }, function(err, name) {
      if (err) throw new Error(err);
      self.name = name;
    });
  } else {
    self.name = null;
  }

  function DBusObject(name, service) {
    this.name = name;
    this.service = service;
    this.as = function(name) {
      return this.proxy[name];
    };
  }

  function DBusService(name, bus) {
    this.name = name;
    this.bus = bus;
    this.getObject = function(name, callback) {
      var obj = new DBusObject(name, this);
      introspect(obj, function(err, ifaces, nodes) {
        if (err) return callback(err);
        obj.proxy = ifaces;
        obj.nodes = nodes;
        callback(null, obj);
      });
    };

    this.getInterface = function(objName, ifaceName, callback) {
      this.getObject(objName, function(err, obj) {
        if (err) return callback(err);
        callback(null, obj.as(ifaceName));
      });
    };
  }

  this.getService = function(name) {
    return new DBusService(name, this);
  };

  this.getObject = function(path, name, callback) {
    var service = this.getService(path);
    return service.getObject(name, callback);
  };

  this.getInterface = function(path, objname, name, callback) {
    return this.getObject(path, objname, function(err, obj) {
      if (err) return callback(err);
      callback(null, obj.as(name));
    });
  };

  // TODO: refactor

  // bus meta functions
  this.addMatch = function(match, callback) {
    this.invokeDbus(
      { member: 'AddMatch', signature: 's', body: [match] },
      callback
    );
  };

  this.removeMatch = function(match, callback) {
    this.invokeDbus(
      { member: 'RemoveMatch', signature: 's', body: [match] },
      callback
    );
  };

  this.getId = function(callback) {
    this.invokeDbus({ member: 'GetId' }, callback);
  };

  this.requestName = function(name, flags, callback) {
    this.invokeDbus(
      { member: 'RequestName', signature: 'su', body: [name, flags] },
      function(err, name) {
        if (callback) callback(err, name);
      }
    );
  };

  this.releaseName = function(name, callback) {
    this.invokeDbus(
      { member: 'ReleaseName', signature: 's', body: [name] },
      callback
    );
  };

  this.listNames = function(callback) {
    this.invokeDbus({ member: 'ListNames' }, callback);
  };

  this.listActivatableNames = function(callback) {
    this.invokeDbus({ member: 'ListActivatableNames' }, callback);
  };

  this.updateActivationEnvironment = function(env, callback) {
    this.invokeDbus(
      {
        member: 'UpdateActivationEnvironment',
        signature: 'a{ss}',
        body: [env]
      },
      callback
    );
  };

  this.startServiceByName = function(name, flags, callback) {
    this.invokeDbus(
      { member: 'StartServiceByName', signature: 'su', body: [name, flags] },
      callback
    );
  };

  this.getConnectionUnixUser = function(name, callback) {
    this.invokeDbus(
      { member: 'GetConnectionUnixUser', signature: 's', body: [name] },
      callback
    );
  };

  this.getConnectionUnixProcessId = function(name, callback) {
    this.invokeDbus(
      { member: 'GetConnectionUnixProcessID', signature: 's', body: [name] },
      callback
    );
  };

  this.getNameOwner = function(name, callback) {
    this.invokeDbus(
      { member: 'GetNameOwner', signature: 's', body: [name] },
      callback
    );
  };

  this.nameHasOwner = function(name, callback) {
    this.invokeDbus(
      { member: 'NameHasOwner', signature: 's', body: [name] },
      callback
    );
  };
};
<|endoftext|>


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

'use strict'

const path = require('path')
const flags = require('commander')

const markserv = require(path.join(__dirname, 'server'))
const pkg = require(path.join('..', 'package.json'))

const cwd = process.cwd()

flags.dir = cwd

flags.version(pkg.version)
	.usage('<file/dir>')
	.option('-p, --port [type]', 'HTTP port [port]', 8642)
	.option('-l, --livereloadport [type]', 'LiveReload port [livereloadport]', 35729)
	.option('-i, --silent [type]', 'Silent (no logs to CLI)', false)
	.option('-a, --address [type]', 'Serve on ip/address [address]', 'localhost')
	.option('-v, --verbose', 'verbose output')
	.action(serverPath => {
		flags.$pathProvided = true
		flags.dir = path.normalize(path.join(cwd, serverPath))
	}).parse(process.argv)

markserv.init(flags)
<commit_msg>Allow serving from root paths<commit_after>#!/usr/bin/env node

'use strict'

const path = require('path')
const flags = require('commander')

const markserv = require(path.join(__dirname, 'server'))
const pkg = require(path.join('..', 'package.json'))

const cwd = process.cwd()

flags.dir = cwd

flags.version(pkg.version)
	.usage('<file/dir>')
	.option('-p, --port [type]', 'HTTP port [port]', 8642)
	.option('-l, --livereloadport [type]', 'LiveReload port [livereloadport]', 35729)
	.option('-i, --silent [type]', 'Silent (no logs to CLI)', false)
	.option('-a, --address [type]', 'Serve on ip/address [address]', 'localhost')
	.option('-v, --verbose', 'verbose output')
	.action(serverPath => {
		flags.$pathProvided = true
		if (flags.dir[0] !== '/') {
			flags.dir = path.normalize(path.join(cwd, serverPath))
		}
	}).parse(process.argv)

markserv.init(flags)
<|endoftext|>


<commit_before>'use strict';
const path = require('path');
const fs = require('fs');
const del = require('del');
const updateNotifier = require('update-notifier');
const figures = require('figures');
const arrify = require('arrify');
const meow = require('meow');
const Promise = require('bluebird');
const isCi = require('is-ci');
const loadConfig = require('./load-config');

// Bluebird specific
Promise.longStackTraces();

function exit(message) {
	console.error(`\n  ${require('./chalk').get().red(figures.cross)} ${message}`);
	process.exit(1); // eslint-disable-line unicorn/no-process-exit
}

exports.run = async () => { // eslint-disable-line complexity
	const {flags: {config: configFile}} = meow({ // Process the --config flag first
		autoHelp: false, // --help should get picked up by the next meow invocation.
		flags: {
			config: {type: 'string'}
		}
	});

	let conf = {};
	let confError = null;
	try {
		conf = loadConfig({configFile});
	} catch (error) {
		confError = error;
	}

	const cli = meow(`
		Usage
		  ava [<file> ...]

		Options
		  --watch, -w             Re-run tests when tests and source files change
		  --match, -m             Only run tests with matching title (Can be repeated)
		  --update-snapshots, -u  Update snapshots
		  --fail-fast             Stop after first test failure
		  --timeout, -T           Set global timeout (milliseconds or human-readable, e.g. 10s, 2m)
		  --serial, -s            Run tests serially
		  --concurrency, -c       Max number of test files running at the same time (Default: CPU cores)
		  --verbose, -v           Enable verbose output
		  --tap, -t               Generate TAP output
		  --color                 Force color output
		  --no-color              Disable color output
		  --reset-cache           Reset AVA's compilation cache and exit
		  --config                JavaScript file for AVA to read its config from, instead of using package.json
		                          or ava.config.js files

		Examples
		  ava
		  ava test.js test2.js
		  ava test-*.js
		  ava test

		The above relies on your shell expanding the glob patterns.
		Without arguments, AVA uses the following patterns:
		  **/test.js **/test-*.js **/*.spec.js **/*.test.js **/test/**/*.js **/tests/**/*.js **/__tests__/**/*.js
	`, {
		flags: {
			watch: {
				type: 'boolean',
				alias: 'w'
			},
			match: {
				type: 'string',
				alias: 'm',
				...'match' in conf && {default: conf.match}
			},
			'update-snapshots': {
				type: 'boolean',
				alias: 'u'
			},
			'fail-fast': {
				type: 'boolean',
				...'failFast' in conf && {default: conf.failFast}
			},
			timeout: {
				type: 'string',
				alias: 'T',
				...'timeout' in conf && {default: conf.timeout}
			},
			serial: {
				type: 'boolean',
				alias: 's',
				...'serial' in conf && {default: conf.serial}
			},
			concurrency: {
				type: 'string',
				alias: 'c',
				...'concurrency' in conf && {default: conf.concurrency}
			},
			verbose: {
				type: 'boolean',
				alias: 'v',
				...'verbose' in conf && {default: conf.verbose}
			},
			tap: {
				type: 'boolean',
				alias: 't',
				...'tap' in conf && {default: conf.tap}
			},
			color: {
				type: 'boolean',
				...'color' in conf && {default: conf.color}
			},
			'reset-cache': {
				type: 'boolean',
				default: false
			},
			'--': {
				type: 'string'
			}
		}
	});

	updateNotifier({pkg: cli.pkg}).notify();
	const chalk = require('./chalk').set({level: cli.flags.color ? 1 : 0});

	if (confError) {
		if (confError.parent) {
			exit(`${confError.message}\n\n${chalk.gray((confError.parent && confError.parent.stack) || confError.parent)}`);
		} else {
			exit(confError.message);
		}
	}

	const {nonSemVerExperiments: experiments, projectDir} = conf;
	if (cli.flags.resetCache) {
		const cacheDir = path.join(projectDir, 'node_modules', '.cache', 'ava');
		try {
			await del('*', {
				cwd: cacheDir,
				nodir: true
			});
			console.error(`\n${chalk.green(figures.tick)} Removed AVA cache files in ${cacheDir}`);
			process.exit(0); // eslint-disable-line unicorn/no-process-exit
		} catch (error) {
			exit(`Error removing AVA cache files in ${cacheDir}\n\n${chalk.gray((error && error.stack) || error)}`);
		}

		return;
	}

	if (cli.flags.watch && cli.flags.tap && !conf.tap) {
		exit('The TAP reporter is not available when using watch mode.');
	}

	if (cli.flags.watch && isCi) {
		exit('Watch mode is not available in CI, as it prevents AVA from terminating.');
	}

	if (
		cli.flags.concurrency === '' ||
		(cli.flags.concurrency && (!Number.isInteger(Number.parseFloat(cli.flags.concurrency)) || parseInt(cli.flags.concurrency, 10) < 0))
	) {
		exit('The --concurrency or -c flag must be provided with a nonnegative integer.');
	}

	if (!conf.tap && Object.keys(experiments).length > 0) {
		console.log(chalk.magenta(`  ${figures.warning} Experiments are enabled. These are unsupported and may change or be removed at any time.`));
	}

	if (experiments.noBabelOutOfTheBox && typeof conf.compileEnhancements === 'boolean') {
		exit('Enhancement compilation must be configured in AVA’s Babel options');
	}

	const ciParallelVars = require('ci-parallel-vars');
	const Api = require('./api');
	const VerboseReporter = require('./reporters/verbose');
	const MiniReporter = require('./reporters/mini');
	const TapReporter = require('./reporters/tap');
	const Watcher = require('./watcher');
	const babelManager = require('./babel-manager');
	const normalizeExtensions = require('./extensions');
	const {normalizeGlobs} = require('./globs');
	const validateEnvironmentVariables = require('./environment-variables');

	let babelProvider;
	if (!experiments.noBabelOutOfTheBox || conf.babel !== undefined) {
		try {
			babelProvider = babelManager({experiments, projectDir});
			babelProvider.validateConfig(conf.babel, conf.compileEnhancements !== false);
		} catch (error) {
			exit(error.message);
		}
	}

	let environmentVariables;
	try {
		environmentVariables = validateEnvironmentVariables(conf.environmentVariables);
	} catch (error) {
		exit(error.message);
	}

	let extensions;
	try {
		extensions = normalizeExtensions(conf.extensions, babelProvider, {experiments});
	} catch (error) {
		exit(error.message);
	}

	let globs;
	try {
		globs = normalizeGlobs(conf.files, conf.helpers, conf.sources, extensions.all);
	} catch (error) {
		exit(error.message);
	}

	// Copy resultant cli.flags into conf for use with Api and elsewhere
	Object.assign(conf, cli.flags);

	let parallelRuns = null;
	if (isCi && ciParallelVars) {
		const {index: currentIndex, total: totalRuns} = ciParallelVars;
		parallelRuns = {currentIndex, totalRuns};
	}

	const match = conf.match === '' ? [] : arrify(conf.match);
	const resolveTestsFrom = cli.input.length === 0 ? projectDir : process.cwd();

	const files = cli.input.map(file => path.relative(resolveTestsFrom, path.resolve(process.cwd(), file)));

	for (const file of cli.input) {
		try {
			const stats = fs.statSync(file);
			if (!stats.isFile()) {
				exit(`${file} is not a test file.`);
			}
		} catch (error) {
			if (error.code === 'ENOENT') {
				exit(`${file} does not exist.`);
			} else {
				exit(`Error accessing ${file}\n\n${chalk.gray((error && error.stack) || error)}`);
			}
		}
	}

	const api = new Api({
		babelProvider,
		cacheEnabled: conf.cache !== false,
		color: conf.color,
		compileEnhancements: conf.compileEnhancements !== false,
		concurrency: conf.concurrency ? parseInt(conf.concurrency, 10) : 0,
		experiments,
		extensions,
		failFast: conf.failFast,
		failWithoutAssertions: conf.failWithoutAssertions !== false,
		globs,
		environmentVariables,
		match,
		parallelRuns,
		projectDir,
		ranFromCli: true,
		require: arrify(conf.require),
		resolveTestsFrom,
		serial: conf.serial,
		snapshotDir: conf.snapshotDir ? path.resolve(projectDir, conf.snapshotDir) : null,
		timeout: conf.timeout,
		updateSnapshots: conf.updateSnapshots,
		workerArgv: cli.flags['--']
	});

	let reporter;
	if (conf.tap && !conf.watch) {
		reporter = new TapReporter({
			reportStream: process.stdout,
			stdStream: process.stderr
		});
	} else if (conf.verbose || isCi || !process.stdout.isTTY) {
		reporter = new VerboseReporter({
			reportStream: process.stdout,
			stdStream: process.stderr,
			watching: conf.watch
		});
	} else {
		reporter = new MiniReporter({
			reportStream: process.stdout,
			stdStream: process.stderr,
			watching: conf.watch
		});
	}

	api.on('run', plan => {
		reporter.startRun(plan);

		plan.status.on('stateChange', evt => {
			if (evt.type === 'interrupt') {
				reporter.endRun();
				process.exit(1); // eslint-disable-line unicorn/no-process-exit
			}
		});
	});

	if (conf.watch) {
		const watcher = new Watcher({
			api,
			reporter,
			files,
			globs,
			resolveTestsFrom
		});
		watcher.observeStdin(process.stdin);
	} else {
		const runStatus = await api.run(files);
		process.exitCode = runStatus.suggestExitCode({matching: match.length > 0});
		reporter.endRun();
	}
};
<commit_msg>When checking for file existence, use normalized files<commit_after>'use strict';
const path = require('path');
const fs = require('fs');
const del = require('del');
const updateNotifier = require('update-notifier');
const figures = require('figures');
const arrify = require('arrify');
const meow = require('meow');
const Promise = require('bluebird');
const isCi = require('is-ci');
const loadConfig = require('./load-config');

// Bluebird specific
Promise.longStackTraces();

function exit(message) {
	console.error(`\n  ${require('./chalk').get().red(figures.cross)} ${message}`);
	process.exit(1); // eslint-disable-line unicorn/no-process-exit
}

exports.run = async () => { // eslint-disable-line complexity
	const {flags: {config: configFile}} = meow({ // Process the --config flag first
		autoHelp: false, // --help should get picked up by the next meow invocation.
		flags: {
			config: {type: 'string'}
		}
	});

	let conf = {};
	let confError = null;
	try {
		conf = loadConfig({configFile});
	} catch (error) {
		confError = error;
	}

	const cli = meow(`
		Usage
		  ava [<file> ...]

		Options
		  --watch, -w             Re-run tests when tests and source files change
		  --match, -m             Only run tests with matching title (Can be repeated)
		  --update-snapshots, -u  Update snapshots
		  --fail-fast             Stop after first test failure
		  --timeout, -T           Set global timeout (milliseconds or human-readable, e.g. 10s, 2m)
		  --serial, -s            Run tests serially
		  --concurrency, -c       Max number of test files running at the same time (Default: CPU cores)
		  --verbose, -v           Enable verbose output
		  --tap, -t               Generate TAP output
		  --color                 Force color output
		  --no-color              Disable color output
		  --reset-cache           Reset AVA's compilation cache and exit
		  --config                JavaScript file for AVA to read its config from, instead of using package.json
		                          or ava.config.js files

		Examples
		  ava
		  ava test.js test2.js
		  ava test-*.js
		  ava test

		The above relies on your shell expanding the glob patterns.
		Without arguments, AVA uses the following patterns:
		  **/test.js **/test-*.js **/*.spec.js **/*.test.js **/test/**/*.js **/tests/**/*.js **/__tests__/**/*.js
	`, {
		flags: {
			watch: {
				type: 'boolean',
				alias: 'w'
			},
			match: {
				type: 'string',
				alias: 'm',
				...'match' in conf && {default: conf.match}
			},
			'update-snapshots': {
				type: 'boolean',
				alias: 'u'
			},
			'fail-fast': {
				type: 'boolean',
				...'failFast' in conf && {default: conf.failFast}
			},
			timeout: {
				type: 'string',
				alias: 'T',
				...'timeout' in conf && {default: conf.timeout}
			},
			serial: {
				type: 'boolean',
				alias: 's',
				...'serial' in conf && {default: conf.serial}
			},
			concurrency: {
				type: 'string',
				alias: 'c',
				...'concurrency' in conf && {default: conf.concurrency}
			},
			verbose: {
				type: 'boolean',
				alias: 'v',
				...'verbose' in conf && {default: conf.verbose}
			},
			tap: {
				type: 'boolean',
				alias: 't',
				...'tap' in conf && {default: conf.tap}
			},
			color: {
				type: 'boolean',
				...'color' in conf && {default: conf.color}
			},
			'reset-cache': {
				type: 'boolean',
				default: false
			},
			'--': {
				type: 'string'
			}
		}
	});

	updateNotifier({pkg: cli.pkg}).notify();
	const chalk = require('./chalk').set({level: cli.flags.color ? 1 : 0});

	if (confError) {
		if (confError.parent) {
			exit(`${confError.message}\n\n${chalk.gray((confError.parent && confError.parent.stack) || confError.parent)}`);
		} else {
			exit(confError.message);
		}
	}

	const {nonSemVerExperiments: experiments, projectDir} = conf;
	if (cli.flags.resetCache) {
		const cacheDir = path.join(projectDir, 'node_modules', '.cache', 'ava');
		try {
			await del('*', {
				cwd: cacheDir,
				nodir: true
			});
			console.error(`\n${chalk.green(figures.tick)} Removed AVA cache files in ${cacheDir}`);
			process.exit(0); // eslint-disable-line unicorn/no-process-exit
		} catch (error) {
			exit(`Error removing AVA cache files in ${cacheDir}\n\n${chalk.gray((error && error.stack) || error)}`);
		}

		return;
	}

	if (cli.flags.watch && cli.flags.tap && !conf.tap) {
		exit('The TAP reporter is not available when using watch mode.');
	}

	if (cli.flags.watch && isCi) {
		exit('Watch mode is not available in CI, as it prevents AVA from terminating.');
	}

	if (
		cli.flags.concurrency === '' ||
		(cli.flags.concurrency && (!Number.isInteger(Number.parseFloat(cli.flags.concurrency)) || parseInt(cli.flags.concurrency, 10) < 0))
	) {
		exit('The --concurrency or -c flag must be provided with a nonnegative integer.');
	}

	if (!conf.tap && Object.keys(experiments).length > 0) {
		console.log(chalk.magenta(`  ${figures.warning} Experiments are enabled. These are unsupported and may change or be removed at any time.`));
	}

	if (experiments.noBabelOutOfTheBox && typeof conf.compileEnhancements === 'boolean') {
		exit('Enhancement compilation must be configured in AVA’s Babel options');
	}

	const ciParallelVars = require('ci-parallel-vars');
	const Api = require('./api');
	const VerboseReporter = require('./reporters/verbose');
	const MiniReporter = require('./reporters/mini');
	const TapReporter = require('./reporters/tap');
	const Watcher = require('./watcher');
	const babelManager = require('./babel-manager');
	const normalizeExtensions = require('./extensions');
	const {normalizeGlobs} = require('./globs');
	const validateEnvironmentVariables = require('./environment-variables');

	let babelProvider;
	if (!experiments.noBabelOutOfTheBox || conf.babel !== undefined) {
		try {
			babelProvider = babelManager({experiments, projectDir});
			babelProvider.validateConfig(conf.babel, conf.compileEnhancements !== false);
		} catch (error) {
			exit(error.message);
		}
	}

	let environmentVariables;
	try {
		environmentVariables = validateEnvironmentVariables(conf.environmentVariables);
	} catch (error) {
		exit(error.message);
	}

	let extensions;
	try {
		extensions = normalizeExtensions(conf.extensions, babelProvider, {experiments});
	} catch (error) {
		exit(error.message);
	}

	let globs;
	try {
		globs = normalizeGlobs(conf.files, conf.helpers, conf.sources, extensions.all);
	} catch (error) {
		exit(error.message);
	}

	// Copy resultant cli.flags into conf for use with Api and elsewhere
	Object.assign(conf, cli.flags);

	let parallelRuns = null;
	if (isCi && ciParallelVars) {
		const {index: currentIndex, total: totalRuns} = ciParallelVars;
		parallelRuns = {currentIndex, totalRuns};
	}

	const match = conf.match === '' ? [] : arrify(conf.match);
	const resolveTestsFrom = cli.input.length === 0 ? projectDir : process.cwd();

	const files = cli.input.map(file => path.relative(resolveTestsFrom, path.resolve(process.cwd(), file)));

	for (const file of files) {
		try {
			const stats = fs.statSync(file);
			if (!stats.isFile()) {
				exit(`${file} is not a test file.`);
			}
		} catch (error) {
			if (error.code === 'ENOENT') {
				exit(`${file} does not exist.`);
			} else {
				exit(`Error accessing ${file}\n\n${chalk.gray((error && error.stack) || error)}`);
			}
		}
	}

	const api = new Api({
		babelProvider,
		cacheEnabled: conf.cache !== false,
		color: conf.color,
		compileEnhancements: conf.compileEnhancements !== false,
		concurrency: conf.concurrency ? parseInt(conf.concurrency, 10) : 0,
		experiments,
		extensions,
		failFast: conf.failFast,
		failWithoutAssertions: conf.failWithoutAssertions !== false,
		globs,
		environmentVariables,
		match,
		parallelRuns,
		projectDir,
		ranFromCli: true,
		require: arrify(conf.require),
		resolveTestsFrom,
		serial: conf.serial,
		snapshotDir: conf.snapshotDir ? path.resolve(projectDir, conf.snapshotDir) : null,
		timeout: conf.timeout,
		updateSnapshots: conf.updateSnapshots,
		workerArgv: cli.flags['--']
	});

	let reporter;
	if (conf.tap && !conf.watch) {
		reporter = new TapReporter({
			reportStream: process.stdout,
			stdStream: process.stderr
		});
	} else if (conf.verbose || isCi || !process.stdout.isTTY) {
		reporter = new VerboseReporter({
			reportStream: process.stdout,
			stdStream: process.stderr,
			watching: conf.watch
		});
	} else {
		reporter = new MiniReporter({
			reportStream: process.stdout,
			stdStream: process.stderr,
			watching: conf.watch
		});
	}

	api.on('run', plan => {
		reporter.startRun(plan);

		plan.status.on('stateChange', evt => {
			if (evt.type === 'interrupt') {
				reporter.endRun();
				process.exit(1); // eslint-disable-line unicorn/no-process-exit
			}
		});
	});

	if (conf.watch) {
		const watcher = new Watcher({
			api,
			reporter,
			files,
			globs,
			resolveTestsFrom
		});
		watcher.observeStdin(process.stdin);
	} else {
		const runStatus = await api.run(files);
		process.exitCode = runStatus.suggestExitCode({matching: match.length > 0});
		reporter.endRun();
	}
};
<|endoftext|>


<commit_before>/**
 * Game.js description here
 *
 * @author fridek
 * @date 16.04.11
 * @version $
 */

var Game = Class.extend({
    world: null,

    currentMap: null,
    fixDef: null,
    bodyDef: null,

    init: function () {
         var    b2Vec2 = Box2D.Common.Math.b2Vec2,
                b2AABB = Box2D.Collision.b2AABB,
                b2BodyDef = Box2D.Dynamics.b2BodyDef,
                b2Body = Box2D.Dynamics.b2Body,
                b2FixtureDef = Box2D.Dynamics.b2FixtureDef,
                b2Fixture = Box2D.Dynamics.b2Fixture,
                b2World = Box2D.Dynamics.b2World,
                b2MassData = Box2D.Collision.Shapes.b2MassData,
                b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
                b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
                b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
                b2MouseJointDef =  Box2D.Dynamics.Joints.b2MouseJointDef;

         this.world = new b2World(
            new b2Vec2(0, 10),    //gravity
            true                 //allow sleep
         );

         this.fixDef = new b2FixtureDef;
         this.fixDef.density = 1.0;
         this.fixDef.friction = 0.5;
         this.fixDef.restitution = 0.2;

         this.bodyDef = new b2BodyDef;

         //create ground
         this.bodyDef.type = b2Body.b2_staticBody;
         this.fixDef.shape = new b2PolygonShape;
         this.fixDef.shape.SetAsBox(20, 2);
         this.bodyDef.position.Set(10, 400 / 30 + 1.8);
         this.world.CreateBody(this.bodyDef).CreateFixture(this.fixDef);
         this.bodyDef.position.Set(10, -1.8);
         this.world.CreateBody(this.bodyDef).CreateFixture(this.fixDef);
         this.fixDef.shape.SetAsBox(2, 14);
         this.bodyDef.position.Set(-1.8, 13);
         this.world.CreateBody(this.bodyDef).CreateFixture(this.fixDef);
         this.bodyDef.position.Set(21.8, 13);
         this.world.CreateBody(this.bodyDef).CreateFixture(this.fixDef);

         this.maps = new Maps(this);
         this.maps.makeMap('testmap');

         //setup debug draw
         var debugDraw = new b2DebugDraw();
			debugDraw.SetSprite(document.getElementById("canvas").getContext("2d"));
			debugDraw.SetDrawScale(30.0);
			debugDraw.SetFillAlpha(0.5);
			debugDraw.SetLineThickness(1.0);
			debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
			this.world.SetDebugDraw(debugDraw);

         var that = this;
         window.setInterval(function() {that.step.apply(that);}, 1000 / 30);
    },

    step: function () {
        this.world.Step(1 / 30, 10, 10);
        this.world.DrawDebugData();
        this.world.ClearForces();
    }
});<commit_msg>fixy do fixów<commit_after>/**
 * Game.js description here
 *
 * @author fridek
 * @date 16.04.11
 * @version $
 */

var Game = Class.extend({
    world: null,

    currentMap: null,
    fixDef: null,
    bodyDef: null,
    canvas: null,

    width: null,
    height: null,

    init: function (canvas) {
        this.canvas = document.getElementById("canvas");
        this.height = this.canvas.offsetHeight;
        this.width = this.canvas.offsetWidth;

         var    b2Vec2 = Box2D.Common.Math.b2Vec2,
                b2AABB = Box2D.Collision.b2AABB,
                b2BodyDef = Box2D.Dynamics.b2BodyDef,
                b2Body = Box2D.Dynamics.b2Body,
                b2FixtureDef = Box2D.Dynamics.b2FixtureDef,
                b2Fixture = Box2D.Dynamics.b2Fixture,
                b2World = Box2D.Dynamics.b2World,
                b2MassData = Box2D.Collision.Shapes.b2MassData,
                b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape,
                b2CircleShape = Box2D.Collision.Shapes.b2CircleShape,
                b2DebugDraw = Box2D.Dynamics.b2DebugDraw,
                b2MouseJointDef =  Box2D.Dynamics.Joints.b2MouseJointDef;

         this.world = new b2World(
            new b2Vec2(0, 10),    //gravity
            true                 //allow sleep
         );

         this.fixDef = new b2FixtureDef;
         this.fixDef.density = 1.0;
         this.fixDef.friction = 0.5;
         this.fixDef.restitution = 0.2;

         this.bodyDef = new b2BodyDef;

         //create ground
         this.bodyDef.type = b2Body.b2_staticBody;
         this.fixDef.shape = new b2PolygonShape;
         this.fixDef.shape.SetAsBox(this.width / 30, 2);
         // bottom
         this.bodyDef.position.Set(10, this.height / 30 + 1.8);
         this.world.CreateBody(this.bodyDef).CreateFixture(this.fixDef);
         // top
         this.bodyDef.position.Set(10, -1.8);
         this.world.CreateBody(this.bodyDef).CreateFixture(this.fixDef);

         this.fixDef.shape.SetAsBox(2, this.height / 30);
         // left
         this.bodyDef.position.Set(-1.8, 13);
         this.world.CreateBody(this.bodyDef).CreateFixture(this.fixDef);
         // right
         this.bodyDef.position.Set(this.width / 30 + 1.8, 13);
         this.world.CreateBody(this.bodyDef).CreateFixture(this.fixDef);

         this.maps = new Maps(this);
         this.maps.makeMap('testmap');

         //setup debug draw
         var debugDraw = new b2DebugDraw();
			debugDraw.SetSprite(this.canvas.getContext("2d"));
			debugDraw.SetDrawScale(30.0);
			debugDraw.SetFillAlpha(0.5);
			debugDraw.SetLineThickness(1.0);
			debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
			this.world.SetDebugDraw(debugDraw);

         var that = this;
         window.setInterval(function() {that.step.apply(that);}, 1000 / 30);
    },

    step: function () {
        this.world.Step(1 / 30, 10, 10);
        this.world.DrawDebugData();
        this.world.ClearForces();
    }
});<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';
var fs = require('fs');
var path = require('path');
var chalk = require('chalk');
var updateNotifier = require('update-notifier');
var Insight = require('insight');
var yosay = require('yosay');
var stringLength = require('string-length');
var rootCheck = require('root-check');
var meow = require('meow');
var pkg = require('../package.json');
var Router = require('./router');
var utils = require('./utils');

var cli = meow({
  help: false,
  pkg: pkg
});

var opts = cli.flags;
var args = cli.input;
var cmd = args[0];

// add un-camelized options too, for legacy
// TODO: remove some time in the future when generators have upgraded
Object.keys(opts).forEach(function (key) {
  var legacyKey = key.replace(/[A-Z]/g, function (m) {
    return '-' + m.toLowerCase();
  });

  opts[legacyKey] = opts[key];
});

function updateCheck() {
  var notifier = updateNotifier({pkg: pkg});
  var message = [];

  if (notifier.update) {
    message.push('Update available: ' + chalk.green.bold(notifier.update.latest) + chalk.gray(' (current: ' + notifier.update.current + ')'));
    message.push('Run ' + chalk.magenta('npm install -g ' + pkg.name) + ' to update.');
    console.log(yosay(message.join(' '), {maxLength: stringLength(message[0])}));
  }
}

function pre() {
  // debugging helper
  if (cmd === 'doctor') {
    require('yeoman-doctor')();
    return;
  }

  // easteregg
  if (cmd === 'yeoman' || cmd === 'yo') {
    console.log(require('yeoman-character'));
    return;
  }

  init();
}

function init() {
  var env = require('yeoman-environment').createEnv();

  env.on('error', function (err) {
    console.error('Error', process.argv.slice(2).join(' '), '\n');
    console.error(opts.debug ? err.stack : err.message);
    process.exit(err.code || 1);
  });

  // lookup for every namespaces, within the environments.paths and lookups
  env.lookup(function () {
    // list generators
    if (opts.generators) {
      return console.log(utils.generatorsFromEnv(env).join('\n'));
    }

    // If no generator is passed, then start the Yo UI
    if (!cmd) {
      if (opts.help) {
        var genList = Object.keys(env.getGeneratorsMeta()).map(function (el) {
          var parts = el.split(':');
          return '  ' + (parts[1] === 'app' ? parts[0] : '  ' + parts[1]);
        }).join('\n');

        console.log(fs.readFileSync(path.join(__dirname, 'usage.txt'), 'utf8') + '\nAvailable Generators:\n' + genList);
        return;
      }

      runYo(env);
      return;
    }

    // Note: at some point, nopt needs to know about the generator options, the
    // one that will be triggered by the below args. Maybe the nopt parsing
    // should be done internally, from the args.
    env.run(args, opts);
  });
}

function runYo(env) {
  var router = new Router(env, insight);
  router.insight.track('yoyo', 'init');
  router.registerRoute('help', require('./routes/help'));
  router.registerRoute('update', require('./routes/update'));
  router.registerRoute('run', require('./routes/run'));
  router.registerRoute('install', require('./routes/install'));
  router.registerRoute('exit', require('./routes/exit'));
  router.registerRoute('clearConfig', require('./routes/clear-config'));
  router.registerRoute('home', require('./routes/home'));

  process.once('exit', router.navigate.bind(router, 'exit'));

  router.updateAvailableGenerators();
  router.navigate('home');
}

rootCheck('\n' + chalk.red('Easy with the `sudo`. Yeoman is the master around here.') + '\n\nSince yo is a user command, there is no need to execute it with root\npermissions. If you\'re having permission errors when using yo without sudo,\nplease spend a few minutes learning more about how your system should work\nand make any necessary repairs.\n\nA quick solution would be to change where npm stores global packages by\nputting ~/npm/bin in your PATH and running:\n' + chalk.blue('npm config set prefix ~/npm') + '\n\nSee: https://github.com/sindresorhus/guides/blob/master/npm-global-without-sudo.md');

var insightMsg = chalk.gray('==========================================================================') +
chalk.yellow('\nWe\'re constantly looking for ways to make ') + chalk.bold.red(pkg.name) +
chalk.yellow(
  ' better! \nMay we anonymously report usage statistics to improve the tool over time? \n' +
  'More info: https://github.com/yeoman/insight & http://yeoman.io'
) +
chalk.gray('\n==========================================================================');

var insight = new Insight({
  trackingCode: 'UA-31537568-1',
  pkg: pkg
});

if (opts.insight === false) {
  insight.config.set('optOut', true);
} else if (opts.insight) {
  insight.config.set('optOut', false);
}

if (opts.insight !== false) {
  if (insight.optOut === undefined) {
    insight.optOut = insight.config.get('optOut');
    insight.track('downloaded');
    insight.askPermission(insightMsg, pre);
    return;
  }
  // only track the two first subcommands
  insight.track.apply(insight, args.slice(0, 2));
}

updateCheck();
pre();
<commit_msg>Fixed the name output for generators in --help<commit_after>#!/usr/bin/env node
'use strict';
var fs = require('fs');
var path = require('path');
var chalk = require('chalk');
var updateNotifier = require('update-notifier');
var Insight = require('insight');
var yosay = require('yosay');
var stringLength = require('string-length');
var rootCheck = require('root-check');
var meow = require('meow');
var pkg = require('../package.json');
var Router = require('./router');
var utils = require('./utils');

var cli = meow({
  help: false,
  pkg: pkg
});

var opts = cli.flags;
var args = cli.input;
var cmd = args[0];

// add un-camelized options too, for legacy
// TODO: remove some time in the future when generators have upgraded
Object.keys(opts).forEach(function (key) {
  var legacyKey = key.replace(/[A-Z]/g, function (m) {
    return '-' + m.toLowerCase();
  });

  opts[legacyKey] = opts[key];
});

function updateCheck() {
  var notifier = updateNotifier({pkg: pkg});
  var message = [];

  if (notifier.update) {
    message.push('Update available: ' + chalk.green.bold(notifier.update.latest) + chalk.gray(' (current: ' + notifier.update.current + ')'));
    message.push('Run ' + chalk.magenta('npm install -g ' + pkg.name) + ' to update.');
    console.log(yosay(message.join(' '), {maxLength: stringLength(message[0])}));
  }
}

function pre() {
  // debugging helper
  if (cmd === 'doctor') {
    require('yeoman-doctor')();
    return;
  }

  // easteregg
  if (cmd === 'yeoman' || cmd === 'yo') {
    console.log(require('yeoman-character'));
    return;
  }

  init();
}

function init() {
  var env = require('yeoman-environment').createEnv();

  env.on('error', function (err) {
    console.error('Error', process.argv.slice(2).join(' '), '\n');
    console.error(opts.debug ? err.stack : err.message);
    process.exit(err.code || 1);
  });

  // lookup for every namespaces, within the environments.paths and lookups
  env.lookup(function () {
    // list generators
    if (opts.generators) {
      return console.log(utils.generatorsFromEnv(env).join('\n'));
    }

    // If no generator is passed, then start the Yo UI
    if (!cmd) {
      if (opts.help) {
        var genList = Object.keys(env.getGeneratorsMeta()).map(function (el) {
          var parts = el.split(':');
          var first = parts.shift();
          return '  ' + (parts[0] === 'app' ? first : '  ' + parts.join(':'));

        }).join('\n');

        console.log(fs.readFileSync(path.join(__dirname, 'usage.txt'), 'utf8') + '\nAvailable Generators:\n' + genList);
        return;
      }

      runYo(env);
      return;
    }

    // Note: at some point, nopt needs to know about the generator options, the
    // one that will be triggered by the below args. Maybe the nopt parsing
    // should be done internally, from the args.
    env.run(args, opts);
  });
}

function runYo(env) {
  var router = new Router(env, insight);
  router.insight.track('yoyo', 'init');
  router.registerRoute('help', require('./routes/help'));
  router.registerRoute('update', require('./routes/update'));
  router.registerRoute('run', require('./routes/run'));
  router.registerRoute('install', require('./routes/install'));
  router.registerRoute('exit', require('./routes/exit'));
  router.registerRoute('clearConfig', require('./routes/clear-config'));
  router.registerRoute('home', require('./routes/home'));

  process.once('exit', router.navigate.bind(router, 'exit'));

  router.updateAvailableGenerators();
  router.navigate('home');
}

rootCheck('\n' + chalk.red('Easy with the `sudo`. Yeoman is the master around here.') + '\n\nSince yo is a user command, there is no need to execute it with root\npermissions. If you\'re having permission errors when using yo without sudo,\nplease spend a few minutes learning more about how your system should work\nand make any necessary repairs.\n\nA quick solution would be to change where npm stores global packages by\nputting ~/npm/bin in your PATH and running:\n' + chalk.blue('npm config set prefix ~/npm') + '\n\nSee: https://github.com/sindresorhus/guides/blob/master/npm-global-without-sudo.md');

var insightMsg = chalk.gray('==========================================================================') +
chalk.yellow('\nWe\'re constantly looking for ways to make ') + chalk.bold.red(pkg.name) +
chalk.yellow(
  ' better! \nMay we anonymously report usage statistics to improve the tool over time? \n' +
  'More info: https://github.com/yeoman/insight & http://yeoman.io'
) +
chalk.gray('\n==========================================================================');

var insight = new Insight({
  trackingCode: 'UA-31537568-1',
  pkg: pkg
});

if (opts.insight === false) {
  insight.config.set('optOut', true);
} else if (opts.insight) {
  insight.config.set('optOut', false);
}

if (opts.insight !== false) {
  if (insight.optOut === undefined) {
    insight.optOut = insight.config.get('optOut');
    insight.track('downloaded');
    insight.askPermission(insightMsg, pre);
    return;
  }
  // only track the two first subcommands
  insight.track.apply(insight, args.slice(0, 2));
}

updateCheck();
pre();
<|endoftext|>


<commit_before>/* global Player, Projectile, Zombie, Explosion, ObjectPoolMaker, FlashMessage */

(function () {
  'use strict';

  var Game = {
    init: function () {
      Game.canvas = document.getElementById('game-canvas');
      Game.context = Game.canvas.getContext('2d');

      Game.loadBackground();
      Game.bind();
      Game.reset();
    },

    hasLeveled: function (level) {
      return Game.score > Game.neededScoreForLevel(level + 1);
    },

    neededScoreForLevel: function (level) {
      return Math.floor(Math.pow(level, 3) * 100) + 1000;
    },

    bind: function () {
      document.addEventListener('keydown', function (e) {
        Game.keysDown[e.keyCode] = true;

        // prevent window from scrolling when pressing UP or DOWN or SPACE
        if (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 32) {
          e.preventDefault();
        }
        if (e.keyCode === 80) {
          Game.isPaused = !Game.isPaused;
          Game.gamePause();
        }
      }, false);

      document.addEventListener('keyup', function (e) {
        delete Game.keysDown[e.keyCode];

        // prevent window from scrolling when pressing UP or DOWN or SPACE
        if (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 32) {
          e.preventDefault();
        }
      }, false);

      window.addEventListener('blur', function () {
        Game.keysDown = {};
      }, false);

      document.getElementById('play-again').addEventListener('click', function () {
        Game.reset();
      }, false);
      document.getElementById('return-play').addEventListener('click', function () {
        Game.isPaused = false;
        Game.gamePause();
      }, false);
    },

    reset: function () {
      // Current game difficulty
      Game.difficulty = 0.01;

      // Max difficulty that Game can reach at any given time
      // It represents the chance percentage of spawning a new Zombie
      Game.maxDifficulty = 0.40;

      // How much difficulty increases after its cooldown elapsed
      Game.difficultyIncrement = 0.005;

      // How long it takes (in seconds) to difficulty to increase
      Game.difficultyCooldown = 4;

      // Last time difficulty was increased
      Game.lastDifficultyIncrease = 0;

      // Time elapsed since Game began
      Game.gameTime = 0;

      // Total score from killing zombies
      Game.score = 0;

      // Maps which keys as currently pressed by e.keyCode
      Game.keysDown = {};

      // Last time a projectile was shot by the player
      Game.lastProjectileTime = 0;

      // How long it takes (in ms) for another projectile to be fired
      Game.projectileCooldown = 225;

      // How much projectile speed improves after each level
      Game.projectileCooldownImprove = 25;

      // Maximum projectile speed (less is faster)
      Game.minProjectileCooldown = 100;

      // Define how many levels it takes to increase projectile power by 1
      // (huge difference)
      Game.powerUpProjectileIn = 10;

      // How many pixels Player and Zombies are constrained by vertically/horizontally
      // (this is interesting according to the background image used)
      Game.verticalBoundary = 35;
      Game.horizontalBoundary = 5;

      Game.isPaused = false;

      Game.isGameOver = false;

      Game.player = new Player(
        Game.canvas.width / 2 - Player.width / 2,
        Game.canvas.height / 2 - Player.height / 2
      );

      // Store pool of objects to be reused for each Entity
      Game.zombiePool = new ObjectPoolMaker(Zombie, 100);
      Game.projectilePool = new ObjectPoolMaker(Projectile, 100);
      Game.explosionPool = new ObjectPoolMaker(Explosion, 100);
      Game.flashMessagePool = new ObjectPoolMaker(FlashMessage, 100);

      document.getElementById('game-overlay').style.display = 'none';
      document.getElementById('game-over').style.display = 'none';
      document.getElementById('game-paused').style.display = 'none';
    },

    loadBackground: function () {
      Game.backgroundReady = false;

      Game.backgroundImg = new Image();
      Game.backgroundImg.src = 'public/images/background.png';

      Game.backgroundImg.onload = function () {
        Game.backgroundReady = true;
      };
    },

    update: function (modifier) {
      if (Game.isPaused) {
        return;
      }

      Game.gameTime += modifier;

      Game.handleInput(modifier);
      Game.handleDifficulty();
      Game.spawnZombies();
      Game.updateEntities(modifier);
    },

    handleInput: function (modifier) {
      if (Game.isGameOver) {
        return;
      }

      var now = Date.now();

      // UP
      if (Game.keysDown[38] && Game.player.y > Game.verticalBoundary) {
        Game.player.setY(Game.player.y - (Game.player.speed * modifier));
      }

      // DOWN
      if (Game.keysDown[40] && Game.player.y < Game.canvas.height - Game.verticalBoundary - Player.height) {
        Game.player.setY(Game.player.y + (Game.player.speed * modifier));
      }

      // RIGHT
      if (Game.keysDown[39] && Game.player.x < Game.canvas.width - Game.horizontalBoundary - Player.width) {
        Game.player.setX(Game.player.x + (Game.player.speed * modifier));
      }

      // LEFT
      if (Game.keysDown[37] && Game.player.x > Game.horizontalBoundary) {
        Game.player.setX(Game.player.x - (Game.player.speed * modifier));
      }

      // SPACE - shoot!
      if (Game.keysDown[32]) {
        // prevent spamming projectiles
        if (now - Game.lastProjectileTime > Game.projectileCooldown) {
          Game.projectilePool.create(
            Game.player.x,
            Game.player.y + (Player.height / 2) - (Projectile.height / 2),
            400,
            Math.floor(Game.player.level / Game.powerUpProjectileIn) + 1
          );
          Game.lastProjectileTime = now;
        }
      }
    },

    handleDifficulty: function () {
      // It gets harder as time goes by..
      if (Game.difficulty < Game.maxDifficulty &&
          Game.gameTime - Game.lastDifficultyIncrease > Game.difficultyCooldown) {
        Game.difficulty += Game.difficultyIncrement;
        Game.lastDifficultyIncrease = Game.gameTime;
      }
    },

    spawnZombies: function () {
      // Create some enemies
      if (Math.random() < Game.difficulty) {
        // resets x coordinate
        // randomize new y coordinate (constrained in available map space)
        Game.zombiePool.create(
          Game.canvas.width,
          Math.random() * (Game.canvas.height - Zombie.height - (2 * Game.verticalBoundary)) + Game.verticalBoundary
        );
      }
    },

    updateEntities: function (modifier) {
      Game.updateProjectilesAndKillZombies(modifier);
      Game.updateZombies(modifier);
      Game.updateExplosions();
      Game.updatePlayer();
      Game.updateFlashMessages(modifier);
    },

    updateProjectilesAndKillZombies: function (modifier) {
      var i,
          j,
          zombie,
          projectile;

      // update all projectiles
      for (i = 0; i < Game.projectilePool.size(); i++) {
        projectile = Game.projectilePool.objectPool()[i];

        projectile.setX(projectile.x + (projectile.speed * modifier));

        // delete projectile if out of the scene
        if (projectile.x > Game.canvas.width) {
          Game.projectilePool.destroy(projectile);
          i--;
        }
        else {
          // kill zombies!
          for (j = 0; j < Game.zombiePool.size(); j++) {
            zombie = Game.zombiePool.objectPool()[j];
            if (projectile.isCollided(zombie)) {
              Game.explosionPool.create(zombie.x, zombie.y);

              // hundred points for each zombie!
              Game.score += 100;

              // Decrease projectile power and
              projectile.power--;
              // destroy projectile if it has no more power
              if (projectile.power === 0) {
                Game.projectilePool.destroy(projectile);
                i--;
              }

              Game.flashMessagePool.create(
                '+ 100',
                zombie.x,
                zombie.y,
                500
              );
              Game.zombiePool.destroy(zombie);
              j--;

              break;
            }
          }
        }
      }
    },

    updateZombies: function (modifier) {
      var zombie,
          i,
          now = Date.now();

      // update all enemies
      for (i = 0; i < Game.zombiePool.size(); i++) {
        zombie = Game.zombiePool.objectPool()[i];
        zombie.update(now);
        zombie.setX(zombie.x - (zombie.speed * modifier));

        // delete zombie if out of the scene
        if (zombie.x + Zombie.width < 0) {
          Game.zombiePool.destroy(zombie);
          i--;
        }
      }
    },

    updateExplosions: function () {
      var i,
          explosion;

      for (i = 0; i < Game.explosionPool.size(); ++i) {
        explosion = Game.explosionPool.objectPool()[i];
        explosion.update();
        if (explosion.currentFrame >= Explosion.framesPosition.length - 1) {
          Game.explosionPool.destroy(explosion);
        }
      }
    },

    updatePlayer: function () {
      var zombie,
          i;

      if (!Game.isGameOver) {
        for (i = 0; i < Game.zombiePool.size(); ++i) {
          zombie = Game.zombiePool.objectPool()[i];
          if (zombie.isCollided(Game.player)) {
            Game.gameOver();
            break;
          }
        }
      }

      // Level up!
      if (Game.hasLeveled(Game.player.level)) {
        Game.player.level += 1;
        Game.flashMessagePool.create(
          'Level ' + Game.player.level,
          Game.player.x,
          Game.player.y,
          700,
          '#E2E215',
          '18px'
        );

        // power up ?
        if (Game.player.level % 10 === 0) {
          Game.flashMessagePool.create(
            'Power Up!',
            Game.player.x,
            Game.player.y - Player.height / 2,
            1000,
            '#34FAC3',
            '16px'
          );
        }

        Game.projectileCooldown -= Game.projectileCooldownImprove;
        if (Game.projectileCooldown < Game.minProjectileCooldown) {
          Game.projectileCooldown = Game.minProjectileCooldown;
        }
      }
    },

    updateFlashMessages: function (modifier) {
      var i,
          flashMessage,
          now = Date.now();

      for (i = 0; i < Game.flashMessagePool.size(); ++i) {
        flashMessage = Game.flashMessagePool.objectPool()[i];
        flashMessage.y -= modifier * 10;
        if (now - flashMessage.createdAt > flashMessage.duration) {
          Game.flashMessagePool.destroy(flashMessage);
        }
      }
    },

    gameOver: function () {
      document.getElementById('game-overlay').style.display = 'block';
      document.getElementById('game-over').style.display = 'block';
      Game.isGameOver = true;
    },

    gamePause: function () {
      var newDisplay = 'block';
      if (document.getElementById('game-paused').style.display === 'block') {
        newDisplay = 'none';
      }
      document.getElementById('game-overlay').style.display = newDisplay;
      document.getElementById('game-paused').style.display = newDisplay;
    },

    render: function () {
      var i;

      // Render Background
      if (Game.backgroundReady) {
        Game.context.drawImage(Game.backgroundImg, 0, 0);
      }

      // Render Projectiles
      for (i = 0; i < Game.projectilePool.size(); ++i) {
        Game.projectilePool.objectPool()[i].render(Game.context);
      }

      // Render Explosions
      for (i = 0; i < Game.explosionPool.size(); ++i) {
        Game.explosionPool.objectPool()[i].render(Game.context);
      }

      // Render Zombies
      for (i = 0; i < Game.zombiePool.size(); ++i) {
        Game.zombiePool.objectPool()[i].render(Game.context);
      }

      // Render Player
      if (!Game.isGameOver) {
        Game.player.render(Game.context);
      }

      // Render Flash messages
      for (i = 0; i < Game.flashMessagePool.size(); ++i) {
        Game.flashMessagePool.objectPool()[i].render(Game.context);
      }

      // Render score
      Game.renderStatus();
    },

    renderStatus: function () {
      Game.context.fillStyle = '#fff';
      Game.context.font = '20px Helvetica';
      Game.context.textAlign = 'left';
      Game.context.textBaseline = 'top';

      Game.context.fillText('Score: ' + Game.score, 10, 5);
      Game.context.fillText('Level: ' + Game.player.level, Game.canvas.width - 110, 5);
    }
  };

  // expose Game globally
  window.Game = Game;
}());
<commit_msg>Check if game is over before handling pause. Check pause on render<commit_after>/* global Player, Projectile, Zombie, Explosion, ObjectPoolMaker, FlashMessage */

(function () {
  'use strict';

  var Game = {
    init: function () {
      Game.canvas = document.getElementById('game-canvas');
      Game.context = Game.canvas.getContext('2d');

      Game.loadBackground();
      Game.bind();
      Game.reset();
    },

    hasLeveled: function (level) {
      return Game.score > Game.neededScoreForLevel(level + 1);
    },

    neededScoreForLevel: function (level) {
      return Math.floor(Math.pow(level, 3) * 100) + 1000;
    },

    bind: function () {
      document.addEventListener('keydown', function (e) {
        Game.keysDown[e.keyCode] = true;

        // prevent window from scrolling when pressing UP or DOWN or SPACE
        if (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 32) {
          e.preventDefault();
        }
        if (!Game.isGameOver && e.keyCode === 80) {
          Game.isPaused = !Game.isPaused;
          Game.gamePause();
        }
      }, false);

      document.addEventListener('keyup', function (e) {
        delete Game.keysDown[e.keyCode];

        // prevent window from scrolling when pressing UP or DOWN or SPACE
        if (e.keyCode === 38 || e.keyCode === 40 || e.keyCode === 32) {
          e.preventDefault();
        }
      }, false);

      window.addEventListener('blur', function () {
        Game.keysDown = {};
      }, false);

      document.getElementById('play-again').addEventListener('click', function () {
        Game.reset();
      }, false);
      document.getElementById('return-play').addEventListener('click', function () {
        Game.isPaused = false;
        Game.gamePause();
      }, false);
    },

    reset: function () {
      // Current game difficulty
      Game.difficulty = 0.01;

      // Max difficulty that Game can reach at any given time
      // It represents the chance percentage of spawning a new Zombie
      Game.maxDifficulty = 0.40;

      // How much difficulty increases after its cooldown elapsed
      Game.difficultyIncrement = 0.005;

      // How long it takes (in seconds) to difficulty to increase
      Game.difficultyCooldown = 4;

      // Last time difficulty was increased
      Game.lastDifficultyIncrease = 0;

      // Time elapsed since Game began
      Game.gameTime = 0;

      // Total score from killing zombies
      Game.score = 0;

      // Maps which keys as currently pressed by e.keyCode
      Game.keysDown = {};

      // Last time a projectile was shot by the player
      Game.lastProjectileTime = 0;

      // How long it takes (in ms) for another projectile to be fired
      Game.projectileCooldown = 225;

      // How much projectile speed improves after each level
      Game.projectileCooldownImprove = 25;

      // Maximum projectile speed (less is faster)
      Game.minProjectileCooldown = 100;

      // Define how many levels it takes to increase projectile power by 1
      // (huge difference)
      Game.powerUpProjectileIn = 10;

      // How many pixels Player and Zombies are constrained by vertically/horizontally
      // (this is interesting according to the background image used)
      Game.verticalBoundary = 35;
      Game.horizontalBoundary = 5;

      Game.isPaused = false;

      Game.isGameOver = false;

      Game.player = new Player(
        Game.canvas.width / 2 - Player.width / 2,
        Game.canvas.height / 2 - Player.height / 2
      );

      // Store pool of objects to be reused for each Entity
      Game.zombiePool = new ObjectPoolMaker(Zombie, 100);
      Game.projectilePool = new ObjectPoolMaker(Projectile, 100);
      Game.explosionPool = new ObjectPoolMaker(Explosion, 100);
      Game.flashMessagePool = new ObjectPoolMaker(FlashMessage, 100);

      document.getElementById('game-overlay').style.display = 'none';
      document.getElementById('game-over').style.display = 'none';
      document.getElementById('game-paused').style.display = 'none';
    },

    loadBackground: function () {
      Game.backgroundReady = false;

      Game.backgroundImg = new Image();
      Game.backgroundImg.src = 'public/images/background.png';

      Game.backgroundImg.onload = function () {
        Game.backgroundReady = true;
      };
    },

    update: function (modifier) {
      if (Game.isPaused) {
        return;
      }

      Game.gameTime += modifier;

      Game.handleInput(modifier);
      Game.handleDifficulty();
      Game.spawnZombies();
      Game.updateEntities(modifier);
    },

    handleInput: function (modifier) {
      if (Game.isGameOver) {
        return;
      }

      var now = Date.now();

      // UP
      if (Game.keysDown[38] && Game.player.y > Game.verticalBoundary) {
        Game.player.setY(Game.player.y - (Game.player.speed * modifier));
      }

      // DOWN
      if (Game.keysDown[40] && Game.player.y < Game.canvas.height - Game.verticalBoundary - Player.height) {
        Game.player.setY(Game.player.y + (Game.player.speed * modifier));
      }

      // RIGHT
      if (Game.keysDown[39] && Game.player.x < Game.canvas.width - Game.horizontalBoundary - Player.width) {
        Game.player.setX(Game.player.x + (Game.player.speed * modifier));
      }

      // LEFT
      if (Game.keysDown[37] && Game.player.x > Game.horizontalBoundary) {
        Game.player.setX(Game.player.x - (Game.player.speed * modifier));
      }

      // SPACE - shoot!
      if (Game.keysDown[32]) {
        // prevent spamming projectiles
        if (now - Game.lastProjectileTime > Game.projectileCooldown) {
          Game.projectilePool.create(
            Game.player.x,
            Game.player.y + (Player.height / 2) - (Projectile.height / 2),
            400,
            Math.floor(Game.player.level / Game.powerUpProjectileIn) + 1
          );
          Game.lastProjectileTime = now;
        }
      }
    },

    handleDifficulty: function () {
      // It gets harder as time goes by..
      if (Game.difficulty < Game.maxDifficulty &&
          Game.gameTime - Game.lastDifficultyIncrease > Game.difficultyCooldown) {
        Game.difficulty += Game.difficultyIncrement;
        Game.lastDifficultyIncrease = Game.gameTime;
      }
    },

    spawnZombies: function () {
      // Create some enemies
      if (Math.random() < Game.difficulty) {
        // resets x coordinate
        // randomize new y coordinate (constrained in available map space)
        Game.zombiePool.create(
          Game.canvas.width,
          Math.random() * (Game.canvas.height - Zombie.height - (2 * Game.verticalBoundary)) + Game.verticalBoundary
        );
      }
    },

    updateEntities: function (modifier) {
      Game.updateProjectilesAndKillZombies(modifier);
      Game.updateZombies(modifier);
      Game.updateExplosions();
      Game.updatePlayer();
      Game.updateFlashMessages(modifier);
    },

    updateProjectilesAndKillZombies: function (modifier) {
      var i,
          j,
          zombie,
          projectile;

      // update all projectiles
      for (i = 0; i < Game.projectilePool.size(); i++) {
        projectile = Game.projectilePool.objectPool()[i];

        projectile.setX(projectile.x + (projectile.speed * modifier));

        // delete projectile if out of the scene
        if (projectile.x > Game.canvas.width) {
          Game.projectilePool.destroy(projectile);
          i--;
        }
        else {
          // kill zombies!
          for (j = 0; j < Game.zombiePool.size(); j++) {
            zombie = Game.zombiePool.objectPool()[j];
            if (projectile.isCollided(zombie)) {
              Game.explosionPool.create(zombie.x, zombie.y);

              // hundred points for each zombie!
              Game.score += 100;

              // Decrease projectile power and
              projectile.power--;
              // destroy projectile if it has no more power
              if (projectile.power === 0) {
                Game.projectilePool.destroy(projectile);
                i--;
              }

              Game.flashMessagePool.create(
                '+ 100',
                zombie.x,
                zombie.y,
                500
              );
              Game.zombiePool.destroy(zombie);
              j--;

              break;
            }
          }
        }
      }
    },

    updateZombies: function (modifier) {
      var zombie,
          i,
          now = Date.now();

      // update all enemies
      for (i = 0; i < Game.zombiePool.size(); i++) {
        zombie = Game.zombiePool.objectPool()[i];
        zombie.update(now);
        zombie.setX(zombie.x - (zombie.speed * modifier));

        // delete zombie if out of the scene
        if (zombie.x + Zombie.width < 0) {
          Game.zombiePool.destroy(zombie);
          i--;
        }
      }
    },

    updateExplosions: function () {
      var i,
          explosion;

      for (i = 0; i < Game.explosionPool.size(); ++i) {
        explosion = Game.explosionPool.objectPool()[i];
        explosion.update();
        if (explosion.currentFrame >= Explosion.framesPosition.length - 1) {
          Game.explosionPool.destroy(explosion);
        }
      }
    },

    updatePlayer: function () {
      var zombie,
          i;

      if (!Game.isGameOver) {
        for (i = 0; i < Game.zombiePool.size(); ++i) {
          zombie = Game.zombiePool.objectPool()[i];
          if (zombie.isCollided(Game.player)) {
            Game.gameOver();
            break;
          }
        }
      }

      // Level up!
      if (Game.hasLeveled(Game.player.level)) {
        Game.player.level += 1;
        Game.flashMessagePool.create(
          'Level ' + Game.player.level,
          Game.player.x,
          Game.player.y,
          700,
          '#E2E215',
          '18px'
        );

        // power up ?
        if (Game.player.level % 10 === 0) {
          Game.flashMessagePool.create(
            'Power Up!',
            Game.player.x,
            Game.player.y - Player.height / 2,
            1000,
            '#34FAC3',
            '16px'
          );
        }

        Game.projectileCooldown -= Game.projectileCooldownImprove;
        if (Game.projectileCooldown < Game.minProjectileCooldown) {
          Game.projectileCooldown = Game.minProjectileCooldown;
        }
      }
    },

    updateFlashMessages: function (modifier) {
      var i,
          flashMessage,
          now = Date.now();

      for (i = 0; i < Game.flashMessagePool.size(); ++i) {
        flashMessage = Game.flashMessagePool.objectPool()[i];
        flashMessage.y -= modifier * 10;
        if (now - flashMessage.createdAt > flashMessage.duration) {
          Game.flashMessagePool.destroy(flashMessage);
        }
      }
    },

    gameOver: function () {
      document.getElementById('game-overlay').style.display = 'block';
      document.getElementById('game-over').style.display = 'block';
      Game.isGameOver = true;
    },

    gamePause: function () {
      var newDisplay = 'block';
      if (document.getElementById('game-paused').style.display === 'block') {
        newDisplay = 'none';
      }
      document.getElementById('game-overlay').style.display = newDisplay;
      document.getElementById('game-paused').style.display = newDisplay;
    },

    render: function () {
      if (Game.isPaused) {
        return;
      }

      var i;

      // Render Background
      if (Game.backgroundReady) {
        Game.context.drawImage(Game.backgroundImg, 0, 0);
      }

      // Render Projectiles
      for (i = 0; i < Game.projectilePool.size(); ++i) {
        Game.projectilePool.objectPool()[i].render(Game.context);
      }

      // Render Explosions
      for (i = 0; i < Game.explosionPool.size(); ++i) {
        Game.explosionPool.objectPool()[i].render(Game.context);
      }

      // Render Zombies
      for (i = 0; i < Game.zombiePool.size(); ++i) {
        Game.zombiePool.objectPool()[i].render(Game.context);
      }

      // Render Player
      if (!Game.isGameOver) {
        Game.player.render(Game.context);
      }

      // Render Flash messages
      for (i = 0; i < Game.flashMessagePool.size(); ++i) {
        Game.flashMessagePool.objectPool()[i].render(Game.context);
      }

      // Render score
      Game.renderStatus();
    },

    renderStatus: function () {
      Game.context.fillStyle = '#fff';
      Game.context.font = '20px Helvetica';
      Game.context.textAlign = 'left';
      Game.context.textBaseline = 'top';

      Game.context.fillText('Score: ' + Game.score, 10, 5);
      Game.context.fillText('Level: ' + Game.player.level, Game.canvas.width - 110, 5);
    }
  };

  // expose Game globally
  window.Game = Game;
}());
<|endoftext|>


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

var version = require('../package.json').version;
var program = require('commander');

program
	.version(version)
	.option('-s, --selenium <serverURL>', 'Specify Selenium Server, like localhost:4444 or ondemand.saucelabs.com:80')
	.option('-v --verbose')
	.option('-u --username <username>', 'Sauce, BrowserStack or Selenium User Name')
	.option('-a --accesskey <accesskey>', 'Sauce, BrowserStack or Selenium Access Key')
	.option('-d --debug', 'Enable debug mode, keep the browser alive even after the tests', false)
	.option('-c --config-file <configFile>', 'Specify a configuration file. If other options are specified, they have precedence over options in config file')
	.option('-o --output <output>', 'Format of output [table|json], defaults to table')
	.option('--prescript-file <preScriptFile>', 'Prescript node module to run (for login, etc) before the tests. Module should be module.exports = function(browser, callback){}')
	.option('-b --browsers <list of browsers>', 'Browsers to run the test on', function(val) {
		return val.split(',');
	})
	.parse(process.argv);

var url = program.args[0];
program.output = program.output || 'table';

if (program.verbose && !process.env.DEBUG) {
	process.env.DEBUG = 'bp:*';
}

require('./index.js')(url, function(err, data) {
	if (err) {
		err.forEach(function(e){
			console.log(e.stack)
		});
	} else {
		if (program.output === 'table') {
			console.log(generateTable(data));
		} else {
			console.log(data);
		}
	}
}, {
	browsers: program.browsers,
	selenium: program.selenium,
	username: program.username,
	accesskey: program.accesskey,
	debugBrowser: program.debug,
	configFile: program.configFile,
	preScriptFile: program.prescriptFile
});

function generateTable(data) {
	var cliTable = require('cli-table');
	var Docs = require('../docs');

	var apiDocs = new Docs();
	var decimalPoints = {
		ms: 3,
		count: 0,
		fps: 3,
		percentage: 2,
	}

	var res = [];
	for (var i = 0; i < data.length; i++) {
		res.push('\n\nBrowser: ', data[i]._browserName + '\n');
		var table = new cliTable({
			head: ['Metrics', 'Value', 'Unit', 'Source'],
			colAligns: ['right', 'right', 'left', 'right'],
			colWidths: [35, 20, 10, 15]
		});
		for (var key in data[i]) {
			if (key.indexOf('_') === 0)
				continue;
			var val = data[i][key];
			var unit = '' + (apiDocs.getProp(key, 'unit') || '');
			if (typeof val === 'number') {
				if (typeof decimalPoints[unit] !== 'undefined') {
					val = val.toFixed(decimalPoints[unit]);
				} else {
					val = val + '';
				}
			}
			table.push([key, val + '', unit, '' + (apiDocs.getProp(key, 'source') || '')]);
		}
		table = table.sort(function(a, b) {
			var rankA = apiDocs.getProp(a[0], 'importance') || -1;
			var rankB = apiDocs.getProp(b[0], 'importance') || -1;

			if (rankA === rankB) {
				if (a[3] === b[3]) {
					return a[0] > b[0] ? 1 : -1;
				} else {
					return a[3] > b[3] ? 1 : -1;
				}
			} else {
				return rankA > rankB ? 1 : (rankA < rankB ? -1 : 0);
			}
		});
		res.push(table.toString());
	}
	return res.join('');
}

// END of File<commit_msg>(feature): Truncate to show only important metrics in CLI<commit_after>#!/usr/bin/env node

var version = require('../package.json').version;
var program = require('commander');

program
	.version(version)
	.option('-s, --selenium <serverURL>', 'Specify Selenium Server, like localhost:4444 or ondemand.saucelabs.com:80')
	.option('-v --verbose')
	.option('-u --username <username>', 'Sauce, BrowserStack or Selenium User Name')
	.option('-a --accesskey <accesskey>', 'Sauce, BrowserStack or Selenium Access Key')
	.option('-d --debug', 'Enable debug mode, keep the browser alive even after the tests', false)
	.option('-c --config-file <configFile>', 'Specify a configuration file. If other options are specified, they have precedence over options in config file')
	.option('-o --output <output>', 'Format of output [table|json], defaults to table')
	.option('--prescript-file <preScriptFile>', 'Prescript node module to run (for login, etc) before the tests. Module should be module.exports = function(browser, callback){}')
	.option('--all', 'Display all metrics')
	.option('-b --browsers <list of browsers>', 'Browsers to run the test on', function(val) {
		return val.split(',');
	})
	.parse(process.argv);

var url = program.args[0];
program.output = program.output || 'table';

var MAX_IMPORTANCE = 30;
if (program.all){
	MAX_IMPORTANCE = 0;
}

if (program.verbose && !process.env.DEBUG) {
	process.env.DEBUG = 'bp:*';
}

require('./index.js')(url, function(err, data) {
	if (err) {
		err.forEach(function(e){
			console.log(e.stack)
		});
	} else {
		if (program.output === 'table') {
			console.log(generateTable(data));
		} else {
			console.log(data);
		}
	}
}, {
	browsers: program.browsers,
	selenium: program.selenium,
	username: program.username,
	accesskey: program.accesskey,
	debugBrowser: program.debug,
	configFile: program.configFile,
	preScriptFile: program.prescriptFile
});

function generateTable(data) {
	var cliTable = require('cli-table');
	var Docs = require('../docs');

	var apiDocs = new Docs();
	var decimalPoints = {
		ms: 3,
		count: 0,
		fps: 3,
		percentage: 2,
	}

	var res = [];
	for (var i = 0; i < data.length; i++) {
		res.push('\n\nBrowser: ', data[i]._browserName + '\n');
		var table = new cliTable({
			head: ['Metrics', 'Value', 'Unit', 'Source'],
			colAligns: ['right', 'right', 'left', 'right'],
			colWidths: [35, 20, 10, 15]
		});
		for (var key in data[i]) {
			if (key.indexOf('_') === 0)
				continue;
			if ((apiDocs.getProp(key, 'importance') || 0) < MAX_IMPORTANCE)
				continue;

			var val = data[i][key];
			var unit = '' + (apiDocs.getProp(key, 'unit') || '');
			if (typeof val === 'number') {
				if (typeof decimalPoints[unit] !== 'undefined') {
					val = val.toFixed(decimalPoints[unit]);
				} else {
					val = val + '';
				}
			}

			table.push([key, val + '', unit, '' + (apiDocs.getProp(key, 'source') || '')]);
		}
		table = table.sort(function(a, b) {
			var rankA = apiDocs.getProp(a[0], 'importance') || -1;
			var rankB = apiDocs.getProp(b[0], 'importance') || -1;

			if (rankA === rankB) {
				if (a[3] === b[3]) {
					return a[0] > b[0] ? 1 : -1;
				} else {
					return a[3] > b[3] ? 1 : -1;
				}
			} else {
				return rankA > rankB ? 1 : (rankA < rankB ? -1 : 0);
			}
		})
		res.push(table.toString());
	}
	return res.join('');
}

// END of File<|endoftext|>


<commit_before>function Load () {
    this.loadBar = null;
    this.playButton = null;
    this.background = null;
    // HACK
    this.loadTicks = 0;
}

Load.prototype.preload = function () {
    this.loadBar = this.add.text(this.game.width / 2, this.game.height / 2, 'Loading assets...');
    this.loadBar.x -= this.loadBar.width / 2;
    this.loadBar.y -= this.loadBar.height / 2;
    this.testRenderer();

    // some game settings
    game.scale.scaleMode = Phaser.ScaleManager.USER_SCALE;
    game.scale.onResize = function () {
        game.scale.setGameSize(innerWidth - 1, innerHeight - 1);
    };
    game.time.advancedTiming = true;
    game.stage.backgroundColor = '#0080ff';

    // load assets
    game.load.image('ball', 'assets/ball.png');
    game.load.atlasJSONArray('shapes', 'img/shapes_small.png', 'img/shapes_small.json');
    game.load.image('background', 'assets/background.png');
    game.load.audio('music', ['assets/music.ogg', 'assets/music.m4a', 'assets/music.wav']);
    game.load.audio('music2', ['assets/music2.ogg', 'assets/music2.m4a']);

    // create texture for showing match-3
    this.game.create.texture('whiteSquare', ['2']);
};

Load.prototype.preloadUpdate = function () {
    // HACK to get the text size
    this.loadBar.x = this.game.width / 2 - this.loadBar.width / (2 * this.game.resolution);
    this.loadBar.y = this.game.height / 2 - this.loadBar.height / (2 * this.game.resolution);
};

Load.prototype.create = function() {
    this.background = this.add.sprite(0, 0, 'background');
    this.background.width = this.game.width;
    this.background.height = this.game.height;
    this.background.moveDown();
    this.loadBar.text = 'Start!';
    this.playButton = this.add.button(this.game.width / 2 - 100, this.game.height / 2 - 35,
      'ball', this.playGame, this);
    this.loadBar.moveUp();
    this.playButton.width = 200;
    this.playButton.height = 70;
};

Load.prototype.update = function () {
    var w = this.game.width;
    var h = this.game.height;
    // HACK to get the text size
    this.loadBar.x = w / 2 - this.loadBar.width / (2 * this.game.resolution);
    this.loadBar.y = h / 2 - this.loadBar.height / (2 * this.game.resolution);
    this.playButton.x = w / 2 - this.playButton.width / 2;
    this.playButton.y = h / 2 - this.playButton.height / 2;
    this.background.width = w;
    this.background.height = h;

    // HACK workaround for Firefox running under file://
    this.loadTicks++;
    if (this.loadTicks == 10 && location.protocol === 'file:') {
        this.game.cache.destroy();
        this.state.start('Load');
    }
};

Load.prototype.playGame = function () {
    var me = this;
    AppleFools.getLife(function (result) {
        if (result) {
            me.state.start('GameScreen');
        }
        else {
            alertBox('遊戲發生內部錯誤，無法繼續');
        }
    });
};

Load.prototype.testRenderer = function () {
    // Test the renderer
    var renderer = 'unknown';
    switch (this.game.renderType) {
      case Phaser.CANVAS:
        renderer = 'CANVAS';
        break;
      case Phaser.WEBGL:
        renderer = 'WEBGL';
        break;
      case Phaser.HEADLESS:
        renderer = 'HEADLESS';
        break;
    }
    try {
        localStorage.setItem('ShapeClear_renderer', renderer);
    }
    catch (e) {
        ;
    }
};
<commit_msg>fix chrome wrong viewport<commit_after>function Load () {
    this.loadBar = null;
    this.playButton = null;
    this.background = null;
    // HACK
    this.loadTicks = 0;
}

Load.prototype.preload = function () {
    this.loadBar = this.add.text(this.game.width / 2, this.game.height / 2, 'Loading assets...');
    this.loadBar.x -= this.loadBar.width / 2;
    this.loadBar.y -= this.loadBar.height / 2;
    this.testRenderer();

    // some game settings
    game.scale.scaleMode = Phaser.ScaleManager.USER_SCALE;
    game.scale.onResize = function () {
        var rect = document.body.getClientRects()[0];
        var width = Math.min(Math.floor(rect.width), innerWidth);
        var height = Math.min(Math.floor(rect.height), innerHeight)
        game.scale.setGameSize(width, height);
    };
    game.time.advancedTiming = true;
    game.stage.backgroundColor = '#0080ff';

    // load assets
    game.load.image('ball', 'assets/ball.png');
    game.load.atlasJSONArray('shapes', 'img/shapes_small.png', 'img/shapes_small.json');
    game.load.image('background', 'assets/background.png');
    game.load.audio('music', ['assets/music.ogg', 'assets/music.m4a', 'assets/music.wav']);
    game.load.audio('music2', ['assets/music2.ogg', 'assets/music2.m4a']);

    // create texture for showing match-3
    this.game.create.texture('whiteSquare', ['2']);
};

Load.prototype.preloadUpdate = function () {
    // HACK to get the text size
    this.loadBar.x = this.game.width / 2 - this.loadBar.width / (2 * this.game.resolution);
    this.loadBar.y = this.game.height / 2 - this.loadBar.height / (2 * this.game.resolution);
};

Load.prototype.create = function() {
    this.background = this.add.sprite(0, 0, 'background');
    this.background.width = this.game.width;
    this.background.height = this.game.height;
    this.background.moveDown();
    this.loadBar.text = 'Start!';
    this.playButton = this.add.button(this.game.width / 2 - 100, this.game.height / 2 - 35,
      'ball', this.playGame, this);
    this.loadBar.moveUp();
    this.playButton.width = 200;
    this.playButton.height = 70;
};

Load.prototype.update = function () {
    var w = this.game.width;
    var h = this.game.height;
    // HACK to get the text size
    this.loadBar.x = w / 2 - this.loadBar.width / (2 * this.game.resolution);
    this.loadBar.y = h / 2 - this.loadBar.height / (2 * this.game.resolution);
    this.playButton.x = w / 2 - this.playButton.width / 2;
    this.playButton.y = h / 2 - this.playButton.height / 2;
    this.background.width = w;
    this.background.height = h;

    // HACK workaround for Firefox running under file://
    this.loadTicks++;
    if (this.loadTicks == 10 && location.protocol === 'file:') {
        this.game.cache.destroy();
        this.state.start('Load');
    }
};

Load.prototype.playGame = function () {
    var me = this;
    AppleFools.getLife(function (result) {
        if (result) {
            me.state.start('GameScreen');
        }
        else {
            alertBox('遊戲發生內部錯誤，無法繼續');
        }
    });
};

Load.prototype.testRenderer = function () {
    // Test the renderer
    var renderer = 'unknown';
    switch (this.game.renderType) {
      case Phaser.CANVAS:
        renderer = 'CANVAS';
        break;
      case Phaser.WEBGL:
        renderer = 'WEBGL';
        break;
      case Phaser.HEADLESS:
        renderer = 'HEADLESS';
        break;
    }
    try {
        localStorage.setItem('ShapeClear_renderer', renderer);
    }
    catch (e) {
        ;
    }
};
<|endoftext|>