<commit_before>const controller = require("../_controller");

function WScriptShell() {
	this.environment = (x) => {
		if (x.toLowerCase() === "system")
			return (argument) => {
				argument = argument.toLowerCase();
				switch (argument) {
					case "comspec":
						return "%SystemRoot%\\system32\\cmd.exe";
					case "os":
						return "Windows_NT";
					case "processor_architecture":
						// Emulate a 32-bit environment for maximum compatibility
						return "x86";
					default:
						controller.kill(`Unknown parameter ${argument} for WScriptShell.Environment.System`);
				}
			};
		return `(Environment variable ${x})`;
	};
	this.specialfolders = (x) => `(Special folder ${x})`;
	this.createshortcut = () => ({});
	this.expandenvironmentstrings = (path) => {
		path = path.replace(/%TE?MP%/gi, "C:\\DOCUME~1\\MyUsername\\LOCALS~1\\Temp");
		path = path.replace(/%PROCESSOR_REVISION%/gi, "0209");

		// %APPDATA% equals C:\Documents and Settings\{username}\Application Data on Windows XP,
		// but C:\Users\{username}\AppData\Roaming on Win Vista and above
		if (process.argv.indexOf("--windows-xp") === -1)
			path = path.replace(/%APPDATA%/gi, "C:\\Documents and Settings\\MyUsername\\Application Data");
		else
			path = path.replace(/%APPDATA%/gi, "C:\\Users\\MyUsername\\AppData\\Roaming");
		return path;
	};
	this.exec = this.run = function(...args) {
		const command = args.join(" ");
		const filename = controller.getUUID();
		console.log(`Executing ${controller.directory + filename} in the WScript shell`);
		controller.logSnippet(filename, {as: "WScript code"}, command);
		if (process.argv.indexOf("--no-shell-error") === -1)
			throw new Error("If you can read this, re-run box.js with the --no-shell-error flag.");
	};
	this.regread = (key) => {
		key = key.toUpperCase();
		console.log(`Reading registry key ${key}`);
		switch (key) {
			case "HKEY_LOCAL_MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION\\CURRENTVERSION":
				return "5.1";
			case "HKLM\\SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION\\SYSTEMROOT":
				return "C:\\WINDOWS";
			default:
				console.log("Unknown registry key!");
				return;
		}
	};
	this.regwrite = (key, value, type = "(unspecified)") => console.log(`Setting registry key ${key} to ${value} of type ${type}`);
	this.popup = function(text, a, title = "[Untitled]", b) {
		if (process.argv.indexOf("--no-echo") === -1) {
			console.log(`Script opened a popup window: title "${title}", text "${text}"`);
			console.log("Add flag --no-echo to disable this.");
		}
		return true; // Emulates a click
	};
}

module.exports = function(name) {
	return new Proxy(new WScriptShell(name), {
		get: function(target, name) {
			name = name.toLowerCase();
			switch (name) {
				default:
					if (!(name in target)) {
						controller.kill(`WScriptShell.${name} not implemented!`);
					}
					return target[name];
			}
		},
		set: function(a, b, c) {
			b = b.toLowerCase();
			if (c.length < 1024)
				console.log(`WScriptShell[${b}] = ${c};`);
			a[b] = c;
			return true;
		},
	});
};
<commit_msg>Add %USERPROFILE% environment variable<commit_after>const controller = require("../_controller");

function WScriptShell() {
	this.environment = (x) => {
		if (x.toLowerCase() === "system")
			return (argument) => {
				argument = argument.toLowerCase();
				switch (argument) {
					case "comspec":
						return "%SystemRoot%\\system32\\cmd.exe";
					case "os":
						return "Windows_NT";
					case "processor_architecture":
						// Emulate a 32-bit environment for maximum compatibility
						return "x86";
					default:
						controller.kill(`Unknown parameter ${argument} for WScriptShell.Environment.System`);
				}
			};
		return `(Environment variable ${x})`;
	};
	this.specialfolders = (x) => `(Special folder ${x})`;
	this.createshortcut = () => ({});
	this.expandenvironmentstrings = (path) => {
		path = path.replace(/%TE?MP%/gi, "C:\\DOCUME~1\\MyUsername\\LOCALS~1\\Temp");
		path = path.replace(/%PROCESSOR_REVISION%/gi, "0209");
		path = path.replace(/%USERPROFILE%/gi, "C:\\Users\\MyUsername");

		// %APPDATA% equals C:\Documents and Settings\{username}\Application Data on Windows XP,
		// but C:\Users\{username}\AppData\Roaming on Win Vista and above
		if (process.argv.indexOf("--windows-xp") === -1)
			path = path.replace(/%APPDATA%/gi, "C:\\Documents and Settings\\MyUsername\\Application Data");
		else
			path = path.replace(/%APPDATA%/gi, "C:\\Users\\MyUsername\\AppData\\Roaming");
		return path;
	};
	this.exec = this.run = function(...args) {
		const command = args.join(" ");
		const filename = controller.getUUID();
		console.log(`Executing ${controller.directory + filename} in the WScript shell`);
		controller.logSnippet(filename, {as: "WScript code"}, command);
		if (process.argv.indexOf("--no-shell-error") === -1)
			throw new Error("If you can read this, re-run box.js with the --no-shell-error flag.");
	};
	this.regread = (key) => {
		key = key.toUpperCase();
		console.log(`Reading registry key ${key}`);
		switch (key) {
			case "HKEY_LOCAL_MACHINE\\SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION\\CURRENTVERSION":
				return "5.1";
			case "HKLM\\SOFTWARE\\MICROSOFT\\WINDOWS NT\\CURRENTVERSION\\SYSTEMROOT":
				return "C:\\WINDOWS";
			default:
				console.log("Unknown registry key!");
				return;
		}
	};
	this.regwrite = (key, value, type = "(unspecified)") => console.log(`Setting registry key ${key} to ${value} of type ${type}`);
	this.popup = function(text, a, title = "[Untitled]", b) {
		if (process.argv.indexOf("--no-echo") === -1) {
			console.log(`Script opened a popup window: title "${title}", text "${text}"`);
			console.log("Add flag --no-echo to disable this.");
		}
		return true; // Emulates a click
	};
}

module.exports = function(name) {
	return new Proxy(new WScriptShell(name), {
		get: function(target, name) {
			name = name.toLowerCase();
			switch (name) {
				default:
					if (!(name in target)) {
						controller.kill(`WScriptShell.${name} not implemented!`);
					}
					return target[name];
			}
		},
		set: function(a, b, c) {
			b = b.toLowerCase();
			if (c.length < 1024)
				console.log(`WScriptShell[${b}] = ${c};`);
			a[b] = c;
			return true;
		},
	});
};
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var nextTick = process.nextTick;

var Session = require('../lib/session');

function SessionStore(dir) {
    this.cache = {};
    this.dir = path.resolve(dir);
}

SessionStore.prototype.keys = function(done) {
    fs.readdir(this.dir, done);
};

SessionStore.prototype.hook = function(session) {
    var self = this;
    session.on('change', function() {
        self.save(session, function(err) {
            if (err) {
                console.error(
                    'failed to save changes to session %s: %s',
                    session.id, err);
            }
        });
    });
};

SessionStore.prototype.load = function(id, done) {
    var self = this;
    if (this.cache[id]) {
        return nextTick(function() {
            done(null, self.cache[id]);
        });
    }
    fs.readFile(path.join(this.dir, id), function(err, buf) {
        if (err) {
            if (err.code === 'ENOENT') err = null;
            return done(err, null);
        }
        var data = JSON.parse(String(buf)); // TODO safe parse
        var session = new Session(data);
        self.cache[session.id] = session;
        self.hook(session);
        done(null, session);
    });
};

SessionStore.prototype.save = function(session, done) {
    var self = this;
    mkdirp(self.dir, function(err) {
        if (err) return done(err, session);
        var data = JSON.stringify(session.getData(), null, 2);
        fs.writeFile(path.join(self.dir, session.id), data, function(err) {
            if (err) return done(err, session);
            if (self.cache[session.id] !== session) {
                self.hook(session);
                self.cache[session.id] = session;
            }
            done(err, session);
        });
    });
};

module.exports = SessionStore;
<commit_msg>SessionStore: parametize type<commit_after>var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var nextTick = process.nextTick;

function SessionStore(dir, sessionType) {
    this.cache = {};
    this.dir = path.resolve(dir);
    if (sessionType) this.sessionType = sessionType;
}

SessionStore.prototype.sessionType = require('../lib/session');

SessionStore.prototype.keys = function(done) {
    fs.readdir(this.dir, done);
};

SessionStore.prototype.hook = function(session) {
    var self = this;
    session.on('change', function() {
        self.save(session, function(err) {
            if (err) {
                console.error(
                    'failed to save changes to session %s: %s',
                    session.id, err);
            }
        });
    });
};

SessionStore.prototype.load = function(id, done) {
    var self = this;
    if (this.cache[id]) {
        return nextTick(function() {
            done(null, self.cache[id]);
        });
    }
    fs.readFile(path.join(this.dir, id), function(err, buf) {
        if (err) {
            if (err.code === 'ENOENT') err = null;
            return done(err, null);
        }
        var data = JSON.parse(String(buf)); // TODO safe parse
        var session = new self.sessionType(data);
        self.cache[session.id] = session;
        self.hook(session);
        done(null, session);
    });
};

SessionStore.prototype.save = function(session, done) {
    var self = this;
    mkdirp(self.dir, function(err) {
        if (err) return done(err, session);
        var data = JSON.stringify(session.getData(), null, 2);
        fs.writeFile(path.join(self.dir, session.id), data, function(err) {
            if (err) return done(err, session);
            if (self.cache[session.id] !== session) {
                self.hook(session);
                self.cache[session.id] = session;
            }
            done(err, session);
        });
    });
};

module.exports = SessionStore;
<|endoftext|>


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

/**
 *
 * Reverse Proxy Script using Node.js
 * ( https://github.com/woonsan/hippo7-rproxy-nodejs )
 *
 * Usage: `sudo node rproxy.js` will open 80 port.
 *        `node rproxy.js 8888` will open 8888 port.
 *        `node rproxy.js 8888 8443` will open 8888 port and 8443 ssl port.
 *
 */

/*============================================================*/
/* Reverse Proxy Server Default Options Configuration         */
/*------------------------------------------------------------*/

var defaultOptions = {
  xfwd: true, // add X-Forwarded-* headers
};

// SSL Key file paths; change those paths if you have those in other paths.
var ssl_private_key_path = './priv.pem';
var ssl_certificate_path = './cert.pem';

/*------------------------------------------------------------*/
/* URL Path Mappings Configuration for Reverse Proxy Targets  */
/*------------------------------------------------------------*/
// You can add edit mappings below!

var mappings = [
  {
    host: '*',
    pathregex: /^\/cms(\/|$)/,
    route: {
      target: 'http://localhost:8080'
    }
  },
  {
    host: '*',
    pathregex: /^\/site(\/|$)/,
    route: {
      target: 'http://localhost:8080'
    }
  },
  {
    host: '*',
    pathregex: /^/,
    pathreplace: '/site',
    route: {
      target: 'http://localhost:8080'
    }
  },
];

/*------------------------------------------------------------*/
/* End of Configuration                                       */
/*============================================================*/

// Normally you don't need to look into the detail below
// in most cases unless you want to debug. :-)

var colors = require('colors');

colors.setTheme({
  silly: 'rainbow',
  input: 'grey',
  verbose: 'cyan',
  prompt: 'grey',
  info: 'green',
  data: 'grey',
  help: 'cyan',
  warn: 'yellow',
  debug: 'blue',
  error: 'red'
});

/**************************************************************/
/* Internal Server Handling Code from here                    */
/*------------------------------------------------------------*/

// find out the port number command line argument
var port = 80;
if (process.argv[2]) {
  port = parseInt(process.argv[2]);
}

// build up the ssl options
var sslOptions = {};
var fs = require('fs');
if (fs.existsSync(ssl_private_key_path)) {
  sslOptions.key = fs.readFileSync(ssl_private_key_path, 'utf8');
} else {
  console.log(('SSL Disabled. SSL private key file does not exist: ' + ssl_private_key_path).warn);
}
if (fs.existsSync(ssl_certificate_path)) {
  sslOptions.cert = fs.readFileSync(ssl_certificate_path, 'utf8');
} else {
  console.log(('SSL Disabled. SSL certificate does not exist: ' + ssl_certificate_path).warn);
}

// let's start building proxy server from here

var http = require('http'),
    httpProxy = require('http-proxy');

//
// function to find a mapping by request path
//
var findMapping = function(req) {
  var host = req.headers['host'];
  for (var i in mappings) {
    var um = mappings[i];
    if (um.host && um.host != '*' && um.host != host) {
      continue;
    }
    if (um.pathregex && req.url.match(um.pathregex)) {
      return um;
    }
  }
  return null;
};

//
// Create a proxy server with custom application logic
//
var proxyServer = httpProxy.createProxyServer(defaultOptions);
proxyServer.on('error', function(error) {
  console.log('-',
              ('[' + new Date().toISOString() + ']').data,
              'ERROR'.warn,
              '-',
              '-'.data,
              ('[Gateway Error] ' + error).warn,
              ('503').error);
});
proxyServer.on('proxyReq', function(proxyReq, req, res, options) {
  var target = options.target;
  if (target) {
    if ((target.protocol == 'http' && target.port == '80') ||
        (target.protocol == 'https' && target.port == '443')) {
      proxyReq.setHeader('Host', target.hostname);
    } else {
      proxyReq.setHeader('Host', target.host);
    }
    target['targetHostHeaderValue'] = proxyReq.getHeader('Host');
    req.proxyAttrs['target'] = target;
  }
  if (req.proxyAttrs['proxyMapping'] && req.proxyAttrs['proxyMapping'].reqHeaders) {
    var headers = req.proxyAttrs['proxyMapping'].reqHeaders;
    for (var name in headers) {
      proxyReq.setHeader(name, headers[name]);
    }
  }
});
proxyServer.on('proxyRes', function(proxyRes, req, res, options) {
  //console.log('DEBUG'.debug, req);
  var location = proxyRes.headers['location'];
  if (location && req.proxyAttrs['target']) {
    var target = req.proxyAttrs['target'];
    if (location.indexOf(target.href) == 0) {
      var sourceBase = req.headers['x-forwarded-proto'] + '://' + req.headers['host'] + '/';
      location = sourceBase + location.substring(target.href.length);
      proxyRes.headers['location'] = location;
    }
  }
  console.log(req.headers['x-forwarded-for'],
              ('[' + new Date().toISOString() + ']').data,
              req.method.info,
              req.proxyAttrs['requestUrl'],
              ('HTTP/' + proxyRes.httpVersion).data,
              (req.proxyAttrs['target'].href + req.proxyAttrs['targetRequestUrl'].substring(1)),
              proxyRes.statusCode < 400 ? ('' + proxyRes.statusCode).info : ('' + proxyRes.statusCode).error);
});

//
// proxy handler
//
var proxyHandler = function(req, res) {
  req.proxyAttrs = {};
  var mapping = findMapping(req);
  if (!mapping) {
    res.writeHead(404);
    res.end();
    console.log('WARN'.warn, 'Mapping not found for '.info, req.url.data);
  } else {
    req.proxyAttrs['proxyMapping'] = mapping;
    var oldReqUrl = req.url;
    req.proxyAttrs['requestUrl'] = oldReqUrl;
    if (mapping.pathreplace) {
      req.url = oldReqUrl.replace(mapping.pathregex, mapping.pathreplace);
    }
    req.proxyAttrs['targetRequestUrl'] = req.url;
    proxyServer.web(req, res, mapping.route);
  }
};

//
// Create your custom server and just call `proxy.web()` to proxy
// a web request to the target passed in the options
// also you can use `proxy.ws()` to proxy a websockets request
//
http.createServer(proxyHandler).listen(port);
console.log('');
console.log(('Reverse Proxy Server started at port ' + port + ' ...').info);

// start another server at ssl port if configured
if (sslOptions.key && sslOptions.cert) {
  var sslPort = 443;
  if (process.argv[3]) {
    sslPort = parseInt(process.argv[3]);
  }
  // Create the HTTPS proxy server in front of an HTTP server
  httpProxy.createServer({
    target: {
      host: 'localhost',
      port: port
    },
    ssl: {
      key: sslOptions.key,
      cert: sslOptions.cert
    },
    xfwd: true
  }).listen(sslPort);
  console.log(('Reverse Proxy Server started at SSL port ' + sslPort + ' ...').info);
}

// print out the route mapping information
console.log('');
console.log('Route mappings are as follows:'.info);
console.log('***********************************************************'.info);
console.log(mappings);
console.log('***********************************************************'.info);
console.log('');
<commit_msg>Update rproxy.js<commit_after>/*
 * Copyright (c) 2013-2015
 *
 * Woonsan Ko
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE
 */

/**
 *
 * Reverse Proxy Script using Node.js
 * ( https://github.com/woonsan/hippo7-rproxy-nodejs )
 *
 * Usage: `sudo node rproxy.js` will open 80 port.
 *        `node rproxy.js 8888` will open 8888 port.
 *        `node rproxy.js 8888 8443` will open 8888 port and 8443 ssl port.
 *
 */

/*============================================================*/
/* Reverse Proxy Server Default Options Configuration         */
/*------------------------------------------------------------*/

var defaultOptions = {
  xfwd: true, // add X-Forwarded-* headers
};

// SSL Key file paths; change those paths if you have those in other paths.
var ssl_private_key_path = './priv.pem';
var ssl_certificate_path = './cert.pem';

/*------------------------------------------------------------*/
/* URL Path Mappings Configuration for Reverse Proxy Targets  */
/*------------------------------------------------------------*/
// You can add edit mappings below!

var mappings = [
  {
    host: '*',
    pathregex: /^\/cms(\/|$)/,
    route: {
      target: 'http://localhost:8080'
    }
  },
  {
    host: '*',
    pathregex: /^\/site(\/|$)/,
    route: {
      target: 'http://localhost:8080'
    }
  },
  {
    host: '*',
    pathregex: /^/,
    pathreplace: '/site',
    route: {
      target: 'http://localhost:8080'
    }
  },
];

/*------------------------------------------------------------*/
/* End of Configuration                                       */
/*============================================================*/

// Normally you don't need to look into the detail below
// in most cases unless you want to debug. :-)

var colors = require('colors');

colors.setTheme({
  silly: 'rainbow',
  input: 'grey',
  verbose: 'cyan',
  prompt: 'grey',
  info: 'green',
  data: 'grey',
  help: 'cyan',
  warn: 'yellow',
  debug: 'blue',
  error: 'red'
});

/**************************************************************/
/* Internal Server Handling Code from here                    */
/*------------------------------------------------------------*/

// find out the port number command line argument
var port = 80;
if (process.argv[2]) {
  port = parseInt(process.argv[2]);
}

// build up the ssl options
var sslOptions = {};
var fs = require('fs');
if (fs.existsSync(ssl_private_key_path)) {
  sslOptions.key = fs.readFileSync(ssl_private_key_path, 'utf8');
} else {
  console.log(('SSL Disabled. SSL private key file does not exist: ' + ssl_private_key_path).warn);
}
if (fs.existsSync(ssl_certificate_path)) {
  sslOptions.cert = fs.readFileSync(ssl_certificate_path, 'utf8');
} else {
  console.log(('SSL Disabled. SSL certificate does not exist: ' + ssl_certificate_path).warn);
}

// let's start building proxy server from here

var http = require('http'),
    httpProxy = require('http-proxy');

//
// function to find a mapping by request path
//
var findMapping = function(req) {
  var host = req.headers['host'];
  for (var i in mappings) {
    var um = mappings[i];
    if (um.host && um.host != '*' && um.host != host) {
      continue;
    }
    if (um.pathregex && req.url.match(um.pathregex)) {
      return um;
    }
  }
  return null;
};

//
// Create a proxy server with custom application logic
//
var proxyServer = httpProxy.createProxyServer(defaultOptions);
proxyServer.on('error', function(error) {
  console.log('-',
              ('[' + new Date().toISOString() + ']').data,
              'ERROR'.warn,
              '-',
              '-'.data,
              ('[Gateway Error] ' + error).warn,
              ('503').error);
});
proxyServer.on('proxyReq', function(proxyReq, req, res, options) {
  var target = options.target;
  if (target) {
    if ((target.protocol == 'http' && target.port == '80') ||
        (target.protocol == 'https' && target.port == '443')) {
      proxyReq.setHeader('Host', target.hostname);
    } else {
      proxyReq.setHeader('Host', target.host);
    }
    target['targetHostHeaderValue'] = proxyReq.getHeader('Host');
    req.proxyAttrs['target'] = target;
  }
  if (req.proxyAttrs['proxyMapping'] && req.proxyAttrs['proxyMapping'].reqHeaders) {
    var headers = req.proxyAttrs['proxyMapping'].reqHeaders;
    for (var name in headers) {
      proxyReq.setHeader(name, headers[name]);
    }
  }
});
proxyServer.on('proxyRes', function(proxyRes, req, res, options) {
  //console.log('DEBUG'.debug, req);
  var location = proxyRes.headers['location'];
  var isHttps = /^https/.test(req.headers['x-forwarded-proto']);
  var scheme = isHttps ? 'https' : 'http';
  if (location && req.proxyAttrs['target']) {
    var target = req.proxyAttrs['target'];
    if (location.indexOf(target.href) == 0) {
      var sourceBase = scheme + '://' + req.headers['host'] + '/';
      location = sourceBase + location.substring(target.href.length);
      proxyRes.headers['location'] = location;
    }
  }
  console.log(scheme,
              ('[' + new Date().toISOString() + ']').data,
              req.method.info,
              req.proxyAttrs['requestUrl'],
              ('HTTP/' + proxyRes.httpVersion).data,
              (req.proxyAttrs['target'].href + req.proxyAttrs['targetRequestUrl'].substring(1)),
              proxyRes.statusCode < 400 ? ('' + proxyRes.statusCode).info : ('' + proxyRes.statusCode).error);
});

//
// proxy handler
//
var proxyHandler = function(req, res) {
  req.proxyAttrs = {};
  var mapping = findMapping(req);
  if (!mapping) {
    res.writeHead(404);
    res.end();
    console.log('WARN'.warn, 'Mapping not found for '.info, req.url.data);
  } else {
    req.proxyAttrs['proxyMapping'] = mapping;
    var oldReqUrl = req.url;
    req.proxyAttrs['requestUrl'] = oldReqUrl;
    if (mapping.pathreplace) {
      req.url = oldReqUrl.replace(mapping.pathregex, mapping.pathreplace);
    }
    req.proxyAttrs['targetRequestUrl'] = req.url;
    proxyServer.web(req, res, mapping.route);
  }
};

//
// Create your custom server and just call `proxy.web()` to proxy
// a web request to the target passed in the options
// also you can use `proxy.ws()` to proxy a websockets request
//
http.createServer(proxyHandler).listen(port);
console.log('');
console.log(('Reverse Proxy Server started at port ' + port + ' ...').info);

// start another server at ssl port if configured
if (sslOptions.key && sslOptions.cert) {
  var sslPort = 443;
  if (process.argv[3]) {
    sslPort = parseInt(process.argv[3]);
  }
  // Create the HTTPS proxy server in front of an HTTP server
  httpProxy.createServer({
    target: {
      host: 'localhost',
      port: port
    },
    ssl: {
      key: sslOptions.key,
      cert: sslOptions.cert
    },
    xfwd: true
  }).listen(sslPort);
  console.log(('Reverse Proxy Server started at SSL port ' + sslPort + ' ...').info);
}

// print out the route mapping information
console.log('');
console.log('Route mappings are as follows:'.info);
console.log('***********************************************************'.info);
console.log(mappings);
console.log('***********************************************************'.info);
console.log('');
<|endoftext|>


<commit_before>import store from '../store'
const debug = {
  setLog (msg, type) {
    var bgColor = ''
    var color = ''
    type === 'warn' ? (
      bgColor = 'yellow',
      color = 'black'
    ) : type === 'error' ? (
      bgColor = 'red',
      color = 'white'
    ) : (
      bgColor = 'green',
      color = 'white'
    )
    if (store.state.debug) {
      if (msg === 'Navigation mode is forward' && store.actions.getHistoryLength() === 1) {
        console.groupCollapsed('%c Z ', 'background: gray; color:  white', 'Initial view') // eslint-disable-line no-console
      } else if (msg === 'Navigation mode is forward' && store.actions.getHistoryLength() >= 1) {
        console.groupCollapsed('%c Z ', 'background: gray; color:  white', 'Zoom-in to new view') // eslint-disable-line no-console
      } else if (msg === 'Navigation mode is backward') {
        console.groupCollapsed('%c Z ', 'background: gray; color:  white', 'Zoom-out to previous view') // eslint-disable-line no-console
      }
      console.log('%c z ', 'background: ' + bgColor + '; color:  ' + color + '', msg) // eslint-disable-line no-console
      if (msg === 'Navigation mode is iddle') console.groupEnd() // eslint-disable-line no-console
    }
  },
  getState () {
    return store.state.$data
  }
}
export default debug<commit_msg>Reduce complexity<commit_after>import store from '../store'
const debug = {
  setLog (msg, type) {
    var bgColor = ''
    var color = ''
    type === 'warn' ? (bgColor = 'yellow', color = 'black') : type === 'error' ? (bgColor = 'red', color = 'white') : ( bgColor = 'green', color = 'white')
    if (store.state.debug && msg === 'Navigation mode is forward' && store.actions.getHistoryLength() === 1) {
      console.groupCollapsed('%c Z ', 'background: gray; color:  white', 'Initial view') // eslint-disable-line no-console
    } else if (store.state.debug && msg === 'Navigation mode is forward' && store.actions.getHistoryLength() >= 1) {
      console.groupCollapsed('%c Z ', 'background: gray; color:  white', 'Zoom-in to new view') // eslint-disable-line no-console
    } else if (store.state.debug && msg === 'Navigation mode is backward') {
      console.groupCollapsed('%c Z ', 'background: gray; color:  white', 'Zoom-out to previous view') // eslint-disable-line no-console
    } else if (store.state.debug && msg === 'Navigation mode is iddle') {
      console.groupEnd() // eslint-disable-line no-console
    } else if (store.state.debug){
      console.log('%c z ', 'background: ' + bgColor + '; color:  ' + color + '', msg) // eslint-disable-line no-console
    }
  },
  getState () {
    return store.state.$data
  }
}
export default debug<|endoftext|>


<commit_before>import store from '../store'

const debug = {
  setLog (msg, type) {
    let bgColor = 'green'
    if (type === 'warn') {
      bgColor = 'yellow'
    } else if (type === 'error') {
      bgColor = 'red'
    }

    const color = (type === 'warn') ? 'black' : 'white'

    if (store.state.debug) {
      console.log('%c z ', 'background: ' + bgColor + '; color:  ' + color + '', msg) // eslint-disable-line no-console
    }
  }
}
export default debug
<commit_msg>fix: re add getState()<commit_after>import store from '../store'

const debug = {
  setLog (msg, type) {
    let bgColor = 'green'
    if (type === 'warn') {
      bgColor = 'yellow'
    } else if (type === 'error') {
      bgColor = 'red'
    }

    const color = (type === 'warn') ? 'black' : 'white'

    if (store.state.debug) {
      console.log('%c z ', 'background: ' + bgColor + '; color:  ' + color + '', msg) // eslint-disable-line no-console
    }
  },
  getState () {
    return store.state.$data
  }
}
export default debug
<|endoftext|>


<commit_before>/**
 * Directive for reusable waterfall chart
 */
angular.module('lcaApp.waterfall.directive', ['lcaApp.waterfall', 'lcaApp.format'])
    .directive('waterfallChart', ['WaterfallService', 'FormatService', function (WaterfallService, FormatService) {

        function link(scope, element, attrs) {
            var margin = {
                    top: 5,
                    right: 50,
                    bottom: 20,
                    left: 10
                },
                parentElement = element[0],
                yAxisWidth = 110,
                labelFormat = FormatService.format("^.2g"),// Format numbers with precision 2, centered
                svg = null,
                waterfall = null,   // Current waterfall instance
                segments,           // Waterfall segments for current scenario
                titleHeight = 0,    // Space for optional title
                unitHeight = 0;     // Space for optional unit

            /**
             * Initial preparation of svg element.
             */
            function createSvg() {
                svg = d3.select(parentElement).append("svg");
            }

            function prepareSvg() {
                svg.attr("width", waterfall.width() + yAxisWidth + margin.left + margin.right);
                svg.attr("height", waterfall.chartHeight + titleHeight + margin.top + margin.bottom + unitHeight);
                // Display does not refresh cleanly after d3 update, so delete and recreate the chart group
                svg.select(".chart-group").remove();
                svg.append("g")
                    .attr("class", "chart-group")
                    .attr("transform", "translate(" + (margin.left + yAxisWidth) + "," + (titleHeight + margin.top) + ")");
            }

            function addTitle() {
                svg.select(".chart-title").remove();
                if (scope.chartTitle) {
                    var width = waterfall.width();
                    svg.append("g")
                        .attr("class", "chart-title")
                        .attr("transform", "translate(" + (margin.left + yAxisWidth) + "," + (titleHeight + margin.top) + ")")
                        .append("text")
                        .attr("x", width / 2)
                        .attr("y", 0)
                        .attr("dy", "-1em")
                        .style("text-anchor", "middle")
                        .text(scope.chartTitle);
                }
            }

            function addTick( val, tickValues) {
                if ( tickValues.every( function (tv) {
                    return (Math.abs(waterfall.xScale(tv) - waterfall.xScale(val)) > 50 );
                }) ) {
                    tickValues.push(val);
                }
            }

            function drawXAxis() {
                var tickValues = [], maxTickVal;
                svg.select(".x.axis").remove();
                if (waterfall.chartHeight > 0) {
                    var xAxis = d3.svg.axis()
                            .scale(waterfall.xScale)
                            .orient("bottom"),
                        minVal = d3.min(segments, function (d) {
                            return d.endVal;
                        }),
                        maxVal = d3.max(segments, function (d) {
                            return d.endVal;
                        });
                    var lastVal = segments[segments.length-1].endVal;

                    if (minVal > 0) {
                        minVal = 0;
                    }
                    else if (maxVal < 0) {
                        maxVal = 0;
                    }
                    tickValues = [lastVal];
                    if (lastVal !== 0 ) {
                        addTick(0, tickValues);
                    }
                    if (maxVal !== 0) {
                        addTick(maxVal, tickValues);
                    }
                    if (minVal !== 0) {
                        addTick(minVal, tickValues);
                    }
                    maxTickVal = d3.max(tickValues);

                    xAxis.tickValues(tickValues)
                        .tickFormat(function (d) {
                            var formatted;
                            switch(d) {
                                case maxTickVal :
                                    formatted =  labelFormat(d) + " " + scope.unit;
                                    break;
                                case 0 :
                                    formatted = "0";
                                    break;
                                default :
                                    formatted = labelFormat(d);
                            }
                            return formatted;
                        });
                    svg.select(".chart-group")
                        .append("g")
                        .attr("class", "x axis")
                        .attr("transform", "translate(0," + waterfall.chartHeight + ")")
                        .call(xAxis);

                }
            }

            function wrap(text, width) {
                text.each(function () {
                    var text = d3.select(this),
                        words = text.text().split(/\s+/).reverse(),
                        word,
                        line = [],
                        lineNumber = 0,
                        lineHeight = 1.1, // ems
                        x = text.attr("x"),
                        y = text.attr("y"),
                        dy = parseFloat(text.attr("dy")),
                        tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", 0);
                    while (word = words.pop()) {
                        line.push(word);
                        tspan.text(line.join(" "));
                        if (tspan.node().getComputedTextLength() > width) {
                            line.pop();
                            tspan.text(line.join(" "));
                            line = [word];
                            tspan = text.append("tspan").attr("x", x).attr("y", y).text(word);
                            ++lineNumber;
                        }
                    }
                    if (lineNumber > 0) {
                        text.selectAll("tspan").attr("dy", function (d, i) {
                            return i * lineHeight - dy + "em";
                        });
                    }
                });
            }

            function drawYAxis() {
                svg.select(".y.axis").remove();
                if (waterfall.chartHeight > 0) {
                    var yAxis = d3.svg.axis()
                        .scale(waterfall.yScale)
                        .orient("left")
                        .tickSize(0);

                    svg.select(".chart-group")
                        .append("g")
                        .attr("class", "y axis")
                        .call(yAxis)
                        .selectAll(".tick text")
                        .call(wrap, yAxisWidth - 10);
                }
            }

            function drawWaterfall() {
                var chartGroup, barGroup,
                    lineColor = d3.rgb(scope.color).darker(2);

                chartGroup = svg.select(".chart-group");
                if (segments && segments.length > 0) {
                    // Draw bars
                    barGroup = chartGroup.selectAll(".bar.g")
                        .data(segments);
                    barGroup.enter().append("g")
                        .attr("class", "bar g");
                    barGroup.exit().remove();
                    barGroup.append("rect")
                        .attr("class", "bar rect")
                        .attr("height", waterfall.segmentHeight())
                        .attr("x", function (d) {
                            return d.x;
                        })
                        .attr("y", function (d) {
                            return d.y;
                        })
                        .attr("width", function (d) {
                            return d.width > 0 ? d.width : 0.1;
                        })
                        .style("fill", scope.color)
                        .style("stroke", lineColor);
                    // Label bars
                    barGroup.append("text")
                        .attr("class", "bar text")
                        .attr("x", function (d) {
                            return d.labelX;
                        })
                        .style("text-anchor", function (d) {
                            return d.labelAnchor;
                        })
                        .attr("y", function (d) {
                            return d.y + (waterfall.segmentHeight() / 2);
                        })
                        .attr("dy", ".5em")
                        .text(function (d) {
                            return labelFormat(d.value);
                        });
                    // Connect bars
                    barGroup.append("line")
                        .attr("class", "bar line")
                        .attr("x1", function (d) {
                            return d.endX;
                        })
                        .attr("y1", function (d) {
                            return d.y + waterfall.segmentHeight();
                        })
                        .attr("x2", function (d) {
                            return d.endX;
                        })
                        .attr("y2", function (d) {
                            return d.y + waterfall.segmentHeight() + waterfall.segmentPadding();
                        })
                        .style("stroke", lineColor);
                }
            }

            createSvg();
            scope.$watch("yAxisWidth", function (newVal) {
                if (newVal) {
                    yAxisWidth = +newVal;
                }
            });
            scope.$watch("chartTitle", function (newVal) {
                if (newVal) {
                    titleHeight = 20;
                }
            });
            scope.$watch("unit", function (newVal) {
                if (newVal) {
                    unitHeight = 20;
                }
            });
            scope.$watch('service', function (newVal) {
                if (newVal) {
                    waterfall = newVal;
                    segments = waterfall.segments[scope.index];
                    prepareSvg();
                    addTitle();
                    if (yAxisWidth > 0) {
                        drawYAxis();
                    }
                    drawWaterfall();
                    drawXAxis();
                }
            });
        }

        return {
            restrict: 'E',
            scope: { service: '=', index: '=', color: '=', yAxisWidth: '=', chartTitle: '=', unit: '='},
            link: link
        }
    }]);
<commit_msg>Vis: WIP on #171<commit_after>/**
 * Directive for reusable waterfall chart
 */
angular.module('lcaApp.waterfall.directive', ['lcaApp.waterfall', 'lcaApp.format'])
    .directive('waterfallChart', ['WaterfallService', 'FormatService', function (WaterfallService, FormatService) {

        function link(scope, element, attrs) {
            var margin = {
                    top: 5,
                    right: 50,
                    bottom: 20,
                    left: 10
                },
                parentElement = element[0],
                xAxisHeight = 21,
                yAxisWidth = 110,
                labelFormat = FormatService.format("^.2g"),// Format numbers with precision 2, centered
                svg = null,
                waterfall = null,   // Current waterfall instance
                segments,           // Waterfall segments for current scenario
                titleHeight = 0,    // Space for optional title
                unitHeight = 0;     // Space for optional unit

            /**
             * Initial preparation of svg element.
             */
            function createSvg() {
                svg = d3.select(parentElement).append("svg");
            }

            function prepareSvg() {
                svg.attr("width", waterfall.width() + yAxisWidth + margin.left + margin.right);
                svg.attr("height", waterfall.chartHeight + titleHeight + margin.top + margin.bottom + unitHeight
                                   + xAxisHeight);
                // Display does not refresh cleanly after d3 update, so delete and recreate the chart group
                svg.select(".chart-group").remove();
                svg.append("g")
                    .attr("class", "chart-group")
                    .attr("transform",
                    "translate(" + (margin.left + yAxisWidth) + "," + (titleHeight + margin.top + xAxisHeight) + ")");
            }

            function addTitle() {
                svg.select(".chart-title").remove();
                if (scope.chartTitle) {
                    var width = waterfall.width();
                    svg.append("g")
                        .attr("class", "chart-title")
                        .attr("transform", "translate(" + (margin.left + yAxisWidth) + "," + (titleHeight + margin.top) + ")")
                        .append("text")
                        .attr("x", width / 2)
                        .attr("y", 0)
                        .attr("dy", "-1em")
                        .style("text-anchor", "middle")
                        .text(scope.chartTitle);
                }
            }

            function addTick( val, tickValues) {
                if ( tickValues.every( function (tv) {
                    return (Math.abs(waterfall.xScale(tv) - waterfall.xScale(val)) > 50 );
                }) ) {
                    tickValues.push(val);
                }
            }

            function drawStartingLine() {
                //svg.select(".top.axis").remove();
                //if (waterfall.chartHeight > 0) {
                //    var xAxis = d3.svg.axis()
                //        .scale(waterfall.xScale)
                //        .orient("top")
                //        .tickValues([0]);
                //    svg.select(".chart-group")
                //        .append("g")
                //        .attr("class", "top axis")
                //        .call(xAxis);
                //}
                svg.select(".top.tick").remove();
                if (waterfall.chartHeight > 0) {

                    svg.select(".chart-group")
                        .append("g")
                        .attr("class", "top tick")
                        .append("line")
                        .attr("x2", 0)
                        .attr("y2", -6)
                        .append("text", "0")
                        .attr("dy", "0em")
                        .attr("y", -9)
                        .attr("x", 0)
                        .style("text-anchor", "middle")
                    ;
                }
            }

            function drawXAxis() {
                var tickValues = [], maxTickVal;
                svg.select(".x.axis").remove();
                if (waterfall.chartHeight > 0) {
                    var xAxis = d3.svg.axis()
                            .scale(waterfall.xScale)
                            .orient("bottom"),
                        minVal = d3.min(segments, function (d) {
                            return d.endVal;
                        }),
                        maxVal = d3.max(segments, function (d) {
                            return d.endVal;
                        });
                    var lastVal = segments[segments.length-1].endVal;

                    if (minVal > 0) {
                        minVal = 0;
                    }
                    else if (maxVal < 0) {
                        maxVal = 0;
                    }
                    tickValues = [lastVal];
                    if (lastVal !== 0 ) {
                        addTick(0, tickValues);
                    }
                    if (maxVal !== 0) {
                        addTick(maxVal, tickValues);
                    }
                    if (minVal !== 0) {
                        addTick(minVal, tickValues);
                    }
                    maxTickVal = d3.max(tickValues);

                    xAxis.tickValues(tickValues)
                        .tickFormat(function (d) {
                            var formatted;
                            switch(d) {
                                case maxTickVal :
                                    formatted =  labelFormat(d) + " " + scope.unit;
                                    break;
                                case 0 :
                                    formatted = "0";
                                    break;
                                default :
                                    formatted = labelFormat(d);
                            }
                            return formatted;
                        });
                    svg.select(".chart-group")
                        .append("g")
                        .attr("class", "x axis")
                        .attr("transform", "translate(0," + waterfall.chartHeight + ")")
                        .call(xAxis);

                }
            }

            function wrap(text, width) {
                text.each(function () {
                    var text = d3.select(this),
                        words = text.text().split(/\s+/).reverse(),
                        word,
                        line = [],
                        lineNumber = 0,
                        lineHeight = 1.1, // ems
                        x = text.attr("x"),
                        y = text.attr("y"),
                        dy = parseFloat(text.attr("dy")),
                        tspan = text.text(null).append("tspan").attr("x", x).attr("y", y).attr("dy", 0);
                    while (word = words.pop()) {
                        line.push(word);
                        tspan.text(line.join(" "));
                        if (tspan.node().getComputedTextLength() > width) {
                            line.pop();
                            tspan.text(line.join(" "));
                            line = [word];
                            tspan = text.append("tspan").attr("x", x).attr("y", y).text(word);
                            ++lineNumber;
                        }
                    }
                    if (lineNumber > 0) {
                        text.selectAll("tspan").attr("dy", function (d, i) {
                            return i * lineHeight - dy + "em";
                        });
                    }
                });
            }

            function drawYAxis() {
                svg.select(".y.axis").remove();
                if (waterfall.chartHeight > 0) {
                    var yAxis = d3.svg.axis()
                        .scale(waterfall.yScale)
                        .orient("left")
                        .tickSize(0);

                    svg.select(".chart-group")
                        .append("g")
                        .attr("class", "y axis")
                        .call(yAxis)
                        .selectAll(".tick text")
                        .call(wrap, yAxisWidth - 10);
                }
            }

            function drawWaterfall() {
                var chartGroup, barGroup,
                    lineColor = d3.rgb(scope.color).darker(2);

                chartGroup = svg.select(".chart-group");
                if (segments && segments.length > 0) {

                    // Draw bars
                    barGroup = chartGroup.selectAll(".bar.g")
                        .data(segments);
                    barGroup.enter().append("g")
                        .attr("class", "bar g");
                    barGroup.exit().remove();
                    barGroup.append("rect")
                        .attr("class", "bar rect")
                        .attr("height", waterfall.segmentHeight())
                        .attr("x", function (d) {
                            return d.x;
                        })
                        .attr("y", function (d) {
                            return d.y;
                        })
                        .attr("width", function (d) {
                            return d.width > 0 ? d.width : 0.1;
                        })
                        .style("fill", scope.color)
                        .style("stroke", lineColor);
                    // Label bars
                    barGroup.append("text")
                        .attr("class", "bar text")
                        .attr("x", function (d) {
                            return d.labelX;
                        })
                        .style("text-anchor", function (d) {
                            return d.labelAnchor;
                        })
                        .attr("y", function (d) {
                            return d.y + (waterfall.segmentHeight() / 2);
                        })
                        .attr("dy", ".5em")
                        .text(function (d) {
                            return labelFormat(d.value);
                        });
                    // Connect bars
                    barGroup.append("line")
                        .attr("class", "bar line")
                        .attr("x1", function (d) {
                            return d.endX;
                        })
                        .attr("y1", function (d) {
                            return d.y + waterfall.segmentHeight();
                        })
                        .attr("x2", function (d) {
                            return d.endX;
                        })
                        .attr("y2", function (d) {
                            return d.y + waterfall.segmentHeight() + waterfall.segmentPadding();
                        })
                        .style("stroke", lineColor);
                }
            }

            createSvg();
            scope.$watch("yAxisWidth", function (newVal) {
                if (newVal) {
                    yAxisWidth = +newVal;
                }
            });
            scope.$watch("chartTitle", function (newVal) {
                if (newVal) {
                    titleHeight = 20;
                }
            });
            scope.$watch("unit", function (newVal) {
                if (newVal) {
                    unitHeight = 20;
                }
            });
            scope.$watch('service', function (newVal) {
                if (newVal) {
                    waterfall = newVal;
                    segments = waterfall.segments[scope.index];
                    prepareSvg();
                    addTitle();
                    drawStartingLine();
                    if (yAxisWidth > 0) {
                        drawYAxis();
                    }
                    drawWaterfall();
                    drawXAxis();
                }
            });
        }

        return {
            restrict: 'E',
            scope: { service: '=', index: '=', color: '=', yAxisWidth: '=', chartTitle: '=', unit: '='},
            link: link
        }
    }]);
<|endoftext|>


<commit_before>import { createSelector } from 'reselect';
import isEmpty from 'lodash/isEmpty';
import uniqBy from 'lodash/uniqBy';
import groupBy from 'lodash/groupBy';
import intersection from 'lodash/intersection';
import { CALCULATION_OPTIONS } from 'app/data/constants';

import {
  getYColumnValue,
  getThemeConfig,
  getTooltipConfig,
  sortEmissionsByValue,
  sortLabelByAlpha,
  getColorPalette
} from 'utils/graphs';

// constants needed for data parsing
const DATA_SCALE = 1000000;

const BASE_COLORS = ['#25597C', '#DFE9ED'];

const AXES_CONFIG = {
  xBottom: {
    name: 'Year',
    unit: 'date',
    format: 'YYYY'
  },
  yLeft: {
    name: 'Emissions',
    unit: 'CO2e',
    format: 'number'
  }
};

const INCLUDED_SECTORS = {
  CAIT: [
    'Energy',
    'Industrial Processes',
    'Agriculture',
    'Waste',
    'Bunker Fuels'
  ],
  PIK: [
    'Energy',
    'Agriculture',
    'Waste',
    'Solvent sector',
    'Industrial process',
    'Other'
  ],
  UNFCCC: [
    'Energy',
    'Industrial Processes',
    'Solvent and Other Product Use',
    'Agriculture',
    'Waste',
    'Other'
  ]
};

const calculationKeys = Object.keys(CALCULATION_OPTIONS);
const options = calculationKeys.map(
  calculationKey => CALCULATION_OPTIONS[calculationKey]
);

// meta data for selectors
const getMeta = state => state.meta || {};
const getCalculationData = state =>
  (state.calculationData && state.calculationData[state.iso]) || [];

// values from search
const getSourceSelection = state => state.search.source || null;
const getCalculationSelection = state => state.search.calculation || null;
const getVersionSelection = state => state.search.version || null;
const getFilterSelection = state => state.search.filter || null;

// data for the graph
const getData = state => state.data || [];

// Sources selectors
export const getSources = createSelector(
  getMeta,
  meta => meta.data_source || null
);
export const getVersions = createSelector(getMeta, meta => meta.gwp || null);

export const getSourceOptions = createSelector(getSources, sources => {
  if (!sources) return [];
  return sources.map(d => ({
    label: d.label,
    value: d.value,
    source: d.source
  }));
});

const parseCalculationData = createSelector([getCalculationData], data => {
  if (!data || !data.length) return null;
  return groupBy(data, 'year');
});

export const getCalculationOptions = createSelector(
  parseCalculationData,
  calculationData => {
    if (!calculationData) return [];
    return options;
  }
);

export const getSourceSelected = createSelector(
  [getSourceOptions, getSourceSelection],
  (sources, selected) => {
    if (!sources || !sources.length) return {};
    if (!selected) return sources[0];
    return sources.find(category => category.value === parseInt(selected, 10));
  }
);

export const getCalculationSelected = createSelector(
  [getCalculationSelection],
  selected => {
    if (!selected) return options[0];
    return options.find(calculation => calculation.value === selected);
  }
);

// Versions selectors
export const getVersionOptions = createSelector(
  [getVersions, getSources, getSourceSelected],
  (versions, sources, sourceSelected) => {
    if (!sourceSelected || !versions) return [];
    const sourceData = sources.find(d => sourceSelected.value === d.value);
    return versions.filter(filter => sourceData.gwp.indexOf(filter.value) > -1);
  }
);

export const getVersionSelected = createSelector(
  [getVersionOptions, getVersionSelection],
  (versions, selected) => {
    if (!versions || !versions.length) return {};
    if (!selected) return versions[0];
    return versions.find(version => version.value === parseInt(selected, 10));
  }
);

// Filters selector
export const getFilterOptions = createSelector(
  [getMeta, getSourceSelected],
  (meta, sourceSelected) => {
    if (!sourceSelected || isEmpty(meta)) return [];
    const activeSourceData = meta.data_source.find(
      source => source.value === sourceSelected.value
    );
    const activeFilterKeys = activeSourceData.sector;
    const filteredSelected = meta.sector.filter(
      filter => activeFilterKeys.indexOf(filter.value) > -1
    );
    return sortLabelByAlpha(filteredSelected);
  }
);

export const getFiltersSelected = createSelector(
  [getFilterOptions, getFilterSelection],
  (filters, selected) => {
    if (!filters || !filters.length) return [];
    if (!selected) return filters;
    let selectedFilters = [];
    const selectedValues = selected.split(',');
    const selectedValuesNum = selectedValues.map(d => parseInt(d, 10));
    selectedFilters = filters.filter(
      filter => selectedValuesNum.indexOf(filter.value) > -1
    );
    return selectedFilters;
  }
);

// get selector defaults
export const getSelectorDefaults = createSelector(
  [getSources, getSourceSelected],
  (sources, sourceSelected) => {
    if (!sources || !sources.length || !sourceSelected) return {};
    const sourceData = sources.find(d => d.value === sourceSelected.value);
    return {
      sector: sourceData.sector[0],
      gas: sourceData.gas[0],
      source: sources[0].value
    };
  }
);

// Map the data from the API
export const filterData = createSelector(
  [getData, getSourceSelected],
  (data, sourceSelected) => {
    if (!data || !data.length) return [];
    return sortEmissionsByValue(
      data.filter(
        d =>
          INCLUDED_SECTORS[sourceSelected.label].indexOf(d.sector.trim()) >= 0
      )
    );
  }
);

const calculatedRatio = (selected, calculationData, x) => {
  if (selected === CALCULATION_OPTIONS.PER_GDP.value) {
    return calculationData[x][0].gdp;
  }
  if (selected === CALCULATION_OPTIONS.PER_CAPITA.value) {
    return calculationData[x][0].population;
  }
  return 1;
};

export const getChartData = createSelector(
  [
    filterData,
    getFiltersSelected,
    parseCalculationData,
    getCalculationSelected
  ],
  (data, filters, calculationData, calculationSelected) => {
    if (
      !data ||
      !data.length ||
      !filters ||
      !calculationData ||
      !calculationSelected
    ) {
      return [];
    }

    let xValues = [];
    xValues = data[0].emissions.map(d => d.year);
    if (
      calculationSelected.value !== CALCULATION_OPTIONS.ABSOLUTE_VALUE.value
    ) {
      xValues = intersection(
        xValues,
        Object.keys(calculationData).map(y => parseInt(y, 10))
      );
    }

    const dataParsed = xValues.map(x => {
      const yItems = {};
      data.forEach(d => {
        const yKey = getYColumnValue(d.sector);
        const yData = d.emissions.find(e => e.year === x);
        const calculationRatio = calculatedRatio(
          calculationSelected.value,
          calculationData,
          x
        );
        const scaledYData = yData.value * DATA_SCALE;
        yItems[yKey] = scaledYData / calculationRatio;
      });
      const item = {
        x,
        ...yItems
      };
      return item;
    });
    return dataParsed;
  }
);

export const getChartConfig = createSelector(
  [filterData, getCalculationSelected],
  (data, calculationSelected) => {
    if (!data || !data.length) return {};
    const yColumns = data.map(d => ({
      label: d.sector,
      value: getYColumnValue(d.sector)
    }));
    const yColumnsChecked = uniqBy(yColumns, 'value');
    const theme = getThemeConfig(
      yColumnsChecked,
      getColorPalette(BASE_COLORS, yColumnsChecked.length)
    );
    const tooltip = getTooltipConfig(yColumnsChecked);
    let unit = AXES_CONFIG.yLeft.unit;
    if (calculationSelected.value === CALCULATION_OPTIONS.PER_GDP.value) {
      unit = `${unit}  per $`;
    } else if (
      calculationSelected.value === CALCULATION_OPTIONS.PER_CAPITA.value
    ) {
      unit = `${unit}  per capita`;
    }
    const axes = {
      ...AXES_CONFIG,
      yLeft: {
        ...AXES_CONFIG.yLeft,
        unit
      }
    };
    return {
      axes,
      theme,
      tooltip,
      columns: {
        x: [{ label: 'year', value: 'x' }],
        y: yColumnsChecked
      }
    };
  }
);

export default {
  getSourceOptions,
  getSourceSelected,
  getFilterOptions,
  getFiltersSelected,
  getCalculationData
};
<commit_msg>Small changes to the tooltip units<commit_after>import { createSelector } from 'reselect';
import isEmpty from 'lodash/isEmpty';
import uniqBy from 'lodash/uniqBy';
import groupBy from 'lodash/groupBy';
import intersection from 'lodash/intersection';
import { CALCULATION_OPTIONS } from 'app/data/constants';

import {
  getYColumnValue,
  getThemeConfig,
  getTooltipConfig,
  sortEmissionsByValue,
  sortLabelByAlpha,
  getColorPalette
} from 'utils/graphs';

// constants needed for data parsing
const DATA_SCALE = 1000000;

const BASE_COLORS = ['#25597C', '#DFE9ED'];

const AXES_CONFIG = {
  xBottom: {
    name: 'Year',
    unit: 'date',
    format: 'YYYY'
  },
  yLeft: {
    name: 'Emissions',
    unit: 'CO2e',
    format: 'number'
  }
};

const INCLUDED_SECTORS = {
  CAIT: [
    'Energy',
    'Industrial Processes',
    'Agriculture',
    'Waste',
    'Bunker Fuels'
  ],
  PIK: [
    'Energy',
    'Agriculture',
    'Waste',
    'Solvent sector',
    'Industrial process',
    'Other'
  ],
  UNFCCC: [
    'Energy',
    'Industrial Processes',
    'Solvent and Other Product Use',
    'Agriculture',
    'Waste',
    'Other'
  ]
};

const calculationKeys = Object.keys(CALCULATION_OPTIONS);
const options = calculationKeys.map(
  calculationKey => CALCULATION_OPTIONS[calculationKey]
);

// meta data for selectors
const getMeta = state => state.meta || {};
const getCalculationData = state =>
  (state.calculationData && state.calculationData[state.iso]) || [];

// values from search
const getSourceSelection = state => state.search.source || null;
const getCalculationSelection = state => state.search.calculation || null;
const getVersionSelection = state => state.search.version || null;
const getFilterSelection = state => state.search.filter || null;

// data for the graph
const getData = state => state.data || [];

// Sources selectors
export const getSources = createSelector(
  getMeta,
  meta => meta.data_source || null
);
export const getVersions = createSelector(getMeta, meta => meta.gwp || null);

export const getSourceOptions = createSelector(getSources, sources => {
  if (!sources) return [];
  return sources.map(d => ({
    label: d.label,
    value: d.value,
    source: d.source
  }));
});

const parseCalculationData = createSelector([getCalculationData], data => {
  if (!data || !data.length) return null;
  return groupBy(data, 'year');
});

export const getCalculationOptions = createSelector(
  parseCalculationData,
  calculationData => {
    if (!calculationData) return [];
    return options;
  }
);

export const getSourceSelected = createSelector(
  [getSourceOptions, getSourceSelection],
  (sources, selected) => {
    if (!sources || !sources.length) return {};
    if (!selected) return sources[0];
    return sources.find(category => category.value === parseInt(selected, 10));
  }
);

export const getCalculationSelected = createSelector(
  [getCalculationSelection],
  selected => {
    if (!selected) return options[0];
    return options.find(calculation => calculation.value === selected);
  }
);

// Versions selectors
export const getVersionOptions = createSelector(
  [getVersions, getSources, getSourceSelected],
  (versions, sources, sourceSelected) => {
    if (!sourceSelected || !versions) return [];
    const sourceData = sources.find(d => sourceSelected.value === d.value);
    return versions.filter(filter => sourceData.gwp.indexOf(filter.value) > -1);
  }
);

export const getVersionSelected = createSelector(
  [getVersionOptions, getVersionSelection],
  (versions, selected) => {
    if (!versions || !versions.length) return {};
    if (!selected) return versions[0];
    return versions.find(version => version.value === parseInt(selected, 10));
  }
);

// Filters selector
export const getFilterOptions = createSelector(
  [getMeta, getSourceSelected],
  (meta, sourceSelected) => {
    if (!sourceSelected || isEmpty(meta)) return [];
    const activeSourceData = meta.data_source.find(
      source => source.value === sourceSelected.value
    );
    const activeFilterKeys = activeSourceData.sector;
    const filteredSelected = meta.sector.filter(
      filter => activeFilterKeys.indexOf(filter.value) > -1
    );
    return sortLabelByAlpha(filteredSelected);
  }
);

export const getFiltersSelected = createSelector(
  [getFilterOptions, getFilterSelection],
  (filters, selected) => {
    if (!filters || !filters.length) return [];
    if (!selected) return filters;
    let selectedFilters = [];
    const selectedValues = selected.split(',');
    const selectedValuesNum = selectedValues.map(d => parseInt(d, 10));
    selectedFilters = filters.filter(
      filter => selectedValuesNum.indexOf(filter.value) > -1
    );
    return selectedFilters;
  }
);

// get selector defaults
export const getSelectorDefaults = createSelector(
  [getSources, getSourceSelected],
  (sources, sourceSelected) => {
    if (!sources || !sources.length || !sourceSelected) return {};
    const sourceData = sources.find(d => d.value === sourceSelected.value);
    return {
      sector: sourceData.sector[0],
      gas: sourceData.gas[0],
      source: sources[0].value
    };
  }
);

// Map the data from the API
export const filterData = createSelector(
  [getData, getSourceSelected],
  (data, sourceSelected) => {
    if (!data || !data.length) return [];
    return sortEmissionsByValue(
      data.filter(
        d =>
          INCLUDED_SECTORS[sourceSelected.label].indexOf(d.sector.trim()) >= 0
      )
    );
  }
);

const calculatedRatio = (selected, calculationData, x) => {
  if (selected === CALCULATION_OPTIONS.PER_GDP.value) {
    return calculationData[x][0].gdp;
  }
  if (selected === CALCULATION_OPTIONS.PER_CAPITA.value) {
    return calculationData[x][0].population;
  }
  return 1;
};

export const getChartData = createSelector(
  [
    filterData,
    getFiltersSelected,
    parseCalculationData,
    getCalculationSelected
  ],
  (data, filters, calculationData, calculationSelected) => {
    if (
      !data ||
      !data.length ||
      !filters ||
      !calculationData ||
      !calculationSelected
    ) {
      return [];
    }

    let xValues = [];
    xValues = data[0].emissions.map(d => d.year);
    if (
      calculationSelected.value !== CALCULATION_OPTIONS.ABSOLUTE_VALUE.value
    ) {
      xValues = intersection(
        xValues,
        Object.keys(calculationData).map(y => parseInt(y, 10))
      );
    }

    const dataParsed = xValues.map(x => {
      const yItems = {};
      data.forEach(d => {
        const yKey = getYColumnValue(d.sector);
        const yData = d.emissions.find(e => e.year === x);
        const calculationRatio = calculatedRatio(
          calculationSelected.value,
          calculationData,
          x
        );
        const scaledYData = yData.value * DATA_SCALE;
        yItems[yKey] = scaledYData / calculationRatio;
      });
      const item = {
        x,
        ...yItems
      };
      return item;
    });
    return dataParsed;
  }
);

export const getChartConfig = createSelector(
  [filterData, getCalculationSelected],
  (data, calculationSelected) => {
    if (!data || !data.length) return {};
    const yColumns = data.map(d => ({
      label: d.sector,
      value: getYColumnValue(d.sector)
    }));
    const yColumnsChecked = uniqBy(yColumns, 'value');
    const theme = getThemeConfig(
      yColumnsChecked,
      getColorPalette(BASE_COLORS, yColumnsChecked.length)
    );
    const tooltip = getTooltipConfig(yColumnsChecked);
    let unit = AXES_CONFIG.yLeft.unit;
    if (calculationSelected.value === CALCULATION_OPTIONS.PER_GDP.value) {
      unit = `${unit}/ million $ GDP`;
    } else if (
      calculationSelected.value === CALCULATION_OPTIONS.PER_CAPITA.value
    ) {
      unit = `${unit} per capita`;
    }
    const axes = {
      ...AXES_CONFIG,
      yLeft: {
        ...AXES_CONFIG.yLeft,
        unit
      }
    };
    return {
      axes,
      theme,
      tooltip,
      columns: {
        x: [{ label: 'year', value: 'x' }],
        y: yColumnsChecked
      }
    };
  }
);

export default {
  getSourceOptions,
  getSourceSelected,
  getFilterOptions,
  getFiltersSelected,
  getCalculationData
};
<|endoftext|>


<commit_before>/*************************
**	Modules		**
**************************/

var request	=	require('request');
var cheerio	=	require('cheerio');

/*************************
**	Variables	**
**************************/

var BASE_URL	=	"http://eztv.it";
var SHOWLIST	=	"/showlist/";
var LATEST	=	"/sort/100/";
var SEARCH	=	"/search/";
var SHOWS   =   "/shows/";

exports.getAllShows	=	function(cb) {
	if(cb == null) return;
    	request(BASE_URL + SHOWLIST, function(err, res, html){

		if(err) return (err, null);

		var $ = cheerio.load(html);
		var title, show;
		var allShows = [];

		$('.thread_link').each(function(){
			var entry = $(this);
			var show = entry.text();
            var id = entry.attr('href').match(/\/shows\/(.*)\/(.*)\//)[1];
            var slug = entry.attr('href').match(/\/shows\/(.*)\/(.*)\//)[2];
			allShows.push({show: show, id: id, slug: slug});
		});

		return cb(null, allShows);
    	});
}

exports.getEpisodeMagnet	=	function(data, cb) {
	if(cb == null) return;
	var show = data.show;
	var season = data.season;
	var episode = data.episode;
	if(season.toString().length==1) season = "0"+season;

	if(episode.toString().length==1) episode = "0"+episode;

	var searchString = show +"+S"+ season + "E" + episode;

	request.post(BASE_URL + SEARCH, {form: {SearchString1: searchString}}, function (err, res, html) {
		if(err) return cb(err, null);

		var $ = cheerio.load(html);

		var show_rows = $('tr.forum_header_border[name="hover"]').filter(function(){
			var entry = $(this);
			return entry.find('img[title="Show Description about '+ show+'"]').length > 0;
		});

		if(show_rows.length === 0) return cb("Show Not Found", null);

		var episode_row = show_rows.filter(function() {
			var entry = $(this);
			return entry.text().indexOf("S"+season+"E"+episode) !== -1;
		});

		if(episode_row.length === 0) return cb("Episode Not Found", null);

		var magnet_link = episode_row.children('td[align="center"]').children('a').first().attr('href');
		return cb(null, magnet_link);
	});
};

exports.getAllEpisodes = function(data, cb) {
    if(cb == null) return;
    var episodes = {};

    request.get(BASE_URL + SHOWS + data.id + "/"+ data.slug +"/", function (err, res, html) {
        if(err) return cb(err, null);

        var $ = cheerio.load(html);

        var show_rows = $('tr.forum_header_border[name="hover"]').filter(function() {
            episode_rows = $(this).children('.forum_thread_post');
	    if(episode_rows.length > 0) {
		var title = $(this).children('td').eq(1).text();
		if(title.indexOf("x264") > -1) return true;
	    }
	    return false;
        });

        if(show_rows.length === 0) return cb("Show Not Found", null);

        show_rows.each(function() {
            var entry = $(this);
            var title = entry.children('td').eq(1).text();
            var magnet = entry.children('td').eq(2).children('a').first().attr('href');
            var matcher = title.match(/S([0-9]+)E([0-9]+)/);
            if(!matcher) matcher = title.match(/([0-9]+)x([0-9]+)/);
            if(matcher) {
                var season = parseInt(matcher[1], 10);
                var episode = parseInt(matcher[2], 10);
                var episodeStruct = {};
                episodeStruct.url = magnet;
                episodeStruct.seeds = 0;
                episodeStruct.peers = 0;
                if(!episodes[season]) episodes[season] = {};
                episodes[season][episode] = episodeStruct;
            }
        });
        return cb(null, episodes);
    });
}
<commit_msg>Update variable name (Minaly to fix timestamp on commits)<commit_after>/*************************
**	Modules		**
**************************/

var request	=	require('request');
var cheerio	=	require('cheerio');

/*************************
**	Variables	**
**************************/

var BASE_URL	=	"http://eztv.it";
var SHOWLIST	=	"/showlist/";
var LATEST	=	"/sort/100/";
var SEARCH	=	"/search/";
var SHOWS   =   "/shows/";

exports.getAllShows	=	function(cb) {
	if(cb == null) return;
    	request(BASE_URL + SHOWLIST, function(err, res, html){

		if(err) return (err, null);

		var $ = cheerio.load(html);
		var title, show;
		var allShows = [];

		$('.thread_link').each(function(){
			var entry = $(this);
			var show = entry.text();
            var id = entry.attr('href').match(/\/shows\/(.*)\/(.*)\//)[1];
            var slug = entry.attr('href').match(/\/shows\/(.*)\/(.*)\//)[2];
			allShows.push({show: show, id: id, slug: slug});
		});

		return cb(null, allShows);
    	});
}

exports.getEpisodeMagnet	=	function(data, cb) {
	if(cb == null) return;
	var show = data.show;
	var season = data.season;
	var episode = data.episode;
	if(season.toString().length==1) season = "0"+season;

	if(episode.toString().length==1) episode = "0"+episode;

	var searchString = show +"+S"+ season + "E" + episode;

	request.post(BASE_URL + SEARCH, {form: {SearchString1: searchString}}, function (err, res, html) {
		if(err) return cb(err, null);

		var $ = cheerio.load(html);

		var show_rows = $('tr.forum_header_border[name="hover"]').filter(function(){
			var entry = $(this);
			return entry.find('img[title="Show Description about '+ show+'"]').length > 0;
		});

		if(show_rows.length === 0) return cb("Show Not Found", null);

		var episode_row = show_rows.filter(function() {
			var entry = $(this);
			return entry.text().indexOf("S"+season+"E"+episode) !== -1;
		});

		if(episode_row.length === 0) return cb("Episode Not Found", null);

		var magnet_link = episode_row.children('td[align="center"]').children('a').first().attr('href');
		return cb(null, magnet_link);
	});
};

exports.getAllEpisodes = function(data, cb) {
    if(cb == null) return;
    var episodes = {};

    request.get(BASE_URL + SHOWS + data.id + "/"+ data.slug +"/", function (err, res, html) {
        if(err) return cb(err, null);

        var $ = cheerio.load(html);

        var show_rows = $('tr.forum_header_border[name="hover"]').filter(function() {
            episode_rows = $(this).children('.forum_thread_post');
	    if(episode_rows.length > 0) {
		var title = $(this).children('td').eq(1).text();
		if(title.indexOf("x264") > -1) return true;
	    }
	    return false;
        });

        if(show_rows.length === 0) return cb("Show Not Found", null);

        show_rows.each(function() {
            var entry = $(this);
            var title = entry.children('td').eq(1).text();
            var magnet = entry.children('td').eq(2).children('a').first().attr('href');
            var matcher = title.match(/S([0-9]+)E([0-9]+)/);
            if(!matcher) matcher = title.match(/([0-9]+)x([0-9]+)/);
            if(matcher) {
                var season = parseInt(matcher[1], 10);
                var episode = parseInt(matcher[2], 10);
                var torrent = {};
                torrent.url = magnet;
                torrent.seeds = 0;
                torrent.peers = 0;
                if(!episodes[season]) episodes[season] = {};
                episodes[season][episode] = torrent;
            }
        });
        return cb(null, episodes);
    });
}
<|endoftext|>


<commit_before>'use strict';

let testee = require('../../../../../../../models/eMailService/jobs/registerUserRequestJob');
let email = require('elyoos-server-lib').eMail;
let db = require('elyoos-server-test-util').db;
let sinon = require('sinon');
let expect = require('chai').expect;

describe('Unit Test eMailService/jobs/registerUserRequestJob', function () {

    let sandbox;

    before(function () {
        sandbox = sinon.sandbox.create();
    });

    beforeEach(function () {
        return db.clearDatabase();
    });

    afterEach(function () {
        sandbox.restore();
    });

    it('Send a email to verify the email address', function () {

        let finished = sinon.spy(), linkId = 'abro8ueiQ', emailAddress = 'test@gmx.ch',
            sendEMail = sandbox.stub(email, 'sendEMail');

        testee.processDefinition({email: emailAddress, linkId: linkId}, finished);
        expect(sendEMail.withArgs('registerUserRequest', {link: `${process.env.ELYOOS_DOMAIN}register/verify/${linkId}`,}, emailAddress).calledOnce).to.be.true;
        expect(finished.calledOnce).to.be.true;
    });
});
<commit_msg>bugfix: async/await added.<commit_after>'use strict';

let testee = require('../../../../../../../models/eMailService/jobs/registerUserRequestJob');
let email = require('elyoos-server-lib').eMail;
let db = require('elyoos-server-test-util').db;
let sinon = require('sinon');
let expect = require('chai').expect;

describe('Unit Test eMailService/jobs/registerUserRequestJob', function () {

    let sandbox;

    before(function () {
        sandbox = sinon.sandbox.create();
    });

    beforeEach(function () {
        return db.clearDatabase();
    });

    afterEach(function () {
        sandbox.restore();
    });

    it('Send a email to verify the email address', async function () {

        let finished = sinon.spy(), linkId = 'abro8ueiQ', emailAddress = 'test@gmx.ch',
            sendEMail = sandbox.stub(email, 'sendEMail');

        await testee.processDefinition({email: emailAddress, linkId: linkId}, finished);
        expect(sendEMail.withArgs('registerUserRequest', {link: `${process.env.ELYOOS_DOMAIN}register/verify/${linkId}`,}, emailAddress).calledOnce).to.be.true;
        expect(finished.calledOnce).to.be.true;
    });
});
<|endoftext|>


<commit_before>'use strict';

var InitiativeTrackerService = angular.module('PathfinderManager.InitiativeTrackerService', ['PathfinderManager.MonsterService']);

InitiativeTrackerService.service('InitiativeTrackerService', ['MonsterManager', '$filter', 'MonsterMigrator', function(MonsterManager, $filter, MonsterMigrator){

  this.characterData = [{characters:[{name:"Boromir", currentHp: 78, hpDifference: "", newStatus:"", statuses:[{name: "Dazed", duration: 1}, {name: "Stunned", duration: 3}]}], initiative:17,},
    {characters:[{name:"Arc", currentHp: 69, hpDifference:"", newStatus:"", statuses:[{name: "Poisoned", duration: 8}, {name: "Stunned", duration: 3}]}], initiative:12,},
    {characters:[{name:"Rhaelyn", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]}], initiative:13,},
    {characters:[{name:"Skirmisher 1", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]},
      {name:"Skirmisher 2", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]},
      {name:"Skirmisher 3", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]}], initiative:10},
    {characters:[{name:"Hound Archon", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]}], initiative:13},
    {characters:[{name:"Succubus", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]}], initiative:13}
  ];
  //Character Data for Initiative Tracker
  //this.characterData=[];

  //Adds new characters to initiative tracker
  this.addCharactersToInitiative = function (newCharacterName, newCharacterInitiative, newCharacterHp, newCharacterCount) {

    if (newCharacterCount == undefined){
      newCharacterCount = 1;
    }
    if (newCharacterInitiative == ""){
      newCharacterInitiative = 1;
    }
    if (newCharacterName.trim() != "") {
      this.characterData.push(this.createNewCharacterGroup(newCharacterName, newCharacterInitiative, newCharacterHp, newCharacterCount));
    }
  };

  //Create New Character Group to add to initiative
  this.createNewCharacterGroup = function(newCharacterName, newCharacterInitiative, newCharacterHp, newCharacterCount){

    //Creates new character Group with empty array of characters and sets initiative
    var characterGroup = {
      characters: [],
      initiative: newCharacterInitiative,
    }
    //Populates characters in characterGroup
    for(var i = 0; i < newCharacterCount; i++) {
      var characterName = newCharacterName.charAt(0).toUpperCase() + newCharacterName.slice(1);
      if (newCharacterCount > 1){
        characterName = characterName + " " + (i+1);
      }
      var newCharacter = {
        name: characterName,
        initiative: newCharacterInitiative,
        currentHp: newCharacterHp,
        hpDifference: "",
        newStatus: "",
        statuses: []
      };
      characterGroup.characters.push(newCharacter);
    }
    return characterGroup;
  }

  //Removes character from initiative
  this.removeCharacterFromInitiative = function(group, character){
    var characterIndex = group.characters.indexOf(character);
    group.characters.splice(characterIndex, 1);
    if (group.characters.length == 0){
      var groupIndex = this.characterData.indexOf(group);
      this.characterData.splice(groupIndex, 1);
    }
  }

  //Sorts character groups  by initiative
  this.sortCharacterDataByInitiative = function(){
    this.characterData = $filter('orderBy')(this.characterData, "-initiative");
  }

  //Adds new status to character
  this.addStatusToCharacter = function (character) {
    var statusArray = character.newStatusName.split("=");
    if (statusArray[0] != null && statusArray[0] != ""
        && statusArray[1] != null && statusArray[1] != "") {
      var statusName = statusArray[0].charAt(0).toUpperCase() +statusArray[0].slice(1);
      var statusDuration = parseInt(statusArray[1], 10)
      var status = {name:statusName, duration:statusDuration };
      //var item = {name:"test", initiative: 1}
      character.statuses.push(status);
      character.newStatusName = "";
    }
  };

  //Removes characters from initiative
  this.removeStatusFromCharacter = function(character, status){
    var statusIndex = character.statuses.indexOf(status);
    character.statuses.splice(statusIndex, 1);
  }

  //Updates hp of character
  this.updateHp = function(hpDifference, character){
      character.currentHp = character.currentHp + hpDifference;
      character.hpDifference="";
  }

  //Moves to next character group in initiative order
  this.nextInitiative = function(){

    //Move first character to bottom of initiative
    this.characterData.push(this.characterData.shift());

    //Decrement all statuses for current character in initiative order
    angular.forEach(this.characterData[0].characters, function(character){
      angular.forEach(character.statuses, function(status)
      {
        status.duration = status.duration - 1;
        if (status.duration <= -1) {
          character.statuses.splice(character.statuses.indexOf(status), 1);
        }
      });
    });

    var currentCharacterName = this.characterData[0].characters[0].name;
    //Updates monster display if current character is monster
    MonsterManager.updateCurrentMonster(currentCharacterName);
    MonsterMigrator.createMonsterFromDatabase();
  };

}]);<commit_msg>fix for blank count ininitiative tracker<commit_after>'use strict';

var InitiativeTrackerService = angular.module('PathfinderManager.InitiativeTrackerService', ['PathfinderManager.MonsterService']);

InitiativeTrackerService.service('InitiativeTrackerService', ['MonsterManager', '$filter', 'MonsterMigrator', function(MonsterManager, $filter, MonsterMigrator){

  /*this.characterData = [{characters:[{name:"Boromir", currentHp: 78, hpDifference: "", newStatus:"", statuses:[{name: "Dazed", duration: 1}, {name: "Stunned", duration: 3}]}], initiative:17,},
    {characters:[{name:"Arc", currentHp: 69, hpDifference:"", newStatus:"", statuses:[{name: "Poisoned", duration: 8}, {name: "Stunned", duration: 3}]}], initiative:12,},
    {characters:[{name:"Rhaelyn", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]}], initiative:13,},
    {characters:[{name:"Skirmisher 1", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]},
      {name:"Skirmisher 2", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]},
      {name:"Skirmisher 3", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]}], initiative:10},
    {characters:[{name:"Hound Archon", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]}], initiative:13},
    {characters:[{name:"Succubus", currentHp: 100,  hpDifference:"", newStatus:"", statuses:[{name: "Dazzled", duration: 9}, {name: "Diseased", duration: 5}]}], initiative:13}
  ];*/
  //Character Data for Initiative Tracker
  this.characterData=[];

  //Adds new characters to initiative tracker
  this.addCharactersToInitiative = function (newCharacterName, newCharacterInitiative, newCharacterHp, newCharacterCount) {

    if (newCharacterCount == undefined){
      newCharacterCount = 1;
    }
    if (newCharacterInitiative == "" || newCharacterInitiative == undefined){
      newCharacterInitiative = 1;
    }
    if (newCharacterName.trim() != "") {
      this.characterData.push(this.createNewCharacterGroup(newCharacterName, newCharacterInitiative, newCharacterHp, newCharacterCount));
    }
  };

  //Create New Character Group to add to initiative
  this.createNewCharacterGroup = function(newCharacterName, newCharacterInitiative, newCharacterHp, newCharacterCount){

    //Creates new character Group with empty array of characters and sets initiative
    var characterGroup = {
      characters: [],
      initiative: newCharacterInitiative,
    }
    //Populates characters in characterGroup
    for(var i = 0; i < newCharacterCount; i++) {
      var characterName = newCharacterName.charAt(0).toUpperCase() + newCharacterName.slice(1);
      if (newCharacterCount > 1){
        characterName = characterName + " " + (i+1);
      }
      var newCharacter = {
        name: characterName,
        initiative: newCharacterInitiative,
        currentHp: newCharacterHp,
        hpDifference: "",
        newStatus: "",
        statuses: []
      };
      characterGroup.characters.push(newCharacter);
    }
    return characterGroup;
  }

  //Removes character from initiative
  this.removeCharacterFromInitiative = function(group, character){
    var characterIndex = group.characters.indexOf(character);
    group.characters.splice(characterIndex, 1);
    if (group.characters.length == 0){
      var groupIndex = this.characterData.indexOf(group);
      this.characterData.splice(groupIndex, 1);
    }
  }

  //Sorts character groups  by initiative
  this.sortCharacterDataByInitiative = function(){
    this.characterData = $filter('orderBy')(this.characterData, "-initiative");
  }

  //Adds new status to character
  this.addStatusToCharacter = function (character) {
    var statusArray = character.newStatusName.split("=");
    if (statusArray[0] != null && statusArray[0] != ""
        && statusArray[1] != null && statusArray[1] != "") {
      var statusName = statusArray[0].charAt(0).toUpperCase() +statusArray[0].slice(1);
      var statusDuration = parseInt(statusArray[1], 10)
      var status = {name:statusName, duration:statusDuration };
      //var item = {name:"test", initiative: 1}
      character.statuses.push(status);
      character.newStatusName = "";
    }
  };

  //Removes characters from initiative
  this.removeStatusFromCharacter = function(character, status){
    var statusIndex = character.statuses.indexOf(status);
    character.statuses.splice(statusIndex, 1);
  }

  //Updates hp of character
  this.updateHp = function(hpDifference, character){
      character.currentHp = character.currentHp + hpDifference;
      character.hpDifference="";
  }

  //Moves to next character group in initiative order
  this.nextInitiative = function(){

    //Move first character to bottom of initiative
    this.characterData.push(this.characterData.shift());

    //Decrement all statuses for current character in initiative order
    angular.forEach(this.characterData[0].characters, function(character){
      angular.forEach(character.statuses, function(status)
      {
        status.duration = status.duration - 1;
        if (status.duration <= -1) {
          character.statuses.splice(character.statuses.indexOf(status), 1);
        }
      });
    });

    var currentCharacterName = this.characterData[0].characters[0].name;
    //Updates monster display if current character is monster
    MonsterManager.updateCurrentMonster(currentCharacterName);
    MonsterMigrator.createMonsterFromDatabase();
  };

}]);<|endoftext|>


<commit_before>//Looping
casper.test.begin('Wizard', 101, function (test) {

    //initial 50 loops
    var loop = [];
    for (var i = 1; i <= 50; i++) {
        loop.push(i);
    }

    casper.start("http://localhost:43502/wizard/index/1");

    //notice loop forEach is inside a casper function...
    casper.then(function () {

        loop.forEach(function (item) {

            //All tests must be inside a casper function
            casper.then(function () {
                test.assertTitle("Wizard Step: " + item + " - CasperJS Mvc");
            });

            casper.then(function () {
                this.fillSelectors('form', {}, true);
            });

            casper.then(function () {
                test.assertTextExists("The Answer field is required", "Validation error message is shown");
                this.fillSelectors('form', {
                    "input[name='Answer']": 'An answer'
                }, true);
            });

        });

    });

    casper.then(function () {
        test.assertTitle("Finished - CasperJS Mvc");
    });

    casper.run(function () {
        test.done();
    });

});<commit_msg>added waitfor after every new resource has been loaded<commit_after>//Looping
casper.test.begin('Wizard', 101, function (test) {

    //initial 50 loops
    var loop = [];
    for (var i = 1; i <= 50; i++) {
        loop.push(i);
    }

    casper.start("http://localhost:43502/wizard/index/1");

    //notice loop forEach is inside a casper function...
    casper.then(function () {

        loop.forEach(function (item) {

            //All tests must be inside a casper function
            casper.waitForSelector("input[name='Answer']", function () {
                test.assertTitle("Wizard Step: " + item + " - CasperJS Mvc");
                this.fillSelectors('form', {}, true);
            });

            casper.waitForSelector("input[name='Answer']", function () {
                test.assertTextExists("The Answer field is required", "Validation error message is shown");
                this.fillSelectors('form', {
                    "input[name='Answer']": 'An answer'
                }, true);
            });

        });

    });

    casper.waitForUrl(/wizard\/finished/, function () {
        test.assertTitle("Finished - CasperJS Mvc");
    });

    casper.run(function () {
        test.done();
    });

});<|endoftext|>