<commit_before>/**	Maltypart is a simple multipart builder.
 *	It is very similar to HTML5 FormData, but offers a bit more control over fields and serialization.
 *
 *	@example
 *	var RequestBody = require('maltypart').RequestBody;
 *
 *	var request = new RequestBody();
 *
 *	request.append({
 *		// String values get serialized with the default content-type, application/octet-stream:
 *		some_key : "some value",
 *
 *		// Specify an Object with "contentType" and "data" properties to set your own content-type.
 *		otherKey : {
 *			contentType : "image/png",
 *			data : "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD"
 *					+ "///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDe"
 *					+ "NGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC"
 *		}
 *	});
 *
 *	request.append('some-file', new File(), function() {
 *		// file added.
 *
 *		// Log the body as text
 *		console.log( request.toString() );
 *
 *		// Send the multipart body with XMLHttpRequest:
 *		xhr.setRequestHeader('Content-Type', request.getContentType());
 *		xhr.send( request.getData() );
 *	});
 */
(function(root, factory) {
	if (typeof define==='function' && define.amd) {
		define([], factory);
	}
	else if (typeof module==='object' && module.exports) {
		module.exports = factory();
	}
	else {
		root.maltypart = factory();
	}
}(this, function() {
	/**	@private */
	var count=0, p;

	/**	Represents a multipart message body to be serialized.
	 *	@class
	 *	@memberOf module:maltypart
	 *	@param {Object|Array} fields
	 *	@param {String} [boundary=random]
	 */
	function RequestBody(fields, boundary) {
		this.fields = {};
		if (fields) {
			this.append(fields);
		}
		this.setBoundary(boundary);
	}

	RequestBody.prototype = {

		/** @ignore */
		constructor : RequestBody,

		/** @private */
		availableTypes : ['multipart', 'form-encoded'],

		/** Override the automatic `mutlipart`/`form-encoded` detection.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {String} type		One of: `multipart` or `form-encoded`.
		 *	@returns {this}
		 */
		setType : function(type) {
			this.typeOverride = this.availableTypes.indexOf(type)!==-1 ? type : null;
			return this;
		},

		/** Returns a `String` indicating if the RequestBody will be serialized as `multipart`, or `form-encoded`.
		 *	If no fields have been added that have a `contentType`, the request will be serialized as `form-encoded`.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@returns {String} type
		 */
		getType : function() {
			var override = this.typeOverride;
			if (this.availableTypes.indexOf(override)!==-1) {
				return override;
			}
			for (var i in this.fields) {
				if (this.fields.hasOwnProperty(i) && typeof this.fields[i] && this.fields[i].contentType) {
					return 'multipart';
				}
			}
			return 'form-encoded';
		},

		/** Append one or more fields to the RequestBody.
		 *	If a `fields` is a `string`, this method acts as an alias of {@link module:maltypart.RequestBody#setField}.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {Array|Object} fields		An Array of objects with `name` and `value` properties, or a key-value Object.
		 *	@param {Boolean} [replace=true]		By default, any existing field with the same name is replaced. If `replace` is set to `false`, existing values will be left in-place, and the new value will be appended. This results in duplicate keys (which can be useful!).
		 *	@returns {this}
		 */
		append : function(fields, replace) {
			var name, i;
			if (typeof fields==='string' && arguments.length>=2) {
				this.setField.apply(this, arguments);
			}
			else if (isArray(fields)) {
				for (i=0; i<fields.length; i++) {
					this.setField(fields[i].name, fields[i].value, replace);
				}
			}
			else {
				for (name in fields) {
					if (fields.hasOwnProperty(name)) {
						this.setField(name, fields[name], replace);
					}
				}
			}
			return this;
		},

		/** Set the value of a new or existing field.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {String} name				A field name with which to associate the specified value
		 *	@param {String|module:maltypart.RequestField|Element|File} value	Any of: a {@link module:maltypart.RequestField RequestField}, a simple String value, an HTML5 [File](https://developer.mozilla.org/en/docs/Web/API/File) object, or any form input Element.
		*	@param {Boolean} [replace=true]		By default, any existing field with the same name is replaced. If `replace` is set to `false`, existing values will be left in-place, and the new value will be appended. This results in duplicate keys (which can be useful!).
		*	@param {Object} [headers]			If set, headers will be added to the field
		 *	@returns {this}
		 */
		setField : function(name, value, replace, headers) {
			var fields = this.fields;
			name = name + '';
			if ((window.File && value instanceof window.File) || (window.Blob && value instanceof window.Blob)) {
				return this.setFileField(name, value, typeof replace==='function' && replace, headers);
			}
			if (value && value.nodeType && value.nodeName && value.getAttribute) {
				value = value.value;
			}
			else if (!isArray(value) && (!value || !(value instanceof RequestField || (value.contentType && value.data)))) {
				value = value + '';
			}
			if (name.match(/\[\]$/g)) {
				replace = false;
			}
			if (replace===false && fields.hasOwnProperty(name)) {
				if (!isArray(fields[name])) {
					fields[name] = [fields[name]];
				}
				fields[name].push(value);
			}
			else {
				fields[name] = value;
			}
			return this;
		},

		/** Add an HTML5 File object to the request body
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {String} name			A field name with which to associate the acquired field value
		 *	@param {File} file				An HTML5 [File](https://developer.mozilla.org/en/docs/Web/API/File) object.
		 *	@param {Function} [callback]	A callback to call once the file has been fully added.
		 *	@returns {this}
		 */
		setFileField : function(name, file, callback, headers) {
			var self = this,
				reader = new FileReader();
			reader.onloadend = function() {
				self.setField(name, new RequestField(
					arrayBufferToBinaryString(reader.result),
					file.type,
					file.name,
					headers
				));
				if (typeof callback==='function') {
					callback();
				}
				file = callback = self = reader = null;
			};
			reader.readAsArrayBuffer(file);
			return this;
		},

		/** Set a custom "boundary" String to use when separating multipart fields.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {String} [boundary=rnd()]	A custom boundary. If omitted, generates a new random boundary.
		 *	@returns {this}
		 */
		setBoundary : function(boundary) {
			this.boundary = (boundary || rnd()) + '';
			return this;
		},

		/** Get the request body as a String.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {Object} [fields]	Optionally add fields prior to serialization
		 *	@returns {String} encodedMultipartBody
		 */
		toString : function(fields) {
			var bodyType = this.getType(),
				body = '',
				iter, name, value, type, item, v, i, headers, p;

			if (!this.boundary) {
				this.setBoundary();
			}

			if (fields) {
				this.append(fields);
			}

			for (name in this.fields) {
				if (this.fields.hasOwnProperty(name)) {
					value = this.fields[name];
					iter = isArray(value) ? value : [value];
					for (i=0; i<iter.length; i++) {
						v = iter[i];
						if (bodyType==='multipart') {
							headers = v.headers;
							//type = 'application/octet-stream';
							type = null;
							if (v.contentType) {
								type = v.contentType;
								v = v.data;
							}
							item = '--' + this.boundary + '\r\n' +
								'Content-Disposition: form-data; name="' + name + '"';
							if (iter[i].filename) {
								item += '; filename="' + iter[i].filename + '"';
							}
							item += '\r\n';
							if (type) {
								item += 'Content-type: ' + type + '\r\n';
							}
							if (headers) {
								for (p in headers) {
									if (headers.hasOwnProperty(p)) {
										item += p + ': ' + headers[p] + '\r\n';
									}
								}
							}
							item += '\r\n' + v + '\r\n';
						}
						else if (bodyType==='form-encoded') {
							item = encodeURIComponent(name) + '=' + encodeURIComponent(v) + '&';
						}
						body += item;
					}
				}
			}

			if (bodyType==='multipart') {
				body += '--' + this.boundary + '--\r\n';
			}
			else if (bodyType==='form-encoded') {
				body = body.substring(0, body.length-1);
			}
			return body;
		},

		/** Get the String or Uint8Array multipart request body.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@returns {String|Uint8Array} data
		 */
		getData : function() {
			var str = this.toString(),
				len, buf;
			if (this.getType()==='multipart') {
				len = str.length;
				buf = new Uint8Array(len);
				for (var i=0; i<len; i++) {
					buf[i] = str.charCodeAt(i) & 0xff;
				}
				return buf;
			}
			return str;
		},

		/** Returns the appropriate Content-Type header value for this request body.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {Boolean} [includeCharset=false]		If `true`, specifies a character set within the content-type.
		 *	@returns {String} contentType
		 */
		getContentType : function(includeCharset) {
			var type = this.getType();
			if (type==='multipart') {
				return 'multipart/form-data; ' + (includeCharset ? 'charset=utf-8; ' : '') + 'boundary=' + this.boundary;
			}
			return 'application/x-www-form-encoded';
		}
	};

	/**	Represents a content field to be added to a request.
	 *	@class
	 *	@memberOf module:maltypart
	 *	@param {Any} data				The binary or textual value of the field
	 *	@param {String} contentType		Content-Type header for the field
	 *	@param {String} [filename]		A filename to attribute to the field when serializing
	 *	@param {Object} [headers]		Extra headers to append to the field when serializing
	 */
	function RequestField(data, contentType, filename, headers) {
		/** The binary or textual value of the field
		 *	@instance @any
		 */
		this.data = data;

		/** Content-Type header for the field
		 *	@instance @string
		 */
		this.contentType = contentType;

		/** A filename to attribute to the field when serializing
		 *	@instance @string
		 */
		this.filename = filename;

		/** Extra headers to append to the field when serializing
		 *	@instance @object
		 */
		this.headers = headers;
	}

	/** @ignore */
	function isArray(arr) {
		return Object.prototype.toString.call(arr)==='[object Array]';
	}

	/** @ignore */
	function rnd() {
		return Math.random().toString(36).substring(2) + (++count).toString(36);
	}

	/** @ignore */
	function arrayBufferToBinaryString(buffer) {
		var bin   = '';
		var bytes = new Uint8Array(buffer);

		for (var i = 0; i < bytes.byteLength; i++)
			bin += String.fromCharCode(bytes[i]);

		return bin;
	}

	return {
		RequestBody : RequestBody,
		RequestField : RequestField
	};
}));
<commit_msg>Fix messy overloading of setFileField()<commit_after>/**	Maltypart is a simple multipart builder.
 *	It is very similar to HTML5 FormData, but offers a bit more control over fields and serialization.
 *
 *	@example
 *	var RequestBody = require('maltypart').RequestBody;
 *
 *	var request = new RequestBody();
 *
 *	request.append({
 *		// String values get serialized with the default content-type, application/octet-stream:
 *		some_key : "some value",
 *
 *		// Specify an Object with "contentType" and "data" properties to set your own content-type.
 *		otherKey : {
 *			contentType : "image/png",
 *			data : "iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD"
 *					+ "///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDe"
 *					+ "NGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC"
 *		}
 *	});
 *
 *	request.append('some-file', new File(), function() {
 *		// file added.
 *
 *		// Log the body as text
 *		console.log( request.toString() );
 *
 *		// Send the multipart body with XMLHttpRequest:
 *		xhr.setRequestHeader('Content-Type', request.getContentType());
 *		xhr.send( request.getData() );
 *	});
 */
(function(root, factory) {
	if (typeof define==='function' && define.amd) {
		define([], factory);
	}
	else if (typeof module==='object' && module.exports) {
		module.exports = factory();
	}
	else {
		root.maltypart = factory();
	}
}(this, function() {
	/**	@private */
	var count=0, p;

	/**	Represents a multipart message body to be serialized.
	 *	@class
	 *	@memberOf module:maltypart
	 *	@param {Object|Array} fields
	 *	@param {String} [boundary=random]
	 */
	function RequestBody(fields, boundary) {
		this.fields = {};
		if (fields) {
			this.append(fields);
		}
		this.setBoundary(boundary);
	}

	RequestBody.prototype = {

		/** @ignore */
		constructor : RequestBody,

		/** @private */
		availableTypes : ['multipart', 'form-encoded'],

		/** Override the automatic `mutlipart`/`form-encoded` detection.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {String} type		One of: `multipart` or `form-encoded`.
		 *	@returns {this}
		 */
		setType : function(type) {
			this.typeOverride = this.availableTypes.indexOf(type)!==-1 ? type : null;
			return this;
		},

		/** Returns a `String` indicating if the RequestBody will be serialized as `multipart`, or `form-encoded`.
		 *	If no fields have been added that have a `contentType`, the request will be serialized as `form-encoded`.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@returns {String} type
		 */
		getType : function() {
			var override = this.typeOverride;
			if (this.availableTypes.indexOf(override)!==-1) {
				return override;
			}
			for (var i in this.fields) {
				if (this.fields.hasOwnProperty(i) && typeof this.fields[i] && this.fields[i].contentType) {
					return 'multipart';
				}
			}
			return 'form-encoded';
		},

		/** Append one or more fields to the RequestBody.
		 *	If a `fields` is a `string`, this method acts as an alias of {@link module:maltypart.RequestBody#setField}.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {Array|Object} fields		An Array of objects with `name` and `value` properties, or a key-value Object.
		 *	@param {Boolean} [replace=true]		By default, any existing field with the same name is replaced. If `replace` is set to `false`, existing values will be left in-place, and the new value will be appended. This results in duplicate keys (which can be useful!).
		 *	@returns {this}
		 */
		append : function(fields, replace) {
			var name, i;
			if (typeof fields==='string' && arguments.length>=2) {
				this.setField.apply(this, arguments);
			}
			else if (isArray(fields)) {
				for (i=0; i<fields.length; i++) {
					this.setField(fields[i].name, fields[i].value, replace);
				}
			}
			else {
				for (name in fields) {
					if (fields.hasOwnProperty(name)) {
						this.setField(name, fields[name], replace);
					}
				}
			}
			return this;
		},

		/** Set the value of a new or existing field.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {String} name				A field name with which to associate the specified value
		 *	@param {String|module:maltypart.RequestField|Element|File} value	Any of: a {@link module:maltypart.RequestField RequestField}, a simple String value, an HTML5 [File](https://developer.mozilla.org/en/docs/Web/API/File) object, or any form input Element.
		*	@param {Boolean} [replace=true]		By default, any existing field with the same name is replaced. If `replace` is set to `false`, existing values will be left in-place, and the new value will be appended. This results in duplicate keys (which can be useful!).
		*	@param {Object} [headers]			If set, headers will be added to the field
		 *	@returns {this}
		 */
		setField : function(name, value, replace, headers, callback) {
			var fields = this.fields;
			name = name + '';
			if ((window.File && value instanceof window.File) || (window.Blob && value instanceof window.Blob)) {
				return this.setFileField.apply(this, arguments);
			}
			if (value && value.nodeType && value.nodeName && value.getAttribute) {
				value = value.value;
			}
			else if (!isArray(value) && (!value || !(value instanceof RequestField || (value.contentType && value.data)))) {
				value = value + '';
			}
			if (name.match(/\[\]$/g)) {
				replace = false;
			}
			if (replace===false && fields.hasOwnProperty(name)) {
				if (!isArray(fields[name])) {
					fields[name] = [fields[name]];
				}
				fields[name].push(value);
			}
			else {
				fields[name] = value;
			}
			return this;
		},

		/** Add an HTML5 File object to the request body
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {String} name			A field name with which to associate the acquired field value
		 *	@param {File} file				An HTML5 [File](https://developer.mozilla.org/en/docs/Web/API/File) object.
		 *	@param {Function} [callback]	A callback to call once the file has been fully added.
		 *	@returns {this}
		 */
		setFileField : function(name, file, replace, headers, callback) {
			var self = this,
				reader = new FileReader();
			if (typeof replace==='function') {
				callback = replace;
				replace = true;
			}
			reader.onloadend = function() {
				self.setField(name, new RequestField(
					arrayBufferToBinaryString(reader.result),
					file.type,
					file.name,
					headers
				), replace!==false);
				if (typeof callback==='function') {
					callback();
				}
				file = callback = self = reader = null;
			};
			reader.readAsArrayBuffer(file);
			return this;
		},

		/** Set a custom "boundary" String to use when separating multipart fields.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {String} [boundary=rnd()]	A custom boundary. If omitted, generates a new random boundary.
		 *	@returns {this}
		 */
		setBoundary : function(boundary) {
			this.boundary = (boundary || rnd()) + '';
			return this;
		},

		/** Get the request body as a String.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {Object} [fields]	Optionally add fields prior to serialization
		 *	@returns {String} encodedMultipartBody
		 */
		toString : function(fields) {
			var bodyType = this.getType(),
				body = '',
				iter, name, value, type, item, v, i, headers, p;

			if (!this.boundary) {
				this.setBoundary();
			}

			if (fields) {
				this.append(fields);
			}

			for (name in this.fields) {
				if (this.fields.hasOwnProperty(name)) {
					value = this.fields[name];
					iter = isArray(value) ? value : [value];
					for (i=0; i<iter.length; i++) {
						v = iter[i];
						if (bodyType==='multipart') {
							headers = v.headers;
							//type = 'application/octet-stream';
							type = null;
							if (v.contentType) {
								type = v.contentType;
								v = v.data;
							}
							item = '--' + this.boundary + '\r\n' +
								'Content-Disposition: form-data; name="' + name + '"';
							if (iter[i].filename) {
								item += '; filename="' + iter[i].filename + '"';
							}
							item += '\r\n';
							if (type) {
								item += 'Content-type: ' + type + '\r\n';
							}
							if (headers) {
								for (p in headers) {
									if (headers.hasOwnProperty(p)) {
										item += p + ': ' + headers[p] + '\r\n';
									}
								}
							}
							item += '\r\n' + v + '\r\n';
						}
						else if (bodyType==='form-encoded') {
							item = encodeURIComponent(name) + '=' + encodeURIComponent(v) + '&';
						}
						body += item;
					}
				}
			}

			if (bodyType==='multipart') {
				body += '--' + this.boundary + '--\r\n';
			}
			else if (bodyType==='form-encoded') {
				body = body.substring(0, body.length-1);
			}
			return body;
		},

		/** Get the String or Uint8Array multipart request body.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@returns {String|Uint8Array} data
		 */
		getData : function() {
			var str = this.toString(),
				len, buf;
			if (this.getType()==='multipart') {
				len = str.length;
				buf = new Uint8Array(len);
				for (var i=0; i<len; i++) {
					buf[i] = str.charCodeAt(i) & 0xff;
				}
				return buf;
			}
			return str;
		},

		/** Returns the appropriate Content-Type header value for this request body.
		 *	@memberOf module:maltypart.RequestBody#
		 *	@param {Boolean} [includeCharset=false]		If `true`, specifies a character set within the content-type.
		 *	@returns {String} contentType
		 */
		getContentType : function(includeCharset) {
			var type = this.getType();
			if (type==='multipart') {
				return 'multipart/form-data; ' + (includeCharset ? 'charset=utf-8; ' : '') + 'boundary=' + this.boundary;
			}
			return 'application/x-www-form-encoded';
		}
	};

	/**	Represents a content field to be added to a request.
	 *	@class
	 *	@memberOf module:maltypart
	 *	@param {Any} data				The binary or textual value of the field
	 *	@param {String} contentType		Content-Type header for the field
	 *	@param {String} [filename]		A filename to attribute to the field when serializing
	 *	@param {Object} [headers]		Extra headers to append to the field when serializing
	 */
	function RequestField(data, contentType, filename, headers) {
		/** The binary or textual value of the field
		 *	@instance @any
		 */
		this.data = data;

		/** Content-Type header for the field
		 *	@instance @string
		 */
		this.contentType = contentType;

		/** A filename to attribute to the field when serializing
		 *	@instance @string
		 */
		this.filename = filename;

		/** Extra headers to append to the field when serializing
		 *	@instance @object
		 */
		this.headers = headers;
	}

	/** @ignore */
	function isArray(arr) {
		return Object.prototype.toString.call(arr)==='[object Array]';
	}

	/** @ignore */
	function rnd() {
		return Math.random().toString(36).substring(2) + (++count).toString(36);
	}

	/** @ignore */
	function arrayBufferToBinaryString(buffer) {
		var bin   = '';
		var bytes = new Uint8Array(buffer);

		for (var i = 0; i < bytes.byteLength; i++)
			bin += String.fromCharCode(bytes[i]);

		return bin;
	}

	return {
		RequestBody : RequestBody,
		RequestField : RequestField
	};
}));
<|endoftext|>


<commit_before>require('dotenv').load();

const craftai = require('craft-ai').createClient;
const fs = require('fs');
const path = require('path');
const process = require('process');

var utils = require('./utils');

const ROOM1 = 'BEDROOM_1';
const ROOM2 = 'LIVING_ROOM';
const ROOM3 = 'RESTROOM';

const GENERATOR_FILTER = [ROOM1, ROOM2, ROOM3];
const GENERATOR_NAME = 'smarthome';

const LOCAL_FILE_PATH1 = path.join(__dirname, `../data/twor_${ROOM1}.json`);
const LOCAL_FILE_PATH2 = path.join(__dirname, `../data/twor_${ROOM2}.json`);
const LOCAL_FILE_PATH3 = path.join(__dirname, `../data/twor_${ROOM3}.json`);

// 0 - Create the craft client
const CRAFT_CLIENT = craftai(process.env.CRAFT_TOKEN);

// 1 - Retrieve the prepared data
utils.readData(LOCAL_FILE_PATH1)
  .then((context) => {
    const agentName = ROOM1;
    // 2 - Cleanup the mess (agent's name can't be duplicate)
    return CRAFT_CLIENT.deleteAgent(agentName)
      // 3 - Create the agent 1
      .then(() => {
        console.log(`Creating agent ${agentName}.`);
        return CRAFT_CLIENT.createAgent({
          context: {
            movement: {
              type: 'continuous'
            },
            light: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day'
            }
          },
          output: ['light'],
          time_quantum: 15 * 60 // 15 min
        }, agentName);
      })
      // 4 - Send the dataset's operations
      .then(() => {
        console.log(`Adding context operations for agent ${agentName}...`);
        return CRAFT_CLIENT.addAgentContextOperations(agentName, context);
      })
      .then(() => {
        console.log(`Computing the decision model for agent ${agentName} (this may take a little while)...`);
        // 5 - Compute decision from the decision tree in order to automate the light
        // Download the tree
        return CRAFT_CLIENT.getAgentDecisionTree(agentName, context[context.length - 1].timestamp, 2);
      })
      .then((tree) => {
        console.log('Decision tree computed!');
        // 6 - Get decisions
        const d1 = craftai.interpreter.decide(
          tree,
          {
            movement: 0
          },
          new craftai.Time('2010-01-04T01:30:00+09:00')
        );
        console.log(`Decision taken:\n- The light is ${d1.output.light.predicted_value} when there is no movement at 1:30AM.`);
        const d2 = craftai.interpreter.decide(
          tree,
          {
            movement: 0
          },
          new craftai.Time('2010-01-04T08:58:00+09:00')
        );
        console.log(`- The light is ${d2.output.light.predicted_value} when there is no movement at 8:58AM.`);
        const d3 = craftai.interpreter.decide(
          tree,
          {
            movement: 0
          },
          new craftai.Time('2010-01-04T09:42:00+09:00')
        );
        console.log(`- The light is ${d3.output.light.predicted_value} when there is no movement at 9:42AM.`);
        const d4 = craftai.interpreter.decide(
          tree,
          {
            movement: 2
          },
          new craftai.Time('2010-01-04T09:42:00+09:00')
        );
        console.log(`- The light is ${d4.output.light.predicted_value} when there is some movement at 9:42AM.`);
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T17:03:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 5:03PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T20:55:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 8:55PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T22:07:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 10:07PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 10
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is a lot of movement at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 10
            },
            new craftai.Time('2010-01-04T02:17:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is a lot of movement at 2:17AM.`);
        }
      })
      .then(() => {
        const deleteBulkPayload = [
          { id: ROOM1 },
          { id: ROOM2 },
          { id: ROOM3 }
        ];
        return Promise.all([
          CRAFT_CLIENT.deleteAgentBulk(deleteBulkPayload),
          CRAFT_CLIENT.deleteGenerator(GENERATOR_NAME)
        ]);
      })
      // 7 - Create Agent 1, 2 and 3
      .then(() => utils.readData(LOCAL_FILE_PATH1))
      .then((context_1) => {
        operations_agent_1 = utils.prepareData(context_1, ROOM1);
        return utils.readData(LOCAL_FILE_PATH2);
      })
      .then((context_2) => {
        operations_agent_2 = utils.prepareData(context_2, ROOM2);
        return utils.readData(LOCAL_FILE_PATH3);
      })
      .then((context_3) => {
        operations_agent_3 = utils.prepareData(context_3, ROOM3);
        const configuration = {
          context: {
            movement: {
              type: 'continuous'
            },
            stateChange: {
              type: 'enum'
            },
            room: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day'
            }
          },
          output: ['stateChange'],
          time_quantum: 15 * 60 // 15 min
        };
        const createBulkPayload = [
          { id: ROOM1, configuration: configuration },
          { id: ROOM2, configuration: configuration },
          { id: ROOM3, configuration: configuration }
        ];
        console.log(`Creating agents ${ROOM1}, ${ROOM2} and ${ROOM3}.`);
        return CRAFT_CLIENT.createAgentBulk(createBulkPayload)
      })
      .then(() => {
        const contextOperationBulkPayload = [
          { id: ROOM1, operations: operations_agent_1 },
          { id: ROOM2, operations: operations_agent_2 },
          { id: ROOM3, operations: operations_agent_3 }
        ];
        console.log(`Adding context operations for agents ${ROOM1}, ${ROOM2} and ${ROOM3}.`);
        return CRAFT_CLIENT.addAgentContextOperationsBulk(contextOperationBulkPayload)
      })
      .then(() => {
        const GENERATOR_CONFIGURATION = {
          context: {
            stateChange: {
              type: 'enum'
            },
            room: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day',
              is_generated: true
            }
          },
          output: [
            "stateChange"
          ],
          learning_period: 1500000,
          tree_max_operations: 15000,
          operations_as_events: true,
          filter: GENERATOR_FILTER
        };
        console.log(`Creating generator ${GENERATOR_NAME}.`);
        // 8 - Create generator
        return CRAFT_CLIENT.createGenerator(GENERATOR_CONFIGURATION, GENERATOR_NAME);
      })
      .then(() => {
        console.log(`Computing the decision model for generator ${GENERATOR_NAME} (this may take a little while)...`);
        // 9 - Compute decision from the decision tree in order to automate the light
        // Download the tree
        return CRAFT_CLIENT.getGeneratorDecisionTree(GENERATOR_NAME, context[context.length - 1].timestamp);
      })
      .then((tree) => {
        console.log('Generator decision tree computed!');
        // 10 - Get decisions
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM1
            },
            new craftai.Time('2010-01-04T01:30:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the bedroom at 1:30AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM2
            },
            new craftai.Time('2010-01-04T08:58:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the living room at 8:58AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM3
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the restroom at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM1
            },
            new craftai.Time('2010-01-08T02:17:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the bedroom at 2:17AM.`);
        }
      })
  })
  .catch((error) => {
    console.log('Error!', error);
    process.exit(1);
  });
<commit_msg>Update src/main.js<commit_after>require('dotenv').load();

const craftai = require('craft-ai').createClient;
const fs = require('fs');
const path = require('path');
const process = require('process');

var utils = require('./utils');

const ROOM1 = 'BEDROOM_1';
const ROOM2 = 'LIVING_ROOM';
const ROOM3 = 'RESTROOM';

const GENERATOR_FILTER = [ROOM1, ROOM2, ROOM3];
const GENERATOR_NAME = 'smarthome';

const LOCAL_FILE_PATH1 = path.join(__dirname, `../data/twor_${ROOM1}.json`);
const LOCAL_FILE_PATH2 = path.join(__dirname, `../data/twor_${ROOM2}.json`);
const LOCAL_FILE_PATH3 = path.join(__dirname, `../data/twor_${ROOM3}.json`);

// 0 - Create the craft client
const CRAFT_CLIENT = craftai(process.env.CRAFT_TOKEN);

// 1 - Retrieve the prepared data
utils.readData(LOCAL_FILE_PATH1)
  .then((context) => {
    const agentName = ROOM1;
    // 2 - Cleanup the mess (agent's name can't be duplicate)
    return CRAFT_CLIENT.deleteAgent(agentName)
      // 3 - Create the agent 1
      .then(() => {
        console.log(`Creating agent ${agentName}.`);
        return CRAFT_CLIENT.createAgent({
          context: {
            movement: {
              type: 'continuous'
            },
            light: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day'
            }
          },
          output: ['light'],
          time_quantum: 15 * 60 // 15 min
        }, agentName);
      })
      // 4 - Send the dataset's operations
      .then(() => {
        console.log(`Adding context operations for agent ${agentName}...`);
        return CRAFT_CLIENT.addAgentContextOperations(agentName, context);
      })
      .then(() => {
        console.log(`Computing the decision model for agent ${agentName} (this may take a little while)...`);
        // 5 - Compute decision from the decision tree in order to automate the light
        // Download the tree
        return CRAFT_CLIENT.getAgentDecisionTree(agentName, context[context.length - 1].timestamp, 2);
      })
      .then((tree) => {
        console.log('Decision tree computed!');
        // 6 - Get decisions
        const d1 = craftai.interpreter.decide(
          tree,
          {
            movement: 0
          },
          new craftai.Time('2010-01-04T01:30:00+09:00')
        );
        console.log(`Decision taken:\n- The light is ${d1.output.light.predicted_value} when there is no movement at 1:30AM.`);
        const d2 = craftai.interpreter.decide(
          tree,
          {
            movement: 0
          },
          new craftai.Time('2010-01-04T08:58:00+09:00')
        );
        console.log(`- The light is ${d2.output.light.predicted_value} when there is no movement at 8:58AM.`);
        const d3 = craftai.interpreter.decide(
          tree,
          {
            movement: 0
          },
          new craftai.Time('2010-01-04T09:42:00+09:00')
        );
        console.log(`- The light is ${d3.output.light.predicted_value} when there is no movement at 9:42AM.`);
        const d4 = craftai.interpreter.decide(
          tree,
          {
            movement: 2
          },
          new craftai.Time('2010-01-04T09:42:00+09:00')
        );
        console.log(`- The light is ${d4.output.light.predicted_value} when there is some movement at 9:42AM.`);
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T17:03:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 5:03PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T20:55:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 8:55PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 2
            },
            new craftai.Time('2010-01-04T22:07:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is some movement at 10:07PM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 10
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is a lot of movement at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              movement: 10
            },
            new craftai.Time('2010-01-04T02:17:00+09:00')
          );
          console.log(`- The light is ${d.output.light.predicted_value} when there is a lot of movement at 2:17AM.`);
        }
      })
      .then(() => {
        const deleteBulkPayload = [
          { id: ROOM1 },
          { id: ROOM2 },
          { id: ROOM3 }
        ];
        return Promise.all([
          CRAFT_CLIENT.deleteAgentBulk(deleteBulkPayload),
          CRAFT_CLIENT.deleteGenerator(GENERATOR_NAME)
        ]);
      })
      // 7 - Create Agent 1, 2 and 3
      .then(() => Promise.all([
        utils.readData(LOCAL_FILE_PATH1)),
        utils.readData(LOCAL_FILE_PATH2),
        utils.readData(LOCAL_FILE_PATH3)
      ])
      .then(([context1, context2, context3]) => {
        const operations_agent_1 = utils.prepareData(context_1, ROOM1);
        const operations_agent_2 = utils.prepareData(context_2, ROOM2);
        const operations_agent_3 = utils.prepareData(context_3, ROOM3);
        const configuration = {
          context: {
            movement: {
              type: 'continuous'
            },
            stateChange: {
              type: 'enum'
            },
            room: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day'
            }
          },
          output: ['stateChange'],
          time_quantum: 15 * 60 // 15 min
        };
        const createBulkPayload = [
          { id: ROOM1, configuration: configuration },
          { id: ROOM2, configuration: configuration },
          { id: ROOM3, configuration: configuration }
        ];
        console.log(`Creating agents ${ROOM1}, ${ROOM2} and ${ROOM3}.`);
        return CRAFT_CLIENT.createAgentBulk(createBulkPayload)
      })
      .then(() => {
        const contextOperationBulkPayload = [
          { id: ROOM1, operations: operations_agent_1 },
          { id: ROOM2, operations: operations_agent_2 },
          { id: ROOM3, operations: operations_agent_3 }
        ];
        console.log(`Adding context operations for agents ${ROOM1}, ${ROOM2} and ${ROOM3}.`);
        return CRAFT_CLIENT.addAgentContextOperationsBulk(contextOperationBulkPayload)
      })
      .then(() => {
        const GENERATOR_CONFIGURATION = {
          context: {
            stateChange: {
              type: 'enum'
            },
            room: {
              type: 'enum'
            },
            tz: {
              type: 'timezone'
            },
            time: {
              type: 'time_of_day',
              is_generated: true
            }
          },
          output: [
            "stateChange"
          ],
          learning_period: 1500000,
          tree_max_operations: 15000,
          operations_as_events: true,
          filter: GENERATOR_FILTER
        };
        console.log(`Creating generator ${GENERATOR_NAME}.`);
        // 8 - Create generator
        return CRAFT_CLIENT.createGenerator(GENERATOR_CONFIGURATION, GENERATOR_NAME);
      })
      .then(() => {
        console.log(`Computing the decision model for generator ${GENERATOR_NAME} (this may take a little while)...`);
        // 9 - Compute decision from the decision tree in order to automate the light
        // Download the tree
        return CRAFT_CLIENT.getGeneratorDecisionTree(GENERATOR_NAME, context[context.length - 1].timestamp);
      })
      .then((tree) => {
        console.log('Generator decision tree computed!');
        // 10 - Get decisions
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM1
            },
            new craftai.Time('2010-01-04T01:30:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the bedroom at 1:30AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM2
            },
            new craftai.Time('2010-01-04T08:58:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the living room at 8:58AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM3
            },
            new craftai.Time('2010-01-04T09:42:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the restroom at 9:42AM.`);
        }
        {
          const d = craftai.interpreter.decide(
            tree,
            {
              room: ROOM1
            },
            new craftai.Time('2010-01-08T02:17:00+09:00')
          );
          console.log(`- A change of state ${d.output.stateChange.predicted_value} is expected in the bedroom at 2:17AM.`);
        }
      })
  })
  .catch((error) => {
    console.log('Error!', error);
    process.exit(1);
  });
<|endoftext|>


<commit_before>/**
	Winter Rush Main
	Handles input, sounds, renderer, resize, score display
	by Felix Turner / @felixturner / www.airtight.cc
**/

//Global Config
var XRConfig = {
	playSound:true,
	playMusic:true,
	hitDetect:true,
	showDebug:true
};

//global
var FLOOR_WIDTH = 3600; //x
var FLOOR_DEPTH = 7200; //z
var MOVE_STEP = 500; //number of z units to move before recreating a new background strip

var snoise = new ImprovedNoise();

var XRMain = function() {

	var camera, scene, renderer;

	//FX
	var composer;
	var superPass;
	var hueTime = 0;
	var fxParams = {
		vignetteAmount:0.8,
		brightness:0,
		saturation: 0.5,
	};

	var hiScore = 0;
	var score = 0;

	var sndPickup;
	var sndCollide;
	var sndMusic;

	var lastEvent;
	var stats;
	var splashSize;

	var bkgndColor = 0x061837;
	var isMobile = false;

	//0->2 indicating which splash page is showing
	var splashMode = 0;
	var isFirstGame = true;

	function init() {

		XRConfig.showDebug = window.location.href.indexOf("?dev");

		if (XRConfig.showDebug){
			stats = new Stats();
			stats.domElement.style.position = 'absolute';
			stats.domElement.style.top = '30px';
			stats.domElement.style.left = '40px';
			$("#container").append( stats.domElement );
			stats.domElement.style.transform = "scale(2,2)";
			stats.domElement.style.webkitTransform = "scale(2,2)";
		}

		isMobile = !!('ontouchstart' in window); //true for android or ios, false for MS surface

		if (isMobile){
			$("#prompt-small").text("Tap to move left or right");
			$("#info").html("Built with Love by Airtight.");
		}

		//INIT CONTROLS
		$("#container").on( 'touchstart', onTouchStart, false );
		$("#container").on( 'touchend', onTouchEnd, false );

		$(document).on('keydown', onKeyDown, false);
		$(document).on('keyup', onKeyUp, false);
		$("#splash").on('mousedown', onMouseDown, false);
		$("#splash").on('tap', onMouseDown, false);

		// if (window.DeviceOrientationEvent) {
		// 	window.addEventListener('deviceorientation', deviceOrientationHandler, false);
		// }

		//init audio
		if (XRConfig.playSound){
			sndPickup = new Howl( {urls: ["res/audio/point.mp3"]});
			sndCollide = new Howl({ urls: ["res/audio/hit.mp3"]});
			sndBest = new Howl( {urls: ["res/audio/best.mp3"]});
		}

		if (XRConfig.playMusic){
			sndMusic = new Howl( {urls: ["res/audio/rouet.mp3"],loop: true,});
			$("#music-toggle").on("click",toggleMusic);
			$("#music-toggle").on("tap",toggleMusic);
		}

		//init 3D

		var size = 800;
		camera = new THREE.PerspectiveCamera( 75, 8 / 6, 1, 10000 );
		camera.position.z = FLOOR_DEPTH/2 - 300;

		scene = new THREE.Scene();
		scene.fog = new THREE.Fog( bkgndColor, FLOOR_DEPTH/2, FLOOR_DEPTH );

		renderer = new THREE.WebGLRenderer();
		renderer.setSize( window.innerWidth, window.innerHeight );
		renderer.setClearColor( bkgndColor, 1 );
		$("#container").append( renderer.domElement );

		//FX
		var renderPass = new THREE.RenderPass( scene, camera );
		superPass = new THREE.ShaderPass(THREE.SuperShader);

		superPass.uniforms.vigDarkness.value = 2;
		superPass.uniforms.vigOffset.value =  fxParams.vignetteAmount;
		superPass.uniforms.saturation.value =  fxParams.saturation -1;

		composer = new THREE.EffectComposer( renderer );
		composer.addPass( renderPass );
		composer.addPass( superPass );
		superPass.renderToScreen = true;

		XRGame.init();

		resize();

		animate();

		//fade in
		TweenMax.fromTo(fxParams , 1, {brightness: -1},{brightness:0,delay:0.5});
		TweenMax.fromTo($('#splash') , 1, {autoAlpha: 0},{autoAlpha: 1,delay:1});
		TweenMax.fromTo($('#info') , 1, {autoAlpha: 0},{autoAlpha: 1,delay:1});
		TweenMax.fromTo($('#music-toggle') , 1, {autoAlpha: 0},{autoAlpha: 1,delay:1});

		$("#preloader").css("display","none");

		//preload splash page images
		var img1 = new Image();
		img1.src = "res/img/xmas-splash.png";
		var img2 = new Image();
		img2.src = "res/img/xmas-best.png";
		var img3 = new Image();
		img3.src = "res/img/xmas-wipeout.png";

	}

	function toggleMusic(){

		$(this).toggleClass("off");

		if($(this).hasClass("off")){
			sndMusic.mute();
		}else{
			sndMusic.unmute();
		}

	}

	$(window).resize(function() {
		resize();
	});

	function resize(){

		var w = window.innerWidth;
		var h = window.innerHeight;

		//handle retina screens
		// var dpr = 1;
		// if (window.devicePixelRatio !== undefined) {
		// 	dpr = window.devicePixelRatio;
		// }

		composer.setSize(w , h );
		renderer.setSize(w, h);
		camera.aspect = w / h;

		//scale to fit and center splash
		splashSize = Math.min(w,h)*0.85;
		splashSize = Math.min(splashSize,500);

		$("#splash").css("width", splashSize + "px");
		$("#splash").css("height", splashSize+ "px");

		$("#splash").css("left",(w - splashSize)/2 + "px");
		$("#splash").css("top",(h - splashSize)/2 + "px");

		//splash page resizing
		if (splashMode === 0){
			if (isMobile){
				$('#prompt-big').css("font-size" , splashSize * 0.05 + "px");
				$('#prompt-small').css("font-size" , splashSize * 0.06 + "px");
			}else{
				$('#prompt-big').css("font-size" , splashSize * 0.06 + "px");
				$('#prompt-small').css("font-size" , splashSize * 0.04 + "px");

			}
		}else if(splashMode == 1){
			$('#prompt-big').css("font-size" , splashSize * 0.09 + "px");
		}else{
			$('#prompt-big').css("font-size" , splashSize * 0.08 + "px");
			$('#prompt-small').css("font-size" , splashSize * 0.04 + "px");
		}

	}

	function playCollide(){
		if (XRConfig.playSound) sndCollide.play();
	}

	function onScorePoint(){
		if (XRConfig.playSound) sndPickup.play();
		score += 1;
		$("#score-text").text(score);
		TweenMax.fromTo($('#score-text') , 0.4, {scale: 2},{scale: 1,ease:Bounce.easeOut});

		if (score === hiScore + 1 && hiScore !== 0){
			if (XRConfig.playSound) sndBest.play();
		}
	}

	function onGameOver(){

		if (XRConfig.playSound) sndCollide.play();

		//display score
		TweenMax.to($('#score-text') , 0.1, {autoAlpha: 0});
		TweenMax.fromTo($('#splash') , 0.5, {scale: 0.6,autoAlpha: 0},{scale: 1,autoAlpha: 1,ease:Expo.easeOut});
		TweenMax.fromTo($('#info') , 0.5, {autoAlpha: 0},{autoAlpha: 1});
		TweenMax.fromTo($('#music-toggle') , 0.5, {autoAlpha: 0},{autoAlpha: 1});

		if (score > hiScore){
			splashMode = 1;
			hiScore = score;
			$('#splash').css('background-image', 'url(res/img/xmas-best.png)');
			$('#prompt-big').text("SCORE: " + score);
			$('#prompt-small').css('display','none');
			$('#prompt-big').css("margin-top" , "10%");

		}else{
			splashMode = 2;
			$('#splash').css('background-image', 'url(res/img/xmas-wipeout.png)');
			$('#prompt-big').text("SCORE: " + score);
			$('#prompt-small').text("BEST SCORE: " + hiScore);
			$('#prompt-small').css('display','block');
			$('#prompt-big').css("margin-top" , "8%");
			$('#prompt-small').css("margin-top" , "2%");
		 }

		resize();
		hueTime =0;

	}

	function onGameStart(){
		TweenMax.to($('#splash') , 0.3, {autoAlpha: 0});
		TweenMax.to($('#info') , 0.3, {autoAlpha: 0});
		TweenMax.to($('#music-toggle') , 0.3, {autoAlpha: 0});
		TweenMax.to($('#score-text') , 0.3, {autoAlpha: 1,delay:0.3});
		score = 0;
		$("#score-text").text(score);

		if (isFirstGame && XRConfig.playMusic ) sndMusic.play();

		XRGame.startGame(isFirstGame);
		isFirstGame = false;
	}

	function animate(){

		requestAnimationFrame( animate );
		XRGame.animate();
		if (XRConfig.showDebug){
			stats.update();
		}

		//faster = more hue amount and faster shifts
		var hueAmount;
		if (XRGame.getSpeed() < 0.5){
			hueAmount = 0;
		}else{
			hueAmount = (XRGame.getSpeed()- 0.5) * 2;
		}
		superPass.uniforms.hueAmount.value =  hueAmount;

		hueTime += XRGame.getSpeed() * XRGame.getSpeed() * 0.05;
		var hue = hueTime % 2 - 1; //put in range -1 to 1
		superPass.uniforms.hue.value =  hue;
		superPass.uniforms.brightness.value =  fxParams.brightness;
		composer.render( 0.1 );

		//XRMain.trace( XRGame.getSpeed());

	}

	//INPUT HANDLERS
	function onTouchStart( event ) {

		if (!XRGame.getPlaying() && XRGame.getAcceptInput()){
			onGameStart();
		}

		for(  var i = 0; i <  event.touches.length; i++) {

			event.preventDefault();

			var xpos = event.touches[ i ].pageX;

			if (xpos > window.innerWidth / 2){
				XRGame.setRightDown(true);
			}else{
				XRGame.setLeftDown(true);
			}
		}
	}

	function onTouchEnd( event ) {

		for(  var i = 0; i <  event.changedTouches.length; i++) {

			event.preventDefault();
			var xpos = event.changedTouches[ i ].pageX;

			if (xpos > window.innerWidth / 2){
				XRGame.setRightDown(false);
			}else{
				XRGame.setLeftDown( false);
			}
		}
	}

	function onKeyUp( event ) {

		lastEvent = null;

		switch ( event.keyCode ) {
			case 39: /* RIGHT */
				XRGame.setRightDown(false);
				break;
			case 37: /* LEFT */
				XRGame.setLeftDown(false);
				break;
		}

		//endSlide();
	}

	function onKeyDown(event) {

		if (lastEvent && lastEvent.keyCode == event.keyCode) {
			return;
		}

		lastEvent = event;

		if (!XRGame.getPlaying() && XRGame.getAcceptInput()){
			onGameStart();
		}

		switch ( event.keyCode ) {
			case 39: /* RIGHT */
				XRGame.setRightDown(true);
				break;
			case 37: /* LEFT */
				XRGame.setLeftDown( true);
				break;

		}
	}

	function onMouseDown(){

		if (!XRGame.getPlaying()){
			onGameStart();
		}
	}

	function trace(text){
		if (XRConfig.showDebug){
			$("#debug-text").text(text);
		}
	}

	// function deviceOrientationHandler(eventData) {
	// 	if (eventData.beta === null) return;
	// 	var cuttoff = 5;
	// 	var tiltedRight = eventData.beta > cuttoff;
	// 	var tiltedLeft = eventData.beta < -cuttoff;
	// 	XRGame.setRightDown(tiltedRight);
	// 	XRGame.setLeftDown(tiltedLeft);
	// }

	return {
		init:init,
		trace: trace,
		onGameOver:onGameOver,
		onScorePoint: onScorePoint,
		getScene:function (){return scene;},
		getCamera:function (){return camera;},
		playCollide:playCollide,
		fxParams:fxParams,
	};

}();

$(document).ready(function() {
	XRMain.init();
});
<commit_msg>Fix dev flag<commit_after>/**
	Winter Rush Main
	Handles input, sounds, renderer, resize, score display
	by Felix Turner / @felixturner / www.airtight.cc
**/

//Global Config
var XRConfig = {
	playSound:true,
	playMusic:true,
	hitDetect:true,
	showDebug:true
};

//global
var FLOOR_WIDTH = 3600; //x
var FLOOR_DEPTH = 7200; //z
var MOVE_STEP = 500; //number of z units to move before recreating a new background strip

var snoise = new ImprovedNoise();

var XRMain = function() {

	var camera, scene, renderer;

	//FX
	var composer;
	var superPass;
	var hueTime = 0;
	var fxParams = {
		vignetteAmount:0.8,
		brightness:0,
		saturation: 0.5,
	};

	var hiScore = 0;
	var score = 0;

	var sndPickup;
	var sndCollide;
	var sndMusic;

	var lastEvent;
	var stats;
	var splashSize;

	var bkgndColor = 0x061837;
	var isMobile = false;

	//0->2 indicating which splash page is showing
	var splashMode = 0;
	var isFirstGame = true;

	function init() {

		XRConfig.showDebug = window.location.href.indexOf("?dev")  > -1;

		if (XRConfig.showDebug){
			stats = new Stats();
			stats.domElement.style.position = 'absolute';
			stats.domElement.style.top = '30px';
			stats.domElement.style.left = '40px';
			$("#container").append( stats.domElement );
			stats.domElement.style.transform = "scale(2,2)";
			stats.domElement.style.webkitTransform = "scale(2,2)";
		}

		isMobile = !!('ontouchstart' in window); //true for android or ios, false for MS surface

		if (isMobile){
			$("#prompt-small").text("Tap to move left or right");
			$("#info").html("Built with Love by Airtight.");
		}

		//INIT CONTROLS
		$("#container").on( 'touchstart', onTouchStart, false );
		$("#container").on( 'touchend', onTouchEnd, false );

		$(document).on('keydown', onKeyDown, false);
		$(document).on('keyup', onKeyUp, false);
		$("#splash").on('mousedown', onMouseDown, false);
		$("#splash").on('tap', onMouseDown, false);

		// if (window.DeviceOrientationEvent) {
		// 	window.addEventListener('deviceorientation', deviceOrientationHandler, false);
		// }

		//init audio
		if (XRConfig.playSound){
			sndPickup = new Howl( {urls: ["res/audio/point.mp3"]});
			sndCollide = new Howl({ urls: ["res/audio/hit.mp3"]});
			sndBest = new Howl( {urls: ["res/audio/best.mp3"]});
		}

		if (XRConfig.playMusic){
			sndMusic = new Howl( {urls: ["res/audio/rouet.mp3"],loop: true,});
			$("#music-toggle").on("click",toggleMusic);
			$("#music-toggle").on("tap",toggleMusic);
		}

		//init 3D

		var size = 800;
		camera = new THREE.PerspectiveCamera( 75, 8 / 6, 1, 10000 );
		camera.position.z = FLOOR_DEPTH/2 - 300;

		scene = new THREE.Scene();
		scene.fog = new THREE.Fog( bkgndColor, FLOOR_DEPTH/2, FLOOR_DEPTH );

		renderer = new THREE.WebGLRenderer();
		renderer.setSize( window.innerWidth, window.innerHeight );
		renderer.setClearColor( bkgndColor, 1 );
		$("#container").append( renderer.domElement );

		//FX
		var renderPass = new THREE.RenderPass( scene, camera );
		superPass = new THREE.ShaderPass(THREE.SuperShader);

		superPass.uniforms.vigDarkness.value = 2;
		superPass.uniforms.vigOffset.value =  fxParams.vignetteAmount;
		superPass.uniforms.saturation.value =  fxParams.saturation -1;

		composer = new THREE.EffectComposer( renderer );
		composer.addPass( renderPass );
		composer.addPass( superPass );
		superPass.renderToScreen = true;

		XRGame.init();

		resize();

		animate();

		//fade in
		TweenMax.fromTo(fxParams , 1, {brightness: -1},{brightness:0,delay:0.5});
		TweenMax.fromTo($('#splash') , 1, {autoAlpha: 0},{autoAlpha: 1,delay:1});
		TweenMax.fromTo($('#info') , 1, {autoAlpha: 0},{autoAlpha: 1,delay:1});
		TweenMax.fromTo($('#music-toggle') , 1, {autoAlpha: 0},{autoAlpha: 1,delay:1});

		$("#preloader").css("display","none");

		//preload splash page images
		var img1 = new Image();
		img1.src = "res/img/xmas-splash.png";
		var img2 = new Image();
		img2.src = "res/img/xmas-best.png";
		var img3 = new Image();
		img3.src = "res/img/xmas-wipeout.png";

	}

	function toggleMusic(){

		$(this).toggleClass("off");

		if($(this).hasClass("off")){
			sndMusic.mute();
		}else{
			sndMusic.unmute();
		}

	}

	$(window).resize(function() {
		resize();
	});

	function resize(){

		var w = window.innerWidth;
		var h = window.innerHeight;

		//handle retina screens
		// var dpr = 1;
		// if (window.devicePixelRatio !== undefined) {
		// 	dpr = window.devicePixelRatio;
		// }

		composer.setSize(w , h );
		renderer.setSize(w, h);
		camera.aspect = w / h;

		//scale to fit and center splash
		splashSize = Math.min(w,h)*0.85;
		splashSize = Math.min(splashSize,500);

		$("#splash").css("width", splashSize + "px");
		$("#splash").css("height", splashSize+ "px");

		$("#splash").css("left",(w - splashSize)/2 + "px");
		$("#splash").css("top",(h - splashSize)/2 + "px");

		//splash page resizing
		if (splashMode === 0){
			if (isMobile){
				$('#prompt-big').css("font-size" , splashSize * 0.05 + "px");
				$('#prompt-small').css("font-size" , splashSize * 0.06 + "px");
			}else{
				$('#prompt-big').css("font-size" , splashSize * 0.06 + "px");
				$('#prompt-small').css("font-size" , splashSize * 0.04 + "px");

			}
		}else if(splashMode == 1){
			$('#prompt-big').css("font-size" , splashSize * 0.09 + "px");
		}else{
			$('#prompt-big').css("font-size" , splashSize * 0.08 + "px");
			$('#prompt-small').css("font-size" , splashSize * 0.04 + "px");
		}

	}

	function playCollide(){
		if (XRConfig.playSound) sndCollide.play();
	}

	function onScorePoint(){
		if (XRConfig.playSound) sndPickup.play();
		score += 1;
		$("#score-text").text(score);
		TweenMax.fromTo($('#score-text') , 0.4, {scale: 2},{scale: 1,ease:Bounce.easeOut});

		if (score === hiScore + 1 && hiScore !== 0){
			if (XRConfig.playSound) sndBest.play();
		}
	}

	function onGameOver(){

		if (XRConfig.playSound) sndCollide.play();

		//display score
		TweenMax.to($('#score-text') , 0.1, {autoAlpha: 0});
		TweenMax.fromTo($('#splash') , 0.5, {scale: 0.6,autoAlpha: 0},{scale: 1,autoAlpha: 1,ease:Expo.easeOut});
		TweenMax.fromTo($('#info') , 0.5, {autoAlpha: 0},{autoAlpha: 1});
		TweenMax.fromTo($('#music-toggle') , 0.5, {autoAlpha: 0},{autoAlpha: 1});

		if (score > hiScore){
			splashMode = 1;
			hiScore = score;
			$('#splash').css('background-image', 'url(res/img/xmas-best.png)');
			$('#prompt-big').text("SCORE: " + score);
			$('#prompt-small').css('display','none');
			$('#prompt-big').css("margin-top" , "10%");

		}else{
			splashMode = 2;
			$('#splash').css('background-image', 'url(res/img/xmas-wipeout.png)');
			$('#prompt-big').text("SCORE: " + score);
			$('#prompt-small').text("BEST SCORE: " + hiScore);
			$('#prompt-small').css('display','block');
			$('#prompt-big').css("margin-top" , "8%");
			$('#prompt-small').css("margin-top" , "2%");
		 }

		resize();
		hueTime =0;

	}

	function onGameStart(){
		TweenMax.to($('#splash') , 0.3, {autoAlpha: 0});
		TweenMax.to($('#info') , 0.3, {autoAlpha: 0});
		TweenMax.to($('#music-toggle') , 0.3, {autoAlpha: 0});
		TweenMax.to($('#score-text') , 0.3, {autoAlpha: 1,delay:0.3});
		score = 0;
		$("#score-text").text(score);

		if (isFirstGame && XRConfig.playMusic ) sndMusic.play();

		XRGame.startGame(isFirstGame);
		isFirstGame = false;
	}

	function animate(){

		requestAnimationFrame( animate );
		XRGame.animate();
		if (XRConfig.showDebug){
			stats.update();
		}

		//faster = more hue amount and faster shifts
		var hueAmount;
		if (XRGame.getSpeed() < 0.5){
			hueAmount = 0;
		}else{
			hueAmount = (XRGame.getSpeed()- 0.5) * 2;
		}
		superPass.uniforms.hueAmount.value =  hueAmount;

		hueTime += XRGame.getSpeed() * XRGame.getSpeed() * 0.05;
		var hue = hueTime % 2 - 1; //put in range -1 to 1
		superPass.uniforms.hue.value =  hue;
		superPass.uniforms.brightness.value =  fxParams.brightness;
		composer.render( 0.1 );

		//XRMain.trace( XRGame.getSpeed());

	}

	//INPUT HANDLERS
	function onTouchStart( event ) {

		if (!XRGame.getPlaying() && XRGame.getAcceptInput()){
			onGameStart();
		}

		for(  var i = 0; i <  event.touches.length; i++) {

			event.preventDefault();

			var xpos = event.touches[ i ].pageX;

			if (xpos > window.innerWidth / 2){
				XRGame.setRightDown(true);
			}else{
				XRGame.setLeftDown(true);
			}
		}
	}

	function onTouchEnd( event ) {

		for(  var i = 0; i <  event.changedTouches.length; i++) {

			event.preventDefault();
			var xpos = event.changedTouches[ i ].pageX;

			if (xpos > window.innerWidth / 2){
				XRGame.setRightDown(false);
			}else{
				XRGame.setLeftDown( false);
			}
		}
	}

	function onKeyUp( event ) {

		lastEvent = null;

		switch ( event.keyCode ) {
			case 39: /* RIGHT */
				XRGame.setRightDown(false);
				break;
			case 37: /* LEFT */
				XRGame.setLeftDown(false);
				break;
		}

		//endSlide();
	}

	function onKeyDown(event) {

		if (lastEvent && lastEvent.keyCode == event.keyCode) {
			return;
		}

		lastEvent = event;

		if (!XRGame.getPlaying() && XRGame.getAcceptInput()){
			onGameStart();
		}

		switch ( event.keyCode ) {
			case 39: /* RIGHT */
				XRGame.setRightDown(true);
				break;
			case 37: /* LEFT */
				XRGame.setLeftDown( true);
				break;

		}
	}

	function onMouseDown(){

		if (!XRGame.getPlaying()){
			onGameStart();
		}
	}

	function trace(text){
		if (XRConfig.showDebug){
			$("#debug-text").text(text);
		}
	}

	// function deviceOrientationHandler(eventData) {
	// 	if (eventData.beta === null) return;
	// 	var cuttoff = 5;
	// 	var tiltedRight = eventData.beta > cuttoff;
	// 	var tiltedLeft = eventData.beta < -cuttoff;
	// 	XRGame.setRightDown(tiltedRight);
	// 	XRGame.setLeftDown(tiltedLeft);
	// }

	return {
		init:init,
		trace: trace,
		onGameOver:onGameOver,
		onScorePoint: onScorePoint,
		getScene:function (){return scene;},
		getCamera:function (){return camera;},
		playCollide:playCollide,
		fxParams:fxParams,
	};

}();

$(document).ready(function() {
	XRMain.init();
});
<|endoftext|>


<commit_before>
/**
 * Core company namespace.  Replace CompanyName with your actual company object
 * at the point you would like to add your scripts.  If you have one.
 * @namespace
 */
var CompanyName = {};

Yo.init({
  namespace: CompanyName,
  scriptRoot: 'myModules',
  debugMode: true
});<commit_msg>commented the debugmode and scripts out so people can see the examples<commit_after>
/**
 * Core company namespace.  Replace CompanyName with your actual company object
 * at the point you would like to add your scripts.  If you have one.
 * @namespace
 */
var CompanyName = {};

Yo.init({
  namespace: CompanyName
  ,scriptRoot: 'myModules'
  //,debugMode: true
  //,debugScripts: ['your', 'fine', 'scripts', 'here']
});<|endoftext|>


<commit_before>import React from 'react'

let Component = React.createClass({
    count: 0,
    runningTimerId: null,
    hidingTimerId: null,

    getInitialState() {
        return {
            state: 'hidden'
        }
    },

    getDefaultProps() {
        return {
            cls: ''
        }
    },

    render() {
        let cls = `loader-60devs ${this.props.cls}`

        return (

        )
    },

    show() {
        if(++ this.count > 1)
            return

        clearTimeout(this.hidingTimerId)

        var {element} = this.refs
        let progressEl = element.querySelector('.loader-60devs-progress')

        element.setAttribute('data-state', 'hidden')
        // the only working way to restart a transition on firefox
        progressEl.outerHTML = progressEl.outerHTML
        element.offsetHeight
        element.setAttribute('data-state', '')
        element.offsetHeight
        element.setAttribute('data-state', 'running')
    },

    hide() {
        if(-- this.count > 0)
            return

        this.refs.element.setAttribute('data-state', 'finishing')
        this.hidingTimerId = setTimeout(this.toHiddenState, 500)
    },

    hideAll() {
        this.count = 1
        this.hide()
    },

    toHiddenState() {
        this.refs.element.setAttribute('data-state', 'hidden')
    },

    componentWillMount() {
        Component.instance = this
    },

    componentWillUnmount() {
        delete Component.instance
    },

    isVisible() {
        return this.refs.element.getAttribute('data-state') != 'hidden'
    }
})

export default {
    Component: Component,
    show() {
        Component.instance.show()
    },
    hide() {
        Component.instance.hide()
    },
    hideAll() {
        Component.instance.hideAll()
    },
    isVisible() {
        return Component.instance.isVisible()
    }
}<commit_msg>Use callback ref instead of string ref<commit_after>import React from 'react'

let Component = React.createClass({
    count: 0,
    runningTimerId: null,
    hidingTimerId: null,

    getInitialState() {
        return {
            state: 'hidden'
        }
    },

    getDefaultProps() {
        return {
            cls: ''
        }
    },

    render() {
        let cls = `loader-60devs ${this.props.cls}`

        return (

 { this.element = element })>

        )
    },

    show() {
        if(++ this.count > 1)
            return

        clearTimeout(this.hidingTimerId)

        var {element} = this
        let progressEl = element.querySelector('.loader-60devs-progress')

        element.setAttribute('data-state', 'hidden')
        // the only working way to restart a transition on firefox
        progressEl.outerHTML = progressEl.outerHTML
        element.offsetHeight
        element.setAttribute('data-state', '')
        element.offsetHeight
        element.setAttribute('data-state', 'running')
    },

    hide() {
        if(-- this.count > 0)
            return

        this.element.setAttribute('data-state', 'finishing')
        this.hidingTimerId = setTimeout(this.toHiddenState, 500)
    },

    hideAll() {
        this.count = 1
        this.hide()
    },

    toHiddenState() {
        this.element.setAttribute('data-state', 'hidden')
    },

    componentWillMount() {
        Component.instance = this
    },

    componentWillUnmount() {
        delete Component.instance
    },

    isVisible() {
        return this.element.getAttribute('data-state') != 'hidden'
    }
})

export default {
    Component: Component,
    show() {
        Component.instance.show()
    },
    hide() {
        Component.instance.hide()
    },
    hideAll() {
        Component.instance.hideAll()
    },
    isVisible() {
        return Component.instance.isVisible()
    }
}
<|endoftext|>


<commit_before>(function (global, factory) {
  /* global module, define */

  "use strict";

  var i18n = factory();

  if(typeof(module) === "object" && typeof(module.exports) === "object") {
    module.exports = i18n;
  } else if(typeof(define) === "function") {
    define([], i18n);
  } else {
    global.i18n = i18n;
  }
}(this, function () {
  "use strict";

  var languageDialect = (function(lang) {
        window.location.search.slice(1).split("&").some(function (searchTerm) {
          if (searchTerm.indexOf("lang=") === 0) {
            lang = searchTerm.split("=").slice(1).join("=");
            return true;
          }
        });

        return lang.toLowerCase();
      })(window.navigator.userLanguage || window.navigator.language),
      language = languageDialect.split("-")[0],
      Translations = (function() {
        var scope = "_scope";

        function Translations(language, o) {
          this.language = language;
          this[scope] = o;
        }

        Translations.prototype.find = function(path) {
          return path.split(".").reduce(function (obj, key) {
            return obj ? obj[key] : undefined;
          }, this[scope]);
        };

        Translations.prototype.translate = function(ele) {
          if(getLang(ele) === this.language) {
            if(!ele.hasAttribute("data-i18n")) {
              [].slice.call(ele.querySelectorAll("[lang]:not([lang='" + this.language + "'])")).forEach(this.translate, this);
            }
          } else if(ele.hasAttribute("data-i18n")) {
            applyTranslationToElement(ele, this);
          } else {
            [].slice.call(ele.querySelectorAll("[data-i18n]")).map(function(match) {
              if(getLang(match, ele) !== this.language) {
                applyTranslationToElement(match, this);
              }
            }, this);
          }

          return ele;
        };

        return Translations;
      }()),
      Localisations = (function() {
        var scope = "_scope";

        function Localisations(language, o) {
          this.language = language;
          this[scope] = o;
        }

        Localisations.prototype.localise = function(node, type) {
          var isEle = node.nodeType === Node.ELEMENT_NODE,
            attr = node.tagName === "DATA" ? "value" : (isEle && node.hasAttribute("data-i18n-original")) ? "data-i18n-original" : undefined,
            val = attr ? node.getAttribute(attr) : isEle ? node.innerHTML : node.nodeValue;

          if(!attr && isEle) {
            node.setAttribute("data-i18n-original", val);
          }

          if(!type && isEle) {
            type = node.getAttribute("data-i18n-localise-as");
          }

          if(!type) {
            throw new Error("Localisations.prototype.localise: missing type");
          }

          switch(type) {
            case "number":
              val = this.localiseNumber(val);
              break;

            default:
              throw new Error("Localisations.prototype.localise: missing type");
          }

          if(isEle) {
            node.innerHTML = val;
          } else {
            node.nodeValue = val;
          }
        };

        Localisations.prototype.localiseNumber = function(number) {
          var separator = [this[scope].number.thousands, this[scope].number.thousandths];

          return parseFloat(number).toString().split(".").map(function(part, i) {
            var chrs = part.split(""),
              length = chrs.length,
              ret = [],
              i2;

            if(length < 4) {
              return part;
            }

            if(!i) {
              chrs.reverse();
            }

            for(i2 = 0; i2 < length; i2 += 3) {
              ret.push(chrs[i2], chrs[i2 + 1], chrs[i2 + 2]);
              if(i2 + 3 < length) {
                ret.push(separator[i]);
              }
            }

            if(!i) {
              ret.reverse();
            }

            return ret.join("");
          }).join(this[scope].number.decimal);
        };

        return Localisations;
      }()),
      debug = (function() {
        var debug = {
          enabled: false
        };

        ["info", "warn", "error"].forEach(function(name) {
          debug[name] = function() {
            if(this.enabled) {
              console[name].apply(console, arguments);
            }
          };
        });

        return debug;
      }()),
      i18n;

  function applyTranslationToElement(ele, obj) {
    if(ele.hasAttribute("data-i18n")) {
      applyTranslation(ele, ele.getAttribute("data-i18n"), obj);
    }
  }

  function applyTranslation(ele, path, obj) {
    var translated = obj.find(path);

    if (typeof(translated) === "object" && !Array.isArray(translated)) {
      debug.warn("Could not translate %o: path '%s' is of type object", ele, path);
    } else if(typeof(translated) !== "undefined") {
      clean(ele);
      ele.appendChild(toDom(translated));
      ele.lang = language;
    }
  }

  function getLang(ele, threshold) {
    do {
      if(ele.lang) {
        return ele.lang.toLowerCase();
      }
    } while((ele = ele.parentElement) && ele !== threshold);
  }

  function clean(ele) {
    var child;
    while((child = ele.firstChild)) {
      ele.removeChild(child);
    }
  }

  function toDom(content) {
    if(Array.isArray(content)) {
      return content.reduce(function(frag, text) {
        var ele = document.createElement("p");
        ele.textContent = text;
        frag.appendChild(ele);

        return frag;
      }, document.createDocumentFragment());
    }
    return document.createTextNode(content);
  }

  function getJson(url) {
    return fetch(url, {
      headers: {
        "Accept": "application/json"
      }
    }).then(function (res) {
      if (res.status >= 200 && res.status < 300) {
        return res.json();
      }

      // TODO add error object instead of false
      return Promise.reject(false);
    });
  }

  i18n = {
    translations: {
      base: (document.documentElement.getAttribute("data-i18n-base") || "locales/"),
      set: (document.documentElement.getAttribute("data-i18n-set") || "translation"),

      load: function(lang, set, base) {
        var url;
        base = base || this.base || "";
        lang = lang || language;
        set = set || this.set;
        url = base + lang + "/" + set + ".json";

        debug.info("loading translations for %s from: %s", lang, url);

        return getJson(url).then(function(obj) {
            debug.info("successfully loaded translations for %s", lang);
            return new Translations(lang || language, obj);
        }).catch(function (err) {
          debug.error("Error loading translations for %s: %o", lang, err);
          return Promise.reject(err);
        });
      },
      loadDefault: function() {
        return this.loaded || this.reloadDefault();
      },
      reloadDefault: function() {
        return (this.loaded = this.load());
      },

      apply: function(ele) {
        return this.loadDefault().then(function(translations) {
          return translations.translate(ele);
        });
      },
      applyAll: function() {
        this.appliedAll = true;
        return this.apply(document.documentElement);
      },

      get: function(path) {
        this.loadDefault();

        return this.loaded.then(function(obj) {
          return obj.find(path);
        });
      }
    },

    localisations: {
      base: (document.documentElement.getAttribute("data-i18n-localisations-base") || "localisations/"),
      load: function(lang, base) {
        var url;
        base = base || this.base || "";
        lang = lang || language;
        url = base + lang + ".json";

        debug.info("loading localisations for %s from: %s", lang, url);

        return getJson(url).then(function(obj) {
            debug.info("successfully loaded localisations for %s", lang);
            return new Localisations(lang || language, obj);
        }).catch(function (err) {
          debug.error("Error loading localisations for %s: %o", lang, err);
          return Promise.reject(err);
        });
      },
      loadDefault: function() {
        return this.loaded || this.reloadDefault();
      },
      reloadDefault: function() {
        return (this.loaded = this.load());
      },

      apply: function(ele) {
        return this.loadDefault().then(function(localisations) {
          return localisations.localise(ele);
        });
      },
      applyAll: function() {
        this.appliedAll = true;
        return this.apply(document.documentElement);
      }
    },

    set language(lang) {
      lang = String(lang);

      if(lang !== language) {
        language = lang;

        if(this.translations.loaded) {
          this.translations.reloadDefault();
        }
        if(this.translations.appliedAll) {
          this.translations.applyAll();
        }
      }
    },
    get language() {
      return language;
    },

    get debug() {
      return debug.enabled;
    },
    set debug(val) {
      debug.enabled = Boolean(val);
    }
  };

  if(!document.documentElement.hasAttribute("data-i18n-disable-auto")) {
    i18n.translations.applyAll();
  }

  return i18n;
}));
<commit_msg>Fix reloadDefault when not loaded yet<commit_after>(function (global, factory) {
  /* global module, define */

  "use strict";

  var i18n = factory();

  if(typeof(module) === "object" && typeof(module.exports) === "object") {
    module.exports = i18n;
  } else if(typeof(define) === "function") {
    define([], i18n);
  } else {
    global.i18n = i18n;
  }
}(this, function () {
  "use strict";

  var languageDialect = (function(lang) {
        window.location.search.slice(1).split("&").some(function (searchTerm) {
          if (searchTerm.indexOf("lang=") === 0) {
            lang = searchTerm.split("=").slice(1).join("=");
            return true;
          }
        });

        return lang.toLowerCase();
      })(window.navigator.userLanguage || window.navigator.language),
      language = languageDialect.split("-")[0],
      Translations = (function() {
        var scope = "_scope";

        function Translations(language, o) {
          this.language = language;
          this[scope] = o;
        }

        Translations.prototype.find = function(path) {
          return path.split(".").reduce(function (obj, key) {
            return obj ? obj[key] : undefined;
          }, this[scope]);
        };

        Translations.prototype.translate = function(ele) {
          if(getLang(ele) === this.language) {
            if(!ele.hasAttribute("data-i18n")) {
              [].slice.call(ele.querySelectorAll("[lang]:not([lang='" + this.language + "'])")).forEach(this.translate, this);
            }
          } else if(ele.hasAttribute("data-i18n")) {
            applyTranslationToElement(ele, this);
          } else {
            [].slice.call(ele.querySelectorAll("[data-i18n]")).map(function(match) {
              if(getLang(match, ele) !== this.language) {
                applyTranslationToElement(match, this);
              }
            }, this);
          }

          return ele;
        };

        return Translations;
      }()),
      Localisations = (function() {
        var scope = "_scope";

        function Localisations(language, o) {
          this.language = language;
          this[scope] = o;
        }

        Localisations.prototype.localise = function(node, type) {
          var isEle = node.nodeType === Node.ELEMENT_NODE,
            attr = node.tagName === "DATA" ? "value" : (isEle && node.hasAttribute("data-i18n-original")) ? "data-i18n-original" : undefined,
            val = attr ? node.getAttribute(attr) : isEle ? node.innerHTML : node.nodeValue;

          if(!attr && isEle) {
            node.setAttribute("data-i18n-original", val);
          }

          if(!type && isEle) {
            type = node.getAttribute("data-i18n-localise-as");
          }

          if(!type) {
            throw new Error("Localisations.prototype.localise: missing type");
          }

          switch(type) {
            case "number":
              val = this.localiseNumber(val);
              break;

            default:
              throw new Error("Localisations.prototype.localise: missing type");
          }

          if(isEle) {
            node.innerHTML = val;
          } else {
            node.nodeValue = val;
          }
        };

        Localisations.prototype.localiseNumber = function(number) {
          var separator = [this[scope].number.thousands, this[scope].number.thousandths];

          return parseFloat(number).toString().split(".").map(function(part, i) {
            var chrs = part.split(""),
              length = chrs.length,
              ret = [],
              i2;

            if(length < 4) {
              return part;
            }

            if(!i) {
              chrs.reverse();
            }

            for(i2 = 0; i2 < length; i2 += 3) {
              ret.push(chrs[i2], chrs[i2 + 1], chrs[i2 + 2]);
              if(i2 + 3 < length) {
                ret.push(separator[i]);
              }
            }

            if(!i) {
              ret.reverse();
            }

            return ret.join("");
          }).join(this[scope].number.decimal);
        };

        return Localisations;
      }()),
      debug = (function() {
        var debug = {
          enabled: false
        };

        ["info", "warn", "error"].forEach(function(name) {
          debug[name] = function() {
            if(this.enabled) {
              console[name].apply(console, arguments);
            }
          };
        });

        return debug;
      }()),
      i18n;

  function applyTranslationToElement(ele, obj) {
    if(ele.hasAttribute("data-i18n")) {
      applyTranslation(ele, ele.getAttribute("data-i18n"), obj);
    }
  }

  function applyTranslation(ele, path, obj) {
    var translated = obj.find(path);

    if (typeof(translated) === "object" && !Array.isArray(translated)) {
      debug.warn("Could not translate %o: path '%s' is of type object", ele, path);
    } else if(typeof(translated) !== "undefined") {
      clean(ele);
      ele.appendChild(toDom(translated));
      ele.lang = language;
    }
  }

  function getLang(ele, threshold) {
    do {
      if(ele.lang) {
        return ele.lang.toLowerCase();
      }
    } while((ele = ele.parentElement) && ele !== threshold);
  }

  function clean(ele) {
    var child;
    while((child = ele.firstChild)) {
      ele.removeChild(child);
    }
  }

  function toDom(content) {
    if(Array.isArray(content)) {
      return content.reduce(function(frag, text) {
        var ele = document.createElement("p");
        ele.textContent = text;
        frag.appendChild(ele);

        return frag;
      }, document.createDocumentFragment());
    }
    return document.createTextNode(content);
  }

  function getJson(url) {
    return fetch(url, {
      headers: {
        "Accept": "application/json"
      }
    }).then(function (res) {
      if (res.status >= 200 && res.status < 300) {
        return res.json();
      }

      // TODO add error object instead of false
      return Promise.reject(false);
    });
  }

  i18n = {
    translations: {
      base: (document.documentElement.getAttribute("data-i18n-base") || "locales/"),
      set: (document.documentElement.getAttribute("data-i18n-set") || "translation"),

      load: function(lang, set, base) {
        var url;
        base = base || this.base || "";
        lang = lang || language;
        set = set || this.set;
        url = base + lang + "/" + set + ".json";

        debug.info("loading translations for %s from: %s", lang, url);

        return getJson(url).then(function(obj) {
            debug.info("successfully loaded translations for %s", lang);
            return new Translations(lang || language, obj);
        }).catch(function (err) {
          debug.error("Error loading translations for %s: %o", lang, err);
          return Promise.reject(err);
        });
      },
      loadDefault: function() {
        return this.loaded || (this.loaded = this.load());
      },
      reloadDefault: function() {
        return this.loaded && (this.loaded = this.load());
      },

      apply: function(ele) {
        return this.loadDefault().then(function(translations) {
          return translations.translate(ele);
        });
      },
      applyAll: function() {
        this.appliedAll = true;
        return this.apply(document.documentElement);
      },

      get: function(path) {
        this.loadDefault();

        return this.loaded.then(function(obj) {
          return obj.find(path);
        });
      }
    },

    localisations: {
      base: (document.documentElement.getAttribute("data-i18n-localisations-base") || "localisations/"),
      load: function(lang, base) {
        var url;
        base = base || this.base || "";
        lang = lang || language;
        url = base + lang + ".json";

        debug.info("loading localisations for %s from: %s", lang, url);

        return getJson(url).then(function(obj) {
            debug.info("successfully loaded localisations for %s", lang);
            return new Localisations(lang || language, obj);
        }).catch(function (err) {
          debug.error("Error loading localisations for %s: %o", lang, err);
          return Promise.reject(err);
        });
      },
      loadDefault: function() {
        return this.loaded || (this.loaded = this.load());
      },
      reloadDefault: function() {
        return this.loaded && (this.loaded = this.load());
      },

      apply: function(ele) {
        return this.loadDefault().then(function(localisations) {
          return localisations.localise(ele);
        });
      },
      applyAll: function() {
        this.appliedAll = true;
        return this.apply(document.documentElement);
      }
    },

    set language(lang) {
      lang = String(lang);

      if(lang !== language) {
        language = lang;

        if(this.translations.loaded) {
          this.translations.reloadDefault();
        }
        if(this.translations.appliedAll) {
          this.translations.applyAll();
        }
      }
    },
    get language() {
      return language;
    },

    get debug() {
      return debug.enabled;
    },
    set debug(val) {
      debug.enabled = Boolean(val);
    }
  };

  if(!document.documentElement.hasAttribute("data-i18n-disable-auto")) {
    i18n.translations.applyAll();
  }

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


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

/* eslint-disable no-console */

import './promisify'

import path from 'path'
import { readFileSync } from 'fs'
import { Command } from 'commander'
import { parse as parseConnectionString } from 'pg-connection-string'
import createGraphqlSchema from './createGraphqlSchema.js'
import createServer from './createServer.js'

const manifest = readFileSync(path.resolve(__dirname, '../package.json'))

const main = async () => {
  const program = new Command('postgraphql')

  /* eslint-disable max-len */
  program
  .version(manifest.version)
  .usage('[options] <url>')
  .option('-s, --schema <identifier>', 'the PostgreSQL schema to serve a GraphQL server of. defaults to public')
  .option('-n, --hostname <name>', 'a URL hostname the server will listen to. defaults to localhost')
  .option('-p, --port <integer>', 'a URL port the server will listen to. defaults to 3000', parseInt)
  .option('-r, --route <path>', 'the route to mount the GraphQL server on. defaults to /')
  .option('-d, --development', 'enables a development mode which enables GraphiQL, nicer errors, and JSON pretty printing')
  .option('-m, --max-pool-size', 'the maximum number of connections to keep in the connection pool. defaults to 10')
  .parse(process.argv)
  /* eslint-enable max-len */

  const {
    args: [connection],
    schema: schemaName = 'public',
    hostname = 'localhost',
    port = 3000,
    route = '/',
    development = false,
    maxPoolSize = 10,
  } = program

  if (!connection)
    throw new Error('Must define a PostgreSQL connection string to connect to.')

  // Parse out the connection string into an object and attach a
  // `poolSize` option.
  const pgConfig = {
    ...parseConnectionString(connection),
    poolSize: maxPoolSize,
  }

  // Create the GraphQL schema.
  const graphqlSchema = await createGraphqlSchema(pgConfig, schemaName)

  // Create the GraphQL HTTP server.
  const server = await createServer({
    graphqlSchema,
    pgConfig,
    route,
    development,
  })

  server.listen(port, hostname, () => {
    console.log(`GraphQL server listening at http://${hostname}:${port}${route} 🚀`)
  })
}

main().catch(error => console.error(error.stack))
<commit_msg>fix(main): fix option documentation<commit_after>#!/usr/bin/env node

/* eslint-disable no-console */

import './promisify'

import path from 'path'
import { readFileSync } from 'fs'
import { Command } from 'commander'
import { parse as parseConnectionString } from 'pg-connection-string'
import createGraphqlSchema from './createGraphqlSchema.js'
import createServer from './createServer.js'

const manifest = readFileSync(path.resolve(__dirname, '../package.json'))

const main = async () => {
  const program = new Command('postgraphql')

  /* eslint-disable max-len */
  program
  .version(manifest.version)
  .usage('[options] <url>')
  .option('-s, --schema <identifier>', 'the PostgreSQL schema to serve a GraphQL server of. defaults to public')
  .option('-n, --hostname <name>', 'a URL hostname the server will listen to. defaults to localhost')
  .option('-p, --port <integer>', 'a URL port the server will listen to. defaults to 3000', parseInt)
  .option('-r, --route <path>', 'the route to mount the GraphQL server on. defaults to /')
  .option('-d, --development', 'enables a development mode which enables GraphiQL, nicer errors, and JSON pretty printing')
  .option('-m, --max-pool-size <integer>', 'the maximum number of connections to keep in the connection pool. defaults to 10')
  .parse(process.argv)
  /* eslint-enable max-len */

  const {
    args: [connection],
    schema: schemaName = 'public',
    hostname = 'localhost',
    port = 3000,
    route = '/',
    development = false,
    maxPoolSize = 10,
  } = program

  if (!connection)
    throw new Error('Must define a PostgreSQL connection string to connect to.')

  // Parse out the connection string into an object and attach a
  // `poolSize` option.
  const pgConfig = {
    ...parseConnectionString(connection),
    poolSize: maxPoolSize,
  }

  // Create the GraphQL schema.
  const graphqlSchema = await createGraphqlSchema(pgConfig, schemaName)

  // Create the GraphQL HTTP server.
  const server = await createServer({
    graphqlSchema,
    pgConfig,
    route,
    development,
  })

  server.listen(port, hostname, () => {
    console.log(`GraphQL server listening at http://${hostname}:${port}${route} 🚀`)
  })
}

main().catch(error => console.error(error.stack))
<|endoftext|>


<commit_before>// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
/* global require:true */
import Vue          from 'vue'
import Mint         from 'mint-ui'
import layzr        from 'layzr.js'
import VueScrollTo  from 'vue-scrollto'
import 'mint-ui/lib/style.min.css'
import 'sweetalert2/dist/sweetalert2.min.css'

import App          from './App'
import router       from './router'
import store        from './store'

require( './assets/iconFont/font-awesome.min.css' )

Vue.config.productionTip = false
Vue.config.devtools = true
Vue.config.debug = true

const lazyLoader = layzr({
    normal: 'data-normal',
    retina: 'data-retina',
    srcset: 'data-srcset',
    threshold: 35
})

Vue.use( Mint )
Vue.use( lazyLoader )
Vue.use( VueScrollTo )
Vue.use( require( 'vue-wechat-title' ) )

/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    store,
    template: '<App/>',
    components: { App }
})

// 不同平台下的文字效果不同
if ( /(iPhone|iPad|iPod|iOS )/i.test( navigator.userAgent ) ) {
    document.body.style.fontFamily = 'PingFang SC Regular'
} else if ( /(Android)/i.test( navigator.userAgent ) ) {
    document.body.style.fontFamily = 'NoteSansCJKsc-Regular'
} else {
    document.body.style.fontFamily = 'Microsoft Yahei'
}
<commit_msg>判断是否微信登陆<commit_after>// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
/* global require:true */
import Vue          from 'vue'
import Mint         from 'mint-ui'
import layzr        from 'layzr.js'
import VueScrollTo  from 'vue-scrollto'
import 'mint-ui/lib/style.min.css'
import 'sweetalert2/dist/sweetalert2.min.css'

import App          from './App'
import router       from './router'
import store        from './store'
require( './assets/iconFont/font-awesome.min.css' )

Vue.config.productionTip = false
Vue.config.devtools = true
Vue.config.debug = true

const lazyLoader = layzr({
    normal: 'data-normal',
    retina: 'data-retina',
    srcset: 'data-srcset',
    threshold: 35
})

Vue.use( Mint )
Vue.use( lazyLoader )
Vue.use( VueScrollTo )
Vue.use( require( 'vue-wechat-title' ) )

/* eslint-disable no-new */
new Vue({
    el: '#app',
    router,
    store,
    template: '<App/>',
    components: { App }
})

// 不同平台下的文字效果不同
if ( /(iPhone|iPad|iPod|iOS )/i.test( navigator.userAgent ) ) {
    document.body.style.fontFamily = 'PingFang SC Regular'
} else if ( /(Android)/i.test( navigator.userAgent ) ) {
    document.body.style.fontFamily = 'NoteSansCJKsc-Regular'
} else {
    document.body.style.fontFamily = 'Microsoft Yahei'
}
// 判斷是否微信登陸
function isWeiXin() {
    let ua = window.navigator.userAgent.toLowerCase()
    console.log( ua )
    if ( ua.match( /MicroMessenger/i ) === 'micromessenger' ) {
        return true
    } else {
        return false
    }
}
if( isWeiXin() ) {
    console.log( '是来自微信内置浏览器' )
}else{
    location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx98c3af70778cd6ce&redirect_uri=https%3A%2F%2Fwx.myysq.com.cn%2Fauth%2Fopenid%3Ftenant_code%3Dpoly%26public_id%3D39d4e5fb-64ac-4d5c-3215-5b9941a7ac49%26return_url%3Dhttp%253A%252F%252Fvmember.myysq.com.cn%252Fpoly%252Fmember%252Fmembership%252Fmember-info%253Fpublic_id%253D39d4e5fb-64ac-4d5c-3215-5b9941a7ac49%26_state%3DFF5XJXwvSffQfL5i&response_type=code&scope=snsapi_base&state=Irc6pPM6BkTvIH0H&component_appid=wx05b2480ca122fbd0&connect_redirect=1#wechat_redirect'
}
<|endoftext|>


<commit_before>var app = require('app');
var Menu = require('menu');
var Tray = require('tray');

var submenu_template = [
  {label: '59.66.1.1', enabled: false},
  {label: '5分钟前上线', enabled: false},
  {label: '≥ 14.32M', enabled: false},
  {label: '下线'}
];

var template = [
  {label: '未知', enabled: false},
  {type: 'separator'},
  {label: 'lisihan13', enabled: false},
  {label: '本月流量', enabled: false},
  {label: '当前余额', enabled: false},
  {type: 'separator'},
  {label: '当前在线', enabled: false},
  {label: 'IOS', submenu: submenu_template},
  {label: '上次更新', enabled: false},
  {type: 'separator'},
  {label: '上线'},
  {label: '下线'},
  {label: '现在刷新'},
  {type: 'separator'},
  {label: '自动管理', type: 'checkbox'},
  {label: '账号设置...'},
  {type: 'separator'},
  {label: '关于'},
  {type: 'separator'},
  {label: '退出'}
];

var appIcon = null;
app.on('ready', function(){
  appIcon = new Tray('icon.png');

  // var submenu = Menu.buildFromTemplate(submenu_template);
  var contextMenu = Menu.buildFromTemplate(template);
  appIcon.setToolTip('This is my application.');
  appIcon.setContextMenu(contextMenu);
});
<commit_msg>Implement quit<commit_after>var app = require('app');
var Menu = require('menu');
var Tray = require('tray');

var submenu_template = [
  {label: '59.66.1.1', enabled: false},
  {label: '5分钟前上线', enabled: false},
  {label: '≥ 14.32M', enabled: false},
  {label: '下线'}
];

var template = [
  {label: '未知', enabled: false},
  {type: 'separator'},
  {label: 'lisihan13', enabled: false},
  {label: '本月流量', enabled: false},
  {label: '当前余额', enabled: false},
  {type: 'separator'},
  {label: '当前在线', enabled: false},
  {label: 'IOS', submenu: submenu_template},
  {label: '上次更新', enabled: false},
  {type: 'separator'},
  {label: '上线'},
  {label: '下线'},
  {label: '现在刷新'},
  {type: 'separator'},
  {label: '自动管理', type: 'checkbox'},
  {label: '账号设置...'},
  {type: 'separator'},
  {label: '关于'},
  {type: 'separator'},
  {label: '退出', click: function() {app.quit();}}
];

var appIcon = null;
app.on('ready', function(){
  appIcon = new Tray('icon.png');

  // var submenu = Menu.buildFromTemplate(submenu_template);
  var contextMenu = Menu.buildFromTemplate(template);
  appIcon.setToolTip('This is my application.');
  appIcon.setContextMenu(contextMenu);
});
<|endoftext|>


<commit_before>/**
*	SpinalJS Main File
*	@author Patricio Ferreira <3dimentionar@gmail.com>
**/
requirejs.config({

	baseURL: '/',

	paths: {
		'libs': 'libs',
		'core': 'com/spinal/core',
		'ioc': 'com/spinal/ioc',
		'ui': 'com/spinal/ui',
		'util': 'com/spinal/util'
	},

	shim: {
		'libs/bootstrap': ['libs/jquery'],
		'libs/underscore': ['libs/bootstrap'],
		'libs/backbone': ['libs/underscore', 'libs/text']
	}

});
<commit_msg>Forgot to commit src/main.js<commit_after>/**
*	SpinalJS Main File
*	@author Patricio Ferreira <3dimentionar@gmail.com>
**/
requirejs.config({

	baseURL: '/',

	paths: {
		'libs': 'libs',
		'text': 'libs/text',
		'core': 'com/spinal/core',
		'ioc': 'com/spinal/ioc',
		'ui': 'com/spinal/ui',
		'util': 'com/spinal/util'
	},

	shim: {
		'libs/bootstrap': ['libs/jquery'],
		'libs/underscore': ['libs/bootstrap'],
		'libs/backbone': ['libs/underscore']
	}

});
<|endoftext|>