<commit_before>var fs = require("fs");
var config = require('./../config.json');
var backendConfig = require('./../Backends/backends.json');
var formatConfig = require('./../Formats/formats.json');
var packageConfig = require('./../package.json');

var spawn = require('child_process').spawn;

var processes = []; // for storing sessions

var getProcess = function(key)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == key)
        {
            return processes[i];
        }
    }

    return null;
};

var timeoutProcessSetPing = function (process)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == process.windowKey)
        {
            processes[i].pingTimeoutObject = setTimeout(pingTimeoutFunc, config.pingTimeout, processes[i]);
            return;
        }
    }
};

var timeoutProcessClearPing = function (process)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == process.windowKey)
        {
            clearTimeout(processes[i].pingTimeoutObject);
            return;
        }
    }
};

var timeoutProcessSetInactivity = function(process)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == process.windowKey)
        {
            processes[i].inactivityTimeoutObject = setTimeout(inactivityTimeoutFunc, config.inactivityTimeout, processes[i]);
            return;
        }
    }
};

var timeoutProcessClearInactivity = function (process)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == process.windowKey)
        {
            clearTimeout(processes[i].inactivityTimeoutObject);
            return;
        }
    }
};

var getBackend = function (backendId)
{
    for (var j = 0; j < backendConfig.backends.length; j++)
    {
        if (backendConfig.backends[j].id == backendId)
        {
            return backendConfig.backends[j];
        }
    }
    return null;
};

var getFormat = function (formatId)
{
    for (var j = 0; j < formatConfig.formats.length; j++)
    {
        if (formatConfig.formats[j].id == formatId)
        {
            return formatConfig.formats[j];
        }
    }

    return null;
};

processRemoveOlder = function (key)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == key)
        {
            processes[i].toKill = true;
            timeoutProcessClearPing(processes[i]);
            processes[i].toRemoveCompletely = true;
            processes[i].windowKey = "none";
            break;
        }
    }
};

var addProcess = function (process)
{
    processRemoveOlder(process.windowKey);
    processes.push(process);
};

var pingTimeoutFunc = function (process)
{
    logSpecific("Error: Ping Timeout", process.windowKey);
    process.result = '{"message": "' + escapeJSON('Error: Ping Timeout. Please consider increasing timeout values in the "config.json" file. Currently it equals ' + config.pingTimeout + ' millisecond(s).') + '"}';
    process.toKill = true;
    process.toRemoveCompletely = true;
    cleanProcesses();
};

var inactivityTimeoutFunc = function (process)
{
    logSpecific("Error: Inactivity Timeout", process.windowKey);
    process.result = '{"message": "' + escapeJSON('Error: Inactivity Timeout. Please consider increasing timeout values in the "config.json" file. Currently it equals ' + config.inactivityTimeout + ' millisecond(s).') + '"}';
    process.toKill = true;
    process.toRemoveCompletely = true;
    cleanProcesses();
};

var cleanProcesses = function ()
{
    var i = 0;
    while (i < processes.length)
    {
        if (processes[i].toKill)
        {
            killProcessTree(processes[i]);
            processes[i].toKill = false;
        }

        if (processes[i].toRemoveCompletely)
        {
            clearTimeout(processes[i].pingTimeoutObject);
            clearTimeout(processes[i].inactivityTimeoutObject);
            setTimeout(cleanupOldFiles, config.cleaningTimeout, processes[i].folder);
            processes.splice(i, 1);
        }
        else
            i++;
    }

    logSpecific("Cleaning complete. #Processes = " + processes.length, null);
};

var killProcessTree = function(process)
{
    process.killed = true;
    killProcessIfExists(process.tool);
    process.tool = null;
    killProcessIfExists(process.clafer_compiler);
    process.clafer_compiler = null;
    logSpecific("Killing the process tree...", process.windowKey);
};

var dependencies = [];
var dependencyCount = 0;

var addDependency = function(path, args, title)
{
    dependencies.push({path : path, args : args, title : title});
};

function checkDependency(dependency, callback)
{
    var tool  = spawn(dependency.path, dependency.args);
    var tool_version = "";

    tool.on('error', function (err){
        logNormal('ERROR: Cannot find "' + dependency.title + '". Please check whether it is installed and accessible.');
    });

    tool.stdout.on('data', function (data){
        tool_version += data;
    });

    tool.stderr.on('data', function (data){
        tool_version += data;
    });

    tool.on('exit', function (code){
        logNormal(tool_version.trim());
        if (code == 0) dependency_ok(callback);
    });
}

var runWithDependencyCheck = function(callback)
{
    var node_version = process.version + ", " + JSON.stringify(process.versions);
    logNormal("Node.JS: " + node_version);
    dependencyCount = dependencies.length;

    for (var i = 0; i < dependencies.length; i++)
    {
        checkDependency(dependencies[i], callback);
    }
};

var dependency_ok = function(callback)
{
    dependencyCount--;
    if (dependencyCount == 0)
    {
        logNormal('Dependencies found successfully. Please review their versions manually');
        callback();
    }
};

var killProcessIfExists = function(tool)
{
    if (tool)
    {
        var pid = tool.pid;
        tool.removeAllListeners();
        logNormal("Killing the process with Parent PID = " + pid);

        // first, try a Windows command
        var killer_win  = spawn("taskkill", ["/F", "/T", "/PID", pid]);

        killer_win.on('error', function (err){  // if error occurs, then we are on Linux
            var killer_linux = spawn("pkill", ["-TERM", "-P", pid]);

            killer_linux.on('error', function(err){
                logNormal("Cannot terminate the process.");
            });
        });
    }
};

var logSpecific = function(message, key)
    {
        var date = new Date();
        var d = date.toUTCString();

        if (key != null)
        {
            console.log(d + " | " + key + " | " + message);
        }
        else
            console.log(d + " | " + "GLOBAL" + " | " + message);
    };

var logNormal = function(message)
    {
        console.log(message);
    };

var cleanupOldFiles = function (dir) {
        logNormal("Cleaning temporary files...");
        //cleanup old files
        fs.readdir(dir, function(err, files){
            //if (err) throw err;
            if (err)
            {
                logSpecific("Could not clear the folder: " + dir, null);
                return; // cannot get the folder
            }
            var results = "";
            var numFiles = files.length;
            logSpecific("#Files = " + numFiles, null);
            if (!numFiles){
                return finishCleanup(dir, results);
            } else {
                files.forEach(function(file){
                    deleteOld(dir + "/" + file);
                    results += file + "\n";
                });
                finishCleanup(dir, results);
            }
        });
    };

var deleteOld = function (path)
    {
        fs.exists(path, function(exists)
        {
            if (exists)
            {
                fs.unlink(path, function (err)
                {
                    if (err)
                    {
                        logNormal("Could not delete the file: " + path);
                        logNormal(err);
                    }
                });
            }
        });
    }

var finishCleanup = function (dir, results)
    {
        fs.exists(dir, function(exists)
        {
            if (exists)
            {
                fs.rmdir(dir, function (err) {
                    if (err)
                    {
                        logNormal("Could not finish the cleanup: " + dir);
                        return;
                    }
                    logNormal("Successfully deleted " + dir + " along with contents:\n" + results);
                });
            }
        });
    };

var escapeJSON = function (unsafe)
    {
        return unsafe.replace(/[\\]/g, '\\\\')
            .replace(/[\"]/g, '\\\"')
            .replace(/[\/]/g, '\\/')
            .replace(/[\b]/g, '\\b')
            .replace(/[\f]/g, '\\f')
            .replace(/[\n]/g, '\\n')
            .replace(/[\r]/g, '\\r')
            .replace(/[\t]/g, '\\t');
    };

var replaceTemplate = function (input_string, replacement_map)
    {
        var result = input_string;

        for (var j = 0; j < replacement_map.length; j++)
        {
            result = result.replace(replacement_map[j].needle, replacement_map[j].replacement);
        }

        return result;
    };

var replaceTemplateList = function(input_list, replacement_map)
    {
        var result = new Array();
        for (var i = 0; i < input_list.length; i++)
        {
            result.push(replaceTemplate(input_list[i], replacement_map));
        }

        return result;
    };

    // filter input command line arguments for safety purposes
var filterArgs = function (argString)
    {
        var args = argString.split(" ");
        var resultArgs = new Array();
        for (var i = 0; i < args.length; i++)
        {
            var arg = args[i].trim();

            if (arg.length == 0)
                continue;

            if (!arg.match(/-[A-Za-z-]+/))
                continue;

            resultArgs.push(arg);
        }

        return resultArgs;
    };

var getVersion = function()
    {
        return "v" + packageConfig.version + "." + packageConfig.release_date;
    };

var getTitle = function()
    {
        return packageConfig.name;
    };

module.exports.addProcess = addProcess;
module.exports.getProcess = getProcess;
module.exports.timeoutProcessSetPing = timeoutProcessSetPing;
module.exports.timeoutProcessClearPing = timeoutProcessClearPing;
module.exports.timeoutProcessSetInactivity = timeoutProcessSetInactivity;
module.exports.timeoutProcessClearInactivity = timeoutProcessClearInactivity;

module.exports.getBackend = getBackend;
module.exports.getFormat = getFormat;
module.exports.cleanProcesses = cleanProcesses;

module.exports.addDependency = addDependency;
module.exports.runWithDependencyCheck = runWithDependencyCheck;

module.exports.killProcessIfExists = killProcessIfExists;
module.exports.logSpecific = logSpecific;
module.exports.logNormal = logNormal;

module.exports.escapeJSON = escapeJSON;

module.exports.replaceTemplate = replaceTemplate;
module.exports.replaceTemplateList = replaceTemplateList;
module.exports.filterArgs = filterArgs;

module.exports.getTitle = getTitle;
module.exports.getVersion = getVersion;
<commit_msg>Added error message when dependency code is not 0<commit_after>var fs = require("fs");
var config = require('./../config.json');
var backendConfig = require('./../Backends/backends.json');
var formatConfig = require('./../Formats/formats.json');
var packageConfig = require('./../package.json');

var spawn = require('child_process').spawn;

var processes = []; // for storing sessions

var getProcess = function(key)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == key)
        {
            return processes[i];
        }
    }

    return null;
};

var timeoutProcessSetPing = function (process)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == process.windowKey)
        {
            processes[i].pingTimeoutObject = setTimeout(pingTimeoutFunc, config.pingTimeout, processes[i]);
            return;
        }
    }
};

var timeoutProcessClearPing = function (process)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == process.windowKey)
        {
            clearTimeout(processes[i].pingTimeoutObject);
            return;
        }
    }
};

var timeoutProcessSetInactivity = function(process)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == process.windowKey)
        {
            processes[i].inactivityTimeoutObject = setTimeout(inactivityTimeoutFunc, config.inactivityTimeout, processes[i]);
            return;
        }
    }
};

var timeoutProcessClearInactivity = function (process)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == process.windowKey)
        {
            clearTimeout(processes[i].inactivityTimeoutObject);
            return;
        }
    }
};

var getBackend = function (backendId)
{
    for (var j = 0; j < backendConfig.backends.length; j++)
    {
        if (backendConfig.backends[j].id == backendId)
        {
            return backendConfig.backends[j];
        }
    }
    return null;
};

var getFormat = function (formatId)
{
    for (var j = 0; j < formatConfig.formats.length; j++)
    {
        if (formatConfig.formats[j].id == formatId)
        {
            return formatConfig.formats[j];
        }
    }

    return null;
};

processRemoveOlder = function (key)
{
    for (var i = 0; i < processes.length; i++)
    {
        if (processes[i].windowKey == key)
        {
            processes[i].toKill = true;
            timeoutProcessClearPing(processes[i]);
            processes[i].toRemoveCompletely = true;
            processes[i].windowKey = "none";
            break;
        }
    }
};

var addProcess = function (process)
{
    processRemoveOlder(process.windowKey);
    processes.push(process);
};

var pingTimeoutFunc = function (process)
{
    logSpecific("Error: Ping Timeout", process.windowKey);
    process.result = '{"message": "' + escapeJSON('Error: Ping Timeout. Please consider increasing timeout values in the "config.json" file. Currently it equals ' + config.pingTimeout + ' millisecond(s).') + '"}';
    process.toKill = true;
    process.toRemoveCompletely = true;
    cleanProcesses();
};

var inactivityTimeoutFunc = function (process)
{
    logSpecific("Error: Inactivity Timeout", process.windowKey);
    process.result = '{"message": "' + escapeJSON('Error: Inactivity Timeout. Please consider increasing timeout values in the "config.json" file. Currently it equals ' + config.inactivityTimeout + ' millisecond(s).') + '"}';
    process.toKill = true;
    process.toRemoveCompletely = true;
    cleanProcesses();
};

var cleanProcesses = function ()
{
    var i = 0;
    while (i < processes.length)
    {
        if (processes[i].toKill)
        {
            killProcessTree(processes[i]);
            processes[i].toKill = false;
        }

        if (processes[i].toRemoveCompletely)
        {
            clearTimeout(processes[i].pingTimeoutObject);
            clearTimeout(processes[i].inactivityTimeoutObject);
            setTimeout(cleanupOldFiles, config.cleaningTimeout, processes[i].folder);
            processes.splice(i, 1);
        }
        else
            i++;
    }

    logSpecific("Cleaning complete. #Processes = " + processes.length, null);
};

var killProcessTree = function(process)
{
    process.killed = true;
    killProcessIfExists(process.tool);
    process.tool = null;
    killProcessIfExists(process.clafer_compiler);
    process.clafer_compiler = null;
    logSpecific("Killing the process tree...", process.windowKey);
};

var dependencies = [];
var dependencyCount = 0;

var addDependency = function(path, args, title)
{
    dependencies.push({path : path, args : args, title : title});
};

function checkDependency(dependency, callback)
{
    var tool  = spawn(dependency.path, dependency.args);
    var tool_version = "";

    tool.on('error', function (err){
        logNormal('ERROR: Cannot find "' + dependency.title + '". Please check whether it is installed and accessible.');
    });

    tool.stdout.on('data', function (data){
        tool_version += data;
    });

    tool.stderr.on('data', function (data){
        tool_version += data;
    });

    tool.on('exit', function (code){
        logNormal(tool_version.trim());
        if (code == 0)
        {
            dependency_ok(callback);
        }
        else
        {
            logNormal('ERROR: Non-zero return code of "' + dependency.title + '": "' + code + '". Please check whether it is installed and accessible.');
        }
    });
}

var runWithDependencyCheck = function(callback)
{
    var node_version = process.version + ", " + JSON.stringify(process.versions);
    logNormal("Node.JS: " + node_version);
    dependencyCount = dependencies.length;

    for (var i = 0; i < dependencies.length; i++)
    {
        checkDependency(dependencies[i], callback);
    }
};

var dependency_ok = function(callback)
{
    dependencyCount--;
    if (dependencyCount == 0)
    {
        logNormal('Dependencies found successfully. Please review their versions manually');
        callback();
    }
};

var killProcessIfExists = function(tool)
{
    if (tool)
    {
        var pid = tool.pid;
        tool.removeAllListeners();
        logNormal("Killing the process with Parent PID = " + pid);

        // first, try a Windows command
        var killer_win  = spawn("taskkill", ["/F", "/T", "/PID", pid]);

        killer_win.on('error', function (err){  // if error occurs, then we are on Linux
            var killer_linux = spawn("pkill", ["-TERM", "-P", pid]);

            killer_linux.on('error', function(err){
                logNormal("Cannot terminate the process.");
            });
        });
    }
};

var logSpecific = function(message, key)
    {
        var date = new Date();
        var d = date.toUTCString();

        if (key != null)
        {
            console.log(d + " | " + key + " | " + message);
        }
        else
            console.log(d + " | " + "GLOBAL" + " | " + message);
    };

var logNormal = function(message)
    {
        console.log(message);
    };

var cleanupOldFiles = function (dir) {
        logNormal("Cleaning temporary files...");
        //cleanup old files
        fs.readdir(dir, function(err, files){
            //if (err) throw err;
            if (err)
            {
                logSpecific("Could not clear the folder: " + dir, null);
                return; // cannot get the folder
            }
            var results = "";
            var numFiles = files.length;
            logSpecific("#Files = " + numFiles, null);
            if (!numFiles){
                return finishCleanup(dir, results);
            } else {
                files.forEach(function(file){
                    deleteOld(dir + "/" + file);
                    results += file + "\n";
                });
                finishCleanup(dir, results);
            }
        });
    };

var deleteOld = function (path)
    {
        fs.exists(path, function(exists)
        {
            if (exists)
            {
                fs.unlink(path, function (err)
                {
                    if (err)
                    {
                        logNormal("Could not delete the file: " + path);
                        logNormal(err);
                    }
                });
            }
        });
    }

var finishCleanup = function (dir, results)
    {
        fs.exists(dir, function(exists)
        {
            if (exists)
            {
                fs.rmdir(dir, function (err) {
                    if (err)
                    {
                        logNormal("Could not finish the cleanup: " + dir);
                        return;
                    }
                    logNormal("Successfully deleted " + dir + " along with contents:\n" + results);
                });
            }
        });
    };

var escapeJSON = function (unsafe)
    {
        return unsafe.replace(/[\\]/g, '\\\\')
            .replace(/[\"]/g, '\\\"')
            .replace(/[\/]/g, '\\/')
            .replace(/[\b]/g, '\\b')
            .replace(/[\f]/g, '\\f')
            .replace(/[\n]/g, '\\n')
            .replace(/[\r]/g, '\\r')
            .replace(/[\t]/g, '\\t');
    };

var replaceTemplate = function (input_string, replacement_map)
    {
        var result = input_string;

        for (var j = 0; j < replacement_map.length; j++)
        {
            result = result.replace(replacement_map[j].needle, replacement_map[j].replacement);
        }

        return result;
    };

var replaceTemplateList = function(input_list, replacement_map)
    {
        var result = new Array();
        for (var i = 0; i < input_list.length; i++)
        {
            result.push(replaceTemplate(input_list[i], replacement_map));
        }

        return result;
    };

    // filter input command line arguments for safety purposes
var filterArgs = function (argString)
    {
        var args = argString.split(" ");
        var resultArgs = new Array();
        for (var i = 0; i < args.length; i++)
        {
            var arg = args[i].trim();

            if (arg.length == 0)
                continue;

            if (!arg.match(/-[A-Za-z-]+/))
                continue;

            resultArgs.push(arg);
        }

        return resultArgs;
    };

var getVersion = function()
    {
        return "v" + packageConfig.version + "." + packageConfig.release_date;
    };

var getTitle = function()
    {
        return packageConfig.name;
    };

module.exports.addProcess = addProcess;
module.exports.getProcess = getProcess;
module.exports.timeoutProcessSetPing = timeoutProcessSetPing;
module.exports.timeoutProcessClearPing = timeoutProcessClearPing;
module.exports.timeoutProcessSetInactivity = timeoutProcessSetInactivity;
module.exports.timeoutProcessClearInactivity = timeoutProcessClearInactivity;

module.exports.getBackend = getBackend;
module.exports.getFormat = getFormat;
module.exports.cleanProcesses = cleanProcesses;

module.exports.addDependency = addDependency;
module.exports.runWithDependencyCheck = runWithDependencyCheck;

module.exports.killProcessIfExists = killProcessIfExists;
module.exports.logSpecific = logSpecific;
module.exports.logNormal = logNormal;

module.exports.escapeJSON = escapeJSON;

module.exports.replaceTemplate = replaceTemplate;
module.exports.replaceTemplateList = replaceTemplateList;
module.exports.filterArgs = filterArgs;

module.exports.getTitle = getTitle;
module.exports.getVersion = getVersion;
<|endoftext|>


<commit_before>const debug = require('../debug').sub('voting', 'condorcets')
const EE    = require('events').EventEmitter
const util  = require('util')

const ndarray = require('ndarray')
ndarray.zeros = require('zeros')
ndarray.show  = require('ndarray-show')
ndarray.ops   = require('ndarray-ops')

function baseMatrix(movies) {
	const matrix = ndarray(new Int8Array(movies.length * movies.length), [ movies.length, movies.length ])
	for(var x = 0; x < matrix.shape[0]; x++) {
		for(var y = 0; y < matrix.shape[1]; y++) {
			matrix.set(x, y, 0)
		}
	}
	return matrix
}

module.exports = function(data) {
	const voting = new EE

	var titles

	function updateTitles() {
		titles = data.movies.map(function(movie) {
			return movie.name.replace(/a|an|and|the|\s+/gi, '').replace(/[^A-Z:]/g, '')
		})

		titles.maxLength = Math.max.apply(Math, [0].concat(titles.map(function(title) {
			return title.length
		})))
	}
	updateTitles()

	function renderMatrix(matrix, numbers) {
		if(titles.length == 0)
			return ''

		var res = new Array(titles.maxLength + 2).join(' ') + titles.join(' ')
		for(var y = 0; y < matrix.shape[1]; y++) {
			res += '\n' + titles[y] + new Array(titles.maxLength - titles[y].length + 2).join(' ')
			for(var x = 0; x < matrix.shape[0]; x++) {
				var num = matrix.get(x, y)
				var content = num ? '<' : ' '
				if(numbers && num)
					content = num + ''
				if(titles[x]) {
					res += content + new Array(Math.max(titles[x].length + 1 - content.length, 0)).join(' ') + ' '
				} else {
					debug(x, content)
					debug(titles[x])
					res += 'titles[' + x + '] = ' + util.inspect(titles[x]) + ' '
				}
			}
			res = res.slice(0, res.length - 1)
		}
		return res
	}

	function generateMatrix(person) {
		const vote = person.vote

		const moviesOrder = {}
		data.movies.forEach(function(movie, id) {
			moviesOrder[id] = Infinity
		})
		vote.forEach(function(id, i) {
			moviesOrder[id] = i
		})
		debug('movies order:', moviesOrder)

		const matrix = baseMatrix(data.movies)
		var val
		for(var x = 0; x < matrix.shape[0]; x++) {
			for(var y = 0; y < matrix.shape[1]; y++) {
				if(moviesOrder[y] < moviesOrder[x]) {
					val = 1
				} else {
					val = 0
				}
				matrix.set(x, y, val)
				debug.trace('setting %d (%d), %d (%d) to %d', x, moviesOrder[x], y, moviesOrder[y], val)
			}
		}
		debug('generated matrix for %s (%d):', person.name, person.id)
		if(debug.enabled) console.log(renderMatrix(matrix))
		return matrix
	}

	function update() {
		updateTitles()

		voting.matrix = baseMatrix(data.movies)
		voting.people.forEach(function(matrix) {
			ndarray.ops.add(voting.matrix, voting.matrix, matrix)
		})

		debug('matrix:')
		if(debug.enabled) console.log(renderMatrix(voting.matrix, true))

		voting.results = []

		const wins = {}
		data.movies.forEach(function(movie, id) {
			wins[id] = 0
		})

		for(var y = 0; y < voting.matrix.shape[1]; y++) {
			for(var x = 0; x < voting.matrix.shape[0]; x++) {
				if(x <= y) continue

				var runner   = voting.matrix.get(x, y)
				var opponent = voting.matrix.get(y, x)

				if(runner > opponent)
					wins[y] += 1
				else if(opponent > runner)
					wins[x] += 1

				debug.trace('%s (%d): %d | %s (%d): %d', data.movies[y].name, y, runner, data.movies[x].name, x, opponent)
			}
		}

		(function() {
			var maxWins = 0
			for(var id = 0; id < data.movies.length; id++) {
				/*if(wins[id] >= data.movies.length - 1) {
					voting.results = [ id ]
					return
				} else */
				if(wins[id] >= maxWins) {
					debug('adding %s (%d) - %d to the tie %s at %d', data.movies[id].name, id, wins[id], voting.results.map(function(id) {
						return data.movies[id].name
					}).join(', '), maxWins)
					if(wins[id] > maxWins) {
						maxWins = wins[id]
						voting.results = []
					}

					voting.results.push(id)
				}
			}
		})()

		debug('wins:', wins)

		if(voting.results.length == data.movies.length)
			voting.results = []

		voting.debugInfo = 'Result:\n' + renderMatrix(voting.matrix, true).split('\n').map(function(line) {
			return '  ' + line
		}).join('\n') + '\n\n' + voting.people.map(function(matrix, i) {
			const person = data.people[i]
			if(!person)
				return "Deleted: " + i
			return person.name + ': ' + person.vote.map(function(i) {
				return titles[i]
			}).join(' ') + '\n' + renderMatrix(matrix).split('\n').map(function(line) {
				return '  ' + line
			}).join('\n')
		}).join('\n\n')

		debug('results: %s', voting.results.map(function(id) {
			return data.movies[id].name
		}).join(', '))

		voting.emit('update')
	}

	voting.update = function(person) { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people[person.id] = generateMatrix(person)
		update()

		process.nextTick(function() { cb(null) })
	} }

	voting.delete = function(person) { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people[person.id] = baseMatrix(data.movies)

		update()

		process.nextTick(function() { cb(null) })
	} }

	voting.reset = function() { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people = []
		voting.matrix = baseMatrix(data.movies)
		voting.results = []
		debug('reseting')

		process.nextTick(function() { cb(null) })
	} }

	return voting
}<commit_msg>Add debug when a title doesn't exist<commit_after>const EE    = require('events').EventEmitter
const util  = require('util')

const debug = require('../debug').sub('voting', 'condorcets')
debug.titles = debug.sub('titles')

const ndarray = require('ndarray')
ndarray.zeros = require('zeros')
ndarray.show  = require('ndarray-show')
ndarray.ops   = require('ndarray-ops')

function baseMatrix(movies) {
	const matrix = ndarray(new Int8Array(movies.length * movies.length), [ movies.length, movies.length ])
	for(var x = 0; x < matrix.shape[0]; x++) {
		for(var y = 0; y < matrix.shape[1]; y++) {
			matrix.set(x, y, 0)
		}
	}
	return matrix
}

module.exports = function(data) {
	const voting = new EE

	var titles = []

	function updateTitles() {
		debug.titles('prev titles', titles.join(', '))
		titles = data.movies.map(function(movie) {
			return movie.name.replace(/a|an|and|the|\s+/gi, '').replace(/[^A-Z:]/g, '')
		})

		titles.maxLength = Math.max.apply(Math, [0].concat(titles.map(function(title) {
			return title.length
		})))
		debug.titles('next titles', titles.join(', '))
	}
	updateTitles()

	function renderMatrix(matrix, numbers) {
		if(titles.length == 0)
			return ''

		var res = new Array(titles.maxLength + 2).join(' ') + titles.join(' ')
		for(var y = 0; y < matrix.shape[1]; y++) {
			if(typeof(titles[y]) != 'string') {
				debug.titles("stuff broke (y)", y, titles, content)
				debug.titles("huh", titles[y])
			}
			res += '\n' + titles[y] + new Array(titles.maxLength - titles[y].length + 2).join(' ')
			for(var x = 0; x < matrix.shape[0]; x++) {
				var num = matrix.get(x, y)
				var content = num ? '<' : ' '
				if(numbers && num)
					content = num + ''
				if(typeof(titles[x]) != 'string') {
					debug.titles("stuff broke (x)", x, titles, content)
					debug.titles("huh", titles[x])
					res += 'titles[' + x + '] = ' + util.inspect(titles[x]) + ' '
				}
				res += content + new Array(Math.max(titles[x].length + 1 - content.length, 0)).join(' ') + ' '
			}
			res = res.slice(0, res.length - 1)
		}
		return res
	}

	function generateMatrix(person) {
		const vote = person.vote

		const moviesOrder = {}
		data.movies.forEach(function(movie, id) {
			moviesOrder[id] = Infinity
		})
		vote.forEach(function(id, i) {
			moviesOrder[id] = i
		})
		debug('movies order:', moviesOrder)

		const matrix = baseMatrix(data.movies)
		var val
		for(var x = 0; x < matrix.shape[0]; x++) {
			for(var y = 0; y < matrix.shape[1]; y++) {
				if(moviesOrder[y] < moviesOrder[x]) {
					val = 1
				} else {
					val = 0
				}
				matrix.set(x, y, val)
				debug.trace('setting %d (%d), %d (%d) to %d', x, moviesOrder[x], y, moviesOrder[y], val)
			}
		}
		debug('generated matrix for %s (%d):', person.name, person.id)
		if(debug.enabled) console.log(renderMatrix(matrix))
		return matrix
	}

	function update() {
		updateTitles()

		voting.matrix = baseMatrix(data.movies)
		voting.people.forEach(function(matrix) {
			ndarray.ops.add(voting.matrix, voting.matrix, matrix)
		})

		debug('matrix:')
		if(debug.enabled) console.log(renderMatrix(voting.matrix, true))

		voting.results = []

		const wins = {}
		data.movies.forEach(function(movie, id) {
			wins[id] = 0
		})

		for(var y = 0; y < voting.matrix.shape[1]; y++) {
			for(var x = 0; x < voting.matrix.shape[0]; x++) {
				if(x <= y) continue

				var runner   = voting.matrix.get(x, y)
				var opponent = voting.matrix.get(y, x)

				if(runner > opponent)
					wins[y] += 1
				else if(opponent > runner)
					wins[x] += 1

				debug.trace('%s (%d): %d | %s (%d): %d', data.movies[y].name, y, runner, data.movies[x].name, x, opponent)
			}
		}

		(function() {
			var maxWins = 0
			for(var id = 0; id < data.movies.length; id++) {
				/*if(wins[id] >= data.movies.length - 1) {
					voting.results = [ id ]
					return
				} else */
				if(wins[id] >= maxWins) {
					debug('adding %s (%d) - %d to the tie %s at %d', data.movies[id].name, id, wins[id], voting.results.map(function(id) {
						return data.movies[id].name
					}).join(', '), maxWins)
					if(wins[id] > maxWins) {
						maxWins = wins[id]
						voting.results = []
					}

					voting.results.push(id)
				}
			}
		})()

		debug('wins:', wins)

		if(voting.results.length == data.movies.length)
			voting.results = []

		voting.debugInfo = 'Result:\n' + renderMatrix(voting.matrix, true).split('\n').map(function(line) {
			return '  ' + line
		}).join('\n') + '\n\n' + voting.people.map(function(matrix, i) {
			const person = data.people[i]
			if(!person)
				return "Deleted: " + i
			return person.name + ': ' + person.vote.map(function(i) {
				return titles[i]
			}).join(' ') + '\n' + renderMatrix(matrix).split('\n').map(function(line) {
				return '  ' + line
			}).join('\n')
		}).join('\n\n')

		debug('results: %s', voting.results.map(function(id) {
			return data.movies[id].name
		}).join(', '))

		voting.emit('update')
	}

	voting.update = function(person) { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people[person.id] = generateMatrix(person)
		update()

		process.nextTick(function() { cb(null) })
	} }

	voting.delete = function(person) { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people[person.id] = baseMatrix(data.movies)

		update()

		process.nextTick(function() { cb(null) })
	} }

	voting.reset = function() { return function(cb) {
		if(!cb) cb = function(err) { if(err) throw err }

		voting.people = []
		voting.matrix = baseMatrix(data.movies)
		voting.results = []
		debug('reseting')

		process.nextTick(function() { cb(null) })
	} }

	return voting
}<|endoftext|>


<commit_before>/*
 *
 * ThemeSwitcher.js -- part of Quantum GIS Web Client
 *
 * Copyright (2010-2012), The QGIS Project All rights reserved.
 * Quantum GIS Web Client is released under a BSD license. Please see
 * https://github.com/qgis/qgis-web-client/blob/master/README
 * for the full text of the license and the list of contributors.
 *
*/

//this object handles the theme optional switching
function ThemeSwitcher(parentPanel) {
	this.parentPanel = parentPanel;
	this.themeSwitcherWindow = undefined; //after initialization this will be the main panel of the themeSwitcher
	this.topicsListView = undefined; //will later hold a referemce to the list view holding the topics
	this.projectDataView = undefined; //will later hold a reference to the thumbnails data view
	this.activeTopicIndex = 0; //points to all topics
	this.activeTopicName = ""; //will hold the current topic filter later
	this.titleAndTagFilter = ""; //will hold the current title or tag filter string later
	me = this;
	//create a new jsonstore holding the topic-listing data
	if (gis_projects) {
		//add a new record to json array
		gis_projects.topics.unshift({
			name: themeSwitcherAllThemesListViewString[lang],
			projects: []
		});
		this.gisTopicListingStore = new Ext.data.JsonStore({
			storeId: 'gisTopicListingStore',
			data: gis_projects,
			// reader configs
			root: 'topics',
			idProperty: 'name',
			fields: ['name', 'projects']
		});
		//fill a new array store with all project records
		//will be used to display a table of thumbnails
		var topicCounter = 0;
		var projListingArray = [];
		for (var i = 0; i < this.gisTopicListingStore.getCount(); i++) {
			var topicRec = this.gisTopicListingStore.getAt(i);
			for (var j = 0; j < topicRec.data.projects.length; j++) {
				var projData = topicRec.data.projects[j];
				projData.topic = topicRec.data.name;
				var tooltip = themeSwitcherTooltipMapThemeString[lang] + projData.name;
				if (projData.tags) {
					tooltip += "\n" + themeSwitcherTooltipTagString[lang] + projData.tags;
				}
				if (projData.responsible) {
					tooltip += "\n" + themeSwitcherTooltipResponsibleString[lang] + projData.responsible;
				}
				if (projData.updateInterval) {
					tooltip += "\n" + themeSwitcherTooltipUpdateString[lang] + projData.updateInterval;
				}
				if (projData.lastUpdate) {
					tooltip += "\n" + themeSwitcherTooltipLastUpdateString[lang] + projData.lastUpdate;
				}
				var pwprotected = "no";
				if (projData.pwProtected) {
					if (projData.pwProtected == "yes") {
						pwprotected = "yes";
						tooltip += "\n\n" + themeSwitcherTooltipPwProtectedString[lang] + ": " + projData.pwMessage;
					}
				}
				projListingArray.push([topicCounter + '_' + projData.projectfile, projData.name, projData.topic, projData.projectfile, projData.tags, pwprotected, tooltip, projData]);
			}
			topicCounter++;
		}
		//create a new json data store holding the project data
		this.gisProjectListingStore = new Ext.data.ArrayStore({
			storeId: 'gisProjectListingStore',
			fields: ['id', 'projname', 'topic', 'projectfile', 'tags', 'pwprotected', 'tooltip', 'data'],
			idProperty: 'id',
			data: projListingArray
		});
		//add click listener to button
		Ext.getCmp('mapThemeButton').addListener("click", function (myButton, event) {
			me.openOrInitialize();
		});
	} else {
		alert(errMessageGisProjectsJSONStructureMissing[lang]);
		//maybe we need to add some more checks if the datastore contains valid data
	}
}

ThemeSwitcher.prototype.openOrInitialize = function () {
	if (this.themeSwitcherWindow) {
		if (this.themeSwitcherWindow.hidden) {
			this.topicsListView.select(0);
			this.themeSwitcherWindow.show();
		} else {
			this.themeSwitcherWindow.hide();
			this.themeSearchField.reset();
			this.filterThumbnailsByTitleOrTag('');
			this.gisProjectListingStore.clearFilter(false);
			this.topicsListView.clearSelections(false);
		}
	} else {
		this.initialize();
	}
}

ThemeSwitcher.prototype.initialize = function () {
	me = this;
	var template = themeSwitcherTemplate?themeSwitcherTemplate:new Ext.XTemplate('
', '<tpl for=".">', '
', '', '<tpl if="pwprotected==\'yes\'">', '','</tpl>','{projname}', '<tpl if="pwprotected==\'yes\'">', ' - ' + themeSwitcherTooltipPwProtectedString[lang], '</tpl>', '', '
', '</tpl>', '
');

	//add data view for grid thumbnails view
	this.projectDataView = new Ext.DataView({
		store: this.gisProjectListingStore,
		tpl: template,
		id: 'projects',
		itemSelector: 'li.project',
		overClass: 'projects-hover',
		singleSelect: true,
		multiSelect: false,
		autoScroll: true,
		listeners: {
			'click': {
				fn: this.changeTheme,
				scope: this
			}
		}
	});

	this.themeSwitcherWindow = new Ext.Window({
		title: themeSwitcherWindowTitleString[lang],
		width: this.parentPanel.getInnerWidth() - 10,
		height: this.parentPanel.getInnerHeight() - 10,
		renderTo: "geoExtMapPanel",
		resizable: true,
		closable: true,
		maximizable: true,
		layout: 'border',
		listeners: {
			"close": function (myWindow) {
				me.themeSearchField.reset();
				me.filterThumbnailsByTitleOrTag('');
				me.gisProjectListingStore.clearFilter(false);
				me.topicsListView.clearSelections(false);
				me.themeSwitcherWindow = undefined;
			}
		},
		x: 5,
		y: 5,
		items: [{
			xtype: 'panel',
			region: 'west',
			collapsible: false,
			boxMinWidth: 200,
			boxMaxWidth: 400,
			split: true,
			headerAsText: false,
			id: 'topicsListPanel',
			layout: 'fit',
			items: [{
				xtype: 'listview',
				store: this.gisTopicListingStore,
				multiSelect: false,
				singleSelect: true,
				id: 'mapTopicsListView',
				columns: [{
					width: 1,
					dataIndex: 'name'
				}],
				listeners: {
					"click": function (listView, index, node, evt) {
						me.filterThumbnailsByList(listView, index, node, evt);
					}
				}
			}]
		}, {
			xtype: 'panel',
			region: 'center',
			collapsible: false,
			split: true,
			headerAsText: false,
			layout: 'fit',
			id: 'imagePanel',
			tbar: {
				xtype: 'toolbar',
				autoHeight: true,
				items: [{
					xtype: 'tbtext',
					text: themeSwitcherFilterLabelString[lang]
				}, {
					xtype: 'textfield',
					width: '250',
					id: 'themeSearchField',
					//plugins: new Ext.ux.form.field.ClearButton({hideClearButtonWhenMouseOut: false}),
					//the ClearButton only works with ExtJS4
					emptyText: emptyThemeSearchFieldString[lang],
					enableKeyEvents: true,
					listeners: {
						"keyup": function (textfield, evt) {
							me.filterThumbnailsByTitleOrTag(textfield.getValue());
						}
					}
				}, {
					xtype: 'button',
					icon: 'gis_icons/mActionUndo.png',
					scale: 'medium',
					tooltipType: 'qtip',
					tooltip: resetThemeSearchFieldTooltipString[lang],
					id: 'EmptyThemeSearchField',
					listeners: {
						"click": function (button, evt) {
							Ext.getCmp('themeSearchField').reset();
							me.filterThumbnailsByTitleOrTag('');
						}
					}
				}]
			},
			items: [
			this.projectDataView]
		}]
	});

	this.topicsListView = Ext.getCmp('mapTopicsListView');
	this.topicsListView.select(0);
	this.themeSearchField = Ext.getCmp('themeSearchField');
	this.themeSwitcherWindow.show();
}

ThemeSwitcher.prototype.filterThumbnailsByList = function (listView, index, node, evt) {
	var topicName = listView.getRecord(node).data.name;
	this.activeTopicIndex = index;
	this.activeTopicName = topicName;
	this.filterThumbnails();
}

ThemeSwitcher.prototype.filterThumbnailsByTitleOrTag = function (newValue) {
	this.titleAndTagFilter = newValue;
	this.filterThumbnails();
}

ThemeSwitcher.prototype.filterThumbnails = function (listView, index, node, evt) {
	me = this;
	if (this.activeTopicIndex == 0 && this.titleAndTagFilter.length < 2) {
		this.gisProjectListingStore.clearFilter(false);
	} else {
		this.gisProjectListingStore.filterBy(

		function (record, recid) {
			returnVal = null;
			if (me.titleAndTagFilter.length < 2) {
				if (record.get('topic') == me.activeTopicName) {
					returnVal = record;
				}
			} else {
				var myRegExp = new RegExp(me.titleAndTagFilter, "i");
				var tags = record.get('projname') + record.get('tags');
				if (me.activeTopicIndex > 0) {
					if (record.get('topic') == me.activeTopicName && tags.match(myRegExp)) {
						returnVal = record;
					}
				} else {
					if (tags.match(myRegExp)) {
						returnVal = record;
					}
				}
			}
			return returnVal;
		});
	}
}

//here we actually change the map theme
ThemeSwitcher.prototype.changeTheme = function (dataView, index, node, evt) {
	if (dataView.getSelectedRecords().length > 0) {
		//close legend/metadata window if active
		 if (legendMetadataWindow_active) {
			legendMetadataWindow.close();
		 }

		//switch off GetFeatureInfo if active
		if (identifyToolActive) {
			identifyToolWasActive = true;
			Ext.getCmp('IdentifyTool').toggle(false);
		}
		themeChangeActive = true;
		var projData = dataView.getSelectedRecords()[0].data.data;
		this.themeSearchField.reset();
		this.filterThumbnailsByTitleOrTag('');
		this.gisProjectListingStore.clearFilter(false);
		this.topicsListView.clearSelections(false);
		this.themeSwitcherWindow.hide();
		layerTree.removeListener("selectionChange",layerTreeSelectionChangeHandlerFunction);
		urlParamsOK = true;
		//concatenate path for webserver and cgi
		wmsURI = '';
		if (projData.mapserver) {
			wmsURI = projData.mapserver;
		} else {
			wmsURI = gis_projects.mapserver;
		}
		if (norewrite) {
			wmsURI += "?map=" + projData.projectpath + "/" + projData.projectfile + ".qgs&";
		} else {
			wmsURI += "/" + projData.projectpath + "/" + projData.projectfile + "?";
		}
		wmsMapName = projData.projectpath + "/" + projData.projectfile;
		//handle visible layers
		if (projData.visibleLayers) {
			visibleLayers = projData.visibleLayers.split(",");
		} else {
			visibleLayers = [];
		}
		//handle full color layers
		if (projData.fullColorLayers) {
			fullColorLayers = projData.fullColorLayers.split(",");
		} else {
			fullColorLayers = [];
		}
		//handle image format
		if (projData.format) {
			format = projData.format;
		}
		origFormat = format;
		//handle search tables
		if (projData.searchtables) {
			searchtables = projData.searchtables;
		}
		//handle max extent
		if (projData.maxExtent) {
			//need to check validity of maxExtent parameter
			//can be either "project" or corner coordinates in OpenLayers.Bounds format (left, bottom, right, top)
			if (projData.maxExtent.match(olBoundsRegexp)) {
				var maxExtentParams = projData.maxExtent.split(",");
				if (parseFloat(maxExtentParams[0]) > parseFloat(maxExtentParams[2]) || parseFloat(maxExtentParams[1]) > parseFloat(maxExtentParams[3])) {
					urlParamsOK = false;
				}
				else {
					maxExtent = new OpenLayers.Bounds(parseFloat(maxExtentParams[0]), parseFloat(maxExtentParams[1]), parseFloat(maxExtentParams[2]), parseFloat(maxExtentParams[3]));
				}
			} else {
				urlParamsOK = false;
				alert(errMessageExtentParamWrongPart1[lang] + "maxExtent" + errMessageExtentParamWrongPart2[lang]);
			}
		}
		//set initialLayerOrder to null to avoid that layers from last project are used for the layer order tree
		initialLayerOrder = null;
		//set printLayoutsDefined to false - will be loaded after theme switch
		printLayoutsDefined = false;
		//now load the config of the new project
		if (urlParamsOK) {
			loadWMSConfig();
		} else {
			alert(errMessageStartupNotAllParamsFoundString[lang]);
		}
	}
}
<commit_msg>make theme switcher thumbnails work out the box<commit_after>/*
 *
 * ThemeSwitcher.js -- part of Quantum GIS Web Client
 *
 * Copyright (2010-2012), The QGIS Project All rights reserved.
 * Quantum GIS Web Client is released under a BSD license. Please see
 * https://github.com/qgis/qgis-web-client/blob/master/README
 * for the full text of the license and the list of contributors.
 *
*/

//this object handles the theme optional switching
function ThemeSwitcher(parentPanel) {
	this.parentPanel = parentPanel;
	this.themeSwitcherWindow = undefined; //after initialization this will be the main panel of the themeSwitcher
	this.topicsListView = undefined; //will later hold a referemce to the list view holding the topics
	this.projectDataView = undefined; //will later hold a reference to the thumbnails data view
	this.activeTopicIndex = 0; //points to all topics
	this.activeTopicName = ""; //will hold the current topic filter later
	this.titleAndTagFilter = ""; //will hold the current title or tag filter string later
	me = this;
	//create a new jsonstore holding the topic-listing data
	if (gis_projects) {
		//add a new record to json array
		gis_projects.topics.unshift({
			name: themeSwitcherAllThemesListViewString[lang],
			projects: []
		});
		this.gisTopicListingStore = new Ext.data.JsonStore({
			storeId: 'gisTopicListingStore',
			data: gis_projects,
			// reader configs
			root: 'topics',
			idProperty: 'name',
			fields: ['name', 'projects']
		});
		//fill a new array store with all project records
		//will be used to display a table of thumbnails
		var topicCounter = 0;
		var projListingArray = [];
		for (var i = 0; i < this.gisTopicListingStore.getCount(); i++) {
			var topicRec = this.gisTopicListingStore.getAt(i);
			for (var j = 0; j < topicRec.data.projects.length; j++) {
				var projData = topicRec.data.projects[j];
				projData.topic = topicRec.data.name;
				var tooltip = themeSwitcherTooltipMapThemeString[lang] + projData.name;
				if (projData.tags) {
					tooltip += "\n" + themeSwitcherTooltipTagString[lang] + projData.tags;
				}
				if (projData.responsible) {
					tooltip += "\n" + themeSwitcherTooltipResponsibleString[lang] + projData.responsible;
				}
				if (projData.updateInterval) {
					tooltip += "\n" + themeSwitcherTooltipUpdateString[lang] + projData.updateInterval;
				}
				if (projData.lastUpdate) {
					tooltip += "\n" + themeSwitcherTooltipLastUpdateString[lang] + projData.lastUpdate;
				}
				var pwprotected = "no";
				if (projData.pwProtected) {
					if (projData.pwProtected == "yes") {
						pwprotected = "yes";
						tooltip += "\n\n" + themeSwitcherTooltipPwProtectedString[lang] + ": " + projData.pwMessage;
					}
				}
				projListingArray.push([topicCounter + '_' + projData.projectfile, projData.name, projData.topic, projData.projectfile, projData.tags, pwprotected, tooltip, projData]);
			}
			topicCounter++;
		}
		//create a new json data store holding the project data
		this.gisProjectListingStore = new Ext.data.ArrayStore({
			storeId: 'gisProjectListingStore',
			fields: ['id', 'projname', 'topic', 'projectfile', 'tags', 'pwprotected', 'tooltip', 'data'],
			idProperty: 'id',
			data: projListingArray
		});
		//add click listener to button
		Ext.getCmp('mapThemeButton').addListener("click", function (myButton, event) {
			me.openOrInitialize();
		});
	} else {
		alert(errMessageGisProjectsJSONStructureMissing[lang]);
		//maybe we need to add some more checks if the datastore contains valid data
	}
}

ThemeSwitcher.prototype.openOrInitialize = function () {
	if (this.themeSwitcherWindow) {
		if (this.themeSwitcherWindow.hidden) {
			this.topicsListView.select(0);
			this.themeSwitcherWindow.show();
		} else {
			this.themeSwitcherWindow.hide();
			this.themeSearchField.reset();
			this.filterThumbnailsByTitleOrTag('');
			this.gisProjectListingStore.clearFilter(false);
			this.topicsListView.clearSelections(false);
		}
	} else {
		this.initialize();
	}
}

ThemeSwitcher.prototype.initialize = function () {
	me = this;
	var template = themeSwitcherTemplate?themeSwitcherTemplate:new Ext.XTemplate('
', '<tpl for=".">', '
', '', '<tpl if="pwprotected==\'yes\'">', '','</tpl>','{projname}', '<tpl if="pwprotected==\'yes\'">', ' - ' + themeSwitcherTooltipPwProtectedString[lang], '</tpl>', '', '
', '</tpl>', '
');

	//add data view for grid thumbnails view
	this.projectDataView = new Ext.DataView({
		store: this.gisProjectListingStore,
		tpl: template,
		id: 'projects',
		itemSelector: 'li.project',
		overClass: 'projects-hover',
		singleSelect: true,
		multiSelect: false,
		autoScroll: true,
		listeners: {
			'click': {
				fn: this.changeTheme,
				scope: this
			}
		}
	});

	this.themeSwitcherWindow = new Ext.Window({
		title: themeSwitcherWindowTitleString[lang],
		width: this.parentPanel.getInnerWidth() - 10,
		height: this.parentPanel.getInnerHeight() - 10,
		renderTo: "geoExtMapPanel",
		resizable: true,
		closable: true,
		maximizable: true,
		layout: 'border',
		listeners: {
			"close": function (myWindow) {
				me.themeSearchField.reset();
				me.filterThumbnailsByTitleOrTag('');
				me.gisProjectListingStore.clearFilter(false);
				me.topicsListView.clearSelections(false);
				me.themeSwitcherWindow = undefined;
			}
		},
		x: 5,
		y: 5,
		items: [{
			xtype: 'panel',
			region: 'west',
			collapsible: false,
			boxMinWidth: 200,
			boxMaxWidth: 400,
			split: true,
			headerAsText: false,
			id: 'topicsListPanel',
			layout: 'fit',
			items: [{
				xtype: 'listview',
				store: this.gisTopicListingStore,
				multiSelect: false,
				singleSelect: true,
				id: 'mapTopicsListView',
				columns: [{
					width: 1,
					dataIndex: 'name'
				}],
				listeners: {
					"click": function (listView, index, node, evt) {
						me.filterThumbnailsByList(listView, index, node, evt);
					}
				}
			}]
		}, {
			xtype: 'panel',
			region: 'center',
			collapsible: false,
			split: true,
			headerAsText: false,
			layout: 'fit',
			id: 'imagePanel',
			tbar: {
				xtype: 'toolbar',
				autoHeight: true,
				items: [{
					xtype: 'tbtext',
					text: themeSwitcherFilterLabelString[lang]
				}, {
					xtype: 'textfield',
					width: '250',
					id: 'themeSearchField',
					//plugins: new Ext.ux.form.field.ClearButton({hideClearButtonWhenMouseOut: false}),
					//the ClearButton only works with ExtJS4
					emptyText: emptyThemeSearchFieldString[lang],
					enableKeyEvents: true,
					listeners: {
						"keyup": function (textfield, evt) {
							me.filterThumbnailsByTitleOrTag(textfield.getValue());
						}
					}
				}, {
					xtype: 'button',
					icon: 'gis_icons/mActionUndo.png',
					scale: 'medium',
					tooltipType: 'qtip',
					tooltip: resetThemeSearchFieldTooltipString[lang],
					id: 'EmptyThemeSearchField',
					listeners: {
						"click": function (button, evt) {
							Ext.getCmp('themeSearchField').reset();
							me.filterThumbnailsByTitleOrTag('');
						}
					}
				}]
			},
			items: [
			this.projectDataView]
		}]
	});

	this.topicsListView = Ext.getCmp('mapTopicsListView');
	this.topicsListView.select(0);
	this.themeSearchField = Ext.getCmp('themeSearchField');
	this.themeSwitcherWindow.show();
}

ThemeSwitcher.prototype.filterThumbnailsByList = function (listView, index, node, evt) {
	var topicName = listView.getRecord(node).data.name;
	this.activeTopicIndex = index;
	this.activeTopicName = topicName;
	this.filterThumbnails();
}

ThemeSwitcher.prototype.filterThumbnailsByTitleOrTag = function (newValue) {
	this.titleAndTagFilter = newValue;
	this.filterThumbnails();
}

ThemeSwitcher.prototype.filterThumbnails = function (listView, index, node, evt) {
	me = this;
	if (this.activeTopicIndex == 0 && this.titleAndTagFilter.length < 2) {
		this.gisProjectListingStore.clearFilter(false);
	} else {
		this.gisProjectListingStore.filterBy(

		function (record, recid) {
			returnVal = null;
			if (me.titleAndTagFilter.length < 2) {
				if (record.get('topic') == me.activeTopicName) {
					returnVal = record;
				}
			} else {
				var myRegExp = new RegExp(me.titleAndTagFilter, "i");
				var tags = record.get('projname') + record.get('tags');
				if (me.activeTopicIndex > 0) {
					if (record.get('topic') == me.activeTopicName && tags.match(myRegExp)) {
						returnVal = record;
					}
				} else {
					if (tags.match(myRegExp)) {
						returnVal = record;
					}
				}
			}
			return returnVal;
		});
	}
}

//here we actually change the map theme
ThemeSwitcher.prototype.changeTheme = function (dataView, index, node, evt) {
	if (dataView.getSelectedRecords().length > 0) {
		//close legend/metadata window if active
		 if (legendMetadataWindow_active) {
			legendMetadataWindow.close();
		 }

		//switch off GetFeatureInfo if active
		if (identifyToolActive) {
			identifyToolWasActive = true;
			Ext.getCmp('IdentifyTool').toggle(false);
		}
		themeChangeActive = true;
		var projData = dataView.getSelectedRecords()[0].data.data;
		this.themeSearchField.reset();
		this.filterThumbnailsByTitleOrTag('');
		this.gisProjectListingStore.clearFilter(false);
		this.topicsListView.clearSelections(false);
		this.themeSwitcherWindow.hide();
		layerTree.removeListener("selectionChange",layerTreeSelectionChangeHandlerFunction);
		urlParamsOK = true;
		//concatenate path for webserver and cgi
		wmsURI = '';
		if (projData.mapserver) {
			wmsURI = projData.mapserver;
		} else {
			wmsURI = gis_projects.mapserver;
		}
		if (norewrite) {
			wmsURI += "?map=" + projData.projectpath + "/" + projData.projectfile + ".qgs&";
		} else {
			wmsURI += "/" + projData.projectpath + "/" + projData.projectfile + "?";
		}
		wmsMapName = projData.projectpath + "/" + projData.projectfile;
		//handle visible layers
		if (projData.visibleLayers) {
			visibleLayers = projData.visibleLayers.split(",");
		} else {
			visibleLayers = [];
		}
		//handle full color layers
		if (projData.fullColorLayers) {
			fullColorLayers = projData.fullColorLayers.split(",");
		} else {
			fullColorLayers = [];
		}
		//handle image format
		if (projData.format) {
			format = projData.format;
		}
		origFormat = format;
		//handle search tables
		if (projData.searchtables) {
			searchtables = projData.searchtables;
		}
		//handle max extent
		if (projData.maxExtent) {
			//need to check validity of maxExtent parameter
			//can be either "project" or corner coordinates in OpenLayers.Bounds format (left, bottom, right, top)
			if (projData.maxExtent.match(olBoundsRegexp)) {
				var maxExtentParams = projData.maxExtent.split(",");
				if (parseFloat(maxExtentParams[0]) > parseFloat(maxExtentParams[2]) || parseFloat(maxExtentParams[1]) > parseFloat(maxExtentParams[3])) {
					urlParamsOK = false;
				}
				else {
					maxExtent = new OpenLayers.Bounds(parseFloat(maxExtentParams[0]), parseFloat(maxExtentParams[1]), parseFloat(maxExtentParams[2]), parseFloat(maxExtentParams[3]));
				}
			} else {
				urlParamsOK = false;
				alert(errMessageExtentParamWrongPart1[lang] + "maxExtent" + errMessageExtentParamWrongPart2[lang]);
			}
		}
		//set initialLayerOrder to null to avoid that layers from last project are used for the layer order tree
		initialLayerOrder = null;
		//set printLayoutsDefined to false - will be loaded after theme switch
		printLayoutsDefined = false;
		//now load the config of the new project
		if (urlParamsOK) {
			loadWMSConfig();
		} else {
			alert(errMessageStartupNotAllParamsFoundString[lang]);
		}
	}
}
<|endoftext|>


<commit_before>const { execSync } = require('child_process');
const os = require('os');

module.exports = () => {
  // On windows, the timezone is not set with `TZ=GMT`. As a workaround, use `tzutil`.
  // This approach is taken from https://www.npmjs.com/package/set-tz.
  if (os.platform() === 'win32') {
    const TZ = 'GMT Standard Time';
    const previousTZ = execSync('tzutil /g').toString();
    const cleanup = () => {
      execSync(`tzutil /s "${previousTZ}"`);
      console.log(`Restored timezone to ${previousTZ}`);
    };
    execSync(`tzutil /s "${TZ}"`);
    console.warn(
      `Changed timezone to ${TZ}. If process is killed, manually run: tzutil /s "${previousTZ}"`,
    );
    process.on('exit', cleanup);
    process.on('SIGINT', () => {
      process.exit(2);
    });
  } else {
    process.env.TZ = 'GMT';
  }
};
<commit_msg>Set timezone to UTC in windows (#5538)<commit_after>const { execSync } = require('child_process');
const os = require('os');

module.exports = () => {
  // On windows, the timezone is not set with `TZ=GMT`. As a workaround, use `tzutil`.
  // This approach is taken from https://www.npmjs.com/package/set-tz.
  if (os.platform() === 'win32') {
    const TZ = 'UTC';
    const previousTZ = execSync('tzutil /g').toString();
    const cleanup = () => {
      execSync(`tzutil /s "${previousTZ}"`);
      console.log(`Restored timezone to ${previousTZ}`);
    };
    execSync(`tzutil /s "${TZ}"`);
    console.warn(
      `Changed timezone to ${TZ}. If process is killed, manually run: tzutil /s "${previousTZ}"`,
    );
    process.on('exit', cleanup);
    process.on('SIGINT', () => {
      process.exit(2);
    });
  } else {
    process.env.TZ = 'GMT';
  }
};
<|endoftext|>


<commit_before>/* Content loader pattern.
 *
 * Options:
 *    url(string): To load content from remote resource. Use 'el' to use with anchor tag href.
 *    content(string): CSS selector for content already on page. Can be used in conjunction with url to load remote content on page.
 *    trigger(string): Event to trigger content loading. Defaults to "click"
 *    target(string): CSS selector of target for content loading. If this is empty, it's assume content will replace pattern element.
 *
 * Documentation:
 *    # With selector
 *    {{ example-1 }}
 *
 *    # With remote content
 *    {{ example-2 }}
 *
 * Example: example-1
 *    Load content
 *
Original Content

 *
Replaced Content

 *
 * Example: example-2
 *    Load content
 *
 *
 */

define([
  'jquery',
  'mockup-patterns-base',
  'pat-logger',
  'pat-registry',
  'mockup-utils'
], function($, Base, logger, Registry, utils) {
  'use strict';
  var log = logger.getLogger('pat-contentloader');

  var ContentLoader = Base.extend({
    name: 'contentloader',
    trigger: '.pat-contentloader',
    defaults: {
      url: null,
      content: null,
      trigger: 'click',
      target: null
    },
    init: function() {
      var that = this;
      if(that.options.url === 'el' && that.$el[0].tagName === 'A'){
        that.options.url = that.$el.attr('href');
      }
      that.$el.on(that.options.trigger, function(e){
        e.preventDefault();
        that.$el.addClass('loading-content');
        if(that.options.url){
          that.loadRemote();
        }else{
          that.loadLocal();
        }
      });
    },
    loadRemote: function(){
      var that = this;
      $.ajax({
        url: that.options.url
      }).done(function(data){
        if(data.indexOf('<html') !== -1){
          data = utils.parseBodyTag(data);
        }
        var $el = $(data);
        if(that.options.content !== null){
          $el = $el.find(that.options.content);
        }
        that.loadLocal($el);
      });
    },
    loadLocal: function($content){
      var that = this;
      if(!$content && that.options.content === null){
        log.warn('No selector configured');
        return;
      }
      var $target = that.$el;
      if(that.options.target !== null){
        $target = $(that.options.target);
        if($target.size() === 0){
          log.warn('No target nodes found');
          return;
        }
      }

      if(!$content){
        $content = $(that.options.content).clone();
      }
      $content.show();
      $target.replaceWith($content);
      Registry.scan($content);
      that.$el.removeClass('loading-content');
    }
  });

  return ContentLoader;

});
<commit_msg>update content loader to work with templates<commit_after>/* Content loader pattern.
 *
 * Options:
 *    url(string): To load content from remote resource. Use 'el' to use with anchor tag href.
 *    content(string): CSS selector for content already on page. Can be used in conjunction with url to load remote content on page.
 *    trigger(string): Event to trigger content loading. Defaults to "click"
 *    target(string): CSS selector of target for content loading. If this is empty, it's assume content will replace pattern element.
 *
 * Documentation:
 *    # With selector
 *    {{ example-1 }}
 *
 *    # With remote content
 *    {{ example-2 }}
 *
 * Example: example-1
 *    Load content
 *
Original Content

 *
Replaced Content

 *
 * Example: example-2
 *    Load content
 *
 *
 */

define([
  'jquery',
  'mockup-patterns-base',
  'pat-logger',
  'pat-registry',
  'mockup-utils',
  'underscore'
], function($, Base, logger, Registry, utils, _) {
  'use strict';
  var log = logger.getLogger('pat-contentloader');

  var ContentLoader = Base.extend({
    name: 'contentloader',
    trigger: '.pat-contentloader',
    defaults: {
      url: null,
      content: null,
      trigger: 'click',
      target: null,
      template: null,
      dataType: 'html'
    },
    init: function() {
      var that = this;
      if(that.options.url === 'el' && that.$el[0].tagName === 'A'){
        that.options.url = that.$el.attr('href');
      }
      if(that.options.trigger === 'immediate'){
        that._load();
      }else{
        that.$el.on(that.options.trigger, function(e){
          e.preventDefault();
          that._load();
        });
      }
    },
    _load: function(){
      var that = this;
      that.$el.addClass('loading-content');
      if(that.options.url){
        that.loadRemote();
      }else{
        that.loadLocal();
      }
    },
    loadRemote: function(){
      var that = this;
      $.ajax({
        url: that.options.url,
        dataType: that.options.dataType,
        success: function(data){
          var $el;
          if(that.options.dataType === 'html'){
            if(data.indexOf('<html') !== -1){
              data = utils.parseBodyTag(data);
            }
            $el = $(data);
          }else if(that.options.dataType.indexOf('json') !== -1){
            // must have template defined with json
            if(data.constructor === Array && data.length === 1){
              // normalize json if it makes sense since some json returns as array with one item
              data = data[0];
            }
            try{
              $el = $(_.template(that.options.template, data));
            }catch(e){
              // log this
              log.warn('error rendering template. pat-contentloader will not work');
              return;
            }
          }
          if(that.options.content !== null){
            $el = $el.find(that.options.content);
          }
          that.loadLocal($el);
          that.$el.removeClass('loading-content');
        },
        error: function(){
          that.$el.addClass('content-load-error');
        }
      });
    },
    loadLocal: function($content){
      var that = this;
      if(!$content && that.options.content === null){
        log.warn('No selector configured');
        return;
      }
      var $target = that.$el;
      if(that.options.target !== null){
        $target = $(that.options.target);
        if($target.size() === 0){
          log.warn('No target nodes found');
          return;
        }
      }

      if(!$content){
        $content = $(that.options.content).clone();
      }
      $content.show();
      $target.replaceWith($content);
      Registry.scan($content);
      that.$el.removeClass('loading-content');
    }
  });

  return ContentLoader;

});
<|endoftext|>


<commit_before>'use strict';

var memoize                = require('memoizee/plain')
  , defineGlobalPrimitives = require('./base')
  , defineUInteger         = require('dbjs-ext/number/integer/u-integer');

module.exports = memoize(function (db) {
	var globalPrimitives = defineGlobalPrimitives(db)
	  , UInteger         = defineUInteger(db);

	globalPrimitives.define('workingHours', {
		type: db.Object,
		nested: true
	});

	globalPrimitives.workingHours.defineProperties({
		start: {
			type: db.Object,
			nested: true
		},
		end: {
			type: db.Object,
			nested: true
		}
	});

	var hoursMinutesDefinition = {
		hours: {
			type: UInteger,
			max: 24
		},
		minutes: {
			type: UInteger,
			max: 59
		}
	};

	globalPrimitives.workingHours.start.defineProperties(hoursMinutesDefinition);
	globalPrimitives.workingHours.end.defineProperties(hoursMinutesDefinition);

	return globalPrimitives;
}, { normalizer: require('memoizee/normalizers/get-1')() });
<commit_msg>#1799 fix working hours setup<commit_after>'use strict';

var memoize                = require('memoizee/plain')
  , defineGlobalPrimitives = require('./base')
  , defineUInteger         = require('dbjs-ext/number/integer/u-integer')
  , _                      = require('mano').i18n.bind('Model');

module.exports = memoize(function (db) {
	var globalPrimitives = defineGlobalPrimitives(db)
	  , UInteger         = defineUInteger(db);

	globalPrimitives.define('workingHours', {
		type: db.Object,
		nested: true
	});

	globalPrimitives.workingHours.defineProperties({
		start: {
			type: db.Object,
			nested: true
		},
		end: {
			type: db.Object,
			nested: true
		}
	});

	var hoursMinutesDefinition = {
		hours: {
			label: _("Hours"),
			type: UInteger,
			max: 23
		},
		minutes: {
			label: _("Minutes"),
			type: UInteger,
			max: 59,
			value: 0
		}
	};

	globalPrimitives.workingHours.start.defineProperties(hoursMinutesDefinition);
	globalPrimitives.workingHours.end.defineProperties(hoursMinutesDefinition);

	globalPrimitives.workingHours.start.hours = 9;
	globalPrimitives.workingHours.end.hours   = 17;

	return globalPrimitives;
}, { normalizer: require('memoizee/normalizers/get-1')() });
<|endoftext|>


<commit_before>// ==UserScript==
// @name          fcpn.ch
// @author        Lenny. (@ohitsLenny)
// @namespace     fcpn.ch
// @description   This will add a buton to shorten and copy links
// @include       *facepunch.com/showthread*
// @require       jquery.js
// @resource      fpnchcss fcpnch.css
// @version       1.0
// ==/UserScript==

var myCss = GM_getResourceText("fpnchcss");
GM_addStyle(myCss);

function getThreadID() {
	var re = /t=\w+/g;

	return $(location).attr("href").match(re)[0].slice(2)
};
var threadID = Number(getThreadID());

var lookUp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
function base62(n, b) {
	var res = []
	do {
		var idk = n % b;
		res.unshift(lookUp.charAt(idk))
		n = Math.floor(n / b)
	} while (n > 0);
	return res.join("");
}

var shortThreadID = base62(threadID, 62);

var shortner = document.createElement("a");
shortner.innerHTML = "shortn";
shortner.className = "fcpnchBtn"

$(".nodecontrols").prepend(shortner);

$(".fcpnchBtn").click(function(event) {
	var postID = $(this).next()[0].name;
	postID = Number(postID.replace("post", ""));

	var shortPostID = base62(postID, 62);

	var toCopy = "http://fcpn.ch/" + shortThreadID + "/" + shortPostID;
	GM_setClipboard(toCopy);
});<commit_msg>update usrscrpt to even shorta<commit_after>// ==UserScript==
// @name          fcpn.ch
// @author        Lenny. (@ohitsLenny)
// @namespace     fcpn.ch
// @description   This will add a buton to shorten and copy links
// @include       *facepunch.com/showthread*
// @require       jquery.js
// @resource      fpnchcss fcpnch.css
// @version       1.0
// ==/UserScript==

var myCss = GM_getResourceText("fpnchcss");
GM_addStyle(myCss);

var lookUp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
function base62(n, b) {
	var res = []
	do {
		var idk = n % b;
		res.unshift(lookUp.charAt(idk))
		n = Math.floor(n / b)
	} while (n > 0);
	return res.join("");
}

var shortner = document.createElement("a");
shortner.innerHTML = "shortn";
shortner.className = "fcpnchBtn"

$(".nodecontrols").prepend(shortner);

$(".fcpnchBtn").click(function(event) {
	var postID = $(this).next()[0].name;
	postID = Number(postID.replace("post", ""));

	var shortPostID = base62(postID, 62);

	var toCopy = "http://fcpn.ch/" + shortPostID;
	GM_setClipboard(toCopy);
});<|endoftext|>


<commit_before>/**
 * @author Pedro Sanders
 * @since v1
 *
 * Unit Test for the "Fonoster Resources Module"
 */
import RedisDataSource from 'data_api/redis_datasource'
import AgentsAPI from 'data_api/agents_api'
import { Status } from 'data_api/status'
import getConfig from 'core/config_util.js'

const ObjectId = Packages.org.bson.types.ObjectId

export let testGroup = { name: "Redis Data Source", enabled: false }

const config = getConfig()
// To force RedisDataSource to use its own default parameters...
delete config.spec.dataSource.parameters

const ds = new RedisDataSource(config)
const agentsApi = new AgentsAPI(ds)

testGroup.basic_operations = function () {
    let agent = {
        apiVersion: 'v1.0',
        kind: "Agent",
        metadata: {
            name: "John Doe"
        },
        spec: {
            domains: ['sip.local'],
            credentials: {
                username: '1001',
                secret: 'secret'
            }
        }
    }

    const initSize = ds.withCollection('agents').find().result.length
    const response = ds.insert(agent)
    let endSize = ds.withCollection('agents').find().result.length

    assertTrue(ObjectId.isValid(response.result))
    assertTrue(endSize == (initSize + 1))
    assertTrue(agent.metadata.name.equals("John Doe"))

    ds.withCollection('agents').remove(response.result)
    endSize = ds.withCollection('agents').find().result.length
    assertTrue (initSize == endSize)
}

testGroup.get_collections = function () {
    let agent = {
        apiVersion: 'v1.0',
        kind: "Agent",
        metadata: {
            name: "John Doe"
        },
        spec: {
            domains: ['sip.local'],
            credentials: {
                username: '1001',
                secret: 'secret'
            }
        }
    }

    const initSize = ds.withCollection('agents').find().result.length
    const ref = ds.insert(agent).result

    // Existing Agent
    let response = ds.withCollection('agents').find("@.spec.credentials.username==1001")
    assertTrue(response.status == Status.OK)

    // Non-Existing Agent
    response = ds.withCollection('agents').find("@.spec.credentials.username=='peter'")
    assertTrue(response.result.length == 0)

    // Invalid filter
    response = ds.withCollection('agents').find("@.spec.credentials.username==mike'")
    assertTrue(response.status == Status.BAD_REQUEST)

    ds.withCollection('agents').remove(ref)
    const endSize = ds.withCollection('agents').find().result.length
    assertTrue:(initSize == endSize)
}

// This also validates the other resources
testGroup.get_agents = function () {
    let john = {
        apiVersion: 'v1.0',
        kind: "Agent",
        metadata: {
            name: "John Doe"
        },
        spec: {
            domains: ['sip.local'],
            credentials: {
                username: '1001',
                secret: 'secret'
            }
        }
    }

    let jane = {
        apiVersion: 'v1.0',
        kind: "Agent",
        metadata: {
            name: "Jane Doe"
        },
        spec: {
            domains: ['sip.local'],
            credentials: {
                username: '1002',
                secret: 'secret'
            }
        }
    }

    const ref1 = ds.insert(john).result
    const ref2 = ds.insert(jane).result

    const l = ds.withCollection('agents')
        .find("'sip.local' in @.spec.domains").result

    assertTrue(l.length == 2)

    // NOTE: The space will not work in the console because is considered another parameter
    const response = agentsApi.getAgents("@.spec.credentials.username=='1001' || @.spec.credentials.username=='1002'")

    assertTrue(response.status == Status.OK)
    assertTrue(response.result.length == 2)

    // Cleanup
    ds.withCollection('agents').remove(ref1)
    ds.withCollection('agents').remove(ref2)
}

// This also validates the other resources
testGroup.get_agent = function () {
    let agent = {
        apiVersion: 'v1.0',
        kind: "Agent",
        metadata: {
            name: "John Doe",
            ref: "ag3f77f6"
        },
        spec: {
            domains: ['sip.local'],
            credentials: {
                username: '1001',
                secret: 'secret'
            }
        }
    }

    const ref = ds.insert(agent).result
    const response = agentsApi.getAgent('ag3f77f6')
    assertTrue(response.status == Status.OK)
    assertTrue(response.result.kind == 'Agent')
    // Cleanup
    ds.withCollection('agents').remove(ref)
}
<commit_msg>Improved maintainability<commit_after>/**
 * @author Pedro Sanders
 * @since v1
 *
 * Unit Test for the "Fonoster Resources Module"
 */
import RedisDataSource from 'data_api/redis_datasource'
import AgentsAPI from 'data_api/agents_api'
import { Status } from 'data_api/status'
import getConfig from 'core/config_util.js'

const ObjectId = Packages.org.bson.types.ObjectId

export let testGroup = { name: "Redis Data Source", enabled: true }

const config = getConfig()
// To force RedisDataSource to use its own default parameters...
delete config.spec.dataSource.parameters

const ds = new RedisDataSource(config)
const agentsApi = new AgentsAPI(ds)

function buildAgent(name, domains, username, secret = '1234') {
    const agent = {
        apiVersion: 'v1.0',
        kind: 'Agent',
        metadata: {
            name: name
        },
        spec: {
            domains: domains,
            credentials: {
                username: username,
                secret: secret
            }
        }
    }
    return agent
}

testGroup.basic_operations = function () {
    const agent = buildAgent('John Doe', ['sip.local'], '1001')

    const initSize = ds.withCollection('agents').find().result.length
    const response = ds.insert(agent)
    let endSize = ds.withCollection('agents').find().result.length

    assertTrue(ObjectId.isValid(response.result))
    assertTrue(endSize == (initSize + 1))
    assertTrue(agent.metadata.name.equals('John Doe'))

    ds.withCollection('agents').remove(response.result)
    endSize = ds.withCollection('agents').find().result.length
    assertTrue (initSize == endSize)
}

testGroup.get_collections = function () {
    const agent = buildAgent('John Doe', ['sip.local'], '1001')
    const initSize = ds.withCollection('agents').find().result.length
    const ref = ds.insert(agent).result

    // Existing Agent
    let response = ds.withCollection('agents').find("@.spec.credentials.username==1001")
    assertTrue(response.status == Status.OK)

    // Non-Existing Agent
    response = ds.withCollection('agents').find("@.spec.credentials.username=='peter'")
    assertTrue(response.result.length == 0)

    // Invalid filter
    response = ds.withCollection('agents').find("@.spec.credentials.username==mike'")
    assertTrue(response.status == Status.BAD_REQUEST)

    ds.withCollection('agents').remove(ref)
    const endSize = ds.withCollection('agents').find().result.length
    assertTrue:(initSize == endSize)
}

// This also validates the other resources
testGroup.get_agents = function () {
    const john = buildAgent('John Doe', ['sip.local'], '1001')
    const jane = buildAgent('Jane Doe', ['sip.local'], '1002')

    const ref1 = ds.insert(john).result
    const ref2 = ds.insert(jane).result

    const l = ds.withCollection('agents')
        .find("'sip.local' in @.spec.domains").result

    assertTrue(l.length == 2)

    // NOTE: The space will not work in the console because is considered another parameter
    const response = agentsApi.getAgents("@.spec.credentials.username=='1001' || @.spec.credentials.username=='1002'")

    assertTrue(response.status == Status.OK)
    assertTrue(response.result.length == 2)

    // Cleanup
    ds.withCollection('agents').remove(ref1)
    ds.withCollection('agents').remove(ref2)
}

// This also validates the other resources
testGroup.get_agent = function () {
    const agent = buildAgent('John Doe', ['sip.local'], '1001')
    agent.ref = 'ag3f77f6'
    const ref = ds.insert(agent).result
    const response = agentsApi.getAgent('ag3f77f6')
    //assertTrue(response.status == Status.OK)
    //assertTrue(response.result.kind == 'Agent')
    // Cleanup
    ds.withCollection('agents').remove(ref)
}
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var Base = require('./base')
  , utils = require('../utils')
  , Progress = require('../browser/progress')
  , escape = utils.escape;

/**
 * Save timer references to avoid Sinon interfering (see GH-237).
 */

var Date = global.Date
  , setTimeout = global.setTimeout
  , setInterval = global.setInterval
  , clearTimeout = global.clearTimeout
  , clearInterval = global.clearInterval;

/**
 * Expose `HTML`.
 */

exports = module.exports = HTML;

/**
 * Stats template.
 */

var statsTemplate = '
'
  + '
<canvas width="40" height="40"></canvas>
'
  + '
passes: 0
'
  + '
failures: 0
'
  + '
duration: 0s
'
  + '
';

/**
 * Initialize a new `HTML` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function HTML(runner) {
  Base.call(this, runner);

  var self = this
    , stats = this.stats
    , total = runner.total
    , stat = fragment(statsTemplate)
    , items = stat.getElementsByTagName('li')
    , passes = items[1].getElementsByTagName('em')[0]
    , passesLink = items[1].getElementsByTagName('a')[0]
    , failures = items[2].getElementsByTagName('em')[0]
    , failuresLink = items[2].getElementsByTagName('a')[0]
    , duration = items[3].getElementsByTagName('em')[0]
    , canvas = stat.getElementsByTagName('canvas')[0]
    , report = fragment('

')
    , stack = [report]
    , progress
    , ctx
    , root = document.getElementById('mocha');

  if (canvas.getContext) {
    var ratio = window.devicePixelRatio || 1;
    canvas.style.width = canvas.width;
    canvas.style.height = canvas.height;
    canvas.width *= ratio;
    canvas.height *= ratio;
    ctx = canvas.getContext('2d');
    ctx.scale(ratio, ratio);
    progress = new Progress;
  }

  if (!root) return error('#mocha div missing, add it to your document');

  // pass toggle
  on(passesLink, 'click', function(){
    unhide();
    var name = /pass/.test(report.className) ? '' : ' pass';
    report.className = report.className.replace(/fail|pass/g, '') + name;
    if (report.className.trim()) hideSuitesWithout('test pass');
  });

  // failure toggle
  on(failuresLink, 'click', function(){
    unhide();
    var name = /fail/.test(report.className) ? '' : ' fail';
    report.className = report.className.replace(/fail|pass/g, '') + name;
    if (report.className.trim()) hideSuitesWithout('test fail');
  });

  root.appendChild(stat);
  root.appendChild(report);

  if (progress) progress.size(40);

  runner.on('suite', function(suite){
    if (suite.root) return;

    // suite
    var url = self.suiteURL(suite);
    var el = fragment('

%s

', url, escape(suite.title));

    // container
    stack[0].appendChild(el);
    stack.unshift(document.createElement('ul'));
    el.appendChild(stack[0]);
  });

  runner.on('suite end', function(suite){
    if (suite.root) return;
    stack.shift();
  });

  runner.on('fail', function(test, err){
    if ('hook' == test.type) runner.emit('test end', test);
  });

  runner.on('test end', function(test){
    // TODO: add to stats
    var percent = stats.tests / this.total * 100 | 0;
    if (progress) progress.update(percent).draw(ctx);

    // update stats
    var ms = new Date - stats.start;
    text(passes, stats.passes);
    text(failures, stats.failures);
    text(duration, (ms / 1000).toFixed(2));

    // test
    if ('passed' == test.state) {
      var url = self.testURL(test);
      var el = fragment('

%e%ems ‣

', test.speed, test.title, test.duration, url);
    } else if (test.pending) {
      var el = fragment('

%e

', test.title);
    } else {
      var el = fragment('

%e ‣

', test.title, self.testURL(test));
      var str = test.err.stack || test.err.toString();

      // FF / Opera do not add the message
      if (!~str.indexOf(test.err.message)) {
        str = test.err.message + '\n' + str;
      }

      // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
      // check for the result of the stringifying.
      if ('[object Error]' == str) str = test.err.message;

      // Safari doesn't give you a stack. Let's at least provide a source line.
      if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
        str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
      }

      el.appendChild(fragment('
%e
', str));
    }

    // toggle code
    // TODO: defer
    if (!test.pending) {
      var h2 = el.getElementsByTagName('h2')[0];

      on(h2, 'click', function(){
        pre.style.display = 'none' == pre.style.display
          ? 'block'
          : 'none';
      });

      var pre = fragment('
%e
', utils.clean(test.fn.toString()));
      el.appendChild(pre);
      pre.style.display = 'none';
    }

    // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack.
    if (stack[0]) stack[0].appendChild(el);
  });
}

/**
 * Makes a URL, preserving querystring ("search") parameters.
 * @param {string} s
 * @returns {string} your new URL
 */
var makeUrl = function makeUrl(s) {
  var search = window.location.search;

  // Remove previous grep query parameter if present
  if (search) {
    search = search.replace(/[?&]grep=[^&\s]*/g, '').replace(/^&/, '?');
  }

  return window.location.pathname + (search ? search + '&' : '?' ) + 'grep=' + encodeURIComponent(s);
};

/**
 * Provide suite URL
 *
 * @param {Object} [suite]
 */
HTML.prototype.suiteURL = function(suite){
  return makeUrl(suite.fullTitle());
};

/**
 * Provide test URL
 *
 * @param {Object} [test]
 */

HTML.prototype.testURL = function(test){
  return makeUrl(test.fullTitle());
};

/**
 * Display error `msg`.
 */

function error(msg) {
  document.body.appendChild(fragment('
%s
', msg));
}

/**
 * Return a DOM fragment from `html`.
 */

function fragment(html) {
  var args = arguments
    , div = document.createElement('div')
    , i = 1;

  div.innerHTML = html.replace(/%([se])/g, function(_, type){
    switch (type) {
      case 's': return String(args[i++]);
      case 'e': return escape(args[i++]);
    }
  });

  return div.firstChild;
}

/**
 * Check for suites that do not have elements
 * with `classname`, and hide them.
 */

function hideSuitesWithout(classname) {
  var suites = document.getElementsByClassName('suite');
  for (var i = 0; i < suites.length; i++) {
    var els = suites[i].getElementsByClassName(classname);
    if (0 == els.length) suites[i].className += ' hidden';
  }
}

/**
 * Unhide .hidden suites.
 */

function unhide() {
  var els = document.getElementsByClassName('suite hidden');
  for (var i = 0; i < els.length; ++i) {
    els[i].className = els[i].className.replace('suite hidden', 'suite');
  }
}

/**
 * Set `el` text to `str`.
 */

function text(el, str) {
  if (el.textContent) {
    el.textContent = str;
  } else {
    el.innerText = str;
  }
}

/**
 * Listen on `event` with callback `fn`.
 */

function on(el, event, fn) {
  if (el.addEventListener) {
    el.addEventListener(event, fn, false);
  } else {
    el.attachEvent('on' + event, fn);
  }
}
<commit_msg>Split message and stack into two separate variables<commit_after>/**
 * Module dependencies.
 */

var Base = require('./base')
  , utils = require('../utils')
  , Progress = require('../browser/progress')
  , escape = utils.escape;

/**
 * Save timer references to avoid Sinon interfering (see GH-237).
 */

var Date = global.Date
  , setTimeout = global.setTimeout
  , setInterval = global.setInterval
  , clearTimeout = global.clearTimeout
  , clearInterval = global.clearInterval;

/**
 * Expose `HTML`.
 */

exports = module.exports = HTML;

/**
 * Stats template.
 */

var statsTemplate = '
'
  + '
<canvas width="40" height="40"></canvas>
'
  + '
passes: 0
'
  + '
failures: 0
'
  + '
duration: 0s
'
  + '
';

/**
 * Initialize a new `HTML` reporter.
 *
 * @param {Runner} runner
 * @api public
 */

function HTML(runner) {
  Base.call(this, runner);

  var self = this
    , stats = this.stats
    , total = runner.total
    , stat = fragment(statsTemplate)
    , items = stat.getElementsByTagName('li')
    , passes = items[1].getElementsByTagName('em')[0]
    , passesLink = items[1].getElementsByTagName('a')[0]
    , failures = items[2].getElementsByTagName('em')[0]
    , failuresLink = items[2].getElementsByTagName('a')[0]
    , duration = items[3].getElementsByTagName('em')[0]
    , canvas = stat.getElementsByTagName('canvas')[0]
    , report = fragment('

')
    , stack = [report]
    , progress
    , ctx
    , root = document.getElementById('mocha');

  if (canvas.getContext) {
    var ratio = window.devicePixelRatio || 1;
    canvas.style.width = canvas.width;
    canvas.style.height = canvas.height;
    canvas.width *= ratio;
    canvas.height *= ratio;
    ctx = canvas.getContext('2d');
    ctx.scale(ratio, ratio);
    progress = new Progress;
  }

  if (!root) return error('#mocha div missing, add it to your document');

  // pass toggle
  on(passesLink, 'click', function(){
    unhide();
    var name = /pass/.test(report.className) ? '' : ' pass';
    report.className = report.className.replace(/fail|pass/g, '') + name;
    if (report.className.trim()) hideSuitesWithout('test pass');
  });

  // failure toggle
  on(failuresLink, 'click', function(){
    unhide();
    var name = /fail/.test(report.className) ? '' : ' fail';
    report.className = report.className.replace(/fail|pass/g, '') + name;
    if (report.className.trim()) hideSuitesWithout('test fail');
  });

  root.appendChild(stat);
  root.appendChild(report);

  if (progress) progress.size(40);

  runner.on('suite', function(suite){
    if (suite.root) return;

    // suite
    var url = self.suiteURL(suite);
    var el = fragment('

%s

', url, escape(suite.title));

    // container
    stack[0].appendChild(el);
    stack.unshift(document.createElement('ul'));
    el.appendChild(stack[0]);
  });

  runner.on('suite end', function(suite){
    if (suite.root) return;
    stack.shift();
  });

  runner.on('fail', function(test, err){
    if ('hook' == test.type) runner.emit('test end', test);
  });

  runner.on('test end', function(test){
    // TODO: add to stats
    var percent = stats.tests / this.total * 100 | 0;
    if (progress) progress.update(percent).draw(ctx);

    // update stats
    var ms = new Date - stats.start;
    text(passes, stats.passes);
    text(failures, stats.failures);
    text(duration, (ms / 1000).toFixed(2));

    // test
    if ('passed' == test.state) {
      var url = self.testURL(test);
      var el = fragment('

%e%ems ‣

', test.speed, test.title, test.duration, url);
    } else if (test.pending) {
      var el = fragment('

%e

', test.title);
    } else {
      var el = fragment('

%e ‣

', test.title, self.testURL(test));
      var stackString, // Note: Includes leading newline
          message = test.err.toString();

      // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
      // check for the result of the stringifying.
      if ('[object Error]' === message) message = test.err.message;

      if (test.err.stack) {
        var indexOfMessage = test.err.stack.indexOf(test.err.message);
        if (indexOfMessage === -1) {
          stackString = test.err.stack;
        } else {
          stackString = test.err.stack.substr(test.err.message.length + indexOfMessage);
        }
      } else if (test.err.sourceURL && test.err.line !== undefined) {
        // Safari doesn't give you a stack. Let's at least provide a source line.
        stackString = "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
      }

      stackString = stackString || '';

      el.appendChild(fragment('
%e%e
', message, stackString));
    }

    // toggle code
    // TODO: defer
    if (!test.pending) {
      var h2 = el.getElementsByTagName('h2')[0];

      on(h2, 'click', function(){
        pre.style.display = 'none' == pre.style.display
          ? 'block'
          : 'none';
      });

      var pre = fragment('
%e
', utils.clean(test.fn.toString()));
      el.appendChild(pre);
      pre.style.display = 'none';
    }

    // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack.
    if (stack[0]) stack[0].appendChild(el);
  });
}

/**
 * Makes a URL, preserving querystring ("search") parameters.
 * @param {string} s
 * @returns {string} your new URL
 */
var makeUrl = function makeUrl(s) {
  var search = window.location.search;

  // Remove previous grep query parameter if present
  if (search) {
    search = search.replace(/[?&]grep=[^&\s]*/g, '').replace(/^&/, '?');
  }

  return window.location.pathname + (search ? search + '&' : '?' ) + 'grep=' + encodeURIComponent(s);
};

/**
 * Provide suite URL
 *
 * @param {Object} [suite]
 */
HTML.prototype.suiteURL = function(suite){
  return makeUrl(suite.fullTitle());
};

/**
 * Provide test URL
 *
 * @param {Object} [test]
 */

HTML.prototype.testURL = function(test){
  return makeUrl(test.fullTitle());
};

/**
 * Display error `msg`.
 */

function error(msg) {
  document.body.appendChild(fragment('
%s
', msg));
}

/**
 * Return a DOM fragment from `html`.
 */

function fragment(html) {
  var args = arguments
    , div = document.createElement('div')
    , i = 1;

  div.innerHTML = html.replace(/%([se])/g, function(_, type){
    switch (type) {
      case 's': return String(args[i++]);
      case 'e': return escape(args[i++]);
    }
  });

  return div.firstChild;
}

/**
 * Check for suites that do not have elements
 * with `classname`, and hide them.
 */

function hideSuitesWithout(classname) {
  var suites = document.getElementsByClassName('suite');
  for (var i = 0; i < suites.length; i++) {
    var els = suites[i].getElementsByClassName(classname);
    if (0 == els.length) suites[i].className += ' hidden';
  }
}

/**
 * Unhide .hidden suites.
 */

function unhide() {
  var els = document.getElementsByClassName('suite hidden');
  for (var i = 0; i < els.length; ++i) {
    els[i].className = els[i].className.replace('suite hidden', 'suite');
  }
}

/**
 * Set `el` text to `str`.
 */

function text(el, str) {
  if (el.textContent) {
    el.textContent = str;
  } else {
    el.innerText = str;
  }
}

/**
 * Listen on `event` with callback `fn`.
 */

function on(el, event, fn) {
  if (el.addEventListener) {
    el.addEventListener(event, fn, false);
  } else {
    el.attachEvent('on' + event, fn);
  }
}
<|endoftext|>