<commit_before>const {
    app,
    BrowserWindow,
    globalShortcut,
    ipcMain,
    dialog
} = require('electron');

const path = require('path');
const url = require('url');

const fs = require('fs');
const id3 = require('musicmetadata');

// window object
let win;

app.on('ready', () => {
    // Create the browser window.
    win = new BrowserWindow({
        width: 800,
        height: 600,
        center: true,
        icon: "assets/img/favicon.png",
        autoHideMenuBar: true,
        frame: false,
        webPreferences: {
            devTools: true
        }
    });

    // and load the index.html of the app.
    win.loadURL("file://" + __dirname + "/index.html");

    // hotkeys
    win.webContents.on("did-finish-load", () => {

        // volume up
        globalShortcut.register("volumeUp", () => {
            win.webContents.send("keyPress", "volumeUp");
        });
        globalShortcut.register("Alt+Up", () => {
            win.webContents.send("keyPress", "volumeUp");
        });

        // volume down
        globalShortcut.register("volumeDown", () => {
            win.webContents.send("keyPress", "volumeDown");
        });
        globalShortcut.register("Alt+Down", () => {
            win.webContents.send("keyPress", "volumeDown");
        });

        // toggleMute
        globalShortcut.register("Alt+M", () => {
            win.webContents.send("keyPress", "toggleMute");
        });

        // previousSong
        globalShortcut.register("mediaPreviousTrack", () => {
            win.webContents.send("keyPress", "previousSong");
        });
        globalShortcut.register("Alt+Left", () => {
            win.webContents.send("keyPress", "previousSong");
        });

        // nextSong
        globalShortcut.register("MediaNextTrack", () => {
            win.webContents.send("keyPress", "nextSong");
        });
        globalShortcut.register("Alt+Right", () => {
            win.webContents.send("keyPress", "nextSong");
        });

        // playPause
        globalShortcut.register("MediaPlayPause", () => {
            win.webContents.send("keyPress", "playPause");
        });
        globalShortcut.register("Alt+Space", () => {
            win.webContents.send("keyPress", "playPause");
        });

        // stop
        globalShortcut.register("MediaStop", () => {
            win.webContents.send("keyPress", "stop");
        });
        globalShortcut.register("Alt+Enter", () => {
            win.webContents.send("keyPress", "stop");
        });

    });

    // user interface titlebar actions
    ipcMain.on("titleBar", (event, arg) => {

        // close
        if (arg == "close") {
            win.close();

        // maximize unmazimize
        } else if (arg == "maximize") {

            // is maximized
            if (win.isMaximized()) {
                win.unmaximize();

            // is not maximized
            } else {
                win.maximize();
            }

        } else if (arg == "minimize") {
            win.minimize();

        } else if (arg == "loadFolder") {
            event.returnValue = loadMusicFromFolder();
        }

        event.returnValue = "ok";
    });

});

// Quit when all windows are closed.
app.on('window-all-closed', () => {
    app.quit();
});

function selectFolder() {
    var dir = undefined;
    while(dir === undefined) {
        dir = dialog.showOpenDialog({
            properties: ['openDirectory']
        });
    }
    return dir = dir[0];
}

function loadMusicFromFolder() {
    var dir = selectFolder();
    var songs = [];

    if (fs.existsSync(dir)) {
        fs.readdir(dir, (error, files) => {
            files.forEach((file) => {
                if (fs.lstatSync(dir + "/" + file).isDirectory()) {
                    // directory
                }

                var f = file.split(".");
                if (f[f.length - 1].toUpperCase() == "MP3") {
                    file = path.resolve(dir, file);

                    var filemtime;
                    fs.stat(file, (err, stats) => {
                        filemtime = new Date(stats.mtime).valueOf();
                    });

                    // doc: https://github.com/leetreveil/musicmetadata
                    var readableStream = fs.createReadStream(file);
                    var parser = id3(readableStream, {duration: true}, function (err, metadata) {
                        if (typeof metadata.picture[0] != "undefined") {
                            metadata.picture[0].data = metadata.picture[0].data.toString("base64");
                        }

                        var resp = {
                            title: metadata.title,
                            artist: metadata.artist,
                            album: metadata.album,
                            duration: metadata.duration,
                            cover: metadata.picture,
                            moddate: filemtime
                        }

                        console.log(resp.title + " - " + resp.artist);

                        readableStream.close();
                        songs.push(resp);
                    });
                }
            });
        });
    }

    return songs;
}
<commit_msg>Removed console.log()<commit_after>const {
    app,
    BrowserWindow,
    globalShortcut,
    ipcMain,
    dialog
} = require('electron');

const path = require('path');
const url = require('url');

const fs = require('fs');
const id3 = require('musicmetadata');

// window object
let win;

app.on('ready', () => {
    // Create the browser window.
    win = new BrowserWindow({
        width: 800,
        height: 600,
        center: true,
        icon: "assets/img/favicon.png",
        autoHideMenuBar: true,
        frame: false,
        webPreferences: {
            devTools: true
        }
    });

    // and load the index.html of the app.
    win.loadURL("file://" + __dirname + "/index.html");

    // hotkeys
    win.webContents.on("did-finish-load", () => {

        // volume up
        globalShortcut.register("volumeUp", () => {
            win.webContents.send("keyPress", "volumeUp");
        });
        globalShortcut.register("Alt+Up", () => {
            win.webContents.send("keyPress", "volumeUp");
        });

        // volume down
        globalShortcut.register("volumeDown", () => {
            win.webContents.send("keyPress", "volumeDown");
        });
        globalShortcut.register("Alt+Down", () => {
            win.webContents.send("keyPress", "volumeDown");
        });

        // toggleMute
        globalShortcut.register("Alt+M", () => {
            win.webContents.send("keyPress", "toggleMute");
        });

        // previousSong
        globalShortcut.register("mediaPreviousTrack", () => {
            win.webContents.send("keyPress", "previousSong");
        });
        globalShortcut.register("Alt+Left", () => {
            win.webContents.send("keyPress", "previousSong");
        });

        // nextSong
        globalShortcut.register("MediaNextTrack", () => {
            win.webContents.send("keyPress", "nextSong");
        });
        globalShortcut.register("Alt+Right", () => {
            win.webContents.send("keyPress", "nextSong");
        });

        // playPause
        globalShortcut.register("MediaPlayPause", () => {
            win.webContents.send("keyPress", "playPause");
        });
        globalShortcut.register("Alt+Space", () => {
            win.webContents.send("keyPress", "playPause");
        });

        // stop
        globalShortcut.register("MediaStop", () => {
            win.webContents.send("keyPress", "stop");
        });
        globalShortcut.register("Alt+Enter", () => {
            win.webContents.send("keyPress", "stop");
        });

    });

    // user interface titlebar actions
    ipcMain.on("titleBar", (event, arg) => {

        // close
        if (arg == "close") {
            win.close();

        // maximize unmazimize
        } else if (arg == "maximize") {

            // is maximized
            if (win.isMaximized()) {
                win.unmaximize();

            // is not maximized
            } else {
                win.maximize();
            }

        } else if (arg == "minimize") {
            win.minimize();

        } else if (arg == "loadFolder") {
            event.returnValue = loadMusicFromFolder();
        }

        event.returnValue = "ok";
    });

});

// Quit when all windows are closed.
app.on('window-all-closed', () => {
    app.quit();
});

function selectFolder() {
    var dir = undefined;
    while(dir === undefined) {
        dir = dialog.showOpenDialog({
            properties: ['openDirectory']
        });
    }
    return dir = dir[0];
}

function loadMusicFromFolder() {
    var dir = selectFolder();
    var songs = [];

    if (fs.existsSync(dir)) {
        fs.readdir(dir, (error, files) => {
            files.forEach((file) => {
                if (fs.lstatSync(dir + "/" + file).isDirectory()) {
                    // directory
                }

                var f = file.split(".");
                if (f[f.length - 1].toUpperCase() == "MP3") {
                    file = path.resolve(dir, file);

                    var filemtime;
                    fs.stat(file, (err, stats) => {
                        filemtime = new Date(stats.mtime).valueOf();
                    });

                    // doc: https://github.com/leetreveil/musicmetadata
                    var readableStream = fs.createReadStream(file);
                    var parser = id3(readableStream, {duration: true}, function (err, metadata) {
                        if (typeof metadata.picture[0] != "undefined") {
                            metadata.picture[0].data = metadata.picture[0].data.toString("base64");
                        }

                        var resp = {
                            title: metadata.title,
                            artist: metadata.artist,
                            album: metadata.album,
                            duration: metadata.duration,
                            cover: metadata.picture,
                            moddate: filemtime
                        }

                        readableStream.close();
                        songs.push(resp);
                    });
                }
            });
        });
    }

    return songs;
}
<|endoftext|>


<commit_before>var _ = require('underscore');
var connect = require('connect');
var fs = require('fs');
var Q = require('q');
var Session = require('./session');
var WSServer = require('ws').Server;

//--------------------------------------

var xo = require('./xo')();

var Api = require('./api');
var api = new Api(xo);

var http_servers = [];

//////////////////////////////////////////////////////////////////////

function json_api_call(session, message)
{
	/* jshint newcap:false */

	var req = {
		'id': null,
	};

	function format_error(error)
	{
		return JSON.stringify({
			'jsonrpc': '2.0',
			'error': error,
			'id': req.id,
		});
	}

	try
	{
		req = JSON.parse(message.toString());
	}
	catch (e)
	{
		if (e instanceof SyntaxError)
		{
			return Q(format_error(Api.err.INVALID_JSON));
		}
		return Q(format_error(Api.err.SERVER_ERROR));
	}

	/* jshint laxbreak: true */
	if (!req.method || !req.params
		|| (undefined === req.id)
		|| ('2.0' !== req.jsonrpc))
	{
		return Q(format_error(Api.err.INVALID_REQUEST));
	}

	return api.exec(
		session,
		{
			'method': req.method,
			'params': req.params,
		}
	).then(
		function (result) {
			return JSON.stringify({
				'jsonrpc': '2.0',
				'result': result,
				'id': req.id,
			});
		},
		function (error) {
			if (!_.isObject(error) || (error instanceof Error))
			{
				console.error(error.stack || error);
				return format_error(Api.err.SERVER_ERROR);
			}

			return format_error(error);
		}
	);
}

//////////////////////////////////////////////////////////////////////
// Static file serving (for XO-Web for instance).
//////////////////////////////////////////////////////////////////////

xo.on('started', function () {
	http_servers.forEach(function (http_server) {
		http_server.on('request', connect()
			// Compresses reponses using GZip.
			.use(connect.compress())

			// Caches the responses in memory.
			//.use(connect.staticCache())

			// Serve static files.
			.use(connect.static(__dirname +'/../public/http'))
		);
	});
});

//////////////////////////////////////////////////////////////////////
// WebSocket to TCP proxy (used for consoles).
//////////////////////////////////////////////////////////////////////

// Protocol:
//
// 1. The web browser connects to the server via WebSocket.
//
// 2. It sends a first message containing the “host” and “port” to
//    connect to in a JSON object.
//
// 3. All messages to send to the TCP server and received from it will
//    be encoded using Base64.

// @todo Avoid Base64 encoding and directly use binary streams.
// xo.on('started', function () {
// 	function on_connection(socket)
// 	{
// 		// Parses the first message which SHOULD contains the host and
// 		// port of the host to connect to.
// 		socket.once('message', function (message) {
// 			try
// 			{
// 				message = JSON.parse(message);
// 			}
// 			catch (e)
// 			{
// 				socket.close();
// 				return;
// 			}

// 			if (!message.host && !message.port)
// 			{
// 				socket.close();
// 				return;
// 			}

// 			var target = tcp.createConnection(message.port, message.host);
// 			target.on('data', function (data) {
// 				socket.send(data.toString('base64'));
// 			});
// 			target.on('end', function () {
// 				socket.close();
// 			});
// 			target.on('error', function () {
// 				target.end();
// 			});

// 			socket.on('message', function (message) {
// 				target.write(new Buffer(message, 'base64'));
// 			});
// 			socket.on('close', function () {
// 				target.end();
// 			});
// 		});

// 		socket.on('error', function () {
// 			socket.close();
// 		});
// 	}

// 	http_servers.forEach(function (http_server) {
// 		new WSServer({
// 			'server': http_server,
// 			'path': '/websockify',
// 		})
// 		.on('connection', on_connection);
// 	});
// });

//////////////////////////////////////////////////////////////////////
// JSON-RPC over WebSocket.
//////////////////////////////////////////////////////////////////////

xo.on('started', function () {
	function on_connection(socket)
	{
		var session = new Session(xo);
		session.once('close', function () {
			socket.close();
		});

		socket.on('message', function (request) {
			json_api_call(session, request).then(function (response) {
				// Send response if session still open.
				if (socket.readyState === socket.OPEN)
				{
					socket.send(response);
				}
			}).done();
		});

		// @todo Ugly inter dependency.
		socket.once('close', function () {
			session.close();
		});
	}

	http_servers.forEach(function (http_server) {
		new WSServer({
			'server': http_server,
			'path': '/api/',
		}).on('connection', on_connection);
	});
});

//////////////////////////////////////////////////////////////////////
// JSON-RPC over TCP.
//////////////////////////////////////////////////////////////////////

// xo.on('started', function () {
// 	require('net').createServer(function (socket) {
// 		var session = new Session(xo);
// 		session.on('close', function () {
// 			socket.end(); // @todo Check it is enough.
// 		});

// 		var length = null; // Expected message length.
// 		var buffer = new Buffer(1024); // @todo I hate hardcoded values!
// 		socket.on('data', function (data) {
// 			data.copy(buffer);

// 			// Read the message length.
// 			if (!length)
// 			{
// 				var i = _.indexOf(buffer, 10);
// 				if (-1 === i)
// 				{
// 					return;
// 				}

// 				length = +(buffer.toString('ascii', 0, i));

// 				// If the length is NaN, we cannot do anything except
// 				// closing the connection.
// 				if (length !== length)
// 				{
// 					session.close();
// 					return;
// 				}

// 				buffer = buffer.slice(i + 1);
// 			}

// 			// We do not have received everything.
// 			if (buffer.length < length)
// 			{
// 				return;
// 			}

// 			json_api_call(
// 				session,
// 				buffer.slice(0, length).toString()
// 			).then(function (response) {
// 				// @todo Handle long messages.
// 				socket.write(response.length +'\n'+ response);
// 			}).done();

// 			// @todo Check it frees the memory.
// 			buffer = buffer.slice(length);

// 			length = null;
// 		});

// 		// @todo Ugly inter dependency.
// 		socket.once('close', function () {
// 			session.close();
// 		});
// 	}).listen(1024); // @todo Should be configurable.
// });

//////////////////////////////////////////////////////////////////////

var cfg = {
	'data': {},

	'get': function (path) {
		/* jshint noempty: false */

		if (!_.isArray(path))
		{
			path = Array.prototype.slice.call(arguments);
		}

		var current = this.data;
		for (
			var i = 0, n = path.length;
			(i < n) && (undefined !== (current = current[path[i]]));
			++i
		)
		{}

		if (i < n)
		{
			return undefined;
		}

		return current;
	},

	'merge': function (data) {
		var helper = function (target, source) {
			if (null === source) // Special case.
			{
				return target;
			}

			if (!_.isObject(target) || !_.isObject(source))
			{
				return source;
			}

			if (_.isArray(target) && _.isArray(source))
			{
				target.push.apply(target, source);
				return target;
			}

			for (var prop in source)
			{
				target[prop] = helper(target[prop], source[prop]);
			}
			return target;
		};

		helper(this.data, data);
		return this;
	},
};

// Defaults values.
cfg.merge({
	'http': {
		'enabled': true,
		'host': '0.0.0.0',
		'port': 80,
	},
	'https': {
		'enabled': false,
		'host': '0.0.0.0',
		'port': 443,
		'certificate': './certificate.pem',
		'key': './key.pem',
	},
	'redis': {
		'uri': 'tcp://127.0.0.1:6379',
	},
});

function read_file(file)
{
	return Q.ninvoke(fs, 'readFile', file, {'encoding': 'utf-8'});
}

read_file(__dirname +'/../config/local.yaml').then(
	function (data) {
		data = require('js-yaml').safeLoad(data);
		cfg.merge(data);
	},
	function (e) {
		console.error('[Warning] Reading config file: '+ e);
	}
).then(function () {
	if (cfg.get('users'))
	{
		console.warn('[Warn] Users in config file are no longer supported.');
	}
	if (cfg.get('servers'))
	{
		console.warn('[Warn] Servers in config file are no longer supported.');
	}

	if (cfg.get('http', 'enabled'))
	{
		var host = cfg.get('http', 'host');
		var port = cfg.get('http', 'port');

		http_servers.push(
			require('http').createServer().listen(port, host)
				.on('listening', function () {
					console.info(
						'XO-Server HTTP server is listening on %s:%s',
						host, port
					);
				})
		);
	}

	if (cfg.get('https', 'enabled'))
	{
		return Q.all([
			read_file(cfg.get('https', 'certificate')),
			read_file(cfg.get('https', 'key')),
		]).spread(function (certificate, key) {
			var host = cfg.get('https', 'host');
			var port = cfg.get('https', 'port');

			http_servers.push(
				require('https').createServer({
					'cert': certificate,
					'key': key,
				}).listen(port, host).on('listening', function () {
					console.info(
						'XO-Server HTTPS server is listening on %s:%s',
						host, port
					);
				})
			);
		});
	}
}).then(function () {
	xo.start(cfg);
}).done();

// Create an initial user if there are none.
xo.on('started', function () {
	xo.users.exists().then(function (success) {
		if (success)
		{
			return;
		}

		console.warn('[Warning] No users, creating “admin@admin.net” with password “admin”');

		return xo.users.create('admin@admin.net', 'admin', 'admin');
	}).done();
});
<commit_msg>Display an error message when the HTTP(S) server could not start.<commit_after>var _ = require('underscore');
var connect = require('connect');
var fs = require('fs');
var Q = require('q');
var Session = require('./session');
var WSServer = require('ws').Server;

//--------------------------------------

var xo = require('./xo')();

var Api = require('./api');
var api = new Api(xo);

var http_servers = [];

//////////////////////////////////////////////////////////////////////

function json_api_call(session, message)
{
	/* jshint newcap:false */

	var req = {
		'id': null,
	};

	function format_error(error)
	{
		return JSON.stringify({
			'jsonrpc': '2.0',
			'error': error,
			'id': req.id,
		});
	}

	try
	{
		req = JSON.parse(message.toString());
	}
	catch (e)
	{
		if (e instanceof SyntaxError)
		{
			return Q(format_error(Api.err.INVALID_JSON));
		}
		return Q(format_error(Api.err.SERVER_ERROR));
	}

	/* jshint laxbreak: true */
	if (!req.method || !req.params
		|| (undefined === req.id)
		|| ('2.0' !== req.jsonrpc))
	{
		return Q(format_error(Api.err.INVALID_REQUEST));
	}

	return api.exec(
		session,
		{
			'method': req.method,
			'params': req.params,
		}
	).then(
		function (result) {
			return JSON.stringify({
				'jsonrpc': '2.0',
				'result': result,
				'id': req.id,
			});
		},
		function (error) {
			if (!_.isObject(error) || (error instanceof Error))
			{
				console.error(error.stack || error);
				return format_error(Api.err.SERVER_ERROR);
			}

			return format_error(error);
		}
	);
}

//////////////////////////////////////////////////////////////////////
// Static file serving (for XO-Web for instance).
//////////////////////////////////////////////////////////////////////

xo.on('started', function () {
	http_servers.forEach(function (http_server) {
		http_server.on('request', connect()
			// Compresses reponses using GZip.
			.use(connect.compress())

			// Caches the responses in memory.
			//.use(connect.staticCache())

			// Serve static files.
			.use(connect.static(__dirname +'/../public/http'))
		);
	});
});

//////////////////////////////////////////////////////////////////////
// WebSocket to TCP proxy (used for consoles).
//////////////////////////////////////////////////////////////////////

// Protocol:
//
// 1. The web browser connects to the server via WebSocket.
//
// 2. It sends a first message containing the “host” and “port” to
//    connect to in a JSON object.
//
// 3. All messages to send to the TCP server and received from it will
//    be encoded using Base64.

// @todo Avoid Base64 encoding and directly use binary streams.
// xo.on('started', function () {
// 	function on_connection(socket)
// 	{
// 		// Parses the first message which SHOULD contains the host and
// 		// port of the host to connect to.
// 		socket.once('message', function (message) {
// 			try
// 			{
// 				message = JSON.parse(message);
// 			}
// 			catch (e)
// 			{
// 				socket.close();
// 				return;
// 			}

// 			if (!message.host && !message.port)
// 			{
// 				socket.close();
// 				return;
// 			}

// 			var target = tcp.createConnection(message.port, message.host);
// 			target.on('data', function (data) {
// 				socket.send(data.toString('base64'));
// 			});
// 			target.on('end', function () {
// 				socket.close();
// 			});
// 			target.on('error', function () {
// 				target.end();
// 			});

// 			socket.on('message', function (message) {
// 				target.write(new Buffer(message, 'base64'));
// 			});
// 			socket.on('close', function () {
// 				target.end();
// 			});
// 		});

// 		socket.on('error', function () {
// 			socket.close();
// 		});
// 	}

// 	http_servers.forEach(function (http_server) {
// 		http_server.on('connection', function () {
// 			new WSServer({
// 				'server': http_server,
// 				'path': '/websockify',
// 			})
// 			.on('connection', on_connection);
// 		});
// 	});
// });

//////////////////////////////////////////////////////////////////////
// JSON-RPC over WebSocket.
//////////////////////////////////////////////////////////////////////

xo.on('started', function () {
	function on_connection(socket)
	{
		var session = new Session(xo);
		session.once('close', function () {
			socket.close();
		});

		socket.on('message', function (request) {
			json_api_call(session, request).then(function (response) {
				// Send response if session still open.
				if (socket.readyState === socket.OPEN)
				{
					socket.send(response);
				}
			}).done();
		});

		// @todo Ugly inter dependency.
		socket.once('close', function () {
			session.close();
		});
	}

	http_servers.forEach(function (http_server) {
		http_server.on('connection', function () {
			new WSServer({
				'server': http_server,
				'path': '/api/',
			}).on('connection', on_connection);
		});
	});
});

//////////////////////////////////////////////////////////////////////
// JSON-RPC over TCP.
//////////////////////////////////////////////////////////////////////

// xo.on('started', function () {
// 	require('net').createServer(function (socket) {
// 		var session = new Session(xo);
// 		session.on('close', function () {
// 			socket.end(); // @todo Check it is enough.
// 		});

// 		var length = null; // Expected message length.
// 		var buffer = new Buffer(1024); // @todo I hate hardcoded values!
// 		socket.on('data', function (data) {
// 			data.copy(buffer);

// 			// Read the message length.
// 			if (!length)
// 			{
// 				var i = _.indexOf(buffer, 10);
// 				if (-1 === i)
// 				{
// 					return;
// 				}

// 				length = +(buffer.toString('ascii', 0, i));

// 				// If the length is NaN, we cannot do anything except
// 				// closing the connection.
// 				if (length !== length)
// 				{
// 					session.close();
// 					return;
// 				}

// 				buffer = buffer.slice(i + 1);
// 			}

// 			// We do not have received everything.
// 			if (buffer.length < length)
// 			{
// 				return;
// 			}

// 			json_api_call(
// 				session,
// 				buffer.slice(0, length).toString()
// 			).then(function (response) {
// 				// @todo Handle long messages.
// 				socket.write(response.length +'\n'+ response);
// 			}).done();

// 			// @todo Check it frees the memory.
// 			buffer = buffer.slice(length);

// 			length = null;
// 		});

// 		// @todo Ugly inter dependency.
// 		socket.once('close', function () {
// 			session.close();
// 		});
// 	}).listen(1024); // @todo Should be configurable.
// });

//////////////////////////////////////////////////////////////////////

var cfg = {
	'data': {},

	'get': function (path) {
		/* jshint noempty: false */

		if (!_.isArray(path))
		{
			path = Array.prototype.slice.call(arguments);
		}

		var current = this.data;
		for (
			var i = 0, n = path.length;
			(i < n) && (undefined !== (current = current[path[i]]));
			++i
		)
		{}

		if (i < n)
		{
			return undefined;
		}

		return current;
	},

	'merge': function (data) {
		var helper = function (target, source) {
			if (null === source) // Special case.
			{
				return target;
			}

			if (!_.isObject(target) || !_.isObject(source))
			{
				return source;
			}

			if (_.isArray(target) && _.isArray(source))
			{
				target.push.apply(target, source);
				return target;
			}

			for (var prop in source)
			{
				target[prop] = helper(target[prop], source[prop]);
			}
			return target;
		};

		helper(this.data, data);
		return this;
	},
};

// Defaults values.
cfg.merge({
	'http': {
		'enabled': true,
		'host': '0.0.0.0',
		'port': 80,
	},
	'https': {
		'enabled': false,
		'host': '0.0.0.0',
		'port': 443,
		'certificate': './certificate.pem',
		'key': './key.pem',
	},
	'redis': {
		'uri': 'tcp://127.0.0.1:6379',
	},
});

function read_file(file)
{
	return Q.ninvoke(fs, 'readFile', file, {'encoding': 'utf-8'});
}

read_file(__dirname +'/../config/local.yaml').then(
	function (data) {
		data = require('js-yaml').safeLoad(data);
		cfg.merge(data);
	},
	function (e) {
		console.error('[Warning] Reading config file: '+ e);
	}
).then(function () {
	if (cfg.get('users'))
	{
		console.warn('[Warn] Users in config file are no longer supported.');
	}
	if (cfg.get('servers'))
	{
		console.warn('[Warn] Servers in config file are no longer supported.');
	}

	if (cfg.get('http', 'enabled'))
	{
		var host = cfg.get('http', 'host');
		var port = cfg.get('http', 'port');

		http_servers.push(
			require('http').createServer().listen(port, host)
				.on('listening', function () {
					console.info(
						'HTTP server is listening on %s:%s',
						host, port
					);
				})
				.on('error', function () {
					console.warn(
						'[Warn] HTTP server could not listen on %s:%s',
						host, port
					);
				})
		);
	}

	if (cfg.get('https', 'enabled'))
	{
		return Q.all([
			read_file(cfg.get('https', 'certificate')),
			read_file(cfg.get('https', 'key')),
		]).spread(function (certificate, key) {
			var host = cfg.get('https', 'host');
			var port = cfg.get('https', 'port');

			http_servers.push(
				require('https').createServer({
					'cert': certificate,
					'key': key,
				}).listen(port, host).on('listening', function () {
					console.info(
						'HTTPS server is listening on %s:%s',
						host, port
					);
				}).on('error', function () {
					console.warn(
						'[Warn] HTTPS server could not listen on %s:%s',
						host, port
					);
				})
			);
		});
	}
}).then(function () {
	xo.start(cfg);
}).done();

// Create an initial user if there are none.
xo.on('started', function () {
	xo.users.exists().then(function (success) {
		if (success)
		{
			return;
		}

		console.warn('[Warning] No users, creating “admin@admin.net” with password “admin”');

		return xo.users.create('admin@admin.net', 'admin', 'admin');
	}).done();
});
<|endoftext|>


<commit_before>'use strict';

const VERSION = '0.3.0';

const electron  = require('electron');
const path      = require('path');
const ospath = require('ospath');
const jsonfile  = require('jsonfile');

var absPath = path.dirname(__dirname),
    configFile = ospath.data() + '/KongDash' + '/config.json';

var {app, ipcMain, BrowserWindow, Menu} = electron;

let mainWindow, appConfig = {kong: {}, app: {enableAnimation: true}};

var startMainWindow = function () {
    mainWindow = new BrowserWindow({
        backgroundColor: '#1A242D',
        width: 1100,
        height: 580,
        center: true,
        title: app.getName(),
        minHeight: 500,
        minWidth: 900,
        icon: absPath + '/kongdash-256x256.png'
    });
    mainWindow.loadURL('file://' + absPath + '/src/initialize.html');

    /* Debugging
    mainWindow.webContents.openDevTools();
    //*/

    mainWindow.on('closed', () => {
        mainWindow = null;
    });
};

app.setName('KongDash');

app.on('ready', () => {
    try {
        appConfig = jsonfile.readFileSync(configFile);

    } catch (e) {
        /* Ignore. Uses default settings. */
    } finally {
        startMainWindow();
    }
});

app.on('activate', () => {
    if (mainWindow === null) startMainWindow();
});

app.on('browser-window-created', (e, window) => {
    let menuTemplate = [{
        label: 'File',
        submenu: [{
            label: 'Settings',
            click: () => {
                mainWindow.webContents.send('open-settings-view', '');
            }
        }, { type: 'separator' }, { role: 'quit' }]
    }, {
        label: 'Edit',
        submenu: [{ role: 'undo' }, { role: 'redo' }, { type: 'separator' }, { role: 'cut' }, { role: 'copy' }, { role: 'paste' }]
    }, {
        label: 'Window',
        submenu: [{role: 'togglefullscreen'}]
    }, {
        label: 'Help',
        submenu: [{
            label: 'GitHub Repository',
            click: () => {
                electron.shell.openExternal('https://github.com/ajaysreedhar/kongdash');
            }
        }, {
            label: 'Report Issues',
            click: () => {
                electron.shell.openExternal('https://github.com/ajaysreedhar/kongdash/issues');
            }
        }, {
            type: 'separator'
        }, {
            label: 'About KongDash',
            click: () => {
                electron.shell.openExternal('https://ajaysreedhar.github.io/kongdash/');
            }
        }]
    }];

    let menu = Menu.buildFromTemplate(menuTemplate);

    if (process.platform === 'darwin' || process.platform === 'mas') {
        Menu.setApplicationMenu(menu);

    } else {
        window.setMenu(menu);
    }
});

app.on('window-all-closed', () => {
    if(process.platform !== 'darwin') app.quit();
});

ipcMain.on('get-config', (event, arg) => {
    if (arg === 'VERSION') {
        event.returnValue = VERSION;
        return;
    }

    event.returnValue = appConfig[arg];
});

ipcMain.on('write-config', (event, arg) => {
    appConfig[arg.name] = arg.config;

    jsonfile.writeFile(configFile, appConfig, function (error) {
        if (error) {
            event.sender.send('write-config-error', {message: 'Could not write configuration file.' + error});

        } else {
            event.sender.send('write-config-success', {message: 'Configuration saved successfully'});
        }
    });
});

ipcMain.on('open-external', (event, arg) => {
    electron.shell.openExternal(arg);
});
<commit_msg>add: app name constant<commit_after>'use strict';

const APP_NAME = 'KongDash';
const VERSION = '0.3.0';

const electron  = require('electron');
const path      = require('path');
const ospath = require('ospath');
const jsonfile  = require('jsonfile');

let absPath = path.dirname(__dirname), configFile = ospath.data() + '/' + APP_NAME + '/config.json';
let {app, ipcMain, BrowserWindow, Menu} = electron;
let mainWindow, appConfig = {kong: {}, app: {enableAnimation: true}};

let startMainWindow = function () {
    mainWindow = new BrowserWindow({
        backgroundColor: '#1A242D',
        width: 1100,
        height: 580,
        center: true,
        title: app.getName(),
        minHeight: 500,
        minWidth: 900,
        icon: absPath + '/kongdash-256x256.png'
    });
    mainWindow.loadURL('file://' + absPath + '/src/initialize.html');

    /* Debugging
    mainWindow.webContents.openDevTools();
    //*/

    mainWindow.on('closed', () => {
        mainWindow = null;
    });
};

app.setName(APP_NAME);

app.on('ready', () => {
    try {
        appConfig = jsonfile.readFileSync(configFile);

    } catch (e) {
        /* Ignore. Uses default settings. */
    } finally {
        startMainWindow();
    }
});

app.on('activate', () => {
    if (mainWindow === null) startMainWindow();
});

app.on('browser-window-created', (e, window) => {
    let menuTemplate = [{
        label: 'File',
        submenu: [{
            label: 'Settings',
            click: () => {
                mainWindow.webContents.send('open-settings-view', '');
            }
        }, { type: 'separator' }, { role: 'quit' }]
    }, {
        label: 'Edit',
        submenu: [{ role: 'undo' }, { role: 'redo' }, { type: 'separator' }, { role: 'cut' }, { role: 'copy' }, { role: 'paste' }]
    }, {
        label: 'Window',
        submenu: [{role: 'togglefullscreen'}]
    }, {
        label: 'Help',
        submenu: [{
            label: 'GitHub Repository',
            click: () => {
                electron.shell.openExternal('https://github.com/ajaysreedhar/kongdash');
            }
        }, {
            label: 'Report Issues',
            click: () => {
                electron.shell.openExternal('https://github.com/ajaysreedhar/kongdash/issues');
            }
        }, {
            type: 'separator'
        }, {
            label: 'About KongDash',
            click: () => {
                electron.shell.openExternal('https://ajaysreedhar.github.io/kongdash/');
            }
        }]
    }];

    let menu = Menu.buildFromTemplate(menuTemplate);

    if (process.platform === 'darwin' || process.platform === 'mas') {
        Menu.setApplicationMenu(menu);

    } else {
        window.setMenu(menu);
    }
});

app.on('window-all-closed', () => {
    if(process.platform !== 'darwin') app.quit();
});

ipcMain.on('get-config', (event, arg) => {
    if (arg === 'VERSION') {
        event.returnValue = VERSION;
        return;
    }

    event.returnValue = appConfig[arg];
});

ipcMain.on('write-config', (event, arg) => {
    appConfig[arg.name] = arg.config;

    jsonfile.writeFile(configFile, appConfig, function (error) {
        if (error) {
            event.sender.send('write-config-error', {message: 'Could not write configuration file.' + error});

        } else {
            event.sender.send('write-config-success', {message: 'Configuration saved successfully'});
        }
    });
});

ipcMain.on('open-external', (event, arg) => {
    electron.shell.openExternal(arg);
});
<|endoftext|>


<commit_before>import Tabs from './components/Tabs';
import TabList from './components/TabList';
import Tab from './components/Tab';
import TabPanel from './components/TabPanel';

export {
  Tabs,
  TabList,
  Tab,
  TabPanel,
};

// For bc we also export a default object, remove in 1.0
export default {
  Tabs,
  TabList,
  Tab,
  TabPanel,
};
<commit_msg>Export adjustments<commit_after>export { Tabs } from './components/Tabs';
export { TabList } from './components/TabList';
export { Tab } from './components/Tab';
export { TabPanel } from './components/TabPanel';
<|endoftext|>


<commit_before>"use strict";
/**
 * Main script
 */
Error.stackTraceLimit = Infinity;

var mode = process.argv[2];
if (!mode) {
    process.stdout.write("Usage: node main.js start|update-all-widgets|install-widget|install-core-widgets");
    process.exit(0);
    return;
}

if (mode == "start") {
    require(__dirname + "/routes");
    require(__dirname + "/rconserver");
    require(__dirname + "/websocketmgr");
    require(__dirname + "/steamapi");
    require(__dirname + "/config");
    return;
}

var Widget = require(__dirname + "/widget");

// update all existing widgets
if (mode == "update-all-widgets") {
    var widgets = Widget.getAllWidgetIds();
    var cbCount = 0;
    for (var i = 0; i < widgets.length; i++) {
        var widget = Widget.get(widgets[i]);
        if (widget && widget.manifest) {
            (function (widget) {
                Widget.install(widget.manifest.repository, function (success) {
                    process.stdout.write("Widget " + widget.manifest.repository + " " + (success ? "successfully updated" : "error") + "\n");
                    cbCount++;
                    if (cbCount == widgets.length) {
                        process.exit(0);
                    }
                });
            })(widget);
        }
    }
}

// update core
if (mode == "update-core") {
    var request = require(__dirname + "/request");
    var fs = require("fs");
    var unzip = require("unzip");
    request.get("https://codeload.github.com/brainfoolong/rcon-web-admin/zip/master", true, function (contents) {
        if (!contents.length) {
            console.error("Cannot load rcon-web-admin zip file");
            process.exit(0);
            return;
        }
        var dir = __dirname + "/..";
        fs.writeFile(dir + "/master.zip", contents, {"mode": 0o777}, function () {
            fs.createReadStream(dir + "/master.zip").pipe(unzip.Parse()).on('entry', function (entry) {
                var fileName = entry.path.split("/").slice(1).join("/");
                if (!fileName.length) return;
                var path = dir + "/" + fileName;
                if (entry.type == "Directory") {
                    if(!fs.existsSync(path)) fs.mkdirSync(path, 0o777);
                    entry.autodrain();
                } else {
                    entry.pipe(fs.createWriteStream(path));
                }
            }).on("close", function () {
                fs.unlinkSync(dir + "/master.zip");
                process.exit(0);
            });
        });
    });
}

// update/install a single widget
if (mode == "install-widget") {
    var widgetRepository = process.argv[3];
    if (!widgetRepository) {
        process.stdout.write("Usage: node main.js install-widget widgetRepositoryHere");
        return;
    }
    Widget.install(widgetRepository, function (success) {
        process.stdout.write("Widget " + widgetRepository + " " + (success ? "successfully installed" : "error") + "\n");
        process.exit(0);
    });
}

// install core widgets
if (mode == "install-core-widgets") {
    var coreWidgets = [
        "brainfoolong/rwa-autobot",
        "brainfoolong/rwa-console",
        "brainfoolong/rwa-restart",
        "brainfoolong/rwa-rustboard",
        "brainfoolong/rwa-shutdown"
    ];
    var cbCount = 0;
    for (var i = 0; i < coreWidgets.length; i++) {
        (function (index) {
            Widget.install(coreWidgets[index], function (success) {
                process.stdout.write("Widget " + coreWidgets[index] + " " + (success ? "successfully installed" : "error") + "\n");
                cbCount++;
                if (cbCount == coreWidgets.length) {
                    process.exit(0);
                }
            });
        })(i);
    }
}<commit_msg>updates for core updates<commit_after>"use strict";
/**
 * Main script
 */
Error.stackTraceLimit = Infinity;

var mode = process.argv[2];
if (!mode) {
    process.stdout.write("Usage: node main.js start|update-all-widgets|install-widget|install-core-widgets");
    process.exit(0);
    return;
}

if (mode == "start") {
    require(__dirname + "/routes");
    require(__dirname + "/rconserver");
    require(__dirname + "/websocketmgr");
    require(__dirname + "/steamapi");
    require(__dirname + "/config");
    return;
}

var Widget = require(__dirname + "/widget");

// update all existing widgets
if (mode == "update-all-widgets") {
    var widgets = Widget.getAllWidgetIds();
    var cbCount = 0;
    for (var i = 0; i < widgets.length; i++) {
        var widget = Widget.get(widgets[i]);
        if (widget && widget.manifest) {
            (function (widget) {
                Widget.install(widget.manifest.repository, function (success) {
                    process.stdout.write("Widget " + widget.manifest.repository + " " + (success ? "successfully updated" : "error") + "\n");
                    cbCount++;
                    if (cbCount == widgets.length) {
                        process.exit(0);
                    }
                });
            })(widget);
        }
    }
}

// update core
if (mode == "update-core") {
    var request = require(__dirname + "/request");
    var fs = require("fs");
    var unzip = require("unzip");
    request.get("https://codeload.github.com/brainfoolong/rcon-web-admin/zip/master", true, function (contents) {
        if (!contents.length) {
            console.error("Cannot load rcon-web-admin zip file");
            process.exit(0);
            return;
        }
        var dir = __dirname + "/..";
        fs.writeFile(dir + "/master.zip", contents, {"mode": 0o777}, function () {
            fs.createReadStream(dir + "/master.zip").pipe(unzip.Parse()).on('entry', function (entry) {
                var fileName = entry.path.split("/").slice(1).join("/");
                if (!fileName.length) return;
                var path = dir + "/" + fileName;
                if (entry.type == "Directory") {
                    if(!fs.existsSync(path)) fs.mkdirSync(path, 0o777);
                    entry.autodrain();
                } else {
                    entry.pipe(fs.createWriteStream(path));
                }
            }).on("close", function () {
                process.stdout.write("Rcon web admin successfully updated");
                fs.unlinkSync(dir + "/master.zip");
                process.exit(0);
            });
        });
    });
}

// update/install a single widget
if (mode == "install-widget") {
    var widgetRepository = process.argv[3];
    if (!widgetRepository) {
        process.stdout.write("Usage: node main.js install-widget widgetRepositoryHere");
        return;
    }
    Widget.install(widgetRepository, function (success) {
        process.stdout.write("Widget " + widgetRepository + " " + (success ? "successfully installed" : "error") + "\n");
        process.exit(0);
    });
}

// install core widgets
if (mode == "install-core-widgets") {
    var coreWidgets = [
        "brainfoolong/rwa-autobot",
        "brainfoolong/rwa-console",
        "brainfoolong/rwa-restart",
        "brainfoolong/rwa-rustboard",
        "brainfoolong/rwa-shutdown"
    ];
    var cbCount = 0;
    for (var i = 0; i < coreWidgets.length; i++) {
        (function (index) {
            Widget.install(coreWidgets[index], function (success) {
                process.stdout.write("Widget " + coreWidgets[index] + " " + (success ? "successfully installed" : "error") + "\n");
                cbCount++;
                if (cbCount == coreWidgets.length) {
                    process.exit(0);
                }
            });
        })(i);
    }
}<|endoftext|>


<commit_before>require.config({
    baseUrl: "static/src/",
    paths: {
      'text': '../vendor/require/text',
      'json': '../vendor/require/json',
      'underscore': '../vendor/underscore/underscore',
      'jquery': '../vendor/jquery/jquery',
      'handlebars': '../vendor/handlebars/handlebars',
      'backbone': '../vendor/backbone/backbone',
      'd3': '../vendor/d3/d3.v3',
      'topojson': '../vendor/topojson/topojson'
    },
    shim: {
        'underscore': {
            exports: '_'
        },
        'jquery': {
          exports: '$'
        },
        'handlebars': {
          exports: 'Handlebars'
        },
        'backbone': {
            //These script dependencies should be loaded before loading
            //backbone.js
            deps: ['underscore'],
            //Once loaded, use the global 'Backbone' as the
            //module value.
            exports: 'Backbone'
        },
        'd3': {
          exports: 'd3'
        },
    }
});

requirejs([
    'require',
    'jquery',
    'underscore',
    'backbone',
    'qoogr/src/qoogr'
  ],
  function(require, _, $, Backbone, Qoogr) {

  var AppController = Backbone.View.extend({

    el: $('body'),

    initialize: function() {
      this.qoogr = new Qoogr.QoogrController();
    },

  });

  window.app_con = new AppController();

});

<commit_msg>Subclass Qoogr.ControlsView and add CheckboxChoicesView as subview<commit_after>require.config({
    baseUrl: "static/src/",
    paths: {
      'text': '../vendor/require/text',
      'json': '../vendor/require/json',
      'underscore': '../vendor/underscore/underscore',
      'jquery': '../vendor/jquery/jquery',
      'handlebars': '../vendor/handlebars/handlebars',
      'backbone': '../vendor/backbone/backbone',
      'd3': '../vendor/d3/d3.v3',
      'topojson': '../vendor/topojson/topojson'
    },
    shim: {
        'underscore': {
            exports: '_'
        },
        'jquery': {
          exports: '$'
        },
        'handlebars': {
          exports: 'Handlebars'
        },
        'backbone': {
            //These script dependencies should be loaded before loading
            //backbone.js
            deps: ['underscore'],
            //Once loaded, use the global 'Backbone' as the
            //module value.
            exports: 'Backbone'
        },
        'd3': {
          exports: 'd3'
        },
    }
});

requirejs([
    'require',
    'jquery',
    'underscore',
    'backbone',
    'qoogr/src/qoogr',
    'qgr-cntrl-checkbox/src/qgr-cntrl-checkbox'
  ],
  function(require, $, _, Backbone, Qoogr, QgrCheckbox) {

  var ControlsView = Qoogr.ControlsView.extend({

    initialize: function(options) {
      this.global_q = this.options.global_q;
      this.render();
      // Set up individual filter widgets here.
      this.color_choices = new QgrCheckbox.CheckboxChoices([
        {choice_val: 'qoral'},
        {choice_val: 'qrimson'},
        {choice_val: 'xhrtreuse'}
      ]);
      this.checkboxes_view  = new QgrCheckbox.CheckboxChoicesView({
        el: '#color-choices',
        choices: this.color_choices,
        col: 'color',
        global_q: this.global_q
      });
    },

  });

  var AppController = Backbone.View.extend({

    el: $('body'),

    initialize: function() {
      this.qoogr = new Qoogr.Controller({
        controls_class: ControlsView
      });
    },

  });

  window.app_con = new AppController();

});

<|endoftext|>


<commit_before>const { ipcRenderer, remote } = require("electron");
const fs = require("fs");
const FileManager = require("./api/fileManager");

window.onload = () => {
    /*loader().then((monaco) => {
        let editor = monaco.editor.create(document.getElementById("container"), {
            language: "javascript",
            theme: "vs-dark",
            cursorBlinking: "smooth",
            cursorStyle: "line"
        });

        let fileManager = new FileManager({editor});

        ipcRenderer.on("navigate", (e, url) => {
            url = url.slice(8);
            fs.readFile(url, "utf8", (error, result) => { if(!error) editor.setModel(monaco.editor.createModel(result, "javascript")); });
        });

        $("#f__open").click(function() { fileManager.openFile() });
        $("#f__save").click(function() { fileManager.saveFile() });
    });*/
}
<commit_msg>Removed unused code<commit_after>const { ipcRenderer, remote } = require("electron");
const { app, BrowserWindow }  = require("electron");
const fs = require("fs");

window.onload = () => {

}
<|endoftext|>


<commit_before>(function(document, location, history) { /* jshint maxdepth:8, boss:true */
    "use strict";

    // do not enable the plugin for old browsers
    if (typeof history.pushState !== "function") return;

    const identity = (s) => s;
    const reTitle = /<title>(.*?)<\/title>/;
    const states = []; // in-memory storage for states
    var lastState = {}, lastFormData;

    function attachNonPreventedListener(eventType, callback) {
        document.addEventListener(eventType, function(e) {
            if (!e.defaultPrevented) {
                callback(e);
            }
        }, false);
    }

    function dispatchAjaxifyEvent(el, eventType, eventDetail) {
        const e = document.createEvent("CustomEvent");

        e.initCustomEvent("ajaxify:" + eventType, true, true, eventDetail || null);

        return el.dispatchEvent(e);
    }

    function updateState(state, detail) {
        const body = document.body;

        if (dispatchAjaxifyEvent(body, "update", detail)) {
            // by default just swap body elements
            body.parentNode.replaceChild(state.body, body);
        }

        if (states.indexOf(lastState) < 0) {
            // if state does not exist - store it in memory
            states.push(lastState);
        }

        document.title = state.title;
    }

    function createDocument(htmlText) {
        const titleMatch = reTitle.exec(htmlText);
        const doc = document.implementation.createHTMLDocument(titleMatch && titleMatch[1] || "");

        doc.body.innerHTML = htmlText.trim().replace(titleMatch && titleMatch[0], "");

        return doc;
    }

    attachNonPreventedListener("click", (e) => {
        const body = document.body;

        for (var el = e.target; el && el !== body; el = el.parentNode) {
            if (el.nodeName.toLowerCase() === "a") {
                if (!el.target) {
                    const targetUrl = el.href;

                    if (el.getAttribute("aria-disabled") === "true") {
                        e.preventDefault();
                    } else if (targetUrl && targetUrl.indexOf("http") === 0) {
                        const currentUrl = location.href;

                        if (targetUrl === currentUrl || targetUrl.split("#")[0] !== currentUrl.split("#")[0]) {
                            if (dispatchAjaxifyEvent(el, "fetch")) {
                                // override default bahavior for links
                                e.preventDefault();
                            }
                        } else {
                            location.hash = el.hash;
                            // override default bahavior for anchors
                            e.preventDefault();
                        }
                    }
                }

                break;
            }
        }
    });

    attachNonPreventedListener("submit", (e) => {
        const el = e.target;

        if (!el.target) {
            if (el.getAttribute("aria-disabled") === "true") {
                e.preventDefault();
            } else {
                const formEnctype = el.getAttribute("enctype");

                var data;

                if (formEnctype === "multipart/form-data") {
                    data = new FormData(el);
                } else {
                    data = {};

                    for (var i = 0, field; field = el.elements[i]; ++i) {
                        const fieldType = field.type;

                        if (fieldType && field.name && !field.disabled) {
                            const fieldName = field.name;

                            if (fieldType === "select-multiple") {
                                for (var j = 0, option; option = field.options[j]; ++j) {
                                    if (option.selected) {
                                        (data[fieldName] = data[fieldName] || []).push(option.value);
                                    }
                                }
                            } else if ((fieldType !== "checkbox" && fieldType !== "radio") || field.checked) {
                                data[fieldName] = field.value;
                            }
                        }
                    }
                }

                if (!dispatchAjaxifyEvent(el, "serialize", data)) {
                    e.preventDefault();
                } else {
                    if (data instanceof FormData) {
                        lastFormData = data;
                    } else {
                        const encode = formEnctype === "text/plain" ? identity : encodeURIComponent;
                        const reSpace = encode === identity ? / /g : /%20/g;

                        lastFormData = Object.keys(data).map((key) => {
                            const name = encode(key);
                            var value = data[key];

                            if (Array.isArray(value)) {
                                value = value.map(encode).join("&" + name + "=");
                            }

                            return name + "=" + encode(value);
                        }).join("&").replace(reSpace, "+");
                    }

                    if (dispatchAjaxifyEvent(el, "fetch")) {
                        e.preventDefault();
                    }

                    lastFormData = null; // cleanup internal reference
                }
            }
        }
    });

    attachNonPreventedListener("ajaxify:fetch", (e) => {
        const el = e.target;
        const detail = e.detail;

        if (detail && detail.nodeType === 9) {
            const state = {body: detail.body, title: detail.title};

            updateState(state, detail);

            lastState = {}; // create a new state object

            if (detail.URL !== location.href) {
                history.pushState(states.length, state.title, detail.URL);
            }
        } else {
            const xhr = new XMLHttpRequest();
            const method = (el.method || "GET").toUpperCase();
            const nodeName = el.nodeName.toLowerCase();
            const nodeType = el.nodeType;

            var url = detail;

            if (nodeName === "a") {
                url = url || el.href;
            } else if (nodeName === "form") {
                url = url || el.action;

                if (method === "GET" && lastFormData) {
                    url += (~url.indexOf("?") ? "&" : "?") + lastFormData;
                    // for get forms append all data to url
                    lastFormData = null;
                }
            }

            ["abort", "error", "load", "timeout"].forEach((type) => {
                xhr["on" + type] = () => {
                    if (nodeType === 1) {
                        el.removeAttribute("aria-disabled");
                    }

                    const res = xhr.response;
                    var url = xhr.responseURL;
                    // polyfill xhr.responseURL value
                    if (!url && res && res.URL) {
                        url = xhr.getResponseHeader("Location");

                        if (url) {
                            url = location.origin + url;
                            // patch XHR object to set responseURL
                            Object.defineProperty(xhr, "responseURL", {get: () => url});
                        }
                    }

                    if (dispatchAjaxifyEvent(el, type, xhr) && type === "load") {
                        const defaultTitle = xhr.status + " " + xhr.statusText;
                        const doc = res || document.implementation.createHTMLDocument(defaultTitle);
                        const state = {body: doc.body, title: doc.title || defaultTitle};

                        updateState(state, doc);

                        lastState = {}; // create a new state object

                        if (url !== location.href) {
                            history.pushState(states.length, state.title, url);
                        }
                    }
                };
            });

            xhr.open(method, url, true);
            xhr.responseType = "document";

            if (dispatchAjaxifyEvent(el, "send", xhr)) {
                xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");

                if (method !== "GET") {
                    xhr.setRequestHeader("Content-Type", el.getAttribute("enctype") || el.enctype);
                }

                xhr.send(lastFormData);

                if (nodeType === 1) {
                    el.setAttribute("aria-disabled", "true");
                }
            }
        }
    });

    document.addEventListener("ajaxify:update", (e) => {
        lastState.body = e.target;
        lastState.title = document.title;
    }, true);

    window.addEventListener("popstate", (e) => {
        // numeric value indicates better-ajaxify state
        if (!e.defaultPrevented && e.state >= 0) {
            const state = states[e.state];

            if (state) {
                updateState(state, state.body);

                lastState = state;
            }
        }
    });

    // update initial state address url
    history.replaceState(0, document.title);

}(window.document, window.location, window.history));
<commit_msg>add support for data-selector<commit_after>(function(document, location, history) { /* jshint maxdepth:8, boss:true */
    "use strict";

    // do not enable the plugin for old browsers
    if (typeof history.pushState !== "function") return;

    const identity = (s) => s;
    const states = []; // in-memory storage for states
    var lastState = {}, lastFormData;

    function attachNonPreventedListener(eventType, callback) {
        document.addEventListener(eventType, function(e) {
            if (!e.defaultPrevented) {
                callback(e);
            }
        }, false);
    }

    function dispatchAjaxifyEvent(el, type, detail) {
        const e = document.createEvent("CustomEvent");
        e.initCustomEvent("ajaxify:" + type, true, true, detail || null);
        return el.dispatchEvent(e);
    }

    function updateState(state, detail) {
        var target = document.body;

        if (detail.nodeType === 9) {
            state.selector = detail.body.getAttribute("data-selector");
        }

        if (state.selector) {
            // try to find the target
            target = document.querySelector(state.selector);
            if (target) {
                lastState.selector = state.selector;
            } else {
                target = document.body;
            }
        }

        if (detail.nodeType === 9) {
            // prepare target content
            state.body = target.cloneNode(false);
            // move all elements to replacement
            for (var node = detail.body.firstChild; !!node; node = detail.body.firstChild) {
                state.body.appendChild(node);
            }
        }

        if (dispatchAjaxifyEvent(target, "update", state.body)) {
            // by default just swap elements
            target.parentNode.replaceChild(state.body, target);
        }

        lastState.body = target;
        lastState.title = document.title;
        if (states.indexOf(lastState) < 0) {
            // if state does not exist - store it in memory
            states.push(lastState);
        }

        document.title = state.title;
    }

    attachNonPreventedListener("click", (e) => {
        const body = document.body;

        for (var el = e.target; el && el !== body; el = el.parentNode) {
            if (el.nodeName.toLowerCase() === "a") {
                if (!el.target) {
                    const targetUrl = el.href;

                    if (el.getAttribute("aria-disabled") === "true") {
                        e.preventDefault();
                    } else if (targetUrl && targetUrl.indexOf("http") === 0) {
                        const currentUrl = location.href;

                        if (targetUrl === currentUrl || targetUrl.split("#")[0] !== currentUrl.split("#")[0]) {
                            if (dispatchAjaxifyEvent(el, "fetch")) {
                                // override default bahavior for links
                                e.preventDefault();
                            }
                        } else {
                            location.hash = el.hash;
                            // override default bahavior for anchors
                            e.preventDefault();
                        }
                    }
                }

                break;
            }
        }
    });

    attachNonPreventedListener("submit", (e) => {
        const el = e.target;

        if (!el.target) {
            if (el.getAttribute("aria-disabled") === "true") {
                e.preventDefault();
            } else {
                const formEnctype = el.getAttribute("enctype");

                var data;

                if (formEnctype === "multipart/form-data") {
                    data = new FormData(el);
                } else {
                    data = {};

                    for (var i = 0, field; field = el.elements[i]; ++i) {
                        const fieldType = field.type;

                        if (fieldType && field.name && !field.disabled) {
                            const fieldName = field.name;

                            if (fieldType === "select-multiple") {
                                for (var j = 0, option; option = field.options[j]; ++j) {
                                    if (option.selected) {
                                        (data[fieldName] = data[fieldName] || []).push(option.value);
                                    }
                                }
                            } else if ((fieldType !== "checkbox" && fieldType !== "radio") || field.checked) {
                                data[fieldName] = field.value;
                            }
                        }
                    }
                }

                if (!dispatchAjaxifyEvent(el, "serialize", data)) {
                    e.preventDefault();
                } else {
                    if (data instanceof FormData) {
                        lastFormData = data;
                    } else {
                        const encode = formEnctype === "text/plain" ? identity : encodeURIComponent;
                        const reSpace = encode === identity ? / /g : /%20/g;

                        lastFormData = Object.keys(data).map((key) => {
                            const name = encode(key);
                            var value = data[key];

                            if (Array.isArray(value)) {
                                value = value.map(encode).join("&" + name + "=");
                            }

                            return name + "=" + encode(value);
                        }).join("&").replace(reSpace, "+");
                    }

                    if (dispatchAjaxifyEvent(el, "fetch")) {
                        e.preventDefault();
                    }

                    lastFormData = null; // cleanup internal reference
                }
            }
        }
    });

    attachNonPreventedListener("ajaxify:fetch", (e) => {
        const el = e.target;
        const detail = e.detail;

        if (detail && detail.nodeType === 9) {
            const state = {title: detail.title};

            updateState(state, detail);

            lastState = {}; // create a new state object

            if (detail.URL !== location.href) {
                history.pushState(states.length, state.title, detail.URL);
            }
        } else {
            const xhr = new XMLHttpRequest();
            const method = (el.method || "GET").toUpperCase();
            const nodeName = el.nodeName.toLowerCase();
            const nodeType = el.nodeType;

            var url = detail;

            if (nodeName === "a") {
                url = url || el.href;
            } else if (nodeName === "form") {
                url = url || el.action;

                if (method === "GET" && lastFormData) {
                    url += (~url.indexOf("?") ? "&" : "?") + lastFormData;
                    // for get forms append all data to url
                    lastFormData = null;
                }
            }

            ["abort", "error", "load", "timeout"].forEach((type) => {
                xhr["on" + type] = () => {
                    if (nodeType === 1) {
                        el.removeAttribute("aria-disabled");
                    }

                    const res = xhr.response;
                    var url = xhr.responseURL;
                    // polyfill xhr.responseURL value
                    if (!url && res && res.URL) {
                        url = xhr.getResponseHeader("Location");

                        if (url) {
                            url = location.origin + url;
                            // patch XHR object to set responseURL
                            Object.defineProperty(xhr, "responseURL", {get: () => url});
                        }
                    }

                    if (dispatchAjaxifyEvent(el, type, xhr) && type === "load") {
                        const defaultTitle = xhr.status + " " + xhr.statusText;
                        const doc = res || document.implementation.createHTMLDocument(defaultTitle);
                        const state = {title: doc.title || defaultTitle};

                        updateState(state, doc);

                        lastState = {}; // create a new state object

                        if (url !== location.href) {
                            history.pushState(states.length, state.title, url);
                        }
                    }
                };
            });

            xhr.open(method, url, true);
            xhr.responseType = "document";

            if (dispatchAjaxifyEvent(el, "send", xhr)) {
                xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");

                if (method !== "GET") {
                    xhr.setRequestHeader("Content-Type", el.getAttribute("enctype") || el.enctype);
                }

                xhr.send(lastFormData);

                if (nodeType === 1) {
                    el.setAttribute("aria-disabled", "true");
                }
            }
        }
    });

    window.addEventListener("popstate", (e) => {
        // numeric value indicates better-ajaxify state
        if (!e.defaultPrevented && e.state >= 0) {
            const state = states[e.state];

            if (state) {
                updateState(state, state.body);

                lastState = state;
            }
        }
    });

    // update initial state address url
    history.replaceState(0, document.title);

}(window.document, window.location, window.history));
<|endoftext|>


<commit_before>import App from './App.vue'
import Vue from 'vue'
import Vuex from 'vuex'
import VueRouter from 'vue-router'
import store from './js/store/index'
const bootstrap = require('./js/bootstrap/autoload')
require('./sass/app.scss')
require(`./sass/themes/${bootstrap.theme}`)

/**
 * Uncomment this line when running npm run offline.
 * This setup SW + AppCache and make Buuk a progressive app.
 */
require('./pwa')

Vue.use(Vuex)
Vue.use(VueRouter)

const router = new VueRouter({
    routes: bootstrap.routes
})

new Vue({
    el: '#app',
    store,
    router,
    render: h => h(App)
})<commit_msg>Minor comment change.<commit_after>import App from './App.vue'
import Vue from 'vue'
import Vuex from 'vuex'
import VueRouter from 'vue-router'
import store from './js/store/index'
const bootstrap = require('./js/bootstrap/autoload')
require('./sass/app.scss')
require(`./sass/themes/${bootstrap.theme}`)

/**
 * Uncomment this line when running npm run pwa.
 * This setup SW + AppCache and make Buuk a progressive app.
 */
require('./pwa')

Vue.use(Vuex)
Vue.use(VueRouter)

const router = new VueRouter({
    routes: bootstrap.routes
})

new Vue({
    el: '#app',
    store,
    router,
    render: h => h(App)
})<|endoftext|>


<commit_before>/**
 * scania-angular-ui
 * https://github.com/scania-bootstrap/scania-angular-ui
 * License: MIT
 *
 *
 */

(function () {
    'use strict';

    angular.module('scania.angular.ui', ['scania.angular.lightbox', 'scania.angular.select2']);

    /**
     * @ngdoc module
     * @name scania.angular.lightbox
     *
     * @description
     * Scania lightbox module
     */
    angular.module('scania.angular.lightbox', ['flow', 'ui.bootstrap']).directive('scLightbox', ['$scmodal', scLightbox]);
    /**
     /**
     * @ngdoc directive
     * @name scLightbox
     * @module scania.angular.lightbox
     *
     * @description file upload and gallery extension on angularJs framework
     * @param $scmodal
     * @returns {{restrict: string, templateUrl: string, controllerAs: string, controller: Function}}
     */

    function scLightbox($scmodal) {

        return {
            restrict: 'AEC',
            templateUrl: 'template/scania-angular-upload.html',
            controllerAs: 'lightbox',
            controller: function ($scope, $attrs) {
                $animate.enabled(false); // to solve the conflict between ngAnimate and ui-bootstrap animate
                var self = this;

                self.interval = $attrs.interval;
                self.open = function (index) {
                    $scope.slides = self.flow.files;
                    $scope.slides[index].active = true;
                    self.activeImage = $scope.slides[index];

                    self.modalInstance = $scmodal.open({
                        animation: $attrs.animation,
                        templateUrl: 'template/scania-angular-lightbox.html',
                        size: $attrs.size,
                        windowClass: $attrs.windowclass,
                        scope: $scope,
                        resolve: {
                            slides: function () {
                                return $scope.slides;
                            }
                        },
                        controller: function ($scope) {
                            $scope.setAsActive = function (slide) {
                                if (slide.active) {
                                    self.activeImage = slide;
                                }
                            };
                        }
                    });
                };
                self.deleteImage = function () {
                    self.activeImage.cancel();
                    if ($scope.slides.length === 0) {
                        self.modalInstance.dismiss();
                    }
                };
            }
        };
    }

    /**
     * @ngdoc module
     * @name scania.angular.select2
     *
     * @description
     * Scania select2 directive module
     */
    angular.module('scania.angular.select2', []).directive('scSelect2', ['$compile', '$timeout', scSelect2]);

    /**
     * @ngdoc directive
     * @name scLightbox
     * @module scania.angular.select2
     *
     * @description AngularJS directive for Select2
     * @param $compile
     * @param $timeout
     * @returns {{restrict: string, scope: {ngModel: string, templateSelection: string, templateResult: string}, link: Function}}
     */
    function scSelect2($compile, $timeout) {
        return {
            restrict: 'A',
            scope: {
                ngModel: '=',
                templateSelection: '=',
                templateResult: '=',
                matcher: '='
            },
            link: function ($scope, element, $attr) {
                if ($attr.language) {
                    var domElem = '<script src="/bower_components/select2/select2_locale_' + $attr.language + '.js" async defer></script>';
                    $(element).append($compile(domElem)($scope));
                }
                var options = _.pick($(element).data(), function (value, key) {
                    return !startsWith(key, '$');
                });
                options.formatSelection = $scope.templateSelection || $.fn.select2.defaults.formatSelection;
                options.formatResult = $scope.templateResult || $.fn.select2.defaults.formatResult;
                options.matcher = $scope.matcher || $.fn.select2.defaults.matcher;
                var selectorName = $attr.multiple ? 'multiselect' : 'select',
                    select = {};

                $timeout(function () {
                    select = $('select.sc-' + selectorName + '[id="' + $attr.id + '"]');
                    select.select2(options);
                    updateSelectedItemsOnDisplay();

                    $scope.$watch( 'ngModel', function() {
                        updateSelectedItemsOnDisplay();
                    });
                });

                // Access ngModel, $attr.multiple, select, options.value,
                function updateSelectedItemsOnDisplay() {
                    if (!$scope.ngModel) return;

                    //True for both single and multiselect
                    if ($scope.ngModel.then && typeof $scope.ngModel.then === 'function') {
                        $scope.ngModel.then(function (response) {
                            //Multi select can have 1 or several default selected options,use each to initialize the select
                            //Single select has 1 default selected option, no iteration is needed to initialize the select
                            var selectedItems = $attr.multiple ? response.data : new Array(response.data);
                            populatePreselectedOptions(select, selectedItems, options.value);
                        });
                    }
                    else {
                        if (!_.isArray($scope.ngModel) && !_.isObject($scope.ngModel)) return;
                        var selectedItems = _.isArray($scope.ngModel) ? $scope.ngModel : new Array($scope.ngModel);
                        populatePreselectedOptions(select, selectedItems, options.value);
                    }
                };

            }
        };

        function populatePreselectedOptions(scSelect, selectedItems, key) {
            //throw "Data-value for " + scSelect[0].id +" must have the same value as its track by.";
            var selectedOptions = [];
            _.each(selectedItems, function (selectedItem) {
                var selectedId = selectedItem[key];
                var selectedOption = _.find(scSelect[0], function (option) {
                    return selectedId == option.value;
                });
                if(!selectedOption) {
                    console.error("Data-value for " + scSelect[0].id +" must have the same value as its track by.");
                    return;
                }
                selectedOptions.push({id: selectedId, text: selectedOption.label});

            });
            if (selectedItems.length == 1) selectedOptions = selectedOptions.pop();
            scSelect.select2('data', selectedOptions);
        }

        function startsWith(str, target) {
            return str.indexOf(target) === 0;
        }
    }

})();
<commit_msg>Added default minimum-resultsFor-search of 10<commit_after>/**
 * scania-angular-ui
 * https://github.com/scania-bootstrap/scania-angular-ui
 * License: MIT
 *
 *
 */

(function () {
    'use strict';

    angular.module('scania.angular.ui', ['scania.angular.lightbox', 'scania.angular.select2']);

    /**
     * @ngdoc module
     * @name scania.angular.lightbox
     *
     * @description
     * Scania lightbox module
     */
    angular.module('scania.angular.lightbox', ['flow', 'ui.bootstrap']).directive('scLightbox', ['$scmodal', scLightbox]);
    /**
     /**
     * @ngdoc directive
     * @name scLightbox
     * @module scania.angular.lightbox
     *
     * @description file upload and gallery extension on angularJs framework
     * @param $scmodal
     * @returns {{restrict: string, templateUrl: string, controllerAs: string, controller: Function}}
     */

    function scLightbox($scmodal) {

        return {
            restrict: 'AEC',
            templateUrl: 'template/scania-angular-upload.html',
            controllerAs: 'lightbox',
            controller: function ($scope, $attrs) {
                $animate.enabled(false); // to solve the conflict between ngAnimate and ui-bootstrap animate
                var self = this;

                self.interval = $attrs.interval;
                self.open = function (index) {
                    $scope.slides = self.flow.files;
                    $scope.slides[index].active = true;
                    self.activeImage = $scope.slides[index];

                    self.modalInstance = $scmodal.open({
                        animation: $attrs.animation,
                        templateUrl: 'template/scania-angular-lightbox.html',
                        size: $attrs.size,
                        windowClass: $attrs.windowclass,
                        scope: $scope,
                        resolve: {
                            slides: function () {
                                return $scope.slides;
                            }
                        },
                        controller: function ($scope) {
                            $scope.setAsActive = function (slide) {
                                if (slide.active) {
                                    self.activeImage = slide;
                                }
                            };
                        }
                    });
                };
                self.deleteImage = function () {
                    self.activeImage.cancel();
                    if ($scope.slides.length === 0) {
                        self.modalInstance.dismiss();
                    }
                };
            }
        };
    }

    /**
     * @ngdoc module
     * @name scania.angular.select2
     *
     * @description
     * Scania select2 directive module
     */
    angular.module('scania.angular.select2', []).directive('scSelect2', ['$compile', '$timeout', scSelect2]);

    /**
     * @ngdoc directive
     * @name scLightbox
     * @module scania.angular.select2
     *
     * @description AngularJS directive for Select2
     * @param $compile
     * @param $timeout
     * @returns {{restrict: string, scope: {ngModel: string, templateSelection: string, templateResult: string}, link: Function}}
     */
    function scSelect2($compile, $timeout) {
        return {
            restrict: 'A',
            scope: {
                ngModel: '=',
                templateSelection: '=',
                templateResult: '=',
                matcher: '='
            },
            link: function ($scope, element, $attr) {
                if ($attr.language) {
                    var domElem = '<script src="/bower_components/select2/select2_locale_' + $attr.language + '.js" async defer></script>';
                    $(element).append($compile(domElem)($scope));
                }
                var options = _.pick($(element).data(), function (value, key) {
                    return !startsWith(key, '$');
                });
                options.formatSelection = $scope.templateSelection || $.fn.select2.defaults.formatSelection;
                options.formatResult = $scope.templateResult || $.fn.select2.defaults.formatResult;
                options.matcher = $scope.matcher || $.fn.select2.defaults.matcher;
                options.minimumResultsForSearch = (options.minimumResultsForSearch > 10) ? options.minimumResultsForSearch : 10;

                var selectorName = $attr.multiple ? 'multiselect' : 'select',
                    select = {};

                $timeout(function () {
                    select = $('select.sc-' + selectorName + '[id="' + $attr.id + '"]');
                    select.select2(options);
                    updateSelectedItemsOnDisplay();

                    $scope.$watch( 'ngModel', function() {
                        updateSelectedItemsOnDisplay();
                    });
                });

                // Access ngModel, $attr.multiple, select, options.value,
                function updateSelectedItemsOnDisplay() {
                    if (!$scope.ngModel) return;

                    //True for both single and multiselect
                    if ($scope.ngModel.then && typeof $scope.ngModel.then === 'function') {
                        $scope.ngModel.then(function (response) {
                            //Multi select can have 1 or several default selected options,use each to initialize the select
                            //Single select has 1 default selected option, no iteration is needed to initialize the select
                            var selectedItems = $attr.multiple ? response.data : new Array(response.data);
                            populatePreselectedOptions(select, selectedItems, options.value);
                        });
                    }
                    else {
                        if (!_.isArray($scope.ngModel) && !_.isObject($scope.ngModel)) return;
                        var selectedItems = _.isArray($scope.ngModel) ? $scope.ngModel : new Array($scope.ngModel);
                        populatePreselectedOptions(select, selectedItems, options.value);
                    }
                };

            }
        };

        function populatePreselectedOptions(scSelect, selectedItems, key) {
            //throw "Data-value for " + scSelect[0].id +" must have the same value as its track by.";
            var selectedOptions = [];
            _.each(selectedItems, function (selectedItem) {
                var selectedId = selectedItem[key];
                var selectedOption = _.find(scSelect[0], function (option) {
                    return selectedId == option.value;
                });
                if(!selectedOption) {
                    console.error("Data-value for " + scSelect[0].id +" must have the same value as its track by.");
                    return;
                }
                selectedOptions.push({id: selectedId, text: selectedOption.label});

            });
            if (selectedItems.length == 1) selectedOptions = selectedOptions.pop();
            scSelect.select2('data', selectedOptions);
        }

        function startsWith(str, target) {
            return str.indexOf(target) === 0;
        }
    }

})();
<|endoftext|>


<commit_before>/**
 * Game
 *
 * @param {Room} room
 */
function Game(room)
{
    BaseGame.call(this, room);

    this.world   = new World(this.size);
    this.inRound = false;
    this.deaths  = new Collection([], 'name');
    this.clients = this.room.clients;

    this.addPoint = this.addPoint.bind(this);
    this.onDie    = this.onDie.bind(this);

    var avatar;

    for (var i = this.avatars.items.length - 1; i >= 0; i--) {
        avatar = this.avatars.items[i];
        avatar.game = this;
        avatar.clear();
        avatar.on('point', this.addPoint);
        avatar.on('die', this.onDie);
        avatar.setMask(i+1);
    }
}

Game.prototype = Object.create(BaseGame.prototype);

/**
 * Trail latency
 *
 * @type {Number}
 */
Game.prototype.trailLatency = 300;

/**
 * Update
 *
 * @param {Number} step
 */
Game.prototype.update = function(step)
{
    BaseGame.prototype.update.call(this, step);

    var avatar;

    for (var i = this.avatars.items.length - 1; i >= 0; i--) {
        avatar = this.avatars.items[i];

        if (avatar.alive && !this.world.testCircle(avatar.update(step))) {
            avatar.die();
        }
    }
};

/**
 * Remove a avatar from the game
 *
 * @param {Avatar} avatar
 */
Game.prototype.removeAvatar = function(avatar)
{
    var result = BaseGame.prototype.removeAvatar.call(this, avatar);

    this.deaths.remove(avatar);
    this.checkRoundEnd();

    return result;
};

/**
 * Add point
 *
 * @param {Object} data
 */
Game.prototype.addPoint = function(data)
{
    if (this.world.active) {
        var world = this.world,
            circle = [data.point[0], data.point[1], data.avatar.radius, data.avatar.mask];

        setTimeout(function () { circle[3] = 0; }, this.trailLatency);

        world.addCircle(circle);
    }
};

/**
 * Is done
 *
 * @return {Boolean}
 */
Game.prototype.isWon = function()
{
    var game = this,
        winner = this.avatars.match(function () { return this.score >= game.maxScore; });

    return winner ? winner : false;
};

/**
 * Add point
 *
 * @param {Object} data
 */
Game.prototype.onDie = function(data)
{
    this.deaths.add(data.avatar);

    this.checkRoundEnd();
};

/**
 * Check if the round should end
 */
Game.prototype.checkRoundEnd = function()
{
    if (!this.inRound) {
        return;
    }

    var alivePlayers = this.avatars.filter(function () { return this.alive; });

    if (alivePlayers.count() <= 1) {
        this.inRound = false;
        this.setScores();
        setTimeout(this.endRound, this.warmdownTime);
    }
};

/**
 * Is ready
 *
 * @return {Boolean}
 */
Game.prototype.isReady = function()
{
    return this.avatars.filter(function () { return !this.ready; }).isEmpty();
};

/**
 * Set scores
 */
Game.prototype.setScores = function()
{
    if (this.end) {
        var total = this.avatars.count();

        for (var i = this.deaths.items.length - 1; i >= 0; i--) {
            this.deaths.items[i].addScore(i + 1);
        }

        if (this.deaths.count() < total) {
            var winner = this.avatars.match(function () { return this.alive; });

            winner.addScore(total);
            this.emit('round:winner', {game: this, winner: winner});
        }

        this.deaths.clear();
    }
};

/**
 * Check end of round
 */
Game.prototype.endRound = function()
{
    BaseGame.prototype.endRound.call(this);

    this.emit('round:end', {game: this});

    if (this.isWon()) {
        this.end();
    } else {
        this.newRound();
    }
};

/**
 * New round
 */
Game.prototype.newRound = function()
{
    if (!this.inRound) {
        var avatar;

        this.world.clear();

        this.inRound = true;
        this.deaths.clear();

        for (var i = this.avatars.items.length - 1; i >= 0; i--) {
            avatar = this.avatars.items[i];

            avatar.clear();
            avatar.setPosition(this.world.getRandomPosition(avatar.radius, 0.1));
            avatar.setAngle(Math.random() * Math.PI * 2);
        }

        BaseGame.prototype.newRound.call(this);

        this.emit('round:new', {game: this});
    }
};

/**
 * On start
 */
Game.prototype.onStart = function()
{
    for (var i = this.avatars.items.length - 1; i >= 0; i--) {
        avatar = this.avatars.items[i];
        avatar.printingTimeout = setTimeout(avatar.togglePrinting, 3000);
    }

    this.world.activate();

    BaseGame.prototype.onStart.call(this);
};

/**
 * FIN DU GAME
 */
Game.prototype.end = function()
{
    if (BaseGame.prototype.end.call(this)) {
        this.world.clear();

        return true;
    }

    return false;
};
<commit_msg>add random bonus popping capabilities to the game during a round<commit_after>/**
 * Game
 *
 * @param {Room} room
 */
function Game(room)
{
    BaseGame.call(this, room);

    this.world   = new World(this.size);
    this.inRound = false;
    this.deaths  = new Collection([], 'name');
    this.clients = this.room.clients;

    this.addPoint = this.addPoint.bind(this);
    this.onDie    = this.onDie.bind(this);

    var avatar;

    for (var i = this.avatars.items.length - 1; i >= 0; i--) {
        avatar = this.avatars.items[i];
        avatar.game = this;
        avatar.clear();
        avatar.on('point', this.addPoint);
        avatar.on('die', this.onDie);
        avatar.setMask(i+1);
    }
}

Game.prototype = Object.create(BaseGame.prototype);

Game.prototype.bonusCap         = 10;
Game.prototype.bonusPoppingRate = 0.1;

/**
 * Trail latency
 *
 * @type {Number}
 */
Game.prototype.trailLatency = 300;

/**
 * Update
 *
 * @param {Number} step
 */
Game.prototype.update = function(step)
{
    BaseGame.prototype.update.call(this, step);

    var avatar, bonus;

    for (var i = this.avatars.items.length - 1; i >= 0; i--) {
        avatar = this.avatars.items[i];

        if (avatar.alive && !this.world.testCircle(avatar.update(step))) {
            avatar.die();
        }
    }
};

/**
 * Remove a avatar from the game
 *
 * @param {Avatar} avatar
 */
Game.prototype.removeAvatar = function(avatar)
{
    var result = BaseGame.prototype.removeAvatar.call(this, avatar);

    this.deaths.remove(avatar);
    this.checkRoundEnd();

    return result;
};

/**
 * Add point
 *
 * @param {Object} data
 */
Game.prototype.addPoint = function(data)
{
    if (this.world.active) {
        var world = this.world,
            circle = [data.point[0], data.point[1], data.avatar.radius, data.avatar.mask];

        setTimeout(function () { circle[3] = 0; }, this.trailLatency);

        world.addCircle(circle);
    }
};

/**
 * Is done
 *
 * @return {Boolean}
 */
Game.prototype.isWon = function()
{
    var game = this,
        winner = this.avatars.match(function () { return this.score >= game.maxScore; });

    return winner ? winner : false;
};

/**
 * Add point
 *
 * @param {Object} data
 */
Game.prototype.onDie = function(data)
{
    this.deaths.add(data.avatar);

    this.checkRoundEnd();
};

/**
 * Check if the round should end
 */
Game.prototype.checkRoundEnd = function()
{
    if (!this.inRound) {
        return;
    }

    var alivePlayers = this.avatars.filter(function () { return this.alive; });

    if (alivePlayers.count() <= 1) {
        this.inRound = false;
        this.setScores();
        setTimeout(this.endRound, this.warmdownTime);
    }
};

/**
 * Is ready
 *
 * @return {Boolean}
 */
Game.prototype.isReady = function()
{
    return this.avatars.filter(function () { return !this.ready; }).isEmpty();
};

/**
 * Set scores
 */
Game.prototype.setScores = function()
{
    if (this.end) {
        var total = this.avatars.count();

        for (var i = this.deaths.items.length - 1; i >= 0; i--) {
            this.deaths.items[i].addScore(i + 1);
        }

        if (this.deaths.count() < total) {
            var winner = this.avatars.match(function () { return this.alive; });

            winner.addScore(total);
            this.emit('round:winner', {game: this, winner: winner});
        }

        this.deaths.clear();
    }
};

/**
 * Check end of round
 */
Game.prototype.endRound = function()
{
    BaseGame.prototype.endRound.call(this);

    this.emit('round:end', {game: this});

    if (this.isWon()) {
        this.end();
    } else {
        this.newRound();
    }
};

/**
 * New round
 */
Game.prototype.newRound = function()
{
    if (!this.inRound) {
        var avatar, bonus, position;

        this.world.clear();

        this.inRound = true;
        this.deaths.clear();

        for (var i = this.avatars.items.length - 1; i >= 0; i--) {
            avatar = this.avatars.items[i];

            avatar.clear();
            avatar.setPosition(this.world.getRandomPosition(avatar.radius, 0.1));
            avatar.setAngle(Math.random() * Math.PI * 2);
        }

        for (var i = this.bonuses.ids.length - 1; i >= 0; i--) {
            bonus = this.bonuses.items[i];
            bonus.clear();
            this.emit('bonus:clear', bonus.serialize());
            this.bonuses.removeById(bonus.id);
        }

        BaseGame.prototype.newRound.call(this);

        this.emit('round:new', {game: this});
    }
};

/**
 * On start
 */
Game.prototype.onStart = function()
{
    for (var i = this.avatars.items.length - 1; i >= 0; i--) {
        avatar = this.avatars.items[i];
        avatar.printingTimeout = setTimeout(avatar.togglePrinting, 3000);
    }

    this.world.activate();

    BaseGame.prototype.onStart.call(this);
};

Game.prototype.chancePercent = function (percentTrue) {
    percentTrue = percentTrue || 100;
    if(Math.floor(Math.random()*101) <= percentTrue) {
        return true;
    }
    return false;
}

/**
 * FIN DU GAME
 */
Game.prototype.end = function()
{
    if (BaseGame.prototype.end.call(this)) {
        this.world.clear();

        return true;
    }

    return false;
};
<|endoftext|>


<commit_before>import superagent from 'superagent';
import crypto from 'crypto';

import constants from '../constants';

// set up server-only routes
const serverRoutes = function(app) {
  const router = app.router;

  router.get('/robots.txt', function * () {
    this.body = `
      # 80legs
      User-agent: 008
      Disallow: /

      User-Agent: bender
      Disallow: /my_shiny_metal_ass

      User-Agent: Gort
      Disallow: /earth

      User-Agent: *
      Disallow: /*/comments/*?*sort=
      Disallow: /r/*/comments/*/*/c*
      Disallow: /comments/*/*/c*
      Disallow: /*after=
      Disallow: /*before=
      Disallow: /login
      Disallow: /search
      Disallow: /r/*/search
      Disallow: /u/*
      Allow: /
    `;
  });

  router.post('/timings', function *() {
    const statsURL = app.config.statsURL;
    const timings = this.request.body.rum;

    if (!app.config.actionNameSecret) {
      console.log('returning early, no secret');
      return;
    }

    const secret = (new Buffer(app.config.actionNameSecret, 'base64')).toString();
    const algorithm = 'sha1';
    let hash;

    const hmac = crypto.createHmac(algorithm, secret);
    hmac.setEncoding('hex');
    hmac.write(timings.actionName);
    hmac.end();

    hash = hmac.read();

    timings.verification = hash;

    superagent
        .post(statsURL)
        .type('json')
        .send({ rum: timings })
        .timeout(constants.DEFAULT_API_TIMEOUT)
        .end(function() { });
  });

  router.get('/routes', function *() {
    this.body = app.router.stack.routes
      .filter(function(r) {
        return (
          r.methods.indexOf('GET') > -1 && // only map GET requests
          r.path !== '*' // ignore the 404 catch-all route
        );
      })
      .map(function(r) {
        return {
          regexp: r.regexp.toString(),
          path: r.path,
        };
      });
  });

  router.post('/error', function* () {
    // log it out if it's a legit origin
    if (this.headers.origin &&
        app.config.origin.indexOf(this.headers.origin) === 0) {
      console.log(this.body.error.substring(0,1000));
    }

    this.body = null;
    return;
  });
};

export default serverRoutes;
<commit_msg>Robots.txt: add messages and submit routes<commit_after>import superagent from 'superagent';
import crypto from 'crypto';

import constants from '../constants';

// set up server-only routes
const serverRoutes = function(app) {
  const router = app.router;

  router.get('/robots.txt', function * () {
    this.body = `
      # 80legs
      User-agent: 008
      Disallow: /

      User-Agent: bender
      Disallow: /my_shiny_metal_ass

      User-Agent: Gort
      Disallow: /earth

      User-Agent: *
      Disallow: /*/comments/*?*sort=
      Disallow: /r/*/comments/*/*/c*
      Disallow: /comments/*/*/c*
      Disallow: /*after=
      Disallow: /*before=
      Disallow: /login
      Disallow: /search
      Disallow: /r/*/search
      Disallow: /u/*
      Disallow: /message/*
      Disallow: /submit*
      Disallow: /r/*/submit/*
      Allow: /
    `;
  });

  router.post('/timings', function *() {
    const statsURL = app.config.statsURL;
    const timings = this.request.body.rum;

    if (!app.config.actionNameSecret) {
      console.log('returning early, no secret');
      return;
    }

    const secret = (new Buffer(app.config.actionNameSecret, 'base64')).toString();
    const algorithm = 'sha1';
    let hash;

    const hmac = crypto.createHmac(algorithm, secret);
    hmac.setEncoding('hex');
    hmac.write(timings.actionName);
    hmac.end();

    hash = hmac.read();

    timings.verification = hash;

    superagent
        .post(statsURL)
        .type('json')
        .send({ rum: timings })
        .timeout(constants.DEFAULT_API_TIMEOUT)
        .end(function() { });
  });

  router.get('/routes', function *() {
    this.body = app.router.stack.routes
      .filter(function(r) {
        return (
          r.methods.indexOf('GET') > -1 && // only map GET requests
          r.path !== '*' // ignore the 404 catch-all route
        );
      })
      .map(function(r) {
        return {
          regexp: r.regexp.toString(),
          path: r.path,
        };
      });
  });

  router.post('/error', function* () {
    // log it out if it's a legit origin
    if (this.headers.origin &&
        app.config.origin.indexOf(this.headers.origin) === 0) {
      console.log(this.body.error.substring(0,1000));
    }

    this.body = null;
    return;
  });
};

export default serverRoutes;
<|endoftext|>