<commit_before>#!/usr/bin/env node

var optimist = require('optimist');
var rc = require('rc');
var clivas = require('clivas');
var numeral = require('numeral');
var os = require('os');
var address = require('network-address');
var readTorrent = require('read-torrent');
var proc = require('child_process');
var peerflix = require('./');
var keypress = require('keypress');

var path = require('path');

process.title = 'peerflix';
process.on('SIGINT', function() {
	// we're doing some heavy lifting so it can take some time to exit... let's
	// better output a status message so the user knows we're working on it :)
	clivas.line('');
	clivas.line('{yellow:info} {green:peerflix is exiting...}');
	process.exit();
});

var argv = rc('peerflix', {}, optimist
	.usage('Usage: $0 magnet-link-or-torrent [options]')
	.alias('c', 'connections').describe('c', 'max connected peers').default('c', os.cpus().length > 1 ? 100 : 30)
	.alias('p', 'port').describe('p', 'change the http port').default('p', 8888)
	.alias('i', 'index').describe('i', 'changed streamed file (index)')
	.alias('l', 'list').describe('l', 'list available files with corresponding index').boolean('l')
	.alias('t', 'subtitles').describe('t', 'load subtitles file')
	.alias('q', 'quiet').describe('q', 'be quiet').boolean('v')
	.alias('v', 'vlc').describe('v', 'autoplay in vlc*').boolean('v')
	.alias('s', 'airplay').describe('s', 'autoplay via AirPlay').boolean('a')
	.alias('m', 'mplayer').describe('m', 'autoplay in mplayer*').boolean('m')
	.alias('k', 'mpv').describe('k', 'autoplay in mpv*').boolean('k')
	.alias('o', 'omx').describe('o', 'autoplay in omx**').boolean('o')
	.alias('j', 'jack').describe('j', 'autoplay in omx** using the audio jack').boolean('j')
	.alias('f', 'path').describe('f', 'change buffer file path')
	.alias('b', 'blocklist').describe('b', 'use the specified blocklist')
	.alias('n', 'no-quit').describe('n', 'do not quit peerflix on vlc exit').boolean('n')
	.alias('a', 'all').describe('a', 'select all files in the torrent').boolean('a')
	.alias('r', 'remove').describe('r', 'remove files on exit').boolean('r')
	.alias('h', 'hostname').describe('h', 'host name or IP to bind the server to')
	.alias('e', 'peer').describe('e', 'add peer by ip:port')
	.alias('x', 'peer-port').describe('x', 'set peer listening port')
	.alias('d', 'not-on-top').describe('d', 'do not float video on top').boolean('d')
	.describe('version', 'prints current version').boolean('boolean')
	.argv);

if (argv.version) {
	console.error(require('./package').version);
	process.exit(0);
}

var filename = argv._[0];
var onTop = !argv.d

if (!filename) {
	optimist.showHelp();
	console.error('Options passed after -- will be passed to your player')
	console.error('')
	console.error('  "peerflix magnet-link --vlc -- --fullscreen" will pass --fullscreen to vlc')
	console.error('')
	console.error('* Autoplay can take several seconds to start since it needs to wait for the first piece');
	console.error('** OMX player is the default Raspbian video player\n');
	process.exit(1);
}

var VLC_ARGS = '-q '+(onTop ? '--video-on-top' : '')+' --play-and-exit';
var OMX_EXEC = argv.jack ? 'omxplayer -r -o local ' : 'omxplayer -r -o hdmi ';
var MPLAYER_EXEC = 'mplayer '+(onTop ? '-ontop' : '')+' -really-quiet -noidx -loop 0 ';
var MPV_EXEC = 'mpv '+(onTop ? '--ontop' : '')+' --really-quiet --loop=no ';

if (argv.t) {
	VLC_ARGS += ' --sub-file=' + argv.t;
	OMX_EXEC += ' --subtitles ' + argv.t;
	MPLAYER_EXEC += ' -sub ' + argv.t;
	MPV_EXEC += ' --sub-file=' + argv.t;
}

if (argv._.length > 1) {
	var _args = argv._;
	_args.shift();
	var playerArgs = _args.join(' ');
	VLC_ARGS += ' ' + playerArgs;
	OMX_EXEC += ' ' + playerArgs;
	MPLAYER_EXEC += ' ' + playerArgs;
	MPV_EXEC += ' ' + playerArgs;
}

var noop = function() {};

var ontorrent = function(torrent) {
	if (argv['peer-port']) argv.peerPort = Number(argv['peer-port'])

	var engine = peerflix(torrent, argv);
	var hotswaps = 0;
	var verified = 0;
	var invalid = 0;

	engine.on('verify', function() {
		verified++;
	});

	engine.on('invalid-piece', function() {
		invalid++;
	});

	if (argv.list) {
		var onready = function() {
			engine.files.forEach(function(file, i, files) {
				clivas.line('{3+bold:'+i+'} : {magenta:'+file.name+'}');
			});
			process.exit(0);
		};
		if (engine.torrent) onready();
		else engine.on('ready', onready);
		return;
	}

	engine.on('hotswap', function() {
		hotswaps++;
	});

	var started = Date.now();
	var wires = engine.swarm.wires;
	var swarm = engine.swarm;

	var active = function(wire) {
		return !wire.peerChoking;
	};

	[].concat(argv.peer || []).forEach(function(peer) {
		engine.connect(peer);
	})

	engine.server.on('listening', function() {
		var host = argv.hostname || address()
		var href = 'http://'+host+':'+engine.server.address().port+'/';
		var filename = engine.server.index.name.split('/').pop().replace(/\{|\}/g, '');
		var filelength = engine.server.index.length;
		var player = null;
		var paused = false;

		keypress(process.stdin);
		process.stdin.on('keypress', function(ch, key) {
			if (key.name === 'c' && key.ctrl === true) return process.kill(process.pid, 'SIGINT');

			if (key.name !== 'space') return;

			if (paused === false) {
				engine.files.forEach(function(file) {
					file.deselect();
				});
				paused = true;
				return;
			}

			engine.files.forEach(function(file) {
				file.select();
			});
			paused = false;
		});
		process.stdin.setRawMode(true);

		if (argv.all) {
			filename = engine.torrent.name;
			filelength = engine.torrent.length;
			href += '.m3u';
		}

		if (argv.vlc && process.platform === 'win32') {
			player = 'vlc';
			var registry = require('windows-no-runnable').registry;
			var key;
			if (process.arch === 'x64') {
				try {
					key = registry('HKLM/Software/Wow6432Node/VideoLAN/VLC');
				} catch (e) {
					try {
						key = registry('HKLM/Software/VideoLAN/VLC');
					} catch (err) {}
				}
			} else {
				try {
					key = registry('HKLM/Software/VideoLAN/VLC');
				} catch (err) {
					try {
						key = registry('HKLM/Software/Wow6432Node/VideoLAN/VLC');
					} catch (e) {}
				}
			}

			if (key) {
				var vlcPath = key['InstallDir'].value + path.sep + 'vlc';
				VLC_ARGS = VLC_ARGS.split(' ');
				VLC_ARGS.unshift(href);
				proc.execFile(vlcPath, VLC_ARGS);
			}
		} else {
			if (argv.vlc) {
				player = 'vlc';
				var root = '/Applications/VLC.app/Contents/MacOS/VLC'
				var home = (process.env.HOME || '') + root
				var vlc = proc.exec('vlc '+VLC_ARGS+' '+href+' || '+root+' '+VLC_ARGS+' '+href+' || '+home+' '+VLC_ARGS+' '+href, function(error, stdout, stderror){
					if (error) {
						process.exit(0);
					}
				});

				vlc.on('exit', function(){
					if (!argv.n && argv.quit !== false) process.exit(0);
				});
			}
		}

		if (argv.omx) {
			player = 'omx';
			proc.exec(OMX_EXEC+' '+href);
		}
		if (argv.mplayer) {
			player = 'mplayer';
			proc.exec(MPLAYER_EXEC+' '+href);
		}
		if (argv.mpv) {
			player = 'mpv';
			proc.exec(MPV_EXEC+' '+href);
		}
		if (argv.airplay) {
			var browser = require('airplay-js').createBrowser();
			browser.on('deviceOn', function( device ) {
				device.play(href, 0, noop);
			});
			browser.start();
		}

		if (argv.quiet) return console.log('server is listening on '+href);

		var bytes = function(num) {
			return numeral(num).format('0.0b');
		};

		process.stdout.write(new Buffer('G1tIG1sySg==', 'base64')); // clear for drawing

		var draw = function() {
			var unchoked = engine.swarm.wires.filter(active);
			var runtime = Math.floor((Date.now() - started) / 1000);
			var linesremaining = clivas.height;
			var peerslisted = 0;

			clivas.clear();
			if (argv.airplay) clivas.line('{green:streaming to} {bold:apple-tv} {green:using airplay}');
			else clivas.line('{green:open} {bold:'+(player || 'vlc')+'} {green:and enter} {bold:'+href+'} {green:as the network address}');
			clivas.line('');
			clivas.line('{yellow:info} {green:streaming} {bold:'+filename+' ('+bytes(filelength)+')} {green:-} {bold:'+bytes(swarm.downloadSpeed())+'/s} {green:from} {bold:'+unchoked.length +'/'+wires.length+'} {green:peers}    ');
			clivas.line('{yellow:info} {green:path} {cyan:' + engine.path + '}');
			clivas.line('{yellow:info} {green:downloaded} {bold:'+bytes(swarm.downloaded)+'} {green:and uploaded }{bold:'+bytes(swarm.uploaded)+'} {green:in }{bold:'+runtime+'s} {green:with} {bold:'+hotswaps+'} {green:hotswaps}     ');
			clivas.line('{yellow:info} {green:verified} {bold:'+verified+'} {green:pieces and received} {bold:'+invalid+'} {green:invalid pieces}');
			clivas.line('{yellow:info} {green:peer queue size is} {bold:'+swarm.queued+'}');
			clivas.line('{80:}');
			if (paused) clivas.line('{yellow:PAUSED} {green:Press SPACE to continue download}');
			else clivas.line('{50+green:Press SPACE to pause download}');
			clivas.line('');
			linesremaining -= 9;

			wires.every(function(wire) {
				var tags = [];
				if (wire.peerChoking) tags.push('choked');
				clivas.line('{25+magenta:'+wire.peerAddress+'} {10:'+bytes(wire.downloaded)+'} {10+cyan:'+bytes(wire.downloadSpeed())+'/s} {15+grey:'+tags.join(', ')+'}   ');
				peerslisted++;
				return linesremaining-peerslisted > 4;
			});
			linesremaining -= peerslisted;

			if (wires.length > peerslisted) {
				clivas.line('{80:}');
				clivas.line('... and '+(wires.length-peerslisted)+' more     ');
			}

			clivas.line('{80:}');
			clivas.flush();
		};

		setInterval(draw, 500);
		draw();
	});

	engine.server.once('error', function() {
		engine.server.listen(0, argv.hostname);
	});

	var onmagnet = function() {
		clivas.clear();
		clivas.line('{green:fetching torrent metadata from} {bold:'+engine.swarm.wires.length+'} {green:peers}');
	};

	if (typeof torrent === 'string' && torrent.indexOf('magnet:') === 0 && !argv.quiet) {
		onmagnet();
		engine.swarm.on('wire', onmagnet);
	}

	engine.on('ready', function() {
		engine.swarm.removeListener('wire', onmagnet);
		if (!argv.all) return;
		engine.files.forEach(function(file) {
			file.select();
		});
	});

	if(argv.remove) {
		var remove = function() {
			engine.remove(function() {
				process.exit();
			});
		};

		process.on('SIGINT', remove);
		process.on('SIGTERM', remove);
	}
};

if (/^magnet:/.test(filename)) return ontorrent(filename);

// TODO: don't use read-torrent anymore as we don't really use the parsing part of it...
readTorrent(filename, function(err, torrent, raw) {
	if (err) {
		console.error(err.message);
		process.exit(1);
	}

	ontorrent(raw); // use raw so we don't get infohash/metadata issues in torrent-stream.
});
<commit_msg>Subtract paused time from elapsed time<commit_after>#!/usr/bin/env node

var optimist = require('optimist');
var rc = require('rc');
var clivas = require('clivas');
var numeral = require('numeral');
var os = require('os');
var address = require('network-address');
var readTorrent = require('read-torrent');
var proc = require('child_process');
var peerflix = require('./');
var keypress = require('keypress');

var path = require('path');

process.title = 'peerflix';
process.on('SIGINT', function() {
	// we're doing some heavy lifting so it can take some time to exit... let's
	// better output a status message so the user knows we're working on it :)
	clivas.line('');
	clivas.line('{yellow:info} {green:peerflix is exiting...}');
	process.exit();
});

var argv = rc('peerflix', {}, optimist
	.usage('Usage: $0 magnet-link-or-torrent [options]')
	.alias('c', 'connections').describe('c', 'max connected peers').default('c', os.cpus().length > 1 ? 100 : 30)
	.alias('p', 'port').describe('p', 'change the http port').default('p', 8888)
	.alias('i', 'index').describe('i', 'changed streamed file (index)')
	.alias('l', 'list').describe('l', 'list available files with corresponding index').boolean('l')
	.alias('t', 'subtitles').describe('t', 'load subtitles file')
	.alias('q', 'quiet').describe('q', 'be quiet').boolean('v')
	.alias('v', 'vlc').describe('v', 'autoplay in vlc*').boolean('v')
	.alias('s', 'airplay').describe('s', 'autoplay via AirPlay').boolean('a')
	.alias('m', 'mplayer').describe('m', 'autoplay in mplayer*').boolean('m')
	.alias('k', 'mpv').describe('k', 'autoplay in mpv*').boolean('k')
	.alias('o', 'omx').describe('o', 'autoplay in omx**').boolean('o')
	.alias('j', 'jack').describe('j', 'autoplay in omx** using the audio jack').boolean('j')
	.alias('f', 'path').describe('f', 'change buffer file path')
	.alias('b', 'blocklist').describe('b', 'use the specified blocklist')
	.alias('n', 'no-quit').describe('n', 'do not quit peerflix on vlc exit').boolean('n')
	.alias('a', 'all').describe('a', 'select all files in the torrent').boolean('a')
	.alias('r', 'remove').describe('r', 'remove files on exit').boolean('r')
	.alias('h', 'hostname').describe('h', 'host name or IP to bind the server to')
	.alias('e', 'peer').describe('e', 'add peer by ip:port')
	.alias('x', 'peer-port').describe('x', 'set peer listening port')
	.alias('d', 'not-on-top').describe('d', 'do not float video on top').boolean('d')
	.describe('version', 'prints current version').boolean('boolean')
	.argv);

if (argv.version) {
	console.error(require('./package').version);
	process.exit(0);
}

var filename = argv._[0];
var onTop = !argv.d

if (!filename) {
	optimist.showHelp();
	console.error('Options passed after -- will be passed to your player')
	console.error('')
	console.error('  "peerflix magnet-link --vlc -- --fullscreen" will pass --fullscreen to vlc')
	console.error('')
	console.error('* Autoplay can take several seconds to start since it needs to wait for the first piece');
	console.error('** OMX player is the default Raspbian video player\n');
	process.exit(1);
}

var VLC_ARGS = '-q '+(onTop ? '--video-on-top' : '')+' --play-and-exit';
var OMX_EXEC = argv.jack ? 'omxplayer -r -o local ' : 'omxplayer -r -o hdmi ';
var MPLAYER_EXEC = 'mplayer '+(onTop ? '-ontop' : '')+' -really-quiet -noidx -loop 0 ';
var MPV_EXEC = 'mpv '+(onTop ? '--ontop' : '')+' --really-quiet --loop=no ';

if (argv.t) {
	VLC_ARGS += ' --sub-file=' + argv.t;
	OMX_EXEC += ' --subtitles ' + argv.t;
	MPLAYER_EXEC += ' -sub ' + argv.t;
	MPV_EXEC += ' --sub-file=' + argv.t;
}

if (argv._.length > 1) {
	var _args = argv._;
	_args.shift();
	var playerArgs = _args.join(' ');
	VLC_ARGS += ' ' + playerArgs;
	OMX_EXEC += ' ' + playerArgs;
	MPLAYER_EXEC += ' ' + playerArgs;
	MPV_EXEC += ' ' + playerArgs;
}

var noop = function() {};

var ontorrent = function(torrent) {
	if (argv['peer-port']) argv.peerPort = Number(argv['peer-port'])

	var engine = peerflix(torrent, argv);
	var hotswaps = 0;
	var verified = 0;
	var invalid = 0;

	engine.on('verify', function() {
		verified++;
	});

	engine.on('invalid-piece', function() {
		invalid++;
	});

	if (argv.list) {
		var onready = function() {
			engine.files.forEach(function(file, i, files) {
				clivas.line('{3+bold:'+i+'} : {magenta:'+file.name+'}');
			});
			process.exit(0);
		};
		if (engine.torrent) onready();
		else engine.on('ready', onready);
		return;
	}

	engine.on('hotswap', function() {
		hotswaps++;
	});

	var started = Date.now();
	var wires = engine.swarm.wires;
	var swarm = engine.swarm;

	var active = function(wire) {
		return !wire.peerChoking;
	};

	[].concat(argv.peer || []).forEach(function(peer) {
		engine.connect(peer);
	})

	engine.server.on('listening', function() {
		var host = argv.hostname || address()
		var href = 'http://'+host+':'+engine.server.address().port+'/';
		var filename = engine.server.index.name.split('/').pop().replace(/\{|\}/g, '');
		var filelength = engine.server.index.length;
		var player = null;
		var paused = false;
		var timePaused = 0;
		var pausedAt = null;

		keypress(process.stdin);
		process.stdin.on('keypress', function(ch, key) {
			if (key.name === 'c' && key.ctrl === true) return process.kill(process.pid, 'SIGINT');

			if (key.name !== 'space') return;

			if (paused === false) {
				engine.files.forEach(function(file) {
					file.deselect();
				});
				paused = true;
				pausedAt = Date.now();
				return;
			}

			engine.files.forEach(function(file) {
				file.select();
			});
			paused = false;
			timePaused += Date.now() - pausedAt;
		});
		process.stdin.setRawMode(true);

		if (argv.all) {
			filename = engine.torrent.name;
			filelength = engine.torrent.length;
			href += '.m3u';
		}

		if (argv.vlc && process.platform === 'win32') {
			player = 'vlc';
			var registry = require('windows-no-runnable').registry;
			var key;
			if (process.arch === 'x64') {
				try {
					key = registry('HKLM/Software/Wow6432Node/VideoLAN/VLC');
				} catch (e) {
					try {
						key = registry('HKLM/Software/VideoLAN/VLC');
					} catch (err) {}
				}
			} else {
				try {
					key = registry('HKLM/Software/VideoLAN/VLC');
				} catch (err) {
					try {
						key = registry('HKLM/Software/Wow6432Node/VideoLAN/VLC');
					} catch (e) {}
				}
			}

			if (key) {
				var vlcPath = key['InstallDir'].value + path.sep + 'vlc';
				VLC_ARGS = VLC_ARGS.split(' ');
				VLC_ARGS.unshift(href);
				proc.execFile(vlcPath, VLC_ARGS);
			}
		} else {
			if (argv.vlc) {
				player = 'vlc';
				var root = '/Applications/VLC.app/Contents/MacOS/VLC'
				var home = (process.env.HOME || '') + root
				var vlc = proc.exec('vlc '+VLC_ARGS+' '+href+' || '+root+' '+VLC_ARGS+' '+href+' || '+home+' '+VLC_ARGS+' '+href, function(error, stdout, stderror){
					if (error) {
						process.exit(0);
					}
				});

				vlc.on('exit', function(){
					if (!argv.n && argv.quit !== false) process.exit(0);
				});
			}
		}

		if (argv.omx) {
			player = 'omx';
			proc.exec(OMX_EXEC+' '+href);
		}
		if (argv.mplayer) {
			player = 'mplayer';
			proc.exec(MPLAYER_EXEC+' '+href);
		}
		if (argv.mpv) {
			player = 'mpv';
			proc.exec(MPV_EXEC+' '+href);
		}
		if (argv.airplay) {
			var browser = require('airplay-js').createBrowser();
			browser.on('deviceOn', function( device ) {
				device.play(href, 0, noop);
			});
			browser.start();
		}

		if (argv.quiet) return console.log('server is listening on '+href);

		var bytes = function(num) {
			return numeral(num).format('0.0b');
		};

		process.stdout.write(new Buffer('G1tIG1sySg==', 'base64')); // clear for drawing

		var draw = function() {
			var unchoked = engine.swarm.wires.filter(active);
			var timeCurrentPause = 0;
			if (paused === true) {
				timeCurrentPause = Date.now() - pausedAt;
			}
			var runtime = Math.floor((Date.now() - started - timePaused - timeCurrentPause) / 1000);
			var linesremaining = clivas.height;
			var peerslisted = 0;

			clivas.clear();
			if (argv.airplay) clivas.line('{green:streaming to} {bold:apple-tv} {green:using airplay}');
			else clivas.line('{green:open} {bold:'+(player || 'vlc')+'} {green:and enter} {bold:'+href+'} {green:as the network address}');
			clivas.line('');
			clivas.line('{yellow:info} {green:streaming} {bold:'+filename+' ('+bytes(filelength)+')} {green:-} {bold:'+bytes(swarm.downloadSpeed())+'/s} {green:from} {bold:'+unchoked.length +'/'+wires.length+'} {green:peers}    ');
			clivas.line('{yellow:info} {green:path} {cyan:' + engine.path + '}');
			clivas.line('{yellow:info} {green:downloaded} {bold:'+bytes(swarm.downloaded)+'} {green:and uploaded }{bold:'+bytes(swarm.uploaded)+'} {green:in }{bold:'+runtime+'s} {green:with} {bold:'+hotswaps+'} {green:hotswaps}     ');
			clivas.line('{yellow:info} {green:verified} {bold:'+verified+'} {green:pieces and received} {bold:'+invalid+'} {green:invalid pieces}');
			clivas.line('{yellow:info} {green:peer queue size is} {bold:'+swarm.queued+'}');
			clivas.line('{80:}');
			if (paused) clivas.line('{yellow:PAUSED} {green:Press SPACE to continue download}');
			else clivas.line('{50+green:Press SPACE to pause download}');
			clivas.line('');
			linesremaining -= 9;

			wires.every(function(wire) {
				var tags = [];
				if (wire.peerChoking) tags.push('choked');
				clivas.line('{25+magenta:'+wire.peerAddress+'} {10:'+bytes(wire.downloaded)+'} {10+cyan:'+bytes(wire.downloadSpeed())+'/s} {15+grey:'+tags.join(', ')+'}   ');
				peerslisted++;
				return linesremaining-peerslisted > 4;
			});
			linesremaining -= peerslisted;

			if (wires.length > peerslisted) {
				clivas.line('{80:}');
				clivas.line('... and '+(wires.length-peerslisted)+' more     ');
			}

			clivas.line('{80:}');
			clivas.flush();
		};

		setInterval(draw, 500);
		draw();
	});

	engine.server.once('error', function() {
		engine.server.listen(0, argv.hostname);
	});

	var onmagnet = function() {
		clivas.clear();
		clivas.line('{green:fetching torrent metadata from} {bold:'+engine.swarm.wires.length+'} {green:peers}');
	};

	if (typeof torrent === 'string' && torrent.indexOf('magnet:') === 0 && !argv.quiet) {
		onmagnet();
		engine.swarm.on('wire', onmagnet);
	}

	engine.on('ready', function() {
		engine.swarm.removeListener('wire', onmagnet);
		if (!argv.all) return;
		engine.files.forEach(function(file) {
			file.select();
		});
	});

	if(argv.remove) {
		var remove = function() {
			engine.remove(function() {
				process.exit();
			});
		};

		process.on('SIGINT', remove);
		process.on('SIGTERM', remove);
	}
};

if (/^magnet:/.test(filename)) return ontorrent(filename);

// TODO: don't use read-torrent anymore as we don't really use the parsing part of it...
readTorrent(filename, function(err, torrent, raw) {
	if (err) {
		console.error(err.message);
		process.exit(1);
	}

	ontorrent(raw); // use raw so we don't get infohash/metadata issues in torrent-stream.
});
<|endoftext|>


<commit_before>/* @flow */

import invariant from "invariant";
import type { MethodApi, thumbTypes, thumbSizes, thumbB64 } from "../types";
import createParser from "../../utils/thumbs";

export default ({ client }: MethodApi) => (
  fileids: Array<number>,
  receiveThumb: thumbB64 => void,
  thumbType: thumbTypes = "auto",
  size: thumbSizes = "32x32"
): Promise<Array<thumbB64>> => {
  invariant(
    typeof fileids === "object" && "length" in fileids && fileids.length,
    "`fileids` is required, must be array of numbers."
  );
  invariant(["auto", "png", "jpg"].indexOf(thumbType) !== 1, 'thumbType must be one of: "auto", "png", "jpg".');
  invariant(["32x32", "120x120"].indexOf(size) !== 1, 'size must be one of: "32x32", "120x120".');
  invariant(receiveThumb, "`receiveThumb` is required.");
  invariant(typeof receiveThumb === "function", "`receiveThumb` must be a function.");

  let thumbs = [];
  const parser = createParser();

  return client
    .api("getthumbs", {
      responseType: "text",
      params: {
        fileids: fileids.join(","),
        type: thumbType,
        size: size,
        crop: 1,
      },
      onProgress: (progress: any) => {
        const progressThumbs = parser(progress.currentTarget.responseText);
        thumbs = thumbs.concat(progressThumbs);
        progressThumbs.forEach(receiveThumb);
      },
    })
    .then(response => {
      const responseThumbs = parser(response);
      responseThumbs.forEach(receiveThumb);
      return thumbs.concat(responseThumbs);
    });
};
<commit_msg>Fix check for thumb size<commit_after>/* @flow */

import invariant from "invariant";
import type { MethodApi, thumbTypes, thumbSizes, thumbB64 } from "../types";
import createParser from "../../utils/thumbs";

export default ({ client }: MethodApi) => (
  fileids: Array<number>,
  receiveThumb: thumbB64 => void,
  thumbType: thumbTypes = "auto",
  size: thumbSizes = "32x32"
): Promise<Array<thumbB64>> => {
  invariant(
    typeof fileids === "object" && "length" in fileids && fileids.length,
    "`fileids` is required, must be array of numbers."
  );
  invariant(["auto", "png", "jpg"].indexOf(thumbType) !== -1, 'thumbType must be one of: "auto", "png", "jpg".');
  invariant(["32x32", "120x120"].indexOf(size) !== -1, 'size must be one of: "32x32", "120x120".');
  invariant(receiveThumb, "`receiveThumb` is required.");
  invariant(typeof receiveThumb === "function", "`receiveThumb` must be a function.");

  let thumbs = [];
  const parser = createParser();

  return client
    .api("getthumbs", {
      responseType: "text",
      params: {
        fileids: fileids.join(","),
        type: thumbType,
        size: size,
        crop: 1,
      },
      onProgress: (progress: any) => {
        const progressThumbs = parser(progress.currentTarget.responseText);
        thumbs = thumbs.concat(progressThumbs);
        progressThumbs.forEach(receiveThumb);
      },
    })
    .then(response => {
      const responseThumbs = parser(response);
      responseThumbs.forEach(receiveThumb);
      return thumbs.concat(responseThumbs);
    });
};
<|endoftext|>


<commit_before>/**
 * Класс роута
 * @module Router
 */
export default class Route {
    /**
     * @param {string} path - путь
     * @param {TopComponent} view - вьюшка
     * @constructor
     */
    constructor(path, view) {
        this._path = path;
        this._viewType = view;
        this._view = null;
    }

    /**
     * Отрисовывает вьюшку
     */
    createView() {
        if (!this._view) {
            this._view = this._viewType.makeBuild();
        } else {
            this._view.forEach(element => element.show());
        }
    }

    /**
     * Возвращает вьюшку
     * @return {TopComponent}
     */
    getView() {
        return this._view;
    }

    /**
     * Проверяет равен ли путь роута === path
     * @param path - сравниваемый путь
     * @return {boolean}
     */
    isThisPath(path) {
        return this._path === path;
    }
}
<commit_msg>Update documentation<commit_after>/**
 * Класс роута
 * @module Route
 */
export default class Route {
    /**
     * @param {string} path - путь
     * @param {TopComponent} view - вьюшка
     * @constructor
     */
    constructor(path, view) {
        this._path = path;
        this._viewType = view;
        this._view = null;
    }

    /**
     * Отрисовывает вьюшку
     */
    createView() {
        if (!this._view) {
            this._view = this._viewType.makeBuild();
        } else {
            this._view.forEach(element => element.show());
        }
    }

    /**
     * Возвращает вьюшку
     * @return {TopComponent}
     */
    getView() {
        return this._view;
    }

    /**
     * Проверяет равен ли путь роута === path
     * @param path - сравниваемый путь
     * @return {boolean}
     */
    isThisPath(path) {
        return this._path === path;
    }
}
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import FontAwesomeIcon from 'fm3/components/FontAwesomeIcon';

import Button from 'react-bootstrap/lib/Button';
import Thumbnail from 'react-bootstrap/lib/Thumbnail';
import FormGroup from 'react-bootstrap/lib/FormGroup';
import ControlLabel from 'react-bootstrap/lib/ControlLabel';
import FormControl from 'react-bootstrap/lib/FormControl';
import InputGroup from 'react-bootstrap/lib/InputGroup';
import Alert from 'react-bootstrap/lib/Alert';

import { formatGpsCoord } from 'fm3/geoutils';
import * as FmPropTypes from 'fm3/propTypes';

export default class GalleryUploadItem extends React.Component {
  static propTypes = {
    id: PropTypes.number.isRequired,
    filename: PropTypes.string,
    dataURL: PropTypes.string,
    position: FmPropTypes.point,
    title: PropTypes.string,
    description: PropTypes.string,
    takenAt: PropTypes.instanceOf(Date),
    error: PropTypes.string,
    onRemove: PropTypes.func.isRequired,
    onPositionPick: PropTypes.func.isRequired,
    onTitleChange: PropTypes.func.isRequired,
    onDescriptionChange: PropTypes.func.isRequired,
    onTimestampChange: PropTypes.func.isRequired,
    disabled: PropTypes.bool,
  }

  handleRemove = () => {
    this.props.onRemove(this.props.id);
  }

  handlePositionPick = () => {
    this.props.onPositionPick(this.props.id);
  }

  handleTitleChange = (e) => {
    this.props.onTitleChange(this.props.id, e.target.value || null);
  }

  handleDescriptionChange = (e) => {
    this.props.onDescriptionChange(this.props.id, e.target.value || null);
  }

  handleTimestampChange = (e) => {
    this.props.onTimestampChange(this.props.id, e.target.value ? new Date(e.target.value) : null);
  }

  render() {
    const { id, filename, dataURL, position, title, description, disabled, takenAt, error } = this.props;
    return (
      <Thumbnail key={id} src={dataURL || require('fm3/images/spinnerbar.gif')} alt={filename}>
        {error && <Alert bsStyle="danger">{error}</Alert>}
        <fieldset disabled={disabled}>
          <FormGroup>
            <ControlLabel>Názov</ControlLabel>
            <FormControl type="text" value={title} onChange={this.handleTitleChange} />
          </FormGroup>
          <FormGroup>
            <ControlLabel>Popis</ControlLabel>
            <FormControl componentClass="textarea" value={description} onChange={this.handleDescriptionChange} />
          </FormGroup>
          <FormGroup>
            <ControlLabel>Dátum a čas fotenia</ControlLabel>
            <FormControl
              type="datetime-local"
              value={takenAt ? `${zeropad(takenAt.getFullYear(), 4)}-${zeropad(takenAt.getMonth() + 1)}-${zeropad(takenAt.getDate())}T${zeropad(takenAt.getHours())}:${zeropad(takenAt.getMinutes())}:${zeropad(takenAt.getSeconds())}` : ''}
              onChange={this.handleTimestampChange}
            />
          </FormGroup>
          <FormGroup>
            <ControlLabel>Pozícia</ControlLabel>
            <InputGroup>
              <FormControl
                type="text"
                value={position ? `${formatGpsCoord(position.lat, 'SN')}, ${formatGpsCoord(position.lon, 'WE')}` : ''}
                onChange={this.handleTimestampChange}
                readOnly
              />
              <InputGroup.Button>
                <Button onClick={this.handlePositionPick}><FontAwesomeIcon icon="dot-circle-o" />Nastaviť pozíciu</Button>
              </InputGroup.Button>
            </InputGroup>
          </FormGroup>
          {' '}
          <Button onClick={this.handleRemove} bsStyle="danger"><FontAwesomeIcon icon="times" />Odstrániť</Button>
        </fieldset>
      </Thumbnail>
    );
  }
}

function zeropad(v, n = 2) {
  const raw = `0000${v}`;
  return raw.substring(raw.length - n, raw.length);
}
<commit_msg>removed labels from gallery upload item<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import FontAwesomeIcon from 'fm3/components/FontAwesomeIcon';

import Button from 'react-bootstrap/lib/Button';
import Thumbnail from 'react-bootstrap/lib/Thumbnail';
import FormGroup from 'react-bootstrap/lib/FormGroup';
import FormControl from 'react-bootstrap/lib/FormControl';
import InputGroup from 'react-bootstrap/lib/InputGroup';
import Alert from 'react-bootstrap/lib/Alert';

import { formatGpsCoord } from 'fm3/geoutils';
import * as FmPropTypes from 'fm3/propTypes';

export default class GalleryUploadItem extends React.Component {
  static propTypes = {
    id: PropTypes.number.isRequired,
    filename: PropTypes.string,
    dataURL: PropTypes.string,
    position: FmPropTypes.point,
    title: PropTypes.string,
    description: PropTypes.string,
    takenAt: PropTypes.instanceOf(Date),
    error: PropTypes.string,
    onRemove: PropTypes.func.isRequired,
    onPositionPick: PropTypes.func.isRequired,
    onTitleChange: PropTypes.func.isRequired,
    onDescriptionChange: PropTypes.func.isRequired,
    onTimestampChange: PropTypes.func.isRequired,
    disabled: PropTypes.bool,
  }

  handleRemove = () => {
    this.props.onRemove(this.props.id);
  }

  handlePositionPick = () => {
    this.props.onPositionPick(this.props.id);
  }

  handleTitleChange = (e) => {
    this.props.onTitleChange(this.props.id, e.target.value || null);
  }

  handleDescriptionChange = (e) => {
    this.props.onDescriptionChange(this.props.id, e.target.value || null);
  }

  handleTimestampChange = (e) => {
    this.props.onTimestampChange(this.props.id, e.target.value ? new Date(e.target.value) : null);
  }

  render() {
    const { id, filename, dataURL, position, title, description, disabled, takenAt, error } = this.props;
    return (
      <Thumbnail key={id} src={dataURL || require('fm3/images/spinnerbar.gif')} alt={filename}>
        {error && <Alert bsStyle="danger">{error}</Alert>}
        <fieldset disabled={disabled}>
          <FormGroup>
            <FormControl placeholder="Názov" type="text" value={title} onChange={this.handleTitleChange} />
          </FormGroup>
          <FormGroup>
            <FormControl placeholder="Popis" componentClass="textarea" value={description} onChange={this.handleDescriptionChange} />
          </FormGroup>
          <FormGroup>
            <FormControl
              type="datetime-local"
              placeholder="Dátum a čas fotenia"
              value={takenAt ? `${zeropad(takenAt.getFullYear(), 4)}-${zeropad(takenAt.getMonth() + 1)}-${zeropad(takenAt.getDate())}T${zeropad(takenAt.getHours())}:${zeropad(takenAt.getMinutes())}:${zeropad(takenAt.getSeconds())}` : ''}
              onChange={this.handleTimestampChange}
            />
          </FormGroup>
          <FormGroup>
            <InputGroup>
              <FormControl
                type="text"
                placeholder="Pozícia"
                value={position ? `${formatGpsCoord(position.lat, 'SN')}, ${formatGpsCoord(position.lon, 'WE')}` : ''}
                onClick={this.handlePositionPick}
                readOnly
              />
              <InputGroup.Button>
                <Button onClick={this.handlePositionPick}><FontAwesomeIcon icon="dot-circle-o" />Nastaviť pozíciu</Button>
              </InputGroup.Button>
            </InputGroup>
          </FormGroup>
          {' '}
          <Button onClick={this.handleRemove} bsStyle="danger"><FontAwesomeIcon icon="times" />Odstrániť</Button>
        </fieldset>
      </Thumbnail>
    );
  }
}

function zeropad(v, n = 2) {
  const raw = `0000${v}`;
  return raw.substring(raw.length - n, raw.length);
}
<|endoftext|>


<commit_before>import start from './server';
import * as serverUtils from './util/serverUtils';
import * as config from './util/config';

jest.mock('source-map-support');

describe('server', () => {
	it('resolves with the return value of serverUtils.server called with expected args', () => {
		const expectedServer = 'foo';
		const fooRoute = { path: '/foo' };
		const fooPlugin = { register: 'foo' };
		const routes = [fooRoute];
		const plugins = [fooPlugin];
		spyOn(serverUtils, 'server').and.returnValue(Promise.resolve(expectedServer));
		spyOn(config, 'default').and.returnValue(Promise.resolve({}));
		return start({}, { routes, plugins }).then(returnedServer => {
			const callArgs = serverUtils.server.calls.mostRecent().args;
			expect(callArgs).toEqual([
				jasmine.any(Array),    // routes
				jasmine.any(Object),   // connection
				jasmine.any(Array),    // plugins
				jasmine.any(String),   // platform_agent
				jasmine.any(Object),   // config
			]);
			expect(callArgs[0].indexOf(fooRoute)).toBeGreaterThan(-1);
			expect(callArgs[2].indexOf(fooPlugin)).toBeGreaterThan(-1);
			expect(returnedServer).toBe(expectedServer);
		});
	});
	describe('Component tests', () => {
		const random32 = 'asdfasdfasdfasdfasdfasdfasdfasdf';
		const mockConfig = () => Promise.resolve({
			CSRF_SECRET: random32,
			COOKIE_ENCRYPT_SECRET: random32,
			oauth: {
				key: random32,
				secret: random32,
			}
		});
		it('starts the server', () => {
			const fooRoute = {
				method: 'get',
				path: '/foo',
				handler: (request, reply) => reply('okay')
			};
			const routes = [fooRoute];
			// spyOn(config, 'default').and.returnValue(Promise.resolve({}));
			return start({}, { routes }, mockConfig)
				.then(returnedServer => returnedServer.stop());
		});
		it('calls the handler for an unauthenticated route', () => {
			const expectedResponse = 'okay';
			const fooRoute = {
				method: 'get',
				path: '/foo',
				config: {
					auth: false,
				},
				handler: (request, reply) => reply(expectedResponse)
			};
			const routes = [fooRoute];
			// spyOn(config, 'default').and.returnValue(Promise.resolve({}));
			return start({}, { routes }, mockConfig)
				.then(server => {
					const requestFooRoute = {
						method: 'get',
						url: '/foo',
					};
					return server.inject(requestFooRoute).then(
						response => expect(response.payload).toEqual(expectedResponse)
					)
					.then(() => server.stop());
				});
		});
		it('calls the handler for an authenticated route', () => {
			const expectedResponse = 'okay';
			const fooRoute = {
				method: 'get',
				path: '/foo',
				handler: (request, reply) => reply(expectedResponse)
			};
			const routes = [fooRoute];
			// spyOn(config, 'default').and.returnValue(Promise.resolve({}));
			return start({}, { routes }, mockConfig)
				.then(server => {
					const authedRequestFooRoute = {
						method: 'get',
						url: '/foo',
						credentials: 'whatever',
					};
					return server.inject(authedRequestFooRoute).then(
						response => expect(response.payload).toEqual(expectedResponse)
					)
					.then(() => server.stop());
				});
		});
	});
});

<commit_msg>integration label<commit_after>import start from './server';
import * as serverUtils from './util/serverUtils';
import * as config from './util/config';

jest.mock('source-map-support');

describe('server', () => {
	it('resolves with the return value of serverUtils.server called with expected args', () => {
		const expectedServer = 'foo';
		const fooRoute = { path: '/foo' };
		const fooPlugin = { register: 'foo' };
		const routes = [fooRoute];
		const plugins = [fooPlugin];
		spyOn(serverUtils, 'server').and.returnValue(Promise.resolve(expectedServer));
		spyOn(config, 'default').and.returnValue(Promise.resolve({}));
		return start({}, { routes, plugins }).then(returnedServer => {
			const callArgs = serverUtils.server.calls.mostRecent().args;
			expect(callArgs).toEqual([
				jasmine.any(Array),    // routes
				jasmine.any(Object),   // connection
				jasmine.any(Array),    // plugins
				jasmine.any(String),   // platform_agent
				jasmine.any(Object),   // config
			]);
			expect(callArgs[0].indexOf(fooRoute)).toBeGreaterThan(-1);
			expect(callArgs[2].indexOf(fooPlugin)).toBeGreaterThan(-1);
			expect(returnedServer).toBe(expectedServer);
		});
	});
	describe('Integration tests', () => {
		const random32 = 'asdfasdfasdfasdfasdfasdfasdfasdf';
		const mockConfig = () => Promise.resolve({
			CSRF_SECRET: random32,
			COOKIE_ENCRYPT_SECRET: random32,
			oauth: {
				key: random32,
				secret: random32,
			}
		});
		it('starts the server', () => {
			const fooRoute = {
				method: 'get',
				path: '/foo',
				handler: (request, reply) => reply('okay')
			};
			const routes = [fooRoute];
			// spyOn(config, 'default').and.returnValue(Promise.resolve({}));
			return start({}, { routes }, mockConfig)
				.then(returnedServer => returnedServer.stop());
		});
		it('calls the handler for an unauthenticated route', () => {
			const expectedResponse = 'okay';
			const fooRoute = {
				method: 'get',
				path: '/foo',
				config: {
					auth: false,
				},
				handler: (request, reply) => reply(expectedResponse)
			};
			const routes = [fooRoute];
			// spyOn(config, 'default').and.returnValue(Promise.resolve({}));
			return start({}, { routes }, mockConfig)
				.then(server => {
					const requestFooRoute = {
						method: 'get',
						url: '/foo',
					};
					return server.inject(requestFooRoute).then(
						response => expect(response.payload).toEqual(expectedResponse)
					)
					.then(() => server.stop());
				});
		});
		it('calls the handler for an authenticated route', () => {
			const expectedResponse = 'okay';
			const fooRoute = {
				method: 'get',
				path: '/foo',
				handler: (request, reply) => reply(expectedResponse)
			};
			const routes = [fooRoute];
			// spyOn(config, 'default').and.returnValue(Promise.resolve({}));
			return start({}, { routes }, mockConfig)
				.then(server => {
					const authedRequestFooRoute = {
						method: 'get',
						url: '/foo',
						credentials: 'whatever',
					};
					return server.inject(authedRequestFooRoute).then(
						response => expect(response.payload).toEqual(expectedResponse)
					)
					.then(() => server.stop());
				});
		});
	});
});

<|endoftext|>


<commit_before>'use strict';
//CREATE IMG
function Images(name) {
  this.name = name;
  this.source = 'img/' + this.name + '.jpg';
  // this.vote = 0;//count when img gets picked
  // this.view = 0;//count when img displays
  Images.all.push(this);
}

Images.all = [];
Images.allNames = ['bag', 'banana', 'bathroom', 'boots', 'breakfast', 'bubblegum', 'chair', 'cthulhu', 'dog-duck', 'dragon', 'pen', 'pet-sweep', 'scissors', 'shark', 'sweep', 'tauntaun', 'unicorn', 'usb', 'water-can', 'wine-glass'];

Images.previousImg = [];

for(var i = 0; i < Images.allNames.length; i++){
  new Images(Images.allNames[i]);
}

function loadImg(){
  var randomIndex = Math.floor(Math.random() * Images.allNames.length);
  if(!Images.previousImg.includes(randomIndex)) {
    Images.all[randomIndex];
    var imgEl = document.createElement('img');
    imgEl.setAttribute('src', Images.all[randomIndex].source);
    imgEl.setAttribute('alt', Images.all[randomIndex].name);
    document.getElementById('img_box').appendChild(imgEl);
    Images.previousImg.push(randomIndex);
  } else {
    loadImg();
  }
}
//PAGE LOAD IMG
loadImg();
<commit_msg>added buttons and event handler<commit_after>'use strict';
//CREATE IMG
function Images(name) {
  this.name = name;
  this.source = 'img/' + this.name + '.jpg';
  // this.vote = 0;//count when img gets picked
  // this.view = 0;//count when img displays
  Images.all.push(this);
}

Images.all = [];
Images.allNames = ['bag', 'banana', 'bathroom', 'boots', 'breakfast', 'bubblegum', 'chair', 'cthulhu', 'dog-duck', 'dragon', 'pen', 'pet-sweep', 'scissors', 'shark', 'sweep', 'tauntaun', 'unicorn', 'usb', 'water-can', 'wine-glass'];

for(var i = 0; i < Images.allNames.length; i++){
  new Images(Images.allNames[i]);
}

Images.all[0].answer = [{y:'1 bag'},{n1: '2bags'},{n2: '3bags'}];

Images.previousImg = [];

function loadImg(){
  var randomIndex = Math.floor(Math.random() * Images.allNames.length);
  if(!Images.previousImg.includes(randomIndex)) {
    Images.all[randomIndex];
    var imgEl = document.createElement('img');
    imgEl.setAttribute('src', Images.all[randomIndex].source);
    imgEl.setAttribute('alt', Images.all[randomIndex].name);
    document.getElementById('img_box').appendChild(imgEl);
    Images.previousImg.push(randomIndex);

    for(var i = 0; i < Images.all[0].answer.length; i++){
      var btnEl = document.createElement('button');
      btnEl.textContent = Images.all[0].answer[i];
      btnEl.setAttribute('id', Object.keys(Images.all[0].answer[i]));
      document.getElementById('answers').appendChild(btnEl);
    }

  } else {
    loadImg();
  }
}
//PAGE LOAD IMG
loadImg();

function answersHandler(e) {
  console.log(e.target.id);
  if(e.target.id === 'y'){
    alert('Right!');
    document.getElementById('img_box').innerHTML = '';
    document.getElementById('answers').innerHTML = '';
    loadImg();
  } else {
    alert('Wrong!');
  }
}

//EVENT listener
document.getElementById('answers').addEventListener('click', answersHandler);
<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

/// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

/// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});

module.exports = app;
<commit_msg>test GH trigger<commit_after>var express = require('express');
var path = require('path');
var favicon = require('static-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
  , users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.use(favicon());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded());
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

/// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

/// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});

module.exports = app;
<|endoftext|>


<commit_before>import React from 'react'
import classes from './Speakers.scss'
import SpeakersSection from 'components/SpeakersSection'
import alex from 'static/Alex.png'
import stephen from 'static/Stephen.png'
import logo from 'static/blueprint-logo.png'

export const Speakers = () => (

 Speakers

        <SpeakersSection title={'Alex Deghan'}
          text={'Lorem ipsum dolor sit amet, consectetur adipiscing elit. \
          Suspendisse eu nisl sed velit convallis scelerisque eget sed nunc. \
          Donec ut turpis accumsan, lobortis turpis eu, tristique ante. \
          Cum sociis natoque penatibus et magnis dis parturient montes, nascetur \
          ridiculus mus. Nullam fermentum nisl est, id interdum nibh semper et. \
          Lorem ipsum dolor sit amet, consectetur adipiscing elit.'}
          imagePath={alex} />
        <SpeakersSection title={'Stephen Lee'}
          text={'Dr. Stephen T. Lee is the Chief Scientist (ST) at the U.S. \
          Army Research Office (ARO). He is interested in how technology can be \
          used to combat illegal poaching and the wildlife trade in Southern Africa.\
          Dr. Lee makes the case that reducing the illegal wildlife trade and poaching in \
          Africa is in the best interest of the international community regarding safety, \
          security, conservation and goodwill. Further, that science and technology have \
          pivotal roles to play via next generation tools and capabilities.'}
          imagePath={stephen} />
        <SpeakersSection title={'Stay Tuned'}
          beforeText={'We will be adding speakers as we get closer to the event. Want to be a speaker at this event? '}
          linkText={'Let us know!'}
          link={'mailto:speakers@dukeblueprint.com'}
          imagePath={logo} />

)

export default Speakers
<commit_msg>Updates speaker information<commit_after>import React from 'react'
import classes from './Speakers.scss'
import SpeakersSection from 'components/SpeakersSection'
import alex from 'static/Alex.png'
import stephen from 'static/Stephen.png'
import logo from 'static/blueprint-logo.png'

export const Speakers = () => (

 Speakers

        <SpeakersSection title={'Alex Deghan'}
          text={'Alex Dehgan is the founder of ConservationXLabs, a conservation technology \
          start-up focused on developing “Conservation 3.0.” He is also the former Chief Scientist at \
          the U.S. Agency for International Development (USAID) and a Rubenstein Fellow at Duke University. \
          As part of Obama’s promise to restore science and technology at USAID, Alex leveraged or \
          raised $500 million dollars in less than four years to establish the USAID Development Lab. \
          He also led efforts to create Afghanistan’s first national park, conducted the first \
          comprehensive biological surveys of the country in 30 years, helped develop Afghanistan’s \
          biodiversity conservation laws and policies, and curtailed illegal wildlife trade on US and \
          ISAF military bases. He was named an “Icon of Science” by Seed Magazine, and received the World \
          Technology Award for Policy in 2011.'}
          imagePath={alex} />
        <SpeakersSection title={'Stephen Lee'}
          text={'Dr. Stephen T. Lee is the Chief Scientist (ST) at the U.S. \
          Army Research Office (ARO). He is interested in how technology can be \
          used to combat illegal poaching and the wildlife trade in Southern Africa.\
          Dr. Lee makes the case that reducing the illegal wildlife trade and poaching in \
          Africa is in the best interest of the international community regarding safety, \
          security, conservation and goodwill. Further, that science and technology have \
          pivotal roles to play via next generation tools and capabilities.'}
          imagePath={stephen} />
        <SpeakersSection title={'Stay Tuned'}
          beforeText={'We will be adding speakers as we get closer to the event. Want to be a speaker at this event? '}
          linkText={'Let us know!'}
          link={'mailto:speakers@dukeblueprint.com'}
          imagePath={logo} />

)

export default Speakers
<|endoftext|>


<commit_before>module("Canvas Addon");

asyncTest("Canvas pixels", function (assert) {
	var context,
		canvas = document.getElementById('qunit-canvas'),
		imageObj = new Image();
	try {
		context = canvas.getContext('2d');
	} catch(e) {
		// probably no canvas support, just exit
		return;
	}

	expect(17);

	// how to use pixelEqual() in conjunction with HTML drawing
	context.fillStyle = 'rgba(0, 0, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 255, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 255, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 255, 153);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 255, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 255, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 0, 255, 153);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 0, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 255, 0, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 255, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 0, 255, 255);
	context.clearRect(0, 0, 5, 5);

	// how to use pixelEqual() in conjunction with drawImage()
	imageObj.onload = function() {
		context.drawImage( imageObj, 0, 0 );
		assert.pixelEqual( canvas, 3, 3, 0, 255, 0, 255, "green pixel" );
		start();
	};
	imageObj.src = "./0-255-0.gif";
});
<commit_msg>canvas addon: Fix jshint warnings<commit_after>module("Canvas Addon");

QUnit.asyncTest("Canvas pixels", function (assert) {
	var context,
		canvas = document.getElementById('qunit-canvas'),
		imageObj = new Image();
	try {
		context = canvas.getContext('2d');
	} catch(e) {
		// probably no canvas support, just exit
		return;
	}

	QUnit.expect(17);

	// how to use pixelEqual() in conjunction with HTML drawing
	context.fillStyle = 'rgba(0, 0, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 0);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 255, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 255, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 0, 0, 0, 0, 255, 153);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 255, 0, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 255, 0, 153);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 0.6)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 2, 2, 0, 0, 255, 153);
	context.clearRect(0, 0, 5, 5);

	context.fillStyle = 'rgba(0, 0, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 0, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(255, 0, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 255, 0, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 255, 0, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 255, 0, 255);
	context.clearRect(0, 0, 5, 5);
	context.fillStyle = 'rgba(0, 0, 255, 1)';
	context.fillRect(0, 0, 5, 5);
	assert.pixelEqual(canvas, 4, 4, 0, 0, 255, 255);
	context.clearRect(0, 0, 5, 5);

	// how to use pixelEqual() in conjunction with drawImage()
	imageObj.onload = function() {
		context.drawImage( imageObj, 0, 0 );
		assert.pixelEqual( canvas, 3, 3, 0, 255, 0, 255, "green pixel" );
		start();
	};
	imageObj.src = "./0-255-0.gif";
});
<|endoftext|>


<commit_before> /**
 * 框架默认配置
 * 可以在App/Conf/config.js里修改下面的配置值
 * @type {Object}
 */
module.exports = {
  port: 8360, //监听端口
  host: '', //监听的host
  use_proxy: false, //是否使用代理访问，如：nginx。开启后不能通过ip+端口直接访问
  encoding: 'utf-8', //输出数据的编码
  url_pathname_prefix: '',  //不解析的pathname前缀
  url_pathname_suffix: '.html', //不解析的pathname后缀，这样利于seo
  app_tag_on: true, //是否支持标签功能
  url_resource_on: true,  //是否监听静态资源类请求
  url_resource_reg: /^(resource\/|static\/|favicon\.ico)/, //判断是否是静态资源的正则
  url_route_on: true, //是否开启自定义路由功能

  post_json_content_type: ['application/json'], //post数据为json时的content-type
  post_max_file_size: 1024 * 1024 * 1024, //上传文件大小限制，默认1G
  post_max_fields: 100, //最大表单数，默认为100
  post_max_fields_size: 2 * 1024 * 1024, //单个表单长度最大值，默认为2MB
  post_ajax_filename_header: 'x-filename', //通过ajax上传文件时文件名对应的header，如果有这个header表示是文件上传
  post_file_upload_path: APP_PATH + '/Runtime/Temp', //文件上传的临时目录

  app_group_list: ['Home', 'Admin', 'Restful'], //分组列表
  deny_group_list: [],
  default_group: 'Home', //默认分组
  default_controller: 'Index', //默认模块
  default_action: 'index',  //默认Action
  call_controller: 'Home:Index:_404', //controller不存在时执行方法，此配置表示调用Home分组下IndexController的_404Action方法
  call_method: '__call', //当找不到方法时调用什么方法，这个方法存在时才有效
  before_action: '__before', //调用一个action前调用的方法，会将action名传递进去
  after_action: '__after', //调用一个action之后调用的方法，会将action名传递进去
  url_params_bind: true, //方法参数绑定,将URL参数值绑定到action的参数上
  action_suffix: 'Action', //action后缀
  url_callback_name: 'callback', //jsonp格式的callback名字
  json_content_type: 'application/json', //发送json时的content-type
  auto_send_content_type: true, //是否自动发送Content-Type,默认值为`tpl_content_type`配置值
  log_process_pid: true, //记录进程的id,方便其他脚本处理。
  use_cluster: false, //是否使用cluster，默认不使用，0：为cpu的数量，可以自定义值
  autoload_path: {}, //autoload查找的path，用于thinkRequire加载自定义库的时候查找
  create_server_fn: '', //自定义create server全局函数名，可以在Common/common.js里实现

  restful_group: 'Restful', //RESTFUL API默认分组

  load_ext_config: [], //加载额外的配置文件 CONF_PATH
  load_ext_file: [], //加载额外的文件 COMMON_PATH

  use_websocket: false, //是否使用websocket
  websocket_allow_origin: '', //允许从那里发送过来的websocket，可以是字符串、数组、回调函数，为空表示不检测
  websocket_sub_protocal: '', //websocket子协议，可以是个字符串也可以是回调函数
  websocket_message_handle: undefined, //websocket消息处理函数

  error_tpl_path: THINK_PATH + '/View/error.html', //错误页模版
  error_no_key: 'errno', //错误number的key
  error_no_default_value: 1000, //错误号默认值
  error_msg_key: 'errmsg', //错误消息的key

  cookie_domain: '', //cookie有效域名
  cookie_path: '/',   //cookie路径
  cookie_timeout: 0, //cookie失效时间，0为浏览器关闭，单位：秒

  session_name: 'thinkjs', //session对应的cookie名称
  session_type: 'File', //session存储类型, 空为内存，还可以为File
  session_path: '', //File类型下文件存储位置，默认为系统的tmp目录
  session_options: {}, //session对应的cookie选项
  session_sign: '', //session对应的cookie使用签名
  session_timeout: 24 * 3600, //服务器上session失效时间，单位：秒

  db_type: 'mysql', // 数据库类型
  db_host: '127.0.0.1', // 服务器地址
  db_port: '', // 端口
  db_name: '', // 数据库名
  db_user: 'root', // 用户名
  db_pwd: '', // 密码
  db_prefix: 'think_', // 数据库表前缀
  db_charset: 'utf8', // 数据库编码默认采用utf8
  db_ext_config: {}, //数据库连接时候额外的参数
  db_fieldtype_check: false, // 是否进行字段类型检查
  db_fields_cache: true, // 启用字段缓存
  db_nums_per_page: 20, //默认每页显示的条数
  db_like_fields: [], //自动进行模糊查询,|连接，如: ['title', 'content']
  db_cache_on: true, //是否启用查询缓存，如果关闭那么cache方法则无效
  db_cache_type: '', //缓存类型，默认为内存缓存
  db_cache_path: CACHE_PATH + '/db', //缓存路径，File类型下有效
  db_cache_timeout: 3600, //缓存时间，默认为1个小时
  db_log_sql: false, //是否打印sql语句
  db_buffer_tostring: true, //是否将buffer转为字符串

  tpl_content_type: 'text/html', //模版输出类型
  tpl_file_suffix: '.html', //模版文件名后缀
  tpl_file_depr: '_', //controller和action之间的分隔符
  tpl_engine_type: 'ejs', //模版引擎名称
  tpl_engine_config: {},

  token_on: false, //是否开启token功能
  token_name: 'token', //token name
  token_key: '{__TOKEN__}', //记录token在模版中的位置替换用。默认自动查找<form和标签替换

  log_console: false, //是否记录日志，开启后会重写console.error等系列方法
  log_console_path: LOG_PATH + '/console', //日志文件存放路径
  log_console_type: ['error'], //默认只接管console.error日志
  log_memory: false, //记录内存使用和负载
  log_memory_path: LOG_PATH + '/memory', //日志文件存放路径
  log_memory_interval: 60 * 1000, //一分钟记录一次

  cache_type: 'File', //数据缓存类型
  cache_key_prefix: '__thinkjs__', //缓存key前置(memcache和redis下有效)
  cache_timeout: 6 * 3600, //数据缓存有效期，单位: 秒
  cache_path: CACHE_PATH,  //缓存路径设置 (File缓存方式有效)
  cache_file_suffix: '.json', //File缓存方式下文件后缀名
  cache_gc_hour: [4], //缓存清除的时间点，数据为小时

  html_cache_on: false, //HTML静态缓存
  html_cache_timeout: 3600, //缓存时间，单位为秒
  html_cache_rules: {}, //缓存规则
  html_cache_path: CACHE_PATH + '/html',
  html_cache_file_callback: undefined, //生成缓存文件的回调函数
  html_cache_file_suffix: '.html', //缓存文件后缀名

  memcache_host: '127.0.0.1', //memcache host
  memcache_port: 11211, //memecache端口

  redis_host: '127.0.0.1', //redis host
  redis_port: 6379, // redis port
};<commit_msg>添加robot.txt到url_resource_reg配置里<commit_after> /**
 * 框架默认配置
 * 可以在App/Conf/config.js里修改下面的配置值
 * @type {Object}
 */
module.exports = {
  port: 8360, //监听端口
  host: '', //监听的host
  use_proxy: false, //是否使用代理访问，如：nginx。开启后不能通过ip+端口直接访问
  encoding: 'utf-8', //输出数据的编码
  url_pathname_prefix: '',  //不解析的pathname前缀
  url_pathname_suffix: '.html', //不解析的pathname后缀，这样利于seo
  app_tag_on: true, //是否支持标签功能
  url_resource_on: true,  //是否监听静态资源类请求
  url_resource_reg: /^(resource\/|static\/|favicon\.ico|robot\.txt)/, //判断是否是静态资源的正则
  url_route_on: true, //是否开启自定义路由功能

  post_json_content_type: ['application/json'], //post数据为json时的content-type
  post_max_file_size: 1024 * 1024 * 1024, //上传文件大小限制，默认1G
  post_max_fields: 100, //最大表单数，默认为100
  post_max_fields_size: 2 * 1024 * 1024, //单个表单长度最大值，默认为2MB
  post_ajax_filename_header: 'x-filename', //通过ajax上传文件时文件名对应的header，如果有这个header表示是文件上传
  post_file_upload_path: APP_PATH + '/Runtime/Temp', //文件上传的临时目录

  app_group_list: ['Home', 'Admin', 'Restful'], //分组列表
  deny_group_list: [],
  default_group: 'Home', //默认分组
  default_controller: 'Index', //默认模块
  default_action: 'index',  //默认Action
  call_controller: 'Home:Index:_404', //controller不存在时执行方法，此配置表示调用Home分组下IndexController的_404Action方法
  call_method: '__call', //当找不到方法时调用什么方法，这个方法存在时才有效
  before_action: '__before', //调用一个action前调用的方法，会将action名传递进去
  after_action: '__after', //调用一个action之后调用的方法，会将action名传递进去
  url_params_bind: true, //方法参数绑定,将URL参数值绑定到action的参数上
  action_suffix: 'Action', //action后缀
  url_callback_name: 'callback', //jsonp格式的callback名字
  json_content_type: 'application/json', //发送json时的content-type
  auto_send_content_type: true, //是否自动发送Content-Type,默认值为`tpl_content_type`配置值
  log_process_pid: true, //记录进程的id,方便其他脚本处理。
  use_cluster: false, //是否使用cluster，默认不使用，0：为cpu的数量，可以自定义值
  autoload_path: {}, //autoload查找的path，用于thinkRequire加载自定义库的时候查找
  create_server_fn: '', //自定义create server全局函数名，可以在Common/common.js里实现

  restful_group: 'Restful', //RESTFUL API默认分组

  load_ext_config: [], //加载额外的配置文件 CONF_PATH
  load_ext_file: [], //加载额外的文件 COMMON_PATH

  use_websocket: false, //是否使用websocket
  websocket_allow_origin: '', //允许从那里发送过来的websocket，可以是字符串、数组、回调函数，为空表示不检测
  websocket_sub_protocal: '', //websocket子协议，可以是个字符串也可以是回调函数
  websocket_message_handle: undefined, //websocket消息处理函数

  error_tpl_path: THINK_PATH + '/View/error.html', //错误页模版
  error_no_key: 'errno', //错误number的key
  error_no_default_value: 1000, //错误号默认值
  error_msg_key: 'errmsg', //错误消息的key

  cookie_domain: '', //cookie有效域名
  cookie_path: '/',   //cookie路径
  cookie_timeout: 0, //cookie失效时间，0为浏览器关闭，单位：秒

  session_name: 'thinkjs', //session对应的cookie名称
  session_type: 'File', //session存储类型, 空为内存，还可以为File
  session_path: '', //File类型下文件存储位置，默认为系统的tmp目录
  session_options: {}, //session对应的cookie选项
  session_sign: '', //session对应的cookie使用签名
  session_timeout: 24 * 3600, //服务器上session失效时间，单位：秒

  db_type: 'mysql', // 数据库类型
  db_host: '127.0.0.1', // 服务器地址
  db_port: '', // 端口
  db_name: '', // 数据库名
  db_user: 'root', // 用户名
  db_pwd: '', // 密码
  db_prefix: 'think_', // 数据库表前缀
  db_charset: 'utf8', // 数据库编码默认采用utf8
  db_ext_config: {}, //数据库连接时候额外的参数
  db_fieldtype_check: false, // 是否进行字段类型检查
  db_fields_cache: true, // 启用字段缓存
  db_nums_per_page: 20, //默认每页显示的条数
  db_like_fields: [], //自动进行模糊查询,|连接，如: ['title', 'content']
  db_cache_on: true, //是否启用查询缓存，如果关闭那么cache方法则无效
  db_cache_type: '', //缓存类型，默认为内存缓存
  db_cache_path: CACHE_PATH + '/db', //缓存路径，File类型下有效
  db_cache_timeout: 3600, //缓存时间，默认为1个小时
  db_log_sql: false, //是否打印sql语句
  db_buffer_tostring: true, //是否将buffer转为字符串

  tpl_content_type: 'text/html', //模版输出类型
  tpl_file_suffix: '.html', //模版文件名后缀
  tpl_file_depr: '_', //controller和action之间的分隔符
  tpl_engine_type: 'ejs', //模版引擎名称
  tpl_engine_config: {},

  token_on: false, //是否开启token功能
  token_name: 'token', //token name
  token_key: '{__TOKEN__}', //记录token在模版中的位置替换用。默认自动查找<form和标签替换

  log_console: false, //是否记录日志，开启后会重写console.error等系列方法
  log_console_path: LOG_PATH + '/console', //日志文件存放路径
  log_console_type: ['error'], //默认只接管console.error日志
  log_memory: false, //记录内存使用和负载
  log_memory_path: LOG_PATH + '/memory', //日志文件存放路径
  log_memory_interval: 60 * 1000, //一分钟记录一次

  cache_type: 'File', //数据缓存类型
  cache_key_prefix: '__thinkjs__', //缓存key前置(memcache和redis下有效)
  cache_timeout: 6 * 3600, //数据缓存有效期，单位: 秒
  cache_path: CACHE_PATH,  //缓存路径设置 (File缓存方式有效)
  cache_file_suffix: '.json', //File缓存方式下文件后缀名
  cache_gc_hour: [4], //缓存清除的时间点，数据为小时

  html_cache_on: false, //HTML静态缓存
  html_cache_timeout: 3600, //缓存时间，单位为秒
  html_cache_rules: {}, //缓存规则
  html_cache_path: CACHE_PATH + '/html',
  html_cache_file_callback: undefined, //生成缓存文件的回调函数
  html_cache_file_suffix: '.html', //缓存文件后缀名

  memcache_host: '127.0.0.1', //memcache host
  memcache_port: 11211, //memecache端口

  redis_host: '127.0.0.1', //redis host
  redis_port: 6379, // redis port
};<|endoftext|>


<commit_before>F=function(c){
	var _=this					// this context
		,x						// the context selected by querySelector
		,l						// length of x
		,i						// placeholder counter1
		,j						// placeholder counter2
		,a						// placeholder array
		,g;						// placeholder generic

	// Global vars
	F.d=d	=document;
	F.L=L	="length";
	F.Q=Q	="querySelectorAll";
	F.H		="innerHTML";

	if(_.__proto__.constructor!=F)return new F(c);

	/**
	 * Iterate over context, call v for each item
	 * Note: Iteration is inverse
	 * @param {Function} v
	 * @returns {F}
	 */
	_.each=function(v){
		for(i=l;i--;)v(_[i],i);
		return this
	};

	/**
	 * Reset keys inside this object and recount length
	 */
	_.y=function(){
		for(i=99;i--;)delete _[i];	// clean up objects indicies
		for(i in x)_[i]=x[i];		// assign new indicies
		_[L]=l=x[L]					// set .length and internal placeholder l
		this.x=x;
	};

	/**
	 * Find selector v in context
	 * @param {String} v
	 * @returns {F}
	 */
	_.find=function(v){
		try{
			a=v.split(" ");
			v="";
			for(i in a)
				g=a[i].split(":"),
				g[1]=!isNaN(g[1])?":nth-of-type("+(parseInt(g[1])+1)+")":g[1]?":"+g[1]:"",
				v+=" "+g[0]+g[1];

			a=[];
			if(!x)a=d[Q](v);
			else for(i=l;i--;)a[i]=x[i][Q](v);

			x=[];
			for(i=0;i<a[L];i++)
				if((g=a[i])[L]&&!g.options)
					for(j=0;j<g[L];j++)
						x.push(g[j]);
				else x.push(g);
			_.y();
		}catch(e){};

		return this
	};

	/**
	 * Get element at index v from context
	 * @param {Number} v index
	 * @returns {F}
	 */
	_.get=function(v){
		x=[x[v]];
		_.y();

		return this
	};

	/**
	 * Load a number of scripts synchronously
	 * @param {Array} a contains urls
	 * @param [s] placeholder script-string
	 * @param [r] placeholder xhr-request
	 */
	_.require=function(a,s,r){
		s="";
		for(i in a)
			(r=new XMLHttpRequest).open('GET',a[i],false),
			r.send(''),
			s+=r.responseText;

		eval(s);

		return this
	};

	// select context
	_.find(c);

	return this
};

/**
 * Extend frameWreck with a module
 * @param {Object} m Module
 */
F.ext=function(m){
	for(i in m)
		F.prototype[i]=m[i]
};<commit_msg>minifying<commit_after>F=function(c){
	var _=this					// this context
		,x						// the context selected by querySelector
		,l						// length of x
		,i						// placeholder counter1
		,j						// placeholder counter2
		,a						// placeholder array
		,g;						// placeholder generic

	// Global vars
	F.d=d	=document;
	F.L=L	="length";
	F.Q=Q	="querySelectorAll";
	F.H		="innerHTML";

	if(_.__proto__.constructor!=F)return new F(c);

	/**
	 * Iterate over context, call v for each item
	 * Note: Iteration is inverse
	 * @param {Function} v
	 * @returns {F}
	 */
	_.each=function(v){
		for(i=l;i--;)v(_[i],i);
		return _
	};

	/**
	 * Reset keys inside this object and recount length
	 */
	_.y=function(){
		for(i=99;i--;)x[i]?_[i]=x[i]:delete _[i];	// clean up objects indicies and assign new indicies
		_[L]=l=x[L];								// set .length and internal placeholder l
		this.x=x;
	};

	/**
	 * Find selector v in context
	 * @param {String} v
	 * @returns {F}
	 */
	_.find=function(v){
		try{
			a=v.split(" ");
			v="";
			for(i in a)
				v+=" "+(g=a[i].split(":"))[0]+(!isNaN(j=g[1])?":nth-of-type("+(+j+1)+")":j?":"+j:"");

			if(!x)l=1,x=[d];
			for(a=[],i=l;i--;)a[i]=x[i][Q](v);

			x=[];
			for(i=0;i<a[L];i++)
				if((g=a[i])[L]&&!g.options)
					for(j=0;j<g[L];j++)
						x.push(g[j]);
				else x.push(g);
			_.y();
		}catch(e){}

		return _
	};

	/**
	 * Get element at index v from context
	 * @param {Number} v index
	 * @returns {F}
	 */
	_.get=function(v){
		x=[x[v]];
		_.y();

		return _
	};

	/**
	 * Load a number of scripts synchronously
	 * @param {Array} a contains urls
	 * @param [s] placeholder script-string
	 * @param [r] placeholder xhr-request
	 */
	_.require=function(a,s,r){
		s="";
		for(i in a)
			(r=new XMLHttpRequest).open('GET',a[i],false),
			r.send(''),
			s+=r.responseText;

		eval(s);

		return _
	};

	// select context
	return _.find(c)
};

/**
 * Extend frameWreck with a module
 * @param {Object} m Module
 */
F.ext=function(m){
	for(i in m)
		F.prototype[i]=m[i]
};<|endoftext|>


<commit_before>angular
	.module('addGame')
	.controller('AddGameController', AddGameController);

function AddGameController($scope, $rootScope, localStorage, FooseyService)
{
	// Set up the types of games you can play
	$scope.gameTypes = [
		{
			name: "1 vs. 1",
			teams: 2,
			playersPerTeam: 1
		},
		{
			name: "2 vs. 2",
			teams: 2,
			playersPerTeam: 2
		},
		{
			name: "Trips",
			teams: 3,
			playersPerTeam: 1
		}
	];

	$scope.reset = reset;

	// initialize page
	reset();
	$scope.scores = new Array(11);

	// function to select game
	$scope.gameSelect = function(type)
	{
		$scope.type = _.clone(type);
		$scope.playersSelected = [];
		$scope.state = "player-select";
		$scope.title = "Select Players";
	};

	// function to select player
	$scope.playerSelect = function(player)
	{
		// don't allow selected players to be selected again
		if (player.selected) return;

		// add player to this team
		player.selected = true;
		$scope.playersSelected.push(player.name);

		// if we have selected all players for the team, select the score
		if ($scope.playersSelected.length === $scope.type.playersPerTeam)
		{
			$scope.state = "score-select";
			$scope.title = "Select Score";
		}
	};

	// function to select score
	$scope.scoreSelect = function(score)
	{
		appendToCommand($scope.playersSelected, score);

		$scope.game.push({
			players: $scope.playersSelected,
			score: score
		});

		$scope.playersSelected = [];
		$scope.type.teams--;

		// if we have scores for every team, go to confirm
		if ($scope.type.teams === 0)
		{
			$scope.state = "confirm";
			$scope.title = "Confirm";
		}
		else
		{
			$scope.state = "player-select";
			$scope.title = "Select Players";
		}
	};

	// add the game
	$scope.submit = function()
	{
		$scope.state = "saving";
		$scope.saveStatus = "saving";
		console.log($scope.command);
		FooseyService.addGame($scope.command).then(function successCallback(response)
		{
			$scope.response = response.data;
			$scope.saveStatus = "success";
		}, function errorCallback(response)
    {
    	if ($scope.state === "saving")
      	$scope.saveStatus = "failed";
    });
	}

	// undo last game
	$scope.undo = function()
	{
		FooseyService.undo();
		$scope.saveStatus = "removed";
		$scope.response = [];
	}

	// function to build the add command out for foosey
	function appendToCommand(players, score)
	{
		for (var i = 0; i < $scope.type.playersPerTeam; i++)
		{
			$scope.command += players[i] + " " + score + " ";
		}
	}

	// reset the game
	function reset()
	{
		$scope.state = "game-select";
		$scope.title = "Select the Type of Game";
		$scope.command = "";
		$scope.game = [];
		$scope.saveStatus = "";
		$scope.response = undefined;
		getPlayers();
	}

	// get players from server
	function getPlayers()
	{
		// load from local storage
		$scope.players = localStorage.getObject('players');

		// load from server
		FooseyService.players().then(function (response)
    	{
	    	// only overwrite if they haven't selected one yet
	    	if (noneSelected())
	    	{
	    		$scope.players = response.data.players;
	    		$scope.players.sort(function(a, b){
	    			return a.name.localeCompare(b.name);
	    		});
	    	}

	    	localStorage.setObject('players', response.data.players);
	  	});
	}

	// return true if none of the players have been selected yet
	function noneSelected()
	{
		for (var i = 0; i < $scope.players.length; i++)
		{
			if ($scope.players[i].selected) return false;
		}
		return true;
	}

	$rootScope.$on("$stateChangeSuccess", function() {
	  reset();
	});

}<commit_msg>Scroll top for add game screen<commit_after>angular
	.module('addGame')
	.controller('AddGameController', AddGameController);

function AddGameController($scope, $rootScope, $ionicScrollDelegate, localStorage, FooseyService)
{
	// Set up the types of games you can play
	$scope.gameTypes = [
		{
			name: "1 vs. 1",
			teams: 2,
			playersPerTeam: 1
		},
		{
			name: "2 vs. 2",
			teams: 2,
			playersPerTeam: 2
		},
		{
			name: "Trips",
			teams: 3,
			playersPerTeam: 1
		}
	];

	$scope.reset = reset;

	// initialize page
	reset();
	$scope.scores = new Array(11);

	// function to select game
	$scope.gameSelect = function(type)
	{
		$scope.type = _.clone(type);
		$scope.playersSelected = [];
		changeState("player-select", "Select Players");
	};

	// function to select player
	$scope.playerSelect = function(player)
	{
		// don't allow selected players to be selected again
		if (player.selected) return;

		// add player to this team
		player.selected = true;
		$scope.playersSelected.push(player.name);

		// if we have selected all players for the team, select the score
		if ($scope.playersSelected.length === $scope.type.playersPerTeam)
		{
			changeState("score-select", "Select Score");
		}
	};

	// function to select score
	$scope.scoreSelect = function(score)
	{
		appendToCommand($scope.playersSelected, score);

		$scope.game.push({
			players: $scope.playersSelected,
			score: score
		});

		$scope.playersSelected = [];
		$scope.type.teams--;

		// if we have scores for every team, go to confirm
		if ($scope.type.teams === 0)
		{
			changeState("confirm", "Confirm");
		}
		else
		{
			changeState("player-select", "Select Players");
		}
	};

	// add the game
	$scope.submit = function()
	{
		$scope.state = "saving";
		changeState("saving", null);
		$scope.saveStatus = "saving";
		console.log($scope.command);
		FooseyService.addGame($scope.command).then(function successCallback(response)
		{
			$scope.response = response.data;
			$scope.saveStatus = "success";
		}, function errorCallback(response)
    {
    	if ($scope.state === "saving")
      	$scope.saveStatus = "failed";
    });
	}

	// undo last game
	$scope.undo = function()
	{
		FooseyService.undo();
		$scope.saveStatus = "removed";
		$scope.response = [];
	}

	// function to build the add command out for foosey
	function appendToCommand(players, score)
	{
		for (var i = 0; i < $scope.type.playersPerTeam; i++)
		{
			$scope.command += players[i] + " " + score + " ";
		}
	}

	// reset the game
	function reset()
	{
		changeState("game-select", "Select the Type of Game");
		$scope.command = "";
		$scope.game = [];
		$scope.saveStatus = "";
		$scope.response = undefined;
		getPlayers();
	}

	// get players from server
	function getPlayers()
	{
		// load from local storage
		$scope.players = localStorage.getObject('players');

		// load from server
		FooseyService.players().then(function (response)
    	{
	    	// only overwrite if they haven't selected one yet
	    	if (noneSelected())
	    	{
	    		$scope.players = response.data.players;
	    		$scope.players.sort(function(a, b){
	    			return a.name.localeCompare(b.name);
	    		});
	    	}

	    	localStorage.setObject('players', response.data.players);
	  	});
	}

	// return true if none of the players have been selected yet
	function noneSelected()
	{
		for (var i = 0; i < $scope.players.length; i++)
		{
			if ($scope.players[i].selected) return false;
		}
		return true;
	}

	function changeState(state, title)
	{
		if (state) $scope.state = state;
		if (title) $scope.title = title;
		$ionicScrollDelegate.scrollTop();
	}

	$rootScope.$on("$stateChangeSuccess", function() {
	  reset();
	});

}<|endoftext|>


<commit_before>(function() {
  $(function() {
    var number_of_units, quantity, quantity_spinner, radios, selectedRadio, unit_amount;

    unit_amount = 0;
    quantity = 0;

    Spree.updateTotalUnits = function(variant) {
      return unit_amount = variant.data('unitAmount');
    };

    Spree.updateQuantity = function(q_spinner) {
      return quantity = q_spinner[0].valueAsNumber;
    };

    Spree.checkStock = function () {
      return quantity * unit_amount;
    };

    radios = $('#product-variants input[type="radio"]');
    if (radios.length > 0) {
      selectedRadio = $('#product-variants input[type="radio"][checked="checked"]');
      Spree.updateTotalUnits(selectedRadio);
    }

    var number_of_units = ($('span#number_of_units')).data('num-units');
    var quantity_spinner = $('input#quantity[type="number"]');
    var spinner = quantity_spinner.spinner({
      change: function (event, ui) {
        Spree.updateQuantity($(this));
      },
    });

    return radios.click(function(event) {
      Spree.updateTotalUnits($(this));
      Spree.updateQuantity(quantity_spinner);
    });
  });

}).call(this);

<commit_msg>Numbers update exactly on interaction.<commit_after>(function() {
  $(function() {
    var number_of_units, quantity, quantity_spinner, radios, selectedRadio, unit_amount;

    unit_amount = 0;
    quantity = 0;

    Spree.updateTotalUnits = function(variant) {
      return unit_amount = variant.data('unitAmount');
    };

    Spree.updateQuantity = function(q_spinner) {
      return quantity = q_spinner[0].valueAsNumber;
    };

    Spree.checkStock = function () {
      return quantity * unit_amount;
    };

    radios = $('#product-variants input[type="radio"]');
    if (radios.length > 0) {
      selectedRadio = $('#product-variants input[type="radio"][checked="checked"]');
      Spree.updateTotalUnits(selectedRadio);
    }

    var number_of_units = ($('span#number_of_units')).data('num-units');
    var quantity_spinner = $('input#quantity[type="number"]');
    $('input#quantity[type="number"]').spinner({
      stop: function (event, ui) {
        Spree.updateQuantity($(this));
      },
    });

    return radios.click(function(event) {
      Spree.updateTotalUnits($(this));
      Spree.updateQuantity(quantity_spinner);
    });
  });

}).call(this);

<|endoftext|>