<commit_before>/*
 * MelonJS Game Engine
 * Copyright (C) 2011 - 2013, Olivier BIOT
 * http://www.melonjs.org
 *
 * Font / Bitmap font
 *
 * ASCII Table
 * http://www.asciitable.com/
 * [ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz]
 *
 * -> first char " " 32d (0x20);
 */

(function($) {

	/**
	 * a generic system font object.
	 * @class
	 * @extends Object
	 * @memberOf me
	 * @constructor
	 * @param {String} font a CSS font name
	 * @param {Number|String} size size, or size + suffix (px, em, pt)
	 * @param {String} color a CSS color value
	 * @param {String} [textAlign="left"] horizontal alignment
	 */
    me.Font = me.Renderable.extend(
    /** @scope me.Font.prototype */ {

		// private font properties
		/** @ignore */
		font : null,
        fontSize : null,
        color : null,

		/**
		 * Set the default text alignment (or justification),

		 * possible values are "left", "right", and "center".

		 * Default value : "left"
		 * @public
		 * @type String
		 * @name me.Font#textAlign
		 */
		textAlign : "left",

		/**
		 * Set the text baseline (e.g. the Y-coordinate for the draw operation),

		 * possible values are "top", "hanging, "middle, "alphabetic, "ideographic, "bottom"

		 * Default value : "top"
		 * @public
		 * @type String
		 * @name me.Font#textBaseline
		 */
		textBaseline : "top",

		/**
		 * Set the line height (when displaying multi-line strings).

		 * Current font height will be multiplied with this value to set the line height.
		 * Default value : 1.0
		 * @public
		 * @type Number
		 * @name me.Font#lineHeight
		 */
		lineHeight : 1.0,

		/** @ignore */
		init : function(font, size, color, textAlign) {
            this.pos = new me.Vector2d();
            this.fontSize = new me.Vector2d();

			// font name and type
			this.set(font, size, color, textAlign);

            // parent constructor
            this.parent(this.pos, 0, this.fontSize.y);
		},

		/**
		 * make the font bold
		 * @name bold
		 * @memberOf me.Font
		 * @function
		 */
		bold : function() {
			this.font = "bold " + this.font;
		},

		/**
		 * make the font italic
		 * @name italic
		 * @memberOf me.Font
		 * @function
		 */
		italic : function() {
			this.font = "italic " + this.font;
		},

		/**
		 * Change the font settings
		 * @name set
		 * @memberOf me.Font
		 * @function
		 * @param {String} font a CSS font name
		 * @param {Number|String} size size, or size + suffix (px, em, pt)
		 * @param {String} color a CSS color value
		 * @param {String} [textAlign="left"] horizontal alignment
		 * @example
		 * font.set("Arial", 20, "white");
		 * font.set("Arial", "1.5em", "white");
		 */
		set : function(font, size, color, textAlign) {
			// font name and type
			var font_names = font.split(",");
			for (var i = 0; i < font_names.length; i++) {
				font_names[i] = "'" + font_names[i] + "'";
			}

            this.fontSize.y = parseInt(size, 10);
			this.height = this.fontSize.y;

            if (typeof size === "number") {
				size = "" + size + "px";
			}
			this.font = size + " " + font_names.join(",");
			this.color = color;
			if (textAlign) {
				this.textAlign = textAlign;
			}
		},

		/**
		 * measure the given text size in pixels
		 * @name measureText
		 * @memberOf me.Font
		 * @function
		 * @param {Context} context 2D Context
		 * @param {String} text
		 * @return {Object} returns an object, with two attributes: width (the width of the text) and height (the height of the text).
		 */
		measureText : function(context, text) {
			// draw the text
			context.font = this.font;
			context.fillStyle = this.color;
			context.textAlign = this.textAlign;
			context.textBaseline = this.textBaseline;

            this.height = this.width = 0;

			var strings = (""+text).split("\n");
			for (var i = 0; i < strings.length; i++) {
				this.width = Math.max(context.measureText(strings[i].trimRight()).width, this.width);
				this.height += this.fontSize.y * this.lineHeight;
			}
			return {width: this.width, height: this.height};
		},

		/**
		 * draw a text at the specified coord
		 * @name draw
		 * @memberOf me.Font
		 * @function
		 * @param {Context} context 2D Context
		 * @param {String} text
		 * @param {Number} x
		 * @param {Number} y
		 */
		draw : function(context, text, x, y) {
			// update initial position
            this.pos.set(x,y);

            // draw the text
			context.font = this.font;
			context.fillStyle = this.color;
			context.textAlign = this.textAlign;
			context.textBaseline = this.textBaseline;

			var strings = (""+text).split("\n");
			for (var i = 0; i < strings.length; i++) {
				// draw the string
				context.fillText(strings[i].trimRight(), ~~x, ~~y);
				// add leading space
				y += this.fontSize.y * this.lineHeight;
			}

		}
	});

	/**
	 * a bitpmap font object
	 * @class
	 * @extends me.Font
	 * @memberOf me
	 * @constructor
	 * @param {String} font
	 * @param {Number|Object} size either an int value, or an object like {x:16,y:16}
	 * @param {Number} [scale="1.0"]
	 * @param {String} [firstChar="0x20"]
	 */
    me.BitmapFont = me.Font.extend(
    /** @scope me.BitmapFont.prototype */ {
		/** @ignore */
        // font scale;
		sSize : null,
		// first char in the ascii table
		firstChar : 0x20,

		// #char per row
		charCount : 0,

		/** @ignore */
		init : function(font, size, scale, firstChar) {
			// font name and type
			this.parent(font, null, null);

			// font scaled size;
			this.sSize = new me.Vector2d();

			// first char in the ascii table
			this.firstChar = firstChar || 0x20;

			// load the font metrics
			this.loadFontMetrics(font, size);

			// set a default alignement
			this.textAlign = "left";
			this.textBaseline = "top";

			// resize if necessary
			if (scale) {
				this.resize(scale);
			}

		},

		/**
		 * Load the font metrics
		 * @ignore
		 */
		loadFontMetrics : function(font, size) {
			this.font = me.loader.getImage(font);

			// some cheap metrics
			this.fontSize.x = size.x || size;
			this.fontSize.y = size.y || this.font.height;
			this.sSize.copy(this.fontSize);
			this.height = this.sSize.y;

			// #char per row
			this.charCount = ~~(this.font.width / this.fontSize.x);
		},

		/**
		 * change the font settings
		 * @name set
		 * @memberOf me.BitmapFont
		 * @function
		 * @param {String} textAlign ("left", "center", "right")
		 * @param {Number} [scale]
		 */
		set : function(textAlign, scale) {
			this.textAlign = textAlign;
			// updated scaled Size
			if (scale) {
				this.resize(scale);
			}
		},

		/**
		 * change the font display size
		 * @name resize
		 * @memberOf me.BitmapFont
		 * @function
		 * @param {Number} scale ratio
		 */
		resize : function(scale) {
			// updated scaled Size
			this.sSize.setV(this.fontSize);
			this.sSize.x *= scale;
			this.sSize.y *= scale;
            this.height = this.sSize.y;
        },

		/**
		 * measure the given text size in pixels
		 * @name measureText
		 * @memberOf me.BitmapFont
		 * @function
		 * @param {Context} context 2D Context
		 * @param {String} text
		 * @return {Object} returns an object, with two attributes: width (the width of the text) and height (the height of the text).
		 */
		measureText : function(context, text) {

			var strings = (""+text).split("\n");

            this.height = this.width = 0;

			for (var i = 0; i < strings.length; i++) {
				this.width = Math.max((strings[i].trimRight().length * this.sSize.x), this.width);
				this.height += this.sSize.y * this.lineHeight;
			}
			return {width: this.width, height: this.height};
		},

		/**
		 * draw a text at the specified coord
		 * @name draw
		 * @memberOf me.BitmapFont
		 * @function
		 * @param {Context} context 2D Context
		 * @param {String} text
		 * @param {Number} x
		 * @param {Number} y
		 */
		draw : function(context, text, x, y) {
			var strings = (""+text).split("\n");
			var lX = x;
			var height = this.sSize.y * this.lineHeight;
			// update initial position
            this.pos.set(x,y);
            for (var i = 0; i < strings.length; i++) {
				x = lX;
				var string = strings[i].trimRight();
				// adjust x pos based on alignment value
				var width = string.length * this.sSize.x;
				switch(this.textAlign) {
					case "right":
						x -= width;
						break;

					case "center":
						x -= width * 0.5;
						break;

					default :
						break;
				}

				// adjust y pos based on alignment value
				switch(this.textBaseline) {
					case "middle":
						y -= height * 0.5;
						break;

					case "ideographic":
					case "alphabetic":
					case "bottom":
						y -= height;
						break;

					default :
						break;
				}

				// draw the string
				for ( var c = 0,len = string.length; c < len; c++) {
					// calculate the char index
					var idx = string.charCodeAt(c) - this.firstChar;
					if (idx >= 0) {
						// draw it
						context.drawImage(this.font,
							this.fontSize.x * (idx % this.charCount),
							this.fontSize.y * ~~(idx / this.charCount),
							this.fontSize.x, this.fontSize.y,
							~~x, ~~y,
							this.sSize.x, this.sSize.y);
					}
					x += this.sSize.x;
				}
				// increment line
				y += height;
			}
		}
	});

	/*---------------------------------------------------------*/
	// END END END
	/*---------------------------------------------------------*/
})(window);
<commit_msg>[#299] renamed the `me.Font` `color` property to a more correct `fillStyle` name and made it public<commit_after>/*
 * MelonJS Game Engine
 * Copyright (C) 2011 - 2013, Olivier BIOT
 * http://www.melonjs.org
 *
 * Font / Bitmap font
 *
 * ASCII Table
 * http://www.asciitable.com/
 * [ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz]
 *
 * -> first char " " 32d (0x20);
 */

(function($) {

	/**
	 * a generic system font object.
	 * @class
	 * @extends Object
	 * @memberOf me
	 * @constructor
	 * @param {String} font a CSS font name
	 * @param {Number|String} size size, or size + suffix (px, em, pt)
	 * @param {String} fillStyle a CSS color value
	 * @param {String} [textAlign="left"] horizontal alignment
	 */
    me.Font = me.Renderable.extend(
    /** @scope me.Font.prototype */ {

		// private font properties
		/** @ignore */
		font : null,
        fontSize : null,

		/**
		 * defines the color used to draw the font.

		 * Default value : "#000000"
		 * @public
		 * @type String
		 * @name me.Font#fillStyle
		 */
		fillStyle : "#000000",

		/**
		 * Set the default text alignment (or justification),

		 * possible values are "left", "right", and "center".

		 * Default value : "left"
		 * @public
		 * @type String
		 * @name me.Font#textAlign
		 */
		textAlign : "left",

		/**
		 * Set the text baseline (e.g. the Y-coordinate for the draw operation),

		 * possible values are "top", "hanging, "middle, "alphabetic, "ideographic, "bottom"

		 * Default value : "top"
		 * @public
		 * @type String
		 * @name me.Font#textBaseline
		 */
		textBaseline : "top",

		/**
		 * Set the line height (when displaying multi-line strings).

		 * Current font height will be multiplied with this value to set the line height.
		 * Default value : 1.0
		 * @public
		 * @type Number
		 * @name me.Font#lineHeight
		 */
		lineHeight : 1.0,

		/** @ignore */
		init : function(font, size, fillStyle, textAlign) {
            this.pos = new me.Vector2d();
            this.fontSize = new me.Vector2d();

			// font name and type
			this.set(font, size, fillStyle, textAlign);

            // parent constructor
            this.parent(this.pos, 0, this.fontSize.y);
		},

		/**
		 * make the font bold
		 * @name bold
		 * @memberOf me.Font
		 * @function
		 */
		bold : function() {
			this.font = "bold " + this.font;
		},

		/**
		 * make the font italic
		 * @name italic
		 * @memberOf me.Font
		 * @function
		 */
		italic : function() {
			this.font = "italic " + this.font;
		},

		/**
		 * Change the font settings
		 * @name set
		 * @memberOf me.Font
		 * @function
		 * @param {String} font a CSS font name
		 * @param {Number|String} size size, or size + suffix (px, em, pt)
		 * @param {String} fillStyle a CSS color value
		 * @param {String} [textAlign="left"] horizontal alignment
		 * @example
		 * font.set("Arial", 20, "white");
		 * font.set("Arial", "1.5em", "white");
		 */
		set : function(font, size, fillStyle, textAlign) {
			// font name and type
			var font_names = font.split(",");
			for (var i = 0; i < font_names.length; i++) {
				font_names[i] = "'" + font_names[i] + "'";
			}

            this.fontSize.y = parseInt(size, 10);
			this.height = this.fontSize.y;

            if (typeof size === "number") {
				size = "" + size + "px";
			}
			this.font = size + " " + font_names.join(",");
			this.fillStyle = fillStyle;
			if (textAlign) {
				this.textAlign = textAlign;
			}
		},

		/**
		 * measure the given text size in pixels
		 * @name measureText
		 * @memberOf me.Font
		 * @function
		 * @param {Context} context 2D Context
		 * @param {String} text
		 * @return {Object} returns an object, with two attributes: width (the width of the text) and height (the height of the text).
		 */
		measureText : function(context, text) {
			// draw the text
			context.font = this.font;
			context.fillStyle = this.fillStyle;
			context.textAlign = this.textAlign;
			context.textBaseline = this.textBaseline;

            this.height = this.width = 0;

			var strings = (""+text).split("\n");
			for (var i = 0; i < strings.length; i++) {
				this.width = Math.max(context.measureText(strings[i].trimRight()).width, this.width);
				this.height += this.fontSize.y * this.lineHeight;
			}
			return {width: this.width, height: this.height};
		},

		/**
		 * draw a text at the specified coord
		 * @name draw
		 * @memberOf me.Font
		 * @function
		 * @param {Context} context 2D Context
		 * @param {String} text
		 * @param {Number} x
		 * @param {Number} y
		 */
		draw : function(context, text, x, y) {
			// update initial position
            this.pos.set(x,y);

            // draw the text
			context.font = this.font;
			context.fillStyle = this.fillStyle;
			context.textAlign = this.textAlign;
			context.textBaseline = this.textBaseline;

			var strings = (""+text).split("\n");
			for (var i = 0; i < strings.length; i++) {
				// draw the string
				context.fillText(strings[i].trimRight(), ~~x, ~~y);
				// add leading space
				y += this.fontSize.y * this.lineHeight;
			}

		}
	});

	/**
	 * a bitpmap font object
	 * @class
	 * @extends me.Font
	 * @memberOf me
	 * @constructor
	 * @param {String} font
	 * @param {Number|Object} size either an int value, or an object like {x:16,y:16}
	 * @param {Number} [scale="1.0"]
	 * @param {String} [firstChar="0x20"]
	 */
    me.BitmapFont = me.Font.extend(
    /** @scope me.BitmapFont.prototype */ {
		/** @ignore */
        // font scale;
		sSize : null,
		// first char in the ascii table
		firstChar : 0x20,

		// #char per row
		charCount : 0,

		/** @ignore */
		init : function(font, size, scale, firstChar) {
			// font name and type
			this.parent(font, null, null);

			// font scaled size;
			this.sSize = new me.Vector2d();

			// first char in the ascii table
			this.firstChar = firstChar || 0x20;

			// load the font metrics
			this.loadFontMetrics(font, size);

			// set a default alignement
			this.textAlign = "left";
			this.textBaseline = "top";

			// resize if necessary
			if (scale) {
				this.resize(scale);
			}

		},

		/**
		 * Load the font metrics
		 * @ignore
		 */
		loadFontMetrics : function(font, size) {
			this.font = me.loader.getImage(font);

			// some cheap metrics
			this.fontSize.x = size.x || size;
			this.fontSize.y = size.y || this.font.height;
			this.sSize.copy(this.fontSize);
			this.height = this.sSize.y;

			// #char per row
			this.charCount = ~~(this.font.width / this.fontSize.x);
		},

		/**
		 * change the font settings
		 * @name set
		 * @memberOf me.BitmapFont
		 * @function
		 * @param {String} textAlign ("left", "center", "right")
		 * @param {Number} [scale]
		 */
		set : function(textAlign, scale) {
			this.textAlign = textAlign;
			// updated scaled Size
			if (scale) {
				this.resize(scale);
			}
		},

		/**
		 * change the font display size
		 * @name resize
		 * @memberOf me.BitmapFont
		 * @function
		 * @param {Number} scale ratio
		 */
		resize : function(scale) {
			// updated scaled Size
			this.sSize.setV(this.fontSize);
			this.sSize.x *= scale;
			this.sSize.y *= scale;
            this.height = this.sSize.y;
        },

		/**
		 * measure the given text size in pixels
		 * @name measureText
		 * @memberOf me.BitmapFont
		 * @function
		 * @param {Context} context 2D Context
		 * @param {String} text
		 * @return {Object} returns an object, with two attributes: width (the width of the text) and height (the height of the text).
		 */
		measureText : function(context, text) {

			var strings = (""+text).split("\n");

            this.height = this.width = 0;

			for (var i = 0; i < strings.length; i++) {
				this.width = Math.max((strings[i].trimRight().length * this.sSize.x), this.width);
				this.height += this.sSize.y * this.lineHeight;
			}
			return {width: this.width, height: this.height};
		},

		/**
		 * draw a text at the specified coord
		 * @name draw
		 * @memberOf me.BitmapFont
		 * @function
		 * @param {Context} context 2D Context
		 * @param {String} text
		 * @param {Number} x
		 * @param {Number} y
		 */
		draw : function(context, text, x, y) {
			var strings = (""+text).split("\n");
			var lX = x;
			var height = this.sSize.y * this.lineHeight;
			// update initial position
            this.pos.set(x,y);
            for (var i = 0; i < strings.length; i++) {
				x = lX;
				var string = strings[i].trimRight();
				// adjust x pos based on alignment value
				var width = string.length * this.sSize.x;
				switch(this.textAlign) {
					case "right":
						x -= width;
						break;

					case "center":
						x -= width * 0.5;
						break;

					default :
						break;
				}

				// adjust y pos based on alignment value
				switch(this.textBaseline) {
					case "middle":
						y -= height * 0.5;
						break;

					case "ideographic":
					case "alphabetic":
					case "bottom":
						y -= height;
						break;

					default :
						break;
				}

				// draw the string
				for ( var c = 0,len = string.length; c < len; c++) {
					// calculate the char index
					var idx = string.charCodeAt(c) - this.firstChar;
					if (idx >= 0) {
						// draw it
						context.drawImage(this.font,
							this.fontSize.x * (idx % this.charCount),
							this.fontSize.y * ~~(idx / this.charCount),
							this.fontSize.x, this.fontSize.y,
							~~x, ~~y,
							this.sSize.x, this.sSize.y);
					}
					x += this.sSize.x;
				}
				// increment line
				y += height;
			}
		}
	});

	/*---------------------------------------------------------*/
	// END END END
	/*---------------------------------------------------------*/
})(window);
<|endoftext|>


<commit_before>/**
 * @file NodeJS File system implementation
 * @since 0.1.9
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_FS_OPENFOR*/ // File system stream opening mode
/*global _GPF_FS_TYPES*/ // File system types constants
/*global _GPF_HOST*/ // Host types
/*global _GpfNodeBaseStream*/ // gpf.node.BaseStream
/*global _GpfNodeReadableStream*/ // gpf.node.ReadableStream
/*global _GpfNodeWritableStream*/ // gpf.node.WritableStream
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfFsSetFileStorageIf*/
/*global _gpfFsExploreEnumerator*/ // IFileStorage.explore helper
/*global _gpfNodeFs*/ // Node/PhantomJS require("fs")
/*global _gpfNodePath*/ // Node require("path")
/*global _gpfPathJoin*/ // Join all arguments together and normalize the resulting path
/*global _gpfPathNormalize*/ // Normalize path
/*#endif*/

/*jshint node:true*/
/*eslint-env node*/

/*eslint-ignore no-unused-vars*/

/**
 * Encapsulate fs API with a list of parameters inside a Promise
 *
 * @param {String} methodName fs method name
 * @param {Array} args Argument array
 * @return {Promise<*>} Resolved with API result
 * @gpf:closure
 * @since 0.1.9
 */
function _gpfFsNodeFsCall (methodName, args) {
    return new Promise(function (resolve, reject) {
        _gpfNodeFs[methodName].apply(_gpfNodeFs, args.concat([function (err, result) {
            if (err) {
                reject(err);
            } else {
                resolve(result);
            }
        }]));
    });
}

/**
 * Encapsulate fs API taking a path parameter inside a Promise
 *
 * @param {String} methodName fs method name
 * @param {String} path file path
 * @return {Promise<*>} Resolved with API result
 * @gpf:closure
 * @since 0.1.9
 */
function _gpfFsNodeFsCallWithPath (methodName, path) {
    return _gpfFsNodeFsCall(methodName, [_gpfPathNormalize(path)]);
}

function _gpfFsNodeOpenTextStream (path, options) {
    return _gpfFsNodeFsCall("open", [_gpfPathNormalize(path), options.flags])
        .then(function (fd) {
            return new options.GpfStream(_gpfNodeFs[options.nodeStream]("", {
                fd: fd,
                autoClose: false
            }), _gpfFsNodeFsCall.bind(null, "close", [fd]));
        });
}

/**
 * Open a text stream for reading
 *
 * @param {String} path File path
 * @return {Promise<gpf.interfaces.IReadableStream>} gpf.node.ReadableStream
 * @since 0.1.9
 */
function _gpfFsNodeOpenTextStreamForReading (path) {
    return _gpfFsNodeOpenTextStream(path, {
        flags: "r",
        GpfStream: _GpfNodeReadableStream,
        nodeStream: "createReadStream"
    });
}

/**
 * Open a text stream for appending
 *
 * @param {String} path File path
 * @return {Promise<gpf.interfaces.IWritableStream>} gpf.node.WritableStream
 * @since 0.1.9
 */
function _gpfFsNodeOpenTextStreamForAppending (path) {
    return _gpfFsNodeOpenTextStream(path, {
        flags: "a",
        GpfStream: _GpfNodeWritableStream,
        nodeStream: "createWriteStream"
    });
}

function _gpfFsNodeGetFileType (stats) {
    if (stats.isFile()) {
        return _GPF_FS_TYPES.FILE;
    }
    return _GPF_FS_TYPES.UNKNOWN;
}

function _gpfFsNodeGetType (stats) {
    if (stats.isDirectory()) {
        return _GPF_FS_TYPES.DIRECTORY;
    }
    return _gpfFsNodeGetFileType(stats);
}

/**
 * NodeJS specific IFileStorage implementation
 *
 * @class gpf.node.FileStorage
 * @implements {gpf.interfaces.IFileStorage}
 * @private
 * @since 0.1.9
 */
var _GpfNodeFileStorage = _gpfDefine({
    $class: "gpf.node.FileStorage",

    //region gpf.interfaces.IFileStorage

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#getInfo
     * @since 0.1.9
     */
    getInfo: function (path) {
        path = _gpfPathNormalize(path);
        return new Promise(function (resolve) {
            _gpfNodeFs.exists(path, resolve);
        })
            .then(function (exists) {
                if (exists) {
                    return _gpfFsNodeFsCallWithPath("stat", path)
                        .then(function (stats) {
                            return {
                                fileName: _gpfNodePath.basename(path),
                                filePath: _gpfPathNormalize(_gpfNodePath.resolve(path)),
                                size: stats.size,
                                createdDateTime: stats.ctime,
                                modifiedDateTime: stats.mtime,
                                type: _gpfFsNodeGetType(stats)
                            };
                        });
                }
                return {
                    type: _GPF_FS_TYPES.NOT_FOUND
                };
            });

    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#openTextStream
     * @since 0.1.9
     */
    openTextStream: function (path, mode) {
        if (_GPF_FS_OPENFOR.READING === mode) {
            return _gpfFsNodeOpenTextStreamForReading(path);
        }
        return _gpfFsNodeOpenTextStreamForAppending(path);
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#close
     * @since 0.1.9
     */
    close: function (stream) {
        if (stream instanceof _GpfNodeBaseStream) {
            return stream.close();
        }
        return Promise.reject(new gpf.Error.IncompatibleStream());
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#explore
     * @since 0.1.9
     */
    explore: function (path) {
        var me = this;
        return _gpfFsNodeFsCallWithPath("readdir", path)
            .then(function (content) {
                return _gpfFsExploreEnumerator(me, content.map(function (name) {
                    return _gpfPathJoin(path, name);
                }));
            });
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#createDirectory
     * @since 0.1.9
     */
    createDirectory: _gpfFsNodeFsCallWithPath.bind(null, "mkdir"),

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#deleteFile
     * @since 0.1.9
     */
    deleteFile: _gpfFsNodeFsCallWithPath.bind(null, "unlink"),

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#deleteDirectory
     * @since 0.1.9
     */
    deleteDirectory: _gpfFsNodeFsCallWithPath.bind(null, "rmdir")

    //endregion

});

_gpfFsSetFileStorageIf(_GPF_HOST.NODEJS, _GpfNodeFileStorage);

/*#ifndef(UMD)*/

gpf.internals._gpfFsNodeGetType = _gpfFsNodeGetType;

/*#endif*/
<commit_msg>Documentation<commit_after>/**
 * @file NodeJS File system implementation
 * @since 0.1.9
 */
/*#ifndef(UMD)*/
"use strict";
/*global _GPF_FS_OPENFOR*/ // File system stream opening mode
/*global _GPF_FS_TYPES*/ // File system types constants
/*global _GPF_HOST*/ // Host types
/*global _GpfNodeBaseStream*/ // gpf.node.BaseStream
/*global _GpfNodeReadableStream*/ // gpf.node.ReadableStream
/*global _GpfNodeWritableStream*/ // gpf.node.WritableStream
/*global _gpfDefine*/ // Shortcut for gpf.define
/*global _gpfFsExploreEnumerator*/ // IFileStorage.explore helper
/*global _gpfFsSetFileStorageIf*/ // Set the file storage implementation if the host matches
/*global _gpfNodeFs*/ // Node/PhantomJS require("fs")
/*global _gpfNodePath*/ // Node require("path")
/*global _gpfPathJoin*/ // Join all arguments together and normalize the resulting path
/*global _gpfPathNormalize*/ // Normalize path
/*#endif*/

/*jshint node:true*/
/*eslint-env node*/

/*eslint-ignore no-unused-vars*/

/**
 * Encapsulate fs API with a list of parameters inside a Promise
 *
 * @param {String} methodName fs method name
 * @param {Array} args Argument array
 * @return {Promise<*>} Resolved with API result
 * @gpf:closure
 * @since 0.1.9
 */
function _gpfFsNodeFsCall (methodName, args) {
    return new Promise(function (resolve, reject) {
        _gpfNodeFs[methodName].apply(_gpfNodeFs, args.concat([function (err, result) {
            if (err) {
                reject(err);
            } else {
                resolve(result);
            }
        }]));
    });
}

/**
 * Encapsulate fs API taking a path parameter inside a Promise
 *
 * @param {String} methodName fs method name
 * @param {String} path file path
 * @return {Promise<*>} Resolved with API result
 * @gpf:closure
 * @since 0.1.9
 */
function _gpfFsNodeFsCallWithPath (methodName, path) {
    return _gpfFsNodeFsCall(methodName, [_gpfPathNormalize(path)]);
}

function _gpfFsNodeOpenTextStream (path, options) {
    return _gpfFsNodeFsCall("open", [_gpfPathNormalize(path), options.flags])
        .then(function (fd) {
            return new options.GpfStream(_gpfNodeFs[options.nodeStream]("", {
                fd: fd,
                autoClose: false
            }), _gpfFsNodeFsCall.bind(null, "close", [fd]));
        });
}

/**
 * Open a text stream for reading
 *
 * @param {String} path File path
 * @return {Promise<gpf.interfaces.IReadableStream>} gpf.node.ReadableStream
 * @since 0.1.9
 */
function _gpfFsNodeOpenTextStreamForReading (path) {
    return _gpfFsNodeOpenTextStream(path, {
        flags: "r",
        GpfStream: _GpfNodeReadableStream,
        nodeStream: "createReadStream"
    });
}

/**
 * Open a text stream for appending
 *
 * @param {String} path File path
 * @return {Promise<gpf.interfaces.IWritableStream>} gpf.node.WritableStream
 * @since 0.1.9
 */
function _gpfFsNodeOpenTextStreamForAppending (path) {
    return _gpfFsNodeOpenTextStream(path, {
        flags: "a",
        GpfStream: _GpfNodeWritableStream,
        nodeStream: "createWriteStream"
    });
}

function _gpfFsNodeGetFileType (stats) {
    if (stats.isFile()) {
        return _GPF_FS_TYPES.FILE;
    }
    return _GPF_FS_TYPES.UNKNOWN;
}

function _gpfFsNodeGetType (stats) {
    if (stats.isDirectory()) {
        return _GPF_FS_TYPES.DIRECTORY;
    }
    return _gpfFsNodeGetFileType(stats);
}

/**
 * NodeJS specific IFileStorage implementation
 *
 * @class gpf.node.FileStorage
 * @implements {gpf.interfaces.IFileStorage}
 * @private
 * @since 0.1.9
 */
var _GpfNodeFileStorage = _gpfDefine({
    $class: "gpf.node.FileStorage",

    //region gpf.interfaces.IFileStorage

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#getInfo
     * @since 0.1.9
     */
    getInfo: function (path) {
        path = _gpfPathNormalize(path);
        return new Promise(function (resolve) {
            _gpfNodeFs.exists(path, resolve);
        })
            .then(function (exists) {
                if (exists) {
                    return _gpfFsNodeFsCallWithPath("stat", path)
                        .then(function (stats) {
                            return {
                                fileName: _gpfNodePath.basename(path),
                                filePath: _gpfPathNormalize(_gpfNodePath.resolve(path)),
                                size: stats.size,
                                createdDateTime: stats.ctime,
                                modifiedDateTime: stats.mtime,
                                type: _gpfFsNodeGetType(stats)
                            };
                        });
                }
                return {
                    type: _GPF_FS_TYPES.NOT_FOUND
                };
            });

    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#openTextStream
     * @since 0.1.9
     */
    openTextStream: function (path, mode) {
        if (_GPF_FS_OPENFOR.READING === mode) {
            return _gpfFsNodeOpenTextStreamForReading(path);
        }
        return _gpfFsNodeOpenTextStreamForAppending(path);
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#close
     * @since 0.1.9
     */
    close: function (stream) {
        if (stream instanceof _GpfNodeBaseStream) {
            return stream.close();
        }
        return Promise.reject(new gpf.Error.IncompatibleStream());
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#explore
     * @since 0.1.9
     */
    explore: function (path) {
        var me = this;
        return _gpfFsNodeFsCallWithPath("readdir", path)
            .then(function (content) {
                return _gpfFsExploreEnumerator(me, content.map(function (name) {
                    return _gpfPathJoin(path, name);
                }));
            });
    },

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#createDirectory
     * @since 0.1.9
     */
    createDirectory: _gpfFsNodeFsCallWithPath.bind(null, "mkdir"),

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#deleteFile
     * @since 0.1.9
     */
    deleteFile: _gpfFsNodeFsCallWithPath.bind(null, "unlink"),

    /**
     * @gpf:sameas gpf.interfaces.IFileStorage#deleteDirectory
     * @since 0.1.9
     */
    deleteDirectory: _gpfFsNodeFsCallWithPath.bind(null, "rmdir")

    //endregion

});

_gpfFsSetFileStorageIf(_GPF_HOST.NODEJS, _GpfNodeFileStorage);

/*#ifndef(UMD)*/

gpf.internals._gpfFsNodeGetType = _gpfFsNodeGetType;

/*#endif*/
<|endoftext|>


<commit_before>import _ from 'lodash'
var validations = require('./validations')

const createEventsRequestBaseOptions = {
  method: 'POST',
  endpoint: 'events'
}

const getCounterRequestBaseOptions = {
  method: 'GET',
  endpoint: 'counters'
}

export function createEvent (request, counters = validations.required('counters', counters)) {
  let body = { 'timestamp': 0, 'counters': {} }
  if (counters instanceof Array) {
    _.each(counters, (name) => body.counters[name] = 0)
  } else {
    body.counters[counters.toString()] = 0
  }
  const reqOpts = Object.assign(createEventsRequestBaseOptions, { body})
  return request(reqOpts)
    .then((response) => response.entities)
}

export function getCounter (request, counterName = validations.required('counterName', counterName)) {
  if (counterName instanceof Array) {
    counterName = counterName.join(',')
  }
  let reqOpts = Object.assign(getCounterRequestBaseOptions, {
    qs: {
      'counter': counterName
    }
  })
  return request(reqOpts)
    .then((response) => response.counters)
}

export function incrementCounter (request, counterName = validations.required('counterName', counterName) , increment = 1) {
  increment = validations.validIncrement('increment', increment)
  let body = { 'timestamp': 0, 'counters': {} }
  body.counters[counterName] = increment
  return postRequestWrapper(body, request)
}

export function resetCounter (request, counterName = validations.required('counterName', counterName)) {
  let body = { 'timestamp': 0, 'counters': {} }
  body.counters[counterName] = 0
  return postRequestWrapper(body, request)
}

function postRequestWrapper (body, request) {
  const reqOpts = Object.assign(createEventsRequestBaseOptions, { body})
  return request(reqOpts)
    .then((response) => {
      let entities = response.entities
      if (_.isEmpty(entities)) { return undefined }
      return entities[0].counters
    })
}

export function getCounterInterval(request, counterName = validations.required('counterName', counterName), interval) {
  interval = validations.validInterval('interval', interval)

  if (counterName instanceof Array) {
    counterName = counterName.join(',')
  }

  let reqOpts = Object.assign(getCounterRequestBaseOptions, {
    qs: {
      'counter': counterName,
      'start_time': interval.start_time,
      'end_time': interval.end_time,
      'resolution': interval.resolution
    }
  });
  return request(reqOpts)
    .then( (response) => {
      return response.count
    });
}

<commit_msg>if counter is an Array we will create a nested counter<commit_after>import _ from 'lodash'
var validations = require('./validations')

const createEventsRequestBaseOptions = {
  method: 'POST',
  endpoint: 'events'
}

const getCounterRequestBaseOptions = {
  method: 'GET',
  endpoint: 'counters'
}

export function createEvent (request, counters = validations.required('counters', counters)) {
  let body = { 'timestamp': 0, 'counters': {} }
  if (counters instanceof Array) {
    body.counters[_.join(counters, '.')] = 0
  } else {
    body.counters[counters.toString()] = 0
  }
  const reqOpts = Object.assign(createEventsRequestBaseOptions, { body})
  return request(reqOpts)
    .then((response) => response.entities)
}

export function getCounter (request, counterName = validations.required('counterName', counterName)) {
  if (counterName instanceof Array) {
    counterName = counterName.join(',')
  }
  let reqOpts = Object.assign(getCounterRequestBaseOptions, {
    qs: {
      'counter': counterName
    }
  })
  return request(reqOpts)
    .then((response) => response.counters)
}

export function incrementCounter (request, counterName = validations.required('counterName', counterName) , increment = 1) {
  increment = validations.validIncrement('increment', increment)
  let body = { 'timestamp': 0, 'counters': {} }
  body.counters[counterName] = increment
  return postRequestWrapper(body, request)
}

export function resetCounter (request, counterName = validations.required('counterName', counterName)) {
  let body = { 'timestamp': 0, 'counters': {} }
  body.counters[counterName] = 0
  return postRequestWrapper(body, request)
}

function postRequestWrapper (body, request) {
  const reqOpts = Object.assign(createEventsRequestBaseOptions, { body})
  return request(reqOpts)
    .then((response) => {
      let entities = response.entities
      if (_.isEmpty(entities)) { return undefined }
      return entities[0].counters
    })
}

export function getCounterInterval(request, counterName = validations.required('counterName', counterName), interval) {
  interval = validations.validInterval('interval', interval)

  if (counterName instanceof Array) {
    counterName = counterName.join(',')
  }

  let reqOpts = Object.assign(getCounterRequestBaseOptions, {
    qs: {
      'counter': counterName,
      'start_time': interval.start_time,
      'end_time': interval.end_time,
      'resolution': interval.resolution
    }
  });
  return request(reqOpts)
    .then( (response) => {
      return response.count
    });
}

<|endoftext|>


<commit_before>// Code ©2017 - 2019 Ecstatic Life Inc. All rights reserved.
console.log(window.location.href.indexOf('ecstaticliving.com') > -1 ? 'Welcome to EcstaticLiving.com' : 'TEST code at ', window.location.href)

// Urls
const containsUrl = str => window.location.href.indexOf(str) > -1
const endsWithUrl = str => window.location.href.endsWith(str)

// Page
const page = () => {
  if (containsUrl('/events/'))  					return 'Event'
  if (endsWithUrl('/update'))  						return 'Update'
  return null
}

// Device
const deviceOrientation = () => window.innerWidth > window.innerHeight
	? 'landscape'
	: 'portrait'

const deviceType = () => {
	//	Some large tablets exist, but for all intents and purposes, we’ll treat them as desktops.
	if (
		(deviceOrientation() === 'portrait' && window.innerWidth > 1024)
		|| (deviceOrientation() === 'landscape' && window.innerWidth > 1366)
	) {
		return 'desktop'
	}
	if (
		(deviceOrientation() === 'portrait' && window.innerWidth > 768)
		|| (deviceOrientation() === 'landscape' && window.innerWidth > 1024)
	) {
		return 'large tablet'
	}
	if (
		(deviceOrientation() === 'portrait' && window.innerWidth > 414)
		|| (deviceOrientation() === 'landscape' && window.innerWidth > 736)
	) {
		return 'tablet'
	}
	return 'mobile'
}

// Element Collections
const querySelectorAll = (className, i) => document.querySelectorAll(className)[i || 0]
const querySelector = className => document.querySelector(className)
const getAttribute = (elem, attribute) => elem.getAttribute(attribute)
const getElementById = elem => document.getElementById(elem)
const getElementByClassName = (className, i) => document.getElementsByClassName(className)[i || 0]
const getElementsByClassName = className => document.getElementsByClassName(className)
const getElementsByTag = tag => document.getElementsByTagName(tag)

// Window Event Listener
const windowEventListener = (triggers, f) => triggers.forEach(trigger => window.addEventListener(trigger, f))

// Element Event Listeners
const onClick = (elem, f) => elem.addEventListener('click', e => f(e))
const onChange = (elem, f) => elem.addEventListener('change', e => f(e))
const onInput = (elem, f) => elem.addEventListener('input', f)
const onKeyPress = (elem, f) => elem.addEventListener('keypress', e => f(e))
const onLoad = (elem, f) => elem.addEventListener('load', f)
const onOrientationChange = (elem, f) => elem.addEventListener('orientationchange', f)
const onScroll = (elem, f) => elem.addEventListener('scroll', f)
const onSubmit = (elem, f) => elem.addEventListener('submit', f)

// Form behaviours
const formSubmit = elem => elem.submit()
const formErrorInit = elem => elem.parsley()
const formErrorValidation = elem => elem.parsley().validate()
const formReset = elem => elem.reset()

// Element Conditions
const isInput = elem => elem.type === 'input'
const isRadio = elem => elem.type === 'radio'
const isBlank = elem => getValue(elem) === '' && getValue(elem) === ''
const isChecked = elem => elem.checked
const isVisible = elem => elem.style.display

// Element Behaviours
const animateElement = (elem, keyframes, options) => elem.animate(keyframes, options)
const clickElement = elem => elem.click()
const fadeInElement = elem => elem.style.opacity = '1.0'
const fadeOutElement = elem => elem.style.opacity = '0'
const focusElement = elem => elem.focus()
const hideElement = elem => elem.style.display = 'none'
const showElement = elem => elem.style.display = 'block'

// Values
const getValue = elem => elem.value
const emptyValue = elem => elem.value === ''
const setValue = (elem, val) => elem.value = val

// Text
const getText = elem => elem.textContent
const setText = (elem, val) => elem.textContent = val
const emptyText = elem => elem.textContent = ''
const properCase = text => text.toLowerCase().charAt(0).toUpperCase() + text.slice(1)

// Select
const emptySelect = elem => {
	for (let i = 0; i < elem.options.length; i++) {
		elem.options[i] = null
	}
}
const appendSelect = (elem, option) => elem.add(option)
const getIndex = elem => elem.selectedIndex

// HTML
const setHtml = (elem, val) => elem.innerHTML = val
const setCss = (elem, css) => elem.className = css

// Check radio
const checkElement = elem => elem.checked = true
const unCheckElement = elem => elem.checked = false

// Combined Behaviours
const emptyHideText = elem => {
	emptyText(elem)
	hideElement(elem)
}
const emptyHideValue = elem => {
	emptyValue(elem)
	hideElement(elem)
}
const showAndScrollTo = elem => {
	showElement(elem)
	window.scrollTo(0, (window.pageYOffset || document.documentElement.scrollTop) - (document.documentElement.clientTop || 0) + 1)
}<commit_msg>007 - flex css<commit_after>// Code ©2017 - 2019 Ecstatic Life Inc. All rights reserved.
console.log(window.location.href.indexOf('ecstaticliving.com') > -1 ? 'Welcome to EcstaticLiving.com' : 'TEST code at ', window.location.href)

// Urls
const containsUrl = str => window.location.href.indexOf(str) > -1
const endsWithUrl = str => window.location.href.endsWith(str)

// Page
const page = () => {
  if (containsUrl('/events/'))  					return 'Event'
  if (endsWithUrl('/update'))  						return 'Update'
  return null
}

// Device
const deviceOrientation = () => window.innerWidth > window.innerHeight
	? 'landscape'
	: 'portrait'

const deviceType = () => {
	//	Some large tablets exist, but for all intents and purposes, we’ll treat them as desktops.
	if (
		(deviceOrientation() === 'portrait' && window.innerWidth > 1024)
		|| (deviceOrientation() === 'landscape' && window.innerWidth > 1366)
	) {
		return 'desktop'
	}
	if (
		(deviceOrientation() === 'portrait' && window.innerWidth > 768)
		|| (deviceOrientation() === 'landscape' && window.innerWidth > 1024)
	) {
		return 'large tablet'
	}
	if (
		(deviceOrientation() === 'portrait' && window.innerWidth > 414)
		|| (deviceOrientation() === 'landscape' && window.innerWidth > 736)
	) {
		return 'tablet'
	}
	return 'mobile'
}

// Element Collections
const querySelectorAll = (className, i) => document.querySelectorAll(className)[i || 0]
const querySelector = className => document.querySelector(className)
const getAttribute = (elem, attribute) => elem.getAttribute(attribute)
const getElementById = elem => document.getElementById(elem)
const getElementByClassName = (className, i) => document.getElementsByClassName(className)[i || 0]
const getElementsByClassName = className => document.getElementsByClassName(className)
const getElementsByTag = tag => document.getElementsByTagName(tag)

// Window Event Listener
const windowEventListener = (triggers, f) => triggers.forEach(trigger => window.addEventListener(trigger, f))

// Element Event Listeners
const onClick = (elem, f) => elem.addEventListener('click', e => f(e))
const onChange = (elem, f) => elem.addEventListener('change', e => f(e))
const onInput = (elem, f) => elem.addEventListener('input', f)
const onKeyPress = (elem, f) => elem.addEventListener('keypress', e => f(e))
const onLoad = (elem, f) => elem.addEventListener('load', f)
const onOrientationChange = (elem, f) => elem.addEventListener('orientationchange', f)
const onScroll = (elem, f) => elem.addEventListener('scroll', f)
const onSubmit = (elem, f) => elem.addEventListener('submit', f)

// Form behaviours
const formSubmit = elem => elem.submit()
const formErrorInit = elem => elem.parsley()
const formErrorValidation = elem => elem.parsley().validate()
const formReset = elem => elem.reset()

// Element Conditions
const isInput = elem => elem.type === 'input'
const isRadio = elem => elem.type === 'radio'
const isBlank = elem => getValue(elem) === '' && getValue(elem) === ''
const isChecked = elem => elem.checked
const isVisible = elem => elem.style.display

// Element Behaviours
const animateElement = (elem, keyframes, options) => elem.animate(keyframes, options)
const clickElement = elem => elem.click()
const fadeInElement = elem => elem.style.opacity = '1.0'
const fadeOutElement = elem => elem.style.opacity = '0'
const focusElement = elem => elem.focus()
const hideElement = elem => elem.style.display = 'none'
const showElement = elem => elem.style.display = 'block'
const flexElement = elem => {
	elem.style.display = 'flex'
	elem.style.flexDirection = 'column'
}

// Values
const getValue = elem => elem.value
const emptyValue = elem => elem.value === ''
const setValue = (elem, val) => elem.value = val

// Text
const getText = elem => elem.textContent
const setText = (elem, val) => elem.textContent = val
const emptyText = elem => elem.textContent = ''
const properCase = text => text.toLowerCase().charAt(0).toUpperCase() + text.slice(1)

// Select
const emptySelect = elem => {
	for (let i = 0; i < elem.options.length; i++) {
		elem.options[i] = null
	}
}
const appendSelect = (elem, option) => elem.add(option)
const getIndex = elem => elem.selectedIndex

// HTML
const setHtml = (elem, val) => elem.innerHTML = val
const setCss = (elem, css) => elem.className = css

// Check radio
const checkElement = elem => elem.checked = true
const unCheckElement = elem => elem.checked = false

// Combined Behaviours
const emptyHideText = elem => {
	emptyText(elem)
	hideElement(elem)
}
const emptyHideValue = elem => {
	emptyValue(elem)
	hideElement(elem)
}
const showAndScrollTo = elem => {
	showElement(elem)
	window.scrollTo(0, (window.pageYOffset || document.documentElement.scrollTop) - (document.documentElement.clientTop || 0) + 1)
}<|endoftext|>


<commit_before>module.exports = function(codegen) {

  function fncall(name, args, cast, type) {
    var obj = codegen(args[0]);
    if (cast) {
      obj = cast + '(' + obj + ')';
      if (cast.lastIndexOf('new ', 0) === 0) obj = '(' + obj + ')';
    }
    return obj + '.' + name + (type < 0 ? '' : type === 0 ?
      '()' :
      '(' + args.slice(1).map(codegen).join(',') + ')');
  }

  function fn(name, cast, type) {
    return function(args) {
      return fncall(name, args, cast, type);
    };
  }

  var DATE = 'new Date',
      STRING = 'String',
      REGEXP = 'RegExp';

  return {
    // MATH functions
    'isNaN':    'isNaN',
    'isFinite': 'isFinite',
    'abs':      'Math.abs',
    'acos':     'Math.acos',
    'asin':     'Math.asin',
    'atan':     'Math.atan',
    'atan2':    'Math.atan2',
    'ceil':     'Math.ceil',
    'cos':      'Math.cos',
    'exp':      'Math.exp',
    'floor':    'Math.floor',
    'log':      'Math.log',
    'max':      'Math.max',
    'min':      'Math.min',
    'pow':      'Math.pow',
    'random':   'Math.random',
    'round':    'Math.round',
    'sin':      'Math.sin',
    'sqrt':     'Math.sqrt',
    'tan':      'Math.tan',

    'clamp': function(args) {
      if (args.length < 3)
        throw new Error('Missing arguments to clamp function.');
      if (args.length > 3)
      throw new Error('Too many arguments to clamp function.');
      var a = args.map(codegen);
      return 'Math.max('+a[1]+', Math.min('+a[2]+','+a[0]+'))';
    },

    // DATE functions
    'now':             'Date.now',
    'datetime':        DATE,
    'date':            fn('getDate', DATE, 0),
    'day':             fn('getDay', DATE, 0),
    'year':            fn('getFullYear', DATE, 0),
    'month':           fn('getMonth', DATE, 0),
    'hours':           fn('getHours', DATE, 0),
    'minutes':         fn('getMinutes', DATE, 0),
    'seconds':         fn('getSeconds', DATE, 0),
    'milliseconds':    fn('getMilliseconds', DATE, 0),
    'time':            fn('getTime', DATE, 0),
    'timezoneoffset':  fn('getTimezoneOffset', DATE, 0),
    'utcdate':         fn('getUTCDate', DATE, 0),
    'utcday':          fn('getUTCDay', DATE, 0),
    'utcyear':         fn('getUTCFullYear', DATE, 0),
    'utcmonth':        fn('getUTCMonth', DATE, 0),
    'utchours':        fn('getUTCHours', DATE, 0),
    'utcminutes':      fn('getUTCMinutes', DATE, 0),
    'utcseconds':      fn('getUTCSeconds', DATE, 0),
    'utcmilliseconds': fn('getUTCMilliseconds', DATE, 0),

    // shared sequence functions
    'length':      fn('length', null, -1),
    'indexof':     fn('indexOf', null),
    'lastindexof': fn('lastIndexOf', null),

    // STRING functions
    'parseFloat':  'parseFloat',
    'parseInt':    'parseInt',
    'upper':       fn('toUpperCase', STRING, 0),
    'lower':       fn('toLowerCase', STRING, 0),
    'slice':       fn('slice', STRING),
    'substring':   fn('substring', STRING),

    // REGEXP functions
    'regexp':  REGEXP,
    'test':    fn('test', REGEXP),

    // Control Flow functions
    'if': function(args) {
        if (args.length < 3)
          throw new Error('Missing arguments to if function.');
        if (args.length > 3)
        throw new Error('Too many arguments to if function.');
        var a = args.map(codegen);
        return a[0]+'?'+a[1]+':'+a[2];
      }
  };
};<commit_msg>Add String.replace to the list of functions<commit_after>module.exports = function(codegen) {

  function fncall(name, args, cast, type) {
    var obj = codegen(args[0]);
    if (cast) {
      obj = cast + '(' + obj + ')';
      if (cast.lastIndexOf('new ', 0) === 0) obj = '(' + obj + ')';
    }
    return obj + '.' + name + (type < 0 ? '' : type === 0 ?
      '()' :
      '(' + args.slice(1).map(codegen).join(',') + ')');
  }

  function fn(name, cast, type) {
    return function(args) {
      return fncall(name, args, cast, type);
    };
  }

  var DATE = 'new Date',
      STRING = 'String',
      REGEXP = 'RegExp';

  return {
    // MATH functions
    'isNaN':    'isNaN',
    'isFinite': 'isFinite',
    'abs':      'Math.abs',
    'acos':     'Math.acos',
    'asin':     'Math.asin',
    'atan':     'Math.atan',
    'atan2':    'Math.atan2',
    'ceil':     'Math.ceil',
    'cos':      'Math.cos',
    'exp':      'Math.exp',
    'floor':    'Math.floor',
    'log':      'Math.log',
    'max':      'Math.max',
    'min':      'Math.min',
    'pow':      'Math.pow',
    'random':   'Math.random',
    'round':    'Math.round',
    'sin':      'Math.sin',
    'sqrt':     'Math.sqrt',
    'tan':      'Math.tan',

    'clamp': function(args) {
      if (args.length < 3)
        throw new Error('Missing arguments to clamp function.');
      if (args.length > 3)
      throw new Error('Too many arguments to clamp function.');
      var a = args.map(codegen);
      return 'Math.max('+a[1]+', Math.min('+a[2]+','+a[0]+'))';
    },

    // DATE functions
    'now':             'Date.now',
    'datetime':        DATE,
    'date':            fn('getDate', DATE, 0),
    'day':             fn('getDay', DATE, 0),
    'year':            fn('getFullYear', DATE, 0),
    'month':           fn('getMonth', DATE, 0),
    'hours':           fn('getHours', DATE, 0),
    'minutes':         fn('getMinutes', DATE, 0),
    'seconds':         fn('getSeconds', DATE, 0),
    'milliseconds':    fn('getMilliseconds', DATE, 0),
    'time':            fn('getTime', DATE, 0),
    'timezoneoffset':  fn('getTimezoneOffset', DATE, 0),
    'utcdate':         fn('getUTCDate', DATE, 0),
    'utcday':          fn('getUTCDay', DATE, 0),
    'utcyear':         fn('getUTCFullYear', DATE, 0),
    'utcmonth':        fn('getUTCMonth', DATE, 0),
    'utchours':        fn('getUTCHours', DATE, 0),
    'utcminutes':      fn('getUTCMinutes', DATE, 0),
    'utcseconds':      fn('getUTCSeconds', DATE, 0),
    'utcmilliseconds': fn('getUTCMilliseconds', DATE, 0),

    // shared sequence functions
    'length':      fn('length', null, -1),
    'indexof':     fn('indexOf', null),
    'lastindexof': fn('lastIndexOf', null),

    // STRING functions
    'parseFloat':  'parseFloat',
    'parseInt':    'parseInt',
    'upper':       fn('toUpperCase', STRING, 0),
    'lower':       fn('toLowerCase', STRING, 0),
    'slice':       fn('slice', STRING),
    'substring':   fn('substring', STRING),
    'replace':     fn('replace', STRING),

    // REGEXP functions
    'regexp':  REGEXP,
    'test':    fn('test', REGEXP),

    // Control Flow functions
    'if': function(args) {
        if (args.length < 3)
          throw new Error('Missing arguments to if function.');
        if (args.length > 3)
        throw new Error('Too many arguments to if function.');
        var a = args.map(codegen);
        return a[0]+'?'+a[1]+':'+a[2];
      }
  };
};
<|endoftext|>


<commit_before>const retry = require('retry');
const request = require('request');

const sequentialPromise = (array, fn) => {
  return array.reduce((sequence, next) => {
    return sequence.then(() => {
      return fn(next);
    });
  }, Promise.resolve());
};

// Split it in chunks too many registers to insert at once
const chunk = (arr, n) => {
  return arr.reduce((p, cur, i) => {
    (p[i/n|0] = p[i/n|0] || []).push(cur);
    return p;
  }, []);
};

const customRequest = (method, opts) => {
  return new Promise((resolve, reject) => {

    const operation = retry.operation({
      retries: 3,
      factor: 1,
      minTimeout: 1000
    });

    operation.attempt(function(currentAttempt) {
      request[method](opts, (error, response, body) => {
        const err = error || response.statusCode !== 200;

        if (operation.retry(err)) {
          return;
        }

        if (err) {
          reject(operation.mainError());
        }

        resolve(body);
      });
    });
  });
};

exports = module.exports = {
  sequentialPromise,
  chunk,
  customRequest
};
<commit_msg>Decrease request timeout<commit_after>const retry = require('retry');
const request = require('request');

const sequentialPromise = (array, fn) => {
  return array.reduce((sequence, next) => {
    return sequence.then(() => {
      return fn(next);
    });
  }, Promise.resolve());
};

// Split it in chunks too many registers to insert at once
const chunk = (arr, n) => {
  return arr.reduce((p, cur, i) => {
    (p[i/n|0] = p[i/n|0] || []).push(cur);
    return p;
  }, []);
};

const customRequest = (method, opts) => {
  return new Promise((resolve, reject) => {

    const operation = retry.operation({
      retries: 3,
      factor: 1,
      minTimeout: 100
    });

    operation.attempt(function(currentAttempt) {
      request[method](opts, (error, response, body) => {
        const err = error || response.statusCode !== 200;

        if (operation.retry(err)) {
          return;
        }

        if (err) {
          reject(operation.mainError());
        }

        resolve(body);
      });
    });
  });
};

exports = module.exports = {
  sequentialPromise,
  chunk,
  customRequest
};
<|endoftext|>


<commit_before>/**
 * Main game object, controls the entire instance of the game
 *
 * @class Game
 * @uses Emitter
 * @constructor
 * @param contId {String} The container for the new canvas we will create for the game
 * @param settings {Object} Options such as renderMethod and interactive (whether the stage can be clicked)
 */
gf.Game = function(contId, settings) {
    //mixin the Event Target methods
    gf.Emitter.call(this);

    /**
     * The domElement that we are putting our rendering canvas into (the container)
     *
     * @property container
     * @type DOMELement
     * @readOnly
     */
    this.container = document.getElementById(contId);

    if(!this.container)
        this.container = document.body;

    /**
     * The method used to render values to the screen (either webgl, or canvas)
     *
     * @property renderMethod
     * @type String
     * @default 'webgl'
     */
    this.renderMethod = 'webgl';

    /**
     * The player entities added into the game
     *
     * @property players
     * @type {Array}
     */
    this.players = [];

    /**
     * Raw PIXI.stage instance
     *
     * @property stage
     * @type PIXI.Stage
     * @readOnly
     */
    this.stage = new PIXI.Stage(
        settings.background,
        settings.interactive !== undefined ? settings.interactive : true
    );

    /**
     * Raw Clock instance for internal timing
     *
     * @property clock
     * @type Clock
     * @readOnly
     */
    this.clock = new gf.Clock(false);

    /**
     * Raw rendering engine
     *
     * @property renderer
     * @type PIXI.WebGLRenderer|PIXI.CanvasRenderer
     * @readOnly
     */
    this.renderer = null;

    //if they speciy a method, check if it is available
    if(settings.renderMethod) {
        if(!gf.support[settings.renderMethod]) {
            throw 'Render method ' + settings.renderMethod + ' is not supported by this browser!';
        }
        this.renderMethod = settings.renderMethod;
    }
    //if they don't specify a method, guess the best to use
    else {
        if(gf.support.webgl) this.renderMethod = 'webgl';
        else if(gf.support.canvas) this.renderMethod = 'canvas';
        else {
            throw 'Neither WebGL nor Canvas is supported by this browser!';
        }
    }

    //initialize the correct renderer
    if(this.renderMethod === 'webgl') {
        this.renderer = new PIXI.WebGLRenderer(settings.width, settings.height, settings.view, settings.transparent);
    } else if(this.renderMethod === 'canvas') {
        this.renderer = new PIXI.CanvasRenderer(settings.width, settings.height, settings.view, settings.transparent);
    }

    /**
     * Maximum Z value
     *
     * @property MAX_Z
     * @type {Number}
     * @default 500
     * @private
     * @readOnly
     */
    this.MAX_Z = 500;

    /**
     * The loader for this game instance
     *
     * @property loader
     * @type AssetLoader
     * @readOnly
     */
    this.loader = new gf.AssetLoader();

    /**
     * The sprite pool to use to create registered entities
     *
     * @property spritepool
     * @type SpritePool
     * @readOnly
     */
    this.spritepool = new gf.SpritePool();

    /**
     * The GameStates added to the game
     *
     * @property states
     * @type Array
     * @readOnly
     */
    this.states = {};

    /**
     * The currently active GameState
     *
     * @property activeState
     * @type GameState
     * @readOnly
     */
    this.activeState = null;
    this._defaultState = new gf.GameState('_default');

    //append the renderer view
    //this.renderer.view.style['z-index'] = opts.zIndex || 5;
    this.container.appendChild(this.renderer.view);

    //mixin user settings
    gf.utils.setValues(this, settings);

    //enable default state
    this.addState(this._defaultState);
    this.enableState('_default');

    //define getters for common properties in GameState
    var self = this;
    ['audio', 'input', 'physics', 'camera', 'world'].forEach(function(prop) {
        self.__defineGetter__(prop, function() {
            return self.activeState[prop];
        });
    });

    //some docs for the getters above

    /**
     * The audio player for this game instance
     * (refers to the active GameState's audio instance)
     *
     * @property audio
     * @type AudioPlayer
     * @readOnly
     */

    /**
     * The input instance for this game
     * (refers to the active GameState's input instance)
     *
     * @property input
     * @type InputManager
     * @readOnly
     */

    /**
     * The physics system to simulate stuffs
     * (refers to the active GameState's physics instance)
     *
     * @property physics
     * @type PhysicsSystem
     * @readOnly
     */

    /**
     * The camera you view the scene through
     * (refers to the active GameState's camera instance)
     *
     * @property camera
     * @type Camera
     * @readOnly
     */

    /**
     * The world instance that holds all sprites and the map
     * (refers to the active GameState's world instance)
     *
     * @property world
     * @type Map
     * @readOnly
     */
};

gf.inherits(gf.Game, Object, {
    /**
     * Allows you to resize the game area
     *
     * @method resize
     * @param width {Number} Width to resize to
     * @param height {Number} Height to resize to
     * @return {Game} Returns itself for chainability
     */
    resize: function(w, h) {
        this.renderer.resize(w, h);

        for(var i = 0, il = this.stage.children.length; i < il; ++i) {
            var o = this.stage.children[i];

            if(o.resize)
                o.resize(w, h);
        }

        return this;
    },
    /**
     * Adds an object to the current stage
     *
     * @method addChild
     * @param obj {Sprite} The sprite to the stage
     * @return {Game} Returns itself for chainability
     */
    addChild: function(obj) {
        this.activeState.addChild(obj);

        return this;
    },
    /**
     * Removes a sprite from the stage
     *
     * @method removeChild
     * @param obj {Sprite} The sprite to the stage
     * @return {Game} Returns itself for chainability
     */
    removeChild: function(obj) {
        if(obj) {
            if(obj instanceof gf.Gui)
                this.camera.removeChild(obj);
            else
                this.world.removeChild(obj);
        }

        return this;
    },
    /**
     * Adds a new game state to this game to be later enabled
     *
     * @method addState
     * @param state {GameState} The state to add to this game
     * @return {Game} Returns itself for chainability
     */
    addState: function(state) {
        var name = state.name;

        if(!name) {
            throw 'No state name could be determined, did you give the state a name when you created it?';
        } else if(this.states[name]) {
            throw 'A state with the name "' + name + '" already exists, did you try to add it twice?';
        } else {
            this.states[name] = state;
            this.stage.addChild(state);

            state.game = this;
        }

        return this;
    },
    /**
     * Removes a game state from the game
     *
     * @method removeState
     * @param state {GameState|String} The state to remove from the game, or the name of a state to remove
     * @return {Game} Returns itself for chainability
     */
    removeState: function(state) {
        var name = (typeof state === 'string') ? state : state.name;

        if(!name) {
            throw 'No state name could be determined, are you sure you passed me a game state?';
        } else if(!this.states[name]) {
            throw 'A state with the name "' + name + '" does not exist, are you sure you added it?';
        } else {
            //don't remove the default state
            if(name === '_default') return;

            //if this is the active state, revert to the default state
            if(name === this.activeState.name) {
                this.enableState('_default');
            }

            delete this.states[name];
        }

        return this;
    },
    /**
     * Enables a state that has been added to the game
     *
     * @method enableState
     * @param state {GameState|String} The state to enable, or the name of a state to enable
     * @return {Game} Returns itself for chainability
     */
    enableState: function(state) {
        var name = (typeof state === 'string') ? state : state.name;

        if(this.activeState)
            this.activeState.disable();

        this.activeState = this.states[name];

        this.activeState.enable();

        return this;
    },
    /**
     * Loads the world map into the game
     *
     * @method loadWorld
     * @param world {String|Map} The map to load as the current world
     * @return {Game} Returns itself for chainability
     */
    loadWorld: function(world) {
        this.activeState.loadWorld(world);

        return this;
    },
    /**
     * Begins the render loop
     *
     * @method render
     * @return {Game} Returns itself for chainability
     */
    render: function() {
        this.clock.start();
        this._tick();

        return this;
    },
    /**
     * The looping render tick
     *
     * @method _tick
     * @private
     */
    _tick: function() {
        this.emit({ type: 'beforetick' });
        //start render loop
        window.requestAnimFrame(this._tick.bind(this));

        //update this game state
        this.activeState.update(this.clock.getDelta());

        //render scene
        this.renderer.render(this.stage);
        this.emit({ type: 'aftertick' });
    }
});
<commit_msg>Add easy-to-use fullscreen helper<commit_after>/**
 * Main game object, controls the entire instance of the game
 *
 * @class Game
 * @uses Emitter
 * @constructor
 * @param contId {String} The container for the new canvas we will create for the game
 * @param settings {Object} Options such as renderMethod and interactive (whether the stage can be clicked)
 */
gf.Game = function(contId, settings) {
    //mixin the Event Target methods
    gf.Emitter.call(this);

    /**
     * The domElement that we are putting our rendering canvas into (the container)
     *
     * @property container
     * @type DOMELement
     * @readOnly
     */
    this.container = document.getElementById(contId);

    if(!this.container)
        this.container = document.body;

    /**
     * The method used to render values to the screen (either webgl, or canvas)
     *
     * @property renderMethod
     * @type String
     * @default 'webgl'
     */
    this.renderMethod = 'webgl';

    /**
     * The player entities added into the game
     *
     * @property players
     * @type {Array}
     */
    this.players = [];

    /**
     * Raw PIXI.stage instance
     *
     * @property stage
     * @type PIXI.Stage
     * @readOnly
     */
    this.stage = new PIXI.Stage(
        settings.background,
        settings.interactive !== undefined ? settings.interactive : true
    );

    /**
     * Raw Clock instance for internal timing
     *
     * @property clock
     * @type Clock
     * @readOnly
     */
    this.clock = new gf.Clock(false);

    /**
     * Raw rendering engine
     *
     * @property renderer
     * @type PIXI.WebGLRenderer|PIXI.CanvasRenderer
     * @readOnly
     */
    this.renderer = null;

    //if they speciy a method, check if it is available
    if(settings.renderMethod) {
        if(!gf.support[settings.renderMethod]) {
            throw 'Render method ' + settings.renderMethod + ' is not supported by this browser!';
        }
        this.renderMethod = settings.renderMethod;
    }
    //if they don't specify a method, guess the best to use
    else {
        if(gf.support.webgl) this.renderMethod = 'webgl';
        else if(gf.support.canvas) this.renderMethod = 'canvas';
        else {
            throw 'Neither WebGL nor Canvas is supported by this browser!';
        }
    }

    //initialize the correct renderer
    if(this.renderMethod === 'webgl') {
        this.renderer = new PIXI.WebGLRenderer(settings.width, settings.height, settings.view, settings.transparent);
    } else if(this.renderMethod === 'canvas') {
        this.renderer = new PIXI.CanvasRenderer(settings.width, settings.height, settings.view, settings.transparent);
    }

    /**
     * Maximum Z value
     *
     * @property MAX_Z
     * @type {Number}
     * @default 500
     * @private
     * @readOnly
     */
    this.MAX_Z = 500;

    /**
     * The loader for this game instance
     *
     * @property loader
     * @type AssetLoader
     * @readOnly
     */
    this.loader = new gf.AssetLoader();

    /**
     * The sprite pool to use to create registered entities
     *
     * @property spritepool
     * @type SpritePool
     * @readOnly
     */
    this.spritepool = new gf.SpritePool();

    /**
     * The GameStates added to the game
     *
     * @property states
     * @type Array
     * @readOnly
     */
    this.states = {};

    /**
     * The currently active GameState
     *
     * @property activeState
     * @type GameState
     * @readOnly
     */
    this.activeState = null;
    this._defaultState = new gf.GameState('_default');

    //append the renderer view
    //this.renderer.view.style['z-index'] = opts.zIndex || 5;
    this.container.appendChild(this.renderer.view);

    //mixin user settings
    gf.utils.setValues(this, settings);

    //enable default state
    this.addState(this._defaultState);
    this.enableState('_default');

    //define getters for common properties in GameState
    var self = this;
    ['audio', 'input', 'physics', 'camera', 'world'].forEach(function(prop) {
        self.__defineGetter__(prop, function() {
            return self.activeState[prop];
        });
    });

    //some docs for the getters above

    /**
     * The audio player for this game instance
     * (refers to the active GameState's audio instance)
     *
     * @property audio
     * @type AudioPlayer
     * @readOnly
     */

    /**
     * The input instance for this game
     * (refers to the active GameState's input instance)
     *
     * @property input
     * @type InputManager
     * @readOnly
     */

    /**
     * The physics system to simulate stuffs
     * (refers to the active GameState's physics instance)
     *
     * @property physics
     * @type PhysicsSystem
     * @readOnly
     */

    /**
     * The camera you view the scene through
     * (refers to the active GameState's camera instance)
     *
     * @property camera
     * @type Camera
     * @readOnly
     */

    /**
     * The world instance that holds all sprites and the map
     * (refers to the active GameState's world instance)
     *
     * @property world
     * @type Map
     * @readOnly
     */
};

gf.inherits(gf.Game, Object, {
    /**
     * Allows you to resize the game area
     *
     * @method resize
     * @param width {Number} Width to resize to
     * @param height {Number} Height to resize to
     * @return {Game} Returns itself for chainability
     */
    resize: function(w, h) {
        this.renderer.resize(w, h);

        for(var i = 0, il = this.stage.children.length; i < il; ++i) {
            var o = this.stage.children[i];

            if(o.resize)
                o.resize(w, h);
        }

        return this;
    },
    /**
     * Adds an object to the current stage
     *
     * @method addChild
     * @param obj {Sprite} The sprite to the stage
     * @return {Game} Returns itself for chainability
     */
    addChild: function(obj) {
        this.activeState.addChild(obj);

        return this;
    },
    /**
     * Removes a sprite from the stage
     *
     * @method removeChild
     * @param obj {Sprite} The sprite to the stage
     * @return {Game} Returns itself for chainability
     */
    removeChild: function(obj) {
        if(obj) {
            if(obj instanceof gf.Gui)
                this.camera.removeChild(obj);
            else
                this.world.removeChild(obj);
        }

        return this;
    },
    requestFullscreen: function() {
        var elem = this.renderer.view;

        if(elem.requestFullscreen) {
          elem.requestFullscreen();
        } else if(elem.mozRequestFullScreen) {
          elem.mozRequestFullScreen();
        } else if(elem.webkitRequestFullscreen) {
          elem.webkitRequestFullscreen();
        }
    },
    /**
     * Adds a new game state to this game to be later enabled
     *
     * @method addState
     * @param state {GameState} The state to add to this game
     * @return {Game} Returns itself for chainability
     */
    addState: function(state) {
        var name = state.name;

        if(!name) {
            throw 'No state name could be determined, did you give the state a name when you created it?';
        } else if(this.states[name]) {
            throw 'A state with the name "' + name + '" already exists, did you try to add it twice?';
        } else {
            this.states[name] = state;
            this.stage.addChild(state);

            state.game = this;
        }

        return this;
    },
    /**
     * Removes a game state from the game
     *
     * @method removeState
     * @param state {GameState|String} The state to remove from the game, or the name of a state to remove
     * @return {Game} Returns itself for chainability
     */
    removeState: function(state) {
        var name = (typeof state === 'string') ? state : state.name;

        if(!name) {
            throw 'No state name could be determined, are you sure you passed me a game state?';
        } else if(!this.states[name]) {
            throw 'A state with the name "' + name + '" does not exist, are you sure you added it?';
        } else {
            //don't remove the default state
            if(name === '_default') return;

            //if this is the active state, revert to the default state
            if(name === this.activeState.name) {
                this.enableState('_default');
            }

            delete this.states[name];
        }

        return this;
    },
    /**
     * Enables a state that has been added to the game
     *
     * @method enableState
     * @param state {GameState|String} The state to enable, or the name of a state to enable
     * @return {Game} Returns itself for chainability
     */
    enableState: function(state) {
        var name = (typeof state === 'string') ? state : state.name;

        if(this.activeState)
            this.activeState.disable();

        this.activeState = this.states[name];

        this.activeState.enable();

        return this;
    },
    /**
     * Loads the world map into the game
     *
     * @method loadWorld
     * @param world {String|Map} The map to load as the current world
     * @return {Game} Returns itself for chainability
     */
    loadWorld: function(world) {
        this.activeState.loadWorld(world);

        return this;
    },
    /**
     * Begins the render loop
     *
     * @method render
     * @return {Game} Returns itself for chainability
     */
    render: function() {
        this.clock.start();
        this._tick();

        return this;
    },
    /**
     * The looping render tick
     *
     * @method _tick
     * @private
     */
    _tick: function() {
        this.emit({ type: 'beforetick' });
        //start render loop
        window.requestAnimFrame(this._tick.bind(this));

        //update this game state
        this.activeState.update(this.clock.getDelta());

        //render scene
        this.renderer.render(this.stage);
        this.emit({ type: 'aftertick' });
    }
});
<|endoftext|>


<commit_before>import React from 'react';
import request from 'request';
import Jumbotron from 'react-bootstrap/lib/Jumbotron';
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
import InitialBoard from './components/InitialBoard';
import NameGameBoard from './components/NameGameBoard';

/*
 * @class Game representing the game board.
 */
class Game extends React.Component {

  /**
   * @constructor
   */
  constructor(options) {
    super(options);
    this.state = {
      employees: [],
      round: 0
    };
  }

  /**
   * @description Load all the data and update state
   * TODO: handle graceful failure of REST API
   * TODO: use local storage to cache the API response
   */
  componentDidMount () {
    request(this.props.url, function (error, response, body) {
      if (!error && response.statusCode === 200) {
        var employees = JSON.parse(body);
        this.setState({
          employees: employees,
          init: true
        });
      }
    }.bind(this));
  }

  /**
   * @description Top level render of name game application
   */
  render () {
    if (!this.state.init) {
      return null;
    }
    return

            <Jumbotron>

WillowTree Name Game

How many names can you remember?

            </Jumbotron>
            <ProgressBar active={this.inProgress()} bsStyle="success" now={this.getProgress()} />
            {this.getCurrentBoard()}

;
  }

  getCurrentBoard () {
    if (this.state.round === 0) {
      return this.getInitialBoard();
    } else if (this.state.round === this.props.roundCount) {
      return this.getEndBoard();
    } else {
      return this.getInPlayBoard();
    }
  }

  startGame () {
    this.setState({
      round: 1
    });
  }

  /**
   * @description the initial board which explains how to play the game
   */
  getInitialBoard() {
    return <InitialBoard employee={this.getExampleEmployee()}
                         startCallback={this.startGame.bind(this)} />
  }

  getExampleEmployee() {
    var employeeCount = this.state.employees.length;
    var exampleIndex = Math.floor(Math.random() * employeeCount);
    return this.state.employees[exampleIndex];
  }

  /**
   * TODO this needs improving vastly
   */
  getEmployeesForRound() {
    var employeeCount = this.state.employees.length;
    var uniqueEmployeeIndices = [];
    while (uniqueEmployeeIndices.length < 3) {
      var candidate = Math.floor(Math.random() * employeeCount);
      if (uniqueEmployeeIndices.indexOf(candidate) == -1) {
        uniqueEmployeeIndices.push(candidate);
      }
    }
    var chosenEmployees = [];
    for (var employeeIndex of uniqueEmployeeIndices) {
      chosenEmployees.push(this.state.employees[employeeIndex]);
    }
    return chosenEmployees;
  }

  getInPlayBoard() {
    return <NameGameBoard employees={this.getEmployeesForRound()} round={this.state.round} />;
  }

  getEndBoard() {
    return
Finished!
;
  }

  /**
   * @description Get users progress through the current game (0 - 100)
   */
  getProgress() {
    return (this.state.round / this.props.roundCount) * 100;
  }

  /**
   * Is the user playing? i.e. started and finished
   */
  inProgress() {
    return this.state.round > 0 && this.state.round <= this.props.roundCount;
  }

}

export default Game;
<commit_msg>Cleaned up function<commit_after>import React from 'react';
import request from 'request';
import Jumbotron from 'react-bootstrap/lib/Jumbotron';
import ProgressBar from 'react-bootstrap/lib/ProgressBar';
import InitialBoard from './components/InitialBoard';
import NameGameBoard from './components/NameGameBoard';

/*
 * @class Game representing the game board.
 */
class Game extends React.Component {

  /**
   * @constructor
   */
  constructor(options) {
    super(options);
    this.state = {
      employees: [],
      round: 0
    };
  }

  /**
   * @description Load all the data and update state
   * TODO: handle graceful failure of REST API
   */
  componentDidMount () {
    request(this.props.url, function (error, response, body) {
      if (!error && response.statusCode === 200) {
        var employees = JSON.parse(body);
        this.setState({
          employees: employees,
          init: true
        });
      }
    }.bind(this));
  }

  /**
   * @description Top level render of name game application
   */
  render () {
    if (!this.state.init) {
      return null;
    }
    return

            <Jumbotron>

WillowTree Name Game

How many names can you remember?

            </Jumbotron>
            <ProgressBar active={this.inProgress()} bsStyle="success" now={this.getProgress()} />
            {this.getCurrentBoard()}

;
  }

  getCurrentBoard () {
    if (this.state.round === 0) {
      return this.getInitialBoard();
    } else if (this.state.round === this.props.roundCount) {
      return this.getEndBoard();
    } else {
      return this.getInPlayBoard();
    }
  }

  startGame () {
    this.setState({
      round: 1
    });
  }

  /**
   * @description the initial board which explains how to play the game
   */
  getInitialBoard() {
    return <InitialBoard employee={this.getExampleEmployee()}
                         startCallback={this.startGame.bind(this)} />
  }

  getExampleEmployee() {
    var employeeCount = this.state.employees.length;
    var exampleIndex = Math.floor(Math.random() * employeeCount);
    return this.state.employees[exampleIndex];
  }

  getEmployeesForRound() {
    var employeeCount = this.state.employees.length;
    var uniqueEmployeeIndices = [];
    var uniqueEmployees = [];
    while (uniqueEmployeeIndices.length < 3) {
      var candidate = Math.floor(Math.random() * employeeCount);
      if (uniqueEmployeeIndices.indexOf(candidate) == -1) {
        uniqueEmployeeIndices.push(candidate);
        uniqueEmployees.push(this.state.employees[candidate]);
      }
    }
    return uniqueEmployees;
  }

  getInPlayBoard() {
    return <NameGameBoard employees={this.getEmployeesForRound()} round={this.state.round} />;
  }

  getEndBoard() {
    return
Finished!
;
  }

  /**
   * @description Get users progress through the current game (0 - 100)
   */
  getProgress() {
    return (this.state.round / this.props.roundCount) * 100;
  }

  /**
   * Is the user playing? i.e. started and finished
   */
  inProgress() {
    return this.state.round > 0 && this.state.round <= this.props.roundCount;
  }

}

export default Game;
<|endoftext|>


<commit_before>const log = require('npmlog');
const fs = require('fs');

/**
 * Loads config for `rnpm` to use by projects.
 *
 * In order to override default settings, simply mirror them under `rnpm` key in your
 * package.json.
 *
 * In order to make `rnpm` ignore certain targets, simply set them to `false`. Otherwise,
 * there will be warnings.
 */
module.exports = () => {
  var pjson = require('../package.json');

  if (!pjson) {
    return log.warn('EPACKAGEJSON', `Not found. Are you sure it's a React Native project?`);
  }

  var defaultConfig = {
    ios: {
      project: `./ios/${pjson.name}.xcodeproj`,
    },
    android: {
      project: './android/app/build.gradle',
    },
  };

  return pjson.rnpm
    ? Object.assign({}, defaultConfig, pjson.rnpm)
    : defaultConfig;
};
<commit_msg>Update require<commit_after>const log = require('npmlog');
const efs = require('./utils/fs');

/**
 * Loads config for `rnpm` to use by projects.
 *
 * In order to override default settings, simply mirror them under `rnpm` key in your
 * package.json.
 *
 * In order to make `rnpm` ignore certain targets, simply set them to `false`. Otherwise,
 * there will be warnings.
 */
module.exports = () => {
  var pjson = efs.requireFile('./package.json');

  if (!pjson) {
    return log.warn('EPACKAGEJSON', `Not found. Are you sure it's a React Native project?`);
  }

  var defaultConfig = {
    ios: {
      project: `./ios/${pjson.name}.xcodeproj`,
    },
    android: {
      project: './android/app/build.gradle',
    },
  };

  return pjson.rnpm
    ? Object.assign({}, defaultConfig, pjson.rnpm)
    : defaultConfig;
};
<|endoftext|>