<commit_before>'use strict';
const async = require("async");

const utils = require("../../../utils/utils.js");
const infraColname = 'infra';
const templateColName = 'templates';
const templateStateColName = 'vm_layers';
const vmModule = require("../vm/index.js")
function checkIfError(soajs, mainCb, data, cb) {
	utils.checkErrorReturn(soajs, mainCb, data, cb);
}
const dbModel = 'mongo';
const vmLayerModule = {

	/**
	 * call cloostro and pass the template and inputs to create the vm layer
	 * @param config
	 * @param soajs
	 * @param BL
	 * @param deployer
	 * @param cbMain
	 */
	deployVM: (config, soajs, BL, deployer, cbMain) => {
		let inputmaskDataClone = JSON.parse(JSON.stringify(soajs.inputmaskData));
		async.auto({
			"getEnvironment": (mCb) => {
				soajs.log.info("get environment record");
				utils.getEnvironment(soajs, BL.model, soajs.inputmaskData.env.toUpperCase(), (error, envRecord) => {
					checkIfError(soajs, mCb, {config: config, error: error || !envRecord, code: 600}, function() {
						return mCb(null, envRecord);
					});
				});
			},
			"getInfra": (mCb) => {
				BL.model.validateCustomId(soajs, soajs.inputmaskData.infraId, (err, id) => {
					checkIfError(soajs, mCb, {config: config, error: err, code: 490}, () => {
						let opts = {
							collection: infraColname,
							conditions: {
								_id: id,
								technologies: {$in: ["vm"]}
							}
						};
						BL.model.findEntry(soajs, opts, function (err, infraRecord) {
							checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
								checkIfError(soajs, mCb, {
									config: config,
									error: !infraRecord,
									code: 600
								}, () => {
									return mCb(null, infraRecord);
								});
							});
						});
					});
				});
			},
			"getInfraCodeTemplate": (mCb) => {
				soajs.log.info("get template record");
				let opts = {
					collection: templateColName,
					conditions: {
						name: soajs.inputmaskData.infraCodeTemplate // todo check this
					}
				};
				BL.model.findEntry(soajs, opts, function (err, templateName) {
					checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
						checkIfError(soajs, mCb, {
							config: config,
							error: !templateName,
							code: 600
						}, () => {
							return mCb(null, templateName);
						});
					});
				});
			},
			"getInfraCodeTemplateState": (mCb) => {
				if (!soajs.inputmaskData.modify) {
					return mCb(null, true);
				}
				soajs.log.info("get template state record");
				let opts = {
					collection: templateStateColName,
					conditions: {
						layerName: soajs.inputmaskData.layerName,
						infraId: soajs.inputmaskData.infraId
					}
				};
				BL.model.findEntry(soajs, opts, function (err, dbRecord) {
					checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
						checkIfError(soajs, mCb, {
							config: config,
							error: !dbRecord,
							code: 600
						}, () => {
							return mCb(null, dbRecord);
						});
					});
				});
			}
		}, (error, result) => {
			checkIfError(soajs, cbMain, {config: config, error: error}, () => {
				let options = {
					soajs: soajs,
					infra: result.getInfra,
					registry: result.getEnvironment,
					params: {
						template: result.getInfraCodeTemplate,
						input: soajs.inputmaskData.specs
					}
				};
				options.params.input.layerName = soajs.inputmaskData.layerName;
				options.params.input.region = soajs.inputmaskData.region;
				let method = "deployCluster";
				let update = false;
				if (soajs.inputmaskData.modify) {
					update = true;
					options.params.templateState = result.getInfraCodeTemplateState.templateState ? JSON.parse(result.getInfraCodeTemplateState.templateState): null;
					method = "updateCluster"
				}

				checkIfError(soajs, cbMain, {config: config, error: update &&!options.params.templateState, code: 495}, () => {
					deployer.execute({
						type: "infra",
						name: result.getInfra.name,
						technology: soajs.inputmaskData.technology || "vm"
					}, method, options, (error, response) => {
						if (error) {
							soajs.log.error(error)
						}
						let opts = {
							collection: templateStateColName,
							versioning: true
						};
						if (soajs.inputmaskData.modify) {
							opts.conditions = {
								layerName: inputmaskDataClone.layerName,
								infraId: inputmaskDataClone.infraId
							};
							opts.fields = {
								$set: {}
							};
							if(response && response.stateFileData) {
								opts.fields.$set.templateState = JSON.stringify(response.stateFileData, null, 2);
							}
							if(response && response.render) {
								opts.fields.$set.renderedTemplate = response.render;
							}
							opts.options = {'upsert': false, 'safe': true};
							BL.model.updateEntry(soajs, opts, function (error) {
								if (error) {
									soajs.log.error(error);
								}
								else {
									soajs.log.info("Template state record update!");
								}

								if(!inputmaskDataClone.wizard){
									BL.model.closeConnection(soajs);
								}
							});
						}
						else {
							opts.record = {
								infraId: inputmaskDataClone.infraId.toString(),
								layerName: inputmaskDataClone.layerName,
								infraCodeTemplate: inputmaskDataClone.infraCodeTemplate,
								input: JSON.stringify(inputmaskDataClone.specs, null, 2),
								env: inputmaskDataClone.env.toLowerCase()
							};
							if (response && response.stateFileData) {
								opts.record.templateState = JSON.stringify(response.stateFileData, null, 2);
							}
							if(response && response.render) {
								opts.record.renderedTemplate = response.render;
							}
							BL.model.insertEntry(soajs, opts, function (error) {
								if (error) {
									soajs.log.error(error);
								}
								else {
									soajs.log.info("Template state record created!");
								}

								if(!inputmaskDataClone.wizard){
									BL.model.closeConnection(soajs);
								}
							});
						}
					});
					return cbMain(null, {"name": inputmaskDataClone.layerName, "infraId": inputmaskDataClone.infraId});
				});
			});
		});
	},

	/**
	 * run one atomic operation to check if the vm layer has been created
	 * @param config
	 * @param soajs
	 * @param BL
	 * @param deployer
	 * @param cbMain
	 */
	getDeployVMStatus: (config, soajs, BL, deployer, cbMain) => {
		let opts = {
			collection: templateStateColName,
			conditions: {
				layerName: soajs.inputmaskData.layerName,
				infraId: soajs.inputmaskData.infraId
			}
		};
		BL.model.findEntry(soajs, opts, function (err, dbRecord) {
			checkIfError(soajs, cbMain, {config: config, error: err, code: 600}, () => {
				if (!dbRecord || !dbRecord.templateState) {
					return cbMain(null, null);
				}
				vmModule.init(dbModel, function (error, model) {
					checkIfError(soajs, callback, {
						config: config,
						error: error,
						code: 407
					}, () => {
						let group;
						let inputs;
						try {
							inputs = JSON.parse(dbRecord.input).group;
							group = inputs.group;
						}
						catch (e) {
							return cbMain(new Error("No input found in template record"));
						}
						soajs.inputmaskData.group = group;
						soajs.inputmaskData.env = dbRecord.env;
						model.listVMs(config, soajs, deployer, (err, vmRecords) => {
							checkIfError(soajs, cbMain, {config: config, error: err, code: 600}, () => {
								if (vmRecords && typeof vmRecords === 'object' && Object.keys(vmRecords).length > 0) {
									async.map(vmRecords[Object.keys(vmRecords)[0]], (oneVm, cb) => {
										return (oneVm.layer === soajs.inputmaskData.layerName) ? cb(null, oneVm.name) : cb();
									}, function (err, vms) {
										return cbMain(null, {
											"name": dbRecord.layerName,
											"infraId": dbRecord.infraId,
											"inputs": inputs,
											"template": dbRecord.infraCodeTemplate,
											"env": dbRecord.env,
											"vms": vms
										});
									});
								}
							});
						});
					});
				});
			});
		});
	},

	/**
	 * call cloostro and pass the details needed to update a vm layer
	 * @param config
	 * @param soajs
	 * @param BL
	 * @param deployer
	 * @param cbMain
	 */
	updateVM: (config, soajs, BL, deployer, cbMain) => {
		soajs.inputmaskData.modify = true;
		vmLayerModule.deployVM(config, soajs, BL, deployer, cbMain)
	},

	/**
	 * call cloostro and pass the details needed to delete the vm layer
	 * @param config
	 * @param soajs
	 * @param BL
	 * @param deployer
	 * @param cbMain
	 */
	destroyVM: (config, soajs, BL, deployer, cbMain) => {
		let inputmaskDataClone = JSON.parse(JSON.stringify(soajs.inputmaskData));
		async.auto({
			"getEnvironment": (mCb) => {
				if (!soajs.inputmaskData.env) {
					return mCb();
				}
				utils.getEnvironment(soajs, BL.model, soajs.inputmaskData.env.toUpperCase(), (error, envRecord) => {
					checkIfError(soajs, mCb, {config: config, error: error || !envRecord, code: 600}, mCb);
				});
			},
			"getInfra": (mCb) => {
				BL.model.validateCustomId(soajs, soajs.inputmaskData.infraId, (err, id) => {
					checkIfError(soajs, mCb, {config: config, error: err, code: 490}, () => {
						let opts = {
							collection: infraColname,
							conditions: {
								_id: id,
								"technologies": {$in: ["vm"]}
							}
						};
						BL.model.findEntry(soajs, opts, function (err, infraRecord) {
							checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
								checkIfError(soajs, mCb, {
									config: config,
									error: !infraRecord,
									code: 600
								}, () => {
									return mCb(null, infraRecord);
								});
							});
						});
					});
				});
			},
			"getInfraCodeTemplateState": (mCb) => {
				let opts = {
					collection: templateStateColName,
					conditions: {
						layerName: soajs.inputmaskData.layerName,
						infraId: soajs.inputmaskData.infraId
					}
				};
				if (soajs.inputmaskData.env) {
					opts.conditions.env = soajs.inputmaskData.env.toLowerCase()
				}
				BL.model.findEntry(soajs, opts, function (err, templateName) {
					checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
						checkIfError(soajs, mCb, {
							config: config,
							error: !templateName,
							code: 600
						}, () => {
							return mCb(null, templateName);
						});
					});
				});
			},
			"getInfraCodeTemplate": ['getInfraCodeTemplateState', (info, mCb) => {
				let opts = {
					collection: templateColName,
					conditions: {
						name: info.getInfraCodeTemplateState.infraCodeTemplate
					}
				};
				BL.model.findEntry(soajs, opts, function (err, templateState) {
					checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
						checkIfError(soajs, mCb, {
							config: config,
							error: !templateState,
							code: 600
						}, () => {
							return mCb(null, templateState);
						});
					});
				});
			}],
		}, (error, result) => {
			checkIfError(soajs, cbMain, {config: config, error: error}, () => {
				let options = {
					soajs: soajs,
					infra: result.getInfra,
					registry: result.getEnvironment,
					params: {
						template: result.getInfraCodeTemplateState.renderedTemplate,
						templateState: JSON.parse(result.getInfraCodeTemplateState.templateState),
						layerName: result.getInfraCodeTemplateState.layerName,
					}
				};
				deployer.execute({
					type: "infra",
					name: result.getInfra.name,
					technology: soajs.inputmaskData.technology || "vm"
				}, 'deleteCluster', options, (error) => {
					if (error) {
						soajs.log.error(error)
					}
					let opts = {
						collection: templateStateColName,
						conditions: {
							layerName: soajs.inputmaskData.layerName,
							infraId: soajs.inputmaskData.infraId,
						}
					};
					BL.model.removeEntry(soajs, opts, function (error) {
						if (error) {
							soajs.log.error(error);
						}
						else {
							soajs.log.info("Template state record deleted!");
						}
						if(!inputmaskDataClone.wizard){
							BL.model.closeConnection(soajs);
						}
					});
				});
				return cbMain(null, true);
			});
		});
	},
};

module.exports = vmLayerModule;
<commit_msg>bug fixes<commit_after>'use strict';
const async = require("async");

const utils = require("../../../utils/utils.js");
const infraColname = 'infra';
const templateColName = 'templates';
const templateStateColName = 'vm_layers';
const vmModule = require("../vm/index.js");
function checkIfError(soajs, mainCb, data, cb) {
	utils.checkErrorReturn(soajs, mainCb, data, cb);
}
const dbModel = 'mongo';
const vmLayerModule = {

	/**
	 * call cloostro and pass the template and inputs to create the vm layer
	 * @param config
	 * @param soajs
	 * @param BL
	 * @param deployer
	 * @param cbMain
	 */
	deployVM: (config, soajs, BL, deployer, cbMain) => {
		let inputmaskDataClone = JSON.parse(JSON.stringify(soajs.inputmaskData));
		async.auto({
			"getEnvironment": (mCb) => {
				soajs.log.info("get environment record");
				utils.getEnvironment(soajs, BL.model, soajs.inputmaskData.env.toUpperCase(), (error, envRecord) => {
					checkIfError(soajs, mCb, {config: config, error: error || !envRecord, code: 600}, function() {
						return mCb(null, envRecord);
					});
				});
			},
			"getInfra": (mCb) => {
				BL.model.validateCustomId(soajs, soajs.inputmaskData.infraId, (err, id) => {
					checkIfError(soajs, mCb, {config: config, error: err, code: 490}, () => {
						let opts = {
							collection: infraColname,
							conditions: {
								_id: id,
								technologies: {$in: ["vm"]}
							}
						};
						BL.model.findEntry(soajs, opts, function (err, infraRecord) {
							checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
								checkIfError(soajs, mCb, {
									config: config,
									error: !infraRecord,
									code: 600
								}, () => {
									return mCb(null, infraRecord);
								});
							});
						});
					});
				});
			},
			"getInfraCodeTemplate": (mCb) => {
				soajs.log.info("get template record");
				let opts = {
					collection: templateColName,
					conditions: {
						name: soajs.inputmaskData.infraCodeTemplate // todo check this
					}
				};
				BL.model.findEntry(soajs, opts, function (err, templateName) {
					checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
						checkIfError(soajs, mCb, {
							config: config,
							error: !templateName,
							code: 600
						}, () => {
							return mCb(null, templateName);
						});
					});
				});
			},
			"getInfraCodeTemplateState": (mCb) => {
				if (!soajs.inputmaskData.modify) {
					return mCb(null, true);
				}
				soajs.log.info("get template state record");
				let opts = {
					collection: templateStateColName,
					conditions: {
						layerName: soajs.inputmaskData.layerName,
						infraId: soajs.inputmaskData.infraId
					}
				};
				BL.model.findEntry(soajs, opts, function (err, dbRecord) {
					checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
						checkIfError(soajs, mCb, {
							config: config,
							error: !dbRecord,
							code: 600
						}, () => {
							return mCb(null, dbRecord);
						});
					});
				});
			}
		}, (error, result) => {
			checkIfError(soajs, cbMain, {config: config, error: error}, () => {
				let options = {
					soajs: soajs,
					infra: result.getInfra,
					registry: result.getEnvironment,
					params: {
						template: result.getInfraCodeTemplate,
						input: soajs.inputmaskData.specs
					}
				};
				options.params.input.layerName = soajs.inputmaskData.layerName;
				options.params.input.region = soajs.inputmaskData.region;
				let method = "deployCluster";
				let update = false;
				if (soajs.inputmaskData.modify) {
					update = true;
					options.params.templateState = result.getInfraCodeTemplateState.templateState ? JSON.parse(result.getInfraCodeTemplateState.templateState): null;
					method = "updateCluster"
				}

				checkIfError(soajs, cbMain, {config: config, error: update &&!options.params.templateState, code: 495}, () => {
					deployer.execute({
						type: "infra",
						name: result.getInfra.name,
						technology: soajs.inputmaskData.technology || "vm"
					}, method, options, (error, response) => {
						if (error) {
							soajs.log.error(error)
						}
						let opts = {
							collection: templateStateColName,
							versioning: true
						};
						if (soajs.inputmaskData.modify) {
							opts.conditions = {
								layerName: inputmaskDataClone.layerName,
								infraId: inputmaskDataClone.infraId
							};
							opts.fields = {
								$set: {}
							};
							if(response && response.stateFileData) {
								opts.fields.$set.templateState = JSON.stringify(response.stateFileData, null, 2);
							}
							if(response && response.render) {
								opts.fields.$set.renderedTemplate = response.render;
							}
							opts.options = {'upsert': false, 'safe': true};
							BL.model.updateEntry(soajs, opts, function (error) {
								if (error) {
									soajs.log.error(error);
								}
								else {
									soajs.log.info("Template state record update!");
								}

								if(!inputmaskDataClone.wizard){
									BL.model.closeConnection(soajs);
								}
							});
						}
						else {
							opts.record = {
								infraId: inputmaskDataClone.infraId.toString(),
								layerName: inputmaskDataClone.layerName,
								infraCodeTemplate: inputmaskDataClone.infraCodeTemplate,
								input: JSON.stringify(inputmaskDataClone.specs, null, 2),
								env: inputmaskDataClone.env.toLowerCase()
							};
							if (response && response.stateFileData) {
								opts.record.templateState = JSON.stringify(response.stateFileData, null, 2);
							}
							if(response && response.render) {
								opts.record.renderedTemplate = response.render;
							}
							BL.model.insertEntry(soajs, opts, function (error) {
								if (error) {
									soajs.log.error(error);
								}
								else {
									soajs.log.info("Template state record created!");
								}

								if(!inputmaskDataClone.wizard){
									BL.model.closeConnection(soajs);
								}
							});
						}
					});
					return cbMain(null, {"name": inputmaskDataClone.layerName, "infraId": inputmaskDataClone.infraId});
				});
			});
		});
	},

	/**
	 * run one atomic operation to check if the vm layer has been created
	 * @param config
	 * @param soajs
	 * @param BL
	 * @param deployer
	 * @param cbMain
	 */
	getDeployVMStatus: (config, soajs, BL, deployer, cbMain) => {
		let opts = {
			collection: templateStateColName,
			conditions: {
				layerName: soajs.inputmaskData.layerName,
				infraId: soajs.inputmaskData.infraId
			}
		};
		BL.model.findEntry(soajs, opts, function (err, dbRecord) {
			checkIfError(soajs, cbMain, {config: config, error: err, code: 600}, () => {
				if (!dbRecord || !dbRecord.templateState) {
					return cbMain(null, null);
				}
				vmModule.init(dbModel, function (error, model) {
					checkIfError(soajs, cbMain, {
						config: config,
						error: error,
						code: 407
					}, () => {
						let group;
						let inputs;
						try {
							inputs = JSON.parse(dbRecord.input).group;
							group = inputs.group;
						}
						catch (e) {
							return cbMain(new Error("No input found in template record"));
						}
						soajs.inputmaskData.group = group;
						soajs.inputmaskData.env = dbRecord.env;
						model.listVMs(config, soajs, deployer, (err, vmRecords) => {
							checkIfError(soajs, cbMain, {config: config, error: err, code: 600}, () => {
								if (vmRecords && typeof vmRecords === 'object' && Object.keys(vmRecords).length > 0) {
									let myVMs = [];
									async.each(vmRecords[Object.keys(vmRecords)[0]], (oneVm, cb) => {
										if(oneVm.name && oneVm.layer === soajs.inputmaskData.layerName){
											myVMs.push(oneVm.name);
										}
										return cb();
									}, function () {
										return cbMain(null, {
											"name": dbRecord.layerName,
											"infraId": dbRecord.infraId,
											"inputs": inputs,
											"template": dbRecord.infraCodeTemplate,
											"env": dbRecord.env,
											"vms": myVMs
										});
									});
								}
							});
						});
					});
				});
			});
		});
	},

	/**
	 * call cloostro and pass the details needed to update a vm layer
	 * @param config
	 * @param soajs
	 * @param BL
	 * @param deployer
	 * @param cbMain
	 */
	updateVM: (config, soajs, BL, deployer, cbMain) => {
		soajs.inputmaskData.modify = true;
		vmLayerModule.deployVM(config, soajs, BL, deployer, cbMain)
	},

	/**
	 * call cloostro and pass the details needed to delete the vm layer
	 * @param config
	 * @param soajs
	 * @param BL
	 * @param deployer
	 * @param cbMain
	 */
	destroyVM: (config, soajs, BL, deployer, cbMain) => {
		let inputmaskDataClone = JSON.parse(JSON.stringify(soajs.inputmaskData));
		async.auto({
			"getEnvironment": (mCb) => {
				if (!soajs.inputmaskData.env) {
					return mCb();
				}
				utils.getEnvironment(soajs, BL.model, soajs.inputmaskData.env.toUpperCase(), (error, envRecord) => {
					checkIfError(soajs, mCb, {config: config, error: error || !envRecord, code: 600}, mCb);
				});
			},
			"getInfra": (mCb) => {
				BL.model.validateCustomId(soajs, soajs.inputmaskData.infraId, (err, id) => {
					checkIfError(soajs, mCb, {config: config, error: err, code: 490}, () => {
						let opts = {
							collection: infraColname,
							conditions: {
								_id: id,
								"technologies": {$in: ["vm"]}
							}
						};
						BL.model.findEntry(soajs, opts, function (err, infraRecord) {
							checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
								checkIfError(soajs, mCb, {
									config: config,
									error: !infraRecord,
									code: 600
								}, () => {
									return mCb(null, infraRecord);
								});
							});
						});
					});
				});
			},
			"getInfraCodeTemplateState": (mCb) => {
				let opts = {
					collection: templateStateColName,
					conditions: {
						layerName: soajs.inputmaskData.layerName,
						infraId: soajs.inputmaskData.infraId
					}
				};
				if (soajs.inputmaskData.env) {
					opts.conditions.env = soajs.inputmaskData.env.toLowerCase()
				}
				BL.model.findEntry(soajs, opts, function (err, templateName) {
					checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
						checkIfError(soajs, mCb, {
							config: config,
							error: !templateName,
							code: 600
						}, () => {
							return mCb(null, templateName);
						});
					});
				});
			},
			"getInfraCodeTemplate": ['getInfraCodeTemplateState', (info, mCb) => {
				let opts = {
					collection: templateColName,
					conditions: {
						name: info.getInfraCodeTemplateState.infraCodeTemplate
					}
				};
				BL.model.findEntry(soajs, opts, function (err, templateState) {
					checkIfError(soajs, mCb, {config: config, error: err, code: 600}, () => {
						checkIfError(soajs, mCb, {
							config: config,
							error: !templateState,
							code: 600
						}, () => {
							return mCb(null, templateState);
						});
					});
				});
			}],
		}, (error, result) => {
			checkIfError(soajs, cbMain, {config: config, error: error}, () => {
				let options = {
					soajs: soajs,
					infra: result.getInfra,
					registry: result.getEnvironment,
					params: {
						template: result.getInfraCodeTemplateState.renderedTemplate,
						templateState: JSON.parse(result.getInfraCodeTemplateState.templateState),
						layerName: result.getInfraCodeTemplateState.layerName,
					}
				};
				deployer.execute({
					type: "infra",
					name: result.getInfra.name,
					technology: soajs.inputmaskData.technology || "vm"
				}, 'deleteCluster', options, (error) => {
					if (error) {
						soajs.log.error(error)
					}
					let opts = {
						collection: templateStateColName,
						conditions: {
							layerName: soajs.inputmaskData.layerName,
							infraId: soajs.inputmaskData.infraId,
						}
					};
					BL.model.removeEntry(soajs, opts, function (error) {
						if (error) {
							soajs.log.error(error);
						}
						else {
							soajs.log.info("Template state record deleted!");
						}
						if(!inputmaskDataClone.wizard){
							BL.model.closeConnection(soajs);
						}
					});
				});
				return cbMain(null, true);
			});
		});
	},
};

module.exports = vmLayerModule;
<|endoftext|>


<commit_before>//    The MIT License (MIT)
//
//    Copyright (c) 2014 YIOM
//
//    Permission is hereby granted, free of charge, to any person obtaining a copy
//    of this software and associated documentation files (the "Software"), to deal
//    in the Software without restriction, including without limitation the rights
//    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//    copies of the Software, and to permit persons to whom the Software is
//    furnished to do so, subject to the following conditions:
//
//    The above copyright notice and this permission notice shall be included in
//    all copies or substantial portions of the Software.
//
//    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//    THE SOFTWARE.

function Sketchpad(config) {
  // Enforces the context for all functions
  for (var key in this.constructor.prototype) {
    this[key] = this[key].bind(this);
  }

  // Warn the user if no DOM element was selected
  if (!config.hasOwnProperty('element')) {
    console.error('SKETCHPAD ERROR: No element selected');
    return;
  }

  this.element = config.element;

  // Width can be defined on the HTML or programatically
  this._width = config.width || $(this.element).attr('data-width') || 0;
  this._height = config.height || $(this.element).attr('data-height') || 0;

  // Pen attributes
  this.color = config.color || $(this.element).attr('data-color') || '#000000';
  this.penSize = config.penSize || $(this.element).attr('data-penSize') || 5;

  // ReadOnly sketchpads may not be modified
  this.readOnly = config.readOnly ||
                  $(this.element).attr('data-readOnly') ||
                  false;

  // Stroke control variables
  this.strokes = config.strokes || [];
  this._currentStroke = {
    color: null,
    size: null,
    lines: [],
  };

  // Undo History
  this.undoHistory = config.undoHistory || [];

  // Animation function calls
  this.animateIds = [];

  // Set sketching state
  this._sketching = false;

  // Setup canvas sketching listeners
  this.reset();
}

//
// Private API
//

Sketchpad.prototype._cursorPosition = function(event) {
  return {
    x: event.pageX - this.canvas.offsetLeft,
    y: event.pageY - this.canvas.offsetTop,
  };
};

Sketchpad.prototype._draw = function(start, end, color, size) {
  this._stroke(start, end, color, size, 'source-over');
};

Sketchpad.prototype._erase = function(start, end, color, size) {
  this._stroke(start, end, color, size, 'destination-out');
};

Sketchpad.prototype._stroke = function(start, end, color, size, compositeOperation) {
  this.context.save();
  this.context.lineJoin = 'round';
  this.context.lineCap = 'round';
  this.context.strokeStyle = color;
  this.context.lineWidth = size;
  this.context.globalCompositeOperation = compositeOperation;
  this.context.beginPath();
  this.context.moveTo(start.x, start.y);
  this.context.lineTo(end.x, end.y);
  this.context.closePath();
  this.context.stroke();

  this.context.restore();
};

//
// Callback Handlers
//

Sketchpad.prototype._mouseDown = function(event) {
  this._lastPosition = this._cursorPosition(event);
  this._currentStroke.color = this.color;
  this._currentStroke.size = this.penSize;
  this._currentStroke.lines = [];
  this._sketching = true;
  this.canvas.addEventListener('mousemove', this._mouseMove);
};

Sketchpad.prototype._mouseUp = function(event) {
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('mousemove', this._mouseMove);
};

Sketchpad.prototype._mouseMove = function(event) {
  var currentPosition = this._cursorPosition(event);

  this._draw(this._lastPosition, currentPosition, this.color, this.penSize);
  this._currentStroke.lines.push({
    start: $.extend(true, {}, this._lastPosition),
    end: $.extend(true, {}, currentPosition),
  });

  this._lastPosition = currentPosition;
};

Sketchpad.prototype._touchStart = function(event) {
  event.preventDefault();
  if (this._sketching) {
    return;
  }
  this._lastPosition = this._cursorPosition(event.changedTouches[0]);
  this._currentStroke.color = this.color;
  this._currentStroke.size = this.penSize;
  this._currentStroke.lines = [];
  this._sketching = true;
  this.canvas.addEventListener('touchmove', this._touchMove, false);
};

Sketchpad.prototype._touchEnd = function(event) {
  event.preventDefault();
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchCancel = function(event) {
  event.preventDefault();
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchLeave = function(event) {
  event.preventDefault();
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchMove = function(event) {
  event.preventDefault();
  var currentPosition = this._cursorPosition(event.changedTouches[0]);

  this._draw(this._lastPosition, currentPosition, this.color, this.penSize);
  this._currentStroke.lines.push({
    start: $.extend(true, {}, this._lastPosition),
    end: $.extend(true, {}, currentPosition),
  });

  this._lastPosition = currentPosition;
};

//
// Public API
//

Sketchpad.prototype.reset = function() {
  // Set attributes
  this.canvas = $(this.element)[0];
  this.canvas.width = this._width;
  this.canvas.height = this._height;
  this.context = this.canvas.getContext('2d');

  // Setup event listeners
  this.redraw(this.strokes);

  if (this.readOnly) {
    return;
  }

  // Mouse
  this.canvas.addEventListener('mousedown', this._mouseDown);
  this.canvas.addEventListener('mouseout', this._mouseUp);
  this.canvas.addEventListener('mouseup', this._mouseUp);

  // Touch
  this.canvas.addEventListener('touchstart', this._touchStart);
  this.canvas.addEventListener('touchend', this._touchEnd);
  this.canvas.addEventListener('touchcancel', this._touchCancel);
  this.canvas.addEventListener('touchleave', this._touchLeave);
};

Sketchpad.prototype.drawStroke = function(stroke) {
  for (var j = 0; j < stroke.lines.length; j++) {
    var line = stroke.lines[j];
    this._draw(line.start, line.end, stroke.color, stroke.size);
  }
};

Sketchpad.prototype.redraw = function(strokes) {
  for (var i = 0; i < strokes.length; i++) {
    this.drawStroke(strokes[i]);
  }
};

Sketchpad.prototype.toObject = function() {
  return {
    width: this.canvas.width,
    height: this.canvas.height,
    strokes: this.strokes,
    undoHistory: this.undoHistory,
  };
};

Sketchpad.prototype.toJSON = function() {
  return JSON.stringify(this.toObject());
};

Sketchpad.prototype.animate = function(ms, loop, loopDelay) {
  this.clear();
  var delay = ms;
  var callback = null;
  for (var i = 0; i < this.strokes.length; i++) {
    var stroke = this.strokes[i];
    for (var j = 0; j < stroke.lines.length; j++) {
      var line = stroke.lines[j];
      callback = this._draw.bind(this, line.start, line.end,
                                 stroke.color, stroke.size);
      this.animateIds.push(setTimeout(callback, delay));
      delay += ms;
    }
  }
  if (loop) {
    loopDelay = loopDelay || 0;
    callback = this.animate.bind(this, ms, loop, loopDelay);
    this.animateIds.push(setTimeout(callback, delay + loopDelay));
  }
};

Sketchpad.prototype.cancelAnimation = function() {
  for (var i = 0; i < this.animateIds.length; i++) {
    clearTimeout(this.animateIds[i]);
  }
};

Sketchpad.prototype.clear = function() {
  this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
};

Sketchpad.prototype.undo = function() {
  this.clear();
  var stroke = this.strokes.pop();
  if (stroke) {
    this.undoHistory.push(stroke);
    this.redraw(this.strokes);
  }
};

Sketchpad.prototype.redo = function() {
  var stroke = this.undoHistory.pop();
  if (stroke) {
    this.strokes.push(stroke);
    this.drawStroke(stroke);
  }
};
<commit_msg>Show crosshair cursor when sketchpad is interactive<commit_after>//    The MIT License (MIT)
//
//    Copyright (c) 2014 YIOM
//
//    Permission is hereby granted, free of charge, to any person obtaining a copy
//    of this software and associated documentation files (the "Software"), to deal
//    in the Software without restriction, including without limitation the rights
//    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//    copies of the Software, and to permit persons to whom the Software is
//    furnished to do so, subject to the following conditions:
//
//    The above copyright notice and this permission notice shall be included in
//    all copies or substantial portions of the Software.
//
//    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//    THE SOFTWARE.

function Sketchpad(config) {
  // Enforces the context for all functions
  for (var key in this.constructor.prototype) {
    this[key] = this[key].bind(this);
  }

  // Warn the user if no DOM element was selected
  if (!config.hasOwnProperty('element')) {
    console.error('SKETCHPAD ERROR: No element selected');
    return;
  }

  this.element = config.element;

  // Width can be defined on the HTML or programatically
  this._width = config.width || $(this.element).attr('data-width') || 0;
  this._height = config.height || $(this.element).attr('data-height') || 0;

  // Pen attributes
  this.color = config.color || $(this.element).attr('data-color') || '#000000';
  this.penSize = config.penSize || $(this.element).attr('data-penSize') || 5;

  // ReadOnly sketchpads may not be modified
  this.readOnly = config.readOnly ||
                  $(this.element).attr('data-readOnly') ||
                  false;
  if (!this.readOnly) {
      $(this.element).css({cursor: 'crosshair'});
  }

  // Stroke control variables
  this.strokes = config.strokes || [];
  this._currentStroke = {
    color: null,
    size: null,
    lines: [],
  };

  // Undo History
  this.undoHistory = config.undoHistory || [];

  // Animation function calls
  this.animateIds = [];

  // Set sketching state
  this._sketching = false;

  // Setup canvas sketching listeners
  this.reset();
}

//
// Private API
//

Sketchpad.prototype._cursorPosition = function(event) {
  return {
    x: event.pageX - this.canvas.offsetLeft,
    y: event.pageY - this.canvas.offsetTop,
  };
};

Sketchpad.prototype._draw = function(start, end, color, size) {
  this._stroke(start, end, color, size, 'source-over');
};

Sketchpad.prototype._erase = function(start, end, color, size) {
  this._stroke(start, end, color, size, 'destination-out');
};

Sketchpad.prototype._stroke = function(start, end, color, size, compositeOperation) {
  this.context.save();
  this.context.lineJoin = 'round';
  this.context.lineCap = 'round';
  this.context.strokeStyle = color;
  this.context.lineWidth = size;
  this.context.globalCompositeOperation = compositeOperation;
  this.context.beginPath();
  this.context.moveTo(start.x, start.y);
  this.context.lineTo(end.x, end.y);
  this.context.closePath();
  this.context.stroke();

  this.context.restore();
};

//
// Callback Handlers
//

Sketchpad.prototype._mouseDown = function(event) {
  this._lastPosition = this._cursorPosition(event);
  this._currentStroke.color = this.color;
  this._currentStroke.size = this.penSize;
  this._currentStroke.lines = [];
  this._sketching = true;
  this.canvas.addEventListener('mousemove', this._mouseMove);
};

Sketchpad.prototype._mouseUp = function(event) {
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('mousemove', this._mouseMove);
};

Sketchpad.prototype._mouseMove = function(event) {
  var currentPosition = this._cursorPosition(event);

  this._draw(this._lastPosition, currentPosition, this.color, this.penSize);
  this._currentStroke.lines.push({
    start: $.extend(true, {}, this._lastPosition),
    end: $.extend(true, {}, currentPosition),
  });

  this._lastPosition = currentPosition;
};

Sketchpad.prototype._touchStart = function(event) {
  event.preventDefault();
  if (this._sketching) {
    return;
  }
  this._lastPosition = this._cursorPosition(event.changedTouches[0]);
  this._currentStroke.color = this.color;
  this._currentStroke.size = this.penSize;
  this._currentStroke.lines = [];
  this._sketching = true;
  this.canvas.addEventListener('touchmove', this._touchMove, false);
};

Sketchpad.prototype._touchEnd = function(event) {
  event.preventDefault();
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchCancel = function(event) {
  event.preventDefault();
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchLeave = function(event) {
  event.preventDefault();
  if (this._sketching) {
    this.strokes.push($.extend(true, {}, this._currentStroke));
    this._sketching = false;
  }
  this.canvas.removeEventListener('touchmove', this._touchMove);
};

Sketchpad.prototype._touchMove = function(event) {
  event.preventDefault();
  var currentPosition = this._cursorPosition(event.changedTouches[0]);

  this._draw(this._lastPosition, currentPosition, this.color, this.penSize);
  this._currentStroke.lines.push({
    start: $.extend(true, {}, this._lastPosition),
    end: $.extend(true, {}, currentPosition),
  });

  this._lastPosition = currentPosition;
};

//
// Public API
//

Sketchpad.prototype.reset = function() {
  // Set attributes
  this.canvas = $(this.element)[0];
  this.canvas.width = this._width;
  this.canvas.height = this._height;
  this.context = this.canvas.getContext('2d');

  // Setup event listeners
  this.redraw(this.strokes);

  if (this.readOnly) {
    return;
  }

  // Mouse
  this.canvas.addEventListener('mousedown', this._mouseDown);
  this.canvas.addEventListener('mouseout', this._mouseUp);
  this.canvas.addEventListener('mouseup', this._mouseUp);

  // Touch
  this.canvas.addEventListener('touchstart', this._touchStart);
  this.canvas.addEventListener('touchend', this._touchEnd);
  this.canvas.addEventListener('touchcancel', this._touchCancel);
  this.canvas.addEventListener('touchleave', this._touchLeave);
};

Sketchpad.prototype.drawStroke = function(stroke) {
  for (var j = 0; j < stroke.lines.length; j++) {
    var line = stroke.lines[j];
    this._draw(line.start, line.end, stroke.color, stroke.size);
  }
};

Sketchpad.prototype.redraw = function(strokes) {
  for (var i = 0; i < strokes.length; i++) {
    this.drawStroke(strokes[i]);
  }
};

Sketchpad.prototype.toObject = function() {
  return {
    width: this.canvas.width,
    height: this.canvas.height,
    strokes: this.strokes,
    undoHistory: this.undoHistory,
  };
};

Sketchpad.prototype.toJSON = function() {
  return JSON.stringify(this.toObject());
};

Sketchpad.prototype.animate = function(ms, loop, loopDelay) {
  this.clear();
  var delay = ms;
  var callback = null;
  for (var i = 0; i < this.strokes.length; i++) {
    var stroke = this.strokes[i];
    for (var j = 0; j < stroke.lines.length; j++) {
      var line = stroke.lines[j];
      callback = this._draw.bind(this, line.start, line.end,
                                 stroke.color, stroke.size);
      this.animateIds.push(setTimeout(callback, delay));
      delay += ms;
    }
  }
  if (loop) {
    loopDelay = loopDelay || 0;
    callback = this.animate.bind(this, ms, loop, loopDelay);
    this.animateIds.push(setTimeout(callback, delay + loopDelay));
  }
};

Sketchpad.prototype.cancelAnimation = function() {
  for (var i = 0; i < this.animateIds.length; i++) {
    clearTimeout(this.animateIds[i]);
  }
};

Sketchpad.prototype.clear = function() {
  this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
};

Sketchpad.prototype.undo = function() {
  this.clear();
  var stroke = this.strokes.pop();
  if (stroke) {
    this.undoHistory.push(stroke);
    this.redraw(this.strokes);
  }
};

Sketchpad.prototype.redo = function() {
  var stroke = this.undoHistory.pop();
  if (stroke) {
    this.strokes.push(stroke);
    this.drawStroke(stroke);
  }
};
<|endoftext|>


<commit_before>// PRIVATE HELPER FUNCTIONS
//

/*!
 * @param {jQuery} $canvasContainer The element that contains the Bezierizer
 * DOM elements.
 * @param {jQuery} $handle The handle to compute X for.
 */
function getHandleX ($canvasContainer, $handle) {
  var handleX = parseInt($handle.css('left'), 10);
  return handleX / ($canvasContainer.width() - $handle.outerWidth(true));
}

/*!
 * @param {jQuery} $canvasContainer The element that contains the Bezierizer
 * DOM elements.
 * @param {jQuery} $handle The handle to compute Y for.
 */
function getHandleY ($canvasContainer, $handle) {
  var handleY = parseInt($handle.css('top'), 10);
  return handleY / ($canvasContainer.height() - $handle.outerHeight(true));
}

/**
 * @param {Element} container The container element to insert the Bezierizer widget into.
 * @constructor
 */
function Bezierizer (container) {
  this.$el = $(container);
  this.$el.append($(HTML_TEMPLATE));

  this._$canvasContainer = this.$el.find('.bezierizer-canvas-container');
  this._$canvas = this._$canvasContainer.find('canvas');
  this._$handles = this._$canvasContainer.find('.bezierizer-handle');

  this._ctx = this._$canvas[0].getContext('2d');
  var ctx = this._ctx;
  ctx.lineWidth = 3;
  ctx.strokeStyle = '#f0f';

  this._$canvas[0].height = this._$canvas.height();
  this._$canvas[0].width = this._$canvas.width();
  this._$handles.dragon({
    within: this._$canvasContainer
  });

  this.initBindings();
}

Bezierizer.prototype.initBindings = function () {
  this._$canvasContainer.on(
      'drag', '.bezierizer-handle', $.proxy(function (evt) {
    this.redraw();
    this.$el.trigger('change');
  }, this));
};

/**
 * @return {Object} Contains normalized x1, y1, x2 and y2 numbers.
 */
Bezierizer.prototype.getHandlePositions = function () {
  var $canvasContainer = this._$canvasContainer;

  return {
     x1: getHandleX($canvasContainer, this._$handles.eq(0))
    ,y1: getHandleY($canvasContainer, this._$handles.eq(0))
    ,x2: getHandleX($canvasContainer, this._$handles.eq(1))
    ,y2: getHandleY($canvasContainer, this._$handles.eq(1))
  };
};

Bezierizer.prototype.redraw = function () {
  var handlePositions = this.getHandlePositions();
  var height = this._$canvas[0].height;
  var width = this._$canvas[0].width;
  var x1 = handlePositions.x1 * width;
  var y1 = handlePositions.y1 * height;
  var x2 = handlePositions.x2 * width;
  var y2 = handlePositions.y2 * height;

  var ctx = this._ctx;
  ctx.clearRect(0, 0, width, height);
  ctx.beginPath();
  ctx.moveTo(x1, y1);
  ctx.lineTo(0, 0);
  ctx.bezierCurveTo(x1, y1, x2, y2, width, height);
  ctx.lineTo(x2, y2);
  ctx.stroke();
  ctx.closePath();
};
<commit_msg>Some refactoring, and implementes setHandlePositions.<commit_after>// PRIVATE HELPER FUNCTIONS
//

/*!
 * @param {jQuery} $canvasContainer The element that contains the Bezierizer
 * DOM elements.
 * @param {jQuery} $handle The handle to compute X for.
 */
function getHandleX ($canvasContainer, $handle) {
  var handleX = parseInt($handle.css('left'), 10);
  return handleX / ($canvasContainer.width() - $handle.outerWidth(true));
}

/*!
 * @param {jQuery} $canvasContainer The element that contains the Bezierizer
 * DOM elements.
 * @param {jQuery} $handle The handle to compute Y for.
 */
function getHandleY ($canvasContainer, $handle) {
  var handleY = parseInt($handle.css('top'), 10);
  return handleY / ($canvasContainer.height() - $handle.outerHeight(true));
}

/**
 * @param {Element} container The container element to insert the Bezierizer widget into.
 * @constructor
 */
function Bezierizer (container) {
  this.$el = $(container);
  this.$el.append($(HTML_TEMPLATE));

  this._$canvasContainer = this.$el.find('.bezierizer-canvas-container');
  this._$canvas = this._$canvasContainer.find('canvas');
  this._$handles = this._$canvasContainer.find('.bezierizer-handle');

  var width = this._$canvas.width();
  var height = this._$canvas.height();
  this._ctx = this._$canvas[0].getContext('2d');
  var ctx = this._ctx;
  ctx.lineWidth = 3;
  ctx.strokeStyle = '#f0f';
  this._$canvas[0].height = height;
  this._$canvas[0].width = width;

  this._$handles.dragon({
    within: this._$canvasContainer
  });
  this._$handles.eq(0).css({
    left: 0
    ,top: height * 0.5
  });
  this._$handles.eq(1).css({
    left: width
    ,top: height * 0.5
  });

  this._initBindings();
  this._updateInternalStateFromDOM();
  this.redraw();
}

/*!
 * @private
 */
Bezierizer.prototype._initBindings = function () {
  this._$canvasContainer.on(
      'drag', '.bezierizer-handle', $.proxy(function (evt) {
    this._updateInternalStateFromDOM();
    this.redraw();
    this.$el.trigger('change');
  }, this));
};

/*!
 * @private
 */
Bezierizer.prototype._updateInternalStateFromDOM = function () {
  var $canvasContainer = this._$canvasContainer;

  this._points = {
     x1: getHandleX($canvasContainer, this._$handles.eq(0))
    ,y1: getHandleY($canvasContainer, this._$handles.eq(0))
    ,x2: getHandleX($canvasContainer, this._$handles.eq(1))
    ,y2: getHandleY($canvasContainer, this._$handles.eq(1))
  };
};

/**
 * @return {Object} Contains normalized x1, y1, x2 and y2 numbers.
 */
Bezierizer.prototype.getHandlePositions = function () {
  return $.extend({}, this._points);
};

/**
 * @param {Object} points An object that may contain numbers representing any or all of x1, y1, x2, and y2.
 */
Bezierizer.prototype.setHandlePositions = function (points) {
  $.extend(this._points, points);

  this._$handles.eq(0).css('left', this._points.x1);
  this._$handles.eq(0).css('top',  this._points.y1);
  this._$handles.eq(1).css('left', this._points.x2);
  this._$handles.eq(1).css('top',  this._points.y2);

  this.redraw();
};

Bezierizer.prototype.redraw = function () {
  var points = this._points;
  var height = this._$canvas[0].height;
  var width = this._$canvas[0].width;
  var x1 = points.x1 * width;
  var y1 = points.y1 * height;
  var x2 = points.x2 * width;
  var y2 = points.y2 * height;

  var ctx = this._ctx;
  ctx.clearRect(0, 0, width, height);
  ctx.beginPath();
  ctx.moveTo(x1, y1);
  ctx.lineTo(0, 0);
  ctx.bezierCurveTo(x1, y1, x2, y2, width, height);
  ctx.lineTo(x2, y2);
  ctx.stroke();
  ctx.closePath();
};
<|endoftext|>


<commit_before>'use babel';

import { BufferedProcess, Emitter, CompositeDisposable } from 'atom';
import path from 'path';
//import pty from 'pty.js';
//import pty from 'node-pty';
import execSeries from 'exec-series';

export default class CommandRunner {

  constructor() {
    this.running = false;
    this.subscriptions = new CompositeDisposable();
    this.emitter = new Emitter();
  }

  spawnProcess(command) {
    this.modified_spawnProcess(command);
    // original_spawnProcess(command);
  }

  original_spawnProcess(command) {
    this.running = true;

    let shell = atom.config.get('run-command.shellCommand') || '/bin/bash';
    let useLogin = atom.config.get('run-command.useLoginShell');

    let args = ['-c', command];
    if (useLogin) {
      args = ['-l'].concat(args);
    }

    this.term = pty.spawn(shell, ['-c', command], {
      name: 'xterm-color',
      cwd: this.constructor.workingDirectory(),
      env: process.env
    }
    );

    this.term.on('data', data => {
      return this.emitter.emit('data', data);
    });
    this.term.on('exit', () => {
      this.running = false;
      return this.emitter.emit('exit');
    });
    return this.term.on('close', () => {
      this.running = false;
      return this.emitter.emit('close');
    });
  }

  modified_spawnProcess(command) {
    this.running = true;

    let shell = atom.config.get('run-command.shellCommand') || '/bin/bash';
    let useLogin = atom.config.get('run-command.useLoginShell');

    let args = ['-c', command];
    if (useLogin) {
      args = ['-l'].concat(args);
    }

    execSeries([command], (err, stdouts, stderrs) => {

      this.emitter.emit('data', stdouts);
      this.emitter.emit('data', stderrs);
      this.emitter.emit('close');
    })
  }

  static homeDirectory() {
    return process.env['HOME'] || process.env['USERPROFILE'] || '/';
  }

  static workingDirectory() {
    let editor = atom.workspace.getActiveTextEditor();
    let activePath = editor != null ? editor.getPath() : undefined;
    let relative = atom.project.relativizePath(activePath);
    if (activePath != null) {
      return relative[0] || path.dirname(activePath);
    } else {
      return __guard__(atom.project.getPaths(), x => x[0]) || this.homeDirectory();
    }
  }

  onCommand(handler) {
    return this.emitter.on('command', handler);
  }
  onData(handler) {
    return this.emitter.on('data', handler);
  }
  onExit(handler) {
    return this.emitter.on('exit', handler);
  }
  onKill(handler) {
    return this.emitter.on('kill', handler);
  }
  onClose(handler) {
    return this.emitter.on('close', handler);
  }

  run(command) {
    return new Promise((function(resolve, reject) {
      this.kill();
      this.emitter.emit('command', command);

      let result = {
        output: '',
        exited: false,
        signal: null
      };

      this.spawnProcess(command);

      this.subscriptions.add(this.onData(data => {
        return result.output += data;
      })
      );
      this.subscriptions.add(this.onClose(() => {
        result.exited = true;
        return resolve(result);
      })
      );
      return this.subscriptions.add(this.onKill(signal => {
        result.signal = signal;
        return resolve(result);
      })
      );
    }.bind(this)));
  }

  kill(signal) {
    if (!signal) { signal = 'SIGTERM'; }

    if ((this.term != null) && this.running) {
      this.emitter.emit('kill', signal);
      process.kill(this.term.pid, signal);
      this.term.destroy();
      this.term = null;

      this.subscriptions.dispose();
      return this.subscriptions.clear();
    }
  }
};

function __guard__(value, transform) {
  return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined;
}
<commit_msg>still trying to get node-pty or pty.js working<commit_after>'use babel';

import { BufferedProcess, Emitter, CompositeDisposable } from 'atom';
import path from 'path';
// import pty from 'pty.js';
// import pty from 'node-pty';
import execSeries from 'exec-series';

export default class CommandRunner {

  constructor() {
    this.running = false;
    this.subscriptions = new CompositeDisposable();
    this.emitter = new Emitter();
  }

  spawnProcess(command) {
    this.modified_spawnProcess(command);
    //this.original_spawnProcess(command);
  }

  original_spawnProcess(command) {
    this.running = true;

    let shell = atom.config.get('run-command.shellCommand') || '/bin/bash';
    let useLogin = atom.config.get('run-command.useLoginShell');

    let args = ['-c', command];
    if (useLogin) {
      args = ['-l'].concat(args);
    }

    this.term = pty.spawn(shell, ['-c', command], {
      name: 'xterm-color',
      cwd: this.constructor.workingDirectory(),
      env: process.env
    }
    );

    this.term.on('data', data => {
      return this.emitter.emit('data', data);
    });
    this.term.on('exit', () => {
      this.running = false;
      return this.emitter.emit('exit');
    });
    return this.term.on('close', () => {
      this.running = false;
      return this.emitter.emit('close');
    });
  }

  modified_spawnProcess(command) {
    this.running = true;

    let shell = atom.config.get('run-command.shellCommand') || '/bin/bash';
    let useLogin = atom.config.get('run-command.useLoginShell');

    let args = ['-c', command];
    if (useLogin) {
      args = ['-l'].concat(args);
    }

    execSeries([command], (err, stdouts, stderrs) => {

      this.emitter.emit('data', stdouts);
      this.emitter.emit('data', stderrs);
      this.emitter.emit('close');
    })
  }

  static homeDirectory() {
    return process.env['HOME'] || process.env['USERPROFILE'] || '/';
  }

  static workingDirectory() {
    let editor = atom.workspace.getActiveTextEditor();
    let activePath = editor != null ? editor.getPath() : undefined;
    let relative = atom.project.relativizePath(activePath);
    if (activePath != null) {
      return relative[0] || path.dirname(activePath);
    } else {
      return __guard__(atom.project.getPaths(), x => x[0]) || this.homeDirectory();
    }
  }

  onCommand(handler) {
    return this.emitter.on('command', handler);
  }
  onData(handler) {
    return this.emitter.on('data', handler);
  }
  onExit(handler) {
    return this.emitter.on('exit', handler);
  }
  onKill(handler) {
    return this.emitter.on('kill', handler);
  }
  onClose(handler) {
    return this.emitter.on('close', handler);
  }

  run(command) {
    return new Promise((function(resolve, reject) {
      this.kill();
      this.emitter.emit('command', command);

      let result = {
        output: '',
        exited: false,
        signal: null
      };

      this.spawnProcess(command);

      this.subscriptions.add(this.onData(data => {
        return result.output += data;
      })
      );
      this.subscriptions.add(this.onClose(() => {
        result.exited = true;
        return resolve(result);
      })
      );
      return this.subscriptions.add(this.onKill(signal => {
        result.signal = signal;
        return resolve(result);
      })
      );
    }.bind(this)));
  }

  kill(signal) {
    if (!signal) { signal = 'SIGTERM'; }

    if ((this.term != null) && this.running) {
      this.emitter.emit('kill', signal);
      process.kill(this.term.pid, signal);
      this.term.destroy();
      this.term = null;

      this.subscriptions.dispose();
      return this.subscriptions.clear();
    }
  }
};

function __guard__(value, transform) {
  return (typeof value !== 'undefined' && value !== null) ? transform(value) : undefined;
}
<|endoftext|>


<commit_before>'use strict';

const tryCatch = require('try-catch');
const ifNotFound = require('../if-not-found');

module.exports = (runners, options, fn) => {
    let names = options.names;
    const all = options.all;

    if (!all && !names.length)
        return fn(Error('name could not be empty'));

    if (all)
        names = runners.map((runner) => runner.name);

    const error = tryCatch(() => {
        names.forEach((name) => {
            ifNotFound(name, runners);
        });
    });

    if (error)
        return fn(error);

    const result = runners.filter((runner) => {
        return !names.includes(runner.name);
    });

    fn(null, result);
};

<commit_msg>refactor(longrun) finish: functional<commit_after>'use strict';

const tryCatch = require('try-catch');
const currify = require('currify');
const squad = require('squad');

const ifNotFound = require('../if-not-found');

const ifNoName = currify((names) => {
    if (!names.length)
        throw Error('name could not be empty');

    return names;
});

const whatIfNotFound = currify((runners, names) => {
    names.forEach((name) => {
        ifNotFound(name, runners);
    });

    return names;
});

const filter = currify((runners, names) => {
    return runners.filter((runner) => {
        return !names.includes(runner.name);
    });
});

module.exports = (runners, options, cb) => {
    const names = options.names;
    const all = options.all;

    if (all)
        return cb(null, []);

    const finish = squad.apply(null, [
        filter(runners),
        whatIfNotFound(runners),
        ifNoName
   ]);

    let result;
    const error = tryCatch(() => {
        result = finish(names);
    });

    cb(error, result);
};

<|endoftext|>


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

/**
 * @module Vik
 * @author Adam Timberlake <adam.timberlake@gmail.com>
 * @link http://github.com/Wildhoney/Vik
 */
(function vik($process) {

    "use strict";

    // Title to use for the process.
    $process.title = 'vik';

    // Dependencies for the messages.
    var cmd    = require('child_process').exec,
        clc    = require('cli-color'),
        parent = require('parentpath'),
        path   = require('path'),
        nopt   = require('nopt'),
        pad    = require('pad');

    // Define the options for the parameters to be passed in.
    var options      = { tag: Boolean, push: Boolean },
        shortOptions = { t : '--tag', p: '--push' },
        parseOptions = nopt(options, shortOptions, $process.argv, 2);

    /**
     * @method outputMessage
     * @param message {String}
     * @param colour {Number}
     * @param backgroundColour {Number}
     * @return {void}
     */
    var outputMessage = function outputMessage(message, colour, backgroundColour) {

        var outputMessage = clc.xterm(colour).bgXterm(backgroundColour),
            paddedMessage = '  ' + message + '.  ';

        console.log();
        console.log(outputMessage(pad(paddedMessage.length, ' ', ' ')));
        console.log(outputMessage(paddedMessage));
        console.log(outputMessage(pad(paddedMessage.length, ' ', ' ')));
        console.log();

    };

    if (!$process.argv[2]) {

        // We couldn't find any instruction for which value to increment.
        outputMessage('Forgot to specify major/minor/patch', 88, 218);
        return;

    }

    /**
     * @property taskOptions
     * @type {Object}
     */
    var taskOptions = { tagged: false, pushed: false };

    // List of supported modules mapping their respective JSON configuration documents
    // to their name.
    var supportedModules = [
        { name: 'npm', document: 'package.json' },
        { name: 'Bower', document: 'bower.json' },
        { name: 'Component', document: 'component.json' }
    ];

    // Iterate over each file that we wish to change the version for.
    supportedModules.forEach(function forEach(module) {

        var name = module.name,
            file = module.document;

        parent(file, function parentDirectory(directory) {

            if (!directory) {

                // We were unable to find the file, so let's do nothing!
                return;

            }

            // Resolve the file to the parent directory.
            file = directory + path.sep + file;

            // All the other dependencies.
            var grunt   = require('grunt'),
                fs      = require('fs'),
                which   = $process.argv[2].trim(),
                pkg     = grunt.file.readJSON(file),
                version = pkg.version,
                format  = require('format-json');

            // Parse the version major.minor.patch.
            var parsed  = version.match(/(\d+)\.(\d+)\.(\d+)/),
                major   = parseInt(parsed[1]),
                minor   = parseInt(parsed[2]),
                patch   = parseInt(parsed[3]);

            switch (which) {

                // Which version are we going to increment?
                case ('major'): case ('major+'): case ('major++'): major++; minor = 0; patch = 0; break;
                case ('minor'): case ('minor+'): case ('minor++'): minor++; patch = 0; break;
                case ('patch'): case ('patch+'): case ('patch++'): patch++; break;

                // Or maybe we wish to decrement instead?
                case ('major-'): case ('major--'): major--; minor = 0; patch = 0; break;
                case ('minor-'): case ('minor--'): minor--; patch = 0; break;
                case ('patch-'): case ('patch--'): patch--; break;

                default:

                    // Otherwise we're going to assume the developer is attempting to set an explicit
                    // version number.
                    var match = which.match(/(\d+)\.(\d+)\.(\d+)/);

                    if (match) {
                        major = match[1];
                        minor = match[2];
                        patch = match[3];
                    }

            }

            // Update the version with the updated value, and then execute
            // the `npm version` command.
            version = major + '.' + minor + '.' + patch;

            // Here we go with the versioning, sunshine!
            pkg.version = version;

            // Determine if we should be adding the tag to Git.
            if (parseOptions.tag && !taskOptions.tagged) {
                taskOptions.tagged = true;
                outputMessage('Added Git tag version v' + version, 22, 122);
                cmd('git tag v' + version);
            }

            // Determine if we should push the tag via Git.
            if (parseOptions.push && !taskOptions.pushed) {
                outputMessage('Pushed Git tag version v' + version, 22, 122);
                cmd('git push --tags');
            }

            fs.writeFile(file, format.plain(pkg), function writeFile(error) {

                if (error) {
                    outputMessage('Insufficient permissions to write to ' + file, 88, 218);
                    return;
                }

                outputMessage('Updated ' + name + ' version to ' + version, 22, 122);

            });

        });

    });

})(process);<commit_msg>Adds support for Expo<commit_after>#!/usr/bin/env node

/**
 * @module Vik
 * @author Adam Timberlake <adam.timberlake@gmail.com>
 * @link http://github.com/Wildhoney/Vik
 */
(function vik($process) {

    "use strict";

    // Title to use for the process.
    $process.title = 'vik';

    // Dependencies for the messages.
    var cmd    = require('child_process').exec,
        clc    = require('cli-color'),
        parent = require('parentpath'),
        path   = require('path'),
        nopt   = require('nopt'),
        pad    = require('pad');

    // Define the options for the parameters to be passed in.
    var options      = { tag: Boolean, push: Boolean },
        shortOptions = { t : '--tag', p: '--push' },
        parseOptions = nopt(options, shortOptions, $process.argv, 2);

    /**
     * @method outputMessage
     * @param message {String}
     * @param colour {Number}
     * @param backgroundColour {Number}
     * @return {void}
     */
    var outputMessage = function outputMessage(message, colour, backgroundColour) {

        var outputMessage = clc.xterm(colour).bgXterm(backgroundColour),
            paddedMessage = '  ' + message + '.  ';

        console.log();
        console.log(outputMessage(pad(paddedMessage.length, ' ', ' ')));
        console.log(outputMessage(paddedMessage));
        console.log(outputMessage(pad(paddedMessage.length, ' ', ' ')));
        console.log();

    };

    if (!$process.argv[2]) {

        // We couldn't find any instruction for which value to increment.
        outputMessage('Forgot to specify major/minor/patch', 88, 218);
        return;

    }

    /**
     * @property taskOptions
     * @type {Object}
     */
    var taskOptions = { tagged: false, pushed: false };

    // List of supported modules mapping their respective JSON configuration documents
    // to their name.
    var supportedModules = [
        { name: 'npm', document: 'package.json' },
        { name: 'Bower', document: 'bower.json' },
        { name: 'Component', document: 'component.json' },
        { name: 'Expo', document: 'app.json' }
    ];

    // Iterate over each file that we wish to change the version for.
    supportedModules.forEach(function forEach(module) {

        var name = module.name,
            file = module.document;

        parent(file, function parentDirectory(directory) {

            if (!directory) {

                // We were unable to find the file, so let's do nothing!
                return;

            }

            // Resolve the file to the parent directory.
            file = directory + path.sep + file;

            // All the other dependencies.
            var grunt   = require('grunt'),
                fs      = require('fs'),
                which   = $process.argv[2].trim(),
                pkg     = grunt.file.readJSON(file),
                version = pkg.version,
                format  = require('format-json');

            if (name == 'Expo') version = pkg.expo.version;

            // Parse the version major.minor.patch.
            var parsed  = version.match(/(\d+)\.(\d+)\.(\d+)/),
                major   = parseInt(parsed[1]),
                minor   = parseInt(parsed[2]),
                patch   = parseInt(parsed[3]);

            switch (which) {

                // Which version are we going to increment?
                case ('major'): case ('major+'): case ('major++'): major++; minor = 0; patch = 0; break;
                case ('minor'): case ('minor+'): case ('minor++'): minor++; patch = 0; break;
                case ('patch'): case ('patch+'): case ('patch++'): patch++; break;

                // Or maybe we wish to decrement instead?
                case ('major-'): case ('major--'): major--; minor = 0; patch = 0; break;
                case ('minor-'): case ('minor--'): minor--; patch = 0; break;
                case ('patch-'): case ('patch--'): patch--; break;

                default:

                    // Otherwise we're going to assume the developer is attempting to set an explicit
                    // version number.
                    var match = which.match(/(\d+)\.(\d+)\.(\d+)/);

                    if (match) {
                        major = match[1];
                        minor = match[2];
                        patch = match[3];
                    }

            }

            // Update the version with the updated value, and then execute
            // the `npm version` command.
            version = major + '.' + minor + '.' + patch;

            // Here we go with the versioning, sunshine!
            if (name === 'Expo') {
              pkg.expo.version = version;
            } else {
              pkg.version = version;
            }

            // Determine if we should be adding the tag to Git.
            if (parseOptions.tag && !taskOptions.tagged) {
                taskOptions.tagged = true;
                outputMessage('Added Git tag version v' + version, 22, 122);
                cmd('git tag v' + version);
            }

            // Determine if we should push the tag via Git.
            if (parseOptions.push && !taskOptions.pushed) {
                outputMessage('Pushed Git tag version v' + version, 22, 122);
                cmd('git push --tags');
            }

            fs.writeFile(file, format.plain(pkg), function writeFile(error) {

                if (error) {
                    outputMessage('Insufficient permissions to write to ' + file, 88, 218);
                    return;
                }

                outputMessage('Updated ' + name + ' version to ' + version, 22, 122);

            });

        });

    });

})(process);
<|endoftext|>


<commit_before>/**
 * Created by kelvinzhang on 6/24/17.
 */

function ActuationDemo(id, dist1, turn, dist2, a1, a2, a3, a4)
{
	this.scale = 50;
	//the canvas element
	this.canvas = document.getElementById(id);
	this.view = new View(this.canvas, this.scale);
	this.ctx = this.canvas.getContext('2d');

	//Distance of first forward movement
	this.firstMove = dist1;
	//Angle of first turn
	this.turn = turn;
	//Distance of second forward movement
	this.secondMove = dist2;

	//Noise parameters
	this.motionModel = new OdometryModel(a1, a2, a3, a4);

	//world size information
	this.width = this.canvas.width/this.scale;
	this.height = this.canvas.height/this.scale;

	//place the robot on a random spot
	this.x = random()*this.width;
	this.y = random()*this.height;
	this.dir = random()*TWO_PI;

	this.drawRobot();

	const self = this;
	this.canvas.onmousedown = function(event){return self.mouseDown(event)};
}

ActuationDemo.prototype.drawRobot = function()
{
	clearCanvas(this.canvas);
	this.ctx.strokeStyle = 'black';
	this.ctx.drawRobot(this.x, this.y, this.dir, 0.2);

	this.ctx.strokeStyle = 'blue';
	//location after first move
	const x1 = this.x + cos(this.dir)*this.firstMove;
	const y1 = this.y + sin(this.dir)*this.firstMove;
	this.ctx.strokeLine(this.x, this.y, x1, y1);

	//direction after first turn
	const dir = this.dir + this.turn;

	//location after the second move
	var x2 = x1 + cos(dir)*this.secondMove;
	var y2 = y1 + sin(dir)*this.secondMove;
	this.ctx.strokeLine(x1, y1, x2, y2);

	if(typeof this.p1 !== 'undefined')
	{
		this.ctx.strokeStyle = 'red';
		this.ctx.strokeLine(this.x, this.y, this.p1.x, this.p1.y);
		this.ctx.strokeLine(this.p1.x, this.p1.y, this.p2.x, this.p2.y);
	}
};

ActuationDemo.prototype.mouseDown = function(event)
{
	//Shorthand for this.view and this.ctx
	const view = this.view;

	var coor = getClickLoc(event);
	const x = view.toWorldX(coor.x);
	const y = view.toWorldY(coor.y);

	//update robot's location
	this.x = x;
	this.y = y;

	//prevent drawing old path
	this.p1 = this.p2 = undefined;

	this.drawRobot();
	const self = this;
	this.canvas.onmousemove = function(event){return self.trackDirection(event);};
	this.canvas.onmouseup = function(event){return self.mouseUp(event);};
	this.canvas.onmouseout = this.canvas.onmouseup;
};

ActuationDemo.prototype.trackDirection = function(event)
{
	const view = this.view;
	const coor = getClickLoc(event);
	const x = view.toWorldX(coor.x);
	const y = view.toWorldY(coor.y);

	this.dir = atan2(y - this.y, x - this.x);
	this.drawRobot();
};

ActuationDemo.prototype.mouseUp = function(event)
{
	this.canvas.onmousemove = undefined;
	this.canvas.onmouseout = undefined;
	this.canvas.onmouseup = undefined;

	this.drawActuation();
	this.drawRobot();
	this.lastFrame = Date.now();
	const self = this;
	requestAnimationFrame(function(timestamp){self.frame(timestamp);});
};

ActuationDemo.prototype.drawActuation = function()
{
	//planned location after first move
	const x1 = this.x + cos(this.dir)*this.firstMove;
	const y1 = this.y + sin(this.dir)*this.firstMove;

	//direction after first turn
	const dir = this.dir + this.turn;

	//planned location after the second move
	const x2 = x1 + cos(dir)*this.secondMove;
	const y2 = y1 + sin(dir)*this.secondMove;

	this.u1 = new Odometry(new RobotState(this.x, this.y, this.dir),
		new RobotState(x1, y1, dir));
	this.u2 = new Odometry(new RobotState(x1, y1, dir),
		new RobotState(x2, y2, dir));

	//actual location after first move
	this.p1 = this.motionModel.sample(this.u1, new RobotState(this.x, this.y, this.dir));
	//actual location after the second move
	this.p2 = this.motionModel.sample(this.u2, this.p1);
};

ActuationDemo.prototype.frame = function(timestamp)
{
	this.fps = 60/(timestamp-this.lastFrame);
	this.lastFrame = timestamp;

};

ActuationDemo.prototype.setDist1 = function(dist1)
{
	this.firstMove = dist1;
	this.drawActuation();
	this.drawRobot();
};

ActuationDemo.prototype.setTurnAngle = function(turn)
{
	this.turn = turn;
	this.drawActuation();
	this.drawRobot();
};

ActuationDemo.prototype.setDist2 = function(dist2)
{
	this.secondMove = dist2;
	this.drawActuation();
	this.drawRobot();
};

ActuationDemo.prototype.setA1 = function(noise)
{
	this.motionModel.a1 = noise;
	this.drawRobot();
	this.drawActuation();
};

ActuationDemo.prototype.setA2 = function(noise)
{
	this.motionModel.a2 = noise;
	this.drawRobot();
	this.drawActuation();
};

ActuationDemo.prototype.setA3 = function(noise)
{
	this.motionModel.a3 = noise;
	this.drawRobot();
	this.drawActuation();
};

ActuationDemo.prototype.setA4 = function(noise)
{
	this.motionModel.a4 = noise;
	this.drawRobot();
	this.drawActuation();
};<commit_msg>add robot motion animation<commit_after>/**
 * Created by kelvinzhang on 6/24/17.
 */

function ActuationDemo(id, dist1, turn, dist2, a1, a2, a3, a4)
{
	this.scale = 50;
	//the canvas element
	this.canvas = document.getElementById(id);
	this.view = new View(this.canvas, this.scale);
	this.ctx = this.canvas.getContext('2d');

	//Distance of first forward movement
	this.firstMove = dist1;
	//Angle of first turn
	this.turn = turn;
	//Distance of second forward movement
	this.secondMove = dist2;

	//Noise parameters
	this.motionModel = new OdometryModel(a1, a2, a3, a4);

	//world size information
	this.width = this.canvas.width/this.scale;
	this.height = this.canvas.height/this.scale;

	//place the robot on a random spot
	this.x = random()*this.width;
	this.y = random()*this.height;
	this.dir = random()*TWO_PI;

	this.draw();

	const self = this;
	this.canvas.onmousedown = function(event){return self.mouseDown(event)};
}

ActuationDemo.prototype.draw = function()
{
	clearCanvas(this.canvas);
	this.ctx.strokeStyle = 'black';
	this.ctx.drawRobot(this.x, this.y, this.dir, 0.2);

	this.ctx.strokeStyle = 'blue';
	//location after first move
	const x1 = this.x + cos(this.dir)*this.firstMove;
	const y1 = this.y + sin(this.dir)*this.firstMove;
	this.ctx.strokeLine(this.x, this.y, x1, y1);

	//direction after first turn
	const dir = this.dir + this.turn;

	//location after the second move
	var x2 = x1 + cos(dir)*this.secondMove;
	var y2 = y1 + sin(dir)*this.secondMove;
	this.ctx.strokeLine(x1, y1, x2, y2);

	if(typeof this.p1 !== 'undefined')
	{
		this.ctx.strokeStyle = 'red';
		this.ctx.strokeLine(this.x, this.y, this.p1.x, this.p1.y);
		this.ctx.strokeLine(this.p1.x, this.p1.y, this.p2.x, this.p2.y);
		if(typeof this.curX !== 'undefined')
		{
			this.ctx.drawRobot(this.curX, this.curY, this.curDir, 0.2);
		}
	}
};

ActuationDemo.prototype.mouseDown = function(event)
{
	//Shorthand for this.view and this.ctx
	const view = this.view;

	var coor = getClickLoc(event);
	const x = view.toWorldX(coor.x);
	const y = view.toWorldY(coor.y);

	//update robot's location
	this.x = x;
	this.y = y;

	//prevent drawing old path
	this.p1 = this.p2 = this.curX = this.curY = this.curDir = undefined;

	this.draw();
	const self = this;
	this.canvas.onmousemove = function(event){return self.trackDirection(event);};
	this.canvas.onmouseup = function(event){return self.mouseUp(event);};
	this.canvas.onmouseout = this.canvas.onmouseup;
};

ActuationDemo.prototype.trackDirection = function(event)
{
	const view = this.view;
	const coor = getClickLoc(event);
	const x = view.toWorldX(coor.x);
	const y = view.toWorldY(coor.y);

	this.dir = atan2(y - this.y, x - this.x);
	this.draw();
};

ActuationDemo.prototype.mouseUp = function(event)
{
	this.canvas.onmousemove = undefined;
	this.canvas.onmouseout = undefined;
	this.canvas.onmouseup = undefined;

	this.simulateActuation();
	this.draw();
	this.startAnimation();
};

ActuationDemo.prototype.simulateActuation = function()
{
	//planned location after first move
	const x1 = this.x + cos(this.dir)*this.firstMove;
	const y1 = this.y + sin(this.dir)*this.firstMove;

	//direction after first turn
	const dir = this.dir + this.turn;

	//planned location after the second move
	const x2 = x1 + cos(dir)*this.secondMove;
	const y2 = y1 + sin(dir)*this.secondMove;

	const u1 = new Odometry(new RobotState(this.x, this.y, this.dir),
		new RobotState(x1, y1, dir));
	const u2 = new Odometry(new RobotState(x1, y1, dir),
		new RobotState(x2, y2, dir));

	//actual location after first move
	this.p1 = this.motionModel.sample(u1, new RobotState(this.x, this.y, this.dir));
	//actual location after the second move
	this.p2 = this.motionModel.sample(u2, this.p1);
};

ActuationDemo.prototype.startAnimation = function()
{
	this.lastFrame = Date.now();
	const self = this;
	this.path = [this.p1, this.p2];
	this.targetIndex = 0;
	this.curX = this.x;
	this.curY = this.y;
	requestAnimationFrame(function(timestamp){self.frame(timestamp);});
};

ActuationDemo.prototype.frame = function(timestamp)
{
	this.fps = 60/(timestamp-this.lastFrame);
	this.lastFrame = timestamp;
	var stride = 0.04;
	var x = this.curX;
	var y = this.curY;
	const EPS = 1E-6;
	while(stride > 0)
	{
		var targetPoint = this.path[this.targetIndex];

		var dist = distance(x, y, targetPoint.x, targetPoint.y);
		while(dist <= EPS)
		{
			this.targetIndex++;
			if(this.targetIndex >= this.path.length)
			{
				this.curX = this.curY = this.curDir = undefined;
				return;
			}
			targetPoint = this.path[this.targetIndex];
			dist = distance(x, y, targetPoint.x, targetPoint.y);
		}

		var cosx = (targetPoint.x-x)/dist;
		var sinx = (targetPoint.y-y)/dist;
		dist = min(dist, stride);

		x += cosx * dist;
		y += sinx * dist;
		stride -= dist;
	}

	//Move the robot
	this.curX = x;
	this.curY = y;
	this.curDir = atan2(targetPoint.y-y, targetPoint.x-x);
	this.draw();

	const self = this;
	requestAnimationFrame(function(timestamp){self.frame(timestamp);});
};

ActuationDemo.prototype.setDist1 = function(dist1)
{
	this.firstMove = dist1;
	this.simulateActuation();
	this.draw();
};

ActuationDemo.prototype.setTurnAngle = function(turn)
{
	this.turn = turn;
	this.simulateActuation();
	this.draw();
};

ActuationDemo.prototype.setDist2 = function(dist2)
{
	this.secondMove = dist2;
	this.simulateActuation();
	this.draw();
};

ActuationDemo.prototype.setA1 = function(noise)
{
	this.motionModel.a1 = noise;
	this.simulateActuation();
	this.draw();
};

ActuationDemo.prototype.setA2 = function(noise)
{
	this.motionModel.a2 = noise;
	this.simulateActuation();
	this.draw();
};

ActuationDemo.prototype.setA3 = function(noise)
{
	this.motionModel.a3 = noise;
	this.simulateActuation();
	this.draw();
};

ActuationDemo.prototype.setA4 = function(noise)
{
	this.motionModel.a4 = noise;
	this.simulateActuation();
	this.draw();
};<|endoftext|>


<commit_before>const Command          = require('./-command');
const Hook             = require('../tasks/run-hook');
const LintIndex        = require('../tasks/lint-index');
const AddCordovaJS     = require('../tasks/add-cordova-js');
const logger           = require('../utils/logger');
const requireTarget    = require('../utils/require-target');
const requireFramework = require('../utils/require-framework');
const path             = require('path');
const Promise          = require('rsvp').Promise;

module.exports = Command.extend({
  name: 'build',
  aliases: ['b'],
  description: 'Build the ember application for cordova',
  works: 'insideProject',

  /* eslint-disable max-len */
  availableOptions: [
    { name: 'platform',                            type: String,  default: 'ios' },
    { name: 'verbose',                             type: Boolean, default: false,                       aliases: ['v'] },
    { name: 'environment',                         type: String,  default: 'development',               aliases: ['e', 'env', { 'dev': 'development' }, { 'prod': 'production' }] },
    { name: 'cordova-output-path',                 type: 'Path',  default: 'corber/cordova/www',        aliases: ['op', 'out'] },
    { name: 'release',                             type: Boolean, default: false },
    { name: 'device',                              type: Boolean, default: true },
    { name: 'emulator',                            type: Boolean, default: false },
    { name: 'build-config',                        type: 'Path', aliases: ['buildConfig'] },
    { name: 'force',                               type: Boolean, default: false },
    { name: 'skip-cordova-build',                  type: Boolean, default: false, aliases: ['scb']},
    { name: 'skip-framework-build',                type: Boolean, default: false, aliases: ['sfb'] },
    { name: 'add-cordova-js',                      type: Boolean },
    { name: 'quiet',                               type: Boolean, default: false, aliases: ['q'] },

    // iOS Signing Options
    { name: 'code-sign-identity',                  type: String },
    { name: 'provisioning-profile',                type: String },
    { name: 'codesign-resource-rules',             type: String },
    { name: 'development-team',                    type: String },
    { name: 'package-type',                        type: String },

    // android Signing Options
    { name: 'keystore',                            type: String },
    { name: 'store-password',                      type: String },
    { name: 'alias',                               type: String },
    { name: 'password',                            type: String },
    { name: 'keystore-type',                       type: String },
    { name: 'gradle-arg',                          type: String },
    { name: 'cdv-build-multiple-apks',             type: Boolean },
    { name: 'cdv-version-code',                    type: String },
    { name: 'cdv-min-sdk-version',                 type: String },
    { name: 'cdv-build-tools-version',             type: String },
    { name: 'cdv-compile-sdk-version',             type: String },
    { name: 'cdv-debug-sigining-properties-file',  type: String },
    { name: 'cdv-release-sigining-properties-file', type: String }

  ],
  /* eslint-enable max-len */

  run(options) {
    this._super.apply(this, arguments);

    //lets for live reload addon service
    this.project.targetIsCordova = true;
    this.project.CORBER_PLATFORM = options.platform;

    let hook = new Hook({
      project: this.project
    });

    let indexHtmlPath = path.join(options.cordovaOutputPath, 'index.html');

    let lint = new LintIndex({
      source: indexHtmlPath
    });

    let addCordovaJS = new AddCordovaJS({
      source: indexHtmlPath
    });

    let framework = requireFramework(this.project);
    let cordovaTarget = requireTarget(this.project, options);

    logger.info('corber: Building app');

    return new Promise((resolve, reject) => {
      hook.run('beforeBuild', options)
        .then(() => framework.validateBuild(options))
        .then(() => cordovaTarget.validateBuild(options.skipCordovaBuild))
        .then(() => {
          if (options.skipFrameworkBuild !== true) {
            return framework.build(options);
          }
        })
        .then(() => {
          if (
            options.skipFrameworkBuild !== true ||
            options.addCordovaJs === true
          ) {
            return addCordovaJS.run();
          }
        })
        .then(() => {
          if (options.skipCordovaBuild !== true) {
            return cordovaTarget.build();
          }
        })
        .then(() => hook.run('afterBuild', options))
        .then(() => lint.run())
        .then(function() {
          logger.success('corber project built');
          resolve();
        })
        .catch(function(e) {
          logger.error(e);

          let validation = cordovaTarget.signingIdentityValidation;
          if (validation && validation.failed) {
            logger.warn('No signing identity has been configured for your'
              + ' xcode project. If you have received an "ARCHIVE FAILED"'
              + ' message with error code 65, you will need to run'
              + '"corber open ios" and set your development team'
              + ' (for automatic signing), or set your'
              + ` ${validation.buildConfigName} provisioning profile`
              + ' (for manual signing).');
          }
        });
    });
  }
});
<commit_msg>missing space: you will need to run"corber<commit_after>const Command          = require('./-command');
const Hook             = require('../tasks/run-hook');
const LintIndex        = require('../tasks/lint-index');
const AddCordovaJS     = require('../tasks/add-cordova-js');
const logger           = require('../utils/logger');
const requireTarget    = require('../utils/require-target');
const requireFramework = require('../utils/require-framework');
const path             = require('path');
const Promise          = require('rsvp').Promise;

module.exports = Command.extend({
  name: 'build',
  aliases: ['b'],
  description: 'Build the ember application for cordova',
  works: 'insideProject',

  /* eslint-disable max-len */
  availableOptions: [
    { name: 'platform',                            type: String,  default: 'ios' },
    { name: 'verbose',                             type: Boolean, default: false,                       aliases: ['v'] },
    { name: 'environment',                         type: String,  default: 'development',               aliases: ['e', 'env', { 'dev': 'development' }, { 'prod': 'production' }] },
    { name: 'cordova-output-path',                 type: 'Path',  default: 'corber/cordova/www',        aliases: ['op', 'out'] },
    { name: 'release',                             type: Boolean, default: false },
    { name: 'device',                              type: Boolean, default: true },
    { name: 'emulator',                            type: Boolean, default: false },
    { name: 'build-config',                        type: 'Path', aliases: ['buildConfig'] },
    { name: 'force',                               type: Boolean, default: false },
    { name: 'skip-cordova-build',                  type: Boolean, default: false, aliases: ['scb']},
    { name: 'skip-framework-build',                type: Boolean, default: false, aliases: ['sfb'] },
    { name: 'add-cordova-js',                      type: Boolean },
    { name: 'quiet',                               type: Boolean, default: false, aliases: ['q'] },

    // iOS Signing Options
    { name: 'code-sign-identity',                  type: String },
    { name: 'provisioning-profile',                type: String },
    { name: 'codesign-resource-rules',             type: String },
    { name: 'development-team',                    type: String },
    { name: 'package-type',                        type: String },

    // android Signing Options
    { name: 'keystore',                            type: String },
    { name: 'store-password',                      type: String },
    { name: 'alias',                               type: String },
    { name: 'password',                            type: String },
    { name: 'keystore-type',                       type: String },
    { name: 'gradle-arg',                          type: String },
    { name: 'cdv-build-multiple-apks',             type: Boolean },
    { name: 'cdv-version-code',                    type: String },
    { name: 'cdv-min-sdk-version',                 type: String },
    { name: 'cdv-build-tools-version',             type: String },
    { name: 'cdv-compile-sdk-version',             type: String },
    { name: 'cdv-debug-sigining-properties-file',  type: String },
    { name: 'cdv-release-sigining-properties-file', type: String }

  ],
  /* eslint-enable max-len */

  run(options) {
    this._super.apply(this, arguments);

    //lets for live reload addon service
    this.project.targetIsCordova = true;
    this.project.CORBER_PLATFORM = options.platform;

    let hook = new Hook({
      project: this.project
    });

    let indexHtmlPath = path.join(options.cordovaOutputPath, 'index.html');

    let lint = new LintIndex({
      source: indexHtmlPath
    });

    let addCordovaJS = new AddCordovaJS({
      source: indexHtmlPath
    });

    let framework = requireFramework(this.project);
    let cordovaTarget = requireTarget(this.project, options);

    logger.info('corber: Building app');

    return new Promise((resolve, reject) => {
      hook.run('beforeBuild', options)
        .then(() => framework.validateBuild(options))
        .then(() => cordovaTarget.validateBuild(options.skipCordovaBuild))
        .then(() => {
          if (options.skipFrameworkBuild !== true) {
            return framework.build(options);
          }
        })
        .then(() => {
          if (
            options.skipFrameworkBuild !== true ||
            options.addCordovaJs === true
          ) {
            return addCordovaJS.run();
          }
        })
        .then(() => {
          if (options.skipCordovaBuild !== true) {
            return cordovaTarget.build();
          }
        })
        .then(() => hook.run('afterBuild', options))
        .then(() => lint.run())
        .then(function() {
          logger.success('corber project built');
          resolve();
        })
        .catch(function(e) {
          logger.error(e);

          let validation = cordovaTarget.signingIdentityValidation;
          if (validation && validation.failed) {
            logger.warn('No signing identity has been configured for your'
              + ' xcode project. If you have received an "ARCHIVE FAILED"'
              + ' message with error code 65, you will need to run'
              + ' "corber open ios" and set your development team'
              + ' (for automatic signing), or set your'
              + ` ${validation.buildConfigName} provisioning profile`
              + ' (for manual signing).');
          }
        });
    });
  }
});
<|endoftext|>


<commit_before>#!/usr/bin/env node
'use strict';

var restify = require('restify');
//var errors = require('restify-errors');
var toCSV = require('../lib');

var pkg = require('../package.json');

// Get untrackable configurations.
var config = {};
try {
  config = require('../config.json'); //eslint-disable-line global-require
} catch (err) {
  if (!err.message || err.code !== 'MODULE_NOT_FOUND') {
    throw err;
  }
}

var serviceName = process.env.npm_package_name || pkg.name;

var server = restify.createServer({
  name:    serviceName,
  version: '1.0.0'
});

server.post('/', restify.bodyParser(), toCSV.httpHandler);

server.listen(config.port || process.env.PORT || process.env.npm_package_config_port || 15000, function () {
  const addr = server.address();
  const bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  console.log('Listening on ' + bind);
});

<commit_msg>approve console log<commit_after>#!/usr/bin/env node
'use strict';

var restify = require('restify');
//var errors = require('restify-errors');
var toCSV = require('../lib');

var pkg = require('../package.json');

// Get untrackable configurations.
var config = {};
try {
  config = require('../config.json'); //eslint-disable-line global-require
} catch (err) {
  if (!err.message || err.code !== 'MODULE_NOT_FOUND') {
    throw err;
  }
}

var serviceName = process.env.npm_package_name || pkg.name;

var server = restify.createServer({
  name:    serviceName,
  version: '1.0.0'
});

server.post('/', restify.bodyParser(), toCSV.httpHandler);

server.listen(config.port || process.env.PORT || process.env.npm_package_config_port || 15000, function () {
  const addr = server.address();
  const bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  console.log('Listening on ' + bind); // eslint-disable-line no-console
});

// 52.43.35.218
<|endoftext|>


<commit_before>var modulus = require('../modulus'),
    mongoController = require('../controllers/mongo'),
    async = require('async'),
    error = require('../common/error'),
    userConfig = require('../common/api').userConfig;

var mongo = {};

mongo.create = function(dbName, cb) {
  var createDatabase = function(dname) {
    mongoController.create(
      dname,
      userConfig.data.userId,
      function(err, database) {
        if(err) {
          err = error.handleApiError(err, 'CREATE_MONGO', cb);
          if(err.length > 0) {
            return cb(err);
          }
        }
        if(!database) {
          return cb('Could not create MongoDB database. Error from server.');
        }
        modulus.io.success('New MongoDB database ' + dname.data + ' created.');
        return cb();
    });
  }

  // If project name is passed do NOT prompt for name
  if(dbName && dbName !== '') {
    modulus.io.print('Creating MongoDB database ' + dbName.data);
    createDatabase(dbName);
  } else {
    mongo._createDatabasePrompt(function(err, name) {
      if(err) {
        return cb('Could not create MongoDB database.');
      }
      createDatabase(name);
    });
  }
};

//-------------------------------------------------------------------------------------------------
mongo._createDatabasePrompt = function(cb) {
  modulus.io.prompt.get([{
    name : 'name',
    description : 'Enter a database name:',
    maxLength : 50,
    required : true
  }], function(err, results) {
    if(err) {
      return error.handlePromptError(err, cb);
    }
    cb(null, results.name);
  });
};

module.exports = mongo;<commit_msg>added uri to message at end of database create<commit_after>var modulus = require('../modulus'),
    mongoController = require('../controllers/mongo'),
    async = require('async'),
    error = require('../common/error'),
    userConfig = require('../common/api').userConfig;

var mongo = {};

mongo.create = function(dbName, cb) {
  var createDatabase = function(dname) {
    mongoController.create(
      dname,
      userConfig.data.userId,
      function(err, database) {
        if(err) {
          err = error.handleApiError(err, 'CREATE_MONGO', cb);
          if(err.length > 0) {
            return cb(err);
          }
        }
        if(!database) {
          return cb('Could not create MongoDB database. Error from server.');
        }
        modulus.io.success('New MongoDB database ' + dname.data + ' created.');
        modulus.io.print('Database available at: ' + database.uri.data);
        return cb();
    });
  }

  // If project name is passed do NOT prompt for name
  if(dbName && dbName !== '') {
    modulus.io.print('Creating MongoDB database ' + dbName.data);
    createDatabase(dbName);
  } else {
    mongo._createDatabasePrompt(function(err, name) {
      if(err) {
        return cb('Could not create MongoDB database.');
      }
      createDatabase(name);
    });
  }
};

//-------------------------------------------------------------------------------------------------
mongo._createDatabasePrompt = function(cb) {
  modulus.io.prompt.get([{
    name : 'name',
    description : 'Enter a database name:',
    maxLength : 50,
    required : true
  }], function(err, results) {
    if(err) {
      return error.handlePromptError(err, cb);
    }
    cb(null, results.name);
  });
};

module.exports = mongo;<|endoftext|>