<commit_before>/*! domvm-MobX v1.0.1 - MIT License - https://github.com/domvm/domvm-mobx */
(function(domvm, mobx, undefined) {
"use strict";

// UTILS:

function noop() {}

// We want the same checks as domvm:
function isPlainObj(val) {	// See: https://github.com/domvm/domvm/blob/3.4.8/src/utils.js#L13
	return val != undefined && val.constructor === Object;		// && typeof val === "object"
}
function isFunc(val) {	// See: https://github.com/domvm/domvm/blob/3.4.8/src/utils.js#L26
	return typeof val === "function";
}

// DESIGN:
//
// We create a new MobX Reaction for each observer domvm vm (ViewModel).
// The Reaction is used to track the observables used by the render() method. It becomes stale
// when one of the tracked observables changes. Upon becoming stale, the default becameStale() hook
// schedules an async redraw of the vm (the user can setup its own becameStale() hook to change
// the default behavior).
// Lazy rendering: re-rendering is executed only when the observer is stale, which is checked by
// its diff.eq() function. (Rendering can be forced by the user diff() function if setup.)
// Reaction lifecycle: the Reaction is created at the beginning of the first render (ie. just before
// mounting), and destroyed during willUnmount(), which allows it to be reclaimed by the GC. But
// because the vm can be reused, we recreate the Reaction during the render() if we detect that
// the vm is reused.
// Conclusion: we need to replace four methods/hooks on every observer vm: diff.eq(), init(), render()
// and willUnmount(). And we also need to add one hook: becameStale().
// Notes:
// - There is no way to know that a vm is being reused before the execution of its diff()
//	 method (the willMount() hook is fired after the diff() and the render() methods).
// - The Reaction must be destroyed explicitly to prevent wasting computations and resources.
//
// Links:
// - domvm ViewModel: https://github.com/domvm/domvm/blob/master/src/view/ViewModel.js
// - MobX Reaction: https://github.com/mobxjs/mobx/blob/5.6.0/src/core/reaction.ts
// - Inspirations:
//	 - MobX bindings for Inferno: https://github.com/infernojs/inferno/blob/master/packages/inferno-mobx/src/observer.ts
//	 - mobx-observer (universal bindings): https://github.com/capaj/mobx-observer/blob/master/observer.js
//	 - MobX bindings for Preact: https://github.com/mobxjs/mobx-preact

// Turns a vm into an observer (ie. into a reactive view vm):
function initvm(vm, reactionName) {
	// Uncomment if you need to find all unkeyed vm:
	//if (vm.key === undefined) console.warn("Unkeyed reactive view:", reactionName, vm);

	var hooks = vm.hooks || (vm.hooks = {});

	vm._mobxObserver = {
		// The reaction name, for debugging:
		name: reactionName,
		// The Reaction instance:
		reaction: undefined,
		// If the current view is stale and need (re-)rendering:
		stale: true,
		// The original diff.eq() if any:
		eq: vm.diff && vm.diff.eq,	// Since domvm 3.4.7
		// The original render():
		render: vm.render,
		// The original hook willUnmount():
		willUnmount: hooks.willUnmount,
	};

	// The user can prevent the default becameStale() if he did setup its own function,
	// or if he did set it to false (note: this also checks for null because domvm often
	// uses null for undefined):
	if (hooks.becameStale == undefined)
		hooks.becameStale = becameStale;

	var valFn = vm.diff ? vm.diff.val : noop;
	vm.config({diff: {val: valFn, eq: eq}});	// "vm.config()" has an alias "vm.cfg()" since domvm v3.4.7
	vm.render = render;
	hooks.willUnmount = willUnmount;
}

// Creates the observer Reaction:
function setReaction(vm) {
	var observerData = vm._mobxObserver;

	// Useful during development:
	if (observerData.reaction)
		throw Error("Reaction already set.");

	observerData.stale = true;
	observerData.reaction = new mobx.Reaction(observerData.name, function() {
		observerData.stale = true;
		if (vm.hooks.becameStale)
			vm.hooks.becameStale(vm, vm.data);
	});

	// The reaction should be started right after creation. (See: https://github.com/mobxjs/mobx/blob/5.6.0/src/core/reaction.ts#L35)
	// But it doesn't seem to be mandatory... ?
	// Not doing it, as that would trigger becameStale() and a vm.redraw() right now !
	// In case we need it, see convoluted implementation of fireImmediately in MobX autorun(): https://github.com/mobxjs/mobx/blob/5.6.0/src/api/autorun.ts#L146
	//observerData.reaction.schedule();
}

// Destroys the observer Reaction:
function unsetReaction(vm) {
	var observerData = vm._mobxObserver;

	// Useful during development:
	if (!observerData.reaction)
		throw Error("Reaction already unset.");

	observerData.reaction.dispose();
	observerData.reaction = undefined;
}

// The default becameStale() assigned to each observer vm's hooks
function becameStale(vm) {
	vm.redraw();
}

// The diff.eq() assigned to each observer vm:
function eq(vm) {
	var observerData = vm._mobxObserver;

	if (observerData.stale)
		return false;	// Re-render.
	else if(observerData.eq)
		return observerData.eq.apply(this, arguments); // Let diff() choose.
	else
		return true;	// By default: no re-render.
}

// The render() wrapper assigned to each observer vm:
function render(vm) {
	var observerData = vm._mobxObserver,
		that = this,
		args = arguments,
		result;

	// If vm was unmounted and is now being reused:
	if (!observerData.reaction)
		setReaction(vm);

	// Note: the following is allowed to run by MobX even if the reaction is not stale:
	observerData.reaction.track(function() {
		mobx._allowStateChanges(false, function() {
			result = observerData.render.apply(that, args);
		});
	});
	observerData.stale = false;

	return result;
}

// The willUnmount() wrapper assigned to each observer vm's hooks:
function willUnmount(vm) {
	unsetReaction(vm);

	var _willUnmount = vm._mobxObserver.willUnmount;
	if (_willUnmount)
		_willUnmount.apply(this, arguments);
}

// Replaces the init() with our own init():
function wrapInit(target, reactionName) {
	target.init = (function(init) {
		return function(vm) {
			if (init)
				init.apply(this, arguments);
			initvm(vm, reactionName);
		};
	})(target.init);
}

// Replaces the init() with our own init(), but also checks that init() was not already replaced.
function wrapInitOnce(target, reactionName) {
	if (!target.init || !target.init._mobxObserver) {
		wrapInit(target, reactionName);
		target.init._mobxObserver = true;
	}
}

// Turns a view into a domvm-MobX observer view:
function observer(name, view) {
	// If no name provided for the observer:
	if (view === undefined) {
		view = name;

		// Generate friendly name for debugging (See: https://github.com/infernojs/inferno/blob/master/packages/inferno-mobx/src/observer.ts#L105)
		name = view.displayName || view.name || (view.constructor && (view.constructor.displayName || view.constructor.name)) || '<View>';
	}

	// The name for the MobX Reaction, for debugging:
	var reactionName = name + ".render()";

	// We need to hook into the init() of the vm, just after that init() is executed,
	// so that all the vm.config(...) have been executed on the vm.
	// This is a bit complex depending on the type of the view.
	// Refer to the ViewModel constructor for details:
	//	 https://github.com/domvm/domvm/blob/3.4.8/src/view/ViewModel.js#L48

	if (isPlainObj(view)) {
		// view is an object: just set our own init on it.
		wrapInit(view, reactionName);
	}
	else {
		// view is a function: we can't do anything before it is executed, so we wrap it
		// with a function that will set our own init later.
		view = (function(view) {
			return function(vm) {
				var out = view.apply(this, arguments);

				if (isFunc(out))
					wrapInit(vm, reactionName);
				else {
					// In case multiple executions of view() returns the same object,
					// we want to wrap init only once:
					wrapInitOnce(out, reactionName);
				}

				return out;
			};
		})(view);
	}

	return view;
}

// Hook into domvm's redrawing to ensure all staled observers are correctly redrawn.
// Fixes issue #2: Redraw bug with domvm's drainQueue() (https://github.com/domvm/domvm-mobx/issues/2)
// In domvm, preventing a parent from re-rendering also prevents all its children.
// But with domvm-MobX we need discrete re-rendering, so we need to ensure that the children
// are actually re-rendered, even when their parents aren't.
// This hook requires domvm v3.4.8
domvm.config({
	didRedraws: function forceRedrawOfStaledObservers(redrawQueue) {
		// We want to redraw the children after the parents, so we sort them by depth:
		var byDepth = [];

		// Sorting:
		redrawQueue.forEach(function(vm) {
			// Only keep staled domvm-mobx observers (and check they were not unmounted)
			if (vm._mobxObserver && vm._mobxObserver.stale && vm.node != undefined) {
				var depth = 0,
					parVm = vm;
				while (parVm = parVm.parent())
					depth++;

				if (!byDepth[depth])
					byDepth[depth] = [];
				byDepth[depth].push(vm);
			}
		});

		// Re-rendering in order:
		for (var d = 0; d < byDepth.length; d++) {
			if (byDepth[d]) {
				byDepth[d].forEach(function(vm) {
					// May have been redrawn or unmounted by a parent in the meanwhile:
					if (vm._mobxObserver.stale && vm.node != undefined)
						vm.redraw(true);
				});
			}
		}
	}
});

// EXPORTS:

domvm.mobxObserver = observer;

})(window.domvm, window.mobx);<commit_msg>[domvm-mobx] whitespace trimming<commit_after>/*! domvm-MobX v1.0.1 - MIT License - https://github.com/domvm/domvm-mobx */
(function(domvm, mobx, undefined) {
"use strict";

// UTILS:

function noop() {}

// We want the same checks as domvm:
function isPlainObj(val) {	// See: https://github.com/domvm/domvm/blob/3.4.8/src/utils.js#L13
	return val != undefined && val.constructor === Object;		// && typeof val === "object"
}
function isFunc(val) {	// See: https://github.com/domvm/domvm/blob/3.4.8/src/utils.js#L26
	return typeof val === "function";
}

// DESIGN:
//
// We create a new MobX Reaction for each observer domvm vm (ViewModel).
// The Reaction is used to track the observables used by the render() method. It becomes stale
// when one of the tracked observables changes. Upon becoming stale, the default becameStale() hook
// schedules an async redraw of the vm (the user can setup its own becameStale() hook to change
// the default behavior).
// Lazy rendering: re-rendering is executed only when the observer is stale, which is checked by
// its diff.eq() function. (Rendering can be forced by the user diff() function if setup.)
// Reaction lifecycle: the Reaction is created at the beginning of the first render (ie. just before
// mounting), and destroyed during willUnmount(), which allows it to be reclaimed by the GC. But
// because the vm can be reused, we recreate the Reaction during the render() if we detect that
// the vm is reused.
// Conclusion: we need to replace four methods/hooks on every observer vm: diff.eq(), init(), render()
// and willUnmount(). And we also need to add one hook: becameStale().
// Notes:
// - There is no way to know that a vm is being reused before the execution of its diff()
//	 method (the willMount() hook is fired after the diff() and the render() methods).
// - The Reaction must be destroyed explicitly to prevent wasting computations and resources.
//
// Links:
// - domvm ViewModel: https://github.com/domvm/domvm/blob/master/src/view/ViewModel.js
// - MobX Reaction: https://github.com/mobxjs/mobx/blob/5.6.0/src/core/reaction.ts
// - Inspirations:
//	 - MobX bindings for Inferno: https://github.com/infernojs/inferno/blob/master/packages/inferno-mobx/src/observer.ts
//	 - mobx-observer (universal bindings): https://github.com/capaj/mobx-observer/blob/master/observer.js
//	 - MobX bindings for Preact: https://github.com/mobxjs/mobx-preact

// Turns a vm into an observer (ie. into a reactive view vm):
function initvm(vm, reactionName) {
	// Uncomment if you need to find all unkeyed vm:
	//if (vm.key === undefined) console.warn("Unkeyed reactive view:", reactionName, vm);

	var hooks = vm.hooks || (vm.hooks = {});

	vm._mobxObserver = {
		// The reaction name, for debugging:
		name: reactionName,
		// The Reaction instance:
		reaction: undefined,
		// If the current view is stale and need (re-)rendering:
		stale: true,
		// The original diff.eq() if any:
		eq: vm.diff && vm.diff.eq,	// Since domvm 3.4.7
		// The original render():
		render: vm.render,
		// The original hook willUnmount():
		willUnmount: hooks.willUnmount,
	};

	// The user can prevent the default becameStale() if he did setup its own function,
	// or if he did set it to false (note: this also checks for null because domvm often
	// uses null for undefined):
	if (hooks.becameStale == undefined)
		hooks.becameStale = becameStale;

	var valFn = vm.diff ? vm.diff.val : noop;
	vm.config({diff: {val: valFn, eq: eq}});	// "vm.config()" has an alias "vm.cfg()" since domvm v3.4.7
	vm.render = render;
	hooks.willUnmount = willUnmount;
}

// Creates the observer Reaction:
function setReaction(vm) {
	var observerData = vm._mobxObserver;

	// Useful during development:
	if (observerData.reaction)
		throw Error("Reaction already set.");

	observerData.stale = true;
	observerData.reaction = new mobx.Reaction(observerData.name, function() {
		observerData.stale = true;
		if (vm.hooks.becameStale)
			vm.hooks.becameStale(vm, vm.data);
	});

	// The reaction should be started right after creation. (See: https://github.com/mobxjs/mobx/blob/5.6.0/src/core/reaction.ts#L35)
	// But it doesn't seem to be mandatory... ?
	// Not doing it, as that would trigger becameStale() and a vm.redraw() right now !
	// In case we need it, see convoluted implementation of fireImmediately in MobX autorun(): https://github.com/mobxjs/mobx/blob/5.6.0/src/api/autorun.ts#L146
	//observerData.reaction.schedule();
}

// Destroys the observer Reaction:
function unsetReaction(vm) {
	var observerData = vm._mobxObserver;

	// Useful during development:
	if (!observerData.reaction)
		throw Error("Reaction already unset.");

	observerData.reaction.dispose();
	observerData.reaction = undefined;
}

// The default becameStale() assigned to each observer vm's hooks
function becameStale(vm) {
	vm.redraw();
}

// The diff.eq() assigned to each observer vm:
function eq(vm) {
	var observerData = vm._mobxObserver;

	if (observerData.stale)
		return false;	// Re-render.
	else if (observerData.eq)
		return observerData.eq.apply(this, arguments); // Let diff() choose.
	else
		return true;	// By default: no re-render.
}

// The render() wrapper assigned to each observer vm:
function render(vm) {
	var observerData = vm._mobxObserver,
		that = this,
		args = arguments,
		result;

	// If vm was unmounted and is now being reused:
	if (!observerData.reaction)
		setReaction(vm);

	// Note: the following is allowed to run by MobX even if the reaction is not stale:
	observerData.reaction.track(function() {
		mobx._allowStateChanges(false, function() {
			result = observerData.render.apply(that, args);
		});
	});
	observerData.stale = false;

	return result;
}

// The willUnmount() wrapper assigned to each observer vm's hooks:
function willUnmount(vm) {
	unsetReaction(vm);

	var _willUnmount = vm._mobxObserver.willUnmount;
	if (_willUnmount)
		_willUnmount.apply(this, arguments);
}

// Replaces the init() with our own init():
function wrapInit(target, reactionName) {
	target.init = (function(init) {
		return function(vm) {
			if (init)
				init.apply(this, arguments);
			initvm(vm, reactionName);
		};
	})(target.init);
}

// Replaces the init() with our own init(), but also checks that init() was not already replaced.
function wrapInitOnce(target, reactionName) {
	if (!target.init || !target.init._mobxObserver) {
		wrapInit(target, reactionName);
		target.init._mobxObserver = true;
	}
}

// Turns a view into a domvm-MobX observer view:
function observer(name, view) {
	// If no name provided for the observer:
	if (view === undefined) {
		view = name;

		// Generate friendly name for debugging (See: https://github.com/infernojs/inferno/blob/master/packages/inferno-mobx/src/observer.ts#L105)
		name = view.displayName || view.name || (view.constructor && (view.constructor.displayName || view.constructor.name)) || '<View>';
	}

	// The name for the MobX Reaction, for debugging:
	var reactionName = name + ".render()";

	// We need to hook into the init() of the vm, just after that init() is executed,
	// so that all the vm.config(...) have been executed on the vm.
	// This is a bit complex depending on the type of the view.
	// Refer to the ViewModel constructor for details:
	//	 https://github.com/domvm/domvm/blob/3.4.8/src/view/ViewModel.js#L48

	if (isPlainObj(view)) {
		// view is an object: just set our own init on it.
		wrapInit(view, reactionName);
	}
	else {
		// view is a function: we can't do anything before it is executed, so we wrap it
		// with a function that will set our own init later.
		view = (function(view) {
			return function(vm) {
				var out = view.apply(this, arguments);

				if (isFunc(out))
					wrapInit(vm, reactionName);
				else {
					// In case multiple executions of view() returns the same object,
					// we want to wrap init only once:
					wrapInitOnce(out, reactionName);
				}

				return out;
			};
		})(view);
	}

	return view;
}

// Hook into domvm's redrawing to ensure all staled observers are correctly redrawn.
// Fixes issue #2: Redraw bug with domvm's drainQueue() (https://github.com/domvm/domvm-mobx/issues/2)
// In domvm, preventing a parent from re-rendering also prevents all its children.
// But with domvm-MobX we need discrete re-rendering, so we need to ensure that the children
// are actually re-rendered, even when their parents aren't.
// This hook requires domvm v3.4.8
domvm.config({
	didRedraws: function forceRedrawOfStaledObservers(redrawQueue) {
		// We want to redraw the children after the parents, so we sort them by depth:
		var byDepth = [];

		// Sorting:
		redrawQueue.forEach(function(vm) {
			// Only keep staled domvm-mobx observers (and check they were not unmounted)
			if (vm._mobxObserver && vm._mobxObserver.stale && vm.node != undefined) {
				var depth = 0,
					parVm = vm;
				while (parVm = parVm.parent())
					depth++;

				if (!byDepth[depth])
					byDepth[depth] = [];
				byDepth[depth].push(vm);
			}
		});

		// Re-rendering in order:
		for (var d = 0; d < byDepth.length; d++) {
			if (byDepth[d]) {
				byDepth[d].forEach(function(vm) {
					// May have been redrawn or unmounted by a parent in the meanwhile:
					if (vm._mobxObserver.stale && vm.node != undefined)
						vm.redraw(true);
				});
			}
		}
	}
});

// EXPORTS:

domvm.mobxObserver = observer;

})(window.domvm, window.mobx);<|endoftext|>


<commit_before>/*
** Module: aireas2sql
**
**
**
**
*/

// **********************************************************************************
"use strict"; // This is for your code to comply with the ECMAScript 5 standard.

var fs = require('fs');
var pg = require('pg');

var aireasFolder, aireasUrl, aireasFileName, aireasLocalPathRoot, fileFolder,
	tmpFolder, tmpFolderName, localPath, fileFolderName,
	resultsFolder, resultsFolderName, sqlFolder, sqlFolderName;
var nrOfMeasures, maxMeasures, nextFolders, sqlConnString;

// **********************************************************************************

module.exports = {

	init: function (options) {

		sqlConnString = options.configParameter.databaseType + '://' +
			options.configParameter.databaseAccount + ':' +
			options.configParameter.databasePassword + '@' +
			options.configParameter.databaseServer + '/' +
			options.systemCode + '_' + options.configParameter.databaseName;

		aireasLocalPathRoot = options.systemFolderParent+'/aireas/';
		fileFolderName 		= 'aireas';
		tmpFolderName 		= 'tmp';
		resultsFolderName 	= 'results';
		sqlFolderName		= 'sql';

		aireasFolder 		= aireasLocalPathRoot 	+ fileFolderName 	+ "/";
		tmpFolder 			= aireasFolder 			+ tmpFolderName 	+ "/";
		resultsFolder 		= aireasFolder 			+ resultsFolderName + "/";
		sqlFolder 			= aireasFolder 			+ sqlFolderName  	+ "/";

		// create subfolders
		try {fs.mkdirSync(sqlFolder );} catch (e) {};//console.log('ERROR: no sql folder found, batch run aborted.'); return } ;

		var inputLocalIndex = -1;
		var inputLocalFiles = [];
		var rootFolderType = 'year';
		var outputPrefix="";
		nextFolders = {'year':'month','month':'day','day':'hour','hour':'minute','minute':'leafs','leafs':'files'} ;

		maxMeasures = 10;  // stop processing when maxMeasures are processed; restart process for continueing.
		nrOfMeasures = 0;

		this.exploreResultFolders(rootFolderType, resultsFolder, outputPrefix);

	},

	exploreResultFolders: function ( folderType ,path, outputPrefix) {
		var _resultsFolder;
		var nextFolderType;
		var tmpOutputPrefix;
		var i;
		var files;
		var folderContent;
		var fileName;
		var nodeName;
		var aireasFile;
		var createSqlAireas = this.createSqlAireas;

		if (nrOfMeasures>=maxMeasures) {
			console.log('WARNING:','Max number of processed measures reached, restart job to continue.')
			return;
		}

		folderContent = fs.readdirSync(path);
		folderContent.sort();

		if (folderContent) {

			if (folderType == 'leafs') {

				var filesProcessed = true;
				var folderHierarchy = path.split('\/');

				//check if allready processed
                                fileName = 'aireas';
				var file = sqlFolder+outputPrefix+"_"+fileName+ '.sql';
				fs.exists( file, function(exists) {
					if ( exists == false ) {
                                		//files
                                		aireasFile = fs.readFileSync(path+fileName + '.json');
                               			if (aireasFile) {
                                        		console.log(path, fileName + '.json');
                                		} else {
                                        		console.log('ERROR: not found:', path, fileName + '.json');
                                		}
                                		createSqlAireas (aireasFile, sqlFolder+outputPrefix+"_"+ fileName + '.sql');
                                		aireasFile =  null;

                                		nrOfMeasures++;
					}
				});

				return;

			} else {
				nextFolderType = nextFolders[folderType];
				for (i=0;i<folderContent.length;i++) {
					nodeName = folderContent[i];
					tmpOutputPrefix = setPrefix( outputPrefix, folderType, nodeName);
					if (nodeName != '.DS_Store') {  // ignore mac-file
						this.exploreResultFolders(nextFolderType, path + nodeName + '/', tmpOutputPrefix);
					}
				}
			}
		};

		function submitJson() {

		};

		function setPrefix(prefix, folderType, nodeName) {
			var _prefix = "";
			switch (folderType) {
				case "year":{
					_prefix = prefix + nodeName;
				}
				case "month": case "day": case "hour": case "minute": {
					if (nodeName.length<2) {
						_prefix = prefix + "0" + nodeName;
					} else {
						_prefix = prefix + nodeName;
					}
				}
				default: {
				}
			}
			return _prefix;
		};

	},

	createSqlAireas: function(inputFileJson , outputFilePath) {
		var i;

 		var inputFile = JSON.parse(inputFileJson);
		var outputFile = "";

	        var executeSql = function  (query, callback) {
        	        console.log('sql start: ');
                	var client = new pg.Client(sqlConnString);
                	client.connect(function(err) {
                        	if(err) {
                                	return console.error('could not connect to postgres', err);
                        	}
                        	client.query(query, function(err, result) {
                                	if(err) {
                                	return console.error('error running query', err);
                        	}
                        	console.log('sql result: ' + result);
                        	client.end();
                        	});
                	});
        	};

		var sqlCallBack = function (err, result) {
			if (err) {
				console.log('ERROR:','sql error:', err, result);
			} else {
				//console.log('Query','sql result:', result);
			}
		};

        	var writeFile = function(fileContent, filepath ) {
                	var _path = filepath;
                	fs.writeFileSync(_path, fileContent);
        	};

		for (i=0;i<inputFile.length;i++) {

			var inputRecord = inputFile[i];
			var outputRecord = "";

			var _measureDate		 			= inputRecord.measureDate==""?"null":"'"+inputRecord.measureDate + "', ";

			outputRecord = "\nINSERT INTO aireas ( airbox, retrieveddatechar, measuredatechar, retrieveddate, measuredate, " +
				" gpslat, gpslng, lat, lng, pm1, pm25, pm10, ufp, ozon, hum, celc, no2" +
				" gpslatfloat, gpslngfloat, pm1float, pm25float, pm10float, ufpfloat, ozonfloat, humfloat, celcfloat, no2float" +
				" geom28992, geom ) VALUES (\n" +
					"'" + 	inputRecord.airbox 			+ "', " +
					"'" + 	inputRecord.retrievedDate 	+ "', " +
					"'" + 	inputRecord.measureDate 	+ "', " +
					"'" +	inputRecord.retrievedDate 	+ "', " + 	// timestamp with time zone,
					"'" + 	_measureDate			 	+ "', \n" +	// timestamp with time zone,
					"'" + 	inputRecord.gpsLat 			+ "', " +
					"'" + 	inputRecord.gpsLng 			+ "', " +
							inputRecord.lat 			+ ", "  +
							inputRecord.lng 			+ ", "  +
					"'" + 	inputRecord.PM1 			+ "', " +
					"'" + 	inputRecord.PM25 			+ "', " +
					"'" +	inputRecord.PM10 			+ "', " +
					"'" + 	inputRecord.UFP 			+ "', " +
					"'" + 	inputRecord.OZON 			+ "', " +
					"'" + 	inputRecord.HUM 			+ "', " +
					"'" + 	inputRecord.CELC 			+ "', " +
					"'" + 	inputRecord.NO2 			+ "', \n" +
							inputRecord.gpsLatFloat 	+ ", "  +
							inputRecord.gpsLngFloat 	+ ", "  +
							inputRecord.PM1Float 		+ ", "  +
							inputRecord.PM25Float 		+ ", "  +
							inputRecord.PM10Float 		+ ", "  +
							inputRecord.UFPFloat 		+ ", "  +
							inputRecord.OZONFloat 		+ ", "  +
							inputRecord.HUMFloat 		+ ", "  +
							inputRecord.CELCFloat 		+ ", "  +
							inputRecord.NO2Float 		+ ", "  +
							" ST_Transform(ST_SetSRID(ST_MakePoint(" + inputRecord.lng + ", " + inputRecord.lat + "), 4326), 28992 ), " +
							" ST_SetSRID(ST_MakePoint(" + inputRecord.lng + ", " + inputRecord.lat + "), 4326) ); ";

			outputFile=outputFile.concat(outputRecord);
		}
	console.log('Write: ' + outputFilePath);
		writeFile(outputFile, outputFilePath);
		executeSql(outputFile, sqlCallBack);
		outputFile = null;  // clear memory

	},

} // end of mopdule.exports
<commit_msg>new record layout csv<commit_after>/*
** Module: aireas2sql
**
**
**
**
*/

// **********************************************************************************
"use strict"; // This is for your code to comply with the ECMAScript 5 standard.

var fs = require('fs');
var pg = require('pg');

var aireasFolder, aireasUrl, aireasFileName, aireasLocalPathRoot, fileFolder,
	tmpFolder, tmpFolderName, localPath, fileFolderName,
	resultsFolder, resultsFolderName, sqlFolder, sqlFolderName;
var nrOfMeasures, maxMeasures, nextFolders, sqlConnString;

// **********************************************************************************

module.exports = {

	init: function (options) {

		sqlConnString = options.configParameter.databaseType + '://' +
			options.configParameter.databaseAccount + ':' +
			options.configParameter.databasePassword + '@' +
			options.configParameter.databaseServer + '/' +
			options.systemCode + '_' + options.configParameter.databaseName;

		aireasLocalPathRoot = options.systemFolderParent+'/aireas/';
		fileFolderName 		= 'aireas';
		tmpFolderName 		= 'tmp';
		resultsFolderName 	= 'results';
		sqlFolderName		= 'sql';

		aireasFolder 		= aireasLocalPathRoot 	+ fileFolderName 	+ "/";
		tmpFolder 			= aireasFolder 			+ tmpFolderName 	+ "/";
		resultsFolder 		= aireasFolder 			+ resultsFolderName + "/";
		sqlFolder 			= aireasFolder 			+ sqlFolderName  	+ "/";

		// create subfolders
		try {fs.mkdirSync(sqlFolder );} catch (e) {};//console.log('ERROR: no sql folder found, batch run aborted.'); return } ;

		var inputLocalIndex = -1;
		var inputLocalFiles = [];
		var rootFolderType = 'year';
		var outputPrefix="";
		nextFolders = {'year':'month','month':'day','day':'hour','hour':'minute','minute':'leafs','leafs':'files'} ;

		maxMeasures = 10;  // stop processing when maxMeasures are processed; restart process for continueing.
		nrOfMeasures = 0;

		this.exploreResultFolders(rootFolderType, resultsFolder, outputPrefix);

	},

	exploreResultFolders: function ( folderType ,path, outputPrefix) {
		var _resultsFolder;
		var nextFolderType;
		var tmpOutputPrefix;
		var i;
		var files;
		var folderContent;
		var fileName;
		var nodeName;
		var aireasFile;
		var createSqlAireas = this.createSqlAireas;

		if (nrOfMeasures>=maxMeasures) {
			console.log('WARNING:','Max number of processed measures reached, restart job to continue.')
			return;
		}

		folderContent = fs.readdirSync(path);
		folderContent.sort();

		if (folderContent) {

			if (folderType == 'leafs') {

				var filesProcessed = true;
				var folderHierarchy = path.split('\/');

				//check if allready processed
                                fileName = 'aireas';
				var file = sqlFolder+outputPrefix+"_"+fileName+ '.sql';
				fs.exists( file, function(exists) {
					if ( exists == false ) {
                                		//files
                                		aireasFile = fs.readFileSync(path+fileName + '.json');
                               			if (aireasFile) {
                                        		console.log(path, fileName + '.json');
                                		} else {
                                        		console.log('ERROR: not found:', path, fileName + '.json');
                                		}
                                		createSqlAireas (aireasFile, sqlFolder+outputPrefix+"_"+ fileName + '.sql');
                                		aireasFile =  null;

                                		nrOfMeasures++;
					}
				});

				return;

			} else {
				nextFolderType = nextFolders[folderType];
				for (i=0;i<folderContent.length;i++) {
					nodeName = folderContent[i];
					tmpOutputPrefix = setPrefix( outputPrefix, folderType, nodeName);
					if (nodeName != '.DS_Store') {  // ignore mac-file
						this.exploreResultFolders(nextFolderType, path + nodeName + '/', tmpOutputPrefix);
					}
				}
			}
		};

		function submitJson() {

		};

		function setPrefix(prefix, folderType, nodeName) {
			var _prefix = "";
			switch (folderType) {
				case "year":{
					_prefix = prefix + nodeName;
				}
				case "month": case "day": case "hour": case "minute": {
					if (nodeName.length<2) {
						_prefix = prefix + "0" + nodeName;
					} else {
						_prefix = prefix + nodeName;
					}
				}
				default: {
				}
			}
			return _prefix;
		};

	},

	createSqlAireas: function(inputFileJson , outputFilePath) {
		var i;

 		var inputFile = JSON.parse(inputFileJson);
		var outputFile = "";

	        var executeSql = function  (query, callback) {
        	        console.log('sql start: ');
                	var client = new pg.Client(sqlConnString);
                	client.connect(function(err) {
                        	if(err) {
                                	return console.error('could not connect to postgres', err);
                        	}
                        	client.query(query, function(err, result) {
                                	if(err) {
                                	return console.error('error running query', err);
                        	}
                        	console.log('sql result: ' + result);
                        	client.end();
                        	});
                	});
        	};

		var sqlCallBack = function (err, result) {
			if (err) {
				console.log('ERROR:','sql error:', err, result);
			} else {
				//console.log('Query','sql result:', result);
			}
		};

        	var writeFile = function(fileContent, filepath ) {
                	var _path = filepath;
                	fs.writeFileSync(_path, fileContent);
        	};

		for (i=0;i<inputFile.length;i++) {

			var inputRecord = inputFile[i];
			var outputRecord = "";

			//var _measureDate		 			= inputRecord.measureDate==""?"null":"'"+inputRecord.measureDate + "', ";

			outputRecord = "\nINSERT INTO aireas ( airbox, retrieveddatechar, measuredatechar, retrieveddate, measuredate, " +
				" gpslat, gpslng, lat, lng, pm1, pm25, pm10, ufp, ozon, hum, celc, no2, " +
				" gpslatfloat, gpslngfloat, pm1float, pm25float, pm10float, ufpfloat, ozonfloat, humfloat, celcfloat, no2float, " +
				" geom28992, geom ) VALUES (\n" +
					"'" + 	inputRecord.airbox 			+ "', " +
					"'" + 	inputRecord.retrievedDate 	+ "', " +
					"'" + 	inputRecord.measureDate 	+ "', " +
					"'" +	inputRecord.retrievedDate 	+ "', " + 	// timestamp with time zone,
					"'" + 	inputRecord.measureDate		+ "', \n" +	// timestamp with time zone,
					"'" + 	inputRecord.gpsLat 			+ "', " +
					"'" + 	inputRecord.gpsLng 			+ "', " +
							inputRecord.lat 			+ ", "  +
							inputRecord.lng 			+ ", "  +
					"'" + 	inputRecord.PM1 			+ "', " +
					"'" + 	inputRecord.PM25 			+ "', " +
					"'" +	inputRecord.PM10 			+ "', " +
					"'" + 	inputRecord.UFP 			+ "', " +
					"'" + 	inputRecord.OZON 			+ "', " +
					"'" + 	inputRecord.HUM 			+ "', " +
					"'" + 	inputRecord.CELC 			+ "', " +
					"'" + 	inputRecord.NO2 			+ "', \n" +
							inputRecord.gpsLatFloat 	+ ", "  +
							inputRecord.gpsLngFloat 	+ ", "  +
							inputRecord.PM1Float 		+ ", "  +
							inputRecord.PM25Float 		+ ", "  +
							inputRecord.PM10Float 		+ ", "  +
							inputRecord.UFPFloat 		+ ", "  +
							inputRecord.OZONFloat 		+ ", "  +
							inputRecord.HUMFloat 		+ ", "  +
							inputRecord.CELCFloat 		+ ", "  +
							inputRecord.NO2Float 		+ ", "  +
							" ST_Transform(ST_SetSRID(ST_MakePoint(" + inputRecord.lng + ", " + inputRecord.lat + "), 4326), 28992 ), " +
							" ST_SetSRID(ST_MakePoint(" + inputRecord.lng + ", " + inputRecord.lat + "), 4326) ); ";

			outputFile=outputFile.concat(outputRecord);
		}
	console.log('Write: ' + outputFilePath);
		writeFile(outputFile, outputFilePath);
		executeSql(outputFile, sqlCallBack);
		outputFile = null;  // clear memory

	},

} // end of mopdule.exports
<|endoftext|>


<commit_before>/*
 * Kuzzle, a backend software, self-hostable and ready to use
 * to power modern apps
 *
 * Copyright 2015-2020 Kuzzle
 * mailto: support AT kuzzle.io
 * website: http://kuzzle.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

const errorsManager = require('../../../util/errors').wrap('network', 'mqtt');
const net = require('net');
const debug = require('../../../util/debug')('kuzzle:entry-point:protocols:mqtt');
const ClientConnection = require('../clientConnection');
const Protocol = require('./protocol');
const aedes = require('aedes');
const { Request } = require('kuzzle-common-objects');
const removeErrorStack = require('../removeErrorStack');

/**
 * @class MqttProtocol
 */
class MqttProtocol extends Protocol {
  constructor () {
    super();

    this.aedes = new aedes.Server();
    this.server = net.createServer(this.aedes.handle);

    this.entryPoint = null;
    this.kuzzle = null;

    this.connections = new Map();
    this.connectionsById = new Map();
  }

  async init (entryPoint) {
    await super.init('mqtt', entryPoint);

    if (this.config.enabled === false) {
      return false;
    }

    debug('initializing MQTT Server with config: %a', this.config);

    this.entryPoint = entryPoint;
    this.kuzzle = this.entryPoint.kuzzle;

    this.config = Object.assign({
      allowPubSub: false,
      developmentMode: false,
      disconnectDelay: 250,
      requestTopic: 'Kuzzle/request',
      responseTopic: 'Kuzzle/response',
      server: {
        port: 1883
      }
    }, this.config);

    /*
     * To avoid ill-use of our topics, we need to configure authorizations:
     * "requestTopic": should be publish-only, so no one but this plugin can
     *                 listen to this topic
     * "responseTopic": should be subscribe-only, so no one but this plugin can
     *                  write in it
     */
    this.aedes.authorizePublish = this._authorizePublish.bind(this);
    this.aedes.authorizeSubscribe = this._authorizeSubscribe.bind(this);

    // Message events
    this.aedes.on('client', this.onConnection.bind(this));
    this.aedes.on('clientError', this.onDisconnection.bind(this));
    this.aedes.on('clientDisconnect', this.onDisconnection.bind(this));
    this.aedes.on('publish', this.onMessage.bind(this));

    await new Promise(res => this.server.listen(this.config.server.port, res));

    return true;
  }

  broadcast (data) {
    debug('broadcast %a', data);

    const payload = JSON.stringify(data.payload);

    for (const channel of data.channels) {
      this.aedes.publish({payload, topic: channel});
    }
  }

  disconnect (connectionId, message = 'Connection closed by remote host') {
    debug('disconnect: connection id: %s, message %s', connectionId, message);

    const client = this.connectionsById.get(connectionId);

    if (client) {
      client.close(undefined, message);
    }
  }

  joinChannel () {
    // do nothing
  }

  leaveChannel () {
    // do nothing
  }

  notify (data) {
    debug('notify %a', data);

    const client = this.connectionsById.get(data.connectionId);

    if (!client) {
      return;
    }

    const payload = Buffer.from(JSON.stringify(data.payload));

    data.channels.forEach(topic => client.publish({payload, topic}));
  }

  /**
   * @param {Client} client
   */
  onConnection (client) {
    debug('onConnection: %s', client.id);

    const connection = new ClientConnection(
      this.name,
      [client.conn.remoteAddress],
      {});
    this.entryPoint.newConnection(connection);

    this.connections.set(client, connection);
    this.connectionsById.set(connection.id, client);
  }

  /**
   * @param {Client} client
   */
  onDisconnection (client) {
    debug('onDisconnection %s', client.id);

    if (this.connections.has(client)) {
      setTimeout(
        () => {
          const connection = this.connections.get(client);

          if (connection) {
            this.connections.delete(client);
            this.connectionsById.delete(connection.id);
            this.entryPoint.removeConnection(connection.id);
          }
        },
        this.config.disconnectDelay);
    }
  }

  /**
   * @param packet
   * @param client
   */
  onMessage (packet, client) {
    if ( packet.topic !== this.config.requestTopic
      || packet.payload === null
      || client.id === null
    ) {
      return;
    }

    const connection = this.connections.get(client);

    if (connection === undefined) {
      debug('no connection id for client id %s - packet: %o', client.id, packet);
      this.kuzzle.log.error(`[MQTT] Received a packet from an unregistered client: ${client.id}`);
      return;
    }

    try {
      const payload = JSON.parse(packet.payload.toString());

      debug('onMessage payload: %o', payload);

      const request = new Request(payload, {
        connection,
        // @deprecated - backward compatibility only
        connectionId: connection.id,
        protocol: this.name
      });

      this.entryPoint.execute(
        request,
        response => this._respond(client, response));
    }
    catch (error) {
      this._respondError(client, error);
    }
  }

  _respond (client, response) {
    debug('sending response: %o', response.content);

    if (process.env.NODE_ENV === 'development' && this.config.developmentMode) {
      this.broadcast({
        channels: [this.config.responseTopic],
        payload: response.content,
      });
      return;
    }

    client.publish({
      payload: Buffer.from(JSON.stringify(response.content)),
      topic: this.config.responseTopic,
    });
  }

  _respondError (client, error) {
    const connection = this.connections.get(client);

    const errReq = new Request({}, {
      connection,
      error: errorsManager.getFrom(error, 'unexpected_error', error.message)
    });
    this._respond(client, removeErrorStack(errReq.response.toJSON()));
  }

  _authorizePublish (client, packet, callback) {
    const topic = packet.topic.toString();

    if (this.config.allowPubSub) {
      if (topic === this.config.responseTopic) {
        callback(new Error('Cannot publish: this topic is read-only'));
      }
      else if (topic.includes('#') || topic.includes('+')) {
        callback(new Error('Cannot publish: wildcards are disabled'));
      }
      else {
        callback(null);
      }
    }
    else {
      callback(topic === this.config.requestTopic
        ? null
        : new Error('Cannot publish on this topic: unauthorized'));
    }
  }

  _authorizeSubscribe (client, sub, callback) {
    if (sub.topic === this.config.requestTopic) {
      callback(new Error('Cannot subscribe: this topic is write-only'));
    }
    else if (sub.topic.includes('#') || sub.topic.includes('+')) {
      callback(new Error('Cannot subscribe: wildcards are disabled'));
    }
    else {
      callback(null, sub);
    }
  }
}

module.exports = MqttProtocol;
<commit_msg>[deprecated] remove support for v1-style request contexts<commit_after>/*
 * Kuzzle, a backend software, self-hostable and ready to use
 * to power modern apps
 *
 * Copyright 2015-2020 Kuzzle
 * mailto: support AT kuzzle.io
 * website: http://kuzzle.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

const errorsManager = require('../../../util/errors').wrap('network', 'mqtt');
const net = require('net');
const debug = require('../../../util/debug')('kuzzle:entry-point:protocols:mqtt');
const ClientConnection = require('../clientConnection');
const Protocol = require('./protocol');
const aedes = require('aedes');
const { Request } = require('kuzzle-common-objects');
const removeErrorStack = require('../removeErrorStack');

/**
 * @class MqttProtocol
 */
class MqttProtocol extends Protocol {
  constructor () {
    super();

    this.aedes = new aedes.Server();
    this.server = net.createServer(this.aedes.handle);

    this.entryPoint = null;
    this.kuzzle = null;

    this.connections = new Map();
    this.connectionsById = new Map();
  }

  async init (entryPoint) {
    await super.init('mqtt', entryPoint);

    if (this.config.enabled === false) {
      return false;
    }

    debug('initializing MQTT Server with config: %a', this.config);

    this.entryPoint = entryPoint;
    this.kuzzle = this.entryPoint.kuzzle;

    this.config = Object.assign({
      allowPubSub: false,
      developmentMode: false,
      disconnectDelay: 250,
      requestTopic: 'Kuzzle/request',
      responseTopic: 'Kuzzle/response',
      server: {
        port: 1883
      }
    }, this.config);

    /*
     * To avoid ill-use of our topics, we need to configure authorizations:
     * "requestTopic": should be publish-only, so no one but this plugin can
     *                 listen to this topic
     * "responseTopic": should be subscribe-only, so no one but this plugin can
     *                  write in it
     */
    this.aedes.authorizePublish = this._authorizePublish.bind(this);
    this.aedes.authorizeSubscribe = this._authorizeSubscribe.bind(this);

    // Message events
    this.aedes.on('client', this.onConnection.bind(this));
    this.aedes.on('clientError', this.onDisconnection.bind(this));
    this.aedes.on('clientDisconnect', this.onDisconnection.bind(this));
    this.aedes.on('publish', this.onMessage.bind(this));

    await new Promise(res => this.server.listen(this.config.server.port, res));

    return true;
  }

  broadcast (data) {
    debug('broadcast %a', data);

    const payload = JSON.stringify(data.payload);

    for (const channel of data.channels) {
      this.aedes.publish({payload, topic: channel});
    }
  }

  disconnect (connectionId, message = 'Connection closed by remote host') {
    debug('disconnect: connection id: %s, message %s', connectionId, message);

    const client = this.connectionsById.get(connectionId);

    if (client) {
      client.close(undefined, message);
    }
  }

  joinChannel () {
    // do nothing
  }

  leaveChannel () {
    // do nothing
  }

  notify (data) {
    debug('notify %a', data);

    const client = this.connectionsById.get(data.connectionId);

    if (!client) {
      return;
    }

    const payload = Buffer.from(JSON.stringify(data.payload));

    data.channels.forEach(topic => client.publish({payload, topic}));
  }

  /**
   * @param {Client} client
   */
  onConnection (client) {
    debug('onConnection: %s', client.id);

    const connection = new ClientConnection(
      this.name,
      [client.conn.remoteAddress],
      {});
    this.entryPoint.newConnection(connection);

    this.connections.set(client, connection);
    this.connectionsById.set(connection.id, client);
  }

  /**
   * @param {Client} client
   */
  onDisconnection (client) {
    debug('onDisconnection %s', client.id);

    if (this.connections.has(client)) {
      setTimeout(
        () => {
          const connection = this.connections.get(client);

          if (connection) {
            this.connections.delete(client);
            this.connectionsById.delete(connection.id);
            this.entryPoint.removeConnection(connection.id);
          }
        },
        this.config.disconnectDelay);
    }
  }

  /**
   * @param packet
   * @param client
   */
  onMessage (packet, client) {
    if ( packet.topic !== this.config.requestTopic
      || packet.payload === null
      || client.id === null
    ) {
      return;
    }

    const connection = this.connections.get(client);

    if (connection === undefined) {
      debug('no connection id for client id %s - packet: %o', client.id, packet);
      this.kuzzle.log.error(`[MQTT] Received a packet from an unregistered client: ${client.id}`);
      return;
    }

    try {
      const payload = JSON.parse(packet.payload.toString());

      debug('onMessage payload: %o', payload);

      const request = new Request(payload, { connection });

      this.entryPoint.execute(
        request,
        response => this._respond(client, response));
    }
    catch (error) {
      this._respondError(client, error);
    }
  }

  _respond (client, response) {
    debug('sending response: %o', response.content);

    if (process.env.NODE_ENV === 'development' && this.config.developmentMode) {
      this.broadcast({
        channels: [this.config.responseTopic],
        payload: response.content,
      });
      return;
    }

    client.publish({
      payload: Buffer.from(JSON.stringify(response.content)),
      topic: this.config.responseTopic,
    });
  }

  _respondError (client, error) {
    const connection = this.connections.get(client);

    const errReq = new Request({}, {
      connection,
      error: errorsManager.getFrom(error, 'unexpected_error', error.message)
    });
    this._respond(client, removeErrorStack(errReq.response.toJSON()));
  }

  _authorizePublish (client, packet, callback) {
    const topic = packet.topic.toString();

    if (this.config.allowPubSub) {
      if (topic === this.config.responseTopic) {
        callback(new Error('Cannot publish: this topic is read-only'));
      }
      else if (topic.includes('#') || topic.includes('+')) {
        callback(new Error('Cannot publish: wildcards are disabled'));
      }
      else {
        callback(null);
      }
    }
    else {
      callback(topic === this.config.requestTopic
        ? null
        : new Error('Cannot publish on this topic: unauthorized'));
    }
  }

  _authorizeSubscribe (client, sub, callback) {
    if (sub.topic === this.config.requestTopic) {
      callback(new Error('Cannot subscribe: this topic is write-only'));
    }
    else if (sub.topic.includes('#') || sub.topic.includes('+')) {
      callback(new Error('Cannot subscribe: wildcards are disabled'));
    }
    else {
      callback(null, sub);
    }
  }
}

module.exports = MqttProtocol;
<|endoftext|>


<commit_before>function GameManager(size, InputManager, Actuator, StorageManager) {
  this.size           = size; // Size of the grid
  this.inputManager   = new InputManager;
  this.storageManager = new StorageManager;
  this.actuator       = new Actuator;

  this.startTiles     = 2;

  //this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));
  this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.storageManager.clearGameState();
  this.actuator.continueGame(); // Clear the game won/lost message
  lastmove = 0;
  this.setup();
};

// Keep playing after winning (allows going over 2048)
GameManager.prototype.keepPlaying = function () {
  this.keepPlaying = true;
  this.actuator.continueGame(); // Clear the game won/lost message
};

// Return true if the game is lost, or has won and the user hasn't kept playing
GameManager.prototype.isGameTerminated = function () {
  return this.over || (this.won && !this.keepPlaying);
};

// Set up the game
GameManager.prototype.setup = function () {
  var previousState = this.storageManager.getGameState();

  // Reload the game from a previous game if present
  if (previousState) {
    this.grid        = new Grid(previousState.grid.size,
                                previousState.grid.cells); // Reload grid
    this.score       = previousState.score;
    this.over        = previousState.over;
    this.won         = previousState.won;
    this.keepPlaying = previousState.keepPlaying;
  } else {
    this.grid        = new Grid(this.size);
    this.score       = 0;
    this.over        = false;
    this.won         = false;
    this.keepPlaying = false;

    // Add the initial tiles
    this.addStartTiles();
  }

  // Update the actuator
  this.actuate();
};

// Set up the initial tiles to start the game with
GameManager.prototype.addStartTiles = function () {
  for (var i = 0; i < this.startTiles; i++) {
    this.addRandomTile();
  }
};

// Adds a tile in a random position
GameManager.prototype.addRandomTile = function () {
  if (this.grid.cellsAvailable()) {
    var value = Math.random() < 0.9 ? 2 : 4;
    var tile = new Tile(this.grid.randomAvailableCell(), value);

    this.grid.insertTile(tile);
  }
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
  if (this.storageManager.getBestScore() < this.score) {
    this.storageManager.setBestScore(this.score);
  }

  // Clear the state when the game is over (game over only, not win)
  if (this.over) {
    this.storageManager.clearGameState();
  } else {
    this.storageManager.setGameState(this.serialize());
  }

  this.actuator.actuate(this.grid, {
    score:      this.score,
    over:       this.over,
    won:        this.won,
    bestScore:  this.storageManager.getBestScore(),
    terminated: this.isGameTerminated()
  });

  // Test run (random):
  //var direction = this.random();
  //this.move.bind(direction);

  // Test run (greedy):
  //var direction = this.greedy();
  //this.move.bind(direction);

  // Test run (human):
  console.log("Test 1")
  var direction = this.human();
  console.log("Test 2")
  this.move(direction);
  console.log("Test 3")
};

// Represent the current game as an object
GameManager.prototype.serialize = function () {
  return {
    grid:        this.grid.serialize(),
    score:       this.score,
    over:        this.over,
    won:         this.won,
    keepPlaying: this.keepPlaying
  };
};

// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
  this.grid.eachCell(function (x, y, tile) {
    if (tile) {
      tile.mergedFrom = null;
      tile.savePosition();
    }
  });
};

// Move a tile and its representation
GameManager.prototype.moveTile = function (tile, cell) {
  this.grid.cells[tile.x][tile.y] = null;
  this.grid.cells[cell.x][cell.y] = tile;
  tile.updatePosition(cell);
};

// Move tiles on the grid in the specified direction
GameManager.prototype.move = function (direction) {
	console.log("Direction is: " + direction)
  // 0: up, 1: right, 2: down, 3: left
  var self = this;

  if (this.isGameTerminated()) return; // Don't do anything if the game's over

  var cell, tile;

  var vector     = this.getVector(direction);
  var traversals = this.buildTraversals(vector);
  var moved      = false;

  // Save the current tile positions and remove merger information
  this.prepareTiles();

  // Traverse the grid in the right direction and move tiles
  traversals.x.forEach(function (x) {
    traversals.y.forEach(function (y) {
      cell = { x: x, y: y };
      tile = self.grid.cellContent(cell);

      if (tile) {
        var positions = self.findFarthestPosition(cell, vector);
        var next      = self.grid.cellContent(positions.next);

        // Only one merger per row traversal?
        if (next && next.value === tile.value && !next.mergedFrom) {
          var merged = new Tile(positions.next, tile.value * 2);
          merged.mergedFrom = [tile, next];

          self.grid.insertTile(merged);
          self.grid.removeTile(tile);

          // Converge the two tiles' positions
          tile.updatePosition(positions.next);

          // Update the score
          self.score += merged.value;

          // The mighty 2048 tile
          if (merged.value === 2048) self.won = true;
        } else {
          self.moveTile(tile, positions.farthest);
        }

        if (!self.positionsEqual(cell, tile)) {
          moved = true; // The tile moved from its original cell!
        }
      }
    });
  });

  if (moved) {
    this.addRandomTile();

    if (!this.movesAvailable()) {
      this.over = true; // Game over!
    }

    this.actuate();
  }
};

// Get the vector representing the chosen direction
GameManager.prototype.getVector = function (direction) {
  // Vectors representing tile movement
  var map = {
    0: { x: 0,  y: -1 }, // Up
    1: { x: 1,  y: 0 },  // Right
    2: { x: 0,  y: 1 },  // Down
    3: { x: -1, y: 0 }   // Left
  };

  return map[direction];
};

// Build a list of positions to traverse in the right order
GameManager.prototype.buildTraversals = function (vector) {
  var traversals = { x: [], y: [] };

  for (var pos = 0; pos < this.size; pos++) {
    traversals.x.push(pos);
    traversals.y.push(pos);
  }

  // Always traverse from the farthest cell in the chosen direction
  if (vector.x === 1) traversals.x = traversals.x.reverse();
  if (vector.y === 1) traversals.y = traversals.y.reverse();

  return traversals;
};

GameManager.prototype.findFarthestPosition = function (cell, vector) {
  var previous;

  // Progress towards the vector direction until an obstacle is found
  do {
    previous = cell;
    cell     = { x: previous.x + vector.x, y: previous.y + vector.y };
  } while (this.grid.withinBounds(cell) &&
           this.grid.cellAvailable(cell));

  return {
    farthest: previous,
    next: cell // Used to check if a merge is required
  };
};

GameManager.prototype.movesAvailable = function () {
  return this.grid.cellsAvailable() || this.tileMatchesAvailable();
};

// Check for available matches between tiles (more expensive check)
GameManager.prototype.tileMatchesAvailable = function () {
  var self = this;

  var tile;

  for (var x = 0; x < this.size; x++) {
    for (var y = 0; y < this.size; y++) {
      tile = this.grid.cellContent({ x: x, y: y });

      if (tile) {
        for (var direction = 0; direction < 4; direction++) {
          var vector = self.getVector(direction);
          var cell   = { x: x + vector.x, y: y + vector.y };

          var other  = self.grid.cellContent(cell);

          if (other && other.value === tile.value) {
            return true; // These two tiles can be merged
          }
        }
      }
    }
  }

  return false;
};

GameManager.prototype.positionsEqual = function (first, second) {
  return first.x === second.x && first.y === second.y;
};

GameManager.prototype.fitnessweights = function () {
	// Highest number x. (2^x = value)
	var x = Math.log2(this.storageManager.getBestScore());
	// Amount of empty cells n.
	var n = this.grid.amountAvailable();

	return x + n;
};

GameManager.prototype.fitnessnoweights = function () {
	// Highest number x. (value / 100 = x)
	var x = this.storageManager.getBestScore() / 100;
	// Amount of empty cells n.
	var n = this.grid.amountAvailable();

	return x + n;
};

// Strategies //

// Random
GameManager.prototype.random = function() {
	  var array = [0, 1, 2, 3];
	  var m = 4;
	  // While there remain elements to shuffle…
	  while (m) {

	    // Pick a remaining element…
	    i = Math.floor(Math.random() * m--);

	    // And swap it with the current element.
	    t = array[m];
	    array[m] = array[i];
	    array[i] = t;
	  }
	  //console.log(array);
	  var direction = this.preferredDirection(array[0], array[1], array[2], array[3]);
	  //console.log("direction: " + direction)
	  return direction; 	// returns next move, random number (0, 1, 2 or 3)
};

// Greedy
GameManager.prototype.greedy = function() {
	// FF Up:
	var ffup = this.fitness(0);

	// FF Right:
	var ffright = this.fitness(1);

	// FF Down:
	var ffdown = this.fitness(2);

	// FF Left:
	var ffleft = this.fitness(3);

	var array = this.makeArray(ffup, ffright, ffdown, ffleft);

	var direction = this.preferredDirection(array[0], array[1], array[2], array[3]);

	return direction;
};

GameManager.prototype.makeArray = function(up, right, down, left) {
	directions = [up, right, down, left];

	var pos1 = Math.max(directions[0], directions[1], directions[2], directions[3]);
	var ind1 = directions.indexOf(pos1);
	if (ind1 > -1) {
		directions.splice(ind1, 1);
	}

	var pos2 = Math.max(directions[0], directions[1], directions[2]);
	var ind2 = directions.indexOf(pos2);
	if (ind2 > -1) {
		directions.splice(ind2, 1);
	}

	var pos3 = Math.max(directions[0], directions[1]);
	var ind3 = directions.indexOf(pos3);
	if (ind3 > -1) {
		directions.splice(ind3, 1);
	}

	var pos4 = directions[0];

	var array = [pos1, pos2, pos3, pos4];

	return array;
};

GameManager.prototype.fitness = function(direction) {
	var previousState = this.storageManager.getGameState();
	this.move(direction);

	// TODO: determine fitness function of current state
	var fitness = 0;

	this.storageManager.setGameState(previousState);
	return fitness;
};

var lastmove = 0;

// Human
GameManager.prototype.human = function() {
	var newDirection = -1;
	if(lastmove == 3) { 		// Left
		newDirection = this.preferredDirection(0, 3, 1, 2);
		lastmove = newDirection;
		return newDirection;
	}
	else if (lastmove == 0) { 	// Up
		newDirection = this.preferredDirection(3, 0, 1, 2);
		lastmove = newDirection;
		return newDirection;
	}
	else if (lastmove == 1) {	// Right
		newDirection = this.preferredDirection(0, 3, 1, 2);
		lastmove = newDirection;
		return newDirection;
	}
	else if (lastmove == 2) {	// Down
		newDirection = this.preferredDirection(0, 3, 1, 2);
		lastmove = newDirection;
		return newDirection;
	}
	else {
		console.log("Should not come here")
		return newDirection;		// Should not come here
	}
};

GameManager.prototype.preferredDirection = function(optionA, optionB, optionC, optionD) {
	var previousState = this.storageManager.getGameState();
	console.log("Before option A")
	this.move(optionA);
	if(previousState == this.storageManager.getGameState()) {
		console.log("equals")
		this.storageManager.setGameState(previousState);
		this.move(optionB);
		if(previousState == this.storageManager.getGameState()) {
			this.storageManager.setGameState(previousState);
			this.move(optionC);
			if(previousState == this.storageManager.getGameState()) {
				this.storageManager.setGameState(previousState);
				return optionD;
			}
			else {
				return optionC;
			}
		}
		else {
			return optionB;
		}
	}
	else {
		return optionA;
	}

}<commit_msg>ownage<commit_after>function GameManager(size, InputManager, Actuator, StorageManager) {
  this.size           = size; // Size of the grid
  this.inputManager   = new InputManager;
  this.storageManager = new StorageManager;
  this.actuator       = new Actuator;

  this.startTiles     = 2;

  //this.inputManager.on("move", this.move.bind(this));
  this.inputManager.on("restart", this.restart.bind(this));
  this.inputManager.on("keepPlaying", this.keepPlaying.bind(this));

  this.setup();
}

// Restart the game
GameManager.prototype.restart = function () {
  this.storageManager.clearGameState();
  this.actuator.continueGame(); // Clear the game won/lost message
  lastmove = 0;
  this.setup();
};

// Keep playing after winning (allows going over 2048)
GameManager.prototype.keepPlaying = function () {
  this.keepPlaying = true;
  this.actuator.continueGame(); // Clear the game won/lost message
};

// Return true if the game is lost, or has won and the user hasn't kept playing
GameManager.prototype.isGameTerminated = function () {
  return this.over || (this.won && !this.keepPlaying);
};

// Set up the game
GameManager.prototype.setup = function () {
  var previousState = this.storageManager.getGameState();

  // Reload the game from a previous game if present
  if (previousState) {
    this.grid        = new Grid(previousState.grid.size,
                                previousState.grid.cells); // Reload grid
    this.score       = previousState.score;
    this.over        = previousState.over;
    this.won         = previousState.won;
    this.keepPlaying = previousState.keepPlaying;
  } else {
    this.grid        = new Grid(this.size);
    this.score       = 0;
    this.over        = false;
    this.won         = false;
    this.keepPlaying = false;

    // Add the initial tiles
    this.addStartTiles();
  }

  // Update the actuator
  this.actuate();
};

// Set up the initial tiles to start the game with
GameManager.prototype.addStartTiles = function () {
  for (var i = 0; i < this.startTiles; i++) {
    this.addRandomTile();
  }
};

// Adds a tile in a random position
GameManager.prototype.addRandomTile = function () {
  if (this.grid.cellsAvailable()) {
    var value = Math.random() < 0.9 ? 2 : 4;
    var tile = new Tile(this.grid.randomAvailableCell(), value);

    this.grid.insertTile(tile);
  }
};

// Sends the updated grid to the actuator
GameManager.prototype.actuate = function () {
  if (this.storageManager.getBestScore() < this.score) {
    this.storageManager.setBestScore(this.score);
  }

  // Clear the state when the game is over (game over only, not win)
  if (this.over) {
    this.storageManager.clearGameState();
  } else {
    this.storageManager.setGameState(this.serialize());
  }

  this.actuator.actuate(this.grid, {
    score:      this.score,
    over:       this.over,
    won:        this.won,
    bestScore:  this.storageManager.getBestScore(),
    terminated: this.isGameTerminated()
  });

  // Test run (random):
  var direction = this.random();
  //console.log("var direction = " + direction)
  //this.move(direction);

  // Test run (greedy):
  //var direction = this.greedy();
  //console.log("var direction = " + direction)
  //this.move.bind(direction);

  // Test run (human):
  //var direction = this.human();
  //console.log("var direction = " + direction)
  //this.move(direction);

};

// Represent the current game as an object
GameManager.prototype.serialize = function () {
  return {
    grid:        this.grid.serialize(),
    score:       this.score,
    over:        this.over,
    won:         this.won,
    keepPlaying: this.keepPlaying
  };
};

// Save all tile positions and remove merger info
GameManager.prototype.prepareTiles = function () {
  this.grid.eachCell(function (x, y, tile) {
    if (tile) {
      tile.mergedFrom = null;
      tile.savePosition();
    }
  });
};

// Move a tile and its representation
GameManager.prototype.moveTile = function (tile, cell) {
  this.grid.cells[tile.x][tile.y] = null;
  this.grid.cells[cell.x][cell.y] = tile;
  tile.updatePosition(cell);
};

// Move tiles on the grid in the specified direction
GameManager.prototype.move = function (direction) {
   //console.log("Direction is: " + direction)
  // 0: up, 1: right, 2: down, 3: left
  var self = this;

  if (this.isGameTerminated()) return; // Don't do anything if the game's over

  var cell, tile;

  var vector     = this.getVector(direction);
  var traversals = this.buildTraversals(vector);
  var moved      = false;

  // Save the current tile positions and remove merger information
  this.prepareTiles();

  // Traverse the grid in the right direction and move tiles
  traversals.x.forEach(function (x) {
    traversals.y.forEach(function (y) {
      cell = { x: x, y: y };
      tile = self.grid.cellContent(cell);

      if (tile) {
        var positions = self.findFarthestPosition(cell, vector);
        var next      = self.grid.cellContent(positions.next);

        // Only one merger per row traversal?
        if (next && next.value === tile.value && !next.mergedFrom) {
          var merged = new Tile(positions.next, tile.value * 2);
          merged.mergedFrom = [tile, next];

          self.grid.insertTile(merged);
          self.grid.removeTile(tile);

          // Converge the two tiles' positions
          tile.updatePosition(positions.next);

          // Update the score
          self.score += merged.value;

          // The mighty 2048 tile
          if (merged.value === 2048) self.won = true;
        } else {
          self.moveTile(tile, positions.farthest);
        }

        if (!self.positionsEqual(cell, tile)) {
          moved = true; // The tile moved from its original cell!
        }
      }
    });
  });

  if (moved) {
    this.addRandomTile();

    if (!this.movesAvailable()) {
      this.over = true; // Game over!
    }

    this.actuate();
  }
};

// Get the vector representing the chosen direction
GameManager.prototype.getVector = function (direction) {
  // Vectors representing tile movement
  var map = {
    0: { x: 0,  y: -1 }, // Up
    1: { x: 1,  y: 0 },  // Right
    2: { x: 0,  y: 1 },  // Down
    3: { x: -1, y: 0 }   // Left
  };

  return map[direction];
};

// Build a list of positions to traverse in the right order
GameManager.prototype.buildTraversals = function (vector) {
  var traversals = { x: [], y: [] };

  for (var pos = 0; pos < this.size; pos++) {
    traversals.x.push(pos);
    traversals.y.push(pos);
  }

  // Always traverse from the farthest cell in the chosen direction
  if (vector.x === 1) traversals.x = traversals.x.reverse();
  if (vector.y === 1) traversals.y = traversals.y.reverse();

  return traversals;
};

GameManager.prototype.findFarthestPosition = function (cell, vector) {
  var previous;

  // Progress towards the vector direction until an obstacle is found
  do {
    previous = cell;
    cell     = { x: previous.x + vector.x, y: previous.y + vector.y };
  } while (this.grid.withinBounds(cell) &&
           this.grid.cellAvailable(cell));

  return {
    farthest: previous,
    next: cell // Used to check if a merge is required
  };
};

GameManager.prototype.movesAvailable = function () {
  return this.grid.cellsAvailable() || this.tileMatchesAvailable();
};

// Check for available matches between tiles (more expensive check)
GameManager.prototype.tileMatchesAvailable = function () {
  var self = this;

  var tile;

  for (var x = 0; x < this.size; x++) {
    for (var y = 0; y < this.size; y++) {
      tile = this.grid.cellContent({ x: x, y: y });

      if (tile) {
        for (var direction = 0; direction < 4; direction++) {
          var vector = self.getVector(direction);
          var cell   = { x: x + vector.x, y: y + vector.y };

          var other  = self.grid.cellContent(cell);

          if (other && other.value === tile.value) {
            return true; // These two tiles can be merged
          }
        }
      }
    }
  }

  return false;
};

GameManager.prototype.positionsEqual = function (first, second) {
  return first.x === second.x && first.y === second.y;
};

GameManager.prototype.fitnessweights = function () {
	// Highest number x. (2^x = value)
	var x = Math.log2(this.storageManager.getBestScore());
	// Amount of empty cells n.
	var n = this.grid.amountAvailable();

	return x + n;
};

GameManager.prototype.fitnessnoweights = function () {
	// Highest number x. (value / 100 = x)
	var x = this.storageManager.getBestScore() / 100;
	// Amount of empty cells n.
	var n = this.grid.amountAvailable();

	return x + n;
};

// Strategies //

// Random
GameManager.prototype.random = function() {
	  var array = [0, 1, 2, 3];
	  var m = 4;
	  // While there remain elements to shuffle…
	  while (m) {

	    // Pick a remaining element…
	    i = Math.floor(Math.random() * m--);

	    // And swap it with the current element.
	    t = array[m];
	    array[m] = array[i];
	    array[i] = t;
	  }
	  //console.log(array);
	  var direction = this.preferredDirection(array[0], array[1], array[2], array[3]);
	  //console.log("direction: " + direction)
	  return direction; 	// returns next move, random number (0, 1, 2 or 3)
};

// Greedy
GameManager.prototype.greedy = function() {
	// FF Up:
	var ffup = this.fitness(0);

	// FF Right:
	var ffright = this.fitness(1);

	// FF Down:
	var ffdown = this.fitness(2);

	// FF Left:
	var ffleft = this.fitness(3);

	var array = this.makeArray(ffup, ffright, ffdown, ffleft);

	var direction = this.preferredDirection(array[0], array[1], array[2], array[3]);

	return direction;
};

GameManager.prototype.makeArray = function(up, right, down, left) {
	directions = [up, right, down, left];

	var pos1 = Math.max(directions[0], directions[1], directions[2], directions[3]);
	var ind1 = directions.indexOf(pos1);
	if (ind1 > -1) {
		directions.splice(ind1, 1);
	}

	var pos2 = Math.max(directions[0], directions[1], directions[2]);
	var ind2 = directions.indexOf(pos2);
	if (ind2 > -1) {
		directions.splice(ind2, 1);
	}

	var pos3 = Math.max(directions[0], directions[1]);
	var ind3 = directions.indexOf(pos3);
	if (ind3 > -1) {
		directions.splice(ind3, 1);
	}

	var pos4 = directions[0];

	var array = [pos1, pos2, pos3, pos4];

	return array;
};

GameManager.prototype.fitness = function(direction) {
	var previousState = this.storageManager.getGameState();
	this.move(direction);

	// TODO: determine fitness function of current state
	var fitness = 0;

	this.storageManager.setGameState(previousState);
	return fitness;
};

var lastmove = 0;

// Human
GameManager.prototype.human = function() {
	var newDirection = -1;
	if(lastmove == 3) { 		// Left
		newDirection = this.preferredDirection(0, 3, 1, 2);
		lastmove = newDirection;
		return newDirection;
	}
	else if (lastmove == 0) { 	// Up
		newDirection = this.preferredDirection(3, 0, 1, 2);
		lastmove = newDirection;
		return newDirection;
	}
	else if (lastmove == 1) {	// Right
		newDirection = this.preferredDirection(0, 3, 1, 2);
		lastmove = newDirection;
		return newDirection;
	}
	else if (lastmove == 2) {	// Down
		newDirection = this.preferredDirection(0, 3, 1, 2);
		lastmove = newDirection;
		return newDirection;
	}
	else {
		console.log("Should not come here")
		return newDirection;		// Should not come here
	}
};

GameManager.prototype.preferredDirection = function(optionA, optionB, optionC, optionD) {
	var previousState = this.storageManager.getGameState();
	//console.log("previousState: " + previousState)
	//this.movePossible(optionA);
	if(!this.movePossible(optionA)) {
		//console.log(this.storageManager.getGameState())
		this.storageManager.setGameState(previousState);
		if(!this.movePossible(optionB)) {
			this.storageManager.setGameState(previousState);
			if(!this.movePossible(optionC)) {
				this.storageManager.setGameState(previousState);
				return optionD;
			}
			else {
				return optionC;
			}
		}
		else {
			return optionB;
		}
	}
	else {
		return optionA;
	}
};

// Move tiles on the grid in the specified direction
GameManager.prototype.movePossible = function (direction) {
  //console.log("Direction is: " + direction)
  // 0: up, 1: right, 2: down, 3: left
  var self = this;

  if (this.isGameTerminated()) return; // Don't do anything if the game's over

  var cell, tile;

  var vector     = this.getVector(direction);
  var traversals = this.buildTraversals(vector);
  var moved      = false;

  // Save the current tile positions and remove merger information
  this.prepareTiles();

  // Traverse the grid in the right direction and move tiles
  traversals.x.forEach(function (x) {
    traversals.y.forEach(function (y) {
      cell = { x: x, y: y };
      tile = self.grid.cellContent(cell);

      if (tile) {
        var positions = self.findFarthestPosition(cell, vector);
        var next      = self.grid.cellContent(positions.next);

        // Only one merger per row traversal?
        if (next && next.value === tile.value && !next.mergedFrom) {
          var merged = new Tile(positions.next, tile.value * 2);
          merged.mergedFrom = [tile, next];

          self.grid.insertTile(merged);
          self.grid.removeTile(tile);

          // Converge the two tiles' positions
          tile.updatePosition(positions.next);

          // Update the score
          self.score += merged.value;

          // The mighty 2048 tile
          if (merged.value === 2048) self.won = true;
        } else {
          self.moveTile(tile, positions.farthest);
        }

        if (!self.positionsEqual(cell, tile)) {
          moved = true; // The tile moved from its original cell!
        }
      }
    });
  });

  if (moved) {
    this.addRandomTile();

    if (!this.movesAvailable()) {
      this.over = true; // Game over!
    }

    this.actuate();
  }

  return moved;
};<|endoftext|>