<commit_before>var vscode = require('vscode');
var CP = require('child_process');
var window = vscode.window;
var workspace = vscode.workspace;

var isWin = /^win/.test(process.platform);
var _channel = window.createOutputChannel('Perforce Log');

function activate() {
	_channel.appendLine("Perforce Log Output");

	vscode.commands.registerCommand('perforce.showOutput', p_showOutput);
	vscode.commands.registerCommand('perforce.add', p_add);
	vscode.commands.registerCommand('perforce.edit', p_edit);
	vscode.commands.registerCommand('perforce.revert', p_revert);
	vscode.commands.registerCommand('perforce.diff', p_diff);
	vscode.commands.registerCommand('perforce.info', p_info);
	vscode.commands.registerCommand('perforce.menuFunctions', p_menuFunction);
}
exports.activate = activate;

function buildCmdline(command, args)
{
	var cmdline = "p4";
	if (isWin) {
		cmdline += ".exe";
	}

	cmdline += " " + command;

	if (args != undefined)
		cmdline += " " + args;

	return cmdline;
}

function p_showOutput() {
	_channel.show();
}

function p_add() {
	var editor = window.activeTextEditor;
	if (!editor) {
		window.showInformationMessage("Perforce: no file selected");
		return;
	}
	if (workspace.rootPath == undefined){
		window.showInformationMessage("Perforce: no folder opened");
		return;
	}
	var uri = editor.document.uri;
	var cmdline = buildCmdline("add", '"' + uri.fsPath + '"');

	_channel.appendLine(cmdline);
	CP.exec(cmdline, {cwd: workspace.rootPath}, function (err, stdout, stderr) {
		if(err){
			_channel.show();
			_channel.appendLine("ERROR:");
			_channel.append(stderr.toString());
		}
		else {
			window.showInformationMessage("Perforce: file opened for add");
			_channel.append(stdout.toString());
		}
	});
}

function p_edit() {
	var editor = window.activeTextEditor;
	if (!editor) {
		window.showInformationMessage("Perforce: no file selected");
		return;
	}
	if (workspace.rootPath == undefined){
		window.showInformationMessage("Perforce: no folder opened");
		return;
	}
	var uri = editor.document.uri;
	var cmdline = buildCmdline("edit", '"' + uri.fsPath + '"');

	_channel.appendLine(cmdline);
	CP.exec(cmdline, {cwd: workspace.rootPath}, function (err, stdout, stderr) {
		if(err){
			_channel.show();
			_channel.appendLine("ERROR:");
			_channel.append(stderr.toString());
		}
		else {
			window.showInformationMessage("Perforce: file opened for edit");
			_channel.append(stdout.toString());
		}
	});
}

function p_revert() {
	var editor = window.activeTextEditor;
	if (!editor) {
		window.showInformationMessage("Perforce: no file selected");
		return;
	}
	if (workspace.rootPath == undefined){
		window.showInformationMessage("Perforce: no folder opened");
		return;
	}
	var uri = editor.document.uri;
	var cmdline = buildCmdline("revert", '"' + uri.fsPath + '"');

	_channel.appendLine(cmdline);
	CP.exec(cmdline, {cwd: workspace.rootPath}, function (err, stdout, stderr) {
		if(err){
			_channel.show();
			_channel.appendLine("ERROR:");
			_channel.append(stderr.toString());
		}
		else {
			window.showInformationMessage("Perforce: file reverted");
			_channel.append(stdout.toString());
		}
	});
}

function p_diff() {
	var editor = window.activeTextEditor;
	if (!editor) {
		window.showInformationMessage("Perforce: no file selected");
		return;
	}
	if (workspace.rootPath == undefined){
		window.showInformationMessage("Perforce: no folder opened");
		return;
	}
	var uri = editor.document.uri;
	var cmdline = buildCmdline("diff", '"' + uri.fsPath + '"');

	//TODO: show in a 'compare' window
	//vscode.commands.executeCommand("workbench.files.action.compareFileWith", uri.fsPath);

	_channel.appendLine(cmdline);
	CP.exec(cmdline, {cwd:workspace.rootPath}, function (err, stdout, stderr) {
		if(err){
			_channel.show();
			_channel.appendLine("ERROR:");
			_channel.append(stderr.toString());
		}
		else {
			_channel.show();
			_channel.append(stdout.toString());
		}
	});
}

function p_info() {
	var cmdline = buildCmdline("info");
	if (workspace.rootPath == undefined){
		window.showInformationMessage("Perforce: no folder opened");
		return;
	}
	if (workspace.rootPath == undefined){
		window.showInformationMessage("Perforce: no folder opened");
		return;
	}

	_channel.appendLine(cmdline);
	CP.exec(cmdline, {cwd:workspace.rootPath}, function (err, stdout, stderr) {
		if(err){
			_channel.show();
			_channel.appendLine("ERROR:");
			_channel.append(stderr.toString());
		}
		else {
			_channel.show();
			_channel.append(stdout.toString());
		}
	});
}

function p_menuFunction() {
	var items = [];
	items.push({ label: "add", description: "Open a new file to add it to the depot" });
	items.push({ label: "edit", description: "Open an existing file for edit" });
	items.push({ label: "revert", description: "Discard changes from an opened file" });
	items.push({ label: "diff", description: "Display diff of client file with depot file" });
	items.push({ label: "info", description: "Display client/server information" });
	window.showQuickPick(items, {matchOnDescription: true, placeHolder: "Choose a Perforce command:"}).then(function (selection) {
		if(selection == undefined)
			return;
		switch (selection.label) {
			case "add":
				p_add();
				break;
			case "edit":
				p_edit();
				break;
			case "revert":
				p_revert();
				break;
			case "diff":
				p_diff();
				break;
			case "info":
				p_info();
				break;
			default:
				break;
		}
	});
}
<commit_msg>Remove duplicate folder check<commit_after>var vscode = require('vscode');
var CP = require('child_process');
var window = vscode.window;
var workspace = vscode.workspace;

var isWin = /^win/.test(process.platform);
var _channel = window.createOutputChannel('Perforce Log');

function activate() {
	_channel.appendLine("Perforce Log Output");

	vscode.commands.registerCommand('perforce.showOutput', p_showOutput);
	vscode.commands.registerCommand('perforce.add', p_add);
	vscode.commands.registerCommand('perforce.edit', p_edit);
	vscode.commands.registerCommand('perforce.revert', p_revert);
	vscode.commands.registerCommand('perforce.diff', p_diff);
	vscode.commands.registerCommand('perforce.info', p_info);
	vscode.commands.registerCommand('perforce.menuFunctions', p_menuFunction);
}
exports.activate = activate;

function buildCmdline(command, args)
{
	var cmdline = "p4";
	if (isWin) {
		cmdline += ".exe";
	}

	cmdline += " " + command;

	if (args != undefined)
		cmdline += " " + args;

	return cmdline;
}

function p_showOutput() {
	_channel.show();
}

function p_add() {
	var editor = window.activeTextEditor;
	if (!editor) {
		window.showInformationMessage("Perforce: no file selected");
		return;
	}
	if (workspace.rootPath == undefined){
		window.showInformationMessage("Perforce: no folder opened");
		return;
	}
	var uri = editor.document.uri;
	var cmdline = buildCmdline("add", '"' + uri.fsPath + '"');

	_channel.appendLine(cmdline);
	CP.exec(cmdline, {cwd: workspace.rootPath}, function (err, stdout, stderr) {
		if(err){
			_channel.show();
			_channel.appendLine("ERROR:");
			_channel.append(stderr.toString());
		}
		else {
			window.showInformationMessage("Perforce: file opened for add");
			_channel.append(stdout.toString());
		}
	});
}

function p_edit() {
	var editor = window.activeTextEditor;
	if (!editor) {
		window.showInformationMessage("Perforce: no file selected");
		return;
	}
	if (workspace.rootPath == undefined){
		window.showInformationMessage("Perforce: no folder opened");
		return;
	}
	var uri = editor.document.uri;
	var cmdline = buildCmdline("edit", '"' + uri.fsPath + '"');

	_channel.appendLine(cmdline);
	CP.exec(cmdline, {cwd: workspace.rootPath}, function (err, stdout, stderr) {
		if(err){
			_channel.show();
			_channel.appendLine("ERROR:");
			_channel.append(stderr.toString());
		}
		else {
			window.showInformationMessage("Perforce: file opened for edit");
			_channel.append(stdout.toString());
		}
	});
}

function p_revert() {
	var editor = window.activeTextEditor;
	if (!editor) {
		window.showInformationMessage("Perforce: no file selected");
		return;
	}
	if (workspace.rootPath == undefined){
		window.showInformationMessage("Perforce: no folder opened");
		return;
	}
	var uri = editor.document.uri;
	var cmdline = buildCmdline("revert", '"' + uri.fsPath + '"');

	_channel.appendLine(cmdline);
	CP.exec(cmdline, {cwd: workspace.rootPath}, function (err, stdout, stderr) {
		if(err){
			_channel.show();
			_channel.appendLine("ERROR:");
			_channel.append(stderr.toString());
		}
		else {
			window.showInformationMessage("Perforce: file reverted");
			_channel.append(stdout.toString());
		}
	});
}

function p_diff() {
	var editor = window.activeTextEditor;
	if (!editor) {
		window.showInformationMessage("Perforce: no file selected");
		return;
	}
	if (workspace.rootPath == undefined){
		window.showInformationMessage("Perforce: no folder opened");
		return;
	}
	var uri = editor.document.uri;
	var cmdline = buildCmdline("diff", '"' + uri.fsPath + '"');

	//TODO: show in a 'compare' window
	//vscode.commands.executeCommand("workbench.files.action.compareFileWith", uri.fsPath);

	_channel.appendLine(cmdline);
	CP.exec(cmdline, {cwd:workspace.rootPath}, function (err, stdout, stderr) {
		if(err){
			_channel.show();
			_channel.appendLine("ERROR:");
			_channel.append(stderr.toString());
		}
		else {
			_channel.show();
			_channel.append(stdout.toString());
		}
	});
}

function p_info() {
	var cmdline = buildCmdline("info");

	if (workspace.rootPath == undefined){
		window.showInformationMessage("Perforce: no folder opened");
		return;
	}

	_channel.appendLine(cmdline);
	CP.exec(cmdline, {cwd:workspace.rootPath}, function (err, stdout, stderr) {
		if(err){
			_channel.show();
			_channel.appendLine("ERROR:");
			_channel.append(stderr.toString());
		}
		else {
			_channel.show();
			_channel.append(stdout.toString());
		}
	});
}

function p_menuFunction() {
	var items = [];
	items.push({ label: "add", description: "Open a new file to add it to the depot" });
	items.push({ label: "edit", description: "Open an existing file for edit" });
	items.push({ label: "revert", description: "Discard changes from an opened file" });
	items.push({ label: "diff", description: "Display diff of client file with depot file" });
	items.push({ label: "info", description: "Display client/server information" });
	window.showQuickPick(items, {matchOnDescription: true, placeHolder: "Choose a Perforce command:"}).then(function (selection) {
		if(selection == undefined)
			return;
		switch (selection.label) {
			case "add":
				p_add();
				break;
			case "edit":
				p_edit();
				break;
			case "revert":
				p_revert();
				break;
			case "diff":
				p_diff();
				break;
			case "info":
				p_info();
				break;
			default:
				break;
		}
	});
}
<|endoftext|>


<commit_before>// GLOBAL VARS
var socket;
var canvas;
var ctx;

var canvasData;
var data;
var type;
var stats;
var image;
var URL = window.URL ? window.URL : window.webkitURL;

//----------------------------------------------------------------------------------------------------------------
// ON READY, SETUP SOCKET!
//----------------------------------------------------------------------------------------------------------------

$(document).ready( function() {
	document.getElementById("brow").textContent = " " + BrowserDetect.browser + " "
		+ BrowserDetect.version +" " + BrowserDetect.OS +" ";

	stats = new Stats();
	stats.setMode( 0 ); // 0: fps, 1: ms

	// Align top-left
	stats.domElement.style.position = 'absolute';
	stats.domElement.style.right = '0px';
	stats.domElement.style.top = '0px';

  	document.body.appendChild( stats.domElement );
	setupSocket();

 	stats.begin();

});

//----------------------------------------------------------------------------------------------------------------
// WS:ON OPEN
//----------------------------------------------------------------------------------------------------------------
function onOpen(){
	document.getElementById("wslm_statustd").style.backgroundColor = "#40ff40";
	document.getElementById("wslm_statustd").textContent = " websocket connection opened ";
}

//----------------------------------------------------------------------------------------------------------------
// WS: ON CLOSE
//----------------------------------------------------------------------------------------------------------------
function onClose(){
	document.getElementById("wslm_statustd").style.backgroundColor = "#ff4040";
	document.getElementById("wslm_statustd").textContent = " websocket connection CLOSED ";
}

//----------------------------------------------------------------------------------------------------------------
// WS: ON MESSAGE
//----------------------------------------------------------------------------------------------------------------

var prevBlob;
function onMessage( messageEvent ){
    stats.end();
    if (messageEvent.data instanceof Blob) {
      URL.revokeObjectURL(prevBlob);
      prevBlob = URL.createObjectURL(messageEvent.data);
      // just set image.src to the blob URL, then you're all good!
      $("#loadintome").attr("src",prevBlob);
	}
    stats.begin();
}

//----------------------------------------------------------------------------------------------------------------
// setup web socket
//----------------------------------------------------------------------------------------------------------------

function setupSocket(){
	// setup!
	socket = new WebSocket( get_appropriate_ws_url());
	socket.binaryType = "arraybuffer";

	// open
	try {
		socket.onopen 		= onOpen;
		socket.onmessage 	= onMessage;
		socket.onclose 	 	= onClose;
	} catch(exception) {
		alert('Error' + exception);
	}
}<commit_msg>Fixed blob example 1<commit_after>// GLOBAL VARS
var socket;
var canvas;
var ctx;

var canvasData;
var data;
var type;
var stats;
var image;
var URL = window.URL ? window.URL : window.webkitURL;

//----------------------------------------------------------------------------------------------------------------
// ON READY, SETUP SOCKET!
//----------------------------------------------------------------------------------------------------------------

$(document).ready( function() {
	document.getElementById("brow").textContent = " " + BrowserDetect.browser + " "
		+ BrowserDetect.version +" " + BrowserDetect.OS +" ";

	stats = new Stats();
	stats.setMode( 0 ); // 0: fps, 1: ms

	// Align top-left
	stats.domElement.style.position = 'absolute';
	stats.domElement.style.right = '0px';
	stats.domElement.style.top = '0px';

  	document.body.appendChild( stats.domElement );
	setupSocket();

 	stats.begin();

});

//----------------------------------------------------------------------------------------------------------------
// WS:ON OPEN
//----------------------------------------------------------------------------------------------------------------
function onOpen(){
	document.getElementById("wslm_statustd").style.backgroundColor = "#40ff40";
	document.getElementById("wslm_statustd").textContent = " websocket connection opened ";
}

//----------------------------------------------------------------------------------------------------------------
// WS: ON CLOSE
//----------------------------------------------------------------------------------------------------------------
function onClose(){
	document.getElementById("wslm_statustd").style.backgroundColor = "#ff4040";
	document.getElementById("wslm_statustd").textContent = " websocket connection CLOSED ";
}

//----------------------------------------------------------------------------------------------------------------
// WS: ON MESSAGE
//----------------------------------------------------------------------------------------------------------------

var prevBlob;
function onMessage( messageEvent ){
    stats.end();
    if (messageEvent.data instanceof Blob) {
      URL.revokeObjectURL(prevBlob);
      prevBlob = URL.createObjectURL(messageEvent.data);
      // just set image.src to the blob URL, then you're all good!
      $("#loadintome").attr("src",prevBlob);
	}
    stats.begin();
}

//----------------------------------------------------------------------------------------------------------------
// setup web socket
//----------------------------------------------------------------------------------------------------------------

function setupSocket(){
	// setup!
	socket = new WebSocket( get_appropriate_ws_url());
	socket.binaryType = "blob";

	// open
	try {
		socket.onopen 		= onOpen;
		socket.onmessage 	= onMessage;
		socket.onclose 	 	= onClose;
	} catch(exception) {
		alert('Error' + exception);
	}
}
<|endoftext|>


<commit_before>/*
 * Copyright 2013 Next Century Corporation
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

charts.LineChart = function (rootElement, selector, opts) {
	opts = opts || {};
	this.chartSelector = selector;
	this.element = d3.select(rootElement).select(selector);

	this.xAttribute = opts.x;
	//this.xLabel = opts.xLabel || this.determineXLabel();
	this.yAttribute = opts.y;
	//this.yLabel = opts.yLabel || this.determineYLabel();
	this.margin = $.extend({}, charts.LineChart.DEFAULT_MARGIN, opts.margin || {});

	this.categories = [];

	/*this.viewboxXMin = 0;
	this.viewboxYMin = 0;
	this.viewboxXMax = 618;
	this.viewboxYMax = 270;*/

	//this.style = $.extend({}, charts.LineChart.DEFAULT_STYLE, opts.style);

	if (opts.responsive) {
		this.redrawOnResize();
	}
	return this;
};

charts.LineChart.DEFAULT_HEIGHT = 300;
charts.LineChart.DEFAULT_WIDTH = 600;
charts.LineChart.DEFAULT_MARGIN = {top: 20, bottom: 30, left: 40, right: 20};
charts.LineChart.DEFAULT_STYLE = {};

charts.LineChart.prototype.determineWidth = function (element) {
	if (this.userSetWidth) {
		return this.userSetWidth;
	}
	else if ($(element[0]).width() !== 0) {
		return $(element[0]).width();
	}
	return charts.LineChart.DEFAULT_WIDTH;
};

charts.LineChart.prototype.determineHeight = function (element) {
	if (this.userSetHeight) {
		return this.userSetHeight;
	}
	else if ($(element[0]).height() !== 0) {
		return $(element[0]).height();
	}
	return charts.LineChart.DEFAULT_HEIGHT;
};

charts.LineChart.prototype.categoryForItem = function (item) {
	var me = this;
	if (typeof this.xAttribute === 'function') {
		return this.xAttribute.call(this, item);
	}

	return item[this.xAttribute];
};

charts.LineChart.prototype.createCategories = function (data) {
	var me = this;
	return _.chain(data)
		.map(function (item) {
			return me.categoryForItem(item);
		})
		.unique()
		.filter(function (item) {
			return !_.isNull(item) && !_.isUndefined(item);
		})
		.sort(charts.LineChart.sortComparator)
		.value();
};

charts.LineChart.sortComparator = function (a, b) {
	if (a instanceof Date && b instanceof Date) {
		return charts.LineChart.compareValues(a.getTime(), b.getTime());
	}
	return charts.LineChart.compareValues(a, b);
};

charts.LineChart.compareValues = function (a, b) {
	if (a < b) {
		return -1;
	}
	if (a > b) {
		return 1;
	}
	return 0;
};

charts.LineChart.prototype.drawChart = function() {
	var me = this;

	$(this.element[0]).empty();

	me.height = me.determineHeight(me.element);
	me.width = me.determineWidth(me.element);

	//me.x = d3.time.scale().range([0, me.width]);

	me.svg = me.element.append("svg")
		.attr("width", me.width)// + me.margin.left + me.margin.right)
		.attr("height", me.height) //+ me.margin.top + me.margin.bottom)
	.append("g")
		.attr("transform", "translate(" + me.margin.left + "," + me.margin.top + ")");
};

charts.LineChart.prototype.drawLine = function(opts) {
	var me = this;

	if(!($.isArray(opts))) {
		opts = [opts];
	}

	me.data = opts;

	var fullDataSet = [];
	//get list of all data
	for(var i = 0; i < opts.length; i++) {
		fullDataSet = fullDataSet.concat(opts[i].data);
	}

	me.categories = me.createCategories(fullDataSet);

	me.x =  d3.scale.ordinal()
		.domain(me.categories)
		.rangePoints([0, (me.width - (me.margin.left + me.margin.right))],.25);

	var xAxis = d3.svg.axis()
		.scale(me.x)
		.orient("bottom");

	me.svg.append("g")
		.attr("class", "x axis")
		.attr("transform", "translate(0," + (me.height - (me.margin.top + me.margin.bottom)) + ")")
		.call(xAxis);

	me.y = d3.scale.linear().range([(me.height - (me.margin.top + me.margin.bottom)), 0]);

	var yAxis = d3.svg.axis()
		.scale(me.y)
		.orient("left");

	me.y.domain([0, d3.max(fullDataSet, function(d) { return d[me.yAttribute]; })]);

	me.svg.append("g")
		.attr("class", "y axis")
		.call(yAxis)
	.append("text")
		.attr("transform", "rotate(-90)")
		.attr("y", 6)
		.attr("dy", ".71em")
		.style("text-anchor", "end")
		.text(me.yAttribute);

	var cls;
	var data;
	var line;
	for(var i = 0; i < opts.length; i++) {
		cls = "line" + (opts[i].classString ? " " + opts[i].classString : "");
		data = opts[i].data;

		data = data.sort(function(a,b) {
			if(a[me.xAttribute] < b[me.xAttribute]) {
				return -1;
			} else if(a[me.xAttribute] === b[me.xAttribute]) {
				return 0;
			} else {
				return 1;
			}
		});

		line = d3.svg.line()
		.x(function(d) {
			return me.x(d[me.xAttribute]); })
		.y(function(d) { return me.y(d[me.yAttribute]); });

		me.svg.append("path")
		.datum(data)
		.attr("class", cls)
		.attr("d", line);
	}
};

charts.LineChart.prototype.redrawOnResize = function () {
	var me = this;

	function drawChart() {
		me.drawChart();
		if(me.data) {
			me.drawLine(me.data);
		}
	}

	// Debounce is needed because browser resizes fire this resize even multiple times.
	// Cache the handler so we can remove it from the window on destroy.
	me.resizeHandler = _.debounce(drawChart, 10);
	$(window).resize(me.resizeHandler);

};

charts.LineChart.destroy = function(el, selector) {
	var element = d3.select(el).select(selector);
	$(window).off('resize', this.resizeHandler);
	$(element[0]).empty();
};<commit_msg>Working on 0 padding data<commit_after>/*
 * Copyright 2013 Next Century Corporation
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

charts.LineChart = function (rootElement, selector, opts) {
	opts = opts || {};
	this.chartSelector = selector;
	this.element = d3.select(rootElement).select(selector);

	this.xAttribute = opts.x;
	//this.xLabel = opts.xLabel || this.determineXLabel();
	this.yAttribute = opts.y;
	//this.yLabel = opts.yLabel || this.determineYLabel();
	this.margin = $.extend({}, charts.LineChart.DEFAULT_MARGIN, opts.margin || {});

	this.categories = [];

	/*this.viewboxXMin = 0;
	this.viewboxYMin = 0;
	this.viewboxXMax = 618;
	this.viewboxYMax = 270;*/

	//this.style = $.extend({}, charts.LineChart.DEFAULT_STYLE, opts.style);

	if (opts.responsive) {
		this.redrawOnResize();
	}
	return this;
};

charts.LineChart.DEFAULT_HEIGHT = 300;
charts.LineChart.DEFAULT_WIDTH = 600;
charts.LineChart.DEFAULT_MARGIN = {top: 20, bottom: 30, left: 40, right: 20};
charts.LineChart.DEFAULT_STYLE = {};

charts.LineChart.prototype.determineWidth = function (element) {
	if (this.userSetWidth) {
		return this.userSetWidth;
	}
	else if ($(element[0]).width() !== 0) {
		return $(element[0]).width();
	}
	return charts.LineChart.DEFAULT_WIDTH;
};

charts.LineChart.prototype.determineHeight = function (element) {
	if (this.userSetHeight) {
		return this.userSetHeight;
	}
	else if ($(element[0]).height() !== 0) {
		return $(element[0]).height();
	}
	return charts.LineChart.DEFAULT_HEIGHT;
};

charts.LineChart.prototype.categoryForItem = function (item) {
	var me = this;
	if (typeof this.xAttribute === 'function') {
		return this.xAttribute.call(this, item);
	}

	return item[this.xAttribute];
};

charts.LineChart.prototype.createCategories = function (data) {
	var me = this;
	return _.chain(data)
		.map(function (item) {
			return me.categoryForItem(item);
		})
		.unique()
		.filter(function (item) {
			return !_.isNull(item) && !_.isUndefined(item);
		})
		.sort(charts.LineChart.sortComparator)
		.value();
};

charts.LineChart.sortComparator = function (a, b) {
	if (a instanceof Date && b instanceof Date) {
		return charts.LineChart.compareValues(a.getTime(), b.getTime());
	}
	return charts.LineChart.compareValues(a, b);
};

charts.LineChart.compareValues = function (a, b) {
	if (a < b) {
		return -1;
	}
	if (a > b) {
		return 1;
	}
	return 0;
};

charts.LineChart.prototype.drawChart = function() {
	var me = this;

	$(this.element[0]).empty();

	me.height = me.determineHeight(me.element);
	me.width = me.determineWidth(me.element);

	//me.x = d3.time.scale().range([0, me.width]);

	me.svg = me.element.append("svg")
		.attr("width", me.width)// + me.margin.left + me.margin.right)
		.attr("height", me.height) //+ me.margin.top + me.margin.bottom)
	.append("g")
		.attr("transform", "translate(" + me.margin.left + "," + me.margin.top + ")");
};

charts.LineChart.prototype.drawLine = function(opts) {
	var me = this;

	if(!($.isArray(opts))) {
		opts = [opts];
	}

	me.data = opts;

	var fullDataSet = [];
	//get list of all data
	for(var i = 0; i < opts.length; i++) {
		fullDataSet = fullDataSet.concat(opts[i].data);
	}

	//me.categories = me.createCategories(fullDataSet);
	var parseDate = d3.time.format("%Y-%m-%d").parse;

	fullDataSet.forEach(function(d) {
		d.date = parseDate(d[me.xAttribute]);
	});

	/*me.x =  d3.scale.ordinal()
		.domain(me.categories)
		.rangePoints([0, (me.width - (me.margin.left + me.margin.right))],.25);*/
	me.x = d3.time.scale()
	.range([0, (me.width - (me.margin.left + me.margin.right))],.25);

	var extent = d3.extent(fullDataSet, function(d) { return d.date; });

	me.x.domain(d3.extent(fullDataSet, function(d) { return d.date; }));

	var xAxis = d3.svg.axis()
		.scale(me.x)
		.orient("bottom")
		.ticks(d3.time.day);

	var xAxisElement = me.svg.append("g")
		.attr("class", "x axis")
		.attr("transform", "translate(0," + (me.height - (me.margin.top + me.margin.bottom)) + ")")
		.call(xAxis);

	xAxisElement.selectAll("text")
	.style("text-anchor", "end")
	.attr("dx", "-.8em")
	.attr("dy", ".15em")
	.attr("transform", function(d) {
		return "rotate(-60)";
	});

	//$(this.element[0]).height(310 + $(this.element[0]).find('g.x')[0].getBoundingClientRect().height);
	$(this.element[0]).children('svg').height(280 + $(this.element[0]).find('g.x')[0].getBoundingClientRect().height);

	me.y = d3.scale.linear().range([(me.height - (me.margin.top + me.margin.bottom)), 0]);

	var yAxis = d3.svg.axis()
		.scale(me.y)
		.orient("left");

	me.y.domain([0, d3.max(fullDataSet, function(d) { return d[me.yAttribute]; })]);

	me.svg.append("g")
		.attr("class", "y axis")
		.call(yAxis)
	.append("text")
		.attr("transform", "rotate(-90)")
		.attr("y", 6)
		.attr("dy", ".71em")
		.style("text-anchor", "end")
		.text(me.yAttribute);

	var cls;
	var data;
	var line;
	for(var i = 0; i < opts.length; i++) {
		cls = "line" + (opts[i].classString ? " " + opts[i].classString : "");
		data = opts[i].data;

		console.log(me.x.ticks());
		me.x.ticks().map(function(bucket) {
			return _.find(data, {date: bucket}) || {date: bucket, value: 0};
		});

		data.forEach(function(d) {
			d.date = parseDate(d[me.xAttribute]);
		});

		data = data.sort(function(a,b) {
			if(a[me.xAttribute] < b[me.xAttribute]) {
				return -1;
			} else if(a[me.xAttribute] === b[me.xAttribute]) {
				return 0;
			} else {
				return 1;
			}
		});

		line = d3.svg.line()
		.x(function(d) { return me.x(d.date); })
		.y(function(d) { return me.y(d[me.yAttribute]); });

		me.svg.append("path")
		.datum(data)
		.attr("class", cls)
		.attr("d", line);
	}
};

charts.LineChart.prototype.redrawOnResize = function () {
	var me = this;

	function drawChart() {
		me.drawChart();
		if(me.data) {
			me.drawLine(me.data);
		}
	}

	// Debounce is needed because browser resizes fire this resize even multiple times.
	// Cache the handler so we can remove it from the window on destroy.
	me.resizeHandler = _.debounce(drawChart, 10);
	$(window).resize(me.resizeHandler);

};

charts.LineChart.destroy = function(el, selector) {
	var element = d3.select(el).select(selector);
	$(window).off('resize', this.resizeHandler);
	$(element[0]).empty();
};<|endoftext|>


<commit_before>var mqtt = require('mqtt');
var gpio = require('pi-gpio');
var fs = require('fs');

var currentState = false;
var turnoffTask = null;

var config = {
  mqttClientOpts: {},
  mqttPort: 1883,
  mqttHost: 'localhost',
  mqttCommandsTopic: '/alarm/commands',
  mqttStateTopic: '/alarm/state',
  turnOffDelay: 10000
};

// Read configfile
if (process.argv.length > 2) {
  console.log('Parsing config file: '+process.argv[2]);
  var data = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
  for (var key in data) {
    config[key] = data[key];
  }
}

// Add will to mqttClientOpts for offline reporting
config['mqttClientOpts']['will'] = {
  topic: config['mqttStateTopic'],
  payload: JSON.stringify({currentState: 'offline'}),
  qos: 1,
  retain: true
};

var mqttClient = mqtt.createClient(config['mqttPort'], config['mqttHost'], config['mqttClientOpts']);

var publishState = function() {
  mqttClient.publish(config['mqttStateTopic'], JSON.stringify({currentState: currentState?'on':'off'}), {qos: 1, retain: true});
};

var updateState = function(newState) {
  currentState = newState?true:false;
  publishState();
};

var actuator = function(outputValue) {
  console.log('Switching relay: '+outputValue);
  gpio.open(11, "output", function(err) {
    gpio.write(11, outputValue, function(err) {
      updateState(outputValue);
      gpio.close(11);
    });
  });
  if (outputValue) {
    // Schedule turnoffTask, cancelling the previous task if exists
    if (turnoffTask != null) {
      clearTimeout(turnoffTask);
    }
    turnoffTask = setTimeout(actuator, config['turnOffDelay'], false);
  } else {
    // If turning off, cancel the outstanding turnoffTask
    if (turnoffTask != null) {
      clearTimeout(turnoffTask);
    }
    turnoffTask = null;
  }
};

publishState();

mqttClient
  .subscribe(config['mqttCommandsTopic'])
  .on('message', function(topic, message) {
    if (topic == config['mqttCommandsTopic']) {
      data = JSON.parse(message);
      actuator(data.value);
    }
  });
<commit_msg>Added configurable delay per-command<commit_after>var mqtt = require('mqtt');
var gpio = require('pi-gpio');
var fs = require('fs');

var currentState = false;
var turnoffTask = null;

var config = {
  mqttClientOpts: {},
  mqttPort: 1883,
  mqttHost: 'localhost',
  mqttCommandsTopic: '/alarm/commands',
  mqttStateTopic: '/alarm/state',
  turnOffDelay: 10000
};

// Read configfile
if (process.argv.length > 2) {
  console.log('Parsing config file: '+process.argv[2]);
  var data = JSON.parse(fs.readFileSync(process.argv[2], 'utf8'));
  for (var key in data) {
    config[key] = data[key];
  }
}

// Add will to mqttClientOpts for offline reporting
config['mqttClientOpts']['will'] = {
  topic: config['mqttStateTopic'],
  payload: JSON.stringify({currentState: 'offline'}),
  qos: 1,
  retain: true
};

var mqttClient = mqtt.createClient(config['mqttPort'], config['mqttHost'], config['mqttClientOpts']);

var publishState = function() {
  mqttClient.publish(config['mqttStateTopic'], JSON.stringify({currentState: currentState?'on':'off'}), {qos: 1, retain: true});
};

var updateState = function(newState) {
  currentState = newState?true:false;
  publishState();
};

var actuator = function(data) {
  if (data.value === undefined) {
    return;
  }
  console.log('Switching relay: '+data.value);
  gpio.open(11, "output", function(err) {
    gpio.write(11, data.value, function(err) {
      updateState(data.value);
      gpio.close(11);
    });
  });
  if (data.value) {
    // Schedule turnoffTask, cancelling the previous task if exists
    if (turnoffTask != null) {
      clearTimeout(turnoffTask);
    }
    turnoffTask = setTimeout(actuator, data.delay || config['turnOffDelay'], {value: false});
  } else {
    // If turning off, cancel the outstanding turnoffTask
    if (turnoffTask != null) {
      clearTimeout(turnoffTask);
    }
    turnoffTask = null;
  }
};

publishState();

mqttClient
  .subscribe(config['mqttCommandsTopic'])
  .on('message', function(topic, message) {
    if (topic == config['mqttCommandsTopic']) {
      data = JSON.parse(message);
      actuator(data);
    }
  });
<|endoftext|>


<commit_before>//     ______ _      _
//     | ___ (_)    | |
//     | |_/ /_  ___| |_ ___   ___  ___  ___
//     |  __/| |/ __| __/ _ \ / _ \/ __|/ _ \
//     | |   | | (__| || (_) | (_) \__ \  __/
//     \_|   |_|\___|\__\___/ \___/|___/\___|
//
//  Carlos Fernández (@sirikon) - Seis Cocos S.L.

/* use strict & requirements */
'use strict';
var fs 				= require('fs');
var path 			= require('path');
var imagemagick 	= require('imagemagick-native');
var url 			= require('url');

/* Settings */
var Settings = {
	RESOURCE_STORAGE_ROOT: 	"./resources/",
	RESOURCE_STORAGE_URL: 	"/public/",
	RESOURCE_MAIN_URL: 		"/resources/"
}

/* Regular expression to check if a string is base64 */
var base64RegExp 			= new RegExp("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$");
var resizeOptionsRegExp 	= new RegExp("^[0-9]{1,4}x[0-9]{1,4}(afit|afil|fill)*$");

/* Allowed MimeTypes list */
var mimes = {
	"image/png"				: {extension: "png", 	type: "image"},
	"image/jpg"				: {extension: "jpg", 	type: "image"},
	"image/jpeg"			: {extension: "jpeg", 	type: "image"},
	"image/gif"				: {extension: "gif", 	type: "image"},
	"image/x-windows-bmp"	: {extension: "bmp", 	type: "image"},
	"image/bmp"				: {extension: "bmp", 	type: "image"},
	"image/webp"			: {extension: "webp", 	type: "image"},
	"video/mp4"				: {extension: "mp4", 	type: "video"},
	"video/avi"				: {extension: "avi", 	type: "video"},
	"video/msvideo"			: {extension: "avi", 	type: "video"},
	"video/x-msvideo"		: {extension: "avi", 	type: "video"},
	"video/quicktime"		: {extension: "mov", 	type: "video"},
	"video/mpeg"			: {extension: "mpeg", 	type: "video"},
}

/**
 * Checks if a given mimetype is valid
 * Returns the extension or false if it's not valid
 */
var GetMimeExtension = function(mime){
	// If the mimetype exists in the object...
	if ( mimes.hasOwnProperty(mime) ){
		return mimes[mime].extension;
	}else{
		return false;
	}
}

/**
 * Checks if a given mimetype is valid.
 * Returns the type or false if it's not valid
 */
var GetMimeType = function(mime){
	// If the mimetype exists in the object...
	if ( mimes.hasOwnProperty(mime) ){
		return mimes[mime].type;
	}else{
		return false;
	}
}

/**
 * Checks if a given mimetype is valid.
 * Returns the type or false if it's not valid
 */
var GetMimeTypeByExtension = function(ext){
	for (var x in mimes){
		if( mimes[x].extension == ext ){
			return mimes[x].type;
		}
	}
	return false;
}

/**
 * Checks if a given base64 string is valid.
 * Returns true/false
 */
var CheckBase64 = function(data){

	/*
	 * A string is base64 when:
	 * 1.- is not undefined/false
	 * 2.- have a single comma
	 * 3.- matches the regular expression
	 */
	if ( !data ){
		return false;
	}

	if( data.indexOf(",") == -1 ){
		return false;
	}

	if(  data.indexOf(",") != data.lastIndexOf(",") ){
		return false;
	}

	var d = data.split(',')[1];

	return base64RegExp.test(d);
}

/**
 * Returns a random string with the given lenght and allowed chars
 */
var randomString = function(length, chars) {
    var result = '';
    for (var i = length; i > 0; --i) result += chars[Math.round(Math.random() * (chars.length - 1))];
    return result;
}

var ParseResizeOptions = function(options){
	if( !resizeOptionsRegExp.test(options) ){
		return false;
	}

	var mode;
	switch(options.substr(-4)) {
		case 'afil':
			mode = 'aspectfill';
			break;
		case 'afit':
			mode = 'aspectfit';
			break;
		case 'fill':
			mode = 'fill';
			break;
	}

	var rest = options.substr(0, options.length-4);
	var rest = rest.split('x');

	return {
		width: parseInt(rest[0]),
		height: parseInt(rest[1]),
		mode: mode
	}
}

var ParseFormatFromExtension = function(extension){
	var ext = extension.toLowerCase();
	var result;
	switch(ext){
		case 'png':
			result = 'PNG';
			break;
		case 'gif':
			result = 'GIF';
			break;
		case 'bmp':
			result = 'BMP';
			break;
		default:
			result = 'JPEG';
	}
	return result;
}

/**
 * Mongoose Getter
 */
var PictureGetter = function(field){
	return function(){
		var filename = this.get("_"+field+"_resid");
		if ( url.parse(filename).host ){
			return filename;
		}else if( filename && filename != "" ){
			return Settings.RESOURCE_MAIN_URL+this.get("_"+field+"_resid");
		}else{
			return "";
		}
	}
}

/**
 * Mongoose Setter
 */
var PictureSetter = function(field){
	return function(value){
		var anchor = this;
		var filename = path.basename(value)

		if(CheckBase64(value)){
			// It's base64, save it!
			var mimetype = value.substr(5).split(";")[0];
			var extension = GetMimeExtension(mimetype);
			if(extension){
				fs.exists(Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid"), function(existsit){
					if(existsit && fs.lstatSync(Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid")).isFile()){
						fs.unlink(Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid"), function(err){
							if(err){
								console.log('Error removing previous image: '+Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid"));
								console.error(err);
								return;
							}
						});
					}
				});
				filename = randomString(32,'abcdef1234567890')+"."+extension;
				fs.writeFile(Settings.RESOURCE_STORAGE_ROOT+filename, value.split(',')[1], 'base64', function(err){
					if(err){
						console.log('Error writing on disk the new file: '+Settings.RESOURCE_STORAGE_ROOT+filename);
						console.error(err);
						return;
					}
					anchor.set("_"+field+"_resid", filename);
					anchor.save();
				});
			}else{
				console.log('invalid mimetype: '+mimetype);
			}
		}else if(fs.existsSync(value) && !fs.existsSync(Settings.RESOURCE_STORAGE_ROOT+filename)){
			// It's a path, move it!
			fs.rename(value, Settings.RESOURCE_STORAGE_ROOT+filename, function(err){
				if(err){
					console.log('Error moving the new file: '+Settings.RESOURCE_STORAGE_ROOT+filename);
					console.error(err);
					return;
				}
				anchor.set("_"+field+"_resid", filename);
				anchor.save();
			});
		}else if(value == '' || value == null || value == undefined){
			fs.unlink(Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid"), function(err){
				if(err){
					console.log('Error removing the actual file: '+Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid"))
					console.error(err);
					return;
				}
			});
			anchor.set("_"+field+"_resid", '');
		}else if( url.parse(value).host ){
			anchor.set("_"+field+"_resid", value);
		}else{
			// Unknown
			console.error('Could not save: ' + value);
		}
	}
}

/**
 * Fields creator of the given field names
 */
var PictureFieldCreator = function(fields){
	var newFields = {};
	for (var i in fields){
		newFields["_"+fields[i]+"_resid"] = {type: String, default: "", select: true};
	}
	return newFields;
}

/**
 * Mongoose Post Remove
 */
var PictureRemover = function(fields){
	return function(doc){
		for(var x in fields){
			if( !fs.existsSync( Settings.RESOURCE_STORAGE_ROOT+doc["_"+fields[x]+"_resid"] ) ){ return; }
			if( !fs.lstatSync(Settings.RESOURCE_STORAGE_ROOT+doc["_"+fields[x]+"_resid"]).isFile() ){ return; }
			fs.unlink(Settings.RESOURCE_STORAGE_ROOT+doc["_"+fields[x]+"_resid"], function(err){
				if(err){
					console.log('Error removing: ' + Settings.RESOURCE_STORAGE_ROOT+doc["_"+fields[x]+"_resid"]);
					console.error(err);
				}
			});
		}
	}
}

/**
 * Mongoose Plugin
 */
var Plugin = function(schema,fields){
	for(var i in fields){
		schema.virtual(fields[i]).get(PictureGetter(fields[i]));
		schema.virtual(fields[i]).set(PictureSetter(fields[i]));
	}
	schema.set('toJSON', {virtuals: true});
	schema.set('toObject', {virtuals: true});
	schema.add(PictureFieldCreator(fields));
	schema.post('remove', PictureRemover(fields));
}

/**
 * Given a key/value, stores it in Settings
 */
var Config = function(key,value){
	Settings[key] = value;
}

/**
 * Express Route Controller
 * Will return an image or redirect to a image
 */
var RouteController = function(req,res){
	var filename = req.params.resid;
	var parsedOptions = ParseResizeOptions(req.query.resize);
	var filenameExtension;
	var filenameName;
	if(req.query.resize && parsedOptions){
		filenameExtension = filename.substr(filename.lastIndexOf('.'));
		filenameName = filename.substr(0,filename.lastIndexOf('.'));
		filename = filenameName+"_"+req.query.resize+filenameExtension;
	}
	fs.exists(Settings.RESOURCE_STORAGE_ROOT+filename, function(exists){
		if(exists){
			res.redirect(Settings.RESOURCE_STORAGE_URL+filename);
		}else if(parsedOptions && GetMimeTypeByExtension(filenameExtension) == 'video' && fs.existsSync(Settings.RESOURCE_STORAGE_ROOT+req.params.resid)){
			var format = ParseFormatFromExtension(filenameExtension);
			var resizedBuffer = imagemagick.convert({
				srcData: fs.readFileSync(Settings.RESOURCE_STORAGE_ROOT+req.params.resid),
				width: parsedOptions.width,
				height: parsedOptions.height,
				resizeStyle: parsedOptions.mode,
				quality: 75,
				format: format
			});
			fs.writeFileSync(Settings.RESOURCE_STORAGE_ROOT+filename,resizedBuffer);
			res.redirect(Settings.RESOURCE_STORAGE_URL+filename);
		}else{
			res.redirect(Settings.RESOURCE_STORAGE_URL+req.params.resid);
		}
	})
}

/**
 * Module exports
 */
module.exports = {
	Plugin: Plugin,
	Config: Config,
	RouteController: RouteController
}<commit_msg>Fixed resizing<commit_after>//     ______ _      _
//     | ___ (_)    | |
//     | |_/ /_  ___| |_ ___   ___  ___  ___
//     |  __/| |/ __| __/ _ \ / _ \/ __|/ _ \
//     | |   | | (__| || (_) | (_) \__ \  __/
//     \_|   |_|\___|\__\___/ \___/|___/\___|
//
//  Carlos Fernández (@sirikon) - Seis Cocos S.L.

/* use strict & requirements */
'use strict';
var fs 				= require('fs');
var path 			= require('path');
var imagemagick 	= require('imagemagick-native');
var url 			= require('url');

/* Settings */
var Settings = {
	RESOURCE_STORAGE_ROOT: 	"./resources/",
	RESOURCE_STORAGE_URL: 	"/public/",
	RESOURCE_MAIN_URL: 		"/resources/"
}

/* Regular expression to check if a string is base64 */
var base64RegExp 			= new RegExp("^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$");
var resizeOptionsRegExp 	= new RegExp("^[0-9]{1,4}x[0-9]{1,4}(afit|afil|fill)*$");

/* Allowed MimeTypes list */
var mimes = {
	"image/png"				: {extension: "png", 	type: "image"},
	"image/jpg"				: {extension: "jpg", 	type: "image"},
	"image/jpeg"			: {extension: "jpeg", 	type: "image"},
	"image/gif"				: {extension: "gif", 	type: "image"},
	"image/x-windows-bmp"	: {extension: "bmp", 	type: "image"},
	"image/bmp"				: {extension: "bmp", 	type: "image"},
	"image/webp"			: {extension: "webp", 	type: "image"},
	"video/mp4"				: {extension: "mp4", 	type: "video"},
	"video/avi"				: {extension: "avi", 	type: "video"},
	"video/msvideo"			: {extension: "avi", 	type: "video"},
	"video/x-msvideo"		: {extension: "avi", 	type: "video"},
	"video/quicktime"		: {extension: "mov", 	type: "video"},
	"video/mpeg"			: {extension: "mpeg", 	type: "video"},
}

/**
 * Checks if a given mimetype is valid
 * Returns the extension or false if it's not valid
 */
var GetMimeExtension = function(mime){
	// If the mimetype exists in the object...
	if ( mimes.hasOwnProperty(mime) ){
		return mimes[mime].extension;
	}else{
		return false;
	}
}

/**
 * Checks if a given mimetype is valid.
 * Returns the type or false if it's not valid
 */
var GetMimeType = function(mime){
	// If the mimetype exists in the object...
	if ( mimes.hasOwnProperty(mime) ){
		return mimes[mime].type;
	}else{
		return false;
	}
}

/**
 * Checks if a given mimetype is valid.
 * Returns the type or false if it's not valid
 */
var GetMimeTypeByExtension = function(ext){
	var extension = ext;
	if(extension.indexOf('.') >= 0){
		extension = extension.substr( extension.indexOf('.')+1 );
	}
	for (var x in mimes){
		if( mimes[x].extension == extension ){
			return mimes[x].type;
		}
	}
	return false;
}

/**
 * Checks if a given base64 string is valid.
 * Returns true/false
 */
var CheckBase64 = function(data){

	/*
	 * A string is base64 when:
	 * 1.- is not undefined/false
	 * 2.- have a single comma
	 * 3.- matches the regular expression
	 */
	if ( !data ){
		return false;
	}

	if( data.indexOf(",") == -1 ){
		return false;
	}

	if(  data.indexOf(",") != data.lastIndexOf(",") ){
		return false;
	}

	var d = data.split(',')[1];

	return base64RegExp.test(d);
}

/**
 * Returns a random string with the given lenght and allowed chars
 */
var randomString = function(length, chars) {
    var result = '';
    for (var i = length; i > 0; --i) result += chars[Math.round(Math.random() * (chars.length - 1))];
    return result;
}

var ParseResizeOptions = function(options){
	if( !resizeOptionsRegExp.test(options) ){
		return false;
	}

	var mode;
	switch(options.substr(-4)) {
		case 'afil':
			mode = 'aspectfill';
			break;
		case 'afit':
			mode = 'aspectfit';
			break;
		case 'fill':
			mode = 'fill';
			break;
	}

	var rest = options.substr(0, options.length-4);
	var rest = rest.split('x');

	return {
		width: parseInt(rest[0]),
		height: parseInt(rest[1]),
		mode: mode
	}
}

var ParseFormatFromExtension = function(extension){
	var ext = extension.toLowerCase();
	var result;
	switch(ext){
		case 'png':
			result = 'PNG';
			break;
		case 'gif':
			result = 'GIF';
			break;
		case 'bmp':
			result = 'BMP';
			break;
		default:
			result = 'JPEG';
	}
	return result;
}

/**
 * Mongoose Getter
 */
var PictureGetter = function(field){
	return function(){
		var filename = this.get("_"+field+"_resid");
		if ( url.parse(filename).host ){
			return filename;
		}else if( filename && filename != "" ){
			return Settings.RESOURCE_MAIN_URL+this.get("_"+field+"_resid");
		}else{
			return "";
		}
	}
}

/**
 * Mongoose Setter
 */
var PictureSetter = function(field){
	return function(value){
		var anchor = this;
		var filename = path.basename(value)

		if(CheckBase64(value)){
			// It's base64, save it!
			var mimetype = value.substr(5).split(";")[0];
			var extension = GetMimeExtension(mimetype);
			if(extension){
				fs.exists(Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid"), function(existsit){
					if(existsit && fs.lstatSync(Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid")).isFile()){
						fs.unlink(Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid"), function(err){
							if(err){
								console.log('Error removing previous image: '+Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid"));
								console.error(err);
								return;
							}
						});
					}
				});
				filename = randomString(32,'abcdef1234567890')+"."+extension;
				fs.writeFile(Settings.RESOURCE_STORAGE_ROOT+filename, value.split(',')[1], 'base64', function(err){
					if(err){
						console.log('Error writing on disk the new file: '+Settings.RESOURCE_STORAGE_ROOT+filename);
						console.error(err);
						return;
					}
					anchor.set("_"+field+"_resid", filename);
					anchor.save();
				});
			}else{
				console.log('invalid mimetype: '+mimetype);
			}
		}else if(fs.existsSync(value) && !fs.existsSync(Settings.RESOURCE_STORAGE_ROOT+filename)){
			// It's a path, move it!
			fs.rename(value, Settings.RESOURCE_STORAGE_ROOT+filename, function(err){
				if(err){
					console.log('Error moving the new file: '+Settings.RESOURCE_STORAGE_ROOT+filename);
					console.error(err);
					return;
				}
				anchor.set("_"+field+"_resid", filename);
				anchor.save();
			});
		}else if(value == '' || value == null || value == undefined){
			fs.unlink(Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid"), function(err){
				if(err){
					console.log('Error removing the actual file: '+Settings.RESOURCE_STORAGE_ROOT+anchor.get("_"+field+"_resid"))
					console.error(err);
					return;
				}
			});
			anchor.set("_"+field+"_resid", '');
		}else if( url.parse(value).host ){
			anchor.set("_"+field+"_resid", value);
		}else{
			// Unknown
			console.error('Could not save: ' + value);
		}
	}
}

/**
 * Fields creator of the given field names
 */
var PictureFieldCreator = function(fields){
	var newFields = {};
	for (var i in fields){
		newFields["_"+fields[i]+"_resid"] = {type: String, default: "", select: true};
	}
	return newFields;
}

/**
 * Mongoose Post Remove
 */
var PictureRemover = function(fields){
	return function(doc){
		for(var x in fields){
			if( !fs.existsSync( Settings.RESOURCE_STORAGE_ROOT+doc["_"+fields[x]+"_resid"] ) ){ return; }
			if( !fs.lstatSync(Settings.RESOURCE_STORAGE_ROOT+doc["_"+fields[x]+"_resid"]).isFile() ){ return; }
			fs.unlink(Settings.RESOURCE_STORAGE_ROOT+doc["_"+fields[x]+"_resid"], function(err){
				if(err){
					console.log('Error removing: ' + Settings.RESOURCE_STORAGE_ROOT+doc["_"+fields[x]+"_resid"]);
					console.error(err);
				}
			});
		}
	}
}

/**
 * Mongoose Plugin
 */
var Plugin = function(schema,fields){
	for(var i in fields){
		schema.virtual(fields[i]).get(PictureGetter(fields[i]));
		schema.virtual(fields[i]).set(PictureSetter(fields[i]));
	}
	schema.set('toJSON', {virtuals: true});
	schema.set('toObject', {virtuals: true});
	schema.add(PictureFieldCreator(fields));
	schema.post('remove', PictureRemover(fields));
}

/**
 * Given a key/value, stores it in Settings
 */
var Config = function(key,value){
	Settings[key] = value;
}

/**
 * Express Route Controller
 * Will return an image or redirect to a image
 */
var RouteController = function(req,res){
	var filename = req.params.resid;
	var parsedOptions = ParseResizeOptions(req.query.resize);
	var filenameExtension;
	var filenameName;
	if(req.query.resize && parsedOptions){
		filenameExtension = filename.substr(filename.lastIndexOf('.'));
		filenameName = filename.substr(0,filename.lastIndexOf('.'));
		filename = filenameName+"_"+req.query.resize+filenameExtension;
	}
	fs.exists(Settings.RESOURCE_STORAGE_ROOT+filename, function(exists){
		if(exists){
			res.redirect(Settings.RESOURCE_STORAGE_URL+filename);
		}else if(parsedOptions && GetMimeTypeByExtension(filenameExtension) == 'image' && fs.existsSync(Settings.RESOURCE_STORAGE_ROOT+req.params.resid)){
			var format = ParseFormatFromExtension(filenameExtension);
			var resizedBuffer = imagemagick.convert({
				srcData: fs.readFileSync(Settings.RESOURCE_STORAGE_ROOT+req.params.resid),
				width: parsedOptions.width,
				height: parsedOptions.height,
				resizeStyle: parsedOptions.mode,
				quality: 75,
				format: format
			});
			fs.writeFileSync(Settings.RESOURCE_STORAGE_ROOT+filename,resizedBuffer);
			res.redirect(Settings.RESOURCE_STORAGE_URL+filename);
		}else{
			res.redirect(Settings.RESOURCE_STORAGE_URL+req.params.resid);
		}
	})
}

/**
 * Module exports
 */
module.exports = {
	Plugin: Plugin,
	Config: Config,
	RouteController: RouteController
}<|endoftext|>


<commit_before>'use strict'

// === WATERWHEEL ===
const { spawn } = require('child_process')
const globby = require('globby')

const task = (props, cb, next) => {
  const { output } = props

  const stream = cb(props)

  // Check current dir for files matching the pattern provided to the task
  // Then call next task in the pipeline with the resolved files
  stream.on('end', () => globby(output).then(next))

  return stream
}

const shell = (cmd) => {
  console.log('Starting: ' + cmd)
  cmd = cmd.split(' ')

  const process = spawn(cmd[0], cmd.slice(1))

  process.stdout.on('data', (data) => {
    console.log(`stdout: ${data}`)
  })

  process.stderr.on('data', (data) => {
    console.log(`stderr: ${data}`)
  })

  process.on('close', (code) => {
    console.log(`child process exited with code ${code}`)
  })
}

// === PIPELINE ===
const ncbi = require('bionode-ncbi')

const config = {
  sraAccession: '2492428'
}

// thunk'it here or inside task?
// const/let does not get hoisted, and it is unnatural to describe pipelines
// in reverse order:
// const task2 = task(...)
// const task1 = task(,,task2)
// functions do get hoisted, but then we have a somewhat less pretty indented
// return task(...) boilerplate

// const samples = task(...)
// const samples = () => task(...)
function samples() {
  // task(props, cb, next)
  return task(
    // these params are then made available to the cb
    {
      input: {
        db: 'sra',
        accession: config.sraAccession
      },
      // will be globby'ed after cb completes
      output: '**/*.sra'
    },
    // the cb for this task
    ( ({ input }) => ncbi.download(input.db, input.accession) ),
    // the next task for this task
    // data is the resolved output
    (data) => shell(`fastq-dump --split-files --skip-technical --gzip ${data[0]}`)
  )
}

// wip
// function dumps() {
//   return task({
//     input: '*.sra',
//     output: [1, 2].map(n => `*_${n}.fastq.gz`)
//   }, )
// }

const pipeline = samples

pipeline()
  .on('data', console.log)
  .on('end', () => console.log('Finished SRA download'))
<commit_msg>Curried next for a task<commit_after>'use strict'

// === WATERWHEEL ===
const { spawn } = require('child_process')
const globby = require('globby')

const task = (props, cb) => (next) => {
// const task = (props, cb, next) => {
  const { output } = props

  const stream = cb(props)

  // Check current dir for files matching the pattern provided to the task
  // Then call next task in the pipeline with the resolved files
  stream.on('end', () => globby(output).then(next))

  return stream
}

// function join(...tasks) {
//   tasks.map((t, i) => {
//     if (i !== tasks.length-1) {
//       return task()
//     }
//   })
// }

const shell = (cmd) => {
  console.log('Starting: ' + cmd)
  cmd = cmd.split(' ')

  const process = spawn(cmd[0], cmd.slice(1))

  process.stdout.on('data', (data) => {
    console.log(`stdout: ${data}`)
  })

  process.stderr.on('data', (data) => {
    console.log(`stderr: ${data}`)
  })

  process.on('close', (code) => {
    console.log(`child process exited with code ${code}`)
  })
}

// === PIPELINE ===
const ncbi = require('bionode-ncbi')

const config = {
  sraAccession: '2492428'
}

// thunk'it here or inside task?
// const/let does not get hoisted, and it is unnatural to describe pipelines
// in reverse order:
// const task2 = task(...)
// const task1 = task(,,task2)
// functions do get hoisted, but then we have a somewhat less pretty indented
// return task(...) boilerplate

// const samples = task(...)
// const samples = () => task(...)
function samples() {
  // task(props, cb, next)
  return task(
    // these params are then made available to the cb
    {
      input: {
        db: 'sra',
        accession: config.sraAccession
      },
      // will be globby'ed after cb completes
      output: '**/*.sra'
    },
    // the cb for this task
    ( ({ input }) => ncbi.download(input.db, input.accession) )

    // the next task for this task is curried
    // data is the resolved output
  )( (data) => shell(`fastq-dump --split-files --skip-technical --gzip ${data[0]}`) )
  // can do () to have next be undefined in the task manager and it will end
}

// wip
// function dumps() {
//   return task({
//     input: '*.sra',
//     // input: stdin('*.sra')
//     output: [1, 2].map(n => `*_${n}.fastq.gz`)
//   }, ( { input }) => {
//     console.log(input)
//     // shell(`fastq-dump --split-files --skip-technical --gzip ${input}`)
//   })
// }

// join(samples, dumps)

const pipeline = samples

pipeline()
  .on('data', console.log)
  .on('end', () => console.log('Finished SRA download'))
<|endoftext|>


<commit_before>'use strict';

const pollingLocatorQuery = {
  source: 'sms',
  utm_campaign: 'sms_gotv',
  utm_medium: 'sms',
  utm_source: 'dosomething',
};

module.exports = {
  // Tags used in message templates.
  tags: {
    links: 'links',
    user: 'user',
  },
  links: {
    pollingLocator: {
      find: {
        url: 'https://www.dosomething.org/us/polling-locator-2018',
        query: pollingLocatorQuery,
      },
      share: {
        url: 'https://www.dosomething.org/us/campaigns/find-your-v-spot/blocks/5WuCqMMGre02mq8MqK4co6',
        query: pollingLocatorQuery,
      },
    },
  },
};
<commit_msg>Adds config overrides for polling locator links<commit_after>'use strict';

const pollingLocatorQuery = {
  source: 'sms',
  utm_campaign: 'sms_gotv',
  utm_medium: 'sms',
  utm_source: 'dosomething',
};

module.exports = {
  // Tags used in message templates.
  tags: {
    links: 'links',
    user: 'user',
  },
  links: {
    pollingLocator: {
      find: {
        url: process.env.DS_GAMBIT_CONVERSATIONS_POLLING_LOCATOR_FIND_URL || 'https://www.dosomething.org/us/polling-locator-2018',
        query: pollingLocatorQuery,
      },
      share: {
        url: process.env.DS_GAMBIT_CONVERSATIONS_POLLING_LOCATOR_SHARE_URL || 'https://www.dosomething.org/us/campaigns/find-your-v-spot/blocks/5WuCqMMGre02mq8MqK4co6',
        query: pollingLocatorQuery,
      },
    },
  },
};
<|endoftext|>


<commit_before>'use strict';

[{
  zoneId: ZoneId.HaukkeManor,
  triggers: [
    {
      id: 'Haukke Normal Dark Mist Stun',
      netRegex: NetRegexes.startsUsing({ id: '2C1', source: ['Manor Maidservant', 'Manor Claviger', 'Lady Amandine'] }),
      netRegexDe: NetRegexes.startsUsing({ id: '2C1', source: ['Hausmädchen', 'Schlüsselträgerin', 'Lady Amandine'] }),
      netRegexFr: NetRegexes.startsUsing({ id: '2C1', source: ['Soubrette Du Manoir', 'Clavière Du Manoir', 'Dame Amandine'] }),
      netRegexJa: NetRegexes.startsUsing({ id: '2C1', source: ['御用邸のメイド', '御用邸のクラヴィジャー', 'レディ・アマンディヌ'] }),
      netRegexKo: NetRegexes.startsUsing({ id: '2C1', source: ['별궁의 하녀', '별궁 청지기', '레이디 아망딘'] }),
      netRegexCn: NetRegexes.startsUsing({ id: '2C1', source: ['庄园的女仆', '庄园的女工', '阿芒迪娜女士'] }),
      condition: function(data, matches) {
        return data.CanStun();
      },
      suppressSeconds: 2,
      response: Responses.stun('info'),
    },
    {
      id: 'Haukke Normal Steward Soul Drain Stun',
      netRegex: NetRegexes.startsUsing({ id: '35C', source: 'Manor Steward' }),
      netRegexDe: NetRegexes.startsUsing({ id: '35C', source: 'Seneschall' }),
      netRegexFr: NetRegexes.startsUsing({ id: '35C', source: 'Intendant Du Manoir' }),
      netRegexJa: NetRegexes.startsUsing({ id: '35C', source: '御用邸の執事長' }),
      netRegexKo: NetRegexes.startsUsing({ id: '35C', source: '별궁의 집사장' }),
      netRegexCn: NetRegexes.startsUsing({ id: '35C', source: '庄园的总管' }),
      condition: function(data, matches) {
        return data.CanStun();
      },
      response: Responses.stun('info'),
    },
    {
      // Particle and spell effects make this particular Dark Mist hard to see.
      id: 'Haukke Normal Amandine Dark Mist Dodge',
      netRegex: NetRegexes.startsUsing({ id: '2C1', source: 'Lady Amandine' }),
      netRegexDe: NetRegexes.startsUsing({ id: '2C1', source: 'Lady Amandine' }),
      netRegexFr: NetRegexes.startsUsing({ id: '2C1', source: 'Dame Amandine' }),
      netRegexJa: NetRegexes.startsUsing({ id: '2C1', source: 'レディ・アマンディヌ' }),
      netRegexKo: NetRegexes.startsUsing({ id: '2C1', source: '레이디 아망딘' }),
      netRegexCn: NetRegexes.startsUsing({ id: '2C1', source: '阿芒迪娜女士' }),
      condition: function(data, matches) {
        return !data.CanStun();
      },
      response: Responses.outOfMelee('alert'),
    },
    {
      id: 'Haukke Normal Amandine Void Fire III',
      netRegex: NetRegexes.startsUsing({ id: '356', source: 'Lady Amandine' }),
      netRegexDe: NetRegexes.startsUsing({ id: '356', source: 'Lady Amandine' }),
      netRegexFr: NetRegexes.startsUsing({ id: '356', source: 'Dame Amandine' }),
      netRegexJa: NetRegexes.startsUsing({ id: '356', source: 'レディ・アマンディヌ' }),
      netRegexKo: NetRegexes.startsUsing({ id: '356', source: '레이디 아망딘' }),
      netRegexCn: NetRegexes.startsUsing({ id: '356', source: '阿芒迪娜女士' }),
      condition: function(data, matches) {
        return data.CanSilence();
      },
      response: Responses.interrupt('info'),
    },
    {
      id: 'Haukke Normal Amandine Void Thunder III',
      netRegex: NetRegexes.startsUsing({ id: '358', source: 'Lady Amandine' }),
      netRegexDe: NetRegexes.startsUsing({ id: '358', source: 'Lady Amandine' }),
      netRegexFr: NetRegexes.startsUsing({ id: '358', source: 'Dame Amandine' }),
      netRegexJa: NetRegexes.startsUsing({ id: '358', source: 'レディ・アマンディヌ' }),
      netRegexKo: NetRegexes.startsUsing({ id: '358', source: '레이디 아망딘' }),
      netRegexCn: NetRegexes.startsUsing({ id: '358', source: '阿芒迪娜女士' }),
      condition: Conditions.targetIsYou(),
      response: Responses.getBehind('info'),
    },
    {
      // Void Lamp Spawn
      id: 'Haukke Normal Void Lamps',
      netRegex: NetRegexes.message({ line: 'The void lamps have begun emitting an eerie glow.', capture: false }),
      netRegexDe: NetRegexes.message({ line: 'Die düsteren Lampen flackern unheilvoll auf.', capture: false }),
      netRegexFr: NetRegexes.message({ line: 'La lanterne sinistre luit d\'un éclat lugubre!', capture: false }),
      netRegexJa: NetRegexes.message({ line: '不気味なランプが妖しく輝き始めた！', capture: false }),
      netRegexKo: NetRegexes.message({ line: '불길한 등불이 요사스러운 빛을 발합니다!', capture: false }),
      netRegexCn: NetRegexes.message({ line: '怪异的灯开始发出令人不安的光芒。', capture: false }),
      infoText: {
        en: 'Turn off Lamps',
        de: 'Schalte die Lampen aus',
        ja: '消灯する',
        cn: '关灯',
      },
    },
    {
      // Lady's Candle Spawn
      id: 'Haukke Normal Ladys Candle',
      netRegex: NetRegexes.addedCombatantFull({ npcNameId: '425', capture: false }),
      response: Responses.killAdds('info'),
    },
    {
      // 2 Lady's Handmaiden and 1 Manor Sentry Spawn
      // The sentry outside the bosses room loads when you enter the zone.
      // This causes the trigger to go off early, parsing for the Handmaiden fixes the problem.
      // Suppression included since 2 Handmaiden's spawn at the same time
      id: 'Haukke Normal Ladys Handmaiden',
      netRegex: NetRegexes.addedCombatantFull({ npcNameId: '424', capture: false }),
      suppressSeconds: 2,
      alertText: {
        en: 'Kill Sentry',
        de: 'Wachposten besiegen',
        ja: '守衛を倒す',
        cn: '击杀守卫',
      },
    },
  ],
  timelineReplace: [
    {
      'locale': 'de',
      'replaceSync': {
        'Manor Maidservant': 'Hausmädchen',
        'Manor Claviger': 'Schlüsselträgerin',
        'Lady Amandine': 'Lady Amandine',
        'Manor Steward': 'Seneschall',
        'The void lamps have begun emitting an eerie glow': 'Die düsteren Lampen flackern unheilvoll auf',
      },
    },
    {
      'locale': 'fr',
      'replaceSync': {
        'Manor Maidservant': 'soubrette du manoir',
        'Manor Claviger': 'clavière du manoir',
        'Lady Amandine': 'dame Amandine',
        'Manor Steward': 'intendant du manoir',
        'The void lamps have begun emitting an eerie glow': 'La lanterne sinistre luit d\'un éclat lugubre',
      },
    },
    {
      'locale': 'ja',
      'replaceSync': {
        'Manor Maidservant': '御用邸のメイド',
        'Manor Claviger': '御用邸のクラヴィジャー',
        'Lady Amandine': 'レディ・アマンディヌ',
        'Manor Steward': '御用邸の執事長',
        'The void lamps have begun emitting an eerie glow': '不気味なランプが妖しく輝き始めた',
      },
    },
    {
      'locale': 'cn',
      'replaceSync': {
        'Manor Maidservant': '庄园的女仆',
        'Manor Claviger': '庄园的女工',
        'Lady Amandine': '阿芒迪娜女士',
        'Manor Steward': '庄园的总管',
        'The void lamps have begun emitting an eerie glow': '怪异的灯开始发出令人不安的光芒',
      },
    },
    {
      'locale': 'ko',
      'replaceSync': {
        'Manor Maidservant': '별궁의 하녀',
        'Manor Claviger': '별궁 청지기',
        'Lady Amandine': '레이디 아망딘',
        'Manor Steward': '별궁의 집사장',
        'The void lamps have begun emitting an eerie glow': '불길한 등불이 요사스러운 빛을 발합니다',
      },
    },
  ],
}];
<commit_msg>raidboss: Haukke missing FR strings (#1911)<commit_after>'use strict';

[{
  zoneId: ZoneId.HaukkeManor,
  triggers: [
    {
      id: 'Haukke Normal Dark Mist Stun',
      netRegex: NetRegexes.startsUsing({ id: '2C1', source: ['Manor Maidservant', 'Manor Claviger', 'Lady Amandine'] }),
      netRegexDe: NetRegexes.startsUsing({ id: '2C1', source: ['Hausmädchen', 'Schlüsselträgerin', 'Lady Amandine'] }),
      netRegexFr: NetRegexes.startsUsing({ id: '2C1', source: ['Soubrette Du Manoir', 'Clavière Du Manoir', 'Dame Amandine'] }),
      netRegexJa: NetRegexes.startsUsing({ id: '2C1', source: ['御用邸のメイド', '御用邸のクラヴィジャー', 'レディ・アマンディヌ'] }),
      netRegexKo: NetRegexes.startsUsing({ id: '2C1', source: ['별궁의 하녀', '별궁 청지기', '레이디 아망딘'] }),
      netRegexCn: NetRegexes.startsUsing({ id: '2C1', source: ['庄园的女仆', '庄园的女工', '阿芒迪娜女士'] }),
      condition: function(data, matches) {
        return data.CanStun();
      },
      suppressSeconds: 2,
      response: Responses.stun('info'),
    },
    {
      id: 'Haukke Normal Steward Soul Drain Stun',
      netRegex: NetRegexes.startsUsing({ id: '35C', source: 'Manor Steward' }),
      netRegexDe: NetRegexes.startsUsing({ id: '35C', source: 'Seneschall' }),
      netRegexFr: NetRegexes.startsUsing({ id: '35C', source: 'Intendant Du Manoir' }),
      netRegexJa: NetRegexes.startsUsing({ id: '35C', source: '御用邸の執事長' }),
      netRegexKo: NetRegexes.startsUsing({ id: '35C', source: '별궁의 집사장' }),
      netRegexCn: NetRegexes.startsUsing({ id: '35C', source: '庄园的总管' }),
      condition: function(data, matches) {
        return data.CanStun();
      },
      response: Responses.stun('info'),
    },
    {
      // Particle and spell effects make this particular Dark Mist hard to see.
      id: 'Haukke Normal Amandine Dark Mist Dodge',
      netRegex: NetRegexes.startsUsing({ id: '2C1', source: 'Lady Amandine' }),
      netRegexDe: NetRegexes.startsUsing({ id: '2C1', source: 'Lady Amandine' }),
      netRegexFr: NetRegexes.startsUsing({ id: '2C1', source: 'Dame Amandine' }),
      netRegexJa: NetRegexes.startsUsing({ id: '2C1', source: 'レディ・アマンディヌ' }),
      netRegexKo: NetRegexes.startsUsing({ id: '2C1', source: '레이디 아망딘' }),
      netRegexCn: NetRegexes.startsUsing({ id: '2C1', source: '阿芒迪娜女士' }),
      condition: function(data, matches) {
        return !data.CanStun();
      },
      response: Responses.outOfMelee('alert'),
    },
    {
      id: 'Haukke Normal Amandine Void Fire III',
      netRegex: NetRegexes.startsUsing({ id: '356', source: 'Lady Amandine' }),
      netRegexDe: NetRegexes.startsUsing({ id: '356', source: 'Lady Amandine' }),
      netRegexFr: NetRegexes.startsUsing({ id: '356', source: 'Dame Amandine' }),
      netRegexJa: NetRegexes.startsUsing({ id: '356', source: 'レディ・アマンディヌ' }),
      netRegexKo: NetRegexes.startsUsing({ id: '356', source: '레이디 아망딘' }),
      netRegexCn: NetRegexes.startsUsing({ id: '356', source: '阿芒迪娜女士' }),
      condition: function(data, matches) {
        return data.CanSilence();
      },
      response: Responses.interrupt('info'),
    },
    {
      id: 'Haukke Normal Amandine Void Thunder III',
      netRegex: NetRegexes.startsUsing({ id: '358', source: 'Lady Amandine' }),
      netRegexDe: NetRegexes.startsUsing({ id: '358', source: 'Lady Amandine' }),
      netRegexFr: NetRegexes.startsUsing({ id: '358', source: 'Dame Amandine' }),
      netRegexJa: NetRegexes.startsUsing({ id: '358', source: 'レディ・アマンディヌ' }),
      netRegexKo: NetRegexes.startsUsing({ id: '358', source: '레이디 아망딘' }),
      netRegexCn: NetRegexes.startsUsing({ id: '358', source: '阿芒迪娜女士' }),
      condition: Conditions.targetIsYou(),
      response: Responses.getBehind('info'),
    },
    {
      // Void Lamp Spawn
      id: 'Haukke Normal Void Lamps',
      netRegex: NetRegexes.message({ line: 'The void lamps have begun emitting an eerie glow.', capture: false }),
      netRegexDe: NetRegexes.message({ line: 'Die düsteren Lampen flackern unheilvoll auf.', capture: false }),
      netRegexFr: NetRegexes.message({ line: 'La lanterne sinistre luit d\'un éclat lugubre!', capture: false }),
      netRegexJa: NetRegexes.message({ line: '不気味なランプが妖しく輝き始めた！', capture: false }),
      netRegexKo: NetRegexes.message({ line: '불길한 등불이 요사스러운 빛을 발합니다!', capture: false }),
      netRegexCn: NetRegexes.message({ line: '怪异的灯开始发出令人不安的光芒。', capture: false }),
      infoText: {
        en: 'Turn off Lamps',
        de: 'Schalte die Lampen aus',
        fr: 'Eteignez les lampes',
        ja: '消灯する',
        cn: '关灯',
      },
    },
    {
      // Lady's Candle Spawn
      id: 'Haukke Normal Ladys Candle',
      netRegex: NetRegexes.addedCombatantFull({ npcNameId: '425', capture: false }),
      response: Responses.killAdds('info'),
    },
    {
      // 2 Lady's Handmaiden and 1 Manor Sentry Spawn
      // The sentry outside the bosses room loads when you enter the zone.
      // This causes the trigger to go off early, parsing for the Handmaiden fixes the problem.
      // Suppression included since 2 Handmaiden's spawn at the same time
      id: 'Haukke Normal Ladys Handmaiden',
      netRegex: NetRegexes.addedCombatantFull({ npcNameId: '424', capture: false }),
      suppressSeconds: 2,
      alertText: {
        en: 'Kill Sentry',
        de: 'Wachposten besiegen',
        fr: 'Tuez la sentinelle',
        ja: '守衛を倒す',
        cn: '击杀守卫',
      },
    },
  ],
  timelineReplace: [
    {
      'locale': 'de',
      'replaceSync': {
        'Manor Maidservant': 'Hausmädchen',
        'Manor Claviger': 'Schlüsselträgerin',
        'Lady Amandine': 'Lady Amandine',
        'Manor Steward': 'Seneschall',
        'The void lamps have begun emitting an eerie glow': 'Die düsteren Lampen flackern unheilvoll auf',
      },
    },
    {
      'locale': 'fr',
      'replaceSync': {
        'Manor Maidservant': 'soubrette du manoir',
        'Manor Claviger': 'clavière du manoir',
        'Lady Amandine': 'dame Amandine',
        'Manor Steward': 'intendant du manoir',
        'The void lamps have begun emitting an eerie glow': 'La lanterne sinistre luit d\'un éclat lugubre',
      },
    },
    {
      'locale': 'ja',
      'replaceSync': {
        'Manor Maidservant': '御用邸のメイド',
        'Manor Claviger': '御用邸のクラヴィジャー',
        'Lady Amandine': 'レディ・アマンディヌ',
        'Manor Steward': '御用邸の執事長',
        'The void lamps have begun emitting an eerie glow': '不気味なランプが妖しく輝き始めた',
      },
    },
    {
      'locale': 'cn',
      'replaceSync': {
        'Manor Maidservant': '庄园的女仆',
        'Manor Claviger': '庄园的女工',
        'Lady Amandine': '阿芒迪娜女士',
        'Manor Steward': '庄园的总管',
        'The void lamps have begun emitting an eerie glow': '怪异的灯开始发出令人不安的光芒',
      },
    },
    {
      'locale': 'ko',
      'replaceSync': {
        'Manor Maidservant': '별궁의 하녀',
        'Manor Claviger': '별궁 청지기',
        'Lady Amandine': '레이디 아망딘',
        'Manor Steward': '별궁의 집사장',
        'The void lamps have begun emitting an eerie glow': '불길한 등불이 요사스러운 빛을 발합니다',
      },
    },
  ],
}];
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import {Link} from 'react-router'
import _ from 'lodash'

import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'

import DeleteConfirmTableCell from 'shared/components/DeleteConfirmTableCell'

const AuthorizedEmptyState = ({onCreateDashboard}) => (

      Looks like you don’t have any dashboards

    <button
      className="btn btn-sm btn-primary"
      onClick={onCreateDashboard}
      style={{marginBottom: '90px'}}
    >
       Create Dashboard
    </button>

)

const unauthorizedEmptyState = (

Looks like you don’t have any dashboards

)

const DashboardsTable = ({
  dashboards,
  onDeleteDashboard,
  onCreateDashboard,
  dashboardLink,
}) => {
  return dashboards && dashboards.length ? (

          Name
          Template Variables

        {_.sortBy(dashboards, d => d.name.toLowerCase()).map(dashboard => (

              <Link to={`${dashboardLink}/dashboards/${dashboard.id}`}>
                {dashboard.name}
              </Link>

              {dashboard.templates.length ? (
                dashboard.templates.map(tv => (

                    {tv.tempVar}

                ))
              ) : (
                None
              )}

            <Authorized
              requiredRole={EDITOR_ROLE}
              replaceWithIfNotAuthorized={}
            >
              <DeleteConfirmTableCell
                onDelete={onDeleteDashboard}
                item={dashboard}
                buttonSize="btn-xs"
              />
            </Authorized>

        ))}

  ) : (
    <Authorized
      requiredRole={EDITOR_ROLE}
      replaceWithIfNotAuthorized={unauthorizedEmptyState}
    >
      <AuthorizedEmptyState onCreateDashboard={onCreateDashboard} />
    </Authorized>
  )
}

const {arrayOf, func, shape, string} = PropTypes

DashboardsTable.propTypes = {
  dashboards: arrayOf(shape()),
  onDeleteDashboard: func.isRequired,
  onCreateDashboard: func.isRequired,
  dashboardLink: string.isRequired,
}

AuthorizedEmptyState.propTypes = {
  onCreateDashboard: func.isRequired,
}

export default DashboardsTable
<commit_msg>Refactor dashboards index table to use confirm buttons<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import {Link} from 'react-router'
import _ from 'lodash'

import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'

import ConfirmButton from 'shared/components/ConfirmButton'

const AuthorizedEmptyState = ({onCreateDashboard}) => (

      Looks like you don’t have any dashboards

    <button
      className="btn btn-sm btn-primary"
      onClick={onCreateDashboard}
      style={{marginBottom: '90px'}}
    >
       Create Dashboard
    </button>

)

const unauthorizedEmptyState = (

Looks like you don’t have any dashboards

)

const DashboardsTable = ({
  dashboards,
  onDeleteDashboard,
  onCreateDashboard,
  dashboardLink,
}) => {
  const wrappedDelete = dashboard => () => {
    onDeleteDashboard(dashboard)
  }
  return dashboards && dashboards.length ? (

          Name
          Template Variables

        {_.sortBy(dashboards, d => d.name.toLowerCase()).map(dashboard => (

              <Link to={`${dashboardLink}/dashboards/${dashboard.id}`}>
                {dashboard.name}
              </Link>

              {dashboard.templates.length ? (
                dashboard.templates.map(tv => (

                    {tv.tempVar}

                ))
              ) : (
                None
              )}

            <Authorized
              requiredRole={EDITOR_ROLE}
              replaceWithIfNotAuthorized={}
            >

                <ConfirmButton
                  confirmAction={wrappedDelete}
                  size="btn-xs"
                  type="btn-danger"
                  text="Delete"
                  customClass="table--show-on-row-hover"
                />

            </Authorized>

        ))}

  ) : (
    <Authorized
      requiredRole={EDITOR_ROLE}
      replaceWithIfNotAuthorized={unauthorizedEmptyState}
    >
      <AuthorizedEmptyState onCreateDashboard={onCreateDashboard} />
    </Authorized>
  )
}

const {arrayOf, func, shape, string} = PropTypes

DashboardsTable.propTypes = {
  dashboards: arrayOf(shape()),
  onDeleteDashboard: func.isRequired,
  onCreateDashboard: func.isRequired,
  dashboardLink: string.isRequired,
}

AuthorizedEmptyState.propTypes = {
  onCreateDashboard: func.isRequired,
}

export default DashboardsTable
<|endoftext|>


<commit_before>/* ========================================================================
 * DBH-PG: DBH 'Class'
 * ========================================================================
 * Copyright 2014 Sapienlab
 * Licensed under MIT (https://github.com/sapienlab/dbh-pg/blob/master/LICENSE)
 * ======================================================================== */
'use strict';

var util = require('util'),
    pg = require('pg'),
    Promise = require('bluebird'),
    Connection = require('./Connection');

/**
 * @param {Object|null} setting
 * @param {Object|null} driver the pg instance
 */
function DBH(setting, driver) {
    if (!(this instanceof DBH)) {
        console.warn('need \'new\' to instantiate DBH');
        return new DBH(setting, driver);
    }
    this.driver = driver || pg;
    this.setting = setting || this.driver.defaults;
    this.verbose = !!setting.verbose;
}
DBH.constructor = DBH;

DBH.prototype.conn = function(scope) {
    var me = this,
        connection = new Connection(null, scope || {}, me.verbose);

    return new Promise(function (resolve, reject) {
        me.driver.connect(me.setting, function (err, client, done) {
            me.verbose && console.log('get connection from the poll');
            if (err) {
                reject(err);
            } else {
                connection.nativeClient = client;
                connection.done = done;
                resolve(connection);
            }
        });
    })
    .bind(connection)
    .disposer(function (connection, promise) {
        if (connection.scope.__openTransaction) {
            me.verbose && console.log('appy rollback');
            connection.rollback()
                .then(function () {
                    me.verbose && console.log('release connection to the poll');
                    this.done();
                }, function () {
                    me.verbose && console.log('release connection to the poll');
                    this.done();
                });
        } else {
            // important! release the connection to the poll
            me.verbose && console.log('release connection to the poll');
            connection.done();
        }
    });

};

// Define 'static' methods
[
    'exec',
    'fetchOne',
    'fetchAll',
    'fetchColumn',
    'fetchScalar',
    'insert',
    'update',
    'delete',
    'count'
].forEach(function(fnName) {
    DBH[fnName] = function() {
        var args = arguments;
        return function() {
            return this[fnName].apply(this, args);
        }
    }
});

// Other 'static' methods
[
    'begin',
    'commit',
    'rollback',
    'done'
].forEach(function(fnName) {
    DBH[fnName] = function() {
        return this[fnName].call(this);
    }
});

DBH.sqlEscape = function(sql) {
    // thanks:
    // https://github.com/felixge/node-mysql/blob/master/lib/protocol/SqlString.js#L46-L58
    // Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
    // MIT License
    return sql.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
        switch(s) {
            case "\0": return "\\0";
            case "\n": return "\\n";
            case "\r": return "\\r";
            case "\b": return "\\b";
            case "\t": return "\\t";
            case "\x1a": return "\\Z";
            default: return "\\" + s;
        }
    });
}

DBH.sqlOrderBy = function sqlOrderBy(sort) {
    if (!(sort instanceof Array)) {
        sort = sort.orderBy || sort.sort;
    }
    if (!sort || sort.length === 0) {
        return ' ';
    }
    var sql = ' order by ';

    sort.forEach(function(sortRule) {
        sql += sortRule.attr
            + ' '
            + (sortRule.asc !== undefined && !sortRule.asc ? 'desc' : 'asc')
            + ', ';
    });
    return sql.slice(0, -2) + ' ';
}

DBH.sqlLimit = function(limit, offset) {
    if (typeof(limit) === 'object') {
        offset = limit.offset;
        limit = limit.limit;
    }
    if ((offset === undefined || offset === null)
        && (limit === undefined || limit === null)) {
        return ' ';
    } else if (offset === undefined || offset === null) {
        return ' limit ' + parseInt(limit, 10) + ' ';
    } else {
        return ' limit ' + parseInt(limit, 10) +
            ' offset ' + parseInt(offset, 10) + ' ';
    }
}

DBH.prepare = function(sql) {
    var cmd = {
        name : sql.trim(),
        text : sql
    }
    return function(values) {
        if (!(values instanceof Array)) {
            values = arguments;
        }
        cmd.values = values;
        return cmd;
    }
}

module.exports = DBH;
<commit_msg>How to use shorthands is simplified<commit_after>/* ========================================================================
 * DBH-PG: DBH 'Class'
 * ========================================================================
 * Copyright 2014 Sapienlab
 * Licensed under MIT (https://github.com/sapienlab/dbh-pg/blob/master/LICENSE)
 * ======================================================================== */
'use strict';

var util = require('util'),
    pg = require('pg'),
    Promise = require('bluebird'),
    Connection = require('./Connection');

/**
 * @param {Object|null} setting
 * @param {Object|null} driver the pg instance
 */
function DBH(setting, driver) {
    if (!(this instanceof DBH)) {
        console.warn('need \'new\' to instantiate DBH');
        return new DBH(setting, driver);
    }
    this.driver = driver || pg;
    this.setting = setting || this.driver.defaults;
    this.verbose = !!setting.verbose;
}
DBH.constructor = DBH;

DBH.prototype.conn = function(scope) {
    var me = this,
        connection = new Connection(null, scope || {}, me.verbose);

    return new Promise(function (resolve, reject) {
        me.driver.connect(me.setting, function (err, client, done) {
            me.verbose && console.log('get connection from the poll');
            if (err) {
                reject(err);
            } else {
                connection.nativeClient = client;
                connection.done = done;
                resolve(connection);
            }
        });
    })
    .bind(connection)
    .disposer(function (connection, promise) {
        if (connection.scope.__openTransaction) {
            me.verbose && console.log('appy rollback');
            connection.rollback()
                .then(function () {
                    me.verbose && console.log('release connection to the poll');
                    this.done();
                }, function () {
                    me.verbose && console.log('release connection to the poll');
                    this.done();
                });
        } else {
            // important! release the connection to the poll
            me.verbose && console.log('release connection to the poll');
            connection.done();
        }
    });

};

// Define 'static' methods
[
    'exec',
    'fetchOne',
    'fetchAll',
    'fetchColumn',
    'fetchScalar',
    'insert',
    'update',
    'delete',
    'count',
    'begin',
    'commit',
    'rollback',
    'done'
].forEach(function(fnName) {
    DBH[fnName] = function() {
        var args = arguments;
        return function() {
            return this[fnName].apply(this, args);
        }
    }
});

DBH.sqlEscape = function(sql) {
    // thanks:
    // https://github.com/felixge/node-mysql/blob/master/lib/protocol/SqlString.js#L46-L58
    // Copyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors
    // MIT License
    return sql.replace(/[\0\n\r\b\t\\\'\"\x1a]/g, function(s) {
        switch(s) {
            case "\0": return "\\0";
            case "\n": return "\\n";
            case "\r": return "\\r";
            case "\b": return "\\b";
            case "\t": return "\\t";
            case "\x1a": return "\\Z";
            default: return "\\" + s;
        }
    });
}

DBH.sqlOrderBy = function sqlOrderBy(sort) {
    if (!(sort instanceof Array)) {
        sort = sort.orderBy || sort.sort;
    }
    if (!sort || sort.length === 0) {
        return ' ';
    }
    var sql = ' order by ';

    sort.forEach(function(sortRule) {
        sql += sortRule.attr
            + ' '
            + (sortRule.asc !== undefined && !sortRule.asc ? 'desc' : 'asc')
            + ', ';
    });
    return sql.slice(0, -2) + ' ';
}

DBH.sqlLimit = function(limit, offset) {
    if (typeof(limit) === 'object') {
        offset = limit.offset;
        limit = limit.limit;
    }
    if ((offset === undefined || offset === null)
        && (limit === undefined || limit === null)) {
        return ' ';
    } else if (offset === undefined || offset === null) {
        return ' limit ' + parseInt(limit, 10) + ' ';
    } else {
        return ' limit ' + parseInt(limit, 10) +
            ' offset ' + parseInt(offset, 10) + ' ';
    }
}

DBH.prepare = function(sql) {
    var cmd = {
        name : sql.trim(),
        text : sql
    }
    return function(values) {
        if (!(values instanceof Array)) {
            values = arguments;
        }
        cmd.values = values;
        return cmd;
    }
}

module.exports = DBH;
<|endoftext|>


<commit_before>import probe from './probe';
import sensor from './sensor';
import AsyncQueue from './AsyncQueue';

export default class Jar {
  constructor(config = {timelimit: 1000, queue: new AsyncQueue()}) {
    this._queue = config.queue;
  }

  probe(displayName) {
    return probe(displayName, {queue: this._queue, timelimit: config.timelimit});
  }

  sensor(displayName) {
    return sensor(displayName, {queue: this._queue, timelimit: config.timelimit});
  }

  done() {
    if (this._queue.isEmpty === false){
      throw new Error('Jar is not empty');
    }
  }
}
<commit_msg>fixed issue<commit_after>import probe from './probe';
import sensor from './sensor';
import AsyncQueue from './AsyncQueue';

export default class Jar {
  constructor(config = {timelimit: 1000, queue: new AsyncQueue()}) {
    this._queue = config.queue;
    this._timelimit = config.timelimit;
  }

  probe(displayName) {
    return probe(displayName, {queue: this._queue, timelimit: this._timelimit});
  }

  sensor(displayName) {
    return sensor(displayName, {queue: this._queue, timelimit: this._timelimit});
  }

  done() {
    if (this._queue.isEmpty === false){
      throw new Error('Jar is not empty');
    }
  }
}
<|endoftext|>