<commit_before>/*
 * Name          : joy.js
 * @author       : Roberto D'Amico (Bobboteck)
 * Last modified : 07.01.2020
 * Revision      : 1.1.4
 *
 * Modification History:
 * Date         Version     Modified By		Description
 * 2020-04-20	1.1.5		Roberto D'Amico	Correct: Two sticks in a row, thanks to @liamw9534 for the suggestion
 * 2020-04-03               Roberto D'Amico Correct: InternalRadius when change the size of canvas, thanks to @vanslipon for the suggestion
 * 2020-01-07	1.1.4		Roberto D'Amico Close #6 by implementing a new parameter to set the functionality of auto-return to 0 position
 * 2019-11-18	1.1.3		Roberto D'Amico	Close #5 correct indication of East direction
 * 2019-11-12   1.1.2       Roberto D'Amico Removed Fix #4 incorrectly introduced and restored operation with touch devices
 * 2019-11-12   1.1.1       Roberto D'Amico Fixed Issue #4 - Now JoyStick work in any position in the page, not only at 0,0
 *
 * The MIT License (MIT)
 *
 *  This file is part of the JoyStick Project (https://github.com/bobboteck/JoyStick).
 *	Copyright (c) 2015 Roberto D'Amico (Bobboteck).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * @desc Principal object that draw a joystick, you only need to initialize the object and suggest the HTML container
 * @costructor
 * @param container {String} - HTML object that contains the Joystick
 * @param parameters (optional) - object with following keys:
 *	title {String} (optional) - The ID of canvas (Default value is 'joystick')
 * 	width {Int} (optional) - The width of canvas, if not specified is setted at width of container object (Default value is the width of container object)
 * 	height {Int} (optional) - The height of canvas, if not specified is setted at height of container object (Default value is the height of container object)
 * 	internalFillColor {String} (optional) - Internal color of Stick (Default value is '#00AA00')
 * 	internalLineWidth {Int} (optional) - Border width of Stick (Default value is 2)
 * 	internalStrokeColor {String}(optional) - Border color of Stick (Default value is '#003300')
 * 	externalLineWidth {Int} (optional) - External reference circonference width (Default value is 2)
 * 	externalStrokeColor {String} (optional) - External reference circonference color (Default value is '#008000')
 * 	autoReturnToCenter {Bool} (optional) - Sets the behavior of the stick, whether or not, it should return to zero position when released (Default value is True and return to zero)
 */
var JoyStick = (function(container, parameters) {
	parameters = parameters || {};
	var title = (parameters.title === undefined ? "joystick" : parameters.title),
		width = (parameters.width === undefined ? 0 : parameters.width),
		height = (parameters.height === undefined ? 0 : parameters.height),
		internalFillColor = (parameters.internalFillColor === undefined ? "#00AA00" : parameters.internalFillColor),
		internalLineWidth = (parameters.internalLineWidth === undefined ? 2 : parameters.internalLineWidth),
		internalStrokeColor = (parameters.internalStrokeColor === undefined ? "#003300" : parameters.internalStrokeColor),
		externalLineWidth = (parameters.externalLineWidth === undefined ? 2 : parameters.externalLineWidth),
		externalStrokeColor = (parameters.externalStrokeColor ===  undefined ? "#008000" : parameters.externalStrokeColor),
		autoReturnToCenter = (parameters.autoReturnToCenter === undefined ? true : parameters.autoReturnToCenter);

	// Create Canvas element and add it in the Container object
	var objContainer = document.getElementById(container);
	var canvas = document.createElement('canvas');
	canvas.id = title;
	if(width === 0) width = objContainer.clientWidth;
	if(height === 0) height = objContainer.clientHeight;
	canvas.width = width;
	canvas.height = height;
	objContainer.appendChild(canvas);
	var context=canvas.getContext('2d');

	var pressed = 0; // Bool - 1=Yes - 0=No
    var circumference = 2 * Math.PI;
    var internalRadius = (canvas.width-((canvas.width/2)+10))/2;
	var maxMoveStick = internalRadius + 5;
	var externalRadius = internalRadius + 30;
	var centerX = canvas.width / 2;
	var centerY = canvas.height / 2;
	var directionHorizontalLimitPos = canvas.width / 10;
	var directionHorizontalLimitNeg = directionHorizontalLimitPos * -1;
	var directionVerticalLimitPos = canvas.height / 10;
	var directionVerticalLimitNeg = directionVerticalLimitPos * -1;
	// Used to save current position of stick
	var movedX=centerX;
	var movedY=centerY;

	// Check if the device support the touch or not
	if("ontouchstart" in document.documentElement)
	{
		canvas.addEventListener('touchstart', onTouchStart, false);
		canvas.addEventListener('touchmove', onTouchMove, false);
		canvas.addEventListener('touchend', onTouchEnd, false);
	}
	else
	{
		canvas.addEventListener('mousedown', onMouseDown, false);
		canvas.addEventListener('mousemove', onMouseMove, false);
		canvas.addEventListener('mouseup', onMouseUp, false);
	}
	// Draw the object
	drawExternal();
	drawInternal();
	/******************************************************
	 * Private methods
	 *****************************************************/
	/**
	 * @desc Draw the external circle used as reference position
	 */
	function drawExternal()
	{
		context.beginPath();
		context.arc(centerX, centerY, externalRadius, 0, circumference, false);
		context.lineWidth = externalLineWidth;
		context.strokeStyle = externalStrokeColor;
		context.stroke();
	}
	/**
	 * @desc Draw the internal stick in the current position the user have moved it
	 */
	function drawInternal()
	{
		context.beginPath();
		if(movedX<internalRadius) movedX=maxMoveStick;
		if((movedX+internalRadius) > canvas.width) movedX = canvas.width-(maxMoveStick);
		if(movedY<internalRadius) movedY=maxMoveStick;
		if((movedY+internalRadius) > canvas.height) movedY = canvas.height-(maxMoveStick);
		context.arc(movedX, movedY, internalRadius, 0, circumference, false);
		// create radial gradient
		var grd = context.createRadialGradient(centerX, centerY, 5, centerX, centerY, 200);
		// Light color
		grd.addColorStop(0, internalFillColor);
		// Dark color
		grd.addColorStop(1, internalStrokeColor);
		context.fillStyle = grd;
		context.fill();
		context.lineWidth = internalLineWidth;
		context.strokeStyle = internalStrokeColor;
		context.stroke();
	}

	/**
	 * @desc Events for manage touch
	 */
	function onTouchStart(event)
	{
		pressed = 1;
	}
	function onTouchMove(event)
	{
		// Prevent the browser from doing its default thing (scroll, zoom)
		event.preventDefault();
		if(pressed === 1 && event.targetTouches[0].target === canvas)
		{
			movedX = event.targetTouches[0].pageX;
			movedY = event.targetTouches[0].pageY;
			// Manage offset
			movedX -= canvas.offsetLeft;
			movedY -= canvas.offsetTop;
			// Delete canvas
			context.clearRect(0, 0, canvas.width, canvas.height);
			// Redraw object
			drawExternal();
			drawInternal();
		}
	}
	function onTouchEnd(event)
	{
		pressed = 0;
		// If required reset position store variable
		if(autoReturnToCenter)
		{
			movedX = centerX;
			movedY = centerY;
		}
		// Delete canvas
		context.clearRect(0, 0, canvas.width, canvas.height);
		// Redraw object
		drawExternal();
		drawInternal();
		//canvas.unbind('touchmove');
	}
	/**
	 * @desc Events for manage mouse
	 */
	function onMouseDown(event)
	{
		pressed = 1;
	}
	function onMouseMove(event)
	{
		if(pressed === 1)
		{
			movedX = event.pageX;
			movedY = event.pageY;
			// Manage offset
			movedX -= canvas.offsetLeft;
			movedY -= canvas.offsetTop;
			// Delete canvas
			context.clearRect(0, 0, canvas.width, canvas.height);
			// Redraw object
			drawExternal();
			drawInternal();
		}
	}
	function onMouseUp(event)
	{
		pressed = 0;
		// If required reset position store variable
		if(autoReturnToCenter)
		{
			movedX = centerX;
			movedY = centerY;
		}
		// Delete canvas
		context.clearRect(0, 0, canvas.width, canvas.height);
		// Redraw object
		drawExternal();
		drawInternal();
		//canvas.unbind('mousemove');
	}
	/******************************************************
	 * Public methods
	 *****************************************************/
	/**
	 * @desc The width of canvas
	 * @return Number of pixel width
	 */
	this.GetWidth = function ()
	{
		return canvas.width;
	};

	/**
	 * @desc The height of canvas
	 * @return Number of pixel height
	 */
	this.GetHeight = function ()
	{
		return canvas.height;
	};

	/**
	 * @desc The X position of the cursor relative to the canvas that contains it and to its dimensions
	 * @return Number that indicate relative position
	 */
	this.GetPosX = function ()
	{
		return movedX;
	};

	/**
	 * @desc The Y position of the cursor relative to the canvas that contains it and to its dimensions
	 * @return Number that indicate relative position
	 */
	this.GetPosY = function ()
	{
		return movedY;
	};

	/**
	 * @desc Normalizzed value of X move of stick
	 * @return Integer from -100 to +100
	 */
	this.GetX = function ()
	{
		return (100*((movedX - centerX)/maxMoveStick)).toFixed();
	};

	/**
	 * @desc Normalizzed value of Y move of stick
	 * @return Integer from -100 to +100
	 */
	this.GetY = function ()
	{
		return ((100*((movedY - centerY)/maxMoveStick))*-1).toFixed();
	};

	/**
	 * @desc Get the direction of the cursor as a string that indicates the cardinal points where this is oriented
	 * @return String of cardinal point N, NE, E, SE, S, SW, W, NW and C when it is placed in the center
	 */
	this.GetDir = function()
	{
		var result = "";
		var orizontal = movedX - centerX;
		var vertical = movedY - centerY;

		if(vertical >= directionVerticalLimitNeg && vertical <= directionVerticalLimitPos)
		{
			result = "C";
		}
		if(vertical < directionVerticalLimitNeg)
		{
			result = "N";
		}
		if(vertical > directionVerticalLimitPos)
		{
			result = "S";
		}

		if(orizontal < directionHorizontalLimitNeg)
		{
			if(result === "C")
			{
				result = "W";
			}
			else
			{
				result += "W";
			}
		}
		if(orizontal > directionHorizontalLimitPos)
		{
			if(result === "C")
			{
				result = "E";
			}
			else
			{
				result += "E";
			}
		}

		return result;
	};
});
<commit_msg>Improved code style<commit_after>/*
 * Name          : joy.js
 * @author       : Roberto D'Amico (Bobboteck)
 * Last modified : 07.01.2020
 * Revision      : 1.1.4
 *
 * Modification History:
 * Date         Version     Modified By		Description
 * 2020-04-20	1.1.5		Roberto D'Amico	Correct: Two sticks in a row, thanks to @liamw9534 for the suggestion
 * 2020-04-03               Roberto D'Amico Correct: InternalRadius when change the size of canvas, thanks to @vanslipon for the suggestion
 * 2020-01-07	1.1.4		Roberto D'Amico Close #6 by implementing a new parameter to set the functionality of auto-return to 0 position
 * 2019-11-18	1.1.3		Roberto D'Amico	Close #5 correct indication of East direction
 * 2019-11-12   1.1.2       Roberto D'Amico Removed Fix #4 incorrectly introduced and restored operation with touch devices
 * 2019-11-12   1.1.1       Roberto D'Amico Fixed Issue #4 - Now JoyStick work in any position in the page, not only at 0,0
 *
 * The MIT License (MIT)
 *
 *  This file is part of the JoyStick Project (https://github.com/bobboteck/JoyStick).
 *	Copyright (c) 2015 Roberto D'Amico (Bobboteck).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

/**
 * @desc Principal object that draw a joystick, you only need to initialize the object and suggest the HTML container
 * @costructor
 * @param container {String} - HTML object that contains the Joystick
 * @param parameters (optional) - object with following keys:
 *	title {String} (optional) - The ID of canvas (Default value is 'joystick')
 * 	width {Int} (optional) - The width of canvas, if not specified is setted at width of container object (Default value is the width of container object)
 * 	height {Int} (optional) - The height of canvas, if not specified is setted at height of container object (Default value is the height of container object)
 * 	internalFillColor {String} (optional) - Internal color of Stick (Default value is '#00AA00')
 * 	internalLineWidth {Int} (optional) - Border width of Stick (Default value is 2)
 * 	internalStrokeColor {String}(optional) - Border color of Stick (Default value is '#003300')
 * 	externalLineWidth {Int} (optional) - External reference circonference width (Default value is 2)
 * 	externalStrokeColor {String} (optional) - External reference circonference color (Default value is '#008000')
 * 	autoReturnToCenter {Bool} (optional) - Sets the behavior of the stick, whether or not, it should return to zero position when released (Default value is True and return to zero)
 */
var JoyStick = (function(container, parameters) {
	parameters = parameters || {};
	var title = (typeof parameters.title === "undefined" ? "joystick" : parameters.title),
		width = (typeof parameters.width === "undefined" ? 0 : parameters.width),
		height = (typeof parameters.height === "undefined" ? 0 : parameters.height),
		internalFillColor = (parameters.internalFillColor === undefined ? "#00AA00" : parameters.internalFillColor),
		internalLineWidth = (parameters.internalLineWidth === undefined ? 2 : parameters.internalLineWidth),
		internalStrokeColor = (parameters.internalStrokeColor === undefined ? "#003300" : parameters.internalStrokeColor),
		externalLineWidth = (parameters.externalLineWidth === undefined ? 2 : parameters.externalLineWidth),
		externalStrokeColor = (parameters.externalStrokeColor ===  undefined ? "#008000" : parameters.externalStrokeColor),
		autoReturnToCenter = (parameters.autoReturnToCenter === undefined ? true : parameters.autoReturnToCenter);

	// Create Canvas element and add it in the Container object
	var objContainer = document.getElementById(container);
	var canvas = document.createElement('canvas');
	canvas.id = title;
	if(width === 0) width = objContainer.clientWidth;
	if(height === 0) height = objContainer.clientHeight;
	canvas.width = width;
	canvas.height = height;
	objContainer.appendChild(canvas);
	var context=canvas.getContext('2d');

	var pressed = 0; // Bool - 1=Yes - 0=No
    var circumference = 2 * Math.PI;
    var internalRadius = (canvas.width-((canvas.width/2)+10))/2;
	var maxMoveStick = internalRadius + 5;
	var externalRadius = internalRadius + 30;
	var centerX = canvas.width / 2;
	var centerY = canvas.height / 2;
	var directionHorizontalLimitPos = canvas.width / 10;
	var directionHorizontalLimitNeg = directionHorizontalLimitPos * -1;
	var directionVerticalLimitPos = canvas.height / 10;
	var directionVerticalLimitNeg = directionVerticalLimitPos * -1;
	// Used to save current position of stick
	var movedX=centerX;
	var movedY=centerY;

	// Check if the device support the touch or not
	if("ontouchstart" in document.documentElement)
	{
		canvas.addEventListener('touchstart', onTouchStart, false);
		canvas.addEventListener('touchmove', onTouchMove, false);
		canvas.addEventListener('touchend', onTouchEnd, false);
	}
	else
	{
		canvas.addEventListener('mousedown', onMouseDown, false);
		canvas.addEventListener('mousemove', onMouseMove, false);
		canvas.addEventListener('mouseup', onMouseUp, false);
	}
	// Draw the object
	drawExternal();
	drawInternal();
	/******************************************************
	 * Private methods
	 *****************************************************/
	/**
	 * @desc Draw the external circle used as reference position
	 */
	function drawExternal()
	{
		context.beginPath();
		context.arc(centerX, centerY, externalRadius, 0, circumference, false);
		context.lineWidth = externalLineWidth;
		context.strokeStyle = externalStrokeColor;
		context.stroke();
	}
	/**
	 * @desc Draw the internal stick in the current position the user have moved it
	 */
	function drawInternal()
	{
		context.beginPath();
		if(movedX<internalRadius) movedX=maxMoveStick;
		if((movedX+internalRadius) > canvas.width) movedX = canvas.width-(maxMoveStick);
		if(movedY<internalRadius) movedY=maxMoveStick;
		if((movedY+internalRadius) > canvas.height) movedY = canvas.height-(maxMoveStick);
		context.arc(movedX, movedY, internalRadius, 0, circumference, false);
		// create radial gradient
		var grd = context.createRadialGradient(centerX, centerY, 5, centerX, centerY, 200);
		// Light color
		grd.addColorStop(0, internalFillColor);
		// Dark color
		grd.addColorStop(1, internalStrokeColor);
		context.fillStyle = grd;
		context.fill();
		context.lineWidth = internalLineWidth;
		context.strokeStyle = internalStrokeColor;
		context.stroke();
	}

	/**
	 * @desc Events for manage touch
	 */
	function onTouchStart(event)
	{
		pressed = 1;
	}
	function onTouchMove(event)
	{
		// Prevent the browser from doing its default thing (scroll, zoom)
		event.preventDefault();
		if(pressed === 1 && event.targetTouches[0].target === canvas)
		{
			movedX = event.targetTouches[0].pageX;
			movedY = event.targetTouches[0].pageY;
			// Manage offset
			movedX -= canvas.offsetLeft;
			movedY -= canvas.offsetTop;
			// Delete canvas
			context.clearRect(0, 0, canvas.width, canvas.height);
			// Redraw object
			drawExternal();
			drawInternal();
		}
	}
	function onTouchEnd(event)
	{
		pressed = 0;
		// If required reset position store variable
		if(autoReturnToCenter)
		{
			movedX = centerX;
			movedY = centerY;
		}
		// Delete canvas
		context.clearRect(0, 0, canvas.width, canvas.height);
		// Redraw object
		drawExternal();
		drawInternal();
		//canvas.unbind('touchmove');
	}
	/**
	 * @desc Events for manage mouse
	 */
	function onMouseDown(event)
	{
		pressed = 1;
	}
	function onMouseMove(event)
	{
		if(pressed === 1)
		{
			movedX = event.pageX;
			movedY = event.pageY;
			// Manage offset
			movedX -= canvas.offsetLeft;
			movedY -= canvas.offsetTop;
			// Delete canvas
			context.clearRect(0, 0, canvas.width, canvas.height);
			// Redraw object
			drawExternal();
			drawInternal();
		}
	}
	function onMouseUp(event)
	{
		pressed = 0;
		// If required reset position store variable
		if(autoReturnToCenter)
		{
			movedX = centerX;
			movedY = centerY;
		}
		// Delete canvas
		context.clearRect(0, 0, canvas.width, canvas.height);
		// Redraw object
		drawExternal();
		drawInternal();
		//canvas.unbind('mousemove');
	}
	/******************************************************
	 * Public methods
	 *****************************************************/
	/**
	 * @desc The width of canvas
	 * @return Number of pixel width
	 */
	this.GetWidth = function ()
	{
		return canvas.width;
	};

	/**
	 * @desc The height of canvas
	 * @return Number of pixel height
	 */
	this.GetHeight = function ()
	{
		return canvas.height;
	};

	/**
	 * @desc The X position of the cursor relative to the canvas that contains it and to its dimensions
	 * @return Number that indicate relative position
	 */
	this.GetPosX = function ()
	{
		return movedX;
	};

	/**
	 * @desc The Y position of the cursor relative to the canvas that contains it and to its dimensions
	 * @return Number that indicate relative position
	 */
	this.GetPosY = function ()
	{
		return movedY;
	};

	/**
	 * @desc Normalizzed value of X move of stick
	 * @return Integer from -100 to +100
	 */
	this.GetX = function ()
	{
		return (100*((movedX - centerX)/maxMoveStick)).toFixed();
	};

	/**
	 * @desc Normalizzed value of Y move of stick
	 * @return Integer from -100 to +100
	 */
	this.GetY = function ()
	{
		return ((100*((movedY - centerY)/maxMoveStick))*-1).toFixed();
	};

	/**
	 * @desc Get the direction of the cursor as a string that indicates the cardinal points where this is oriented
	 * @return String of cardinal point N, NE, E, SE, S, SW, W, NW and C when it is placed in the center
	 */
	this.GetDir = function()
	{
		var result = "";
		var orizontal = movedX - centerX;
		var vertical = movedY - centerY;

		if(vertical >= directionVerticalLimitNeg && vertical <= directionVerticalLimitPos)
		{
			result = "C";
		}
		if(vertical < directionVerticalLimitNeg)
		{
			result = "N";
		}
		if(vertical > directionVerticalLimitPos)
		{
			result = "S";
		}

		if(orizontal < directionHorizontalLimitNeg)
		{
			if(result === "C")
			{
				result = "W";
			}
			else
			{
				result += "W";
			}
		}
		if(orizontal > directionHorizontalLimitPos)
		{
			if(result === "C")
			{
				result = "E";
			}
			else
			{
				result += "E";
			}
		}

		return result;
	};
});
<|endoftext|>


<commit_before>class A {
    constructor() {
        this.callInitHooks()
    }
    static addInitHook(fn) {
        const args = Array.prototype.slice.call(arguments, 1)
        const init = typeof fn === 'function' ? fn : function () {
            this[fn].apply(this, args)
        }
        const proto = this.prototype
        const parentProto = Object.getPrototypeOf(proto)
        if (!proto._initHooks || proto._initHooks === parentProto._initHooks) {
            console.log('init hooks array')
            proto._initHooks = []
        }
        proto._initHooks.push(init)
    }
    callInitHooks() {
        // TODO: this???
        if (this._initHooksCalled) {
            return
        }
        this._initHooksCalled = true
        const proto = Object.getPrototypeOf(this)
        const parentProto = Object.getPrototypeOf(proto)
        if (parentProto.callInitHooks) {
            parentProto.callInitHooks.call(this)
        }
        const hooks = proto._initHooks
        for (let i = 0; i < hooks.length; i++) {
            hooks[i].call(this)
        }
    }
}
class B extends A {
    constructor() {
        super()
        // this.handlers = []
        console.log('B.constructor')
        console.log(B.prototype._initHooks.join())
    }
    addHandler(name) {
        if (!this.handlers) {
            this.handlers = []
        }
        this.handlers.push(name)
    }
    bMethod() {}
}
class C extends B {
    constructor() {
        super()
        // this.handlers = []
        console.log('C.constructor')
        console.log(C.prototype._initHooks.join())
    }
    addHandlerC(name) {
        if (!this.handlers) {
            this.handlers = []
        }
        this.handlers.push(name)
    }
    cMethod() {}
}

B.addInitHook('addHandler', 'h1')
C.addInitHook('addHandler', 'h2')
C.addInitHook('addHandler', 'h3')
console.log('B.hooks', B.prototype._initHooks)
console.log('C.hooks', C.prototype._initHooks)

const b = new B()
const c = new C()
console.log('b.handlers', b.handlers)
console.log('c.handlers', c.handlers)
<commit_msg>Proto (#2)<commit_after>class A {
    constructor() {
        this.callInitHooks()
    }
    static addInitHook(fn) {
        const args = Array.prototype.slice.call(arguments, 1)
        const init = typeof fn === 'function' ? fn : function () {
            this[fn].apply(this, args)
        }
        const proto = this.prototype
        const parentProto = Object.getPrototypeOf(proto)
        if (!proto._initHooks || proto._initHooks === parentProto._initHooks) {
            console.log('init hooks array')
            proto._initHooks = []
        }
        proto._initHooks.push(init)
    }
    callInitHooks() {
        const proto = Object.getPrototypeOf(this)
        this._traverseInitHooks(proto)
    }
    _traverseInitHooks(proto) {
        if (this._initHooksCalled) {
            return
        }
        const parentProto = Object.getPrototypeOf(proto)
        if (parentProto._initHooks) {
            parentProto._traverseInitHooks.call(this, parentProto)
        }
        this._initHooksCalled = true
        const hooks = proto._initHooks
        if (hooks) {
            for (let i = 0; i < hooks.length; i++) {
                hooks[i].call(this)
            }
        }
    }
}
class B extends A {
    constructor() {
        super()
        // this.handlers = []
        console.log('B.constructor')
    }
    addHandler(name) {
        if (!this.handlers) {
            this.handlers = []
        }
        this.handlers.push(name)
    }
    bMethod() {}
}
class C extends B {
    constructor() {
        super()
        // this.handlers = []
        console.log('C.constructor')
    }
    addHandlerC(name) {
        if (!this.handlers) {
            this.handlers = []
        }
        this.handlers.push(name)
    }
    cMethod() {}
}

B.addInitHook('addHandler', 'h1')
C.addInitHook('addHandler', 'h2')
C.addInitHook('addHandler', 'h3')
console.log('B.hooks', B.prototype._initHooks)
console.log('C.hooks', C.prototype._initHooks)

const b = new B()
const c = new C()
console.log('b.handlers', b.handlers)
console.log('c.handlers', c.handlers)
<|endoftext|>


<commit_before>/**
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.
 */

if (typeof WScript != 'undefined') {
  var shell = WScript.CreateObject("WScript.Shell");
  try {
    var ret = shell.Run('node "' + WScript.ScriptFullName + '" --pause_on_exit', 1, true);
  } catch (e) {
    shell.Popup('NodeJS is not installed. Please install it from http://nodejs.org');
    ret = 1;
  }
  WScript.Quit(ret);
}

process.on('uncaughtException', function(e) {
  fatal('Uncaught exception: ' + e);
});

var childProcess = require('child_process');
var fs = require('fs');
var path = require('path');
var isWindows = process.platform.slice(0, 3) == 'win';
var scriptDir = path.dirname(process.argv[1]);

function exit(code) {
  if (process.argv[2] == '--pause_on_exit') {
    waitForKey(function() {
      process.exit(code);
    });
  } else {
    process.exit(code);
  }
}

function fatal(msg) {
  console.error(msg);
  exit(1);
}

function exec(cmd, onSuccess, opt_onError, opt_silent) {
  var onError = opt_onError || function(e) {
    fatal('command failed: ' + cmd + '\n' + e);
  };
  if (!opt_silent) {
    console.log('Running: ' + cmd);
  }
  childProcess.exec(cmd, function(error, stdout, stderr) {
    if (error) {
      onError(error);
    } else {
      onSuccess(stdout.trim());
    }
  });
}

function sudo(cmd, onSuccess, opt_onError, silent) {
  if (!isWindows) {
    cmd = 'sudo ' + cmd;
  }
  exec(cmd, onSuccess, opt_onError, silent);
}

function copyFile(src, dst, callback) {
  var rd = fs.createReadStream(src);
  var wr = fs.createWriteStream(dst);
  wr.on('error', function(err) {
    fatal('Copy file error: ' + err);
  });
  wr.on('close', callback);
  rd.pipe(wr);
}

function recursiveDelete(dirPath) {
  if (fs.existsSync(dirPath)) {
    console.log('Deleting: ' + dirPath);
    helper(dirPath);
  }
  function helper(dirPath) {
    try {
       var files = fs.readdirSync(dirPath);
    } catch(e) {
      return;
    }
    for (var i = 0; i < files.length; i++) {
      var filePath = path.join(dirPath, files[i]);
      fs.chmodSync(filePath, '777');
      if (fs.statSync(filePath).isFile()) {
        fs.unlinkSync(filePath);
      } else {
        helper(filePath);
      }
    }
    fs.rmdirSync(dirPath);
  }
}

function checkGit(callback) {
  var errMsg = 'git is not installed (or not available on your PATH). Please install it from http://git-scm.com';
  exec('git --version', callback, function() {
    if (isWindows) {
      // See if it's at the default install path.
      process.env['PATH'] += ';' + path.join(process.env['ProgramFiles'], 'Git', 'bin');
      exec('git --version', callback, function() {
        fatal(errMsg);
      }, true);
    } else {
      fatal(errMsg);
    }
  }, true);
}

function computeGitVersion(callback) {
  exec('git describe --tags --long', function(stdout) {
    var version = stdout.replace(/^2.5.0-.*?-/, 'dev-');
    callback(version);
  }, null, true);
}

function chdir(d) {
  d = path.join(scriptDir, d);
  if (process.cwd() != d) {
    console.log('Changing directory to: ' + d);
    process.chdir(d);
  }
}

function checkOutSelf(callback) {
  // If the repo doesn't exist where the script is, then use the CWD as the checkout location.
  var origDir = process.cwd();
  var requiresClone = true;
  // First - try the directory of the script.
  if (scriptDir.slice(0, 2) != '\\\\') {
    process.chdir(scriptDir);
    requiresClone = !fs.existsSync('.git');
  }
  // Next - try the CWD.
  if (requiresClone) {
    scriptDir = origDir;
    process.chdir(scriptDir);
    requiresClone = !fs.existsSync('.git');
  }
  // Next - see if it exists within the CWD.
  if (requiresClone) {
    if (fs.existsSync(path.join(origDir, 'mobile-chrome-apps'))) {
      scriptDir = path.join(origDir, 'mobile-chrome-apps');
      process.chdir(scriptDir);
      requiresClone = !fs.existsSync('.git');
    }
  }
  if (requiresClone) {
    scriptDir = origDir;
    chdir('');
    recursiveDelete('mobile-chrome-apps');
    exec('git clone --progress "https://github.com/MobileChromeApps/mobile-chrome-apps.git"', function() {
      scriptDir = path.join(origDir, 'mobile-chrome-apps');
      var scriptName = path.basename(process.argv[1]);
      // Copy the init script in to so that it will be used when hacking on it.
      copyFile(process.argv[1], path.join(scriptDir, scriptName), function() {
        chdir('');
        exec('"' + process.argv[0] + '" ' + scriptName, function() {
          exit(0);
        });
      });
    });
  } else {
    callback();
  }
}

function checkOutSubModules(callback) {
  chdir('');
  exec('git pull', function() {
    exec('git submodule init', function() {
      exec('git submodule update', callback);
    });
  });
}

function buildCordovaJs(callback) {
  chdir('cordova-js');
  var needsJake = true;
  computeGitVersion(function(version) {
    if (fs.existsSync('pkg/cordova.ios.js')) {
      needsJake = (fs.readFileSync('pkg/cordova.ios.js').toString().indexOf(version) != -1);
    }
    if (needsJake) {
      console.log('CordovaJS needs to be built.');
      exec('jake build', callback, function() {
        console.log('Jake not installed. Installing.');
        sudo('npm install -g jake', function() {
          exec('jake build', callback);
        });
      });
    } else {
      console.log('CordovaJS is up-to-date.');
      callback();
    }
  });
}

function initPlugman(callback) {
  chdir('cordova-plugman');
  exec('npm install', function() {
    sudo('npm link', callback);
  });
}

function initCli(callback) {
  chdir('cordova-cli');
  exec('npm install', function() {
    sudo('npm link', function() {
      exec('npm link plugman', callback);
    });
  });
}

function finished(callback) {
  console.log('You\'ve successfully set up for Mobile Chrome Apps.');
}

function waitForKey(callback) {
  console.log('press a key');
  function cont(key) {
    if (key == '\u0003') {
      process.exit(2);
    }
    process.stdin.removeListener('data', cont);
    process.stdin.pause();
    callback();
  }
  process.stdin.resume();
  process.stdin.setRawMode(true);
  process.stdin.on('data', cont);
}

var eventQueue = [];
eventQueue.push(checkGit);
eventQueue.push(checkOutSelf);
eventQueue.push(checkOutSubModules);
eventQueue.push(buildCordovaJs);
eventQueue.push(initPlugman);
eventQueue.push(initCli);
eventQueue.push(finished);

function pump() {
  eventQueue.shift()(pump);
}
pump();
<commit_msg>Tweak jscript -> node launcher snippet to work when node is installed<commit_after>/**
  Licensed to the Apache Software Foundation (ASF) under one
  or more contributor license agreements.  See the NOTICE file
  distributed with this work for additional information
  regarding copyright ownership.  The ASF licenses this file
  to you under the Apache License, Version 2.0 (the
  "License"); you may not use this file except in compliance
  with the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing,
  software distributed under the License is distributed on an
  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  KIND, either express or implied.  See the License for the
  specific language governing permissions and limitations
  under the License.
 */

if (typeof WScript != 'undefined') {
  var shell = WScript.CreateObject("WScript.Shell");
  try {
    var ret = shell.Run('cmd /c node "' + WScript.ScriptFullName + '" --pause_on_exit', 1, true);
  } catch (e) {
    shell.Popup('NodeJS is not installed. Please install it from http://nodejs.org');
    ret = 1;
  }
  WScript.Quit(ret);
}

process.on('uncaughtException', function(e) {
  fatal('Uncaught exception: ' + e);
});

var childProcess = require('child_process');
var fs = require('fs');
var path = require('path');
var isWindows = process.platform.slice(0, 3) == 'win';
var scriptDir = path.dirname(process.argv[1]);

function exit(code) {
  if (process.argv[2] == '--pause_on_exit') {
    waitForKey(function() {
      process.exit(code);
    });
  } else {
    process.exit(code);
  }
}

function fatal(msg) {
  console.error(msg);
  exit(1);
}

function exec(cmd, onSuccess, opt_onError, opt_silent) {
  var onError = opt_onError || function(e) {
    fatal('command failed: ' + cmd + '\n' + e);
  };
  if (!opt_silent) {
    console.log('Running: ' + cmd);
  }
  childProcess.exec(cmd, function(error, stdout, stderr) {
    if (error) {
      onError(error);
    } else {
      onSuccess(stdout.trim());
    }
  });
}

function sudo(cmd, onSuccess, opt_onError, silent) {
  if (!isWindows) {
    cmd = 'sudo ' + cmd;
  }
  exec(cmd, onSuccess, opt_onError, silent);
}

function copyFile(src, dst, callback) {
  var rd = fs.createReadStream(src);
  var wr = fs.createWriteStream(dst);
  wr.on('error', function(err) {
    fatal('Copy file error: ' + err);
  });
  wr.on('close', callback);
  rd.pipe(wr);
}

function recursiveDelete(dirPath) {
  if (fs.existsSync(dirPath)) {
    console.log('Deleting: ' + dirPath);
    helper(dirPath);
  }
  function helper(dirPath) {
    try {
       var files = fs.readdirSync(dirPath);
    } catch(e) {
      return;
    }
    for (var i = 0; i < files.length; i++) {
      var filePath = path.join(dirPath, files[i]);
      fs.chmodSync(filePath, '777');
      if (fs.statSync(filePath).isFile()) {
        fs.unlinkSync(filePath);
      } else {
        helper(filePath);
      }
    }
    fs.rmdirSync(dirPath);
  }
}

function checkGit(callback) {
  var errMsg = 'git is not installed (or not available on your PATH). Please install it from http://git-scm.com';
  exec('git --version', callback, function() {
    if (isWindows) {
      // See if it's at the default install path.
      process.env['PATH'] += ';' + path.join(process.env['ProgramFiles'], 'Git', 'bin');
      exec('git --version', callback, function() {
        fatal(errMsg);
      }, true);
    } else {
      fatal(errMsg);
    }
  }, true);
}

function computeGitVersion(callback) {
  exec('git describe --tags --long', function(stdout) {
    var version = stdout.replace(/^2.5.0-.*?-/, 'dev-');
    callback(version);
  }, null, true);
}

function chdir(d) {
  d = path.join(scriptDir, d);
  if (process.cwd() != d) {
    console.log('Changing directory to: ' + d);
    process.chdir(d);
  }
}

function checkOutSelf(callback) {
  // If the repo doesn't exist where the script is, then use the CWD as the checkout location.
  var origDir = process.cwd();
  var requiresClone = true;
  // First - try the directory of the script.
  if (scriptDir.slice(0, 2) != '\\\\') {
    process.chdir(scriptDir);
    requiresClone = !fs.existsSync('.git');
  }
  // Next - try the CWD.
  if (requiresClone) {
    scriptDir = origDir;
    process.chdir(scriptDir);
    requiresClone = !fs.existsSync('.git');
  }
  // Next - see if it exists within the CWD.
  if (requiresClone) {
    if (fs.existsSync(path.join(origDir, 'mobile-chrome-apps'))) {
      scriptDir = path.join(origDir, 'mobile-chrome-apps');
      process.chdir(scriptDir);
      requiresClone = !fs.existsSync('.git');
    }
  }
  if (requiresClone) {
    scriptDir = origDir;
    chdir('');
    recursiveDelete('mobile-chrome-apps');
    exec('git clone "https://github.com/MobileChromeApps/mobile-chrome-apps.git"', function() {
      scriptDir = path.join(origDir, 'mobile-chrome-apps');
      var scriptName = path.basename(process.argv[1]);
      // Copy the init script in to so that it will be used when hacking on it.
      copyFile(process.argv[1], path.join(scriptDir, scriptName), function() {
        chdir('');
        exec('"' + process.argv[0] + '" ' + scriptName, function() {
          exit(0);
        });
      });
    });
  } else {
    callback();
  }
}

function checkOutSubModules(callback) {
  chdir('');
  exec('git pull', function() {
    exec('git submodule init', function() {
      exec('git submodule update', callback);
    });
  });
}

function buildCordovaJs(callback) {
  chdir('cordova-js');
  var needsJake = true;
  computeGitVersion(function(version) {
    if (fs.existsSync('pkg/cordova.ios.js')) {
      needsJake = (fs.readFileSync('pkg/cordova.ios.js').toString().indexOf(version) != -1);
    }
    if (needsJake) {
      console.log('CordovaJS needs to be built.');
      exec('jake build', callback, function() {
        console.log('Jake not installed. Installing.');
        sudo('npm install -g jake', function() {
          exec('jake build', callback);
        });
      });
    } else {
      console.log('CordovaJS is up-to-date.');
      callback();
    }
  });
}

function initPlugman(callback) {
  chdir('cordova-plugman');
  exec('npm install', function() {
    sudo('npm link', callback);
  });
}

function initCli(callback) {
  chdir('cordova-cli');
  exec('npm install', function() {
    sudo('npm link', function() {
      exec('npm link plugman', callback);
    });
  });
}

function finished(callback) {
  console.log('You\'ve successfully set up for Mobile Chrome Apps.');
}

function waitForKey(callback) {
  console.log('press a key');
  function cont(key) {
    if (key == '\u0003') {
      process.exit(2);
    }
    process.stdin.removeListener('data', cont);
    process.stdin.pause();
    callback();
  }
  process.stdin.resume();
  process.stdin.setRawMode(true);
  process.stdin.on('data', cont);
}

var eventQueue = [];
eventQueue.push(checkGit);
eventQueue.push(checkOutSelf);
eventQueue.push(checkOutSubModules);
eventQueue.push(buildCordovaJs);
eventQueue.push(initPlugman);
eventQueue.push(initCli);
eventQueue.push(finished);

function pump() {
  eventQueue.shift()(pump);
}
pump();
<|endoftext|>


<commit_before>var kue = require('kue')
var mongoose = require('mongoose')
var raven = require('raven')
var workers = require('./lib/workers')

if(process.env.SENTRY_URL) {
	var c = new raven.Client(process.env.SENTRY_URL)
	c.patchGlobal()
}

mongoose.connect(process.env.MONGO_URL || process.env.MONGOLAB_URI, function(err) {
	if(err) {
		console.log(err)
		process.exit(1)
	}
})

queue = kue.createQueue({
	jobEvents: false
})

queue.process('battle', workers.battle)
queue.on('job complete', function() {
	process.exit(0)
})
<commit_msg>Shutdown gracefully<commit_after>var kue = require('kue')
var mongoose = require('mongoose')
var raven = require('raven')
var workers = require('./lib/workers')

if(process.env.SENTRY_URL) {
	var c = new raven.Client(process.env.SENTRY_URL)
	c.patchGlobal()
}

mongoose.connect(process.env.MONGO_URL || process.env.MONGOLAB_URI, function(err) {
	if(err) {
		console.log(err)
		process.exit(1)
	}
})

queue = kue.createQueue({
	jobEvents: false
})

queue.process('battle', function(job, done) {
	queue.shutdown(80000, function(err) {
		process.exit(0)
	})
	workers.battle(job, done)
})
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

'use strict';

/**
 * @param {!Object} manifest Parsed JSON manifest.
 * @return {!Array<{name: string, attr: !Object}>}
 */
function parse(manifest) {
  const out = [];

  function createMeta(name, value) {
    if (!value) { return; }
    out.push({
      name: 'meta',
      attr: {
        'name': name,
        'content': value === true ? 'yes' : value,
      },
    });
  }

  const capable = ['standalone', 'fullscreen'].indexOf(manifest['display']) !== -1;
  createMeta('apple-mobile-web-app-capable', capable);
  createMeta('mobile-web-app-capable', capable);
  createMeta('apple-mobile-web-app-title', manifest['short_name'] || manifest['name']);
  createMeta('msapplication-starturl', manifest['start_url'] || '/');
  createMeta('msapplication-TileColor', manifest['theme_color']);

  // nb. pwacompat does _not_ create the meta 'theme-color', as browsers that support the manifest
  // file don't use its 'theme_color' when the webpage is just loaded in a normal browser (as of
  // July 2016). So be sure to set it yourself.

  // TODO(samthor): Set 'apple-mobile-web-app-status-bar-style' to 'black' for dark theme-color,
  // and use 'default' for light theme-color.

  let itunes;
  (manifest['related_applications'] || [])
      .filter(app => app['platform'] == 'itunes')
      .forEach(app => {
        if (app['id']) {
          itunes = app['id'];
        } else {
          const match = app['url'].match(/id(\d+)/);
          if (match) {
            itunes = match[1];
          }
        }
      });
  if (itunes) {
    createMeta('apple-itunes-app', `app-id=${itunes}`)
  }

  // Parse the icons.
  const icons = manifest['icons'] || [];
  icons.sort((a, b) => {
    return parseInt(b.sizes, 10) - parseInt(a.sizes, 10);  // sort larger first
  });
  icons.forEach(icon => {
    out.push({
      name: 'icon',
      attr: {
        'rel': 'icon',
        'href': icon.src,
        'sizes': icon.sizes,
      },
    });
    out.push({
      name: 'icon',
      attr: {
        'rel': 'apple-touch-icon',
        'href': icon.src,
        'sizes': icon.sizes,
      },
    });
  });

  return out;
}

module.exports = parse;
<commit_msg>incorrect icon => link<commit_after>/*
 * Copyright 2016 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

'use strict';

/**
 * @param {!Object} manifest Parsed JSON manifest.
 * @return {!Array<{name: string, attr: !Object}>}
 */
function parse(manifest) {
  const out = [];

  function createMeta(name, value) {
    if (!value) { return; }
    out.push({
      name: 'meta',
      attr: {
        'name': name,
        'content': value === true ? 'yes' : value,
      },
    });
  }

  const capable = ['standalone', 'fullscreen'].indexOf(manifest['display']) !== -1;
  createMeta('apple-mobile-web-app-capable', capable);
  createMeta('mobile-web-app-capable', capable);
  createMeta('apple-mobile-web-app-title', manifest['short_name'] || manifest['name']);
  createMeta('msapplication-starturl', manifest['start_url'] || '/');
  createMeta('msapplication-TileColor', manifest['theme_color']);

  // nb. pwacompat does _not_ create the meta 'theme-color', as browsers that support the manifest
  // file don't use its 'theme_color' when the webpage is just loaded in a normal browser (as of
  // July 2016). So be sure to set it yourself.

  // TODO(samthor): Set 'apple-mobile-web-app-status-bar-style' to 'black' for dark theme-color,
  // and use 'default' for light theme-color.

  let itunes;
  (manifest['related_applications'] || [])
      .filter(app => app['platform'] == 'itunes')
      .forEach(app => {
        if (app['id']) {
          itunes = app['id'];
        } else {
          const match = app['url'].match(/id(\d+)/);
          if (match) {
            itunes = match[1];
          }
        }
      });
  if (itunes) {
    createMeta('apple-itunes-app', `app-id=${itunes}`)
  }

  // Parse the icons.
  const icons = manifest['icons'] || [];
  icons.sort((a, b) => {
    return parseInt(b.sizes, 10) - parseInt(a.sizes, 10);  // sort larger first
  });
  icons.forEach(icon => {
    out.push({
      name: 'link',
      attr: {
        'rel': 'icon',
        'href': icon.src,
        'sizes': icon.sizes,
      },
    });
    out.push({
      name: 'link',
      attr: {
        'rel': 'apple-touch-icon',
        'href': icon.src,
        'sizes': icon.sizes,
      },
    });
  });

  return out;
}

module.exports = parse;
<|endoftext|>


<commit_before>'use strict';

const async = require('async');
const fs = require('fs-extra');
const got = require('got');
const ora = require('ora');
const path = require('path');
const Polly = require('aws-sdk/clients/polly').Presigner;
const spawn = require('child_process').spawn;
const tempfile = require('tempfile');

const fileExtensions = {
  mp3: 'mp3',
  ogg_vorbis: 'ogg', // eslint-disable-line camelcase
  pcm: 'pcm',
};

// Set up the spinner.
let spinner = ora().start();
spinner.begin = text => {
  spinner.text = text;
  spinner.start();
};
spinner.end = () => {
  spinner.succeed();
};

exports.checkUsage = args => {
  spinner.stop();
  const minNumArgs = 2;
  const script = path.basename(process.argv[1]);
  const usageStatement = `Converts a text file to speech using the AWS Polly API.
Usage:
  ${script} INPUTFILE OUTPUTFILE [OPTIONS]
Required:
  INPUTFILE           The text file to convert
  OUTPUTFILE          The filename to save the audio to
Options:
  --help              Displays this info and exits
  --format FORMAT     Target audio format ("mp3", "ogg_vorbis", or "pcm") (default "mp3")
  --region REGION     AWS region to send requests to (default "us-east-1")
  --throttle SIZE     Number of simultaneous requests allowed against the AWS API (default 5)
  --voice VOICE       Voice to use for the speech (default "Joanna")
`;
  if (args.help) {
    process.stderr.write(usageStatement);
    process.exit(0);
  }
  if (args._.length < minNumArgs) {
    process.stderr.write(usageStatement);
    process.exit(1);
  }
};

exports.compressSpace = str => {
  return str.replace(/\s+/g, ' ');
};

// Returns a Promise with the temporary audio file.
exports.generateSpeech = (strParts, opts) => {
  // Add in the default options.
  opts = Object.assign({}, {
    format: opts.format || 'mp3',
    limit: Number(opts.throttle) || 5, // eslint-disable-line no-magic-numbers
    region: opts.region || 'us-east-1',
    voice: opts.voice || 'Joanna'
  }, opts);

  const secsPerMin = 60;
  const minsInHalfHour = 30;
  const halfHour = secsPerMin * minsInHalfHour;

  // Creates an object containing all the data.
  let buildInfo = text => {
    return {
      tempfile: tempfile(`.${fileExtensions[opts.format]}`),
      text: text
    };
  };

  // Create an AWS Polly instance.
  let polly = new Polly({
    apiVersion: '2016-06-10',
    region: opts.region
  });

  // Calls AWS Polly with the given info.
  let callAws = (info, i, callback) => {
    spinner.text = spinner.text.replace(/\d+\//, `${i}/`);
    let url = polly.getSynthesizeSpeechUrl({
      OutputFormat: opts.format,
      Text: info.text,
      VoiceId: opts.voice
    }, halfHour);
    let error;
    let outputStream = fs.createWriteStream(info.tempfile);
    outputStream.on('close', () => { callback(error); });
    got.stream(url).on('error', err => { error = err; }).pipe(outputStream);
  };

  // Calls the API for each text part (throttled). Returns a Promise.
  let generateAll = parts => {
    let count = parts.length;
    spinner.begin(`Convert to audio (0/${count})`);
    return (new Promise((resolve, reject) => {
      async.eachOfLimit(
        parts,
        opts.limit,
        callAws,
        err => {
          if (err) {
            spinner.fail();
            return reject(err);
          }
          spinner.text = spinner.text.replace(/\d+\//, `${count}/`);
          spinner.end();
          resolve(parts);
        }
      );
    }));
  };

  // Writes down all the temp files for ffmpeg to read in.
  // Returns the text filename.
  let createManifest = parts => {
    let txtFile = tempfile('.txt');
    let contents = parts.map(info => {
      return `file '${info.tempfile}'`;
    }).join('\n');
    fs.writeFileSync(txtFile, contents, 'utf8');
    return txtFile;
  };

  // Deletes the manifest and its files.
  let cleanup = manifestFile => {
    let manifest = fs.readFileSync(manifestFile, 'utf8');
    let regexpState = /^file\s+(.*)$/gm;
    let match;
    while ((match = regexpState.exec(manifest)) !== null) {
      fs.removeSync(match[1]);
    }
    fs.removeSync(manifestFile);
  };

  // Combines all the parts into one file.
  // Resolves with the new filename.
  let combine = manifestFile => {
    spinner.begin('Combine audio');
    let newFile = tempfile(`.${fileExtensions[opts.format]}`);
    let args = [
      '-f', 'concat',
      '-safe', '0',
      '-i', manifestFile,
      '-c', 'copy',
      newFile
    ];
    return (new Promise((resolve, reject) => {
      let ffmpeg = spawn('ffmpeg', args);
      let stderr = '';
      ffmpeg.stderr.on('data', (data) => {
        stderr += `\n${data}`;
      });
      ffmpeg.on('error', err => {
        reject(new Error('Could not start ffmpeg process'));
      });
      ffmpeg.on('close', code => {
        if (code > 0) {
          spinner.fail();
          return reject(new Error(`ffmpeg returned an error (${code}): ${stderr}`));
        }
        spinner.end();
        resolve(newFile);
      });
    })).then(audioFile => {
      spinner.begin('Clean up');
      cleanup(manifestFile);
      spinner.end();
      return audioFile;
    }).catch(err => {
      cleanup(manifestFile);
      throw err;
    });
  };

  // Compile the text parts and options together in a packet.
  let parts = strParts.map(buildInfo);

  return generateAll(parts)
    .then(createManifest)
    .then(combine);
};

exports.getSpinner = () => {
  return spinner;
};

exports.trim = str => {
  return str.trim();
};
<commit_msg>Fix regexp for parsing the manifest file.<commit_after>'use strict';

const async = require('async');
const fs = require('fs-extra');
const got = require('got');
const ora = require('ora');
const path = require('path');
const Polly = require('aws-sdk/clients/polly').Presigner;
const spawn = require('child_process').spawn;
const tempfile = require('tempfile');

const fileExtensions = {
  mp3: 'mp3',
  ogg_vorbis: 'ogg', // eslint-disable-line camelcase
  pcm: 'pcm',
};

// Set up the spinner.
let spinner = ora().start();
spinner.begin = text => {
  spinner.text = text;
  spinner.start();
};
spinner.end = () => {
  spinner.succeed();
};

exports.checkUsage = args => {
  spinner.stop();
  const minNumArgs = 2;
  const script = path.basename(process.argv[1]);
  const usageStatement = `Converts a text file to speech using the AWS Polly API.
Usage:
  ${script} INPUTFILE OUTPUTFILE [OPTIONS]
Required:
  INPUTFILE           The text file to convert
  OUTPUTFILE          The filename to save the audio to
Options:
  --help              Displays this info and exits
  --format FORMAT     Target audio format ("mp3", "ogg_vorbis", or "pcm") (default "mp3")
  --region REGION     AWS region to send requests to (default "us-east-1")
  --throttle SIZE     Number of simultaneous requests allowed against the AWS API (default 5)
  --voice VOICE       Voice to use for the speech (default "Joanna")
`;
  if (args.help) {
    process.stderr.write(usageStatement);
    process.exit(0);
  }
  if (args._.length < minNumArgs) {
    process.stderr.write(usageStatement);
    process.exit(1);
  }
};

exports.compressSpace = str => {
  return str.replace(/\s+/g, ' ');
};

// Returns a Promise with the temporary audio file.
exports.generateSpeech = (strParts, opts) => {
  // Add in the default options.
  opts = Object.assign({}, {
    format: opts.format || 'mp3',
    limit: Number(opts.throttle) || 5, // eslint-disable-line no-magic-numbers
    region: opts.region || 'us-east-1',
    voice: opts.voice || 'Joanna'
  }, opts);

  const secsPerMin = 60;
  const minsInHalfHour = 30;
  const halfHour = secsPerMin * minsInHalfHour;

  // Creates an object containing all the data.
  let buildInfo = text => {
    return {
      tempfile: tempfile(`.${fileExtensions[opts.format]}`),
      text: text
    };
  };

  // Create an AWS Polly instance.
  let polly = new Polly({
    apiVersion: '2016-06-10',
    region: opts.region
  });

  // Calls AWS Polly with the given info.
  let callAws = (info, i, callback) => {
    spinner.text = spinner.text.replace(/\d+\//, `${i}/`);
    let url = polly.getSynthesizeSpeechUrl({
      OutputFormat: opts.format,
      Text: info.text,
      VoiceId: opts.voice
    }, halfHour);
    let error;
    let outputStream = fs.createWriteStream(info.tempfile);
    outputStream.on('close', () => { callback(error); });
    got.stream(url).on('error', err => { error = err; }).pipe(outputStream);
  };

  // Calls the API for each text part (throttled). Returns a Promise.
  let generateAll = parts => {
    let count = parts.length;
    spinner.begin(`Convert to audio (0/${count})`);
    return (new Promise((resolve, reject) => {
      async.eachOfLimit(
        parts,
        opts.limit,
        callAws,
        err => {
          if (err) {
            spinner.fail();
            return reject(err);
          }
          spinner.text = spinner.text.replace(/\d+\//, `${count}/`);
          spinner.end();
          resolve(parts);
        }
      );
    }));
  };

  // Writes down all the temp files for ffmpeg to read in.
  // Returns the text filename.
  let createManifest = parts => {
    let txtFile = tempfile('.txt');
    let contents = parts.map(info => {
      return `file '${info.tempfile}'`;
    }).join('\n');
    fs.writeFileSync(txtFile, contents, 'utf8');
    return txtFile;
  };

  // Deletes the manifest and its files.
  let cleanup = manifestFile => {
    let manifest = fs.readFileSync(manifestFile, 'utf8');
    let regexpState = /^file\s+'(.*)'$/gm;
    let match;
    while ((match = regexpState.exec(manifest)) !== null) {
      fs.removeSync(match[1]);
    }
    fs.removeSync(manifestFile);
  };

  // Combines all the parts into one file.
  // Resolves with the new filename.
  let combine = manifestFile => {
    spinner.begin('Combine audio');
    let newFile = tempfile(`.${fileExtensions[opts.format]}`);
    let args = [
      '-f', 'concat',
      '-safe', '0',
      '-i', manifestFile,
      '-c', 'copy',
      newFile
    ];
    return (new Promise((resolve, reject) => {
      let ffmpeg = spawn('ffmpeg', args);
      let stderr = '';
      ffmpeg.stderr.on('data', (data) => {
        stderr += `\n${data}`;
      });
      ffmpeg.on('error', err => {
        reject(new Error('Could not start ffmpeg process'));
      });
      ffmpeg.on('close', code => {
        if (code > 0) {
          spinner.fail();
          return reject(new Error(`ffmpeg returned an error (${code}): ${stderr}`));
        }
        spinner.end();
        resolve(newFile);
      });
    })).then(audioFile => {
      spinner.begin('Clean up');
      cleanup(manifestFile);
      spinner.end();
      return audioFile;
    }).catch(err => {
      cleanup(manifestFile);
      throw err;
    });
  };

  // Compile the text parts and options together in a packet.
  let parts = strParts.map(buildInfo);

  return generateAll(parts)
    .then(createManifest)
    .then(combine);
};

exports.getSpinner = () => {
  return spinner;
};

exports.trim = str => {
  return str.trim();
};
<|endoftext|>


<commit_before>// Utility library
//

var request = require('request')
  , events = require('events')
  ;

exports.LOG_LEVEL = process.env.cqs_log_level || "info";

exports.scrub_creds = function scrub_creds(url) {
  return url.replace(/^(https?:\/\/)[^:]+:[^@]+@(.*)$/, '$1$2'); // Scrub username and password
}

exports.JP = JSON.parse;
exports.JS = JSON.stringify;
exports.JDUP = function(obj) { return JSON.parse(JSON.stringify(obj)) };

exports.copy = function(src, dst, pred) {
  pred = pred || function() { return true };
  if(pred === 'uppercase')
    pred = function(key) { return /^[A-Z]/.test(key) };

  Object.keys(src).forEach(function(key) {
    var val = src[key];
    if(pred(key, val))
      dst[key] = val;
  })
}

exports.opt_def = function(opts) {
  if(typeof opts === 'string')
    opts = {'_str': opts};
  else if(typeof opts === 'function')
    opts = {'_func': opts};
  return opts;
}

exports.req_json = function req_json(opts, callback) {
  if(typeof opts === 'string')
    opts = {'uri':opts};

  var couch_errors_are_ok = !! opts.couch_errors;

  opts.headers = opts.headers || {};
  opts.headers['accept']       = 'application/json';
  opts.headers['content-type'] = 'application/json';

  var started_at = new Date;
  var timer_ms = (opts.timeout || 5000) * (opts.time_C || 1.0);
  delete opts.time_C;

  //console.log('Request timeout will be: ' + timer_ms);
  var timed_out = false, timer = setTimeout(on_timeout, timer_ms);
  function on_timeout() {
    timed_out = true;
    var duration = (new Date) - started_at;
    callback(new Error('Request timeout (' + (duration/1000) + 's) : ' + opts.uri));
  }

  function on_req_done(er, resp, body) {
    clearTimeout(timer);
    if(timed_out)
      return;
    if(er)
      return callback(er);

    if(resp.statusCode < 200 || resp.statusCode >= 300)
      if(! couch_errors_are_ok)
        return callback(new Error('Couch response ' + resp.statusCode + ' to ' + opts.uri + ': ' + body));

    var obj;
    try           { obj = JSON.parse(body) }
    catch (js_er) { return callback(js_er) }

    return callback(null, resp, obj);
  }

  return request(opts, on_req_done);
}

exports.enc_id = function encode_doc_id(id) {
  return encodeURIComponent(id).replace(/^_design%2[fF]/, '_design/');
}

// Wrap log4js so it will not be a dependency.
var VERBOSE = !!process.env.verbose;

var noop = function() {};
var noops = { "trace": noop
            , "debug": VERBOSE ? console.log   : noop
            , "info" : console.info
            , "warn" : console.warn
            , "error": console.error
            , "fatal": console.error

            , "setLevel": noop
            }

try {
  exports.log4js = require('log4js');
} catch(e) {
  exports.log4js = function() {
    return { 'getLogger': function() { return noops }
           }
  }
}

//
// A simple run-once tool
//

exports.Once = Once;
function Once () {
  var self = this;

  self.task    = null;
  self.is_done = false;
  self.pending = null;
  self.result  = undefined;
}

Once.prototype.on_done = function(callback) {
  var self = this;

  if(self.is_done)
    return callback.apply(null, self.result);

  self.pending = self.pending || new events.EventEmitter;
  self.pending.on('done', callback);
}

Once.prototype.job = function(task) {
  var self = this;

  // Only the first .job() call does anything.
  if(self.task)
    return;
  self.task = task;

  self.pending = self.pending || new events.EventEmitter;

  function on_done() {
    self.is_done = true;
    self.result = Array.prototype.slice.call(arguments);
    self.pending.emit.apply(self.pending, ['done'].concat(self.result));
  }

  task(on_done);
}
<commit_msg>Do not follow redirects for anything<commit_after>// Utility library
//

var request = require('request')
  , events = require('events')
  ;

exports.LOG_LEVEL = process.env.cqs_log_level || "info";

exports.scrub_creds = function scrub_creds(url) {
  return url.replace(/^(https?:\/\/)[^:]+:[^@]+@(.*)$/, '$1$2'); // Scrub username and password
}

exports.JP = JSON.parse;
exports.JS = JSON.stringify;
exports.JDUP = function(obj) { return JSON.parse(JSON.stringify(obj)) };

exports.copy = function(src, dst, pred) {
  pred = pred || function() { return true };
  if(pred === 'uppercase')
    pred = function(key) { return /^[A-Z]/.test(key) };

  Object.keys(src).forEach(function(key) {
    var val = src[key];
    if(pred(key, val))
      dst[key] = val;
  })
}

exports.opt_def = function(opts) {
  if(typeof opts === 'string')
    opts = {'_str': opts};
  else if(typeof opts === 'function')
    opts = {'_func': opts};
  return opts;
}

exports.req_json = function req_json(opts, callback) {
  if(typeof opts === 'string')
    opts = {'uri':opts};

  var couch_errors_are_ok = !! opts.couch_errors;

  opts.headers = opts.headers || {};
  opts.headers['accept']       = 'application/json';
  opts.headers['content-type'] = 'application/json';

  if(!('followRedirect' in opts))
    opts.followRedirect = false;

  var started_at = new Date;
  var timer_ms = (opts.timeout || 5000) * (opts.time_C || 1.0);
  delete opts.time_C;

  //console.log('Request timeout will be: ' + timer_ms);
  var timed_out = false, timer = setTimeout(on_timeout, timer_ms);
  function on_timeout() {
    timed_out = true;
    var duration = (new Date) - started_at;
    callback(new Error('Request timeout (' + (duration/1000) + 's) : ' + opts.uri));
  }

  function on_req_done(er, resp, body) {
    clearTimeout(timer);
    if(timed_out)
      return;
    if(er)
      return callback(er);

    if(resp.statusCode < 200 || resp.statusCode >= 300)
      if(! couch_errors_are_ok)
        return callback(new Error('Couch response ' + resp.statusCode + ' to ' + opts.uri + ': ' + body));

    var obj;
    try           { obj = JSON.parse(body) }
    catch (js_er) { return callback(js_er) }

    return callback(null, resp, obj);
  }

  return request(opts, on_req_done);
}

exports.enc_id = function encode_doc_id(id) {
  return encodeURIComponent(id).replace(/^_design%2[fF]/, '_design/');
}

// Wrap log4js so it will not be a dependency.
var VERBOSE = !!process.env.verbose;

var noop = function() {};
var noops = { "trace": noop
            , "debug": VERBOSE ? console.log   : noop
            , "info" : console.info
            , "warn" : console.warn
            , "error": console.error
            , "fatal": console.error

            , "setLevel": noop
            }

try {
  exports.log4js = require('log4js');
} catch(e) {
  exports.log4js = function() {
    return { 'getLogger': function() { return noops }
           }
  }
}

//
// A simple run-once tool
//

exports.Once = Once;
function Once () {
  var self = this;

  self.task    = null;
  self.is_done = false;
  self.pending = null;
  self.result  = undefined;
}

Once.prototype.on_done = function(callback) {
  var self = this;

  if(self.is_done)
    return callback.apply(null, self.result);

  self.pending = self.pending || new events.EventEmitter;
  self.pending.on('done', callback);
}

Once.prototype.job = function(task) {
  var self = this;

  // Only the first .job() call does anything.
  if(self.task)
    return;
  self.task = task;

  self.pending = self.pending || new events.EventEmitter;

  function on_done() {
    self.is_done = true;
    self.result = Array.prototype.slice.call(arguments);
    self.pending.emit.apply(self.pending, ['done'].concat(self.result));
  }

  task(on_done);
}
<|endoftext|>


<commit_before>function getSuffix(filename)
{
  let pos = filename.lastIndexOf(".");
  if (pos == -1) {
    return null;
  }
  return filename.slice(pos + 1).toLowerCase();
}

function chooseIcon(path)
{
  let suffix = getSuffix(path);
  return { 'cpp': 'cpp', 'h': 'h', 'c': 'c', 'js': 'js', 'jsm': 'js', 'py': 'py' }[suffix] || "";
}

function readAnalysis(filePath, keep)
{
  let text = snarf(filePath);
  let lines = text.split("\n");
  lines.pop();

  let result = {sources: [], targets: []};

  let dummyCol = [0, 0];
  let analysisLine = 0;
  for (let l of lines) {
    analysisLine++;
    let j;
    try {
      j = JSON.parse(l);
    } catch (e) {
      print(`Bad JSON: ${filePath}:${analysisLine}. ${e}`);
    }
    if (!keep(j)) {
      continue;
    }

    let [line, col] = j.loc.split(":");
    if (col.indexOf("-") != -1) {
      [col1, col2] = col.split("-");
      col1 = parseInt(col1);
      col2 = parseInt(col2);
      col = [col1, col2];
    } else {
      col = dummyCol;
    }
    line = parseInt(line);
    j.loc = {line, col};

    if (j.source) {
      result.sources.push(j);
    } else if (j.target) {
      result.targets.push(j);
    }
  }

  function sortAnalysis(list) {
    list.sort(function(r1, r2) {
      if (r1.loc.line == r2.loc.line) {
        return r1.loc.col[0] - r2.loc.col[0];
      } else {
        return r1.loc.line - r2.loc.line;
      }
    });

    let result = [];
    let lastLoc = null;
    let lastElt = null;
    for (let j of list) {
      let loc = j.loc;
      if (lastLoc && loc.line == lastLoc.line && loc.col[0] == lastLoc.col[0]) {
        lastElt.push(j);
      } else {
        lastLoc = loc;

        let r = {loc, analysis: [j]};
        lastElt = r.analysis;
        result.push(r);
      }
    }

    return result;
  }

  result.sources = sortAnalysis(result.sources);
  result.targets = sortAnalysis(result.targets);

  return result;
}
<commit_msg>Possible fix for macro issue<commit_after>function getSuffix(filename)
{
  let pos = filename.lastIndexOf(".");
  if (pos == -1) {
    return null;
  }
  return filename.slice(pos + 1).toLowerCase();
}

function chooseIcon(path)
{
  let suffix = getSuffix(path);
  return { 'cpp': 'cpp', 'h': 'h', 'c': 'c', 'js': 'js', 'jsm': 'js', 'py': 'py' }[suffix] || "";
}

function readAnalysis(filePath, keep)
{
  let text = snarf(filePath);
  let lines = text.split("\n");
  lines.pop();

  let result = {sources: [], targets: []};

  let dummyCol = [0, 0];
  let analysisLine = 0;
  for (let l of lines) {
    analysisLine++;
    let j;
    try {
      j = JSON.parse(l);
    } catch (e) {
      print(`Bad JSON: ${filePath}:${analysisLine}. ${e}`);
    }
    if (!keep(j)) {
      continue;
    }

    let [line, col] = j.loc.split(":");
    if (col.indexOf("-") != -1) {
      [col1, col2] = col.split("-");
      col1 = parseInt(col1);
      col2 = parseInt(col2);
      col = [col1, col2];
    } else {
      col = parseInt(col);
      col = [col, col];
    }
    line = parseInt(line);
    j.loc = {line, col};

    if (j.source) {
      result.sources.push(j);
    } else if (j.target) {
      result.targets.push(j);
    }
  }

  function sortAnalysis(list) {
    list.sort(function(r1, r2) {
      if (r1.loc.line == r2.loc.line) {
        return r1.loc.col[0] - r2.loc.col[0];
      } else {
        return r1.loc.line - r2.loc.line;
      }
    });

    let result = [];
    let pushed = {};
    let lastLoc = null;
    let lastElt = null;
    for (let j of list) {
      let loc = j.loc;
      if (lastLoc && loc.line == lastLoc.line && loc.col[0] == lastLoc.col[0]) {
        let s = JSON.stringify(j);
        if (!(s in pushed)) {
          pushed[s] = true;
          lastElt.push(j);
        }
      } else {
        lastLoc = loc;

        pushed = {};
        let s = JSON.stringify(j);
        pushed[s] = true;

        let r = {loc, analysis: [j]};
        lastElt = r.analysis;
        result.push(r);
      }
    }

    return result;
  }

  result.sources = sortAnalysis(result.sources);
  result.targets = sortAnalysis(result.targets);

  return result;
}
<|endoftext|>


<commit_before>module.exports = {
  'enforce': function(f, msg) {
    if (!f()) {
      console.error("\u001b[31m" + msg + "\u001b[0m");
    }
  },

  'odd': function(x) {
    if ((x % 2) == 1) {
      return true;
    }
    return false;
  },

  'single': function(x) {
    return {'each': function(f) { return f(x); }};
  },

  'below': function(x) {
    return function(y) { return y < x; };
  },

  'above': function(x) {
    return function(y) { return y > x; };
  },

  'equal': function(x) {
    return function(y) { return y === x; };
  },

  'sorted': function(x) {
  	return (function(direction) {
	    return this.reduce(function(prev, next, i, arr) {
	      if (direction === undefined)
	        return (direction = prev <= next ? 1 : -1) || true;
	      else
	        return (direction + 1 ?
	          (arr[i-1] <= next) :
	          (arr[i-1] >  next));
	    }) ? Number(direction) : false;
	  }).call(this);
  },

  'all': function(x) {
    return {'each': function(f) {
    	return x.every(f);
    }};
  },
}
<commit_msg>Added a few library functions from design doc<commit_after>module.exports = {
  'enforce': function(f, msg) {
    if (!f()) {
      console.error("\u001b[31m" + msg + "\u001b[0m");
    }
  },

  'odd': function(x) {
    if ((x % 2) == 1) {
      return true;
    }
    return false;
  },

  'single': function(x) {
    return {'each': function(f) { return f(x); }};
  },

  'below': function(x) {
    return function(y) { return y < x; };
  },

  'above': function(x) {
    return function(y) { return y > x; };
  },

  'equal': function(x) {
    return function(y) { return y === x; };
  },

  'sorted': function(x) {
  	return (function(direction) {
	    return this.reduce(function(prev, next, i, arr) {
	      if (direction === undefined)
	        return (direction = prev <= next ? 1 : -1) || true;
	      else
	        return (direction + 1 ?
	          (arr[i-1] <= next) :
	          (arr[i-1] >  next));
	    }) ? Number(direction) : false;
	  }).call(this);
  },

  'all': function(arr) {
    return function(f) {
    	return arr.every(f);
    };
  },

  'number': function(x) {
  	return typeof x === 'number';
  },

  'string': function(x) {
  	return typeof x === 'string';
  },

  'array': function(x) {
  	return x.constructor === Array;
  },

  'object': function(x) {
  	return typeof x === 'object';
  },

  'function': function(x) {
  	return typeof(x) === 'function';
  },

  'in': function(arr) {
    return function(x) {
    	return arr.indexOf(x) !== -1;
    };
  }
}
<|endoftext|>


<commit_before>
var fs = require('fs')

var mkdirp = require('mkdirp');
var path = require('path')

var level = 0

exports.setLevelInfo = function(){
	level = 0
}
exports.setLevelWarn = function(){
	level = 1
}
exports.setLevelErr = function(){
	level = 2
}
exports.setLevelNone = function(){
	level = 3
}

function Logger(ws){
	this.ws = ws
	this.then = Date.now()
	this.dateStr = new Date(this.then).toString()
	this.cache = ''
	this.flushHandle = this._flush.bind(this)
	this.loggerHandle = this._log.bind(this)
	this.loggerHandle.info = this._info.bind(this)
	this.loggerHandle.warn = this._warn.bind(this)
	this.loggerHandle.err = this._err.bind(this)
}
Logger.prototype._flush = function flush(){
	this.ws.write(this.cache)
	this.cache = ''
}
Logger.prototype._logger = function(arr){
	var msg = ''
	for(var i=0;i<arr.length;++i){
		var part = arr[i]
		if(i !== 0) msg += ' '
		if(typeof(part) === 'object'){
			msg += JSON.stringify(part)
		}else{
			msg += part
		}
	}
	this._stampedLog(msg)
}
Logger.prototype._stampedLog = function(msg){
	msg = msg + ''
	var now = Date.now()
	if(now - this.then > 1000){
		this.then = now
		this.dateStr = new Date(now).toString()
	}
	if(this.cache.length === 0){
		setTimeout(this.flushHandle, 100)
	}
	this.cache += this.dateStr + ': ' + msg+'\n'
}

Logger.prototype._log = function _log(){
	if(level === 0){
		var arr = Array.prototype.slice.call(arguments)
		this._logger(arr)
	}
}

Logger.prototype._info = function(){
	if(level === 0){
		var arr = Array.prototype.slice.call(arguments)
		this._logger(arr)
	}
}
Logger.prototype._warn = function(){
	if(level <= 1){
		var arr = Array.prototype.slice.call(arguments)
		this._logger(arr)
	}
}
Logger.prototype._err = function(){
	if(level <= 2){
		var arr = Array.prototype.slice.call(arguments)
		this._logger(arr)
	}
}

exports.make = function(name){

	try{
		fs.mkdirSync('logs')
	}catch(e){
		if(e.code === 'EEXIST'){
		}else{
			throw e
		}
	}
	mkdirp.sync(path.dirname('logs/'+name+'.log'))
	var ws = fs.createWriteStream('logs/'+name+'.log')

	return new Logger(ws).loggerHandle

	/*

	var then = Date.now()
	var dateStr = new Date(then).toString()
	var cache = ''
	function flush(){
		ws.write(cache)
		cache = ''
	}
	function logger(arr){
		var msg = ''
		for(var i=0;i<arr.length;++i){
			var part = arr[i]
			if(i !== 0) msg += ' '
			if(typeof(part) === 'object'){
				msg += JSON.stringify(part)
			}else{
				msg += part
			}
		}
		//str += msg
		//if(str.length > 10000) str = ''
		stampedLog(msg)
	}
	function stampedLog(msg){
		msg = msg + ''
		var now = Date.now()
		if(now - then > 1000){
			then = now
			dateStr = new Date(then).toString()
		}
		if(cache.length === 0){
			setTimeout(flush, 100)
		}
		cache += dateStr + ': ' + msg+'\n'
	}

	function log(){
		if(level === 0){
			var arr = Array.prototype.slice.call(arguments)
			logger(arr)
		}
	}
	log.info = function(){
		if(level === 0){
			var arr = Array.prototype.slice.call(arguments)
			logger(arr)
		}
	}
	log.warn = function(){
		if(level <= 1){
			var arr = Array.prototype.slice.call(arguments)
			logger(arr)
		}
	}
	log.err = function(){
		if(level <= 2){
			var arr = Array.prototype.slice.call(arguments)
			logger(arr)
		}
	}
	return log*/
}

<commit_msg>improved logging completeness when uncaught exception thrown<commit_after>
var fs = require('fs')

var mkdirp = require('mkdirp');
var path = require('path')

var level = 0

exports.setLevelInfo = function(){
	level = 0
}
exports.setLevelWarn = function(){
	level = 1
}
exports.setLevelErr = function(){
	level = 2
}
exports.setLevelNone = function(){
	level = 3
}

var loggers = []
function uncaughtListener(err) {
	console.log('Caught exception: ' + err);
	process.removeListener('uncaughtException', uncaughtListener)
	var left = loggers.length
	for(var i=0;i<loggers.length;++i){
		var logger = loggers[i]
		logger._flush(function(){
			--left
			if(left === 0){
				throw err
			}
		})
	}
}
process.on('uncaughtException', uncaughtListener);

function Logger(ws){
	this.ws = ws
	this.then = Date.now()
	this.dateStr = new Date(this.then).toString()
	this.cache = ''
	this.flushHandle = this._flush.bind(this)
	this.loggerHandle = this._log.bind(this)
	this.loggerHandle.info = this._info.bind(this)
	this.loggerHandle.warn = this._warn.bind(this)
	this.loggerHandle.err = this._err.bind(this)
	loggers.push(this)
}
Logger.prototype._flush = function flush(cb){
	this.ws.write(this.cache)
	this.ws.flush(cb)
	this.cache = ''
}
Logger.prototype._logger = function(arr){
	var msg = ''
	for(var i=0;i<arr.length;++i){
		var part = arr[i]
		if(i !== 0) msg += ' '
		if(typeof(part) === 'object'){
			msg += JSON.stringify(part)
		}else{
			msg += part
		}
	}
	this._stampedLog(msg)
}
Logger.prototype._stampedLog = function(msg){
	msg = msg + ''
	var now = Date.now()
	if(now - this.then > 1000){
		this.then = now
		this.dateStr = new Date(now).toString()
	}
	if(this.cache.length === 0){
		setTimeout(this.flushHandle, 100)
	}
	this.cache += this.dateStr + ': ' + msg+'\n'
}

Logger.prototype._log = function _log(){
	if(level === 0){
		var arr = Array.prototype.slice.call(arguments)
		this._logger(arr)
	}
}

Logger.prototype._info = function(){
	if(level === 0){
		var arr = Array.prototype.slice.call(arguments)
		this._logger(arr)
	}
}
Logger.prototype._warn = function(){
	if(level <= 1){
		var arr = Array.prototype.slice.call(arguments)
		this._logger(arr)
	}
}
Logger.prototype._err = function(){
	if(level <= 2){
		var arr = Array.prototype.slice.call(arguments)
		this._logger(arr)
	}
}

exports.make = function(name){

	try{
		fs.mkdirSync('logs')
	}catch(e){
		if(e.code === 'EEXIST'){
		}else{
			throw e
		}
	}
	mkdirp.sync(path.dirname('logs/'+name+'.log'))
	var ws = fs.createWriteStream('logs/'+name+'.log')

	return new Logger(ws).loggerHandle

	/*

	var then = Date.now()
	var dateStr = new Date(then).toString()
	var cache = ''
	function flush(){
		ws.write(cache)
		cache = ''
	}
	function logger(arr){
		var msg = ''
		for(var i=0;i<arr.length;++i){
			var part = arr[i]
			if(i !== 0) msg += ' '
			if(typeof(part) === 'object'){
				msg += JSON.stringify(part)
			}else{
				msg += part
			}
		}
		//str += msg
		//if(str.length > 10000) str = ''
		stampedLog(msg)
	}
	function stampedLog(msg){
		msg = msg + ''
		var now = Date.now()
		if(now - then > 1000){
			then = now
			dateStr = new Date(then).toString()
		}
		if(cache.length === 0){
			setTimeout(flush, 100)
		}
		cache += dateStr + ': ' + msg+'\n'
	}

	function log(){
		if(level === 0){
			var arr = Array.prototype.slice.call(arguments)
			logger(arr)
		}
	}
	log.info = function(){
		if(level === 0){
			var arr = Array.prototype.slice.call(arguments)
			logger(arr)
		}
	}
	log.warn = function(){
		if(level <= 1){
			var arr = Array.prototype.slice.call(arguments)
			logger(arr)
		}
	}
	log.err = function(){
		if(level <= 2){
			var arr = Array.prototype.slice.call(arguments)
			logger(arr)
		}
	}
	return log*/
}

<|endoftext|>


<commit_before>/*
	This file is part of FacilMap.

	FacilMap is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	FacilMap is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with FacilMap.  If not, see <http://www.gnu.org/licenses/>.

	Obtain the source code from http://gitorious.org/facilmap.
*/

(function(fm, ol, $) {

window.initMap = function()
{
	window.mapObject = new fm.Map("map");

	// Readd keyboard control without onlyOnMouseOver setting, as the map is full-screen
	var keyboardControl = mapObject.getControlsByClass("FacilMap.Control.KeyboardDefaults")[0];
	if(keyboardControl)
	{
		keyboardControl.deactivate();
		mapObject.removeControl(keyboardControl);
	}
	mapObject.addControl(new fm.Control.KeyboardDefaults({ onlyOnMouseOver : false }));

	mapObject.addAllAvailableLayers();
	mapObject.addLayer(new fm.Layer.CoordinateGrid(null, { visibility: false, shortName: "grid" }));

	var activeTool = null;
	var cookies = document.cookie.split(/;\s*/);
	for(var i=0; i<cookies.length; i++)
	{
		var cookie = cookies[i].split("=");
		if(cookie[0] == "fmTool")
		{
			activeTool = decodeURIComponent(cookie[1]);
			break;
		}
	}

	mapObject.addControl(new fm.Control.GeoLocation());
	mapObject.addControl(new fm.Control.Search({ permalinkName : "s" }));

	mapObject.addControl(new FacilMap.Control.ToolsMenu.Default());

	var historyStateHandler = new fm.Control.HistoryStateHandler({ autoActivate: true, prefixWithMapId: false });
	// Patch q parameter for searching
	historyStateHandler.stateHandler.getState = function() {
		var obj = fm.HistoryStateHandler.prototype.getState.apply(this, arguments);
		if(obj.q)
		{
			if(!obj.c) obj.c = { };
			if(!obj.c.s) obj.c.s = { };

			var q = (""+obj.q).split(/\s+to\s+/i, 2);
			if(q.length == 1)
				obj.c.s.query = q[0];
			else {
				obj.c.s.from = q[0];
				obj.c.s.to = q[1];
			}

			if(obj.lon == undefined && obj.lat == undefined && obj.zoom == undefined)
				obj.c.s.zoom = "1";
			delete obj.q;
		}
		return obj;
	};
	historyStateHandler.stateHandler.setState = function(obj) {
		if(obj && obj.c && obj.c.s) {
			if(obj.c.s.query != null) {
				obj.q = obj.c.s.query;
				delete obj.c.s.query;
			} else if(obj.c.s.from != null && obj.c.s.to != null) {
				obj.q = obj.c.s.from+" to "+obj.c.s.to;
				delete obj.c.s.from;
				delete obj.c.s.to;
			}
		}
		fm.HistoryStateHandler.prototype.setState.apply(this, [ obj ]);
	};
	mapObject.addControl(historyStateHandler);

	$(".olMap .fmControlSearch .from").attr("name", "q");

	$(".olControlPanel").mouseover(
		function(){ fm.Util.changeOpacity(this, 1); }
	).mouseout(
		function(){ fm.Util.changeOpacity(this, 0.5); }
	).mouseout();
}

ol.Lang.en = ol.Util.extend(ol.Lang.en, {
	"Move map" : "Move map",
	"OpenStreetBugs" : "OpenStreetBugs",
	"Markers" : "Markers"
});

ol.Lang.de = ol.Util.extend(ol.Lang.de, {
	"Move map" : "Karte verschieben",
	"OpenStreetBugs" : "OpenStreetBugs",
	"Markers" : "Marker"
});

})(FacilMap, OpenLayers, FacilMap.$);<commit_msg>Adapted to changes in search form<commit_after>/*
	This file is part of FacilMap.

	FacilMap is free software: you can redistribute it and/or modify
	it under the terms of the GNU Affero General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	FacilMap is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Affero General Public License for more details.

	You should have received a copy of the GNU Affero General Public License
	along with FacilMap.  If not, see <http://www.gnu.org/licenses/>.

	Obtain the source code from http://gitorious.org/facilmap.
*/

(function(fm, ol, $) {

window.initMap = function()
{
	window.mapObject = new fm.Map("map");

	// Readd keyboard control without onlyOnMouseOver setting, as the map is full-screen
	var keyboardControl = mapObject.getControlsByClass("FacilMap.Control.KeyboardDefaults")[0];
	if(keyboardControl)
	{
		keyboardControl.deactivate();
		mapObject.removeControl(keyboardControl);
	}
	mapObject.addControl(new fm.Control.KeyboardDefaults({ onlyOnMouseOver : false }));

	mapObject.addAllAvailableLayers();
	mapObject.addLayer(new fm.Layer.CoordinateGrid(null, { visibility: false, shortName: "grid" }));

	var activeTool = null;
	var cookies = document.cookie.split(/;\s*/);
	for(var i=0; i<cookies.length; i++)
	{
		var cookie = cookies[i].split("=");
		if(cookie[0] == "fmTool")
		{
			activeTool = decodeURIComponent(cookie[1]);
			break;
		}
	}

	mapObject.addControl(new fm.Control.GeoLocation());
	mapObject.addControl(new fm.Control.Search({ permalinkName : "s" }));

	mapObject.addControl(new FacilMap.Control.ToolsMenu.Default());

	var historyStateHandler = new fm.Control.HistoryStateHandler({ autoActivate: true, prefixWithMapId: false });
	// Patch q parameter for searching
	historyStateHandler.stateHandler.getState = function() {
		var obj = fm.HistoryStateHandler.prototype.getState.apply(this, arguments);
		if(obj.q)
		{
			if(!obj.c) obj.c = { };
			if(!obj.c.s) obj.c.s = { };

			if(typeof obj.q == "string") {
				var q = obj.q.split(/\s+to\s+/i, 2);
				if(q.length == 1)
					obj.c.s.query = q[0];
				else
					obj.c.s.query = q;
			} else {
				obj.c.s.query = obj.q;
			}

			if(obj.lon == undefined && obj.lat == undefined && obj.zoom == undefined)
				obj.c.s.zoom = "1";
			delete obj.q;
		}
		return obj;
	};
	historyStateHandler.stateHandler.setState = function(obj) {
		if(obj && obj.c && obj.c.s) {
			if(obj.c.s.query != null) {
				obj.q = obj.c.s.query;
				delete obj.c.s.query;
			} else if(obj.c.s.from != null && obj.c.s.to != null) {
				obj.q = obj.c.s.from+" to "+obj.c.s.to;
				delete obj.c.s.from;
				delete obj.c.s.to;
			}
		}
		fm.HistoryStateHandler.prototype.setState.apply(this, [ obj ]);
	};
	mapObject.addControl(historyStateHandler);

	$(".olMap .fmControlSearch .from").attr("name", "q");

	$(".olControlPanel").mouseover(
		function(){ fm.Util.changeOpacity(this, 1); }
	).mouseout(
		function(){ fm.Util.changeOpacity(this, 0.5); }
	).mouseout();
}

ol.Lang.en = ol.Util.extend(ol.Lang.en, {
	"Move map" : "Move map",
	"OpenStreetBugs" : "OpenStreetBugs",
	"Markers" : "Markers"
});

ol.Lang.de = ol.Util.extend(ol.Lang.de, {
	"Move map" : "Karte verschieben",
	"OpenStreetBugs" : "OpenStreetBugs",
	"Markers" : "Marker"
});

})(FacilMap, OpenLayers, FacilMap.$);<|endoftext|>