<commit_before>//
// This is our main object that will be responsible for collecting
// information from user request and running docker container
//
var sandbox = function(sandboxData) {

	var exec = require('child_process').exec;
	var q = require('q');
	var fs = require('fs');
	var path = require('path');
	var constants   =  require(path.resolve('./modules/common/constants.js'));
    var sandboxError   =  require(path.resolve('./modules/common/sandboxerror.js'));

	var self = this;

	this.usercode = sandboxData.usercode;
	this.languageid = sandboxData.languageid;
	this.tempFolder = sandboxData.tempFolder;
	this.currentWorkingPath = sandboxData.currentWorkingPath;
	this.compilerName = sandboxData.compilerName;
	this.fileName = sandboxData.fileName;
	this.outputCommand = sandboxData.outputCommand;
	this.languageName = sandboxData.languageName;
	this.extraArguments = sandboxData.extraArguments;
	this.standardInput = sandboxData.standardInput;
	this.dockerImage = constants.dockerImage;

	this.fullPathToTemp = this.currentWorkingPath + this.tempFolder;

	this.timeoutValue = 20;

	//
	// check of docker image exists before we do anything further
	//
	function checkDockerImageExists() {

		console.log("checkDockerImageExists");

		var deferred = q.defer();

		var command = "docker images -q " + self.dockerImage;

		exec(command, function(error, stdout, stderr) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				//
				// if docker image found
				if (stdout) {
					deferred.resolve();
				} else // container not found
				{
					deferred.reject(sandboxError.errordockerimage);
				}
			}
		})

		return deferred.promise;
	}
	//
	// create user's temp directory where files will be saved
	//
	function createTempDirectory() {
		console.log("createTempDirectory");

		var deferred = q.defer();

		//
		// each user will have its own directory path where code will be saved
		// make that directory
		//
		exec("mkdir -p " +  self.fullPathToTemp, function(error) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		})

		return deferred.promise;
	};

	//
	// copy script.sh file to the user's directory
	//
	function copyScriptExecutionFile() {
		console.log("copyScriptExecutionFile");

		var deferred = q.defer();

		var command = "cp " + self.currentWorkingPath + "/bashscripts/* " + self.fullPathToTemp;

		exec(command, function(error) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		})

		return deferred.promise;
	};

	//
	// write user entered code to a file
	//
	function writeUserCodeToFile() {
		console.log("writeUserCodeToFile");

		var deferred = q.defer();

		var userFile = self.fullPathToTemp + "/" + self.fileName;

		fs.writeFile(userFile, self.usercode, function(error) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		});

		return deferred.promise;

	}

	//
	// set permissions on the file
	//
	function setPermissionsToFile() {
		console.log("setPermissionsToFile");

		var deferred = q.defer();

		//
		// set permissions on the user's file
		//
		var command = "chmod 777 \'" + self.fullPathToTemp + "/" + self.fileName + "\'";

		exec(command, function(error){
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		})

		return deferred.promise;
	};

	//
	// write standard input to a file
	//
	function writeStdInputToFile() {
		console.log("writeStdInputToFile");

		var deferred = q.defer();

		var userStanardInputFile = self.fullPathToTemp + "/inputFile";

		fs.writeFile(userStanardInputFile, self.standardInput, function(error) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		});

		return deferred.promise;

	}

	//
	// main run method
	//
	function run(success) {

		checkDockerImageExists()
			.then(createTempDirectory)
			.then(copyScriptExecutionFile)
			.then(writeUserCodeToFile)
			.then(setPermissionsToFile)
			.then(writeStdInputToFile)
			.then(runDocker)
			.then(checkForCompleted)
			.then(function(compilationDetails) {
				console.log(compilationDetails);
				success(compilationDetails.error,
					compilationDetails.data,
					compilationDetails.compilationerrors)
			})
			.catch(function(error) {
				console.log(sandboxError.genericpromise + error);
				success(error, null);
			})
			.done();

	};

	//
	// run docker container
	//
	function runDocker() {
		console.log("runDocker");
		//
		// run docker command using docker timeout script and script.sh file
		//

		   dockerRunCommand = self.currentWorkingPath + '/dockertimeout.sh ' +  self.timeoutValue + 's' +
			' -i -t -v  "' + self.fullPathToTemp + '":/mountfolder ' + self.dockerImage +
			' /mountfolder/script.sh ' + self.compilerName + ' ' + self.fileName +
		    ' ' + self.outputCommand + ' ' + self.extraArguments;

		console.log("Command to execute:" + dockerRunCommand +
			" language id: " + self.languageid);

		var deferred = q.defer();
		//
		// execute the Docker
		//
		exec(dockerRunCommand, function(error, stdout, stderr) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		});

		return deferred.promise;

	}

	function checkForCompleted() {

		console.log("checkForCompleted");

		var timerCount = 0; //variable to enforce the timeout_value

		var deferred = q.defer();

		//
		// check for file named "completed" after 1 second interval
		//
		var intid = setInterval(function() {

			timerCount = timerCount + 1;

			fs.readFile(self.currentWorkingPath + self.tempFolder + '/completed', 'utf8', function(err, data) {

				//
				// if file is not available yet and the file interval is not yet up continue
				//
				if (err && timerCount < self.timeoutValue) {
					console.log(err);
					return;
				}
				//
				// if file is found simply display a message and proceed
				//
				else if (timerCount < self.timeoutValue) {

					//
					// check for any errors
					//
					fs.readFile(self.fullPathToTemp + '/errors', 'utf8', function(err2, compilationerrors) {
						if (!compilationerrors) compilationerrors = ""

						var lines = data.toString().split('*-COMPILEBOX::ENDOFOUTPUT-*');
						data = lines[0];
						var time = lines[1];

						deferred.resolve({
							error: compilationerrors.length > 0 ? new Error() : null,
							data: data,
							time: time,
							compilationerrors: compilationerrors
						});

						//success(null, data, time, compilationerrors)
					});
				}
				//
				// if time is up. Save an error message to the data variable
				//
				else {
					//
					// Since the time is up, we take the partial output and return it.
					//
					fs.readFile(self.fullPathToTemp + '/logfile.txt', 'utf8', function(err, data) {
						if (!data) data = "";
						data += "\nExecution Timed Out";

						fs.readFile(self.fullPathToTemp + '/errors', 'utf8', function(err2, compilationerrors) {
							if (!compilationerrors) compilationerrors = "";

							var lines = data.toString().split('*---*');
							data = lines[0];
							var time = lines[1];

							deferred.resolve({
								error: compilationerrors.length > 0 ? new Error() : null,
								data: data,
								time: time,
								compilationerrors: compilationerrors
							});

						});
					});

				}

				//
				// remove the temp user directory
				//
				// exec("rm -r " + self.fullPathToTemp, function(err, data) {
				// 	if (err) {
				// 		console.log(sandboxError.errorremovingtemp);

				// 		deferred.reject({
				// 				error: err,
				// 				data: null,
				// 				time: null,
				// 				compilationerrors: null
				// 		});

				// 	} else {
				// 		//console.log("Success..");
				// 	}
				// });

				clearInterval(intid);
			});
		}, 1000);

		return deferred.promise;
	}

	//
	// this is our only public function
	//
	return {
		run: run
	}
};

module.exports = sandbox;
<commit_msg>remove temp directory<commit_after>//
// This is our main object that will be responsible for collecting
// information from user request and running docker container
//
var sandbox = function(sandboxData) {

	var exec = require('child_process').exec;
	var q = require('q');
	var fs = require('fs');
	var path = require('path');
	var constants   =  require(path.resolve('./modules/common/constants.js'));
    var sandboxError   =  require(path.resolve('./modules/common/sandboxerror.js'));

	var self = this;

	this.usercode = sandboxData.usercode;
	this.languageid = sandboxData.languageid;
	this.tempFolder = sandboxData.tempFolder;
	this.currentWorkingPath = sandboxData.currentWorkingPath;
	this.compilerName = sandboxData.compilerName;
	this.fileName = sandboxData.fileName;
	this.outputCommand = sandboxData.outputCommand;
	this.languageName = sandboxData.languageName;
	this.extraArguments = sandboxData.extraArguments;
	this.standardInput = sandboxData.standardInput;
	this.dockerImage = constants.dockerImage;

	this.fullPathToTemp = this.currentWorkingPath + this.tempFolder;

	this.timeoutValue = 20;

	//
	// check of docker image exists before we do anything further
	//
	function checkDockerImageExists() {

		console.log("checkDockerImageExists");

		var deferred = q.defer();

		var command = "docker images -q " + self.dockerImage;

		exec(command, function(error, stdout, stderr) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				//
				// if docker image found
				if (stdout) {
					deferred.resolve();
				} else // container not found
				{
					deferred.reject(sandboxError.errordockerimage);
				}
			}
		})

		return deferred.promise;
	}
	//
	// create user's temp directory where files will be saved
	//
	function createTempDirectory() {
		console.log("createTempDirectory");

		var deferred = q.defer();

		//
		// each user will have its own directory path where code will be saved
		// make that directory
		//
		exec("mkdir -p " +  self.fullPathToTemp, function(error) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		})

		return deferred.promise;
	};

	//
	// copy script.sh file to the user's directory
	//
	function copyScriptExecutionFile() {
		console.log("copyScriptExecutionFile");

		var deferred = q.defer();

		var command = "cp " + self.currentWorkingPath + "/bashscripts/* " + self.fullPathToTemp;

		exec(command, function(error) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		})

		return deferred.promise;
	};

	//
	// write user entered code to a file
	//
	function writeUserCodeToFile() {
		console.log("writeUserCodeToFile");

		var deferred = q.defer();

		var userFile = self.fullPathToTemp + "/" + self.fileName;

		fs.writeFile(userFile, self.usercode, function(error) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		});

		return deferred.promise;

	}

	//
	// set permissions on the file
	//
	function setPermissionsToFile() {
		console.log("setPermissionsToFile");

		var deferred = q.defer();

		//
		// set permissions on the user's file
		//
		var command = "chmod 777 \'" + self.fullPathToTemp + "/" + self.fileName + "\'";

		exec(command, function(error){
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		})

		return deferred.promise;
	};

	//
	// write standard input to a file
	//
	function writeStdInputToFile() {
		console.log("writeStdInputToFile");

		var deferred = q.defer();

		var userStanardInputFile = self.fullPathToTemp + "/inputFile";

		fs.writeFile(userStanardInputFile, self.standardInput, function(error) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		});

		return deferred.promise;

	}

	//
	// main run method
	//
	function run(success) {

		checkDockerImageExists()
			.then(createTempDirectory)
			.then(copyScriptExecutionFile)
			.then(writeUserCodeToFile)
			.then(setPermissionsToFile)
			.then(writeStdInputToFile)
			.then(runDocker)
			.then(checkForCompleted)
			.then(function(compilationDetails) {
				console.log(compilationDetails);
				success(compilationDetails.error,
					compilationDetails.data,
					compilationDetails.compilationerrors)
			})
			.catch(function(error) {
				console.log(sandboxError.genericpromise + error);
				success(error, null);
			})
			.done();

	};

	//
	// run docker container
	//
	function runDocker() {
		console.log("runDocker");
		//
		// run docker command using docker timeout script and script.sh file
		//

		   dockerRunCommand = self.currentWorkingPath + '/dockertimeout.sh ' +  self.timeoutValue + 's' +
			' -i -t -v  "' + self.fullPathToTemp + '":/mountfolder ' + self.dockerImage +
			' /mountfolder/script.sh ' + self.compilerName + ' ' + self.fileName +
		    ' ' + self.outputCommand + ' ' + self.extraArguments;

		console.log("Command to execute:" + dockerRunCommand +
			" language id: " + self.languageid);

		var deferred = q.defer();
		//
		// execute the Docker
		//
		exec(dockerRunCommand, function(error, stdout, stderr) {
			if (error) {
				deferred.reject(error + new Error(error.stack || error));
			} else {
				deferred.resolve();
			}
		});

		return deferred.promise;

	}

	function checkForCompleted() {

		console.log("checkForCompleted");

		var timerCount = 0; //variable to enforce the timeout_value

		var deferred = q.defer();

		//
		// check for file named "completed" after 1 second interval
		//
		var intid = setInterval(function() {

			timerCount = timerCount + 1;

			fs.readFile(self.currentWorkingPath + self.tempFolder + '/completed', 'utf8', function(err, data) {

				//
				// if file is not available yet and the file interval is not yet up continue
				//
				if (err && timerCount < self.timeoutValue) {
					console.log(err);
					return;
				}
				//
				// if file is found simply display a message and proceed
				//
				else if (timerCount < self.timeoutValue) {

					//
					// check for any errors
					//
					fs.readFile(self.fullPathToTemp + '/errors', 'utf8', function(err2, compilationerrors) {
						if (!compilationerrors) compilationerrors = ""

						var lines = data.toString().split('*-COMPILEBOX::ENDOFOUTPUT-*');
						data = lines[0];
						var time = lines[1];

						deferred.resolve({
							error: compilationerrors.length > 0 ? new Error() : null,
							data: data,
							time: time,
							compilationerrors: compilationerrors
						});

						//success(null, data, time, compilationerrors)
					});
				}
				//
				// if time is up. Save an error message to the data variable
				//
				else {
					//
					// Since the time is up, we take the partial output and return it.
					//
					fs.readFile(self.fullPathToTemp + '/logfile.txt', 'utf8', function(err, data) {
						if (!data) data = "";
						data += "\nExecution Timed Out";

						fs.readFile(self.fullPathToTemp + '/errors', 'utf8', function(err2, compilationerrors) {
							if (!compilationerrors) compilationerrors = "";

							var lines = data.toString().split('*---*');
							data = lines[0];
							var time = lines[1];

							deferred.resolve({
								error: compilationerrors.length > 0 ? new Error() : null,
								data: data,
								time: time,
								compilationerrors: compilationerrors
							});

						});
					});

				}

				//
				// remove the temp user directory
				//
				exec("rm -r " + self.fullPathToTemp, function(err, data) {
					if (err) {
						console.log(sandboxError.errorremovingtemp);

						deferred.reject({
								error: err,
								data: null,
								time: null,
								compilationerrors: null
						});

					} else {
						//console.log("Success..");
					}
				});

				clearInterval(intid);
			});
		}, 1000);

		return deferred.promise;
	}

	//
	// this is our only public function
	//
	return {
		run: run
	}
};

module.exports = sandbox;
<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function(grunt) {

    // Project configuration.
    grunt.initConfig({
        meta: {
            version: 'v0.5.1',
            banner: '/**\n\
 * enchant.js <%= meta.version %>\n\
 *\n\
 * Copyright (c) Ubiquitous Entertainment Inc.\n\
 * Dual licensed under the MIT or GPL Version 3 licenses\n\
 *\n\
 * Permission is hereby granted, free of charge, to any person obtaining a copy\n\
 * of this software and associated documentation files (the "Software"), to deal\n\
 * in the Software without restriction, including without limitation the rights\n\
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n\
 * copies of the Software, and to permit persons to whom the Software is\n\
 * furnished to do so, subject to the following conditions:\n\
 *\n\
 * The above copyright notice and this permission notice shall be included in\n\
 * all copies or substantial portions of the Software.\n\
 *\n\
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n\
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n\
 * THE SOFTWARE.\n\
 *\n\
 * This program is free software: you can redistribute it and/or modify\n\
 * it under the terms of the GNU General Public License as published by\n\
 * the Free Software Foundation, either version 3 of the License, or\n\
 * (at your option) any later version.\n\
 *\n\
 * This program is distributed in the hope that it will be useful,\n\
 * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
 * GNU General Public License for more details.\n\
 *\n\
 * You should have received a copy of the GNU General Public License\n\
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\
 */',
            min_banner: '/* enchant.js <%= meta.version %> http://enchantjs.com Licensed under MIT or GPLv3. (c) Ubiquitous Entertainment Inc. */'
        },
        lint: {
            files: ['dev/header.js', 'dev/src/*.js']
        },
        qunit: {
            files: ['qunit/*/index.html']
        },
        concat: {
            dist: {
                src: ['<banner:meta.banner>',
                    'dev/src/_header.js',
                    'dev/src/Class.js',
                    'dev/src/Env.js',
                    'dev/src/Event.js',
                    'dev/src/EventTarget.js',
                    'dev/src/Game.js',
                    'dev/src/Node.js',
                    'dev/src/Entity.js',
                    'dev/src/Sprite.js',
                    'dev/src/Label.js',
                    'dev/src/Map.js',
                    'dev/src/Group.js',
                    'dev/src/RGroup.js',
                    'dev/src/CanvasGroup.js',
                    'dev/src/Scene.js',
                    'dev/src/Surface.js',
                    'dev/src/Sound.js'
                ],
                dest: 'dev/enchant.js'
            }
        },
        min: {
            dist: {
                src: ['<banner:meta.min_banner>', 'dev/enchant.js'],
                dest: 'enchant.min.js'
            }
        },
        watch: {
            files: '<config:concat.dist.src>',
            tasks: 'concat min'
        },
        jshint: {
            options: {
                curly: true,
                eqeqeq: true,
                immed: true,
                latedef: true,
                newcap: true,
                noarg: true,
                sub: true,
                undef: true,
                boss: true,
                eqnull: true,
                browser: true,
                proto: true
            },
            globals: {
                enchant: true
            }
        },
        uglify: {}
    });

    // Default task.
    grunt.registerTask('default', 'qunit concat min lint');
};
<commit_msg>add lang task for grunt.js<commit_after>/*global module:false*/

module.exports = function(grunt) {
    grunt.loadNpmTasks('grunt-exec');

    // Project configuration.
    grunt.initConfig({
        meta: {
            version: 'v0.5.1',
            banner: '/**\n\
 * enchant.js <%= meta.version %>\n\
 *\n\
 * Copyright (c) Ubiquitous Entertainment Inc.\n\
 * Dual licensed under the MIT or GPL Version 3 licenses\n\
 *\n\
 * Permission is hereby granted, free of charge, to any person obtaining a copy\n\
 * of this software and associated documentation files (the "Software"), to deal\n\
 * in the Software without restriction, including without limitation the rights\n\
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n\
 * copies of the Software, and to permit persons to whom the Software is\n\
 * furnished to do so, subject to the following conditions:\n\
 *\n\
 * The above copyright notice and this permission notice shall be included in\n\
 * all copies or substantial portions of the Software.\n\
 *\n\
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n\
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n\
 * THE SOFTWARE.\n\
 *\n\
 * This program is free software: you can redistribute it and/or modify\n\
 * it under the terms of the GNU General Public License as published by\n\
 * the Free Software Foundation, either version 3 of the License, or\n\
 * (at your option) any later version.\n\
 *\n\
 * This program is distributed in the hope that it will be useful,\n\
 * but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n\
 * GNU General Public License for more details.\n\
 *\n\
 * You should have received a copy of the GNU General Public License\n\
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\
 */',
            min_banner: '/* enchant.js <%= meta.version %> http://enchantjs.com Licensed under MIT or GPLv3. (c) Ubiquitous Entertainment Inc. */'
        },
        lint: {
            files: ['dev/header.js', 'dev/src/*.js']
        },
        qunit: {
            files: ['qunit/*/index.html']
        },
        concat: {
            dist: {
                src: ['<banner:meta.banner>',
                    'dev/src/_header.js',
                    'dev/src/Class.js',
                    'dev/src/Env.js',
                    'dev/src/Event.js',
                    'dev/src/EventTarget.js',
                    'dev/src/Game.js',
                    'dev/src/Node.js',
                    'dev/src/Entity.js',
                    'dev/src/Sprite.js',
                    'dev/src/Label.js',
                    'dev/src/Map.js',
                    'dev/src/Group.js',
                    'dev/src/RGroup.js',
                    'dev/src/CanvasGroup.js',
                    'dev/src/Scene.js',
                    'dev/src/Surface.js',
                    'dev/src/Sound.js'
                ],
                dest: 'dev/enchant.js'
            }
        },
        min: {
            dist: {
                src: ['<banner:meta.min_banner>', 'dev/enchant.js'],
                dest: 'enchant.min.js'
            }
        },
        watch: {
            files: '<config:concat.dist.src>',
            tasks: 'concat min'
        },
        jshint: {
            options: {
                curly: true,
                eqeqeq: true,
                immed: true,
                latedef: true,
                newcap: true,
                noarg: true,
                sub: true,
                undef: true,
                boss: true,
                eqnull: true,
                browser: true,
                proto: true
            },
            globals: {
                enchant: true
            }
        },
        exec: {
            lang: {
                command: 'rake lang'
            },
            doc: {
                command: 'rake doc'
            }
        }
    });

    // Default task.
    grunt.registerTask('default', 'lint qunit concat min exec:lang');
};
<|endoftext|>


<commit_before>/*
Run to enable this:

jupyter serverextension enable --py jupyter_notebook_gist
jupyter nbextension install --py jupyter_notebook_gist
jupyter nbextension enable --py jupyter_notebook_gist
*/
function get_base_path() {
    var loc = window.location;
    var proto = loc.protocol;
    var host = loc.hostname;
    var port = loc.port;

    var base = proto + "//" + host;
    if (parseInt(port) != 80) {
        base += ":" + port;
    }
    return base;
}

function url_path_split(path) {
    var idx = path.lastIndexOf('/');
    if (idx === -1) {
        return ['', path];
    } else {
        return [ path.slice(0, idx), path.slice(idx + 1) ];
    }
}

function is_url_valid(url) {
    return /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(url);
}

define([
    'base/js/utils',
    'moment'
], function (utils, moment) {
    var github_redirect_uri = get_base_path() + "/create_gist";
    var gist_notebook = function () {
        // Save the notebook and create a checkpoint to ensure that we create
        // the gist using the most up-to-date content
        Jupyter.notebook.save_checkpoint();

        var github_client_id = Jupyter.notebook.config.data.oauth_client_id;
        // Get notebook path and encode it in base64
        // Characters like # get decoded by the github API and will mess up
        // getting the file path on the server if we use URI percent encoding,
        // so we use base64 instead
        var nb_path = window.btoa(Jupyter.notebook.base_url + Jupyter.notebook.notebook_path);

        // Start OAuth dialog
        window.open("https://github.com/login/oauth/authorize?client_id=" + github_client_id +
          "&scope=gist&redirect_uri=" + github_redirect_uri + "?nb_path=" + nb_path);
    };

    var load_from_url = function() {
        var url = prompt("Enter the URL to a Gist or a .ipynb.");
        if (url == "" || url == null) {
            // prompt() returns "" if empty value, or null
            // if user clicked cancel, want to abort in either case
            return;
        }
        if (!is_url_valid(url)) {
            alert('Invalid URL.');
            return;
        }
        var parser = document.createElement('a');
        parser.href = url;
        if (parser.hostname.indexOf('gist.github.com') > -1) {
            // this is a gist URL, extract the raw_url for the .ipynb file
            load_from_gist_url(url);
        } else if (url.indexOf('.ipynb', url.length - '.ipynb'.length) !== -1) {
            // URL is a raw .ipynb file
            var nb_pathname_parts = parser.pathname.split('/');
            var filename = decodeURIComponent(nb_pathname_parts[nb_pathname_parts.length - 1]);
            download_nb_on_server(url, filename, false);
        }
    }

    var load_from_gist_url = function(url) {
        // this is a gist URL, extract the raw_url for the .ipynb file
        var gist_url_parts = url.split('/');
        var gist_id = gist_url_parts[gist_url_parts.length-1];

        var gist_api_url = "https://api.github.com/gists/" + gist_id;

        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (xhr.readyState == XMLHttpRequest.DONE) {
                if (xhr.status == 200) {
                    var res = JSON.parse(xhr.responseText);
                    for (var filename in res.files) {
                        if (!res.files.hasOwnProperty(filename)) continue;
                        if (filename.endsWith('.ipynb')) {
                            download_nb_on_server(res.files[filename].raw_url, filename, false);
                        }
                    }
                    console.log(res);
                } else if (xhr.status == 404) {
                    alert("Gist not found")
                } else {
                    alert("Couldn't load Gist.")
                }
            }
        }
        xhr.open("GET", gist_api_url, true);
        xhr.send(null);
    }

    var download_nb_on_server = function(url, name, force_download) {
        var xhr = new XMLHttpRequest();
        var nb_info = {
            nb_url: url,
            nb_name: window.btoa(name),
            force_download: force_download
        }
        xhr.open("POST",  "/download_notebook", true);
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.onload = function () {
            if (xhr.status == 409) {
                // 409 Conflict
                // used if file already exists
                var newname = prompt("File already exists. Please enter a new name.\nNote: This may overwrite existing files.",
                                     name);
                if (newname == "" || newname == null) {
                    // prompt() returns "" if empty value, or null
                    // if user clicked cancel, want to abort in either case
                    return;
                }
                download_nb_on_server(url, newname, true);
            } else if (xhr.status == 200) {
                window.open(url_path_split(Jupyter.notebook.notebook_path)[0] + encodeURIComponent(this.responseText));
            } else if (xhr.status == 400) {
                alert("File did not download");
            }
        };
        xhr.send(JSON.stringify(nb_info));
    }

    var load_public_user_gists = function() {
        // TODO: Figure out how to deal with page redirect when obtaining GitHub access code
        // For now, prompt user for their GitHub username to load their public gists
        var github_username = prompt("Please enter your GitHub username in order to retrieve your public gists.");
        if (github_username == "" || github_username == null) {
            // Do not send a request if user did not input anything
            return;
        };

        var gist_api_url = "https://api.github.com/users/" + github_username + "/gists";

        if (!is_url_valid(gist_api_url)) {
            alert('GitHub username is invalid.');
        };

        var xhr = new XMLHttpRequest();
        xhr.open("GET", gist_api_url, true);
        xhr.setRequestHeader("Content-Type", "application/json");
        xhr.onload = function(){
            Jupyter.dialog.modal({
                title: "Gists",
                body: format_user_gists(xhr.responseText),
                buttons: {
                    "OK": {}
                }
            });
        };
        xhr.send(null);
    };

    // Listen for the response message containing the user's gists
    // that is sent from the LoadGistHandler
    var auth_window;
    window.addEventListener('message', function(event) {
        if (event.origin != get_base_path()) return;
        auth_window.close();
        Jupyter.dialog.modal({
            title: "All User Gists",
            body: format_user_gists(window.atob(event.data)),
            buttons: {
                "OK": {}
            }
        })
    });

    var load_all_user_gists = function () {
        var redirect_uri = get_base_path() + "/load_user_gists"

        var github_client_id = Jupyter.notebook.config.data.oauth_client_id;
        var nb_path = window.btoa(Jupyter.notebook.base_url + Jupyter.notebook.notebook_path);

        auth_window = window.open("https://github.com/login/oauth/authorize?client_id=" + github_client_id +
                                  "&scope=gist&redirect_uri=" + redirect_uri, "", "width=550, height=500");
    };

    var format_user_gists = function(responseText) {
        var body = $('
').attr({class: "table", id: "my_table"});
        var head = $('
');
        var header = $('
').addClass("row list_header");
        header.append("Filename	");
        header.append("Description	");
        header.append("Last Updated	");
        header.append("Open Notebook	");
        head.append(header);
        body.append(head);
        var row, button, files, last_updated, pretty_date;
        var json_response = JSON.parse(responseText);
        // create flag to check if a notebook has been loaded
        var notebook_loaded = false;

        for (var i = 0; i < json_response.length; i++) {
            files = json_response[i].files;
            // Only load notebook gists
            if (!files[Object.keys(files)[0]].filename.endsWith('.ipynb')) continue;
            notebook_loaded = true;

            // Use same date formatting as SaveWidget's _render_checkpoint
            last_updated = moment(json_response[i].updated_at);
            var tdelta = Math.ceil(new Date() - last_updated);
            if (tdelta < utils.time.milliseconds.d) {
                // less than 24 hours old, use relative date
                pretty_date = last_updated.fromNow();
            } else {
                // otherwise show calendar
                // <Today | yesterday|...> at hh,mm,ss
                pretty_date = last_updated.calendar();
            }

            // Create row containing gist information
            row = $('
').addClass("list_item row");
            row.append("" + files[Object.keys(files)[0]].filename + "	");
            row.append("" + json_response[i].description + "	");
            row.append("" + pretty_date + "	");
            // Create button to load notebook
            button_td = $('');
            button = $('<button>Open</button>').addClass("btn btn-default btn-sm");
            button.click({url: json_response[i].html_url}, load_gist_from_click);
            button.appendTo(button_td);
            row.append(button_td);
            body.append(row);
        };

        // Inform user if no public notebooks were found
        if (!notebook_loaded) {
            row = $('
').addClass("list_item row");
            row_message = $('').attr("colspan", "4");
            row_message.text('No public notebooks found.');
            row.append(row_message);
            body.append(row);
        }

        return body;
    };

    var load_gist_from_click = function(event) {
        var url = event.data.url;
        load_from_gist_url(url);
    };

    var setup_info = function() {
        Jupyter.dialog.modal({
            title: "Configuration Incomplete",
            body: "You haven't configured your GitHub Client ID in your jupyter_notebook_config.py file. Please set the Client ID and Secret before using this plugin. See the README for more info.",
            buttons: {
                "OK": {}
            },
            sanitize: false
        });
    }

    var is_valid_client_id = function(client_id) {
        if (client_id === "my_client_id" || client_id === null || client_id === undefined) {
            return false;
        }
        return true;
    }

    var gist_button = function () {
        if (!Jupyter.toolbar) {
            $([Jupyter.events]).on("app_initialized.NotebookApp", gist_button);
            return;
        }

        if (!is_valid_client_id(Jupyter.notebook.config.data.oauth_client_id)) {
            Jupyter.toolbar.add_buttons_group([{
                'label':    'jupyter-notebook-gist setup',
                'icon':     'fa-github',
                'callback': setup_info,
                'id':       'setup_info'
            }]);

            return;
        }

        if ($("#gist_notebook").length === 0) {
            Jupyter.toolbar.add_buttons_group([
                {
                    'label'   : 'save notebook as gist',
                    'icon'    : 'fa-github',
                    'callback': gist_notebook,
                    'id'      : 'gist_notebook'
                }, {
                    'label'   : 'load notebook from URL',
                    'icon'    : 'fa-link',
                    'callback': load_from_url,
                    'id'      : 'load_notebook_from_url'
                }, {
                    'label'   : 'load public user gists',
                    'icon'    : 'fa-list-alt',
                    'callback': load_public_user_gists,
                    'id'      : 'load_public_user_gists',
                }, {
                    'label'   : 'load all user gists',
                    'icon'    : 'fa-list',
                    'callback': load_all_user_gists,
                    'id'      : 'load_all_user_gists',
                }
            ]);
        }
    };

    var load_ipython_extension = function () {
        gist_button();
    };

    return {
        load_ipython_extension: load_ipython_extension
    };
});
<commit_msg>Require Jupyter JavaScript from base namespace instead of using global object<commit_after>/*
Run to enable this:

jupyter serverextension enable --py jupyter_notebook_gist
jupyter nbextension install --py jupyter_notebook_gist
jupyter nbextension enable --py jupyter_notebook_gist
*/
function get_base_path() {
    var loc = window.location;
    var proto = loc.protocol;
    var host = loc.hostname;
    var port = loc.port;

    var base = proto + "//" + host;
    if (parseInt(port) != 80) {
        base += ":" + port;
    }
    return base;
}

function url_path_split(path) {
    var idx = path.lastIndexOf('/');
    if (idx === -1) {
        return ['', path];
    } else {
        return [ path.slice(0, idx), path.slice(idx + 1) ];
    }
}

function is_url_valid(url) {
    return /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(url);
}

define([
    'base/js/namespace',
    'base/js/utils',
    'moment'
], function (Jupyter, utils, moment) {
    var github_redirect_uri = get_base_path() + "/create_gist";
    var gist_notebook = function () {
        // Save the notebook and create a checkpoint to ensure that we create
        // the gist using the most up-to-date content
        Jupyter.notebook.save_checkpoint();

        var github_client_id = Jupyter.notebook.config.data.oauth_client_id;
        // Get notebook path and encode it in base64
        // Characters like # get decoded by the github API and will mess up
        // getting the file path on the server if we use URI percent encoding,
        // so we use base64 instead
        var nb_path = window.btoa(Jupyter.notebook.base_url + Jupyter.notebook.notebook_path);

        // Start OAuth dialog
        window.open("https://github.com/login/oauth/authorize?client_id=" + github_client_id +
          "&scope=gist&redirect_uri=" + github_redirect_uri + "?nb_path=" + nb_path);
    };

    var load_from_url = function() {
        var url = prompt("Enter the URL to a Gist or a .ipynb.");
        if (url == "" || url == null) {
            // prompt() returns "" if empty value, or null
            // if user clicked cancel, want to abort in either case
            return;
        }
        if (!is_url_valid(url)) {
            alert('Invalid URL.');
            return;
        }
        var parser = document.createElement('a');
        parser.href = url;
        if (parser.hostname.indexOf('gist.github.com') > -1) {
            // this is a gist URL, extract the raw_url for the .ipynb file
            load_from_gist_url(url);
        } else if (url.indexOf('.ipynb', url.length - '.ipynb'.length) !== -1) {
            // URL is a raw .ipynb file
            var nb_pathname_parts = parser.pathname.split('/');
            var filename = decodeURIComponent(nb_pathname_parts[nb_pathname_parts.length - 1]);
            download_nb_on_server(url, filename, false);
        }
    }

    var load_from_gist_url = function(url) {
        // this is a gist URL, extract the raw_url for the .ipynb file
        var gist_url_parts = url.split('/');
        var gist_id = gist_url_parts[gist_url_parts.length-1];

        var gist_api_url = "https://api.github.com/gists/" + gist_id;

        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
            if (xhr.readyState == XMLHttpRequest.DONE) {
                if (xhr.status == 200) {
                    var res = JSON.parse(xhr.responseText);
                    for (var filename in res.files) {
                        if (!res.files.hasOwnProperty(filename)) continue;
                        if (filename.endsWith('.ipynb')) {
                            download_nb_on_server(res.files[filename].raw_url, filename, false);
                        }
                    }
                    console.log(res);
                } else if (xhr.status == 404) {
                    alert("Gist not found")
                } else {
                    alert("Couldn't load Gist.")
                }
            }
        }
        xhr.open("GET", gist_api_url, true);
        xhr.send(null);
    }

    var download_nb_on_server = function(url, name, force_download) {
        var xhr = new XMLHttpRequest();
        var nb_info = {
            nb_url: url,
            nb_name: window.btoa(name),
            force_download: force_download
        }
        xhr.open("POST",  "/download_notebook", true);
        xhr.setRequestHeader('Content-Type', 'application/json');
        xhr.onload = function () {
            if (xhr.status == 409) {
                // 409 Conflict
                // used if file already exists
                var newname = prompt("File already exists. Please enter a new name.\nNote: This may overwrite existing files.",
                                     name);
                if (newname == "" || newname == null) {
                    // prompt() returns "" if empty value, or null
                    // if user clicked cancel, want to abort in either case
                    return;
                }
                download_nb_on_server(url, newname, true);
            } else if (xhr.status == 200) {
                window.open(url_path_split(Jupyter.notebook.notebook_path)[0] + encodeURIComponent(this.responseText));
            } else if (xhr.status == 400) {
                alert("File did not download");
            }
        };
        xhr.send(JSON.stringify(nb_info));
    }

    var load_public_user_gists = function() {
        // TODO: Figure out how to deal with page redirect when obtaining GitHub access code
        // For now, prompt user for their GitHub username to load their public gists
        var github_username = prompt("Please enter your GitHub username in order to retrieve your public gists.");
        if (github_username == "" || github_username == null) {
            // Do not send a request if user did not input anything
            return;
        };

        var gist_api_url = "https://api.github.com/users/" + github_username + "/gists";

        if (!is_url_valid(gist_api_url)) {
            alert('GitHub username is invalid.');
        };

        var xhr = new XMLHttpRequest();
        xhr.open("GET", gist_api_url, true);
        xhr.setRequestHeader("Content-Type", "application/json");
        xhr.onload = function(){
            Jupyter.dialog.modal({
                title: "Gists",
                body: format_user_gists(xhr.responseText),
                buttons: {
                    "OK": {}
                }
            });
        };
        xhr.send(null);
    };

    // Listen for the response message containing the user's gists
    // that is sent from the LoadGistHandler
    var auth_window;
    window.addEventListener('message', function(event) {
        if (event.origin != get_base_path()) return;
        auth_window.close();
        Jupyter.dialog.modal({
            title: "All User Gists",
            body: format_user_gists(window.atob(event.data)),
            buttons: {
                "OK": {}
            }
        })
    });

    var load_all_user_gists = function () {
        var redirect_uri = get_base_path() + "/load_user_gists"

        var github_client_id = Jupyter.notebook.config.data.oauth_client_id;
        var nb_path = window.btoa(Jupyter.notebook.base_url + Jupyter.notebook.notebook_path);

        auth_window = window.open("https://github.com/login/oauth/authorize?client_id=" + github_client_id +
                                  "&scope=gist&redirect_uri=" + redirect_uri, "", "width=550, height=500");
    };

    var format_user_gists = function(responseText) {
        var body = $('
').attr({class: "table", id: "my_table"});
        var head = $('
');
        var header = $('
').addClass("row list_header");
        header.append("Filename	");
        header.append("Description	");
        header.append("Last Updated	");
        header.append("Open Notebook	");
        head.append(header);
        body.append(head);
        var row, button, files, last_updated, pretty_date;
        var json_response = JSON.parse(responseText);
        // create flag to check if a notebook has been loaded
        var notebook_loaded = false;

        for (var i = 0; i < json_response.length; i++) {
            files = json_response[i].files;
            // Only load notebook gists
            if (!files[Object.keys(files)[0]].filename.endsWith('.ipynb')) continue;
            notebook_loaded = true;

            // Use same date formatting as SaveWidget's _render_checkpoint
            last_updated = moment(json_response[i].updated_at);
            var tdelta = Math.ceil(new Date() - last_updated);
            if (tdelta < utils.time.milliseconds.d) {
                // less than 24 hours old, use relative date
                pretty_date = last_updated.fromNow();
            } else {
                // otherwise show calendar
                // <Today | yesterday|...> at hh,mm,ss
                pretty_date = last_updated.calendar();
            }

            // Create row containing gist information
            row = $('
').addClass("list_item row");
            row.append("" + files[Object.keys(files)[0]].filename + "	");
            row.append("" + json_response[i].description + "	");
            row.append("" + pretty_date + "	");
            // Create button to load notebook
            button_td = $('');
            button = $('<button>Open</button>').addClass("btn btn-default btn-sm");
            button.click({url: json_response[i].html_url}, load_gist_from_click);
            button.appendTo(button_td);
            row.append(button_td);
            body.append(row);
        };

        // Inform user if no public notebooks were found
        if (!notebook_loaded) {
            row = $('
').addClass("list_item row");
            row_message = $('').attr("colspan", "4");
            row_message.text('No public notebooks found.');
            row.append(row_message);
            body.append(row);
        }

        return body;
    };

    var load_gist_from_click = function(event) {
        var url = event.data.url;
        load_from_gist_url(url);
    };

    var setup_info = function() {
        Jupyter.dialog.modal({
            title: "Configuration Incomplete",
            body: "You haven't configured your GitHub Client ID in your jupyter_notebook_config.py file. Please set the Client ID and Secret before using this plugin. See the README for more info.",
            buttons: {
                "OK": {}
            },
            sanitize: false
        });
    }

    var is_valid_client_id = function(client_id) {
        if (client_id === "my_client_id" || client_id === null || client_id === undefined) {
            return false;
        }
        return true;
    }

    var gist_button = function () {
        if (!Jupyter.toolbar) {
            $([Jupyter.events]).on("app_initialized.NotebookApp", gist_button);
            return;
        }

        if (!is_valid_client_id(Jupyter.notebook.config.data.oauth_client_id)) {
            Jupyter.toolbar.add_buttons_group([{
                'label':    'jupyter-notebook-gist setup',
                'icon':     'fa-github',
                'callback': setup_info,
                'id':       'setup_info'
            }]);

            return;
        }

        if ($("#gist_notebook").length === 0) {
            Jupyter.toolbar.add_buttons_group([
                {
                    'label'   : 'save notebook as gist',
                    'icon'    : 'fa-github',
                    'callback': gist_notebook,
                    'id'      : 'gist_notebook'
                }, {
                    'label'   : 'load notebook from URL',
                    'icon'    : 'fa-link',
                    'callback': load_from_url,
                    'id'      : 'load_notebook_from_url'
                }, {
                    'label'   : 'load public user gists',
                    'icon'    : 'fa-list-alt',
                    'callback': load_public_user_gists,
                    'id'      : 'load_public_user_gists',
                }, {
                    'label'   : 'load all user gists',
                    'icon'    : 'fa-list',
                    'callback': load_all_user_gists,
                    'id'      : 'load_all_user_gists',
                }
            ]);
        }
    };

    var load_ipython_extension = function () {
        gist_button();
    };

    return {
        load_ipython_extension: load_ipython_extension
    };
});
<|endoftext|>


<commit_before>import { props, define } from '@bolt/core/utils';
import { withLitHtml, html } from '@bolt/core/renderers/renderer-lit-html';
import { parse } from 'himalaya';

import classNames from 'classnames/bind';

import styles from './table.scss';
import schema from '../table.schema.yml';

let cx = classNames.bind(styles);

@define
class BoltTable extends withLitHtml() {
  static is = 'bolt-table';

  static props = {
    format: {
      ...props.string,
      ...{ default: 'regular' },
    },
    borderless: {
      ...props.boolean,
      ...{ default: false },
    },
    firstColFixedWidth: {
      ...props.boolean,
      ...{ default: false },
    },
  };

  // constructor(self) {
  //   self = super(self);
  //   self.useShadow = hasNativeShadowDomSupport;
  //   self.validate = ajv.compile(schema);
  //   return self;
  // }

  removeEmptyNodes(nodes) {
    return nodes.filter(node => {
      if (node.type === 'element') {
        node.children = this.removeEmptyNodes(node.children);
        return true;
      }
      return node.content.length;
    });
  }

  stripWhitespace(nodes) {
    return nodes.map(node => {
      if (node.type === 'element') {
        node.children = this.stripWhitespace(node.children);
      } else {
        node.content = node.content.trim();
      }
      return node;
    });
  }

  removeWhitespace(nodes) {
    return this.removeEmptyNodes(this.stripWhitespace(nodes));
  }

  createProp(object, prop, value) {
    if (object[`${prop}`] === undefined) {
      object[`${prop}`] = value;
    }
  }

  convertElements(element, object, parent = 'rows') {
    const boltedObject = object !== undefined ? object : {};

    element.map(element => {
      switch (element.tagName) {
        case 'thead':
          this.createProp(boltedObject, 'header', []);
          this.convertElements(element.children, boltedObject, 'header');
          break;
        case 'tbody':
          this.createProp(boltedObject, 'rows', []);
          this.convertElements(element.children, boltedObject, 'rows');
          break;
        case 'tfoot':
          this.createProp(boltedObject, 'footer', []);
          this.convertElements(element.children, boltedObject, 'footer');
          break;
        case 'tr':
          const elements = element.children.map(child => {
            const { type, children, ...partialObject } = child;

            const correctText =
              child.children[0] !== undefined ? child.children[0].content : '';

            const updatedChild = {
              text: correctText,
              ...partialObject,
            };

            return updatedChild;
          });

          boltedObject[`${parent}`].push(elements);
          break;
        default:
          this.convertElements(element.children, boltedObject);
      }
    });

    return boltedObject;
  }

  // setAttr(element, attribute, value, defaultValue) {
  //   value === ''
  //     ? element.setAttribute(attribute, defaultValue)
  //     : element.setAttribute(attribute, value);
  // }

  render() {
    const parseCode = this.removeWhitespace(parse(this.innerHTML));
    const { format, borderless, firstColFixedWidth } = this.props;
    console.log(format);
    const tableClasses = cx('c-bolt-table', {
      [`c-bolt-table--format-${format}`]: format !== 'regular',
      [`c-bolt-table--borderless`]: borderless,
      [`c-bolt-table--first-col-fixed-width`]: firstColFixedWidth,
    });
    const bodyClasses = cx('c-bolt-table__body');
    const headClasses = cx('c-bolt-table__head');
    const footClasses = cx('c-bolt-table__foot');
    const rowClasses = cx('c-bolt-table__row');
    const cellClasses = cx('c-bolt-table__cell');
    let boltTableMarkup = [];

    this.setAttribute('format', format);

    const boltTable = this.convertElements(parseCode);

    function setCellTag(item) {
      if (item.tagName === 'th') {
        return html`

            ${item.text}

        `;
      } else {
        return html`

            ${item.text}

        `;
      }
    }

    function setAttributes(element, attributes) {
      if (attributes.length > 0) {
        return attributes.map(attribute =>
          element.setAttribute(attribute.key, attribute.value),
        );
      }
    }

    if (boltTable.header) {
      boltTableMarkup.push(html`

          ${boltTable.header.map(
            row => html`

                ${row.map(
                  item =>
                    html`
                      ${setCellTag(item)}
                    `,
                )}

            `,
          )}

      `);
    }

    if (boltTable.rows) {
      boltTableMarkup.push(html`

          ${boltTable.rows.map(
            row => html`

                ${row.map(
                  item =>
                    html`
                      ${setCellTag(item)}
                    `,
                )}

            `,
          )}

      `);
    }

    if (boltTable.footer) {
      boltTableMarkup.push(html`

          ${boltTable.footer.map(
            row => html`

                ${row.map(
                  item =>
                    html`
                      ${setCellTag(item)}
                    `,
                )}

            `,
          )}

      `);
    }

    console.log('BT:', boltTable);
    console.log('BTM:', boltTableMarkup);

    return html`
      ${this.addStyles([styles])}

        ${boltTableMarkup}

    `;
  }
}

export { BoltTable };
<commit_msg>WIP(@bolt/components-table): create function for row generation<commit_after>import { props, define } from '@bolt/core/utils';
import { withLitHtml, html } from '@bolt/core/renderers/renderer-lit-html';
import { parse } from 'himalaya';

import classNames from 'classnames/bind';

import styles from './table.scss';
import schema from '../table.schema.yml';

let cx = classNames.bind(styles);

@define
class BoltTable extends withLitHtml() {
  static is = 'bolt-table';

  static props = {
    format: {
      ...props.string,
      ...{ default: 'regular' },
    },
    borderless: {
      ...props.boolean,
      ...{ default: false },
    },
    firstColFixedWidth: {
      ...props.boolean,
      ...{ default: false },
    },
  };

  // constructor(self) {
  //   self = super(self);
  //   self.useShadow = hasNativeShadowDomSupport;
  //   self.validate = ajv.compile(schema);
  //   return self;
  // }

  removeEmptyNodes(nodes) {
    return nodes.filter(node => {
      if (node.type === 'element') {
        node.children = this.removeEmptyNodes(node.children);
        return true;
      }
      return node.content.length;
    });
  }

  stripWhitespace(nodes) {
    return nodes.map(node => {
      if (node.type === 'element') {
        node.children = this.stripWhitespace(node.children);
      } else {
        node.content = node.content.trim();
      }
      return node;
    });
  }

  removeWhitespace(nodes) {
    return this.removeEmptyNodes(this.stripWhitespace(nodes));
  }

  createProp(object, prop, value) {
    if (object[`${prop}`] === undefined) {
      object[`${prop}`] = value;
    }
  }

  convertElements(element, object, parent = 'rows') {
    const boltedObject = object !== undefined ? object : {};

    element.map(element => {
      switch (element.tagName) {
        case 'thead':
          this.createProp(boltedObject, 'header', []);
          this.convertElements(element.children, boltedObject, 'header');
          break;
        case 'tbody':
          this.createProp(boltedObject, 'rows', []);
          this.convertElements(element.children, boltedObject, 'rows');
          break;
        case 'tfoot':
          this.createProp(boltedObject, 'footer', []);
          this.convertElements(element.children, boltedObject, 'footer');
          break;
        case 'tr':
          const elements = element.children.map(child => {
            const { type, children, ...partialObject } = child;

            const correctText =
              child.children[0] !== undefined ? child.children[0].content : '';

            const updatedChild = {
              text: correctText,
              ...partialObject,
            };

            return updatedChild;
          });

          boltedObject[`${parent}`].push(elements);
          break;
        default:
          this.convertElements(element.children, boltedObject);
      }
    });

    return boltedObject;
  }

  // setAttr(element, attribute, value, defaultValue) {
  //   value === ''
  //     ? element.setAttribute(attribute, defaultValue)
  //     : element.setAttribute(attribute, value);
  // }

  render() {
    const parseCode = this.removeWhitespace(parse(this.innerHTML));
    const { format, borderless, firstColFixedWidth } = this.props;
    console.log(format);
    const tableClasses = cx('c-bolt-table', {
      [`c-bolt-table--format-${format}`]: format !== 'regular',
      [`c-bolt-table--borderless`]: borderless,
      [`c-bolt-table--first-col-fixed-width`]: firstColFixedWidth,
    });
    const bodyClasses = cx('c-bolt-table__body');
    const headClasses = cx('c-bolt-table__head');
    const footClasses = cx('c-bolt-table__foot');
    const rowClasses = cx('c-bolt-table__row');
    const cellClasses = cx('c-bolt-table__cell');
    let boltTableMarkup = [];

    this.setAttribute('format', format);

    const boltTable = this.convertElements(parseCode);

    function setRowTag(row) {
      return html`

          ${row.map(
            item =>
              html`
                ${setCellTag(item)}
              `,
          )}

      `;
    }

    function setCellTag(item) {
      if (item.tagName === 'th') {
        return html`

            ${item.text}

        `;
      } else {
        return html`

            ${item.text}

        `;
      }
    }

    function setAttributes(element, attributes) {
      if (attributes.length > 0) {
        return attributes.map(attribute =>
          element.setAttribute(attribute.key, attribute.value),
        );
      }
    }

    if (boltTable.header) {
      boltTableMarkup.push(html`

          ${boltTable.header.map(
            row => html`
              ${setRowTag(row)}
            `,
          )}

      `);
    }

    if (boltTable.rows) {
      boltTableMarkup.push(html`

          ${boltTable.rows.map(
            row => html`
              ${setRowTag(row)}
            `,
          )}

      `);
    }

    if (boltTable.footer) {
      boltTableMarkup.push(html`

          ${boltTable.footer.map(
            row => html`
              ${setRowTag(row)}
            `,
          )}

      `);
    }

    console.log('BT:', boltTable);
    console.log('BTM:', boltTableMarkup);

    return html`
      ${this.addStyles([styles])}

        ${boltTableMarkup}

    `;
  }
}

export { BoltTable };
<|endoftext|>


<commit_before>// When grunt 0.4 is released, this will become a CoffeeScript file (Gruntfile.coffee).

module.exports = function (grunt) {

	grunt.initConfig({

		meta: {
			banner: '// ' + grunt.file.read('LICENSE').split('\n')[0]
		},

		coffee: {
			compile: {
				files: {
					'lib/strukt.js': 'lib/strukt.coffee',
					'spec/spec.js': 'spec/spec.coffee'
				}
			}
		},

		concat: {
			dist: {
				lib: ['<banner>', 'lib/strukt.js'],
				dest: 'lib/strukt.js'
			}
		},

		watch: {
			files: ['lib/strukt.coffee', 'spec/spec.coffee'],
			tasks: 'coffee'
		}

	})

	grunt.loadNpmTasks('grunt-contrib-coffee')

	grunt.registerTask('default', 'release')
	grunt.registerTask('release', 'coffee concat')
	grunt.registerTask('dev', 'coffee')

}<commit_msg>readd grunt-mocha<commit_after>// When grunt 0.4 is released, this will become a CoffeeScript file (Gruntfile.coffee).

module.exports = function (grunt) {

	grunt.initConfig({

		meta: {
			banner: '// ' + grunt.file.read('LICENSE').split('\n')[0]
		},

		coffee: {
			compile: {
				files: {
					'lib/strukt.js': 'lib/strukt.coffee',
					'spec/spec.js': 'spec/spec.coffee'
				}
			}
		},

		concat: {
			dist: {
				lib: ['<banner>', 'lib/strukt.js'],
				dest: 'lib/strukt.js'
			}
		},

		mocha: {
			all: {
				src: 'spec/index.html',
				run: true
			}
		},

		watch: {
			files: ['lib/strukt.coffee', 'spec/spec.coffee'],
			tasks: 'coffee'
		}

	})

	grunt.loadNpmTasks('grunt-contrib-coffee')
	grunt.loadNpmTasks('grunt-mocha')

	grunt.registerTask('dev', 'coffee')
	grunt.registerTask('test', 'mocha')
	grunt.registerTask('release', 'coffee concat')
	grunt.registerTask('default', 'release')

}<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({

    pasteup: {
      version: grunt.file.readJSON('versions').versions.pop(),
      dist: "build/deployable_artefact"
    },

    copy: {
      dist: {
        files: {
          "<%= pasteup.dist %>/js/lib/": "js/lib/**"
        }
      }
    },

    less: {
      production: {
        files: {
          "<%= pasteup.dist %>/<%= pasteup.version %>/css/core.pasteup.min.css": "less/core.pasteup.less",
          "<%= pasteup.dist %>/<%= pasteup.version %>/css/layout.pasteup.min.css": "less/layout.pasteup.less",
          "<%= pasteup.dist %>/<%= pasteup.version %>/css/pasteup.min.css": "less/pasteup.less"
        },
        options: {
          compress: true
        }
      }
    },

    requirejs: {
      compile: {
        options: {
          baseUrl: "js/modules",
          dir: "<%= pasteup.dist %>/<%= pasteup.version %>/js/modules",
          modules: [
            {
              name: "main"
            }
          ]
        }
      }
    },

    watch: {
      scripts: {
        files: 'js/**/*.js',
        tasks: ['requirejs']
      },
      less: {
        files: 'less/**/*.less',
        tasks: ['less']
      },
      docs: {
        files: ['build/templates/*.html', 'docs/**/*.html'],
        tasks: ['docs']
      }
    }

  });

  // Register the default task which does the full build.
  grunt.registerTask('default', 'less requirejs copy docs server watch');
  grunt.registerTask('build', 'less requirejs copy docs');

  // Load tasks.
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-requirejs');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadTasks('build');

};
<commit_msg>Add image directory to versioned deploy directory.<commit_after>/*global module:false*/
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({

    pasteup: {
      version: grunt.file.readJSON('versions').versions.pop(),
      dist: "build/deployable_artefact"
    },

    copy: {
      dist: {
        files: {
          "<%= pasteup.dist %>/js/lib/": "js/lib/**",
          "<%= pasteup.dist %>/<%= pasteup.version %>/i/": "i/**"
        }
      }
    },

    less: {
      production: {
        files: {
          "<%= pasteup.dist %>/<%= pasteup.version %>/css/core.pasteup.min.css": "less/core.pasteup.less",
          "<%= pasteup.dist %>/<%= pasteup.version %>/css/layout.pasteup.min.css": "less/layout.pasteup.less",
          "<%= pasteup.dist %>/<%= pasteup.version %>/css/pasteup.min.css": "less/pasteup.less"
        },
        options: {
          compress: true
        }
      }
    },

    requirejs: {
      compile: {
        options: {
          baseUrl: "js/modules",
          dir: "<%= pasteup.dist %>/<%= pasteup.version %>/js/modules",
          modules: [
            {
              name: "main"
            }
          ]
        }
      }
    },

    watch: {
      scripts: {
        files: 'js/**/*.js',
        tasks: ['requirejs']
      },
      less: {
        files: 'less/**/*.less',
        tasks: ['less']
      },
      docs: {
        files: ['build/templates/*.html', 'docs/**/*.html'],
        tasks: ['docs']
      }
    }

  });

  // Register the default task which does the full build.
  grunt.registerTask('default', 'less requirejs copy docs server watch');
  grunt.registerTask('build', 'less requirejs copy docs');

  // Load tasks.
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-requirejs');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadTasks('build');

};
<|endoftext|>


<commit_before>var f = require('util').format
  , Long = require('bson').Long;

exports['Should correctly connect using mongos object'] = {
  metadata: {
    requires: {
      topology: "mongos"
    }
  },

  test: function(configuration, test) {
    var Mongos = configuration.require.Mongos;

    // Attempt to connect
    var server = new Mongos([{
        host: configuration.host
      , port: configuration.port
    }, {
        host: configuration.host
      , port: configuration.port + 1
    }])

    // Add event listeners
    server.on('connect', function(_server) {
      setTimeout(function() {
        test.equal(true, _server.isConnected());
        _server.destroy();
        test.equal(false, _server.isConnected());
        test.done();
      }, 100);
    })

    // Start connection
    server.connect();
  }
}

exports['Should correctly execute command using mongos'] = {
  metadata: {
    requires: {
      topology: "mongos"
    }
  },

  test: function(configuration, test) {
    var Mongos = configuration.require.Mongos
      ReadPreference = configuration.require.ReadPreference;

    // Attempt to connect
    var server = new Mongos([{
        host: configuration.host
      , port: configuration.port
    }]);

    // Add event listeners
    server.on('connect', function(_server) {
      // Execute the command
      _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
        test.equal(null, err);
        test.equal(true, result.result.ismaster);
        // Destroy the connection
        _server.destroy();
        // Finish the test
        test.done();
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly execute write using mongos'] = {
  metadata: {
    requires: {
      topology: "mongos"
    }
  },

  test: function(configuration, test) {
    var Mongos = configuration.require.Mongos;

    // Attempt to connect
    var server = new Mongos([{
        host: configuration.host
      , port: configuration.port
    }]);

    // Add event listeners
    server.on('connect', function(_server) {
      // Execute the write
      _server.insert(f("%s.inserts_mongos1", configuration.db), [{a:1}], {
        writeConcern: {w:1}, ordered:true
      }, function(err, results) {
        test.equal(null, err);
        test.equal(1, results.result.n);
        // Destroy the connection
        _server.destroy();
        // Finish the test
        test.done();
      });
    })

    // Start connection
    server.connect();
  }
}

exports['Should correctly remove mongos and re-add it'] = {
  metadata: {
    requires: {
      topology: "mongos"
    }
  },

  test: function(configuration, test) {
    var Mongos = configuration.require.Mongos
      , ReadPreference = configuration.require.ReadPreference;
    // Attempt to connect
    // Attempt to connect
    var server = new Mongos([{
        host: configuration.host
      , port: configuration.port
    }, {
        host: configuration.host
      , port: configuration.port + 1
    }])

    // The state
    var joined = 0;
    var left = 0;

    // Add event listeners
    server.on('connect', function(_server) {
      _server.on('joined', function(t, s) {
        joined = joined + 1;
      });

      _server.on('left', function(t, s) {
        left = left + 1;
      });

      var interval = setInterval(function() {
        // We are done
        if(joined == 2 && left == 2) {
          clearInterval(interval);
          server.destroy();
          return test.done();
        }

        // Execute the write
        _server.insert(f("%s.inserts_mongos2", configuration.db), [{a:1}], {
          writeConcern: {w:1}, ordered:true
        }, function(err, results) {
          test.equal(null, err);
        });
      }, 1000)

      setTimeout(function() {
        // Shutdown the first secondary
        configuration.manager.remove('mongos', {index: 0}, function(err, serverDetails) {
          if(err) console.dir(err);

          setTimeout(function() {
            // Shutdown the second secondary
            configuration.manager.add(serverDetails, function(err, result) {
              // Shutdown the first secondary
              configuration.manager.remove('mongos', {index: 1}, function(err, serverDetails) {
                if(err) console.dir(err);

                setTimeout(function() {
                  // Shutdown the second secondary
                  configuration.manager.add(serverDetails, function(err, result) {});
                }, 2000)
              });
            });
          }, 2000)
        });
      }, 2000);
    });

    // Start connection
    server.connect();
  }
}<commit_msg>Add missing variables declaration separator<commit_after>var f = require('util').format
  , Long = require('bson').Long;

exports['Should correctly connect using mongos object'] = {
  metadata: {
    requires: {
      topology: "mongos"
    }
  },

  test: function(configuration, test) {
    var Mongos = configuration.require.Mongos;

    // Attempt to connect
    var server = new Mongos([{
        host: configuration.host
      , port: configuration.port
    }, {
        host: configuration.host
      , port: configuration.port + 1
    }])

    // Add event listeners
    server.on('connect', function(_server) {
      setTimeout(function() {
        test.equal(true, _server.isConnected());
        _server.destroy();
        test.equal(false, _server.isConnected());
        test.done();
      }, 100);
    })

    // Start connection
    server.connect();
  }
}

exports['Should correctly execute command using mongos'] = {
  metadata: {
    requires: {
      topology: "mongos"
    }
  },

  test: function(configuration, test) {
    var Mongos = configuration.require.Mongos
      , ReadPreference = configuration.require.ReadPreference;

    // Attempt to connect
    var server = new Mongos([{
        host: configuration.host
      , port: configuration.port
    }]);

    // Add event listeners
    server.on('connect', function(_server) {
      // Execute the command
      _server.command("system.$cmd", {ismaster: true}, {readPreference: new ReadPreference('primary')}, function(err, result) {
        test.equal(null, err);
        test.equal(true, result.result.ismaster);
        // Destroy the connection
        _server.destroy();
        // Finish the test
        test.done();
      });
    });

    // Start connection
    server.connect();
  }
}

exports['Should correctly execute write using mongos'] = {
  metadata: {
    requires: {
      topology: "mongos"
    }
  },

  test: function(configuration, test) {
    var Mongos = configuration.require.Mongos;

    // Attempt to connect
    var server = new Mongos([{
        host: configuration.host
      , port: configuration.port
    }]);

    // Add event listeners
    server.on('connect', function(_server) {
      // Execute the write
      _server.insert(f("%s.inserts_mongos1", configuration.db), [{a:1}], {
        writeConcern: {w:1}, ordered:true
      }, function(err, results) {
        test.equal(null, err);
        test.equal(1, results.result.n);
        // Destroy the connection
        _server.destroy();
        // Finish the test
        test.done();
      });
    })

    // Start connection
    server.connect();
  }
}

exports['Should correctly remove mongos and re-add it'] = {
  metadata: {
    requires: {
      topology: "mongos"
    }
  },

  test: function(configuration, test) {
    var Mongos = configuration.require.Mongos
      , ReadPreference = configuration.require.ReadPreference;
    // Attempt to connect
    // Attempt to connect
    var server = new Mongos([{
        host: configuration.host
      , port: configuration.port
    }, {
        host: configuration.host
      , port: configuration.port + 1
    }])

    // The state
    var joined = 0;
    var left = 0;

    // Add event listeners
    server.on('connect', function(_server) {
      _server.on('joined', function(t, s) {
        joined = joined + 1;
      });

      _server.on('left', function(t, s) {
        left = left + 1;
      });

      var interval = setInterval(function() {
        // We are done
        if(joined == 2 && left == 2) {
          clearInterval(interval);
          server.destroy();
          return test.done();
        }

        // Execute the write
        _server.insert(f("%s.inserts_mongos2", configuration.db), [{a:1}], {
          writeConcern: {w:1}, ordered:true
        }, function(err, results) {
          test.equal(null, err);
        });
      }, 1000)

      setTimeout(function() {
        // Shutdown the first secondary
        configuration.manager.remove('mongos', {index: 0}, function(err, serverDetails) {
          if(err) console.dir(err);

          setTimeout(function() {
            // Shutdown the second secondary
            configuration.manager.add(serverDetails, function(err, result) {
              // Shutdown the first secondary
              configuration.manager.remove('mongos', {index: 1}, function(err, serverDetails) {
                if(err) console.dir(err);

                setTimeout(function() {
                  // Shutdown the second secondary
                  configuration.manager.add(serverDetails, function(err, result) {});
                }, 2000)
              });
            });
          }, 2000)
        });
      }, 2000);
    });

    // Start connection
    server.connect();
  }
}
<|endoftext|>


<commit_before>var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleGuard = require('role.guard');
var roleRepair = require('role.repair');

module.exports = {

    run: function() {

    	create();

        for(var name in Game.creeps) {
	    	var creep = Game.creeps[name];
	    	setRoleForCreep(creep);
	    }

	}
};

// Runs the role for the given creep.
function setRoleForCreep(creep){
   if(creep.memory.role == 'harvester') {
        roleHarvester.run(creep, getSourceForCreep(creep));
    }
    if(creep.memory.role == 'upgrader') {
        roleUpgrader.run(creep,  getSourceForCreep(creep));
    }
    if(creep.memory.role == 'builder') {
        roleBuilder.run(creep,  getSourceForCreep(creep));
    }
    if(creep.memory.role == 'repair') {
        roleRepair.run(creep, getSourceForCreep(creep));
    }
    if(creep.memory.role == 'guard') {
        roleGuard.run(creep);
    }
}

// Counts the creeps attached to the given source.
function getCreepCountForSource(source){
	var count = 0;
	 for(var name in Game.creeps) {
	    	var creep = Game.creeps[name];
	    	if (creep.memory.sourceId == source.id){
	    		count++;
	    	}
	 }
	 return count;
}

// Gets the source with the lowest creep count.
function getSourceWithMinCreepCount(creep){
	 var sources = creep.room.find(FIND_SOURCES);

    var minSource = null;

	 for (var i = 0; i < sources.length ; i++ ){
		 var tmpSource = sources[i];

	     if (minSource==null){
	         minSource = creep.room.find(FIND_SOURCES)[0];
	     }
		 var minSourceCount = getCreepCountForSource(minSource);
		 var tmpSourceCount = getCreepCountForSource(tmpSource);

		 if(minSourceCount >  tmpSourceCount){
			 minSource = tmpSource;
		 }
	 }
	 return minSource;
}

// Getting the source for the given creep. If the creep is not assinged to a
// source a source is randomly chossen and saved for the creep.
function getSourceForCreep(creep){
	 var sources = creep.room.find(FIND_SOURCES);
	 var sourceToMine = sources[0];

	// If the creep has no assigned source the source with the minimun creep
	// count is set for the creep.
    if (creep.memory.sourceId === undefined){
    	sourceToMine = getSourceWithMinCreepCount(creep);
        creep.memory.sourceId = sourceToMine.id;
        console.log(creep.name+"  role: "+creep.memory.role+ " source: "+creep.memory.sourceId);
    }
    return Game.getObjectById(creep.memory.sourceId);
}

// Creating all the creeps.
function create() {

	clean();

	if (createCreep('harvester', 10, [WORK, WORK, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE])){
		return;
	}
	if(createCreep('upgrader', 4, [WORK, WORK, WORK, CARRY, CARRY, MOVE])){
		return;
	}
	if(createCreep('builder', 2, [WORK, WORK, CARRY, CARRY, CARRY, MOVE])){
		return;
	}
	if(createCreep('repair', 1, [WORK, CARRY, CARRY, MOVE, MOVE, MOVE])){
		return;
	}
	if(createCreep('guard', 4, [ATTACK, ATTACK, MOVE, MOVE, MOVE, MOVE, MOVE, TOUGH, TOUGH, TOUGH, TOUGH])){
		return;
	}

}

// Creates a single creep with the given role and work
function createCreep(roleTyp, counter, work){
    var exisitingCreeps = _.filter(Game.creeps, (creep) => creep.memory.role == roleTyp);
    if(exisitingCreeps.length < counter) {
        var newName = Game.spawns.Spawn1.createCreep(work, undefined, {role: roleTyp});
        if (newName<0){
        	return true;
        }
        console.log('Spawning new creep for role '+roleTyp+' with name ' + newName);
        return true;
    }
    return false;
}

// Cleans the memory from dead creeps.
function clean(){
	for(var name in Memory.creeps) {
        if(!Game.creeps[name]) {
            delete Memory.creeps[name];
            console.log('Clearing dead creep memory:', name);
        }
    }
}
<commit_msg>More to repair<commit_after>var roleHarvester = require('role.harvester');
var roleUpgrader = require('role.upgrader');
var roleBuilder = require('role.builder');
var roleGuard = require('role.guard');
var roleRepair = require('role.repair');

module.exports = {

    run: function() {

    	create();

        for(var name in Game.creeps) {
	    	var creep = Game.creeps[name];
	    	setRoleForCreep(creep);
	    }

	}
};

// Runs the role for the given creep.
function setRoleForCreep(creep){
   if(creep.memory.role == 'harvester') {
        roleHarvester.run(creep, getSourceForCreep(creep));
    }
    if(creep.memory.role == 'upgrader') {
        roleUpgrader.run(creep,  getSourceForCreep(creep));
    }
    if(creep.memory.role == 'builder') {
        roleBuilder.run(creep,  getSourceForCreep(creep));
    }
    if(creep.memory.role == 'repair') {
        roleRepair.run(creep, getSourceForCreep(creep));
    }
    if(creep.memory.role == 'guard') {
        roleGuard.run(creep);
    }
}

// Counts the creeps attached to the given source.
function getCreepCountForSource(source){
	var count = 0;
	 for(var name in Game.creeps) {
	    	var creep = Game.creeps[name];
	    	if (creep.memory.sourceId == source.id){
	    		count++;
	    	}
	 }
	 return count;
}

// Gets the source with the lowest creep count.
function getSourceWithMinCreepCount(creep){
	 var sources = creep.room.find(FIND_SOURCES);

    var minSource = null;

	 for (var i = 0; i < sources.length ; i++ ){
		 var tmpSource = sources[i];

	     if (minSource==null){
	         minSource = creep.room.find(FIND_SOURCES)[0];
	     }
		 var minSourceCount = getCreepCountForSource(minSource);
		 var tmpSourceCount = getCreepCountForSource(tmpSource);

		 if(minSourceCount >  tmpSourceCount){
			 minSource = tmpSource;
		 }
	 }
	 return minSource;
}

// Getting the source for the given creep. If the creep is not assinged to a
// source a source is randomly chossen and saved for the creep.
function getSourceForCreep(creep){
	 var sources = creep.room.find(FIND_SOURCES);
	 var sourceToMine = sources[0];

	// If the creep has no assigned source the source with the minimun creep
	// count is set for the creep.
    if (creep.memory.sourceId === undefined){
    	sourceToMine = getSourceWithMinCreepCount(creep);
        creep.memory.sourceId = sourceToMine.id;
        console.log(creep.name+"  role: "+creep.memory.role+ " source: "+creep.memory.sourceId);
    }
    return Game.getObjectById(creep.memory.sourceId);
}

// Creating all the creeps.
function create() {

	clean();

	if (createCreep('harvester', 10, [WORK, WORK, CARRY, CARRY, CARRY, MOVE, MOVE, MOVE])){
		return;
	}
	if(createCreep('upgrader', 4, [WORK, WORK, WORK, CARRY, CARRY, MOVE])){
		return;
	}
	if(createCreep('builder', 2, [WORK, WORK, CARRY, CARRY, CARRY, MOVE])){
		return;
	}
	if(createCreep('repair', 2, [WORK, CARRY, CARRY, MOVE, MOVE, MOVE])){
		return;
	}
	if(createCreep('guard', 4, [ATTACK, ATTACK, MOVE, MOVE, MOVE, MOVE, MOVE, TOUGH, TOUGH, TOUGH, TOUGH])){
		return;
	}

}

// Creates a single creep with the given role and work
function createCreep(roleTyp, counter, work){
    var exisitingCreeps = _.filter(Game.creeps, (creep) => creep.memory.role == roleTyp);
    if(exisitingCreeps.length < counter) {
        var newName = Game.spawns.Spawn1.createCreep(work, undefined, {role: roleTyp});
        if (newName<0){
        	return true;
        }
        console.log('Spawning new creep for role '+roleTyp+' with name ' + newName);
        return true;
    }
    return false;
}

// Cleans the memory from dead creeps.
function clean(){
	for(var name in Memory.creeps) {
        if(!Game.creeps[name]) {
            delete Memory.creeps[name];
            console.log('Clearing dead creep memory:', name);
        }
    }
}
<|endoftext|>


<commit_before>/*global Ghost, _, Backbone */
(function () {
    'use strict';

    Ghost.Models.Post = Ghost.ProgressModel.extend({

        defaults: {
            status: 'draft'
        },

        blacklist: ['published', 'draft'],

        parse: function (resp) {
            if (resp.status) {
                resp.published = resp.status === 'published';
                resp.draft = resp.status === 'draft';
            }
            if (resp.tags) {
                return resp;
            }
            return resp;
        },

        validate: function (attrs) {
            if (_.isEmpty(attrs.title)) {
                return 'You must specify a title for the post.';
            }
        },

        addTag: function (tagToAdd) {
            var tags = this.get('tags') || [];
            tags.push(tagToAdd);
            this.set('tags', tags);
        },

        removeTag: function (tagToRemove) {
            var tags = this.get('tags') || [];
            tags = _.reject(tags, function (tag) {
                return tag.id === tagToRemove.id || tag.name === tagToRemove.name;
            });
            this.set('tags', tags);
        }
    });

    Ghost.Collections.Posts = Backbone.Collection.extend({
        currentPage: 1,
        totalPages: 0,
        totalPosts: 0,
        nextPage: 0,
        prevPage: 0,

        url: Ghost.paths.apiRoot + '/posts/',
        model: Ghost.Models.Post,

        parse: function (resp) {
            if (_.isArray(resp.posts)) {
                this.limit = resp.limit;
                this.currentPage = resp.page;
                this.totalPages = resp.pages;
                this.totalPosts = resp.total;
                this.nextPage = resp.next;
                this.prevPage = resp.prev;
                return resp.posts;
            }
            return resp;
        }
    });

}());
<commit_msg>Move post API to primary document format<commit_after>/*global Ghost, _, Backbone, JSON */
(function () {
    'use strict';

    Ghost.Models.Post = Ghost.ProgressModel.extend({

        defaults: {
            status: 'draft'
        },

        blacklist: ['published', 'draft'],

        parse: function (resp) {

            if (resp.posts) {
                resp = resp.posts[0];
            }
            if (resp.status) {
                resp.published = resp.status === 'published';
                resp.draft = resp.status === 'draft';
            }
            if (resp.tags) {
                return resp;
            }
            return resp;
        },

        validate: function (attrs) {
            if (_.isEmpty(attrs.title)) {
                return 'You must specify a title for the post.';
            }
        },

        addTag: function (tagToAdd) {
            var tags = this.get('tags') || [];
            tags.push(tagToAdd);
            this.set('tags', tags);
        },

        removeTag: function (tagToRemove) {
            var tags = this.get('tags') || [];
            tags = _.reject(tags, function (tag) {
                return tag.id === tagToRemove.id || tag.name === tagToRemove.name;
            });
            this.set('tags', tags);
        },
        sync: function (method, model, options) {
            //wrap post in {posts: [{...}]}
            if (method === 'create' || method === 'update') {
                options.data = JSON.stringify({posts: [this.attributes]});
                options.contentType = 'application/json';
            }

            return Backbone.Model.prototype.sync.apply(this, arguments);
        }
    });

    Ghost.Collections.Posts = Backbone.Collection.extend({
        currentPage: 1,
        totalPages: 0,
        totalPosts: 0,
        nextPage: 0,
        prevPage: 0,

        url: Ghost.paths.apiRoot + '/posts/',
        model: Ghost.Models.Post,

        parse: function (resp) {
            if (_.isArray(resp.posts)) {
                this.limit = resp.limit;
                this.currentPage = resp.page;
                this.totalPages = resp.pages;
                this.totalPosts = resp.total;
                this.nextPage = resp.next;
                this.prevPage = resp.prev;
                return resp.posts;
            }
            return resp;
        }
    });

}());
<|endoftext|>


<commit_before>'use strict';

var mongoose = require('mongoose'),
  Schema = mongoose.Schema,
  archive = require('./archive.js'),
  socket = require('../../../mean-socket/server');

const UpdateSchema = new Schema({
  entity: {
    type: String
  },
  entityType: {
    type: String,
    enum: [
      'task', 'project', 'discussion', 'officeDocument',
      'folder', 'office', 'templateDocument'
    ]
  },
  creator: {
    type: Schema.ObjectId,
    ref: 'User'
  },
  updateField: {
      type: String,
      enum: [
          'create',
          'star', 'due', 'status', 'assign', 'location', 'color',
          'title', 'description', 'tags', 'comment', 'attachment',
          'watchers', 'deadline'
      ]
  },
  date: {
    type: Date
  },
  prev: {
    type: Schema.Types.Mixed
  },
  current: {
    type: Schema.Types.Mixed
  }
});

var attachmentsVirtual = UpdateSchema.virtual('attachments');
attachmentsVirtual.get(function() {
  return this._attachments;
});
attachmentsVirtual.set(function(value) {
  this._attachments = value;
});
UpdateSchema.set('toJSON', {virtuals: true});
UpdateSchema.set('toObject', {virtuals: true});

/**
 * Validations
 */
UpdateSchema.path('entity').validate(function(entity) {
  return !!entity;
}, 'Entity cannot be blank');

UpdateSchema.path('entityType').validate(function(entityType) {
  return !!entityType;
}, 'Entity type id cannot be blank');

/**
 * Statics
 */
UpdateSchema.statics.load = function(id, cb) {
  this.findOne({
    _id: id
  }).populate('creator', 'name username').exec(cb);
};

UpdateSchema.statics.task = function(id, cb) {
  require('./task');
  var Task = mongoose.model('Task');
  Task.findById(id).populate('project').exec(function(err, task) {
    cb(err, {room: task.project ? task.project.room : null, title: task.title});
  });
};

UpdateSchema.statics.project = function(id, cb) {
  require('./project');
  var Project = mongoose.model('Project');
  Project.findById(id, function(err, project) {
    cb(err, {room: project.room, title: project.title});
  });
};

UpdateSchema.statics.office = function(id, cb) {
  require('./office');
  var Office = mongoose.model('Office');
  Office.findById(id, function(err, office) {
    cb(err, {room: office.room, title: office.title});
  });
};

UpdateSchema.statics.folder = function(id, cb) {
  require('./folder');
  var Folder = mongoose.model('Folder');
  Folder.findById(id, function(err, folder) {
    cb(err, {room: folder.room, title: folder.title});
  });
};

/**
 * Post middleware
 */
var elasticsearch = require('../controllers/elasticsearch');

UpdateSchema.post('save', function(req, next) {
  var update = this;

  if(UpdateSchema.statics[update.issue]) {
    UpdateSchema.statics[update.issue](update.issueId, function(err, result) {
      if(err) {
        return err;
      }
      elasticsearch.save(update, 'update');
    });
  }
  else {
    elasticsearch.save(update, 'update');
  }

  checkAndNotify(update);

  next();
});

function checkAndNotify(update) {

  let { entityType } = update;

  // Check if update is important
  if(![
    'comment',
    'assign',
    'due',
    'status'
  ].includes(update.updateField)) return;

  let modelName = entityType[0].toUpperCase() + entityType.slice(1);

  mongoose.model('Update')
  .populate(update, [{
    path: 'creator',
    select: 'name username'
  }, {
    path: 'entity',
    model: modelName
  }], (err, doc) => {

    if(err) return;

    let { entity, creator } = update;

    // Check if there is assignee
    if(!entity || !entity.assign) return;

    // Skip if assignee by himself created the update
    if(creator._id.equals(entity.assign)) return;
    socket.notify(entity.assign.toString(), update);
  })
}

UpdateSchema.pre('remove', function(next) {
  elasticsearch.delete(this, 'update', next);
  next();
});

UpdateSchema.plugin(archive, 'update');

module.exports = mongoose.model('Update', UpdateSchema);
<commit_msg>Fixed mongoose model: officeDocument -> Document<commit_after>'use strict';

var mongoose = require('mongoose'),
  Schema = mongoose.Schema,
  archive = require('./archive.js'),
  socket = require('../../../mean-socket/server');

const UpdateSchema = new Schema({
  entity: {
    type: String
  },
  entityType: {
    type: String,
    enum: [
      'task', 'project', 'discussion', 'officeDocument',
      'folder', 'office', 'templateDocument'
    ]
  },
  creator: {
    type: Schema.ObjectId,
    ref: 'User'
  },
  updateField: {
      type: String,
      enum: [
          'create',
          'star', 'due', 'status', 'assign', 'location', 'color',
          'title', 'description', 'tags', 'comment', 'attachment',
          'watchers', 'deadline'
      ]
  },
  date: {
    type: Date
  },
  prev: {
    type: Schema.Types.Mixed
  },
  current: {
    type: Schema.Types.Mixed
  }
});

var attachmentsVirtual = UpdateSchema.virtual('attachments');
attachmentsVirtual.get(function() {
  return this._attachments;
});
attachmentsVirtual.set(function(value) {
  this._attachments = value;
});
UpdateSchema.set('toJSON', {virtuals: true});
UpdateSchema.set('toObject', {virtuals: true});

/**
 * Validations
 */
UpdateSchema.path('entity').validate(function(entity) {
  return !!entity;
}, 'Entity cannot be blank');

UpdateSchema.path('entityType').validate(function(entityType) {
  return !!entityType;
}, 'Entity type id cannot be blank');

/**
 * Statics
 */
UpdateSchema.statics.load = function(id, cb) {
  this.findOne({
    _id: id
  }).populate('creator', 'name username').exec(cb);
};

UpdateSchema.statics.task = function(id, cb) {
  require('./task');
  var Task = mongoose.model('Task');
  Task.findById(id).populate('project').exec(function(err, task) {
    cb(err, {room: task.project ? task.project.room : null, title: task.title});
  });
};

UpdateSchema.statics.project = function(id, cb) {
  require('./project');
  var Project = mongoose.model('Project');
  Project.findById(id, function(err, project) {
    cb(err, {room: project.room, title: project.title});
  });
};

UpdateSchema.statics.office = function(id, cb) {
  require('./office');
  var Office = mongoose.model('Office');
  Office.findById(id, function(err, office) {
    cb(err, {room: office.room, title: office.title});
  });
};

UpdateSchema.statics.folder = function(id, cb) {
  require('./folder');
  var Folder = mongoose.model('Folder');
  Folder.findById(id, function(err, folder) {
    cb(err, {room: folder.room, title: folder.title});
  });
};

/**
 * Post middleware
 */
var elasticsearch = require('../controllers/elasticsearch');

UpdateSchema.post('save', function(req, next) {
  var update = this;

  if(UpdateSchema.statics[update.issue]) {
    UpdateSchema.statics[update.issue](update.issueId, function(err, result) {
      if(err) {
        return err;
      }
      elasticsearch.save(update, 'update');
    });
  }
  else {
    elasticsearch.save(update, 'update');
  }

  checkAndNotify(update);

  next();
});

function checkAndNotify(update) {

  let { entityType } = update;

  // Check if update is important
  if(![
    'comment',
    'assign',
    'due',
    'status'
  ].includes(update.updateField)) return;

  let modelName = entityType[0].toUpperCase() + entityType.slice(1);
  if(entityType === 'officeDocument') {
    modelName = 'Document';
  }

  mongoose.model('Update')
  .populate(update, [{
    path: 'creator',
    select: 'name username'
  }, {
    path: 'entity',
    model: modelName
  }], (err, doc) => {

    if(err) return;

    let { entity, creator } = update;

    // Check if there is assignee
    if(!entity || !entity.assign) return;

    // Skip if assignee by himself created the update
    if(creator._id.equals(entity.assign)) return;
    socket.notify(entity.assign.toString(), update);
  })
}

UpdateSchema.pre('remove', function(next) {
  elasticsearch.delete(this, 'update', next);
  next();
});

UpdateSchema.plugin(archive, 'update');

module.exports = mongoose.model('Update', UpdateSchema);
<|endoftext|>