<commit_before>/*********************************************************************
 * A small custom icon class, which draws a two bit icon centered and
 * maximized, preserving the aspect ratio.
 *
 * This class was introduced to solve the following problems:
 *  a) draw the icon with the current theme color
 *  b) to work-around the strange streched icon I get in gnome-3.14
 *
 * If there is a better way for a) using my previous svg icon file,
 * please let me know ;)
 ********************************************************************/

const Lang    = imports.lang;
const St      = imports.gi.St;
const Clutter = imports.gi.Clutter;
const ExUt    = imports.misc.extensionUtils;
const Me      = ExUt.getCurrentExtension();
const Utils   = Me.imports.utils;

const TwoColorIcon = new Lang.Class({
	Name: 'TwoColorIcon',
	Extends: St.DrawingArea,

	_init : function(size, drawingObject) {
		this.parent({ reactive : true });
        this.set_width(size);
        this.set_height(size);
		this._drawingObject = drawingObject;

		this.connect('repaint', Lang.bind(this, this._drawIcon));

		// some fallback color
		this._primaryColor = new Clutter.Color({
            red: 150,
            green: 150,
            blue: 150,
            alpha: 255
        });
		this._secundaryColor = this._primaryColor;
		this._currentStatus  = null;
	},
	setPadding: function(padding) {
		this.margin_left  = padding;
		this.margin_right = padding;
	},
    setColor: function(primary, secundary) {
		this._primaryColor   = primary;
		this._secundaryColor = secundary;
		this.queue_repaint();
    },
	setStatus: function(newStatus) {
		this._customStatus = newStatus;
		this.queue_repaint();
	},
	_drawIcon: function() {
	  	let cr    = this.get_context();
		let orWdt = this._drawingObject.width;
		let orHgt = this._drawingObject.height;
        let[width, height] = this.get_surface_size();

		cr.save();

		// layout object in box
		if (orWdt/orHgt > width/height) {
			// take full width and center vertically
			cr.scale(width/orWdt, width/orWdt);
			cr.translate(0, (orWdt-orHgt)*0.5);
		} else {
			cr.scale(height/orHgt, height/orHgt)
			cr.translate(-(orWdt-orHgt)*0.5, 0);;
		}

		this._drawingObject.draw(cr, this._customStatus, this._primaryColor, this._secundaryColor);

		cr.restore();
	}

});

const TeaPot = {
	width  : 484,
	height : 295,
	draw   : function(cr, stat, primary, secundary) {
	// draw TeaPot
		// cairo commands generated from svg2cairo
		// https://github.com/akrinke/svg2cairo

		Utils.setCairoColorFromClutter(cr, primary);

		cr.moveTo(127.894531, 276.472656);
		cr.curveTo(98.457031, 244.316406, 76.527344, 238.09375, 47.953125, 210.996094);
		cr.curveTo(17.957031, 186.902344, -7.5625, 148.257812, 2.066406, 108.261719);
		cr.curveTo(6.914062, 83.1875, 33.097656, 66.261719, 57.921875, 71.910156);
		cr.curveTo(75.457031, 74.132812, 91.273438, 82.546875, 106.296875, 91.351562);
		cr.curveTo(115.582031, 75.792969, 143.570312, 72.222656, 134.984375, 50.113281);
		cr.curveTo(148.652344, 38.449219, 169.386719, 38.300781, 186.574219, 34.550781);
		cr.curveTo(194.753906, 31.46875, 224.667969, 35.746094, 204.664062, 27.492188);
		cr.curveTo(191.921875, 8.488281, 224.023438, -2.769531, 239.1875, 0.589844);
		cr.curveTo(266.851562, -1.550781, 262.417969, 31.988281, 246.710938, 32.113281);
		cr.curveTo(277.785156, 34.632812, 309.761719, 36.359375, 339.148438, 47.523438);
		cr.curveTo(349.664062, 56.277344, 334.71875, 72.871094, 353.0625, 77.5625);
		cr.curveTo(365.789062, 87.367188, 373.671875, 119.875, 391.816406, 97.292969);
		cr.curveTo(408.726562, 84.214844, 418.597656, 56.902344, 444.113281, 60.386719);
		cr.curveTo(455.804688, 60.738281, 498.675781, 59.714844, 478.949219, 78.144531);
		cr.curveTo(459.007812, 90.46875, 438.289062, 106.699219, 434.382812, 131.382812);
		cr.curveTo(424.910156, 164.207031, 403.375, 177.308594, 377.503906, 202.261719);
		cr.curveTo(356.9375, 218.46875, 366.351562, 240.726562, 316.707031, 285.832031);
		cr.curveTo(289.941406, 297.757812, 175.589844, 302.082031, 127.894531, 276.472656);
		cr.closePath();
		cr.moveTo(83.28125, 184.4375);
		cr.curveTo(78.351562, 164.75, 89.941406, 143.515625, 85.308594, 124.882812);
		cr.curveTo(73.085938, 112.210938, 40.816406, 104.996094, 44.332031, 130.574219);
		cr.curveTo(48.808594, 142.773438, 71.621094, 185.558594, 83.28125, 184.4375);
		cr.closePath();
		cr.moveTo(83.28125, 184.4375);
		cr.setTolerance(0.1);
		cr.fillPreserve();

		// end of image
	} // draw
}; // TeaPot

const Pie = {
	width : 1,
	height: 1,
	draw   : function(cr, stat, primary, secundary) {
        const pi = Math.PI;
        const r  = 0.5;

        if(stat == null) stat = 0;

        cr.translate(0.5, 0.5);
        cr.save();

        Utils.setCairoColorFromClutter(cr, secundary);
        cr.moveTo(0, 0);
        cr.arc(0, 0, r, 3 / 2 * pi + 2 * pi * stat, 3 / 2 * pi + 2
                * pi);
        cr.fill();

        Utils.setCairoColorFromClutter(cr, primary);
        cr.moveTo(0, 0);
        cr.arc(0, 0, r, 3 / 2 * pi, 3 / 2 * pi + 2 * pi * stat);
        cr.fill();
    } // draw
}; // Pie
<commit_msg>fix comment<commit_after>/*********************************************************************
 * A small custom icon class, which draws a two bit icon centered and
 * maximized, preserving the aspect ratio.
 *
 * This class was introduced to solve the following problems:
 *  a) draw the icon with the current theme color
 *  b) to work-around the strange streched icon I get in gnome-3.14
 *  c) draw an animation using current theme color
 *
 * If there is a better way for that stuff, please let me know ;)
 ********************************************************************/

const Lang    = imports.lang;
const St      = imports.gi.St;
const Clutter = imports.gi.Clutter;
const ExUt    = imports.misc.extensionUtils;
const Me      = ExUt.getCurrentExtension();
const Utils   = Me.imports.utils;

const TwoColorIcon = new Lang.Class({
	Name: 'TwoColorIcon',
	Extends: St.DrawingArea,

	_init : function(size, drawingObject) {
		this.parent({ reactive : true });
        this.set_width(size);
        this.set_height(size);
		this._drawingObject = drawingObject;

		this.connect('repaint', Lang.bind(this, this._drawIcon));

		// some fallback color
		this._primaryColor = new Clutter.Color({
            red: 150,
            green: 150,
            blue: 150,
            alpha: 255
        });
		this._secundaryColor = this._primaryColor;
		this._currentStatus  = null;
	},
	setPadding: function(padding) {
		this.margin_left  = padding;
		this.margin_right = padding;
	},
    setColor: function(primary, secundary) {
		this._primaryColor   = primary;
		this._secundaryColor = secundary;
		this.queue_repaint();
    },
	setStatus: function(newStatus) {
		this._customStatus = newStatus;
		this.queue_repaint();
	},
	_drawIcon: function() {
	  	let cr    = this.get_context();
		let orWdt = this._drawingObject.width;
		let orHgt = this._drawingObject.height;
        let[width, height] = this.get_surface_size();

		cr.save();

		// layout object in box
		if (orWdt/orHgt > width/height) {
			// take full width and center vertically
			cr.scale(width/orWdt, width/orWdt);
			cr.translate(0, (orWdt-orHgt)*0.5);
		} else {
			cr.scale(height/orHgt, height/orHgt)
			cr.translate(-(orWdt-orHgt)*0.5, 0);;
		}

		this._drawingObject.draw(cr, this._customStatus, this._primaryColor, this._secundaryColor);

		cr.restore();
	}

});

const TeaPot = {
	width  : 484,
	height : 295,
	draw   : function(cr, stat, primary, secundary) {
	// draw TeaPot
		// cairo commands generated from svg2cairo
		// https://github.com/akrinke/svg2cairo

		Utils.setCairoColorFromClutter(cr, primary);

		cr.moveTo(127.894531, 276.472656);
		cr.curveTo(98.457031, 244.316406, 76.527344, 238.09375, 47.953125, 210.996094);
		cr.curveTo(17.957031, 186.902344, -7.5625, 148.257812, 2.066406, 108.261719);
		cr.curveTo(6.914062, 83.1875, 33.097656, 66.261719, 57.921875, 71.910156);
		cr.curveTo(75.457031, 74.132812, 91.273438, 82.546875, 106.296875, 91.351562);
		cr.curveTo(115.582031, 75.792969, 143.570312, 72.222656, 134.984375, 50.113281);
		cr.curveTo(148.652344, 38.449219, 169.386719, 38.300781, 186.574219, 34.550781);
		cr.curveTo(194.753906, 31.46875, 224.667969, 35.746094, 204.664062, 27.492188);
		cr.curveTo(191.921875, 8.488281, 224.023438, -2.769531, 239.1875, 0.589844);
		cr.curveTo(266.851562, -1.550781, 262.417969, 31.988281, 246.710938, 32.113281);
		cr.curveTo(277.785156, 34.632812, 309.761719, 36.359375, 339.148438, 47.523438);
		cr.curveTo(349.664062, 56.277344, 334.71875, 72.871094, 353.0625, 77.5625);
		cr.curveTo(365.789062, 87.367188, 373.671875, 119.875, 391.816406, 97.292969);
		cr.curveTo(408.726562, 84.214844, 418.597656, 56.902344, 444.113281, 60.386719);
		cr.curveTo(455.804688, 60.738281, 498.675781, 59.714844, 478.949219, 78.144531);
		cr.curveTo(459.007812, 90.46875, 438.289062, 106.699219, 434.382812, 131.382812);
		cr.curveTo(424.910156, 164.207031, 403.375, 177.308594, 377.503906, 202.261719);
		cr.curveTo(356.9375, 218.46875, 366.351562, 240.726562, 316.707031, 285.832031);
		cr.curveTo(289.941406, 297.757812, 175.589844, 302.082031, 127.894531, 276.472656);
		cr.closePath();
		cr.moveTo(83.28125, 184.4375);
		cr.curveTo(78.351562, 164.75, 89.941406, 143.515625, 85.308594, 124.882812);
		cr.curveTo(73.085938, 112.210938, 40.816406, 104.996094, 44.332031, 130.574219);
		cr.curveTo(48.808594, 142.773438, 71.621094, 185.558594, 83.28125, 184.4375);
		cr.closePath();
		cr.moveTo(83.28125, 184.4375);
		cr.setTolerance(0.1);
		cr.fillPreserve();

		// end of image
	} // draw
}; // TeaPot

const Pie = {
	width : 1,
	height: 1,
	draw   : function(cr, stat, primary, secundary) {
        const pi = Math.PI;
        const r  = 0.5;

        if(stat == null) stat = 0;

        cr.translate(0.5, 0.5);
        cr.save();

        Utils.setCairoColorFromClutter(cr, secundary);
        cr.moveTo(0, 0);
        cr.arc(0, 0, r, 3 / 2 * pi + 2 * pi * stat, 3 / 2 * pi + 2
                * pi);
        cr.fill();

        Utils.setCairoColorFromClutter(cr, primary);
        cr.moveTo(0, 0);
        cr.arc(0, 0, r, 3 / 2 * pi, 3 / 2 * pi + 2 * pi * stat);
        cr.fill();
    } // draw
}; // Pie
<|endoftext|>


<commit_before>var log = require('npmlog');
var android = require('./android/project');
var ios = require('./ios/project');
var loadConfig = require('./config');

// Load npmlog heading
log.heading = 'rnpm';

/**
 * Validates projects and prints warnings if there are any issues (side-effect).
 *
 * Projects that have no config supplied are ommited. Otherwise, they are added
 * to the accumulated value and return at the end of iteration.
 */
function validateProjects(projects, config) {
  return Object.keys(projects).reduce(function(acc, platform) {
    var project = projects[platform];

    if (!config[platform]) return acc;

    if (!project) {
      log.warn('ENOENT', `No project for ${platform} at ${config[platform].project}`);
      return acc;
    }

    var projectError = project.validate();
    if (projectError) {
      log.warn('EPROJECT', projectError);
      return acc;
    }

    return Object.assign({}, acc, {[platform]: project});
  }, {});
}

/*
 * Initialisation of the `rnpm` called before anything.
 * Sets up some basic loggers and loads projects to work with
 *
 * Returns object containing `ios` and `android` projects
 * that can be used later on to perform some platform-specific
 * tasks.
 *
 * Any invalid projects are omitted and deleted from the object
 * being returned. See `validateProjects` for further details.
 */
function init() {
  var config = loadConfig();

  var projects = {
    ios: ios.fromConfig(config.ios),
    android: android.fromConfig(config.android)
  };

  return validateProjects(projects, config);
}

module.exports = init;
<commit_msg>Add comments<commit_after>var log = require('npmlog');
var android = require('./android/project');
var ios = require('./ios/project');
var loadConfig = require('./config');

// Load npmlog heading
log.heading = 'rnpm';

/**
 * Validates projects and prints warnings if there are any issues (side-effect).
 *
 * Projects that have no config supplied are ommited. Otherwise, they are added
 * to the accumulated value and return at the end of iteration.
 *
 * User might set config for a given platform to `false` to indicate that given
 * platform is not available (e.g {ios: false});
 *
 * If project has been created, it's being validated to check if any additional errors
 * are present (e.g. missing assets etc) that this package cannot fix. In such situation,
 * extra care by the application author has to be taken.
 */
function validateProjects(projects, config) {
  return Object.keys(projects).reduce(function(acc, platform) {
    var project = projects[platform];

    if (!config[platform]) return acc;

    if (!project) {
      log.warn('ENOENT', `No project for ${platform} at ${config[platform].project}`);
      return acc;
    }

    var projectError = project.validate();
    if (projectError) {
      log.warn('EPROJECT', projectError);
      return acc;
    }

    return Object.assign({}, acc, {[platform]: project});
  }, {});
}

/*
 * Initialisation of the `rnpm` called before anything.
 * Sets up some basic loggers and loads projects to work with
 *
 * Returns object containing `ios` and `android` projects
 * that can be used later on to perform some platform-specific
 * tasks.
 *
 * Any invalid projects are omitted and deleted from the object
 * being returned. See `validateProjects` for further details.
 */
function init() {
  var config = loadConfig();

  var projects = {
    ios: ios.fromConfig(config.ios),
    android: android.fromConfig(config.android)
  };

  return validateProjects(projects, config);
}

module.exports = init;
<|endoftext|>


<commit_before>/* Copyright (c) 2011 by The Authors.
 * Published under the LGPL 2.1 license.
 * See /license-notice.txt for the full text of the license notice.
 * See /license.txt for the full text of the license.
 */

/*jslint forin: true */

/**
 * @namespace
 */
jsts = {
  version: '1.11-SNAPSHOT'
};

jsts.abstractFunc = function() {
  throw new jsts.error.AbstractMethodInvocationError();
};

/**
 * @namespace
 */
jsts.error = {};

/**
 * @param {String}
 *          message User defined error message.
 * @constructor
 */
jsts.error.IllegalArgumentError = function(message) {
  this.name = 'IllegalArgumentError';
  this.message = message || '';
};
jsts.error.IllegalArgumentError.prototype = new Error();

/**
 * @constructor
 */
jsts.error.TopologyError = function(message) {
  this.name = 'TopologyError';
  this.message = message || '';
};
jsts.error.TopologyError.prototype = new Error();

/**
 * @constructor
 */
jsts.error.AbstractMethodInvocationError = function() {
  this.name = 'AbstractMethodInvocationError';
  this.message = 'Abstract method called, should be implemented in subclass.';
};
jsts.error.AbstractMethodInvocationError.prototype = new Error();

/**
 * @constructor
 */
jsts.error.NotImplementedError = function() {
  this.name = 'NotImplementedError';
  this.message = 'This method has not yet been implemented.';
};
jsts.error.NotImplementedError.prototype = new Error();

/**
 * @constructor
 */
jsts.error.NotRepresentableError = function(message) {
  this.name = 'NotRepresentableError';
  this.message = message || '';
};
jsts.error.NotRepresentableError.prototype = new Error();
<commit_msg>Do not use JTS version, instead start at 0.1-SNAPSHOT.<commit_after>/* Copyright (c) 2011 by The Authors.
 * Published under the LGPL 2.1 license.
 * See /license-notice.txt for the full text of the license notice.
 * See /license.txt for the full text of the license.
 */

/*jslint forin: true */

/**
 * @namespace
 */
jsts = {
  version: '0.1-SNAPSHOT'
};

jsts.abstractFunc = function() {
  throw new jsts.error.AbstractMethodInvocationError();
};

/**
 * @namespace
 */
jsts.error = {};

/**
 * @param {String}
 *          message User defined error message.
 * @constructor
 */
jsts.error.IllegalArgumentError = function(message) {
  this.name = 'IllegalArgumentError';
  this.message = message || '';
};
jsts.error.IllegalArgumentError.prototype = new Error();

/**
 * @constructor
 */
jsts.error.TopologyError = function(message) {
  this.name = 'TopologyError';
  this.message = message || '';
};
jsts.error.TopologyError.prototype = new Error();

/**
 * @constructor
 */
jsts.error.AbstractMethodInvocationError = function() {
  this.name = 'AbstractMethodInvocationError';
  this.message = 'Abstract method called, should be implemented in subclass.';
};
jsts.error.AbstractMethodInvocationError.prototype = new Error();

/**
 * @constructor
 */
jsts.error.NotImplementedError = function() {
  this.name = 'NotImplementedError';
  this.message = 'This method has not yet been implemented.';
};
jsts.error.NotImplementedError.prototype = new Error();

/**
 * @constructor
 */
jsts.error.NotRepresentableError = function(message) {
  this.name = 'NotRepresentableError';
  this.message = message || '';
};
jsts.error.NotRepresentableError.prototype = new Error();
<|endoftext|>


<commit_before>var HTMLCS_WCAG2AAA_Sniffs_Principle2_Guideline2_2_2_2_2 = {
    /**
     * Determines the elements to register for processing.
     *
     * Each element of the returned array can either be an element name, or "_top"
     * which is the top element of the tested code.
     *
     * @returns {Array} The list of elements.
     */
    register: function()
    {
        return ['_top'];

    },

    /**
     * Process the registered element.
     *
     * @param {DOMNode} element The element registered.
     * @param {DOMNode} top     The top element of the tested code.
     */
    process: function(element, top)
    {
        HTMLCS.addMessage(HTMLCS.NOTICE, element, 'If any part of the content moves, scrolls or blinks for more than 5 seconds, or auto-updates, check that there is a mechanism available to pause, stop, or hide the content.', 'SCR33,SCR22,G187,G152,G186,G191');

    }
};
<commit_msg>SC 2.2.2: Add tests for blinking elements. Blink elements are shown as errors as per F47, those with text-decoration: blink are shown warnings as per F4, as that is conditional on being able to turn it off within 5 seconds or not. (Blink elements are presumed as not being able to do this - although it can be disabled with CSS, F47 seems to imply that you put it in a blink tag for a reason, ie. for it to continuously blink.)<commit_after>var HTMLCS_WCAG2AAA_Sniffs_Principle2_Guideline2_2_2_2_2 = {
    /**
     * Determines the elements to register for processing.
     *
     * Each element of the returned array can either be an element name, or "_top"
     * which is the top element of the tested code.
     *
     * @returns {Array} The list of elements.
     */
    register: function()
    {
        return [
            '_top',
            'blink'
        ];

    },

    /**
     * Process the registered element.
     *
     * @param {DOMNode} element The element registered.
     * @param {DOMNode} top     The top element of the tested code.
     */
    process: function(element, top)
    {
        if (element === top) {
            HTMLCS.addMessage(HTMLCS.NOTICE, element, 'If any part of the content moves, scrolls or blinks for more than 5 seconds, or auto-updates, check that there is a mechanism available to pause, stop, or hide the content.', 'SCR33,SCR22,G187,G152,G186,G191');

            var elements = top.querySelectorAll('*');
            for (var i = 0; i < elements.length; i++) {
                var computedStyle = null;
                if (element[i].currentStyle) {
                    computedStyle = element[i].currentStyle;
                } else {
                    computerStyle = element[i].getComputedStyle();
                }

                if (/blink/.test(computedStyle['text-decoration']) === true) {
                    HTMLCS.addMessage(HTMLCS.WARNING, element, 'Ensure there is a mechanism available to stop this blinking element in less than five seconds.', 'F4');
                }
        } else if (element.nodeName.toLowerCase() === 'blink') {
            HTMLCS.addMessage(HTMLCS.ERROR, element, 'Blink elements cannot satisfy the requirement that blinking information can be stopped within five seconds.', 'F47');
        }

    }
};
<|endoftext|>


<commit_before>/**
 * @fileOverview A module for spawning processes, connecting to their
 * input/output/errput and returning their response codes.
 */

var {Stream, MemoryStream, TextStream} = require('io');
var arrays = require('ringo/utils/arrays');

function createProcess(args) {
    // arguments may end with a {dir: "", env: {}} object
    var opts = (args.length > 1 && arrays.peek(args) instanceof Object) ?
            Array.pop(args) : {};
    // make command either a single string or an array of strings
    var command = args.length == 1 ? String(args[0]) : Array.map(args, String);
    var {dir, env} = opts;
    dir = dir ? new java.io.File(dir) : null;
    if (env && !Array.isArray(env)) {
        // convert env to an array of the form ["key=value", ...]
        env = [key + "=" + env[key] for (key in env)];
    } else if (!env) {
        env = null;
    }
    return java.lang.Runtime.getRuntime().exec(command, env, dir);
}

function connect(process, output, errput) {
    spawn(function() {
        new TextStream(new Stream(process.inputStream)).copy(output);
    }).get();
    spawn(function() {
        new TextStream(new Stream(process.errorStream)).copy(errput);
    }).get();
}

/**
 * executes a given command and returns the
 * standard output.  If the exit status is non-zero,
 * throws an Error.
 * @param {String} command... and optional arguments as individual strings
 * @param {Object} [options] options object. This may contain a `dir` string
 * property specifying the directory to run the process in and a `env`
 * object property specifying additional environment variable mappings.
 * @returns String the standard output of the command
 */
exports.command = function() {
    var process = createProcess(arguments);
    var output = new TextStream(new MemoryStream());
    var error = new TextStream(new MemoryStream());
    connect(process, output, error);
    var status = process.waitFor();
    if (status != 0) {
        throw new Error("(" + status + ") " + error.content);
    }
    return output.content;
};

/**
 * executes a given command, attached to this process's
 * output and error streams, and returns the exit status.
 * @param {String} command... and optional arguments as individual strings
 * @param {Object} [options] options object. This may contain a `dir` string
 * property specifying the directory to run the process in and a `env`
 * object property specifying additional environment variable mappings.
 * @returns Number exit status
 */
exports.system = function() {
    var process = createProcess(arguments);
    connect(process, system.stdout, system.stderr);
    return process.waitFor();
};

/**
 * executes a given command quietly and returns
 * the exit status.
 * @param {String} command... and optional arguments as individual strings
 * @param {Object} [options] options object. This may contain a `dir` string
 * property specifying the directory to run the process in and a `env`
 * object property specifying additional environment variable mappings.
 * @returns Number exit status
 */
exports.status = function() {
    var process = createProcess(arguments);
    connect(process, dummyStream(), dummyStream());
    return process.waitFor();
};

function dummyStream() {
    return {
        writable: function() true,
        readable: function() false,
        seekable: function() false,
        write: function() this,
        flush: function() this,
        close: function() this
    }
}

<commit_msg>Improve jsdoc in ringo/subprocess<commit_after>/**
 * @fileOverview A module for spawning processes, connecting to their
 * input/output/errput and returning their response codes.
 */

var {Stream, MemoryStream, TextStream} = require('io');
var arrays = require('ringo/utils/arrays');

function createProcess(args) {
    // arguments may end with a {dir: "", env: {}} object
    var opts = (args.length > 1 && arrays.peek(args) instanceof Object) ?
            Array.pop(args) : {};
    // make command either a single string or an array of strings
    var command = args.length == 1 ? String(args[0]) : Array.map(args, String);
    var {dir, env} = opts;
    dir = dir ? new java.io.File(dir) : null;
    if (env && !Array.isArray(env)) {
        // convert env to an array of the form ["key=value", ...]
        env = [key + "=" + env[key] for (key in env)];
    } else if (!env) {
        env = null;
    }
    return java.lang.Runtime.getRuntime().exec(command, env, dir);
}

function connect(process, output, errput) {
    spawn(function() {
        new TextStream(new Stream(process.inputStream)).copy(output);
    }).get();
    spawn(function() {
        new TextStream(new Stream(process.errorStream)).copy(errput);
    }).get();
}

/**
 * executes a given command and returns the
 * standard output.  If the exit status is non-zero,
 * throws an Error.
 * @param {String} command... command and optional arguments as single or multiple
 * string parameters
 * @param {Object} [options] options object. This may contain a `dir` string
 * property specifying the directory to run the process in and a `env`
 * object property specifying additional environment variable mappings.
 * @returns String the standard output of the command
 */
exports.command = function() {
    var process = createProcess(arguments);
    var output = new TextStream(new MemoryStream());
    var error = new TextStream(new MemoryStream());
    connect(process, output, error);
    var status = process.waitFor();
    if (status != 0) {
        throw new Error("(" + status + ") " + error.content);
    }
    return output.content;
};

/**
 * executes a given command, attached to this process's
 * output and error streams, and returns the exit status.
 * @param {String} command... command and optional arguments as single or multiple
 * string parameters
 * @param {Object} [options] options object. This may contain a `dir` string
 * property specifying the directory to run the process in and a `env`
 * object property specifying additional environment variable mappings.
 * @returns Number exit status
 */
exports.system = function() {
    var process = createProcess(arguments);
    connect(process, system.stdout, system.stderr);
    return process.waitFor();
};

/**
 * executes a given command quietly and returns
 * the exit status.
 * @param {String} command... command and optional arguments as single or multiple
 * string parameters
 * @param {Object} [options] options object. This may contain a `dir` string
 * property specifying the directory to run the process in and a `env`
 * object property specifying additional environment variable mappings.
 * @returns Number exit status
 */
exports.status = function() {
    var process = createProcess(arguments);
    connect(process, dummyStream(), dummyStream());
    return process.waitFor();
};

function dummyStream() {
    return {
        writable: function() true,
        readable: function() false,
        seekable: function() false,
        write: function() this,
        flush: function() this,
        close: function() this
    }
}

<|endoftext|>


<commit_before>// generated on 2016-02-04 using generator-gulp-webapp 1.1.1
import gulp from 'gulp';
import gulpLoadPlugins from 'gulp-load-plugins';
import browserSync from 'browser-sync';
import del from 'del';
import {
  stream as wiredep
} from 'wiredep';
var jade = require('gulp-jade');
var imageop = require('gulp-image-optimization');
var image = require('gulp-image');
var Imagemin = require('imagemin');
const imagemin = require('gulp-imagemin');
const imageminJpegtran = require('imagemin-jpegtran');

const $ = gulpLoadPlugins();
const reload = browserSync.reload;

gulp.task('styles', () => {
  return gulp.src('app/styles/*.scss')
    .pipe($.plumber())
    .pipe($.sourcemaps.init())
    .pipe($.sass.sync({
      outputStyle: 'expanded',
      precision: 10,
      includePaths: ['.']
    }).on('error', $.sass.logError))
    .pipe($.autoprefixer({
      browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']
    }))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('.tmp/styles'))
    .pipe(reload({
      stream: true
    }));
});

gulp.task('scripts', () => {
  return gulp.src('app/scripts/**/*.js')
    .pipe($.plumber())
    .pipe($.sourcemaps.init())
    .pipe($.babel())
    .pipe($.sourcemaps.write('.'))
    .pipe(gulp.dest('.tmp/scripts'))
    .pipe(reload({
      stream: true
    }));
});

gulp.task('jade', function() {
  return gulp.src('app/index.jade')
    .pipe(jade({pretty: true}))
    .pipe(gulp.dest('.tmp/'));
});

function lint(files, options) {
  return () => {
    return gulp.src(files)
      .pipe(reload({
        stream: true,
        once: true
      }))
      .pipe($.eslint(options))
      .pipe($.eslint.format())
      .pipe($.if(!browserSync.active, $.eslint.failAfterError()));
  };
}
const testLintOptions = {
  env: {
    mocha: true
  }
};

gulp.task('lint', lint('app/scripts/**/*.js'));
gulp.task('lint:test', lint('test/spec/**/*.js', testLintOptions));

gulp.task('html', ['jade','styles', 'scripts'], () => {
  return gulp.src('app/*.html')
    .pipe($.useref({
      searchPath: ['.tmp', 'app', '.']
    }))
    .pipe($.if('*.js', $.uglify()))
    .pipe($.if('*.css', $.cssnano()))
    .pipe($.if('*.html', $.htmlmin({
      collapseWhitespace: true
    })))
    .pipe(gulp.dest('../public'));
});
gulp.task('images', () => {
	return gulp.src('app/images/**/*')
  .pipe(imagemin({
    progressive: true,
    interlaced:true,
    svgoPlugins: [{removeViewBox: false}],
    use: [imageminJpegtran({progressive: true})]
  }))
    .pipe(image({
      pngquant: true,
      optipng: false,
      zopflipng: true,
      advpng: true,
      jpegRecompress: false,
      jpegoptim: true,
      mozjpeg: true,
      gifsicle: true,
      svgo: true
    }))
		.pipe(gulp.dest('../public/images'));
});
gulp.task('fonts', () => {
  return gulp.src(require('main-bower-files')('**/*.{eot,svg,ttf,woff,woff2}', function(err) {})
      .concat('app/fonts/**/*'))
    .pipe(gulp.dest('.tmp/fonts'))
    .pipe(gulp.dest('../public/fonts'));
});

gulp.task('extras', () => {
  return gulp.src([
    'app/*.*',
    '!app/*.html',
    '!app/**/.jade',
    '!app/*.jade'
  ], {
    dot: true
  }).pipe(gulp.dest('../public'));
});

gulp.task('clean', del.bind(null, ['.tmp', '../public']));

gulp.task('serve', ['jade', 'styles', 'scripts', 'fonts'], () => {
  browserSync({
    notify: false,
    port: 9000,
    server: {
      baseDir: ['.tmp', 'app'],
      routes: {
        '/bower_components': 'bower_components'
      }
    }
  });

  gulp.watch([
    'app/*.html',
    '.tmp/scripts/**/*.js',
    'app/images/**/*',
    '.tmp/fonts/**/*'
  ]).on('change', reload);

  gulp.watch('app/styles/**/*.scss', ['styles']);
  gulp.watch('app/*.jade', ['jade']);
  gulp.watch('app/views/*.jade', ['jade']);
  gulp.watch('app/scripts/**/*.js', ['scripts']);
  gulp.watch('app/fonts/**/*', ['fonts']);
  gulp.watch('bower.json', ['wiredep', 'fonts']);
});

gulp.task('serve:dist', () => {
  browserSync({
    notify: false,
    port: 9000,
    server: {
      baseDir: ['../public']
    }
  });
});

gulp.task('serve:test', ['scripts'], () => {
  browserSync({
    notify: false,
    port: 9000,
    ui: false,
    server: {
      baseDir: 'test',
      routes: {
        '/scripts': '.tmp/scripts',
        '/bower_components': 'bower_components'
      }
    }
  });

  gulp.watch('app/scripts/**/*.js', ['scripts']);
  gulp.watch('test/spec/**/*.js').on('change', reload);
  gulp.watch('test/spec/**/*.js', ['lint:test']);
});

// inject bower components
gulp.task('wiredep', () => {
  gulp.src('app/styles/*.scss')
    .pipe(wiredep({
      ignorePath: /^(\.\.\/)+/
    }))
    .pipe(gulp.dest('app/styles'));

  gulp.src('app/*.html')
    .pipe(wiredep({
      exclude: ['bootstrap-sass'],
      ignorePath: /^(\.\.\/)*\.\./
    }))
    .pipe(gulp.dest('app'));
});

gulp.task('build', ['lint', 'html', 'images', 'fonts', 'extras'], () => {
  return gulp.src('dist/**/*').pipe($.size({
    title: 'build',
    gzip: true
  }));
});

gulp.task('default', ['clean'], () => {
  gulp.start('build');
});
<commit_msg>changed back gulpfile<commit_after>// generated on 2016-02-04 using generator-gulp-webapp 1.1.1
import gulp from 'gulp';
import gulpLoadPlugins from 'gulp-load-plugins';
import browserSync from 'browser-sync';
import del from 'del';
import {
  stream as wiredep
} from 'wiredep';
var jade = require('gulp-jade');
var imageop = require('gulp-image-optimization');
var image = require('gulp-image');
var Imagemin = require('imagemin');
const imagemin = require('gulp-imagemin');
const imageminJpegtran = require('imagemin-jpegtran');

const $ = gulpLoadPlugins();
const reload = browserSync.reload;

gulp.task('styles', () => {
  return gulp.src('app/styles/*.scss')
    .pipe($.plumber())
    .pipe($.sourcemaps.init())
    .pipe($.sass.sync({
      outputStyle: 'expanded',
      precision: 10,
      includePaths: ['.']
    }).on('error', $.sass.logError))
    .pipe($.autoprefixer({
      browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']
    }))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('.tmp/styles'))
    .pipe(reload({
      stream: true
    }));
});

gulp.task('scripts', () => {
  return gulp.src('app/scripts/**/*.js')
    .pipe($.plumber())
    .pipe($.sourcemaps.init())
    .pipe($.babel())
    .pipe($.sourcemaps.write('.'))
    .pipe(gulp.dest('.tmp/scripts'))
    .pipe(reload({
      stream: true
    }));
});

gulp.task('jade', function() {
  return gulp.src('app/index.jade')
    .pipe(jade({pretty: true}))
    .pipe(gulp.dest('app/'));
});

function lint(files, options) {
  return () => {
    return gulp.src(files)
      .pipe(reload({
        stream: true,
        once: true
      }))
      .pipe($.eslint(options))
      .pipe($.eslint.format())
      .pipe($.if(!browserSync.active, $.eslint.failAfterError()));
  };
}
const testLintOptions = {
  env: {
    mocha: true
  }
};

gulp.task('lint', lint('app/scripts/**/*.js'));
gulp.task('lint:test', lint('test/spec/**/*.js', testLintOptions));

gulp.task('html', ['jade','styles', 'scripts'], () => {
  return gulp.src('app/*.html')
    .pipe($.useref({
      searchPath: ['.tmp', 'app', '.']
    }))
    .pipe($.if('*.js', $.uglify()))
    .pipe($.if('*.css', $.cssnano()))
    .pipe($.if('*.html', $.htmlmin({
      collapseWhitespace: true
    })))
    .pipe(gulp.dest('../public'));
});
gulp.task('images', () => {
	return gulp.src('app/images/**/*')
  .pipe(imagemin({
    progressive: true,
    interlaced:true,
    svgoPlugins: [{removeViewBox: false}],
    use: [imageminJpegtran({progressive: true})]
  }))
    .pipe(image({
      pngquant: true,
      optipng: false,
      zopflipng: true,
      advpng: true,
      jpegRecompress: false,
      jpegoptim: true,
      mozjpeg: true,
      gifsicle: true,
      svgo: true
    }))
		.pipe(gulp.dest('../public/images'));
});
gulp.task('fonts', () => {
  return gulp.src(require('main-bower-files')('**/*.{eot,svg,ttf,woff,woff2}', function(err) {})
      .concat('app/fonts/**/*'))
    .pipe(gulp.dest('.tmp/fonts'))
    .pipe(gulp.dest('../public/fonts'));
});

gulp.task('extras', () => {
  return gulp.src([
    'app/*.*',
    '!app/*.html',
    '!app/**/.jade',
    '!app/*.jade'
  ], {
    dot: true
  }).pipe(gulp.dest('../public'));
});

gulp.task('clean', del.bind(null, ['.tmp', '../public']));

gulp.task('serve', ['jade', 'styles', 'scripts', 'fonts'], () => {
  browserSync({
    notify: false,
    port: 9000,
    server: {
      baseDir: ['.tmp', 'app'],
      routes: {
        '/bower_components': 'bower_components'
      }
    }
  });

  gulp.watch([
    'app/*.html',
    '.tmp/scripts/**/*.js',
    'app/images/**/*',
    '.tmp/fonts/**/*'
  ]).on('change', reload);

  gulp.watch('app/styles/**/*.scss', ['styles']);
  gulp.watch('app/*.jade', ['jade']);
  gulp.watch('app/views/*.jade', ['jade']);
  gulp.watch('app/scripts/**/*.js', ['scripts']);
  gulp.watch('app/fonts/**/*', ['fonts']);
  gulp.watch('bower.json', ['wiredep', 'fonts']);
});

gulp.task('serve:dist', () => {
  browserSync({
    notify: false,
    port: 9000,
    server: {
      baseDir: ['../public']
    }
  });
});

gulp.task('serve:test', ['scripts'], () => {
  browserSync({
    notify: false,
    port: 9000,
    ui: false,
    server: {
      baseDir: 'test',
      routes: {
        '/scripts': '.tmp/scripts',
        '/bower_components': 'bower_components'
      }
    }
  });

  gulp.watch('app/scripts/**/*.js', ['scripts']);
  gulp.watch('test/spec/**/*.js').on('change', reload);
  gulp.watch('test/spec/**/*.js', ['lint:test']);
});

// inject bower components
gulp.task('wiredep', () => {
  gulp.src('app/styles/*.scss')
    .pipe(wiredep({
      ignorePath: /^(\.\.\/)+/
    }))
    .pipe(gulp.dest('app/styles'));

  gulp.src('app/*.html')
    .pipe(wiredep({
      exclude: ['bootstrap-sass'],
      ignorePath: /^(\.\.\/)*\.\./
    }))
    .pipe(gulp.dest('app'));
});

gulp.task('build', ['lint', 'html', 'images', 'fonts', 'extras'], () => {
  return gulp.src('dist/**/*').pipe($.size({
    title: 'build',
    gzip: true
  }));
});

gulp.task('default', ['clean'], () => {
  gulp.start('build');
});
<|endoftext|>


<commit_before>'use strict'

/**
 * Mine sources in local room, placing energy in storage.
 */

class CityMine extends kernel.process {
  constructor (...args) {
    super(...args)
    this.priority = PRIORITIES_CONSTRUCTION
  }

  getDescriptor () {
    if (this.data.mine) {
      return `${this.data.room} to ${this.data.mine}`
    } else {
      return this.data.room
    }
  }

  getPerformanceDescriptor () {
    if (this.data.mine) {
      return 'remote'
    }
    return false
  }

  main () {
    if (!Game.rooms[this.data.room]) {
      return this.suicide()
    }
    this.room = Game.rooms[this.data.room]

    if (this.data.mine && this.data.mine !== this.data.room) {
      this.remote = true
      this.scout()
      if (!Game.rooms[this.data.mine]) {
        return
      }
      this.mine = Game.rooms[this.data.mine]
      this.underAttack = this.mine.find(FIND_HOSTILE_CREEPS).length > 0
      this.reserveRoom()
    } else {
      this.mine = this.room
    }

    this.sources = this.mine.find(FIND_SOURCES)
    let source
    for (source of this.sources) {
      this.mineSource(source)
    }
  }

  mineSource (source) {
    // Identify where the miner should sit and any container should be built
    const minerPos = source.getMiningPosition()

    // Look for a container
    const containers = _.filter(minerPos.lookFor(LOOK_STRUCTURES), (a) => a.structureType === STRUCTURE_CONTAINER)
    const container = containers.length > 0 ? containers[0] : false

    // Build container if it isn't there
    let construction = false
    if (!container) {
      const constructionSites = minerPos.lookFor(LOOK_CONSTRUCTION_SITES)
      if (constructionSites.length <= 0) {
        this.mine.createConstructionSite(minerPos, STRUCTURE_CONTAINER)
      } else {
        construction = constructionSites[0]
      }
    }

    // Run miners.
    const miners = this.getCluster(`miners_${source.id}`, this.room)

    // Check if a replacement miner is needed and spawn it early
    const minerCreeps = miners.getCreeps()
    let minerQuantity = 1
    if (miners.getClusterSize() === 1 && minerCreeps.length > 0 && minerCreeps[0].ticksToLive < 60) {
      minerQuantity = 2
    }
    if (this.underAttack) {
      minerQuantity = 0
    }

    miners.sizeCluster('miner', minerQuantity, {'priority': 2})
    miners.forEach(function (miner) {
      if (!miner.pos.isNearTo(source)) {
        miner.travelTo(minerPos)
        return
      }
      if (construction && miner.carry[RESOURCE_ENERGY]) {
        miner.build(construction)
        return
      }
      if (source.energy > 0) {
        miner.harvest(source)
      } else if (container && container.hits < container.hitsMax) {
        if (miner.carry[RESOURCE_ENERGY] > 0) {
          miner.repair(container)
        } else if (container.store[RESOURCE_ENERGY] > 0) {
          miner.withdraw(container, RESOURCE_ENERGY)
        }
      }
    })

    let storage = false
    if (this.room.storage) {
      storage = this.room.storage
    } else if (this.room.terminal) {
      storage = this.room.terminal
    } else if (this.remote) {
      if (!this.room.structure) {
        return
      }

      const containers = this.room.structure[STRUCTURE_CONTAINER]

      if (containers && containers.length > 0) {
        if (containers.length > 1) {
          containers.sort((a, b) => a.store[RESOURCE_ENERGY] - b.store[RESOURCE_ENERGY])
        }
        storage = containers[0]
      } else {
        const spawns = this.room.structure[STRUCTURE_SPAWN]
        if (spawns) {
          if (spawns.length > 1) {
            spawns.sort((a, b) => a.energy - b.energy)
          }
          storage = spawns[0]
        }
      }
    }

    // If using containers spawn haulers
    if (!container || !storage) {
      return
    }

    const haulers = this.getCluster(`haulers_${source.id}`, this.room)
    let distance = 50
    if (!this.underAttack && this.mine.name === this.room.name) {
      haulers.sizeCluster('hauler', 1)
    } else if (!this.underAttack) {
      if (!this.data.ssp) {
        this.data.ssp = {}
      }
      if (!this.data.ssp[source.id]) {
        if (this.room.storage) {
          this.data.ssp[source.id] = this.room.findPath(this.room.storage, source, {
            ignoreCreeps: true,
            maxOps: 6000
          }).length
        }
      }
      distance = this.data.ssp[source.id] ? this.data.ssp[source.id] : 80
      const carryAmount = (Math.ceil((distance * 20) / 100) * 100) + 200
      const carryCost = BODYPART_COST['move'] + BODYPART_COST['carry']
      const maxEnergy = carryCost * (MAX_CREEP_SIZE / 2)
      let energy = (carryAmount / CARRY_CAPACITY) * carryCost // 50 carry == 1m1c == 100 energy
      let quantity = 1
      if (energy > maxEnergy) {
        quantity = 2
        energy = maxEnergy
      }
      haulers.sizeCluster('hauler', quantity, {'energy': maxEnergy})
    }

    haulers.forEach(function (hauler) {
      if (hauler.ticksToLive < (distance + 30)) {
        return hauler.recycle()
      }
      if (hauler.getCarryPercentage() > 0.8) {
        if (!hauler.pos.isNearTo(storage)) {
          hauler.travelTo(storage)
        } else {
          hauler.transferAll(storage, RESOURCE_ENERGY)
        }
        return
      }
      if (!hauler.pos.isNearTo(container)) {
        hauler.travelTo(container)
      }
      if (hauler.pos.isNearTo(container)) {
        if (container.store[RESOURCE_ENERGY]) {
          hauler.withdraw(container, RESOURCE_ENERGY)
        }
      }
    })
  }

  scout () {
    const center = new RoomPosition(25, 25, this.data.mine)
    const quantity = Game.rooms[this.data.mine] ? 0 : 1
    const scouts = this.getCluster(`scout`, this.room)
    scouts.sizeCluster('spook', quantity)
    scouts.forEach(function (scout) {
      if (scout.room.name === center.roomName) {
        if (scout.pos.getRangeTo(center) <= 20) {
          return
        }
      }
      scout.travelTo(center, {range: 20})
    })
  }

  reserveRoom () {
    if (this.underAttack) {
      return
    }
    const controller = this.mine.controller
    const timeout = controller.reservation ? controller.reservation.ticksToEnd : 0
    let quantity = 0
    if (timeout < 3500) {
      quantity = Math.min(this.room.getRoomSetting('RESERVER_COUNT'), controller.pos.getSteppableAdjacent().length)
    }

    const reservists = this.getCluster(`reservists`, this.room)
    reservists.sizeCluster('reservist', quantity)
    reservists.forEach(function (reservist) {
      if (!reservist.pos.isNearTo(controller)) {
        reservist.travelTo(controller)
      } else if (!controller.reservation || timeout < (CONTROLLER_RESERVE_MAX - 5)) {
        reservist.reserveController(controller)
      }
    })
  }
}

module.exports = CityMine
<commit_msg>The underlying problem seem to be found, typo in the extension name.<commit_after>'use strict'

/**
 * Mine sources in local room, placing energy in storage.
 */

class CityMine extends kernel.process {
  constructor (...args) {
    super(...args)
    this.priority = PRIORITIES_CONSTRUCTION
  }

  getDescriptor () {
    if (this.data.mine) {
      return `${this.data.room} to ${this.data.mine}`
    } else {
      return this.data.room
    }
  }

  getPerformanceDescriptor () {
    if (this.data.mine) {
      return 'remote'
    }
    return false
  }

  main () {
    if (!Game.rooms[this.data.room]) {
      return this.suicide()
    }
    this.room = Game.rooms[this.data.room]

    if (this.data.mine && this.data.mine !== this.data.room) {
      this.remote = true
      this.scout()
      if (!Game.rooms[this.data.mine]) {
        return
      }
      this.mine = Game.rooms[this.data.mine]
      this.underAttack = this.mine.find(FIND_HOSTILE_CREEPS).length > 0
      this.reserveRoom()
    } else {
      this.mine = this.room
    }

    this.sources = this.mine.find(FIND_SOURCES)
    let source
    for (source of this.sources) {
      this.mineSource(source)
    }
  }

  mineSource (source) {
    // Identify where the miner should sit and any container should be built
    const minerPos = source.getMiningPosition()

    // Look for a container
    const containers = _.filter(minerPos.lookFor(LOOK_STRUCTURES), (a) => a.structureType === STRUCTURE_CONTAINER)
    const container = containers.length > 0 ? containers[0] : false

    // Build container if it isn't there
    let construction = false
    if (!container) {
      const constructionSites = minerPos.lookFor(LOOK_CONSTRUCTION_SITES)
      if (constructionSites.length <= 0) {
        this.mine.createConstructionSite(minerPos, STRUCTURE_CONTAINER)
      } else {
        construction = constructionSites[0]
      }
    }

    // Run miners.
    const miners = this.getCluster(`miners_${source.id}`, this.room)

    // Check if a replacement miner is needed and spawn it early
    const minerCreeps = miners.getCreeps()
    let minerQuantity = 1
    if (miners.getClusterSize() === 1 && minerCreeps.length > 0 && minerCreeps[0].ticksToLive < 60) {
      minerQuantity = 2
    }
    if (this.underAttack) {
      minerQuantity = 0
    }

    miners.sizeCluster('miner', minerQuantity, {'priority': 2})
    miners.forEach(function (miner) {
      if (!miner.pos.isNearTo(source)) {
        miner.travelTo(minerPos)
        return
      }
      if (construction && miner.carry[RESOURCE_ENERGY]) {
        miner.build(construction)
        return
      }
      if (source.energy > 0) {
        miner.harvest(source)
      } else if (container && container.hits < container.hitsMax) {
        if (miner.carry[RESOURCE_ENERGY] > 0) {
          miner.repair(container)
        } else if (container.store[RESOURCE_ENERGY] > 0) {
          miner.withdraw(container, RESOURCE_ENERGY)
        }
      }
    })

    let storage = false
    if (this.room.storage) {
      storage = this.room.storage
    } else if (this.room.terminal) {
      storage = this.room.terminal
    } else if (this.remote) {
      const containers = this.room.structures[STRUCTURE_CONTAINER]

      if (containers && containers.length > 0) {
        if (containers.length > 1) {
          containers.sort((a, b) => a.store[RESOURCE_ENERGY] - b.store[RESOURCE_ENERGY])
        }
        storage = containers[0]
      } else {
        const spawns = this.room.structures[STRUCTURE_SPAWN]
        if (spawns) {
          if (spawns.length > 1) {
            spawns.sort((a, b) => a.energy - b.energy)
          }
          storage = spawns[0]
        }
      }
    }

    // If using containers spawn haulers
    if (!container || !storage) {
      return
    }

    const haulers = this.getCluster(`haulers_${source.id}`, this.room)
    let distance = 50
    if (!this.underAttack && this.mine.name === this.room.name) {
      haulers.sizeCluster('hauler', 1)
    } else if (!this.underAttack) {
      if (!this.data.ssp) {
        this.data.ssp = {}
      }
      if (!this.data.ssp[source.id]) {
        if (this.room.storage) {
          this.data.ssp[source.id] = this.room.findPath(this.room.storage, source, {
            ignoreCreeps: true,
            maxOps: 6000
          }).length
        }
      }
      distance = this.data.ssp[source.id] ? this.data.ssp[source.id] : 80
      const carryAmount = (Math.ceil((distance * 20) / 100) * 100) + 200
      const carryCost = BODYPART_COST['move'] + BODYPART_COST['carry']
      const maxEnergy = carryCost * (MAX_CREEP_SIZE / 2)
      let energy = (carryAmount / CARRY_CAPACITY) * carryCost // 50 carry == 1m1c == 100 energy
      let quantity = 1
      if (energy > maxEnergy) {
        quantity = 2
        energy = maxEnergy
      }
      haulers.sizeCluster('hauler', quantity, {'energy': maxEnergy})
    }

    haulers.forEach(function (hauler) {
      if (hauler.ticksToLive < (distance + 30)) {
        return hauler.recycle()
      }
      if (hauler.getCarryPercentage() > 0.8) {
        if (!hauler.pos.isNearTo(storage)) {
          hauler.travelTo(storage)
        } else {
          hauler.transferAll(storage, RESOURCE_ENERGY)
        }
        return
      }
      if (!hauler.pos.isNearTo(container)) {
        hauler.travelTo(container)
      }
      if (hauler.pos.isNearTo(container)) {
        if (container.store[RESOURCE_ENERGY]) {
          hauler.withdraw(container, RESOURCE_ENERGY)
        }
      }
    })
  }

  scout () {
    const center = new RoomPosition(25, 25, this.data.mine)
    const quantity = Game.rooms[this.data.mine] ? 0 : 1
    const scouts = this.getCluster(`scout`, this.room)
    scouts.sizeCluster('spook', quantity)
    scouts.forEach(function (scout) {
      if (scout.room.name === center.roomName) {
        if (scout.pos.getRangeTo(center) <= 20) {
          return
        }
      }
      scout.travelTo(center, {range: 20})
    })
  }

  reserveRoom () {
    if (this.underAttack) {
      return
    }
    const controller = this.mine.controller
    const timeout = controller.reservation ? controller.reservation.ticksToEnd : 0
    let quantity = 0
    if (timeout < 3500) {
      quantity = Math.min(this.room.getRoomSetting('RESERVER_COUNT'), controller.pos.getSteppableAdjacent().length)
    }

    const reservists = this.getCluster(`reservists`, this.room)
    reservists.sizeCluster('reservist', quantity)
    reservists.forEach(function (reservist) {
      if (!reservist.pos.isNearTo(controller)) {
        reservist.travelTo(controller)
      } else if (!controller.reservation || timeout < (CONTROLLER_RESERVE_MAX - 5)) {
        reservist.reserveController(controller)
      }
    })
  }
}

module.exports = CityMine
<|endoftext|>


<commit_before>
importPackage(com.google.gridworks.rdf.commands);

/*
 * Function invoked to initialize the extension.
 */
function init() {
    /*
     *  Attach an rdf schema to each project.
     */
    Packages.com.google.gridworks.model.Project.registerOverlayModel(
        "rdfSchema",
        Packages.com.google.gridworks.rdf.RdfSchema);

    /*
     *  Operations
     */
    Packages.com.google.gridworks.operations.OperationRegistry.register(
        "save-rdf-schema", Packages.com.google.gridworks.rdf.operations.SaveRdfSchemaOperation);

    /*
     *  Exporters
     */
    var ExporterRegistry = Packages.com.google.gridworks.exporters.ExporterRegistry;
    var RdfExporter = Packages.com.google.gridworks.rdf.exporters.RdfExporter;

    ExporterRegistry.registerExporter("rdf", new RdfExporter("RDF/XML"));
    ExporterRegistry.registerExporter("n3", new RdfExporter("N3"));

    /*
     *  GEL Functions and Binders
     */
    Packages.com.google.gridworks.gel.ControlFunctionRegistry.registerFunction(
        "urlify", new Packages.com.google.gridworks.rdf.expr.functions.strings.Urlify());

    Packages.com.google.gridworks.expr.ExpressionUtils.registerBinder(
        new Packages.com.google.gridworks.rdf.expr.RdfBinder());

    /*
     *  Commands
     */
    var GridworksServlet = Packages.com.google.gridworks.GridworksServlet;
    GridworksServlet.registerCommand(module, "save-rdf-schema", new SaveRdfSchemaCommand());
    GridworksServlet.registerCommand(module, "preview-rdf", new PreviewRdfCommand());
    GridworksServlet.registerCommand(module, "save-baseURI", new SaveBaseURI());
    GridworksServlet.registerCommand(module, "suggest-term", new SuggestTermCommand());
    GridworksServlet.registerCommand(module, "import-vocabulary", new ImportVocabularyCommand());
    GridworksServlet.registerCommand(module, "list-vocabularies", new ListVocabulariesCommand());
    GridworksServlet.registerCommand(module, "delete-vocabulary", new DeleteVocabularyCommand());

    /*
     *  Client-side Resources
     */
    var ClientSideResourceManager = Packages.com.google.gridworks.ClientSideResourceManager;

    // Script files to inject into /project page
    ClientSideResourceManager.addPaths(
        "project/scripts",
        module,
        [
            "scripts/menu-bar-extensions.js",
            "scripts/rdf-schema-alignment.js",
            "scripts/rdf-schema-alignment-ui-node.js",
            "scripts/rdf-schema-alignment-ui-link.js",
            "scripts/suggestterm.suggest.js"
        ]
    );

    // Style files to inject into /project page
    ClientSideResourceManager.addPaths(
        "project/styles",
        module,
        [
            "styles/rdf-schema-alignment-dialog.css",
        ]
    );
}
<commit_msg>Updated to include the module while registering operations.<commit_after>
importPackage(com.google.gridworks.rdf.commands);

/*
 * Function invoked to initialize the extension.
 */
function init() {
    /*
     *  Attach an rdf schema to each project.
     */
    Packages.com.google.gridworks.model.Project.registerOverlayModel(
        "rdfSchema",
        Packages.com.google.gridworks.rdf.RdfSchema);

    /*
     *  Operations
     */
    Packages.com.google.gridworks.operations.OperationRegistry.registerOperation(
        module, "save-rdf-schema", Packages.com.google.gridworks.rdf.operations.SaveRdfSchemaOperation);

    /*
     *  Exporters
     */
    var ExporterRegistry = Packages.com.google.gridworks.exporters.ExporterRegistry;
    var RdfExporter = Packages.com.google.gridworks.rdf.exporters.RdfExporter;

    ExporterRegistry.registerExporter("rdf", new RdfExporter("RDF/XML"));
    ExporterRegistry.registerExporter("n3", new RdfExporter("N3"));

    /*
     *  GEL Functions and Binders
     */
    Packages.com.google.gridworks.gel.ControlFunctionRegistry.registerFunction(
        "urlify", new Packages.com.google.gridworks.rdf.expr.functions.strings.Urlify());

    Packages.com.google.gridworks.expr.ExpressionUtils.registerBinder(
        new Packages.com.google.gridworks.rdf.expr.RdfBinder());

    /*
     *  Commands
     */
    var GridworksServlet = Packages.com.google.gridworks.GridworksServlet;
    GridworksServlet.registerCommand(module, "save-rdf-schema", new SaveRdfSchemaCommand());
    GridworksServlet.registerCommand(module, "preview-rdf", new PreviewRdfCommand());
    GridworksServlet.registerCommand(module, "save-baseURI", new SaveBaseURI());
    GridworksServlet.registerCommand(module, "suggest-term", new SuggestTermCommand());
    GridworksServlet.registerCommand(module, "import-vocabulary", new ImportVocabularyCommand());
    GridworksServlet.registerCommand(module, "list-vocabularies", new ListVocabulariesCommand());
    GridworksServlet.registerCommand(module, "delete-vocabulary", new DeleteVocabularyCommand());

    /*
     *  Client-side Resources
     */
    var ClientSideResourceManager = Packages.com.google.gridworks.ClientSideResourceManager;

    // Script files to inject into /project page
    ClientSideResourceManager.addPaths(
        "project/scripts",
        module,
        [
            "scripts/menu-bar-extensions.js",
            "scripts/rdf-schema-alignment.js",
            "scripts/rdf-schema-alignment-ui-node.js",
            "scripts/rdf-schema-alignment-ui-link.js",
            "scripts/suggestterm.suggest.js"
        ]
    );

    // Style files to inject into /project page
    ClientSideResourceManager.addPaths(
        "project/styles",
        module,
        [
            "styles/rdf-schema-alignment-dialog.css",
        ]
    );
}
<|endoftext|>


<commit_before>define([
  'underscore',
  'backbone'
], function (_, Backbone) {
  'use strict';

  var AddressModel = Backbone.Model.extend({
    urlRoot: 'http://localhost:3000/rez/addresses',

    defaults: {
      building_number: '',
      street_address: '',
      secondary_address: '',
      city: '',
      state: '',
      zip_code: '',
      county: '',
      country: ''
    },

    parse: function(response) {
      if (response.address) {
        return response.address;
      } else {
        return response;
      }
    }
  });

  return AddressModel;
});
<commit_msg>correction<commit_after>define([
  'underscore',
  'backbone'
], function (_, Backbone) {
  'use strict';

  var AddressModel = Backbone.Model.extend({
    urlRoot: 'http://localhost:3000/rez/addresses',

    defaults: {
      building_number: '',
      street_name: '',
      secondary_address: '',
      city: '',
      state: '',
      zip_code: '',
      county: '',
      country: ''
    },

    parse: function(response) {
      if (response.address) {
        return response.address;
      } else {
        return response;
      }
    }
  });

  return AddressModel;
});
<|endoftext|>


<commit_before>//using axios as an api utility
import axios from 'axios';
import apiKey from './apiKey';
//setting API key to variables

var _APIURL = "http://api.openweathermap.org/data/2.5/";
var _APIKEY = apiKey;

//This utility will provide access to the open weather API.
// From openweather documents: 'To make the result more accurate just put the city name and country divided by comma.'
// Example
// http://api.openweathermap.org/data/2.5/weather?q=tarrytown&type=accurate&unit=celcius&appid=b714ec74bbab5650795063cb0fdf5fbe
//Unit is metric because... when I go to Norway I need to use metric! (celcius is used in global aviation also. Yes even the US)
//function to provide endpoint parameters
var getQueryStringData = function(city){
	return {
		q : city,
		type: 'accurate',
    units: 'metric',
		APPID: _APIKEY,
	}
};

// prepRouteParams is invoked in makeWeatherURL function
// Object.keys returns an array
// .map goes through Object.keys array and applies a callback to each key
// return a string of the key and value
// .join will join each string returned from every iteration of .map
var prepRouteParams = function(queryStringData){
	return Object.keys(queryStringData)
		.map(function(key){
			return key + '=' + encodeURIComponent(queryStringData[key]);
		}).join('&')
};

//concats different string components to create a URL
var makeWeatherURL = function(type, queryStringData){
	return _APIURL + type + '?' + prepRouteParams(queryStringData);
};

//Run API get request with axios
var getCurrentWeather = function(city){
	var queriedString = getQueryStringData(city); //JS object from above
	var url = makeWeatherURL("weather", queriedString);
	//axios performs get request to endpoint
	return axios.get(url)
		//Promise to provide success or fail results
		//success provides data as a JSON object
		.then(function(data){
				//Send data back to where it was called
				return data
			})
		//.catch provides error description
		.catch(function(error){
			console.warn("Error with weatherApi" + error)
			return error
		})
};

//export json data as getCurrentWeather
module.exports = {
	getCurrentWeather: getCurrentWeather
};
<commit_msg>Update weatherApi.js<commit_after>//using axios as an api utility
import axios from 'axios';
import apiKey from './apiKey';
//setting API key to variables

var _APIURL = "http://api.openweathermap.org/data/2.5/";
var _APIKEY = apiKey;

//This utility will provide access to the open weather API.
// From openweather documents: 'To make the result more accurate just put the city name and country divided by comma.'
// Example
// http://api.openweathermap.org/data/2.5/weather?q=tarrytown&type=accurate&unit=celcius&appid=b714ec74bbab5650795063cb0fdf5fbe
//Unit is metric because... when I go to Norway I need to use metric! (celcius is used in global aviation also. Yes even the US)
//function to provide endpoint parameters
var getQueryStringData = function(city){
	return {
		q : city,
		type: 'accurate',
    units: 'metric',
		APPID: _APIKEY,
	}
};

// prepRouteParams is invoked in makeWeatherURL function
// Object.keys returns an array
// .map goes through Object.keys array and applies a callback to each key
// return a string of the key and value
// .join will join each string returned from every iteration of .map
var prepRouteParams = function(queryStringData){
	return Object.keys(queryStringData)
		.map(function(key){
			return key + '=' + encodeURIComponent(queryStringData[key]);
		}).join('&')
};

//concats different string components to create a URL
var makeWeatherURL = function(type, queryStringData){
	return _APIURL + type + '?' + prepRouteParams(queryStringData);
};

//Run API get request with axios
var getCurrentWeather = function(city){
	var queriedString = getQueryStringData(city); //JS object from above
	var url = makeWeatherURL("weather", queriedString);
	//axios performs get request to endpoint
	return axios.get(url)
		//Promise to provide success or fail results
		//success provides data as a JSON object
		.then(function(data){
				//Send data back to where it was called
				return data
			})
		//.catch provides error description
		.catch(function(error){
			console.warn("Error with weatherApi" + error)
			return error
		})
};

//export json data as getCurrentWeather
module.exports = {
	getCurrentWeather: getCurrentWeather
};
<|endoftext|>


<commit_before>Seed({
		name : "Mold.Lib.Template",
		dna : "class",
		test : "Mold.Test.Lib.Template",
		include : [
			{ Builder : "Mold.Lib.VDom.Builder" },
			{ Ajax : "Mold.Lib.Ajax" },
			{ MultiLineString :  "Mold.Lib.MultiLineString" },
			{ Path : "Mold.Lib.Path" },
			{ Promise : "Mold.Lib.Promise" },
		]
	},
	function(markup, config){

		config = config || {};

		var ajax = new Ajax();
		var _tree = false;
		var _parseAsString= config.parseAsString || false;

		var undefined;

		//load the
		var _template = new Promise(function(resolve, reject){
			var data = markup;
			if(typeof markup === "function"){
				data = MultiLineString(markup)
				resolve(data);
				return;
			}

			if(Path.is(markup)){
				ajax
					.get(markup)
					.then(function(data){
						resolve(data);
					})
					.fail(function(error){
						reject(error);
					});
			}else{
				resolve(data);
			}
		});

		var _templateTree = new Promise(function(resolve, reject){
			_template.then(function(data){
				_tree = new Builder(data, this);
				resolve(_tree);
			})
		});

		/**
		 * @method  _connector
		 * @private
		 * @description collection of methods to bind a model to the template
		 * @type {Object}
		 */
		var _connector = {
			renderTimer : false,
			reRender : function(tree){
				clearTimeout(_connector.renderTimer);
				_connector.renderTimer = setTimeout(function(){
					if(!_parseAsString){
						tree.render();
					}else{
						tree.renderString();
					}
				}, 2);

			},
			updateChildren : function(children, data, tree){
				if(Mold.isObject(children)){
					for(var childName in children){
						_connector.updateChild(children[childName], data[childName], tree, childName)
					}
				}else{
					throw new Error("only object implemented in _connector.updateChildren")
				}
			},
			updateChild : function(child, data, tree, name){
				//if blocknode
				if(child.type === 2){
					var blockData = {};
					blockData[name] = data;
					//console.log("set data", name, data)
					child.setData(blockData);
				}else{
					child.setData(data);
				}
				_connector.reRender(tree);

			},
			watchObjectProp : function(model, subTree, properties, path, tree, name){
				model.on(path + ".changed", function(e){
					switch(e.data.type){
						case "update":
						case "splice":
							//console.log("property changed", path + ".changed", properties, subTree)
							//if subtree is an array update all childnodes
							//console.log("SPLCIE", e.data)
							if(Mold.isArray(subTree)){
								var i = 0, len = subTree.length;
								for(; i < len; i++){
									_connector.updateChild(subTree[i], e.data.object, tree, name);
									//if(e.data.type)
									_connect(model, subTree[i], properties, path, tree);
								}
							}else if(subTree.children && subTree.children[name]){
								_connector.updateChild(subTree, e.data.object, tree, name);
							}
							break;
						default:
							throw new Error("type " + e.data.type + " for watchObjectProp is not implemented!");
					}

				});
			},
			watchArray : function(model, subTree, properties, path, tree){
				model.on(path + ".changed", function(e){
					switch(e.data.type){
						case "update":
							if(Mold.isObject(e.data.object)){
								_connector.updateChildren(subTree, e.data.object, tree)
							}else{
								throw new Error("e.data.object is no Object, not Implemented");
							}
							break;
						default:
							throw new Error("method " + e.data.type + " for watchArray is not implemented!");
					}
				});
			},
			parseArray : function(model, subTree, properties, path, tree){
				var i = 0, len = subTree.children.length;
				for(; i < len; i++){
					var newPath = path + "." + i;
					//console.log("watch", newPath)

					_connector.watchArray(model, subTree.children[i], properties[0], newPath, tree)
					_connect(model, subTree.children[i], properties[0], newPath, tree)
				}
			},
			parseObject : function(model, subTree, properties, path, tree){
				for(var prop in properties){
					//_connector.watchObject
					var newPath = path + "." + prop;
					if(subTree.children){
						if(subTree.children[prop]){
							_connector.watchObjectProp(model, subTree.children[prop], properties[prop], newPath, tree, prop)
						}
					}else{
						_connector.watchObjectProp(model, subTree[prop], properties[prop], newPath, tree, prop)
						//throw new Error("subTree children is not defined, in _connector.parseObject!");
					}
				}
			}
		}

		var _connect = function(model, subTree, properties, path, tree){
			if(Mold.isArray(properties)){
				_connector.parseArray(model, subTree, properties, path, tree);
			}else if(Mold.isObject(properties)){
				_connector.parseObject(model, subTree, properties, path, tree);
			}
		}

		this.publics = {
			snatch : function(){

			},
			connect : function(model){
				_templateTree.then(function(tree){
					_connect(model, tree.dom, model.getProperties(), "data", tree);
					window.setTimeout(function(){
						model.triggerUpdate();
					}, 50)

				});
			},
			setData : function(data){
				_templateTree.then(function(tree){
					tree.dom.setData(data);
					if(!_parseAsString){
						tree.render();
					}else{
						tree.renderString();
					}
				});
			},
			appendTo : function(element){
				_templateTree.then(function(tree){
					element.appendChild(tree.render())
				})
			},
			getString : function(data){
				return new Promise(function(resolve, reject){
					_templateTree.then(function(tree){
						if(data){
							tree.dom.setData(data);
						}
						resolve(tree.renderString());
					})
				});
			},
			get : _templateTree,
			tree : _templateTree
		}
	}
)<commit_msg>add "renderd" event<commit_after>Seed({
		name : "Mold.Lib.Template",
		dna : "class",
		test : "Mold.Test.Lib.Template",
		include : [
			{ Builder : "Mold.Lib.VDom.Builder" },
			{ Ajax : "Mold.Lib.Ajax" },
			{ MultiLineString :  "Mold.Lib.MultiLineString" },
			{ Path : "Mold.Lib.Path" },
			{ Promise : "Mold.Lib.Promise" },
			{ Event : "Mold.Lib.Event" },
		]
	},
	function(markup, config){

		config = config || {};

		var ajax = new Ajax();
		var _tree = false;
		var _that = this;
		var _parseAsString= config.parseAsString || false;
		var undefined;

		Mold.mixin(this, new Event(this));

		//load the
		var _template = new Promise(function(resolve, reject){
			var data = markup;
			if(typeof markup === "function"){
				data = MultiLineString(markup)
				resolve(data);
				return;
			}

			if(Path.is(markup)){
				ajax
					.get(markup)
					.then(function(data){
						resolve(data);
					})
					.fail(function(error){
						reject(error);
					});
			}else{
				resolve(data);
			}
		});

		var _templateTree = new Promise(function(resolve, reject){
			_template.then(function(data){
				_tree = new Builder(data, this);
				resolve(_tree);
				_that.trigger("ready");
			})
		});

		/**
		 * @method  _connector
		 * @private
		 * @description collection of methods to bind a model to the template
		 * @type {Object}
		 */
		var _connector = {
			renderTimer : false,
			reRender : function(tree){
				clearTimeout(_connector.renderTimer);
				_connector.renderTimer = setTimeout(function(){
					if(!_parseAsString){
						tree.render();
					}else{
						tree.renderString();
					}
					_that.trigger("renderd", { tree : _tree });
				}, 2);

			},
			updateChildren : function(children, data, tree){
				if(Mold.isObject(children)){
					for(var childName in children){
						_connector.updateChild(children[childName], data[childName], tree, childName)
					}
				}else{
					throw new Error("only object implemented in _connector.updateChildren")
				}
			},
			updateChild : function(child, data, tree, name){
				//if blocknode
				if(child.type === 2){
					var blockData = {};
					blockData[name] = data;
					//console.log("set data", name, data)
					child.setData(blockData);
				}else{
					child.setData(data);
				}
				_connector.reRender(tree);

			},
			watchObjectProp : function(model, subTree, properties, path, tree, name){
				model.on(path + ".changed", function(e){
					switch(e.data.type){
						case "update":
						case "splice":
							//if subtree is an array update all childnodes
							if(Mold.isArray(subTree)){
								var i = 0, len = subTree.length;
								for(; i < len; i++){
									_connector.updateChild(subTree[i], e.data.object, tree, name);
									//if(e.data.type)
									_connect(model, subTree[i], properties, path, tree);
								}
							}else if(subTree.children && subTree.children[name]){
								_connector.updateChild(subTree, e.data.object, tree, name);
							}
							break;
						default:
							throw new Error("type " + e.data.type + " for watchObjectProp is not implemented!");
					}

				});
			},
			watchArray : function(model, subTree, properties, path, tree){
				model.on(path + ".changed", function(e){
					switch(e.data.type){
						case "update":
							if(Mold.isObject(e.data.object)){
								_connector.updateChildren(subTree, e.data.object, tree)
							}else{
								throw new Error("e.data.object is no Object, not Implemented");
							}
							break;
						default:
							throw new Error("method " + e.data.type + " for watchArray is not implemented!");
					}
				});
			},
			parseArray : function(model, subTree, properties, path, tree){
				var i = 0, len = subTree.children.length;
				for(; i < len; i++){
					var newPath = path + "." + i;
					//console.log("watch", newPath)

					_connector.watchArray(model, subTree.children[i], properties[0], newPath, tree)
					_connect(model, subTree.children[i], properties[0], newPath, tree)
				}
			},
			parseObject : function(model, subTree, properties, path, tree){
				for(var prop in properties){
					//_connector.watchObject
					var newPath = path + "." + prop;
					if(subTree.children){
						if(subTree.children[prop]){
							_connector.watchObjectProp(model, subTree.children[prop], properties[prop], newPath, tree, prop)
						}
					}else{
						_connector.watchObjectProp(model, subTree[prop], properties[prop], newPath, tree, prop)
						//throw new Error("subTree children is not defined, in _connector.parseObject!");
					}
				}
			}
		}

		var _connect = function(model, subTree, properties, path, tree){
			if(Mold.isArray(properties)){
				_connector.parseArray(model, subTree, properties, path, tree);
			}else if(Mold.isObject(properties)){
				_connector.parseObject(model, subTree, properties, path, tree);
			}
		}

		this.publics = {
			snatch : function(){

			},
			connect : function(model){
				_templateTree.then(function(tree){
					_connect(model, tree.dom, model.getProperties(), "data", tree);
					window.setTimeout(function(){
						model.triggerUpdate();
					}, 50)

				});
			},
			setData : function(data){
				_templateTree.then(function(tree){
					tree.dom.setData(data);
					if(!_parseAsString){
						tree.render();
					}else{
						tree.renderString();
					}
					_that.trigger("renderd", { tree : _tree });
				});
			},
			appendTo : function(element){
				_templateTree.then(function(tree){
					element.appendChild(tree.render())
					_that.trigger("renderd", { tree : _tree });
				})
			},
			getString : function(data){
				return new Promise(function(resolve, reject){
					_templateTree.then(function(tree){
						if(data){
							tree.dom.setData(data);
						}
						resolve(tree.renderString());
						_that.trigger("renderd", { tree : _tree });
					})
				});
			},
			get : _templateTree,
			tree : _templateTree
		}
	}
)<|endoftext|>


<commit_before>var _ = require('underscore');
var async = require('async');
var crypto = require('crypto');
var fs = require('fs');
var rmRf = require('rimraf');
var imagemagick = require('node-imagemagick');

module.exports = function() {
  return new uploadfs();
}

function uploadfs() {
  var tempPath;
  var backend;
  var imageSizes;
  var orientOriginals = true;
  var self = this;
  self.init = function(options, callback) {
    if (!options.backend) {
      return callback("backend must be specified");
    }
    // Load standard backends, by name
    if (typeof(options.backend) === 'string') {
      options.backend = require(__dirname + '/' + options.backend + '.js');
    }
    // Custom backends can be passed as objects
    backend = options.backend;
    imageSizes = options.imageSizes ? options.imageSizes : [];
    if (typeof(options.orientOriginals) !== 'undefined') {
      orientOriginals = options.orientOriginals;
    }

    async.series([ createTempFolderIfNeeded, backendInit ], callback);

    function createTempFolderIfNeeded(callback) {
      if (!imageSizes.length) {
        return callback();
      }
      if (!options.tempPath) {
        return callback("options.tempPath not set");
      }
      tempPath = options.tempPath;
      fs.exists(options.tempPath, function(exists) {
        if (!exists) {
          return fs.mkdir(options.tempPath, callback);
        } else {
          return callback(null);
        }
      });
    }

    function backendInit(callback) {
      return backend.init(options, callback);
    }
  },

  self.copyIn = function(localPath, path, options, callback) {
    if (typeof(options) === 'function') {
      callback = options;
      options = {};
    }
    return backend.copyIn(localPath, path, options, callback);
  },

  /**
   * Copy an image into uploadfs. Scaled versions as defined by the imageSizes option
   * at init() time are copied into uploadfs as follows:
   *
   * If 'path' is '/me' and sizes with names 'small', 'medium' and 'large'
   * were defined at init() time, the scaled versions will be:
   *
   * '/me.small.jpg', '/me.medium.jpg', '/me.large.jpg'
   *
   * And the original file will be copied to:
   *
   * '/me.jpg'
   *
   * Note that a file extension is added automatically. If you provide a
   * file extension in 'path' it will be honored when copying the original only.
   * The scaled versions will get appropriate extensions for their format
   * as detected by Imagemagick.
   *
   * If there is no error the second argument passed to the callback will
   * be an object with a 'basePath' property containing your original path
   * with the file extension removed and an 'extension' property containing
   * the automatically added file extension, as a convenience for locating the
   * original and scaled versions just by adding .jpg, .small.jpg, .medium.jpg,
   * etc.
   *
   * Scaled versions have the same file format as the original and are no wider
   * or taller than specified by the width and height properties of the
   * corresponding size, with the aspect ratio always being preserved.
   * If options.copyOriginal is explicitly false, the original image is
   * not copied into uploadfs at all.
   *
   * Image scaling is performed with imagemagick, which must be installed
   * (note that Heroku provides it). In no case is an image ever scaled to
   * be larger than the original. Scaled versions of images with an orientation
   * hint, such as iPhone photographs, are automatically rotated by imagemagick
   * so that they will display properly in web browsers.
   */

  self.copyImageIn = function(localPath, path, options, callback) {
    if (typeof(options) === 'function') {
      callback = options;
      options = {};
    }

    async.series([ identify, makeTempFolder, copyOriginal, scaleAndCopy ], cleanup);

    var context = {};

    function identify(callback) {
      imagemagick.identify(localPath, function(err, info) {
        if (err) {
          return callback(err);
        }
        context.info = info;

        // Imagemagick gives us the raw width and height, but we're
        // going to orient the scaled images and, in most cases, the
        // original image so that they actually display properly in
        // web browsers. So return the oriented width and height
        // to the developer. Also return the original width and
        // height just to be thorough, but use the obvious names
        // for the obvious thing

        context.info.originalWidth = context.info.width;
        context.info.originalHeight = context.info.height;
        var o = context.info.orientation;
        if ((o === 'LeftTop') || (o === 'RightTop') || (o === 'RightBottom') || (o === 'LeftBottom')) {
          var t = context.info.width;
          context.info.width = context.info.height;
          context.info.height = t;
        }

        context.tempName = generateId();
        // File extension from format, which is GIF, JPEG, PNG
        context.extension = info.format.toLowerCase();
        if (context.extension === 'jpeg') {
          context.extension = 'jpg';
        }
        callback(null);
      });
    }

    function makeTempFolder(callback) {
      // Create destination folder
      if (imageSizes.length) {
        context.tempFolder = tempPath + '/' + context.tempName;
        fs.mkdir(context.tempFolder, callback);
      } else {
        return callback(null);
      }
    }

    function copyOriginal(callback) {
      if (options.copyOriginal !== false) {
        context.basePath = path.replace(/\.\w+$/, '');
        var originalPath;
        if (context.basePath !== path) {
          // If there was already an extension, respect it for the original
          originalPath = path;
        } else {
          // Caller did not supply an extension, so add one for the original
          originalPath = context.basePath + '.' + context.extension;
        }

        // By default, if the original would appear "flipped" on the web,
        // we ask imagemagick to reorient it. This is pretty much necessary
        // to make the image useful on a website, but since it's a lossy
        // operation, we provide an option to disable it

        if (orientOriginals && context.info.orientation && (context.info.orientation !== 'TopLeft'))
        {
          var tempFile = context.tempFolder + '/oriented.' + context.extension;
          imagemagick.convert(
            [ localPath, '-auto-orient', tempFile ],
            function(err) {
              if (err) {
                return callback(err);
              } else {
                return self.copyIn(tempFile, originalPath, options, callback);
              }
            }
          );
        } else {
          self.copyIn(localPath, originalPath, options, callback);
        }
      } else {
        callback(null);
      }
    }

    function scaleAndCopy(callback) {
      // Render scaled versions.
      //
      // I use async.mapSeries rather than async.map because the impact
      // of three imagemagick processes running at once is nontrivial and
      // there could be many people uploading. In fact, I need to add a
      // throttling mechanism to delay the launching of extra pipelines
      // at some point

      async.mapSeries(imageSizes, function(size, callback) {
        var suffix = size.name + '.' + context.extension;
        var tempFile = context.tempFolder + '/' + suffix;

        // Can't use imagemagick.resize convenience method because it doesn't
        // offer -auto-orient, which rotates iPhone photos to the correct
        // orientation before scaling them. The '>' means "don't make things bigger
        // than the original, ever." Anyone who does that is bad at the Internet

        var cmd = [ localPath, '-auto-orient', '-resize', size.width + 'x' + size.height + '>', tempFile ];
        imagemagick.convert(
          cmd,
          function(err) {
            if (err) {
              return callback(err);
            }
            var permanentFile = context.basePath + '.' + suffix;
            return self.copyIn(tempFile, permanentFile, options, callback);
        });
      }, callback);
    }

    function cleanup(err) {
      // Try to clean up the temp folder. This can fail if its creation
      // failed, in which case there is nothing we can or should do,
      // thus the empty callback
      if (context.tempFolder) {
        rmRf(context.tempFolder, function(e) { });
      }
      callback(err, {
        basePath: context.basePath,
        extension: context.extension,
        width: context.info.width,
        height: context.info.height,
        originalWidth: context.info.originalWidth,
        originalHeight: context.info.originalHeight
      });
    }
  },

  self.getUrl = function(options, callback) {
    return backend.getUrl(options, callback);
  },

  self.remove = function(path, callback) {
    return backend.remove(path, callback);
  }
};

function generateId() {
  return crypto.randomBytes(16).toString('hex');
}

<commit_msg>uploadfs.js now passes jslint, with leading underscores tolerated (for compatibility with typical usage of underscore). All unit tests still passing. I need to jslint the backends next.<commit_after>"use strict";

/*jslint nomen:true*/

var _ = require('underscore');
var async = require('async');
var crypto = require('crypto');
var fs = require('fs');
var rmRf = require('rimraf');
var imagemagick = require('node-imagemagick');

function generateId() {
    return crypto.randomBytes(16).toString('hex');
}

function Uploadfs() {
    var tempPath, backend, imageSizes, orientOriginals = true, self = this;
    self.init = function (options, callback) {
        if (!options.backend) {
            return callback("backend must be specified");
        }
        // Load standard backends, by name
        if (typeof (options.backend) === 'string') {
            options.backend = require(__dirname + '/' + options.backend + '.js');
        }
        // Custom backends can be passed as objects
        backend = options.backend;
        imageSizes = options.imageSizes || [];
        if (typeof (options.orientOriginals) !== 'undefined') {
            orientOriginals = options.orientOriginals;
        }

        async.series([
            // create temp folder if needed
            function (callback) {
                if (!imageSizes.length) {
                    return callback();
                }
                if (!options.tempPath) {
                    return callback("options.tempPath not set");
                }
                tempPath = options.tempPath;
                fs.exists(options.tempPath, function (exists) {
                    if (!exists) {
                        return fs.mkdir(options.tempPath, callback);
                    }
                    return callback(null);
                });
            },

            // invoke backend init with options
            function (callback) {
                return backend.init(options, callback);
            }
        ], callback);
    };

    self.copyIn = function (localPath, path, options, callback) {
        if (typeof (options) === 'function') {
            callback = options;
            options = {};
        }
        return backend.copyIn(localPath, path, options, callback);
    };

    /**
     * Copy an image into uploadfs. Scaled versions as defined by the imageSizes option
     * at init() time are copied into uploadfs as follows:
     *
     * If 'path' is '/me' and sizes with names 'small', 'medium' and 'large'
     * were defined at init() time, the scaled versions will be:
     *
     * '/me.small.jpg', '/me.medium.jpg', '/me.large.jpg'
     *
     * And the original file will be copied to:
     *
     * '/me.jpg'
     *
     * Note that a file extension is added automatically. If you provide a
     * file extension in 'path' it will be honored when copying the original only.
     * The scaled versions will get appropriate extensions for their format
     * as detected by Imagemagick.
     *
     * If there is no error the second argument passed to the callback will
     * be an object with a 'basePath' property containing your original path
     * with the file extension removed and an 'extension' property containing
     * the automatically added file extension, as a convenience for locating the
     * original and scaled versions just by adding .jpg, .small.jpg, .medium.jpg,
     * etc.
     *
     * Scaled versions have the same file format as the original and are no wider
     * or taller than specified by the width and height properties of the
     * corresponding size, with the aspect ratio always being preserved.
     * If options.copyOriginal is explicitly false, the original image is
     * not copied into uploadfs at all.
     *
     * Image scaling is performed with imagemagick, which must be installed
     * (note that Heroku provides it). In no case is an image ever scaled to
     * be larger than the original. Scaled versions of images with an orientation
     * hint, such as iPhone photographs, are automatically rotated by imagemagick
     * so that they will display properly in web browsers.
     */

    self.copyImageIn = function (localPath, path, options, callback) {
        if (typeof (options) === 'function') {
            callback = options;
            options = {};
        }

        var context = {};

        async.series([
            // Identify the file
            function (callback) {
                imagemagick.identify(localPath, function (err, info) {
                    if (err) {
                        return callback(err);
                    }
                    context.info = info;
                    console.log(context);

                    // Imagemagick gives us the raw width and height, but we're
                    // going to orient the scaled images and, in most cases, the
                    // original image so that they actually display properly in
                    // web browsers. So return the oriented width and height
                    // to the developer. Also return the original width and
                    // height just to be thorough, but use the obvious names
                    // for the obvious thing

                    context.info.originalWidth = context.info.width;
                    context.info.originalHeight = context.info.height;
                    var o = context.info.orientation, t;
                    if ((o === 'LeftTop') || (o === 'RightTop') || (o === 'RightBottom') || (o === 'LeftBottom')) {
                        t = context.info.width;
                        context.info.width = context.info.height;
                        context.info.height = t;
                    }

                    context.tempName = generateId();
                    // File extension from format, which is GIF, JPEG, PNG
                    context.extension = info.format.toLowerCase();
                    if (context.extension === 'jpeg') {
                        context.extension = 'jpg';
                    }
                    callback(null);
                });
            },
            // make a temporary folder for our work
            function (callback) {
                // Create destination folder
                if (imageSizes.length) {
                    context.tempFolder = tempPath + '/' + context.tempName;
                    fs.mkdir(context.tempFolder, callback);
                } else {
                    return callback(null);
                }
            },
            // Copy the original into uploadfs
            function (callback) {
                if (options.copyOriginal !== false) {
                    context.basePath = path.replace(/\.\w+$/, '');
                    var originalPath, tempFile;
                    if (context.basePath !== path) {
                        // If there was already an extension, respect it for the original
                        originalPath = path;
                    } else {
                        // Caller did not supply an extension, so add one for the original
                        originalPath = context.basePath + '.' + context.extension;
                    }

                    // By default, if the original would appear "flipped" on the web,
                    // we ask imagemagick to reorient it. This is pretty much necessary
                    // to make the image useful on a website, but since it's a lossy
                    // operation, we provide an option to disable it

                    if (orientOriginals && context.info.orientation && (context.info.orientation !== 'TopLeft')) {
                        tempFile = context.tempFolder + '/oriented.' + context.extension;
                        imagemagick.convert(
                            [ localPath, '-auto-orient', tempFile ],
                            function (err) {
                                if (err) {
                                    return callback(err);
                                }
                                return self.copyIn(tempFile, originalPath, options, callback);
                            }
                        );
                    } else {
                        self.copyIn(localPath, originalPath, options, callback);
                    }
                } else {
                    callback(null);
                }
            },
            // Scale and copy versions of various sizes
            function (callback) {
                // I use async.mapSeries rather than async.map because the impact
                // of three imagemagick processes running at once is nontrivial and
                // there could be many people uploading. In fact, I need to add a
                // throttling mechanism to delay the launching of extra pipelines
                // at some point

                async.mapSeries(imageSizes, function (size, callback) {
                    var suffix = size.name + '.' + context.extension,
                        tempFile = context.tempFolder + '/' + suffix,
                        // Can't use imagemagick.resize convenience method because it doesn't
                        // offer -auto-orient, which rotates iPhone photos to the correct
                        // orientation before scaling them. The '>' means "don't make things bigger
                        // than the original, ever." Anyone who does that is bad at the Internet
                        cmd = [ localPath, '-auto-orient', '-resize', size.width + 'x' + size.height + '>', tempFile ];

                    imagemagick.convert(
                        cmd,
                        function (err) {
                            if (err) {
                                return callback(err);
                            }
                            var permanentFile = context.basePath + '.' + suffix;
                            return self.copyIn(tempFile, permanentFile, options, callback);
                        }
                    );
                }, callback);
            }
        ], function (err) {
            // Try to clean up the temp folder. This can fail if its creation
            // failed, in which case there is nothing we can or should do,
            // thus the empty callback
            if (context.tempFolder) {
                rmRf(context.tempFolder, function (e) { });
            }
            callback(err, {
                basePath: context.basePath,
                extension: context.extension,
                width: context.info.width,
                height: context.info.height,
                originalWidth: context.info.originalWidth,
                originalHeight: context.info.originalHeight
            });
        });
    };

    self.getUrl = function (options, callback) {
        return backend.getUrl(options, callback);
    };

    self.remove = function (path, callback) {
        return backend.remove(path, callback);
    };
}

module.exports = function () {
    return new Uploadfs();
};
<|endoftext|>