<commit_before>// This code is awful, and I know it.

var irc = require('irc');

var config = Config.ircconfig;
var connection = exports.connection = new irc.Client(config.server, config.nickname, config);

function identity(value) {
	return function identityFunction() {
		return value;
	}
}

function parseRaw(message) {
	return message
		.replace(/Super Effective<\/font><\/b>/g, "\x033Super Effective\x0F")
		.replace(/]*room=[^>]*>(.*?)<\/a>/g, "$1")
		.replace(/(.*?)<\/a>/g, "[$2]($1)")
		.replace(/
/g, "\n  • ")
		.replace(/<\/?(?:ul|font size|div)[^>]*?>/g, "")
		.replace(/.*?<\/small>/g, "")
		.replace(/<\/?(?:b|strong)(?: class="username")?>/g, "\x02")
		.replace(/<\/?em>/g, "\x1D")
		.replace(/<(?:\/span|\/font|font color=black)>/g, "\x0F")
		.replace(//g, "\x02\x034")
		.replace(//g, "\x02\x0312")
		.replace(//g, "\x02\x0314")
		.replace(//g, "\x02\x1F\x033")
		.replace(//g, "\x02\x1F\x034")
		.replace(//g, "\x0314")
		.replace(//g, "\x0314")
		.replace(/ |  | +/g, " ")
		.replace(/✓/g, "✓")
		.split(/
/);
}

function verifyParts(parts) {
	if (parts.length > 6) {
		return false;
	}
	for (var i = 0; i < parts.length; i++) {
		var part = parts[i];
		if (part.length > 440) {
			return false;
		}
	}
	return true;
}

function filter(message) {
	var parts = message.split(/\n/);
	var rawSignal = '|raw|';
	var dataSignal = '|c|~|/data-';
	var errorSignal = '|html|
';
	var finalParts = [];
	for (var i = 0; i < parts.length; i++) {
		var part = parts[i];
		var message;
		if (part.slice(0, rawSignal.length) === rawSignal) {
			message = part.slice(rawSignal.length);
			Array.prototype.push.apply(finalParts, parseRaw(message));
		} else if (part.slice(0, dataSignal.length) === dataSignal) {
			message = part.slice(dataSignal.length);
			var splitter = message.indexOf(' ');
			var type = message.slice(0, splitter);
			var what = message.slice(splitter + 1);
			finalParts.push(dataParsers[type](what));
		} else if (part.slice(0, errorSignal.length) !== errorSignal) {
			finalParts.push(part);
		}
	}
	if (!verifyParts(finalParts)) return "Response too long.";
	return finalParts.join("\n");
}

var dataParsers = {
	pokemon: function (specie) {
		var specieData = Tools.getTemplate(specie);
		var result = [];
		var tier = specieData.tier;
		if (!require('./data/tpp').BattleTPP[specieData.id] && !specieData.isNonstandard && !specieData.isUnreleased) {
			tier = 'T-Rule ' + tier;
		}
		result.push(tier);
		result.push(specieData.species);
		result.push(specieData.types.join("/") + '-type');

		var baseStats = [];
		var bst = 0;
		var stats = ['HP', 'Atk', 'Def', 'SpA', 'SpD', 'Spe'];
		var statsLength = stats.length;
		var i;
		for (i = 0; i < statsLength; i++) {
			var stat = stats[i];
			var statValue = specieData.baseStats[toId(stat)];
			bst += statValue;
			baseStats.push('\x0314' + stat + ':\x0F ' + statValue);
		}
		baseStats.push('\x0314BST:\x0F ' + bst);
		result.push(baseStats.join(', '));

		var abilityData = specieData.abilities;
		var abilityOrder = [0, 1, 'H'];
		var abilityOrderLength = abilityOrder.length;
		var abilities = [];

		for (i = 0; i < abilityOrderLength; i++) {
			var abilityPosition = abilityOrder[i];
			var ability = abilityData[abilityPosition];
			if (ability) {
				if (abilityPosition === 'H') {
					ability = '\x1D' + ability + '\x1D';
				}
				abilities.push(ability);
			}
		}
		result.push('\x0314Abilities:\x0F ' + abilities.join(', '));

		return result.join(' | ');
	},
	item: function (item) {
		var itemData = Tools.getItem(item);
		return [itemData.name, itemData.desc].join(' | ');
	},
	ability: function (ability) {
		var abilityData = Tools.getAbility(ability);
		return [abilityData.name, abilityData.shortDesc].join(' | ');
	},
	move: function (move) {
		var moveData = Tools.getMove(move);

		var result = [];
		result.push(moveData.name);
		result.push(moveData.category);
		result.push(moveData.type + '-type');

		if (moveData.category !== 'Status') {
			if (moveData.basePower) {
				result.push('\x0314Power:\x0F ' + moveData.basePower + ' BP');
			}
			else {
				result.push('\x0314Power:\x0F —');
			}
		}

		if (moveData.accuracy === true) {
			result.push('\x0314Accuracy:\x0F —');
		}
		else {
			result.push('\x0314Accuracy:\x0F ' + moveData.accuracy + '%');
		}

		result.push('\x0314PP:\x0F ' + moveData.pp * 8 / 5);
		result.push(moveData.shortDesc);

		return result.join(' | ');
	}
};

function FakeRoom(id) {
	this.id = id;
}
FakeRoom.prototype.isMuted = identity(false);
FakeRoom.prototype.users = {};

var ircUser = {
	named: false,
	can: identity(false),
	resetName: identity(),
	tryJoinRoom: identity(null),
	leaveRoom: identity(),
	group: ' '
};

var ircConnection = {
	sendTo: function (room, message) {
		connection.say(room.id, filter(message));
	},
	popup: identity()
};

connection.on('message', function parseMessage(from, to, message) {
	if (to.charAt(0) !== '#') {
		to = from;
	}
	if (/\byay\b/i.test(message)) {
		connection.say(to, 'Y+A+Y')
	}
	// DootBot conflict
	if (message.slice(0, 2) === '!?') return;
	if (message.charAt(0) !== '!' && message.charAt(0) !== '/') return;
	CommandParser.parse('/' + message.slice(1), new FakeRoom(to), ircUser, ircConnection);
});
<commit_msg>Add support into bot for unescaping HTML<commit_after>// This code is awful, and I know it.

var irc = require('irc');

var config = Config.ircconfig;
var connection = exports.connection = new irc.Client(config.server, config.nickname, config);

function identity(value) {
	return function identityFunction() {
		return value;
	}
}

function parseRaw(message) {
	return message
		.replace(/Super Effective<\/font><\/b>/g, "\x033Super Effective\x0F")
		.replace(/]*room=[^>]*>(.*?)<\/a>/g, "$1")
		.replace(/(.*?)<\/a>/g, "[$2]($1)")
		.replace(/
/g, "\n  • ")
		.replace(/<\/?(?:ul|font size|div)[^>]*?>/g, "")
		.replace(/.*?<\/small>/g, "")
		.replace(/<\/?(?:b|strong)(?: class="username")?>/g, "\x02")
		.replace(/<\/?em>/g, "\x1D")
		.replace(/<(?:\/span|\/font|font color=black)>/g, "\x0F")
		.replace(//g, "\x02\x034")
		.replace(//g, "\x02\x0312")
		.replace(//g, "\x02\x0314")
		.replace(//g, "\x02\x1F\x033")
		.replace(//g, "\x02\x1F\x034")
		.replace(//g, "\x0314")
		.replace(//g, "\x0314")
		.replace(/ |  | +/g, " ")
		.replace(/✓/g, "✓")
		.replace(/</g, "<")
		.replace(/>/g, ">")
		.replace(/"/g, '"')
		.replace(/'/g, "'")
		.replace(///g, "/")
		.replace(/é/, "é")
		.replace(/&/g, "&")
		.split(/
/);
}

function verifyParts(parts) {
	if (parts.length > 6) {
		return false;
	}
	for (var i = 0; i < parts.length; i++) {
		var part = parts[i];
		if (part.length > 440) {
			return false;
		}
	}
	return true;
}

function filter(message) {
	var parts = message.split(/\n/);
	var rawSignal = '|raw|';
	var dataSignal = '|c|~|/data-';
	var errorSignal = '|html|
';
	var finalParts = [];
	for (var i = 0; i < parts.length; i++) {
		var part = parts[i];
		var message;
		if (part.slice(0, rawSignal.length) === rawSignal) {
			message = part.slice(rawSignal.length);
			Array.prototype.push.apply(finalParts, parseRaw(message));
		} else if (part.slice(0, dataSignal.length) === dataSignal) {
			message = part.slice(dataSignal.length);
			var splitter = message.indexOf(' ');
			var type = message.slice(0, splitter);
			var what = message.slice(splitter + 1);
			finalParts.push(dataParsers[type](what));
		} else if (part.slice(0, errorSignal.length) !== errorSignal) {
			finalParts.push(part);
		}
	}
	if (!verifyParts(finalParts)) return "Response too long.";
	return finalParts.join("\n");
}

var dataParsers = {
	pokemon: function (specie) {
		var specieData = Tools.getTemplate(specie);
		var result = [];
		var tier = specieData.tier;
		if (!require('./data/tpp').BattleTPP[specieData.id] && !specieData.isNonstandard && !specieData.isUnreleased) {
			tier = 'T-Rule ' + tier;
		}
		result.push(tier);
		result.push(specieData.species);
		result.push(specieData.types.join("/") + '-type');

		var baseStats = [];
		var bst = 0;
		var stats = ['HP', 'Atk', 'Def', 'SpA', 'SpD', 'Spe'];
		var statsLength = stats.length;
		var i;
		for (i = 0; i < statsLength; i++) {
			var stat = stats[i];
			var statValue = specieData.baseStats[toId(stat)];
			bst += statValue;
			baseStats.push('\x0314' + stat + ':\x0F ' + statValue);
		}
		baseStats.push('\x0314BST:\x0F ' + bst);
		result.push(baseStats.join(', '));

		var abilityData = specieData.abilities;
		var abilityOrder = [0, 1, 'H'];
		var abilityOrderLength = abilityOrder.length;
		var abilities = [];

		for (i = 0; i < abilityOrderLength; i++) {
			var abilityPosition = abilityOrder[i];
			var ability = abilityData[abilityPosition];
			if (ability) {
				if (abilityPosition === 'H') {
					ability = '\x1D' + ability + '\x1D';
				}
				abilities.push(ability);
			}
		}
		result.push('\x0314Abilities:\x0F ' + abilities.join(', '));

		return result.join(' | ');
	},
	item: function (item) {
		var itemData = Tools.getItem(item);
		return [itemData.name, itemData.desc].join(' | ');
	},
	ability: function (ability) {
		var abilityData = Tools.getAbility(ability);
		return [abilityData.name, abilityData.shortDesc].join(' | ');
	},
	move: function (move) {
		var moveData = Tools.getMove(move);

		var result = [];
		result.push(moveData.name);
		result.push(moveData.category);
		result.push(moveData.type + '-type');

		if (moveData.category !== 'Status') {
			if (moveData.basePower) {
				result.push('\x0314Power:\x0F ' + moveData.basePower + ' BP');
			}
			else {
				result.push('\x0314Power:\x0F —');
			}
		}

		if (moveData.accuracy === true) {
			result.push('\x0314Accuracy:\x0F —');
		}
		else {
			result.push('\x0314Accuracy:\x0F ' + moveData.accuracy + '%');
		}

		result.push('\x0314PP:\x0F ' + moveData.pp * 8 / 5);
		result.push(moveData.shortDesc);

		return result.join(' | ');
	}
};

function FakeRoom(id) {
	this.id = id;
}
FakeRoom.prototype.isMuted = identity(false);
FakeRoom.prototype.users = {};

var ircUser = {
	named: false,
	can: identity(false),
	resetName: identity(),
	tryJoinRoom: identity(null),
	leaveRoom: identity(),
	group: ' '
};

var ircConnection = {
	sendTo: function (room, message) {
		connection.say(room.id, filter(message));
	},
	popup: identity()
};

connection.on('message', function parseMessage(from, to, message) {
	if (to.charAt(0) !== '#') {
		to = from;
	}
	if (/\byay\b/i.test(message)) {
		connection.say(to, 'Y+A+Y')
	}
	// DootBot conflict
	if (message.slice(0, 2) === '!?') return;
	if (message.charAt(0) !== '!' && message.charAt(0) !== '/') return;
	CommandParser.parse('/' + message.slice(1), new FakeRoom(to), ircUser, ircConnection);
});
<|endoftext|>


<commit_before><commit_msg>removed SpecHelper.js as no longer needed<commit_after><|endoftext|>


<commit_before>// Initialize the datepicker widgets
$(document).ready(function() {
    $(".datepickerTrigger").datepicker({
        buttonImage: "/third-party/Farm-Fresh_calendar_view_month.png",
        buttonImageOnly: true,
        changeMonth: true,
        changeYear: true,
        dateFormat: "yy-mm-dd",
        showOn: 'both',
	onSelect: function(dateText) {
	    // $(this) gets the input field to which the datepicker is attached.
        var wrapper =  $(this).closest(".datepickerWrapper")
        // put the selected date in the hidden input whose value will be used for filtering.
        wrapper.find(".form-control").val(dateText);
        // Also display the selected date so the user can see it.
        wrapper.find(".pickedDate").text(dateText);

	}
    });
});

<commit_msg>Remove datepickerInit.js #103<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2012, Matt Godbolt
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

function parseLines(lines, callback) {
    var re = /^\/tmp\/[^:]+:([0-9]+)(:([0-9]+))?:\s+(.*)/;
    $.each(lines.split('\n'), function(_, line) {
        line = line.trim();
        if (line != "") {
            var match = line.match(re);
            if (match) {
                callback(parseInt(match[1]), match[4]);
            } else {
                callback(null, line);
            }
        }
    });
}

function clearBackground(cm) {
    for (var i = 0; i < cm.lineCount(); ++i) {
        cm.removeLineClass(i, "background", null);
    }
}

const NumRainbowColours = 12;

function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback) {
    var compilersByExe = {};
    var pendingTimeout = null;
    var asmCodeMirror = null;
    var cppEditor = null;
    var lastRequest = null;
    var currentAssembly = null;
    var filters = origFilters;
    var ignoreChanges = true; // Horrible hack to avoid onChange doing anything on first starting, ie before we've set anything up.

    cppEditor = CodeMirror.fromTextArea(domRoot.find(".editor textarea")[0], {
        lineNumbers: true,
        matchBrackets: true,
        useCPP: true,
        mode: "text/x-c++src"
    });
    cppEditor.on("change", onChange);
    asmCodeMirror = CodeMirror.fromTextArea(domRoot.find(".asm textarea")[0], {
        lineNumbers: true,
                  matchBrackets: true,
                  mode: "text/x-asm",
                  readOnly: true
    });

    function getSetting(name) {
        return window.localStorage[windowLocalPrefix + "." + name];
    }
    function setSetting(name, value) {
        window.localStorage[windowLocalPrefix + "." + name] = value;
    }

    if (getSetting('code')) cppEditor.setValue(getSetting('code'));
    domRoot.find('.compiler').change(onCompilerChange);
    domRoot.find('.compiler_options').change(onChange).keyup(onChange);
    ignoreChanges = false;

    if (getSetting('compilerOptions')) {
        domRoot.find('.compiler_options').val(getSetting('compilerOptions'));
    }

    function makeErrNode(text) {
        var node = $('
!!
');
        node.find(".msg").text(text);
        return node[0];
    }

    var errorWidgets = [];
    function onCompileResponse(data) {
        var stdout = data.stdout || "";
        var stderr = data.stderr || "";
        if (data.code == 0) {
            stdout += "\nCompiled ok";
        } else {
            stderr += "\nCompilation failed";
        }
        $('.result .output :visible').remove();
        var highlightLine = (data.asm == null);
        for (var i = 0; i < errorWidgets.length; ++i)
            cppEditor.removeLineWidget(errorWidgets[i]);
        errorWidgets.length = 0;
        parseLines(stderr + stdout, function(lineNum, msg) {
            var elem = $('.result .output .template').clone().appendTo('.result .output').removeClass('template');
            if (lineNum) {
                errorWidgets.push(cppEditor.addLineWidget(lineNum - 1, makeErrNode(msg), {
                    coverGutter:false, noHScroll: true
                }));
                elem.html($('').append(lineNum + " : " + msg)).click(function() {
                    cppEditor.setSelection({line: lineNum - 1, ch: 0}, {line: lineNum, ch: 0});
                    return false;
                });
            } else {
                elem.text(msg);
            }
        });
        currentAssembly = data.asm || "[no output]";
        updateAsm();
    }

    function numberUsedLines(asm) {
        var sourceLines = {};
        $.each(asm, function(_, x) { if (x.source) sourceLines[x.source - 1] = true; });
        var ordinal = 0;
        $.each(sourceLines, function(k, _) { sourceLines[k] = ordinal++; });
        var asmLines = {};
        $.each(asm, function(index, x) { if (x.source) asmLines[index] = sourceLines[x.source - 1]; });
        return { source: sourceLines, asm: asmLines };
    }

    var lastUpdatedAsm = null;
    function updateAsm(forceUpdate) {
        if (!currentAssembly) return;
        var hashedUpdate = JSON.stringify({
            asm: currentAssembly,
            filters: filters
        });
        if (!forceUpdate && lastUpdatedAsm == hashedUpdate) { return; }
        lastUpdatedAsm = hashedUpdate;

        var asm = processAsm(currentAssembly, filters);
        var asmText = $.map(asm, function(x){ return x.text; }).join("\n");
        var numberedLines = numberUsedLines(asm);
        asmCodeMirror.setValue(asmText);

        clearBackground(cppEditor);
        clearBackground(asmCodeMirror);
        if (filters.colouriseAsm) {
            $.each(numberedLines.source, function(line, ordinal) {
                cppEditor.addLineClass(parseInt(line), "background", "rainbow-" + (ordinal % NumRainbowColours));
            });
            $.each(numberedLines.asm, function(line, ordinal) {
                asmCodeMirror.addLineClass(parseInt(line), "background", "rainbow-" + (ordinal % NumRainbowColours));
            });
        }
    }

    function pickOnlyRequestFilters(filters) {
        return {intel: !!filters.intel };
    }

    function onChange() {
        if (ignoreChanges) return;  // Ugly hack during startup.
        if (pendingTimeout) clearTimeout(pendingTimeout);
        pendingTimeout = setTimeout(function() {
            var data = {
                source: cppEditor.getValue(),
                compiler: $('.compiler').val(),
                options: $('.compiler_options').val(),
                filters: pickOnlyRequestFilters(filters)
            };
            setSetting('compiler', data.compiler);
            setSetting('compilerOptions', data.options);
            if (JSON.stringify(data) == JSON.stringify(lastRequest)) return;
            lastRequest = data;
            $.ajax({
                type: 'POST',
                url: '/compile',
                dataType: 'json',
                data: data,
                success: onCompileResponse});
            asmCodeMirror.setValue("Processing...");
        }, 750);
        setSetting('code', cppEditor.getValue());
        updateAsm();
        onChangeCallback();
    }

    function setSource(code) {
        cppEditor.setValue(code);
    }

    function getSource() {
        return cppEditor.getValue();
    }

    function serialiseState() {
        var state = {
            source: cppEditor.getValue(),
            compiler: domRoot.find('.compiler').val(),
            options: domRoot.find('.compiler_options').val(),
        };
        return state;
    }

    function deserialiseState(state) {
        cppEditor.setValue(state.source);
        domRoot.find('.compiler').val(state.compiler);
        domRoot.find('.compiler_options').val(state.options);
        // Somewhat hackily persist compiler into local storage else when the ajax response comes in
        // with the list of compilers it can splat over the deserialized version.
        // The whole serialize/hash/localStorage code is a mess! TODO(mg): fix
        setSetting('compiler', state.compiler);
        updateAsm(true);  // Force the update to reset colours after calling cppEditor.setValue
        return true;
    }

    function onCompilerChange() {
        onChange();
        var compiler = compilersByExe[$('.compiler').val()];
        domRoot.find('.filter button.btn[value="intel"]').toggleClass("disabled", !compiler.supportedOpts["-masm"]);
    }

    function setCompilers(compilers) {
        domRoot.find('.compiler option').remove();
        compilersByExe = {};
        $.each(compilers, function(index, arg) {
            compilersByExe[arg.exe] = arg;
            domRoot.find('.compiler').append($('<option value="' + arg.exe + '">' + arg.version + '</option>'));
        });
        if (getSetting('compiler')) {
            domRoot.find('.compiler').val(getSetting('compiler'));
        }
        onCompilerChange();
    }

    function setFilters(f) {
        filters = f;
        onChange();  // used to just update ASM, but things like "Intel syntax" need a new request
    }

    return {
        serialiseState: serialiseState,
        deserialiseState: deserialiseState,
        setCompilers: setCompilers,
        getSource: getSource,
        setSource: setSource,
        setFilters: setFilters
    };
}
<commit_msg>Use CodeMirror's batch api<commit_after>// Copyright (c) 2012, Matt Godbolt
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright
//       notice, this list of conditions and the following disclaimer in the
//       documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

function parseLines(lines, callback) {
    var re = /^\/tmp\/[^:]+:([0-9]+)(:([0-9]+))?:\s+(.*)/;
    $.each(lines.split('\n'), function(_, line) {
        line = line.trim();
        if (line != "") {
            var match = line.match(re);
            if (match) {
                callback(parseInt(match[1]), match[4]);
            } else {
                callback(null, line);
            }
        }
    });
}

function clearBackground(cm) {
    for (var i = 0; i < cm.lineCount(); ++i) {
        cm.removeLineClass(i, "background", null);
    }
}

const NumRainbowColours = 12;

function Compiler(domRoot, origFilters, windowLocalPrefix, onChangeCallback) {
    var compilersByExe = {};
    var pendingTimeout = null;
    var asmCodeMirror = null;
    var cppEditor = null;
    var lastRequest = null;
    var currentAssembly = null;
    var filters = origFilters;
    var ignoreChanges = true; // Horrible hack to avoid onChange doing anything on first starting, ie before we've set anything up.

    cppEditor = CodeMirror.fromTextArea(domRoot.find(".editor textarea")[0], {
        lineNumbers: true,
        matchBrackets: true,
        useCPP: true,
        mode: "text/x-c++src"
    });
    cppEditor.on("change", onChange);
    asmCodeMirror = CodeMirror.fromTextArea(domRoot.find(".asm textarea")[0], {
        lineNumbers: true,
                  matchBrackets: true,
                  mode: "text/x-asm",
                  readOnly: true
    });

    function getSetting(name) {
        return window.localStorage[windowLocalPrefix + "." + name];
    }
    function setSetting(name, value) {
        window.localStorage[windowLocalPrefix + "." + name] = value;
    }

    if (getSetting('code')) cppEditor.setValue(getSetting('code'));
    domRoot.find('.compiler').change(onCompilerChange);
    domRoot.find('.compiler_options').change(onChange).keyup(onChange);
    ignoreChanges = false;

    if (getSetting('compilerOptions')) {
        domRoot.find('.compiler_options').val(getSetting('compilerOptions'));
    }

    function makeErrNode(text) {
        var node = $('
!!
');
        node.find(".msg").text(text);
        return node[0];
    }

    var errorWidgets = [];
    function onCompileResponse(data) {
        var stdout = data.stdout || "";
        var stderr = data.stderr || "";
        if (data.code == 0) {
            stdout += "\nCompiled ok";
        } else {
            stderr += "\nCompilation failed";
        }
        $('.result .output :visible').remove();
        var highlightLine = (data.asm == null);
        for (var i = 0; i < errorWidgets.length; ++i)
            cppEditor.removeLineWidget(errorWidgets[i]);
        errorWidgets.length = 0;
        parseLines(stderr + stdout, function(lineNum, msg) {
            var elem = $('.result .output .template').clone().appendTo('.result .output').removeClass('template');
            if (lineNum) {
                errorWidgets.push(cppEditor.addLineWidget(lineNum - 1, makeErrNode(msg), {
                    coverGutter:false, noHScroll: true
                }));
                elem.html($('').append(lineNum + " : " + msg)).click(function() {
                    cppEditor.setSelection({line: lineNum - 1, ch: 0}, {line: lineNum, ch: 0});
                    return false;
                });
            } else {
                elem.text(msg);
            }
        });
        currentAssembly = data.asm || "[no output]";
        updateAsm();
    }

    function numberUsedLines(asm) {
        var sourceLines = {};
        $.each(asm, function(_, x) { if (x.source) sourceLines[x.source - 1] = true; });
        var ordinal = 0;
        $.each(sourceLines, function(k, _) { sourceLines[k] = ordinal++; });
        var asmLines = {};
        $.each(asm, function(index, x) { if (x.source) asmLines[index] = sourceLines[x.source - 1]; });
        return { source: sourceLines, asm: asmLines };
    }

    var lastUpdatedAsm = null;
    function updateAsm(forceUpdate) {
        if (!currentAssembly) return;
        var hashedUpdate = JSON.stringify({
            asm: currentAssembly,
            filters: filters
        });
        if (!forceUpdate && lastUpdatedAsm == hashedUpdate) { return; }
        lastUpdatedAsm = hashedUpdate;

        var asm = processAsm(currentAssembly, filters);
        var asmText = $.map(asm, function(x){ return x.text; }).join("\n");
        var numberedLines = numberUsedLines(asm);

        cppEditor.operation(function(){ clearBackground(cppEditor);});
        asmCodeMirror.operation(function() {
            asmCodeMirror.setValue(asmText);
            clearBackground(asmCodeMirror);
        });
        if (filters.colouriseAsm) {
            cppEditor.operation(function() {
                $.each(numberedLines.source, function(line, ordinal) {
                    cppEditor.addLineClass(parseInt(line),
                        "background", "rainbow-" + (ordinal % NumRainbowColours));
                });
            });
            asmCodeMirror.operation(function() {
                $.each(numberedLines.asm, function(line, ordinal) {
                    asmCodeMirror.addLineClass(parseInt(line),
                        "background", "rainbow-" + (ordinal % NumRainbowColours));
                });
            });
        }
    }

    function pickOnlyRequestFilters(filters) {
        return {intel: !!filters.intel };
    }

    function onChange() {
        if (ignoreChanges) return;  // Ugly hack during startup.
        if (pendingTimeout) clearTimeout(pendingTimeout);
        pendingTimeout = setTimeout(function() {
            var data = {
                source: cppEditor.getValue(),
                compiler: $('.compiler').val(),
                options: $('.compiler_options').val(),
                filters: pickOnlyRequestFilters(filters)
            };
            setSetting('compiler', data.compiler);
            setSetting('compilerOptions', data.options);
            if (JSON.stringify(data) == JSON.stringify(lastRequest)) return;
            lastRequest = data;
            $.ajax({
                type: 'POST',
                url: '/compile',
                dataType: 'json',
                data: data,
                success: onCompileResponse});
            asmCodeMirror.setValue("Processing...");
        }, 750);
        setSetting('code', cppEditor.getValue());
        updateAsm();
        onChangeCallback();
    }

    function setSource(code) {
        cppEditor.setValue(code);
    }

    function getSource() {
        return cppEditor.getValue();
    }

    function serialiseState() {
        var state = {
            source: cppEditor.getValue(),
            compiler: domRoot.find('.compiler').val(),
            options: domRoot.find('.compiler_options').val(),
        };
        return state;
    }

    function deserialiseState(state) {
        cppEditor.setValue(state.source);
        domRoot.find('.compiler').val(state.compiler);
        domRoot.find('.compiler_options').val(state.options);
        // Somewhat hackily persist compiler into local storage else when the ajax response comes in
        // with the list of compilers it can splat over the deserialized version.
        // The whole serialize/hash/localStorage code is a mess! TODO(mg): fix
        setSetting('compiler', state.compiler);
        updateAsm(true);  // Force the update to reset colours after calling cppEditor.setValue
        return true;
    }

    function onCompilerChange() {
        onChange();
        var compiler = compilersByExe[$('.compiler').val()];
        domRoot.find('.filter button.btn[value="intel"]').toggleClass("disabled", !compiler.supportedOpts["-masm"]);
    }

    function setCompilers(compilers) {
        domRoot.find('.compiler option').remove();
        compilersByExe = {};
        $.each(compilers, function(index, arg) {
            compilersByExe[arg.exe] = arg;
            domRoot.find('.compiler').append($('<option value="' + arg.exe + '">' + arg.version + '</option>'));
        });
        if (getSetting('compiler')) {
            domRoot.find('.compiler').val(getSetting('compiler'));
        }
        onCompilerChange();
    }

    function setFilters(f) {
        filters = f;
        onChange();  // used to just update ASM, but things like "Intel syntax" need a new request
    }

    return {
        serialiseState: serialiseState,
        deserialiseState: deserialiseState,
        setCompilers: setCompilers,
        getSource: getSource,
        setSource: setSource,
        setFilters: setFilters
    };
}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import Cismap from '../containers/Cismap';

import { connect } from "react-redux";
import { Tooltip, Button} from 'react-bootstrap';
import Control from 'react-leaflet-control';
import {Icon} from 'react-fa'

import { actions as mappingActions } from '../redux/modules/mapping';
import { actions as uiStateActions } from '../redux/modules/uiState';
import { actions as stadtplanActions } from '../redux/modules/stadtplan';
import {routerActions} from 'react-router-redux'

import { bindActionCreators } from 'redux';

import { featureStyler, featureHoverer, poiClusterIconCreator } from '../utils/stadtplanHelper';

import Loadable from 'react-loading-overlay';
import queryString from 'query-string';

import {modifyQueryPart} from '../utils/routingHelper'
import ProjSingleGeoJson from '../components/ProjSingleGeoJson';
import StadtplanInfo from '../components/StadtplanInfo';
import StadtplanModalApplicationMenu from '../components/StadtplanModalApplicationMenu';
import PhotoLightbox from './PhotoLightbox';

import 'react-image-lightbox/style.css';

function mapStateToProps(state) {
  return {
    uiState: state.uiState,
    mapping: state.mapping,
    routing: state.routing,
    stadtplan: state.stadtplan,
  };
}

function mapDispatchToProps(dispatch) {
  return {
    mappingActions: bindActionCreators(mappingActions, dispatch),
    uiStateActions: bindActionCreators(uiStateActions, dispatch),
    stadtplanActions: bindActionCreators(stadtplanActions, dispatch),
    routingActions: bindActionCreators(routerActions, dispatch),
  };
}

export class Stadtplan_ extends React.Component {
    constructor(props, context) {
      super(props, context);
      this.gazeteerhHit=this.gazeteerhHit.bind(this);
      this.searchButtonHit=this.searchButtonHit.bind(this);
      this.featureClick=this.featureClick.bind(this);
      this.gotoHome=this.gotoHome.bind(this);
      this.doubleMapClick=this.doubleMapClick.bind(this);
      this.searchTooltip=this.searchTooltip.bind(this);
      this.selectNextIndex=this.selectNextIndex.bind(this);
      this.selectPreviousIndex=this.selectPreviousIndex.bind(this);
      this.createfeatureCollectionByBoundingBox=this.createfeatureCollectionByBoundingBox.bind(this);
      this.filterChanged=this.filterChanged.bind(this);
      this.resetFilter=this.resetFilter.bind(this);
      this.centerOnPoint=this.centerOnPoint.bind(this);
      this.props.mappingActions.setBoundingBoxChangedTrigger(this.createfeatureCollectionByBoundingBox);
    }
    componentWillUnmount() {
        // console.log("Ehrenamt unmount")
    }

    componentWillMount() {
        // console.log("Ehrenamt mount")
        this.dataLoaded=false;
        this.loadThePOIs().then((data) => {
            this.dataLoaded=true;
        });
        //this.props.uiStateActions.setApplicationMenuActiveKey("filtertab");
      }
    componentWillUpdate() {

        if (this.props.stadtplan.pois.length===0){
            return;
        }
        // let urlCart=queryString.parse(this.props.routing.location.search).cart;
        // let urlCartIds=new Set();
        // if (urlCart){
        //     urlCartIds=new Set(urlCart.split(",").sort((a,b)=>parseInt(a,10)-parseInt(b,10)));
        // }
        // let cartIds=new Set(this.props.ehrenamt.cart.map(x=>x.id).sort((a,b)=>parseInt(a,10)-parseInt(b,10)));

        // let missingIdsInCart=new Set([...urlCartIds].filter(x => !cartIds.has(x)));

        // if (missingIdsInCart.size>0) {
        //     this.props.ehrenamtActions.addToCartByIds(Array.from(missingIdsInCart));
        // }

        // let newUrlCartArr=Array.from(cartIds).sort((a,b)=>parseInt(a,10)-parseInt(b,10));

        // let newUrlCart=newUrlCartArr.join();

        // if (urlCart!==newUrlCart && newUrlCart.length>0){

        //     let pn=this.props.routing.location.pathname;
        //     if (pn.indexOf("stadtplan")===-1){
        //         pn="/stadtplan"; //in certain conditions the pathname does not contain ehrenamt. fix that.
        //     }
        //     let newRoute= pn + modifyQueryPart(this.props.routing.location.search, {
        //         cart: newUrlCart
        //     });
        //     console.log("push new route:"+newRoute);
        //     this.props.routingActions.push(newRoute);
        // }
    }

    loadThePOIs() {
        var promise = new Promise((resolve, reject) => {
            setTimeout(() => {
                this.props.stadtplanActions.loadPOIs();
                resolve('ok');
            }, 100);
        });
        return promise;
    }
    createfeatureCollectionByBoundingBox(bbox) {
       this.props.stadtplanActions.createFeatureCollectionFromPOIs(bbox)
    }

    gazeteerhHit(selectedObject) {
        if (selectedObject && selectedObject[0] && selectedObject[0].more && selectedObject[0].more.pid) {
            //this.props.stadtplanActions.setPoiGazHit(selectedObject[0].more.pid);
            this.props.stadtplanActions.setSelectedPOI(selectedObject[0].more.pid);
        }
    }

    searchButtonHit(event) {

    }

    featureClick(event){
      if (event.target.feature) {
        this.props.mappingActions.setSelectedFeatureIndex(event.target.feature.index);
      }
    }

    doubleMapClick(event) {

    }

    gotoHome() {
      //x1=361332.75015625&y1=5669333.966678483&x2=382500.79703125&y2=5687261.576954328
      this.cismapRef.wrappedInstance.gotoHomeBB()
    }

    centerOnPoint(x,y,z) {
        this.cismapRef.wrappedInstance.centerOnPoint(x,y,z);
    }

    selectNextIndex() {
      let potIndex=this.props.mapping.selectedIndex+1;
      if (potIndex>=this.props.mapping.featureCollection.length){
        potIndex=0;
      }
      this.props.mappingActions.setSelectedFeatureIndex(potIndex);
      //this.props.mappingActions.fitSelectedFeatureBounds(stateConstants.AUTO_FIT_MODE_NO_ZOOM_IN);
    }

    selectPreviousIndex() {
      let potIndex=this.props.mapping.selectedIndex-1;
      if (potIndex<0){
        potIndex=this.props.mapping.featureCollection.length-1;
      }
      this.props.mappingActions.setSelectedFeatureIndex(potIndex);

    }
    filterChanged(filtergroup,filter) {
      //this.props.ehrenamtActions.toggleFilter(filtergroup,filter);
    }

    resetFilter() {
        // if (this.props.ehrenamt.mode===ehrenamtConstants.FILTER_FILTER){
        //     this.props.ehrenamtActions.resetFilter();
        // }
        // else {
        //     this.props.ehrenamtActions.setMode(ehrenamtConstants.FILTER_FILTER);
        // }

    }
    searchTooltip(){
        return (
);
    };

    render() {
      let info= null;
           info = (

             <StadtplanInfo
             key={"stadtplanInfo."+(this.props.mapping.selectedIndex||0)}
              pixelwidth={300}
              featureCollection={this.props.mapping.featureCollection}
              filteredPOIs={this.props.stadtplan.filteredPois}
              selectedIndex={this.props.mapping.selectedIndex||0}
              next={this.selectNextIndex}
              previous={this.selectPreviousIndex}
              fitAll={this.gotoHome}
              showModalMenu={(section)=>this.props.uiStateActions.showApplicationMenuAndActivateSection(true,section)}
              uiState={this.props.uiState}
              uiStateActions={this.props.uiStateActions}

              />
           );
        // Auflistung der ids die momentan nicht dargestllt werden
        // let offerIds=[];
        // let fcIds=[];
        // for (let f of this.props.mapping.featureCollection) {
        //     fcIds.push(f.id);
        // }
        // for (let o of this.props.ehrenamt.offers) {
        //     offerIds.push(o.id);
        // }
        // offerIds.sort();
        // fcIds.sort();
        // let difference = offerIds.filter(x => !fcIds.includes(x));
        // console.log(difference);

    let title=null;
    let themenstadtplanDesc="";
    let content;
    let qTitle=queryString.parse(this.props.routing.location.search).title;
    if (qTitle!==undefined){
        if (qTitle===null) {
            if  (this.props.stadtplan.filter.positiv.length>0) {
                if (this.props.stadtplan.filter.positiv.length<=4) {
                    themenstadtplanDesc+=this.props.stadtplan.filter.positiv.join(", ")
                }
                else {
                    themenstadtplanDesc+=this.props.stadtplan.filter.positiv.length+" Themen"
                }
            }
            if  (this.props.stadtplan.filter.negativ.length>0) {
                themenstadtplanDesc+=" ohne ";
                if  (this.props.stadtplan.filter.negativ.length<=3) {
                    themenstadtplanDesc+=this.props.stadtplan.filter.negativ.join(", ")
                }
            }
            content=(

                    Mein Themenstadtplan:  {themenstadtplanDesc}

            );
        }
        else {
            themenstadtplanDesc=qTitle;
            content=(

                    {themenstadtplanDesc}

            );
        }
        title=(

                           {content}

        );
    }

      return (

                <StadtplanModalApplicationMenu key={'StadtplanModalApplicationMenu.visible:'+this.props.uiState.applicationMenuVisible}
                    lebenslagen={this.props.stadtplan.lebenslagen}
                    filter={this.props.stadtplan.filter}
                    filterChanged={this.filterChanged}
                    filteredPois={this.props.stadtplan.filteredPois||[]}
                    featureCollectionCount={this.props.mapping.featureCollection.length}
                    offersMD5={this.props.stadtplan.poisMD5}
                    centerOnPoint={this.centerOnPoint}
                    stadtplanActions={this.props.stadtplanActions}
                />
               <Loadable
                active={!this.dataLoaded}
                spinner
                text='Laden der POIs ...'
                >
                <PhotoLightbox/>
                {title}
                <Cismap ref={cismap => {this.cismapRef = cismap;}}
                       layers={this.props.match.params.layers ||'rvrWMS@90'}
                       gazeteerHitTrigger={this.gazeteerhHit}
                       searchButtonTrigger={this.searchButtonHit}
                       featureStyler={featureStyler}
                       hoverer={featureHoverer}
                       featureClickHandler={this.featureClick}
                       ondblclick={this.doubleMapClick}
                       searchTooltipProvider={this.searchTooltip}
                       searchMinZoom={99}
                       searchMaxZoom={98}
                       gazTopics={["adressen", "bezirke", "quartiere","pois"]}
                       clustered={(queryString.parse(this.props.routing.location.search).unclustered)===undefined}
                       minZoom={6}
                       clusterOptions={{
                            spiderfyOnMaxZoom: false,
                            showCoverageOnHover: false,
                            zoomToBoundsOnClick: false,
                            maxClusterRadius:40,
                            disableClusteringAtZoom:19,
                            animate:false,
                            cismapZoomTillSpiderfy:12,
                            selectionSpiderfyMinZoom:12,
                            iconCreateFunction: poiClusterIconCreator,
                        }}
                        infoBox={info}
                        applicationMenuTooltipProvider={()=> (<Tooltip style={{
                                zIndex: 3000000000
                              }} id="helpTooltip">Themenstadtplan | Einstellungen | Anleitung</Tooltip>)
                           }
                        gazBoxInfoText="Stadtteil | Adresse | POI" >
                    </Cismap>
               </Loadable>

       );
    }
}

//<Control position = "bottomleft"> <Button>xxx</Button></Control>

const Stadtplan = connect(mapStateToProps,mapDispatchToProps)(Stadtplan_);

export default Stadtplan;

Stadtplan.propTypes = {
  ui: PropTypes.object,
  uiState: PropTypes.object,
};
<commit_msg>:sparkles: #18: if more than 3 topics are in the negatuve filter in the title there is only a summary<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import Cismap from '../containers/Cismap';

import { connect } from "react-redux";
import { Tooltip, Button} from 'react-bootstrap';
import Control from 'react-leaflet-control';
import {Icon} from 'react-fa'

import { actions as mappingActions } from '../redux/modules/mapping';
import { actions as uiStateActions } from '../redux/modules/uiState';
import { actions as stadtplanActions } from '../redux/modules/stadtplan';
import {routerActions} from 'react-router-redux'

import { bindActionCreators } from 'redux';

import { featureStyler, featureHoverer, poiClusterIconCreator } from '../utils/stadtplanHelper';

import Loadable from 'react-loading-overlay';
import queryString from 'query-string';

import {modifyQueryPart} from '../utils/routingHelper'
import ProjSingleGeoJson from '../components/ProjSingleGeoJson';
import StadtplanInfo from '../components/StadtplanInfo';
import StadtplanModalApplicationMenu from '../components/StadtplanModalApplicationMenu';
import PhotoLightbox from './PhotoLightbox';

import 'react-image-lightbox/style.css';

function mapStateToProps(state) {
  return {
    uiState: state.uiState,
    mapping: state.mapping,
    routing: state.routing,
    stadtplan: state.stadtplan,
  };
}

function mapDispatchToProps(dispatch) {
  return {
    mappingActions: bindActionCreators(mappingActions, dispatch),
    uiStateActions: bindActionCreators(uiStateActions, dispatch),
    stadtplanActions: bindActionCreators(stadtplanActions, dispatch),
    routingActions: bindActionCreators(routerActions, dispatch),
  };
}

export class Stadtplan_ extends React.Component {
    constructor(props, context) {
      super(props, context);
      this.gazeteerhHit=this.gazeteerhHit.bind(this);
      this.searchButtonHit=this.searchButtonHit.bind(this);
      this.featureClick=this.featureClick.bind(this);
      this.gotoHome=this.gotoHome.bind(this);
      this.doubleMapClick=this.doubleMapClick.bind(this);
      this.searchTooltip=this.searchTooltip.bind(this);
      this.selectNextIndex=this.selectNextIndex.bind(this);
      this.selectPreviousIndex=this.selectPreviousIndex.bind(this);
      this.createfeatureCollectionByBoundingBox=this.createfeatureCollectionByBoundingBox.bind(this);
      this.filterChanged=this.filterChanged.bind(this);
      this.resetFilter=this.resetFilter.bind(this);
      this.centerOnPoint=this.centerOnPoint.bind(this);
      this.props.mappingActions.setBoundingBoxChangedTrigger(this.createfeatureCollectionByBoundingBox);
    }
    componentWillUnmount() {
        // console.log("Ehrenamt unmount")
    }

    componentWillMount() {
        // console.log("Ehrenamt mount")
        this.dataLoaded=false;
        this.loadThePOIs().then((data) => {
            this.dataLoaded=true;
        });
        //this.props.uiStateActions.setApplicationMenuActiveKey("filtertab");
      }
    componentWillUpdate() {

        if (this.props.stadtplan.pois.length===0){
            return;
        }
        // let urlCart=queryString.parse(this.props.routing.location.search).cart;
        // let urlCartIds=new Set();
        // if (urlCart){
        //     urlCartIds=new Set(urlCart.split(",").sort((a,b)=>parseInt(a,10)-parseInt(b,10)));
        // }
        // let cartIds=new Set(this.props.ehrenamt.cart.map(x=>x.id).sort((a,b)=>parseInt(a,10)-parseInt(b,10)));

        // let missingIdsInCart=new Set([...urlCartIds].filter(x => !cartIds.has(x)));

        // if (missingIdsInCart.size>0) {
        //     this.props.ehrenamtActions.addToCartByIds(Array.from(missingIdsInCart));
        // }

        // let newUrlCartArr=Array.from(cartIds).sort((a,b)=>parseInt(a,10)-parseInt(b,10));

        // let newUrlCart=newUrlCartArr.join();

        // if (urlCart!==newUrlCart && newUrlCart.length>0){

        //     let pn=this.props.routing.location.pathname;
        //     if (pn.indexOf("stadtplan")===-1){
        //         pn="/stadtplan"; //in certain conditions the pathname does not contain ehrenamt. fix that.
        //     }
        //     let newRoute= pn + modifyQueryPart(this.props.routing.location.search, {
        //         cart: newUrlCart
        //     });
        //     console.log("push new route:"+newRoute);
        //     this.props.routingActions.push(newRoute);
        // }
    }

    loadThePOIs() {
        var promise = new Promise((resolve, reject) => {
            setTimeout(() => {
                this.props.stadtplanActions.loadPOIs();
                resolve('ok');
            }, 100);
        });
        return promise;
    }
    createfeatureCollectionByBoundingBox(bbox) {
       this.props.stadtplanActions.createFeatureCollectionFromPOIs(bbox)
    }

    gazeteerhHit(selectedObject) {
        if (selectedObject && selectedObject[0] && selectedObject[0].more && selectedObject[0].more.pid) {
            //this.props.stadtplanActions.setPoiGazHit(selectedObject[0].more.pid);
            this.props.stadtplanActions.setSelectedPOI(selectedObject[0].more.pid);
        }
    }

    searchButtonHit(event) {

    }

    featureClick(event){
      if (event.target.feature) {
        this.props.mappingActions.setSelectedFeatureIndex(event.target.feature.index);
      }
    }

    doubleMapClick(event) {

    }

    gotoHome() {
      //x1=361332.75015625&y1=5669333.966678483&x2=382500.79703125&y2=5687261.576954328
      this.cismapRef.wrappedInstance.gotoHomeBB()
    }

    centerOnPoint(x,y,z) {
        this.cismapRef.wrappedInstance.centerOnPoint(x,y,z);
    }

    selectNextIndex() {
      let potIndex=this.props.mapping.selectedIndex+1;
      if (potIndex>=this.props.mapping.featureCollection.length){
        potIndex=0;
      }
      this.props.mappingActions.setSelectedFeatureIndex(potIndex);
      //this.props.mappingActions.fitSelectedFeatureBounds(stateConstants.AUTO_FIT_MODE_NO_ZOOM_IN);
    }

    selectPreviousIndex() {
      let potIndex=this.props.mapping.selectedIndex-1;
      if (potIndex<0){
        potIndex=this.props.mapping.featureCollection.length-1;
      }
      this.props.mappingActions.setSelectedFeatureIndex(potIndex);

    }
    filterChanged(filtergroup,filter) {
      //this.props.ehrenamtActions.toggleFilter(filtergroup,filter);
    }

    resetFilter() {
        // if (this.props.ehrenamt.mode===ehrenamtConstants.FILTER_FILTER){
        //     this.props.ehrenamtActions.resetFilter();
        // }
        // else {
        //     this.props.ehrenamtActions.setMode(ehrenamtConstants.FILTER_FILTER);
        // }

    }
    searchTooltip(){
        return (
);
    };

    render() {
      let info= null;
           info = (

             <StadtplanInfo
             key={"stadtplanInfo."+(this.props.mapping.selectedIndex||0)}
              pixelwidth={300}
              featureCollection={this.props.mapping.featureCollection}
              filteredPOIs={this.props.stadtplan.filteredPois}
              selectedIndex={this.props.mapping.selectedIndex||0}
              next={this.selectNextIndex}
              previous={this.selectPreviousIndex}
              fitAll={this.gotoHome}
              showModalMenu={(section)=>this.props.uiStateActions.showApplicationMenuAndActivateSection(true,section)}
              uiState={this.props.uiState}
              uiStateActions={this.props.uiStateActions}

              />
           );
        // Auflistung der ids die momentan nicht dargestllt werden
        // let offerIds=[];
        // let fcIds=[];
        // for (let f of this.props.mapping.featureCollection) {
        //     fcIds.push(f.id);
        // }
        // for (let o of this.props.ehrenamt.offers) {
        //     offerIds.push(o.id);
        // }
        // offerIds.sort();
        // fcIds.sort();
        // let difference = offerIds.filter(x => !fcIds.includes(x));
        // console.log(difference);

    let title=null;
    let themenstadtplanDesc="";
    let content;
    let qTitle=queryString.parse(this.props.routing.location.search).title;
    if (qTitle!==undefined){
        if (qTitle===null) {
            if  (this.props.stadtplan.filter.positiv.length>0) {
                if (this.props.stadtplan.filter.positiv.length<=4) {
                    themenstadtplanDesc+=this.props.stadtplan.filter.positiv.join(", ")
                }
                else {
                    themenstadtplanDesc+=this.props.stadtplan.filter.positiv.length+" Themen"
                }
            }
            if  (this.props.stadtplan.filter.negativ.length>0) {
                if  (this.props.stadtplan.filter.negativ.length<=3) {
                    themenstadtplanDesc+=" ohne ";
                    themenstadtplanDesc+=this.props.stadtplan.filter.negativ.join(", ");
                }
                else {
                    themenstadtplanDesc+=" ("+this.props.stadtplan.filter.negativ.length+" Themen ausgeschlossen)";
                }
            }
            content=(

                    Mein Themenstadtplan:  {themenstadtplanDesc}

            );
        }
        else {
            themenstadtplanDesc=qTitle;
            content=(

                    {themenstadtplanDesc}

            );
        }
        title=(

                           {content}

        );
    }

      return (

                <StadtplanModalApplicationMenu key={'StadtplanModalApplicationMenu.visible:'+this.props.uiState.applicationMenuVisible}
                    lebenslagen={this.props.stadtplan.lebenslagen}
                    filter={this.props.stadtplan.filter}
                    filterChanged={this.filterChanged}
                    filteredPois={this.props.stadtplan.filteredPois||[]}
                    featureCollectionCount={this.props.mapping.featureCollection.length}
                    offersMD5={this.props.stadtplan.poisMD5}
                    centerOnPoint={this.centerOnPoint}
                    stadtplanActions={this.props.stadtplanActions}
                />
               <Loadable
                active={!this.dataLoaded}
                spinner
                text='Laden der POIs ...'
                >
                <PhotoLightbox/>
                {title}
                <Cismap ref={cismap => {this.cismapRef = cismap;}}
                       layers={this.props.match.params.layers ||'rvrWMS@90'}
                       gazeteerHitTrigger={this.gazeteerhHit}
                       searchButtonTrigger={this.searchButtonHit}
                       featureStyler={featureStyler}
                       hoverer={featureHoverer}
                       featureClickHandler={this.featureClick}
                       ondblclick={this.doubleMapClick}
                       searchTooltipProvider={this.searchTooltip}
                       searchMinZoom={99}
                       searchMaxZoom={98}
                       gazTopics={["adressen", "bezirke", "quartiere","pois"]}
                       clustered={(queryString.parse(this.props.routing.location.search).unclustered)===undefined}
                       minZoom={6}
                       clusterOptions={{
                            spiderfyOnMaxZoom: false,
                            showCoverageOnHover: false,
                            zoomToBoundsOnClick: false,
                            maxClusterRadius:40,
                            disableClusteringAtZoom:19,
                            animate:false,
                            cismapZoomTillSpiderfy:12,
                            selectionSpiderfyMinZoom:12,
                            iconCreateFunction: poiClusterIconCreator,
                        }}
                        infoBox={info}
                        applicationMenuTooltipProvider={()=> (<Tooltip style={{
                                zIndex: 3000000000
                              }} id="helpTooltip">Themenstadtplan | Einstellungen | Anleitung</Tooltip>)
                           }
                        gazBoxInfoText="Stadtteil | Adresse | POI" >
                    </Cismap>
               </Loadable>

       );
    }
}

//<Control position = "bottomleft"> <Button>xxx</Button></Control>

const Stadtplan = connect(mapStateToProps,mapDispatchToProps)(Stadtplan_);

export default Stadtplan;

Stadtplan.propTypes = {
  ui: PropTypes.object,
  uiState: PropTypes.object,
};
<|endoftext|>


<commit_before>CT.panel = {
	"lastClicked": {},
	"swap": function(key, trysidepanel, keystring, noitem) {
	    keystring = keystring || "sb";
	    key = key.replace(/ /g, "");
	    var items = CT.dom.className(keystring + "panel");
	    for (var i = 0; i < items.length; i++)
	        items[i].className = keystring + "panel hidden";
	    CT.dom.id(keystring +  "panel" + key).className = keystring + "panel";
	    if (trysidepanel) {
	        var n = CT.dom.id(keystring + "panel" + key + "Side");
	        if (n) n.className = keystring+"panel";
	        var n2 = CT.dom.id(keystring + "panel" + key + "Side2");
	        if (n2) n2.className = keystring + "panel";
	    }
	    if (!noitem)
	        CT.panel.select(key, keystring);
	},
	"select": function(key, keystring) {
	    keystring = keystring || "sb";
	    var items = CT.dom.className(keystring + "item");
	    for (var i = 0; i < items.length; i++)
	        items[i].className = items[i].className.replace(" activetab", "");
	    if (key) {
	        CT.dom.id(keystring + "item" + key, true).className += " activetab";
	        CT.panel.lastClicked[keystring] = key;
	    }
	    CT.mobile && CT.mobile.mobileSnap();
	},
	"selectLister": function(newkey, oldkey, newhtml) {
	    if (oldkey)
	        CT.dom.id("ll" + oldkey).className = "pointer";
	    var newnode = CT.dom.id("ll" + newkey);
	    newnode.className = "pointer activetab";
	    if (newhtml)
	        newnode.firstChild.innerHTML = newhtml;
	    CT.mobile && CT.mobile.mobileSnap();
	},
	"add": function(key, trysidepanel, keystring, itemnode, panelnode, nospace, icon, cb) {
	    nospace = nospace || key.replace(/ /g, "");
	    keystring = keystring || "sb";
	    if (!CT.dom.id(keystring + "panel" + nospace)) {
	        var n = CT.dom.node("", "div", keystring + "panel", keystring + "panel" + nospace);
	        n.appendChild(CT.dom.node(key, "div", CT.style.panel.title));
	        n.appendChild(CT.dom.node("", "div", "", keystring+"content"+nospace));
	        (panelnode || CT.dom.id(keystring+"panels")).appendChild(n);
	    }
	    var i = CT.dom.id(keystring+"item"+nospace);
	    if (i)
	        i.style.display = "block";
	    else {
	        itemnode = itemnode || CT.dom.id(keystring+"items");
	        var clickfunc = function() {
	            CT.panel.swap(nospace, trysidepanel, keystring);
	            cb && cb();
	        };
	        if (icon)
	            itemnode.appendChild(CT.dom.node(CT.dom.img(icon,
	                null, clickfunc), "div", "lfloat shiftleft"));
	        itemnode.appendChild(CT.dom.node(CT.dom.link(key, clickfunc),
	            "div", keystring + "item pointer", keystring + "item" + nospace));
	        if (icon)
	            itemnode.appendChild(CT.dom.node("", "div", "clearnode"));
	    }
	},
	"remove": function(key, keystring) {
	    var nospace = key.replace(/ /g, "");
	    var p = CT.dom.id(keystring+"panel"+nospace);
	    if (p) p.style.display = "none";
	    var l = CT.dom.id(keystring+"item"+nospace);
	    if (l) l.style.display = "none";
	},
	"load": function(pnames, trysidepanel, keystring, itemnode, panelnode, nospaces, icons, noclear, stillswap, cbs) {
	    keystring = keystring || "sb";
	    if (!noclear)
	        (itemnode || CT.dom.id(keystring+"items")).innerHTML = "";
	    for (var i = 0; i < pnames.length; i++)
	        CT.panel.add(pnames[i], trysidepanel, keystring, itemnode,
	            panelnode, nospaces && nospaces[i] || null,
	            icons && icons[i] || null, cbs && cbs[i] || null);
	    if (pnames.length && (stillswap || (!itemnode && !noclear)))
	        CT.panel.swap(pnames[0], trysidepanel, keystring);
	},
	"simple": function(pnames, keystring, itemnode, panelnode, cbs) {
		CT.panel.load(pnames, null, keystring, itemnode, panelnode, null, null, null, true, cbs);
	},
	"pager": function(getContent, request, limit, colClass, dataClass, ks) {
		var content = CT.dom.node(null, null, dataClass),
			sideBar = CT.dom.node(),
			pager = new CT.Pager(function(data) {
				var dnames = data.map(function(d) { return (d.label || d.key); }),
					keystring = ks || ("p" + pager.id);
				CT.panel.simple(dnames, keystring, sideBar, content);
				data.forEach(function(d) {
					CT.dom.setContent(CT.dom.id(keystring + "content"
						+ (d.label || d.key).replace(/ /g, ""),
						true), getContent(d));
				});
				return sideBar;
			}, request, limit, colClass),
			n = CT.dom.node([pager.node, content]);
		n.pager = pager;
		return n;
	},
	"alternatebg": function(n, watchforicons, resetonbreak) {
	    n = n || document.getElementById("sbitems");
	    if (watchforicons) {
	        var switcher = 1;
	        for (var i = 0; i < n.childNodes.length; i++) {
	            var c = n.childNodes[i];
	            if (c.className.indexOf("lfloat") == -1 && c.className.indexOf("clearnode") == -1) {
	                if (resetonbreak && c.nodeName == "BR") {
	                    switcher = 1;
	                    continue;
	                }
	                if (switcher == 1)
	                    c.style.background = "#899fb0";
	                switcher *= -1;
	            }
	        }
	    }
	    else {
	        for (var i = 0; i < n.childNodes.length; i+=2)
	            n.childNodes[i].style.background = "#899fb0";
	    }
	}
};<commit_msg>CT.panel.drill(): processes an object mapping panel keystrings to data keys<commit_after>CT.panel = {
	"lastClicked": {},
	"swap": function(key, trysidepanel, keystring, noitem) {
	    keystring = keystring || "sb";
	    key = key.replace(/ /g, "");
	    var items = CT.dom.className(keystring + "panel");
	    for (var i = 0; i < items.length; i++)
	        items[i].className = keystring + "panel hidden";
	    CT.dom.id(keystring +  "panel" + key).className = keystring + "panel";
	    if (trysidepanel) {
	        var n = CT.dom.id(keystring + "panel" + key + "Side");
	        if (n) n.className = keystring+"panel";
	        var n2 = CT.dom.id(keystring + "panel" + key + "Side2");
	        if (n2) n2.className = keystring + "panel";
	    }
	    if (!noitem)
	        CT.panel.select(key, keystring);
	},
	"drill": function(keymap) { // keystring: key
		for (var k in keymap)
			CT.panel.swap(keymap[k], false, k);
	},
	"select": function(key, keystring) {
	    keystring = keystring || "sb";
	    var items = CT.dom.className(keystring + "item");
	    for (var i = 0; i < items.length; i++)
	        items[i].className = items[i].className.replace(" activetab", "");
	    if (key) {
	        CT.dom.id(keystring + "item" + key, true).className += " activetab";
	        CT.panel.lastClicked[keystring] = key;
	    }
	    CT.mobile && CT.mobile.mobileSnap();
	},
	"selectLister": function(newkey, oldkey, newhtml) {
	    if (oldkey)
	        CT.dom.id("ll" + oldkey).className = "pointer";
	    var newnode = CT.dom.id("ll" + newkey);
	    newnode.className = "pointer activetab";
	    if (newhtml)
	        newnode.firstChild.innerHTML = newhtml;
	    CT.mobile && CT.mobile.mobileSnap();
	},
	"add": function(key, trysidepanel, keystring, itemnode, panelnode, nospace, icon, cb) {
	    nospace = nospace || key.replace(/ /g, "");
	    keystring = keystring || "sb";
	    if (!CT.dom.id(keystring + "panel" + nospace)) {
	        var n = CT.dom.node("", "div", keystring + "panel", keystring + "panel" + nospace);
	        n.appendChild(CT.dom.node(key, "div", CT.style.panel.title));
	        n.appendChild(CT.dom.node("", "div", "", keystring+"content"+nospace));
	        (panelnode || CT.dom.id(keystring+"panels")).appendChild(n);
	    }
	    var i = CT.dom.id(keystring+"item"+nospace);
	    if (i)
	        i.style.display = "block";
	    else {
	        itemnode = itemnode || CT.dom.id(keystring+"items");
	        var clickfunc = function() {
	            CT.panel.swap(nospace, trysidepanel, keystring);
	            cb && cb();
	        };
	        if (icon)
	            itemnode.appendChild(CT.dom.node(CT.dom.img(icon,
	                null, clickfunc), "div", "lfloat shiftleft"));
	        itemnode.appendChild(CT.dom.node(CT.dom.link(key, clickfunc),
	            "div", keystring + "item pointer", keystring + "item" + nospace));
	        if (icon)
	            itemnode.appendChild(CT.dom.node("", "div", "clearnode"));
	    }
	},
	"remove": function(key, keystring) {
	    var nospace = key.replace(/ /g, "");
	    var p = CT.dom.id(keystring+"panel"+nospace);
	    if (p) p.style.display = "none";
	    var l = CT.dom.id(keystring+"item"+nospace);
	    if (l) l.style.display = "none";
	},
	"load": function(pnames, trysidepanel, keystring, itemnode, panelnode, nospaces, icons, noclear, stillswap, cbs) {
	    keystring = keystring || "sb";
	    if (!noclear)
	        (itemnode || CT.dom.id(keystring+"items")).innerHTML = "";
	    for (var i = 0; i < pnames.length; i++)
	        CT.panel.add(pnames[i], trysidepanel, keystring, itemnode,
	            panelnode, nospaces && nospaces[i] || null,
	            icons && icons[i] || null, cbs && cbs[i] || null);
	    if (pnames.length && (stillswap || (!itemnode && !noclear)))
	        CT.panel.swap(pnames[0], trysidepanel, keystring);
	},
	"simple": function(pnames, keystring, itemnode, panelnode, cbs) {
		CT.panel.load(pnames, null, keystring, itemnode, panelnode, null, null, null, true, cbs);
	},
	"pager": function(getContent, request, limit, colClass, dataClass, ks) {
		var content = CT.dom.node(null, null, dataClass),
			sideBar = CT.dom.node(),
			pager = new CT.Pager(function(data) {
				var dnames = data.map(function(d) { return (d.label || d.key); }),
					keystring = ks || ("p" + pager.id);
				CT.panel.simple(dnames, keystring, sideBar, content);
				data.forEach(function(d) {
					CT.dom.setContent(CT.dom.id(keystring + "content"
						+ (d.label || d.key).replace(/ /g, ""),
						true), getContent(d));
				});
				return sideBar;
			}, request, limit, colClass),
			n = CT.dom.node([pager.node, content]);
		n.pager = pager;
		return n;
	},
	"alternatebg": function(n, watchforicons, resetonbreak) {
	    n = n || document.getElementById("sbitems");
	    if (watchforicons) {
	        var switcher = 1;
	        for (var i = 0; i < n.childNodes.length; i++) {
	            var c = n.childNodes[i];
	            if (c.className.indexOf("lfloat") == -1 && c.className.indexOf("clearnode") == -1) {
	                if (resetonbreak && c.nodeName == "BR") {
	                    switcher = 1;
	                    continue;
	                }
	                if (switcher == 1)
	                    c.style.background = "#899fb0";
	                switcher *= -1;
	            }
	        }
	    }
	    else {
	        for (var i = 0; i < n.childNodes.length; i+=2)
	            n.childNodes[i].style.background = "#899fb0";
	    }
	}
};<|endoftext|>


<commit_before>if (!window.jQuery) {
  var jq = document.createElement('script'); jq.type = 'text/javascript';
  // Path to jquery.js file, eg. Google hosted version
  jq.src = "//ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.min.js",
  //jq.src = 'js/jquery.min.js'; // local loading
  document.getElementsByTagName('head')[0].appendChild(jq);
}

var PDP = {}; // stop it being loaded twice (until we want that.)
PDP.config = { version: "0.02", overlay: {}, menu: {} },
// check the local store for css and config
PDP.loadUserSettings = function(){
 // check local storage (recursively, the local settings may indicate that the settings are in another castle)
    console.log('looking for settings');
},
PDP.loadUserData = function(){
// check local storage for data
    console.log('checking local storage for user data');
},
PDP.message = function (m, t) {
// alert the user of something
alert(t +": " + m);
},
PDP.menu = function(){
// parent for the menu functions
},
PDP.menu.tab = function(){
// create the menu tab
},
PDP.menu.append = function(){
// if the settings don't explicity block it, then add a menu icon to the overlay
// so that the user can access the config menu
},
PDP.init = function () {
  var a = this,
    b = this.config;
  this.loadUserSettings(),
  this.loadUserData();
  //"undefined" == typeof this.config.overlay.noShow ?  this.loadOverlay() : console.log("overlay hidden by config") ;
  this.config.overlay.noShow != 1 ? this.loadOverlay() :  console.log("overlay hidden by config") ;
  this.config.menu.noShow != 1 ? this.menu.append(this.menu.tab) : console.log("menu hidden by config") ;
},
PDP.update = function() {
// save data and send changes
}
PDP.loadOverlay = function(){
    console.log("loading overlay");

    var ovl = document.createElement('div');
    ovl.setAttribute("contentEditable", true);
    ovl.setAttribute("class", 'PDP_overlay overlay');
    ovl.innerHTML = 'Welcome to Your Personal Data: Feel free to add something here';
    var body_elm = {};
    if( body_elm = document.getElementsByTagName('body')[0]){
        body_elm.appendChild(ovl);
    }else{
        document.getElementsByTagName('html')[0].appendChild('Missing body' + ovl + '</html');
    };
};

var loadPDPinit = setTimeout(function loadPDP() { PDP.init()}, 500);
//var autoSave = setInterval(function savePDP() { PDP.update()}, 500);

<commit_msg>loadContextMenu and setZindex functions<commit_after>if (!window.jQuery) {
  var jq = document.createElement('script'); jq.type = 'text/javascript';
  // Path to jquery.js file, eg. Google hosted version
  jq.src = "//ajax.aspnetcdn.com/ajax/jQuery/jquery-2.1.0.min.js",
  //jq.src = 'js/jquery.min.js'; // local loading
  document.getElementsByTagName('head')[0].appendChild(jq);
}

var PDP = {}; // stop it being loaded twice (until we want that.)
PDP.config = { version: "0.03", overlay: {}, menu: {} },
// check the local store for css and config
PDP.loadUserSettings = function(){
 // check local storage (recursively, the local settings may indicate that the settings are in another castle)
    console.log('looking for settings');
},
PDP.loadUserData = function(){
// check local storage for data
    console.log('checking local storage for user data');
},
PDP.loadContextMenu = function(){
    // slurp in the template from t/default_context_menu.html
    console.log('creating ContextMenu');
    var cm = document.createElement('menu');
    cm.setAttribute("type", 'context');
    cm.setAttribute("id", 'PDP_overlay_CM');
  //document.getElementById('PDP_overlay').appendChild(cm);
  // can't do that becase we may not have created the DIV yet
    document.getElementsByTagName('head')[0].appendChild(cm);
    $('#PDP_overlay_CM').load('t/default_context_menu.html');
    console.log('loading ContextMenu');
},
PDP.setZindex = function(){
   var c = this.config;
   var maxZ = 1;
   $.map($('body > *'), function(e,n){
        if($(e).css('position')=='absolute'){
            if($(e).css('z-index')>maxZ){
                maxZ = parseInt($(e).css('z-index'))|| maxZ++ ;
            }
           }
    });
   c.overlay.Zindex = maxZ + 1;
   $('#PDP_overlay').length ? $('#PDP_overlay').css('z-index',c.overlay.Zindex) : PDP.log('z-index: ' + c.overlay.Zindex);
},
PDP.log = function (m, t) {
// alert the user of something
 console.log(t +": " + m);
},
PDP.say = function (m, t) {
// alert the user of something
alert(t +": " + m);
},
PDP.menu = function(){
// parent for the menu functions
},
PDP.menu.tab = function(){
// create the menu tab
},
PDP.menu.append = function(){
// if the settings don't explicity block it, then add a menu icon to the overlay
// so that the user can access the config menu
},
PDP.init = function () {
  var c = this.config;
  this.loadUserSettings(),
  this.loadUserData();
  //"undefined" == typeof this.config.overlay.noShow ?  this.loadOverlay() : console.log("overlay hidden by config") ;
  this.config.overlay.noShow != 1 ? this.loadOverlay() :  console.log("overlay hidden by config") ;
  this.config.menu.noShow != 1 ? this.menu.append(this.menu.tab) : console.log("menu hidden by config") ;
  this.loadContextMenu();
  this.setZindex();
  var autoSave = setInterval(function savePDP() { PDP.update()}, 500);
},
PDP.update = function() {
// save data and send changes
    //this.log('Saving data', 'info');
}
PDP.loadOverlay = function(){
    console.log("loading overlay");

    var ovl = document.createElement('div');
    ovl.setAttribute("contentEditable", true);
    ovl.setAttribute("id", 'PDP_overlay');
    ovl.setAttribute("class", 'PDP_overlay');
    ovl.setAttribute("contextmenu", 'PDP_overlay_CM');
    ovl.innerHTML = 'Welcome to Your Personal Data: Feel free to add something here';
    var body_elm = {};
    if( body_elm = document.getElementsByTagName('body')[0]){
        body_elm.appendChild(ovl);
    }else{
        document.getElementsByTagName('html')[0].appendChild('Missing body' + ovl + '</html');
    };
};

var loadPDPinit = setTimeout(function loadPDP() { PDP.init()}, 500);
//var autoSave = setInterval(function savePDP() { PDP.update()}, 500);

<|endoftext|>


<commit_before>'use strict';

// Include Gulp and other build automation tools and utilities
// See: https://github.com/gulpjs/gulp/blob/master/docs/API.md
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var del = require('del');
var path = require('path');
var runSequence = require('run-sequence');
var webpack = require('webpack');
var argv = require('minimist')(process.argv.slice(2));

// Settings
var RELEASE = !!argv.release;                 // Minimize and optimize during a build?
var AUTOPREFIXER_BROWSERS = [                 // https://github.com/ai/autoprefixer
  'ie >= 10',
  'ie_mob >= 10',
  'ff >= 30',
  'chrome >= 34',
  'safari >= 7',
  'opera >= 23',
  'ios >= 7',
  'android >= 4.4',
  'bb >= 10'
];

var src = {};
var watch = false;
var browserSync;

// The default task
gulp.task('default', ['sync']);

// Clean output directory
gulp.task('clean', del.bind(
  null, ['.tmp', 'build/*', '!build/.git'], {dot: true}
));

// 3rd party libraries
gulp.task('vendor', function() {
  return gulp.src('node_modules/bootstrap/dist/fonts/**')
    .pipe(gulp.dest('build/fonts'));
});

// Fonts
gulp.task('fonts', function() {
  return gulp.src('src/client/fonts/**')
    .pipe(gulp.dest('build/fonts'));
});

// Static files
gulp.task('assets', function() {
  src.assets = [
    'src/client/assets/**',
    'src/client/templates*/**/*.*'
  ];
  return gulp.src(src.assets)
    .pipe($.changed('build'))
    .pipe(gulp.dest('build'))
    .pipe($.size({title: 'assets'}));
});

// CSS style sheets
gulp.task('styles', function() {
  src.styles = 'src/client/styles/**/*.{css,less}';
  return gulp.src('src/client/styles/bootstrap.less')
    .pipe($.plumber())
    .pipe($.less({
      sourceMap: !RELEASE,
      sourceMapBasepath: __dirname
    }))
    .on('error', console.error.bind(console))
    .pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS}))
    .pipe($.csscomb())
    .pipe($.if(RELEASE, $.minifyCss()))
    .pipe(gulp.dest('build/css'))
    .pipe($.size({title: 'styles'}));
});

// Bundle
gulp.task('bundle', function(cb) {
  var started = false;
  var config = require('./webpack.config.js');
  var bundler = webpack(config);

  function bundle(err, stats) {
    if (err) {
      throw new $.util.PluginError('webpack', err);
    }

    if (argv.verbose) {
      $.util.log('[webpack]', stats.toString({colors: true}));
    }

    if (!started) {
      started = true;
      return cb();
    }
  }

  if (watch) {
    bundler.watch(200, bundle);
  } else {
    bundler.run(bundle);
  }
});

// Build the app from source code
gulp.task('build', ['clean'], function(cb) {
  runSequence(['vendor', 'fonts', 'assets', 'styles', 'bundle'], cb);
});

// Build and start watching for modifications
gulp.task('build:watch', function(cb) {
  watch = true;
  runSequence('build', function() {
    gulp.watch(src.assets, ['assets']);
    gulp.watch(src.styles, ['styles']);
    cb();
  });
});

// Launch a Node.js/Express server
gulp.task('serve', ['build:watch'], function(cb) {
  src.server = [
    'build/server.js',
    'build/templates/**/*'
  ];

  var started = false;
  var cp = require('child_process');
  var assign = require('react/lib/Object.assign');

  var server = (function startup() {
    var child = cp.fork('build/server.js', {
      env: assign({NODE_ENV: 'development'}, process.env)
    });
    child.once('message', function(message) {
      if (message.match(/^online$/)) {
        if (browserSync) {
          browserSync.reload();
        }
        if (!started) {
          started = true;
          gulp.watch(src.server, function() {
            $.util.log('Restarting development server.');
            server.kill('SIGTERM');
            server = startup();
          });
          cb();
        }
      }
    });
    return child;
  })();

  process.on('exit', function() {
    server.kill('SIGTERM');
  });
});

// Launch BrowserSync development server
gulp.task('sync', ['serve'], function(cb) {
  browserSync = require('browser-sync');

  browserSync({
    notify: false,
    // Run as an https by setting 'https: true'
    // Note: this uses an unsigned certificate which on first access
    //       will present a certificate warning in the browser.
    https: false,
    // Informs browser-sync to proxy our Express app which would run
    // at the following location
    proxy: 'localhost:5000'
  }, cb);

  process.on('exit', function() {
    browserSync.exit();
  });

  gulp.watch(['build/**/*.*'].concat(
    src.server.map(function(file) {return '!' + file;})
  ), function(file) {
    browserSync.reload(path.relative(__dirname, file.path));
  });
});

// Deploy to GitHub Pages
gulp.task('deploy', function() {

  // Remove temp folder
  if (argv.clean) {
    var os = require('os');
    var repoPath = path.join(os.tmpdir(), 'tmpRepo');
    $.util.log('Delete ' + $.util.colors.magenta(repoPath));
    del.sync(repoPath, {force: true});
  }

  return gulp.src('build/**/*')
    .pipe($.if('**/robots.txt', !argv.production ?
      $.replace('Disallow:', 'Disallow: /') : $.util.noop()))
    .pipe($.ghPages({
      remoteUrl: 'https://github.com/{name}/{name}.github.io.git',
      branch: 'master'
    }));
});

// Run PageSpeed Insights
gulp.task('pagespeed', function(cb) {
  var pagespeed = require('psi');
  // Update the below URL to the public URL of your site
  pagespeed.output('example.com', {
    strategy: 'mobile'
    // By default we use the PageSpeed Insights free (no API key) tier.
    // Use a Google Developer API key if you have one: http://goo.gl/RkN0vE
    // key: 'YOUR_API_KEY'
  }, cb);
});
<commit_msg>Adding gulp shell task for running mocha with es6<commit_after>'use strict';

// Include Gulp and other build automation tools and utilities
// See: https://github.com/gulpjs/gulp/blob/master/docs/API.md
var gulp = require('gulp');
var shell = require('gulp-shell');
var $ = require('gulp-load-plugins')();
var del = require('del');
var path = require('path');
var runSequence = require('run-sequence');
var webpack = require('webpack');
var argv = require('minimist')(process.argv.slice(2));

// Settings
var RELEASE = !!argv.release;                 // Minimize and optimize during a build?
var AUTOPREFIXER_BROWSERS = [                 // https://github.com/ai/autoprefixer
  'ie >= 10',
  'ie_mob >= 10',
  'ff >= 30',
  'chrome >= 34',
  'safari >= 7',
  'opera >= 23',
  'ios >= 7',
  'android >= 4.4',
  'bb >= 10'
];

var src = {};
var watch = false;
var browserSync;

// The default task
gulp.task('default', ['sync']);

// Clean output directory
gulp.task('clean', del.bind(
  null, ['.tmp', 'build/*', '!build/.git'], {dot: true}
));

// 3rd party libraries
gulp.task('vendor', function() {
  return gulp.src('node_modules/bootstrap/dist/fonts/**')
    .pipe(gulp.dest('build/fonts'));
});

// Fonts
gulp.task('fonts', function() {
  return gulp.src('src/client/fonts/**')
    .pipe(gulp.dest('build/fonts'));
});

// Static files
gulp.task('assets', function() {
  src.assets = [
    'src/client/assets/**',
    'src/client/templates*/**/*.*'
  ];
  return gulp.src(src.assets)
    .pipe($.changed('build'))
    .pipe(gulp.dest('build'))
    .pipe($.size({title: 'assets'}));
});

// CSS style sheets
gulp.task('styles', function() {
  src.styles = 'src/client/styles/**/*.{css,less}';
  return gulp.src('src/client/styles/bootstrap.less')
    .pipe($.plumber())
    .pipe($.less({
      sourceMap: !RELEASE,
      sourceMapBasepath: __dirname
    }))
    .on('error', console.error.bind(console))
    .pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS}))
    .pipe($.csscomb())
    .pipe($.if(RELEASE, $.minifyCss()))
    .pipe(gulp.dest('build/css'))
    .pipe($.size({title: 'styles'}));
});

// Bundle
gulp.task('bundle', function(cb) {
  var started = false;
  var config = require('./webpack.config.js');
  var bundler = webpack(config);

  function bundle(err, stats) {
    if (err) {
      throw new $.util.PluginError('webpack', err);
    }

    if (argv.verbose) {
      $.util.log('[webpack]', stats.toString({colors: true}));
    }

    if (!started) {
      started = true;
      return cb();
    }
  }

  if (watch) {
    bundler.watch(200, bundle);
  } else {
    bundler.run(bundle);
  }
});

// Build the app from source code
gulp.task('build', ['clean'], function(cb) {
  runSequence(['vendor', 'fonts', 'assets', 'styles', 'bundle'], cb);
});

// Build and start watching for modifications
gulp.task('build:watch', function(cb) {
  watch = true;
  runSequence('build', function() {
    gulp.watch(src.assets, ['assets']);
    gulp.watch(src.styles, ['styles']);
    cb();
  });
});

// Launch a Node.js/Express server
gulp.task('serve', ['build:watch'], function(cb) {
  src.server = [
    'build/server.js',
    'build/templates/**/*'
  ];

  var started = false;
  var cp = require('child_process');
  var assign = require('react/lib/Object.assign');

  var server = (function startup() {
    var child = cp.fork('build/server.js', {
      env: assign({NODE_ENV: 'development'}, process.env)
    });
    child.once('message', function(message) {
      if (message.match(/^online$/)) {
        if (browserSync) {
          browserSync.reload();
        }
        if (!started) {
          started = true;
          gulp.watch(src.server, function() {
            $.util.log('Restarting development server.');
            server.kill('SIGTERM');
            server = startup();
          });
          cb();
        }
      }
    });
    return child;
  })();

  process.on('exit', function() {
    server.kill('SIGTERM');
  });
});

// Launch BrowserSync development server
gulp.task('sync', ['serve'], function(cb) {
  browserSync = require('browser-sync');

  browserSync({
    notify: false,
    // Run as an https by setting 'https: true'
    // Note: this uses an unsigned certificate which on first access
    //       will present a certificate warning in the browser.
    https: false,
    // Informs browser-sync to proxy our Express app which would run
    // at the following location
    proxy: 'localhost:5000'
  }, cb);

  process.on('exit', function() {
    browserSync.exit();
  });

  gulp.watch(['build/**/*.*'].concat(
    src.server.map(function(file) {return '!' + file;})
  ), function(file) {
    browserSync.reload(path.relative(__dirname, file.path));
  });
});

// Deploy to GitHub Pages
gulp.task('deploy', function() {

  // Remove temp folder
  if (argv.clean) {
    var os = require('os');
    var repoPath = path.join(os.tmpdir(), 'tmpRepo');
    $.util.log('Delete ' + $.util.colors.magenta(repoPath));
    del.sync(repoPath, {force: true});
  }

  return gulp.src('build/**/*')
    .pipe($.if('**/robots.txt', !argv.production ?
      $.replace('Disallow:', 'Disallow: /') : $.util.noop()))
    .pipe($.ghPages({
      remoteUrl: 'https://github.com/{name}/{name}.github.io.git',
      branch: 'master'
    }));
});

// Run PageSpeed Insights
gulp.task('pagespeed', function(cb) {
  var pagespeed = require('psi');
  // Update the below URL to the public URL of your site
  pagespeed.output('example.com', {
    strategy: 'mobile'
    // By default we use the PageSpeed Insights free (no API key) tier.
    // Use a Google Developer API key if you have one: http://goo.gl/RkN0vE
    // key: 'YOUR_API_KEY'
  }, cb);
});

gulp.task('test', shell.task([
  'mocha --recursive --compilers js:mocha-traceur'
]));
<|endoftext|>


<commit_before>var qs = require('querystring');
var prompt = require('prompt');
var request = require('request');
var irc = require("irc");
var util = require("util");
var fs = require("fs");

var API = require('./api.json');
var OAUTH = require('./oauth.json');

// enable this to keep it out of the main channel
var TESTING = 1;

var channel = (TESTING) ? "#doubleaw" : "#reddit-hockey";

var config = {
  channels: [channel],
  server: "irc.freenode.net",
  botName: (TESTING) ? "rfstats2" : "rfstats"
};

var initOAuth = function() {
  var oauth = {
    callback: 'oob',
    consumer_key: API.key,
    consumer_secret: API.secret
  };
  var url = 'https://api.login.yahoo.com/oauth/v2/get_request_token';
  request.post({url:url, oauth:oauth}, function (e, r, body) {
    // Ideally, you would take the body in the response
    // and construct a URL that a user clicks on (like a sign in button).
    // The verifier is only available in the response after a user has
    // verified with twitter that they are authorizing your app.
    var access_token = qs.parse(body);
    var oauth = {
      consumer_key: API.key,
      consumer_secret: API.secret,
      token: access_token.oauth_token,
      token_secret: access_token.oauth_token_secret
    };
    this.log("Visit " + access_token.xoauth_request_auth_url);
    prompt.start();
    prompt.get(['verifier'], function(err, res) {
      oauth.verifier = res.verifier;
      request.post({url: 'https://api.login.yahoo.com/oauth/v2/get_token', oauth:oauth}, function (e, r, body) {
        var perm_token = qs.parse(body);
        this.log(perm_token);
        OAUTH = {
          consumer_key: API.key,
          consumer_secret: API.secret,
          token: perm_token.oauth_token,
          token_secret: perm_token.oauth_token_secret,
          session_handle: perm_token.oauth_session_handle
        };
        this.log("Authenticated.");
        fs.writeFileSync('./oauth.json', JSON.stringify(OAUTH));
      });
    });
  });
};

function Bot() {
  this.nickHash = {
    '321.l.99282.t.1': ['dan408', 'dan', 'dan408_', 'dan408__'],
    '321.l.99282.t.2': ['doubleaw', 'awaw'],
    '321.l.99282.t.3': ['leafer91'],
    '321.l.99282.t.4': ['thero'],
    '321.l.99282.t.5': ['amaninacan'],
    '321.l.99282.t.6': ['thatoneroadie']
  };
  this.help = require('./help.json');

  this.teamData = null;
  this.statIds = null;
  this.commands = require('./commands').bind(this)(this.get.bind(this), channel);
  this.log(Object.keys(this.commands).length + " commands loaded.");
}

Bot.prototype.log = function() {
  var args = Array.prototype.slice.call(arguments);
  console.log.apply(null, args);
  var now = new Date();
  var y = now.getFullYear(),
      m = now.getMonth() + 1,
      d = now.getDate(),
      h = now.getHours(),
      m = now.getMinutes(),
      s = now.getSeconds(),
      timestamp = "[" + m + "/" + d + "/" + y + " " + h + ":" + m + ":" + s + "] ";
  args = args.map(function(a){
    return timestamp + a;
  });
  fs.appendFile('./bot.log', Array.prototype.join.call(args, "\n") + "\n");
}

Bot.prototype.get = function(url, cb, cmdData, nickname) {
  cb = cb.bind(this);
  request.get({ url: 'http://fantasysports.yahooapis.com/fantasy/v2/' + url + '?format=json', oauth: OAUTH, json: true }, function(e, r, body) {
    if(body.error) {
      this.log(body.error);
      this.log("Token expired. Reauthenticating...");
      request.post({url: 'https://api.login.yahoo.com/oauth/v2/get_token', oauth: OAUTH}, function (e, r, body) {
        var perm_token = qs.parse(body);
        OAUTH = {
          consumer_key: API.key,
          consumer_secret: API.secret,
          token: perm_token.oauth_token,
          token_secret: perm_token.oauth_token_secret,
          session_handle: perm_token.oauth_session_handle
        };
        fs.writeFileSync('./oauth.json', JSON.stringify(OAUTH));
        this.get(url, cb, cmdData, nickname);
      }.bind(this));
    } else {
      cb.bind(this)(body.fantasy_content, cmdData, nickname || "?");
    }
  }.bind(this));
};

Bot.prototype.init = function() {
  this.log('Connecting to IRC...');
  this.client = new irc.Client(config.server, config.botName, {
    channels: config.channels
  });
  this.client.addListener('registered', this.onConnect.bind(this));
  this.client.addListener('names', this.onJoin.bind(this));
  this.client.addListener('message' + channel, this.onMessage.bind(this));
  this.client.addListener('error', function(message) {
    this.log("IRC Error: " + message);
  }.bind(this));
};

Bot.prototype.getTeam = function(data) {
  var specNick = (data.length === 0) ? '' : data[0].toLowerCase();
  return Object.keys(this.teamData).map(function(k){
    // unzip into [key, value] pairs
    return [k, this.teamData[k]];
  }, this).filter(function(i){
    // filter to find the one that either matches the full team name
    // or matches the nickname
    return i[1].name === data.join(" ") || i[1].owner.indexOf(specNick) > -1
  })[0];
};

Bot.prototype.onConnect = function(message) {
  this.log('Bot connected.');
  this.log('Getting team data...');
  this.get('league/nhl.l.99282/teams', function(data) {
    var team;
    this.teamData = {};
    for(var i = 0; i < data.league[1].teams.count; i++) {
      team = data.league[1].teams[i].team[0];
      this.teamData[team[0].team_key] = {
        name: team[2].name,
        owner: this.nickHash[team[0].team_key]
      };
    }
    this.log("Team data loaded.");
  });
  this.log("Loading league settings...");
  this.get('league/nhl.l.99282/settings', function(data) {
    var settings = data.league[1].settings[0];
    this.statIds = {};
    settings.stat_categories.stats.forEach(function(data) {
      var stat = data.stat;
      this.statIds[stat.stat_id] = stat;
    }, this);
    this.log("League settings loaded.");
  });
};

Bot.prototype.onJoin = function(channel, names) {
  this.log("Joined " + channel);
};

Bot.prototype.onMessage = function(nick, text, message) {
  if(!OAUTH) {
    return;
  }
  var msg = message.args[1].split(" ");
  if(!msg[0].match(/^\!f/)) {
    return;
  }
  var cmd = msg[0].replace(/^\!f/,'').toLowerCase();
  if(this.commands.hasOwnProperty(cmd)) {
    var c = this.commands[cmd];
    // check if alias
    if(typeof c === typeof "") {
      c = this.commands[c];
    }
    try {
      if(c.url) {
        this.get(c.url, c.fn.bind(this), msg.slice(1), message.nick);
      } else {
        c.fn.bind(this)(msg.slice(1), message.nick);
      }
    } catch(e) {
      this.log("Calling command '" + cmd + "' resulted in the following error: " + e.message);
    }
    if(message.nick === "ruhan" && Math.random() < 0.8) {
      this.client.say(channel, "And no, you can't have the Blackhawks' fourth line.");
    }
  } else {
    this.log(message.nick + " tried to use unrecognized command '" + cmd + "'.");
  }
};

Bot.prototype.reload = function() {
  delete require.cache[Object.keys(require.cache).filter(function(m){return m.match(/commands\.js/)})[0]];
  this.commands = require('./commands.js').bind(this)(this.get.bind(this), channel);
  this.log(Object.keys(this.commands).length + " commands loaded.");
  fs.readFile('./help.json', function(err, data) {
    if(err) {
      console.log('Error reading help data.');
    } else {
      this.help = JSON.parse(data);
      this.log("Help loaded.");
    }
  }.bind(this));
};

var b = new Bot();
b.init();
<commit_msg>Remove testing, lower ruhan threshold<commit_after>var qs = require('querystring');
var prompt = require('prompt');
var request = require('request');
var irc = require("irc");
var util = require("util");
var fs = require("fs");

var API = require('./api.json');
var OAUTH = require('./oauth.json');

// enable this to keep it out of the main channel
var TESTING = 0;

var channel = (TESTING) ? "#doubleaw" : "#reddit-hockey";

var config = {
  channels: [channel],
  server: "irc.freenode.net",
  botName: (TESTING) ? "rfstats2" : "rfstats"
};

var initOAuth = function() {
  var oauth = {
    callback: 'oob',
    consumer_key: API.key,
    consumer_secret: API.secret
  };
  var url = 'https://api.login.yahoo.com/oauth/v2/get_request_token';
  request.post({url:url, oauth:oauth}, function (e, r, body) {
    // Ideally, you would take the body in the response
    // and construct a URL that a user clicks on (like a sign in button).
    // The verifier is only available in the response after a user has
    // verified with twitter that they are authorizing your app.
    var access_token = qs.parse(body);
    var oauth = {
      consumer_key: API.key,
      consumer_secret: API.secret,
      token: access_token.oauth_token,
      token_secret: access_token.oauth_token_secret
    };
    this.log("Visit " + access_token.xoauth_request_auth_url);
    prompt.start();
    prompt.get(['verifier'], function(err, res) {
      oauth.verifier = res.verifier;
      request.post({url: 'https://api.login.yahoo.com/oauth/v2/get_token', oauth:oauth}, function (e, r, body) {
        var perm_token = qs.parse(body);
        this.log(perm_token);
        OAUTH = {
          consumer_key: API.key,
          consumer_secret: API.secret,
          token: perm_token.oauth_token,
          token_secret: perm_token.oauth_token_secret,
          session_handle: perm_token.oauth_session_handle
        };
        this.log("Authenticated.");
        fs.writeFileSync('./oauth.json', JSON.stringify(OAUTH));
      });
    });
  });
};

function Bot() {
  this.nickHash = {
    '321.l.99282.t.1': ['dan408', 'dan', 'dan408_', 'dan408__'],
    '321.l.99282.t.2': ['doubleaw', 'awaw'],
    '321.l.99282.t.3': ['leafer91'],
    '321.l.99282.t.4': ['thero'],
    '321.l.99282.t.5': ['amaninacan'],
    '321.l.99282.t.6': ['thatoneroadie']
  };
  this.help = require('./help.json');

  this.teamData = null;
  this.statIds = null;
  this.commands = require('./commands').bind(this)(this.get.bind(this), channel);
  this.log(Object.keys(this.commands).length + " commands loaded.");
}

Bot.prototype.log = function() {
  var args = Array.prototype.slice.call(arguments);
  console.log.apply(null, args);
  var now = new Date();
  var y = now.getFullYear(),
      m = now.getMonth() + 1,
      d = now.getDate(),
      h = now.getHours(),
      m = now.getMinutes(),
      s = now.getSeconds(),
      timestamp = "[" + m + "/" + d + "/" + y + " " + h + ":" + m + ":" + s + "] ";
  args = args.map(function(a){
    return timestamp + a;
  });
  fs.appendFile('./bot.log', Array.prototype.join.call(args, "\n") + "\n");
}

Bot.prototype.get = function(url, cb, cmdData, nickname) {
  cb = cb.bind(this);
  request.get({ url: 'http://fantasysports.yahooapis.com/fantasy/v2/' + url + '?format=json', oauth: OAUTH, json: true }, function(e, r, body) {
    if(body.error) {
      this.log(body.error);
      this.log("Token expired. Reauthenticating...");
      request.post({url: 'https://api.login.yahoo.com/oauth/v2/get_token', oauth: OAUTH}, function (e, r, body) {
        var perm_token = qs.parse(body);
        OAUTH = {
          consumer_key: API.key,
          consumer_secret: API.secret,
          token: perm_token.oauth_token,
          token_secret: perm_token.oauth_token_secret,
          session_handle: perm_token.oauth_session_handle
        };
        fs.writeFileSync('./oauth.json', JSON.stringify(OAUTH));
        this.get(url, cb, cmdData, nickname);
      }.bind(this));
    } else {
      cb.bind(this)(body.fantasy_content, cmdData, nickname || "?");
    }
  }.bind(this));
};

Bot.prototype.init = function() {
  this.log('Connecting to IRC...');
  this.client = new irc.Client(config.server, config.botName, {
    channels: config.channels
  });
  this.client.addListener('registered', this.onConnect.bind(this));
  this.client.addListener('names', this.onJoin.bind(this));
  this.client.addListener('message' + channel, this.onMessage.bind(this));
  this.client.addListener('error', function(message) {
    this.log("IRC Error: " + message);
  }.bind(this));
};

Bot.prototype.getTeam = function(data) {
  var specNick = (data.length === 0) ? '' : data[0].toLowerCase();
  return Object.keys(this.teamData).map(function(k){
    // unzip into [key, value] pairs
    return [k, this.teamData[k]];
  }, this).filter(function(i){
    // filter to find the one that either matches the full team name
    // or matches the nickname
    return i[1].name === data.join(" ") || i[1].owner.indexOf(specNick) > -1
  })[0];
};

Bot.prototype.onConnect = function(message) {
  this.log('Bot connected.');
  this.log('Getting team data...');
  this.get('league/nhl.l.99282/teams', function(data) {
    var team;
    this.teamData = {};
    for(var i = 0; i < data.league[1].teams.count; i++) {
      team = data.league[1].teams[i].team[0];
      this.teamData[team[0].team_key] = {
        name: team[2].name,
        owner: this.nickHash[team[0].team_key]
      };
    }
    this.log("Team data loaded.");
  });
  this.log("Loading league settings...");
  this.get('league/nhl.l.99282/settings', function(data) {
    var settings = data.league[1].settings[0];
    this.statIds = {};
    settings.stat_categories.stats.forEach(function(data) {
      var stat = data.stat;
      this.statIds[stat.stat_id] = stat;
    }, this);
    this.log("League settings loaded.");
  });
};

Bot.prototype.onJoin = function(channel, names) {
  this.log("Joined " + channel);
};

Bot.prototype.onMessage = function(nick, text, message) {
  if(!OAUTH) {
    return;
  }
  var msg = message.args[1].split(" ");
  if(!msg[0].match(/^\!f/)) {
    return;
  }
  var cmd = msg[0].replace(/^\!f/,'').toLowerCase();
  if(this.commands.hasOwnProperty(cmd)) {
    var c = this.commands[cmd];
    // check if alias
    if(typeof c === typeof "") {
      c = this.commands[c];
    }
    try {
      if(c.url) {
        this.get(c.url, c.fn.bind(this), msg.slice(1), message.nick);
      } else {
        c.fn.bind(this)(msg.slice(1), message.nick);
      }
    } catch(e) {
      this.log("Calling command '" + cmd + "' resulted in the following error: " + e.message);
    }
    if(message.nick === "ruhan" && Math.random() < 0.3) {
      this.client.say(channel, "And no, you can't have the Blackhawks' fourth line.");
    }
  } else {
    this.log(message.nick + " tried to use unrecognized command '" + cmd + "'.");
  }
};

Bot.prototype.reload = function() {
  delete require.cache[Object.keys(require.cache).filter(function(m){return m.match(/commands\.js/)})[0]];
  this.commands = require('./commands.js').bind(this)(this.get.bind(this), channel);
  this.log(Object.keys(this.commands).length + " commands loaded.");
  fs.readFile('./help.json', function(err, data) {
    if(err) {
      console.log('Error reading help data.');
    } else {
      this.help = JSON.parse(data);
      this.log("Help loaded.");
    }
  }.bind(this));
};

var b = new Bot();
b.init();
<|endoftext|>