first commit

This commit is contained in:
Francois Klieber committed 2021-06-06 20:25:14 +02:00
commit aa7869eb33
386 files changed
+69375

No files matched your search

+48
View File
@@ -0,0 +1,48 @@
const fs = require('fs');
const _ = require('lodash');
const cache = require('./state/cache');
const broadcast = cache.get('broadcast');
const apiKeysFile = __dirname + '/../SECRET-api-keys.json';
// on init:
const noApiKeysFile = !fs.existsSync(apiKeysFile);
if(noApiKeysFile)
fs.writeFileSync(
apiKeysFile,
JSON.stringify({})
);
const apiKeys = JSON.parse( fs.readFileSync(apiKeysFile, 'utf8') );
module.exports = {
get: () => _.keys(apiKeys),
// note: overwrites if exists
add: (exchange, props) => {
apiKeys[exchange] = props;
fs.writeFileSync(apiKeysFile, JSON.stringify(apiKeys));
broadcast({
type: 'apiKeys',
exchanges: _.keys(apiKeys)
});
},
remove: exchange => {
if(!apiKeys[exchange])
return;
delete apiKeys[exchange];
fs.writeFileSync(apiKeysFile, JSON.stringify(apiKeys));
broadcast({
type: 'apiKeys',
exchanges: _.keys(apiKeys)
});
},
// retrieve api keys
// this cannot touch the frontend for security reaons.
_getApiKeyPair: key => apiKeys[key]
}
+26
View File
@@ -0,0 +1,26 @@
// Note: this file gets copied around, make sure you edit
// the UIconfig located at `gekko/web/vue/dist/UIconfig.js`.
// This config is used by both the frontend as well as the web server.
// see https://gekko.wizb.it/docs/installation/installing_gekko_on_a_server.html#Configuring-Gekko
const CONFIG = {
headless: false,
api: {
host: '127.0.0.1',
port: 3000,
timeout: 120000 // 2 minutes
},
ui: {
ssl: false,
host: 'localhost',
port: 3000,
path: '/'
},
adapter: 'sqlite'
}
if(typeof window === 'undefined')
module.exports = CONFIG;
else
window.CONFIG = CONFIG;
+9
View File
@@ -0,0 +1,9 @@
const os = require('os');
var isWindows = (
os.platform() == 'win32' // true evenon 64 bit archs
|| os.release().indexOf('Microsoft') > -1 // bash on Windows 10 scenario
);
module.exports = isWindows;
+26
View File
@@ -0,0 +1,26 @@
const cache = require('../state/cache');
const manager = cache.get('apiKeyManager');
module.exports = {
get: function *() {
this.body = manager.get();
},
add: function *() {
const content = this.request.body;
manager.add(content.exchange, content.values);
this.body = {
status: 'ok'
};
},
remove: function *() {
const exchange = this.request.body.exchange;
manager.remove(exchange);
this.body = {
status: 'ok'
};
}
}
+31
View File
@@ -0,0 +1,31 @@
// simple POST request that returns the backtest result
const _ = require('lodash');
const promisify = require('tiny-promisify');
const pipelineRunner = promisify(require('../../core/workers/pipeline/parent'));
// starts a backtest
// requires a post body like:
//
// {
// gekkoConfig: {watch: {exchange: "poloniex", currency: "USDT", asset: "BTC"},…},…}
// data: {
// candleProps: ["close", "start"],
// indicatorResults: true,
// report: true,
// roundtrips: true
// }
// }
module.exports = function *() {
var mode = 'backtest';
var config = {};
var base = require('./baseConfig');
var req = this.request.body;
_.merge(config, base, req);
this.body = yield pipelineRunner(mode, config);
}
+104
View File
@@ -0,0 +1,104 @@
var UIconfig = require('../vue/dist/UIconfig');
var config = {};
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// GENERAL SETTINGS
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
config.silent = false;
config.debug = true;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CONFIGURING TRADING ADVICE
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
config.tradingAdvisor = {
}
config.candleWriter = {
enabled: false
}
config.backtestResultExporter = {
enabled: false,
writeToDisk: false,
data: {
stratUpdates: false,
roundtrips: true,
stratCandles: true,
trades: true
}
}
config.childToParent = {
enabled: false,
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CONFIGURING ADAPTER
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// configurable in the UIconfig
config.adapter = UIconfig.adapter;
config.sqlite = {
path: 'plugins/sqlite',
version: 0.1,
dataDirectory: 'history',
journalMode: require('../isWindows.js') ? 'PERSIST' : 'WAL',
dependencies: [{
module: 'sqlite3',
version: '3.1.4'
}]
}
// Postgres adapter example config (please note: requires postgres >= 9.5):
config.postgresql = {
path: 'plugins/postgresql',
version: 0.1,
connectionString: 'postgres://user:pass@localhost:5432', // if default port
database: null, // if set, we'll put all tables into a single database.
schema: 'public',
dependencies: [{
module: 'pg',
version: '7.4.3'
}]
}
// Mongodb adapter, requires mongodb >= 3.3 (no version earlier tested)
config.mongodb = {
path: 'plugins/mongodb',
version: 0.1,
connectionString: 'mongodb://mongodb/gekko', // connection to mongodb server
dependencies: [{
module: 'mongojs',
version: '2.4.0'
}]
}
config.adviceWriter = {
enabled: false,
muteSoft: true,
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// CONFIGURING BACKTESTING
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Note that these settings are only used in backtesting mode, see here:
// @link: https://github.com/askmike/gekko/blob/stable/docs/Backtesting.md
config.backtest = {
daterange: 'scan',
batchSize: 50
}
config.importer = {
daterange: {
// NOTE: these dates are in UTC
from: "2016-06-01 12:00:00"
}
}
module.exports = config;
+20
View File
@@ -0,0 +1,20 @@
const _ = require('lodash');
const fs = require('co-fs');
const parts = {
paperTrader: 'config/plugins/paperTrader',
candleWriter: 'config/plugins/candleWriter',
performanceAnalyzer: 'config/plugins/performanceAnalyzer'
}
const gekkoRoot = __dirname + '/../../';
module.exports = function *() {
if(!_.has(parts, this.params.part))
return this.body = 'error :(';
const fileName = gekkoRoot + '/' + parts[this.params.part] + '.toml';
this.body = {
part: yield fs.readFile(fileName, 'utf8')
}
}
+22
View File
@@ -0,0 +1,22 @@
const cache = require('../state/cache');
const gekkoManager = cache.get('gekkos');
// Deletes a gekko
// requires a post body with an id
module.exports = function *() {
let id = this.request.body.id;
if(!id) {
this.body = { status: 'not ok' }
return;
}
try {
gekkoManager.delete(id);
} catch(e) {
this.body = { status: e.message }
}
this.body = { status: 'ok' };
}
+39
View File
@@ -0,0 +1,39 @@
const _ = require('lodash');
const fs = require('co-fs');
const gekkoRoot = __dirname + '/../../';
var util = require(__dirname + '/../../core/util');
var config = {};
config.debug = false;
config.silent = false;
util.setConfig(config);
module.exports = function *() {
const exchangesDir = yield fs.readdir(gekkoRoot + 'exchange/wrappers/');
const exchanges = exchangesDir
.filter(f => _.last(f, 3).join('') === '.js')
.map(f => f.slice(0, -3));
let allCapabilities = [];
exchanges.forEach(function (exchange) {
let Trader = null;
try {
Trader = require(gekkoRoot + 'exchange/wrappers/' + exchange);
} catch (e) {
return;
}
if (!Trader || !Trader.getCapabilities) {
return;
}
allCapabilities.push(Trader.getCapabilities());
});
this.body = allCapabilities;
}
+40
View File
@@ -0,0 +1,40 @@
// simple POST request that returns the candles requested
// expects a config like:
// let config = {
// watch: {
// exchange: 'poloniex',
// currency: 'USDT',
// asset: 'BTC'
// },
// daterange: {
// from: '2016-05-22 11:22',
// to: '2016-06-03 19:56'
// },
// adapter: 'sqlite',
// sqlite: {
// path: 'plugins/sqlite',
// dataDirectory: 'history',
// version: 0.1,
// dependencies: [{
// module: 'sqlite3',
// version: '3.1.4'
// }]
// },
// candleSize: 100
// }
const _ = require('lodash');
const promisify = require('tiny-promisify');
const candleLoader = promisify(require('../../core/workers/loadCandles/parent'));
const base = require('./baseConfig');
module.exports = function *() {
config = {};
_.merge(config, base, this.request.body);
this.body = yield candleLoader(config);
}
+75
View File
@@ -0,0 +1,75 @@
const _ = require('lodash');
const promisify = require('tiny-promisify');
const pipelineRunner = promisify(require('../../core/workers/pipeline/parent'));
const cache = require('../state/cache');
const broadcast = cache.get('broadcast');
const importManager = cache.get('imports');
const base = require('./baseConfig');
// starts an import
// requires a post body with a config object
module.exports = function *() {
let mode = 'importer';
let config = {}
_.merge(config, base, this.request.body);
let importId = (Math.random() + '').slice(3);
let errored = false;
console.log('Import', importId, 'started');
pipelineRunner(mode, config, (err, event) => {
if(errored)
return;
if(err) {
errored = true;
console.error('RECEIVED ERROR IN IMPORT', importId);
console.error(err);
importManager.delete(importId);
return broadcast({
type: 'import_error',
import_id: importId,
error: err
});
}
if(!event)
return;
// update local cache
importManager.update(importId, {
latest: event.latest,
done: event.done
});
// emit update over ws
let wsEvent = {
type: 'import_update',
import_id: importId,
updates: {
latest: event.latest,
done: event.done
}
}
broadcast(wsEvent);
});
let daterange = this.request.body.importer.daterange;
const _import = {
watch: config.watch,
id: importId,
latest: '',
from: daterange.from,
to: daterange.to
}
importManager.add(_import);
this.body = _import;
}
+8
View File
@@ -0,0 +1,8 @@
const p = require('../../package.json');
// Retrieves API information
module.exports = function *() {
this.body = {
version: p.version
}
}
+7
View File
@@ -0,0 +1,7 @@
const cache = require('../state/cache');
module.exports = function(name) {
return function *() {
this.body = cache.get(name).list();
}
}
+19
View File
@@ -0,0 +1,19 @@
const _ = require('lodash');
const promisify = require('promisify-node');
const scan = promisify(require('../../core/workers/datasetScan/parent'));
// starts a scan
// requires a post body with configuration of:
//
// - config.watch
const route = function *() {
var config = require('./baseConfig');
_.merge(config, this.request.body);
this.body = yield scan(config);
};
module.exports = route;
+19
View File
@@ -0,0 +1,19 @@
const _ = require('lodash');
const promisify = require('promisify-node');
const scan = promisify(require('../../core/workers/dateRangeScan/parent'));
// starts a scan
// requires a post body with configuration of:
//
// - config.watch
const route = function *() {
var config = require('./baseConfig');
_.merge(config, this.request.body);
this.body = yield scan(config);
};
module.exports = route;
+38
View File
@@ -0,0 +1,38 @@
const _ = require('lodash');
const cache = require('../state/cache');
const Logger = require('../state/logger');
const apiKeyManager= cache.get('apiKeyManager');
const gekkoManager = cache.get('gekkos');
const base = require('./baseConfig');
// starts an import
// requires a post body with a config object
module.exports = function *() {
const mode = this.request.body.mode;
let config = {};
_.merge(config, base, this.request.body);
// Attach API keys
if(config.trader && config.trader.enabled && !config.trader.key) {
const keys = apiKeyManager._getApiKeyPair(config.watch.exchange);
if(!keys) {
this.body = 'No API keys found for this exchange.';
return;
}
_.merge(
config.trader,
keys
);
}
const state = gekkoManager.add({config, mode});
this.body = state;
}
+23
View File
@@ -0,0 +1,23 @@
const cache = require('../state/cache');
const gekkoManager = cache.get('gekkos');
// stops a Gekko
// requires a post body with an id
module.exports = function *() {
let id = this.request.body.id;
if(!id) {
this.body = { status: 'not ok' }
return;
}
let stopped = gekkoManager.stop(id);
if(!stopped) {
this.body = { status: 'not ok' }
return;
}
this.body = { status: 'ok' };
}
+27
View File
@@ -0,0 +1,27 @@
const _ = require('lodash');
const fs = require('co-fs');
const gekkoRoot = __dirname + '/../../';
module.exports = function *() {
const strategyDir = yield fs.readdir(gekkoRoot + 'strategies');
const strats = strategyDir
.filter(f => _.last(f, 3).join('') === '.js')
.map(f => {
return { name: f.slice(0, -3) }
});
// for every strat, check if there is a config file and add it
const stratConfigPath = gekkoRoot + 'config/strategies';
const strategyParamsDir = yield fs.readdir(stratConfigPath);
for(let i = 0; i < strats.length; i++) {
let strat = strats[i];
if(strategyParamsDir.indexOf(strat.name + '.toml') !== -1)
strat.params = yield fs.readFile(stratConfigPath + '/' + strat.name + '.toml', 'utf8')
else
strat.params = '';
}
this.body = strats;
}
+139
View File
@@ -0,0 +1,139 @@
const config = require('./vue/dist/UIconfig');
const koa = require('koa');
const serve = require('koa-static');
const cors = require('koa-cors');
const _ = require('lodash');
const bodyParser = require('koa-bodyparser');
const opn = require('opn');
const server = require('http').createServer();
const router = require('koa-router')();
const ws = require('ws');
const app = koa();
const WebSocketServer = require('ws').Server;
const wss = new WebSocketServer({ server: server });
const cache = require('./state/cache');
const nodeCommand = _.last(process.argv[1].split('/'));
const isDevServer = nodeCommand === 'server' || nodeCommand === 'server.js';
wss.on('connection', ws => {
ws.isAlive = true;
ws.on('pong', () => {
ws.isAlive = true;
});
ws.ping(_.noop);
ws.on('error', e => {
console.error(new Date, '[WS] connection error:', e);
});
});
setInterval(() => {
wss.clients.forEach(ws => {
if(!ws.isAlive) {
console.log(new Date, '[WS] stale websocket client, terminiating..');
return ws.terminate();
}
ws.isAlive = false;
ws.ping(_.noop);
});
}, 10 * 1000);
// broadcast function
const broadcast = data => {
if(_.isEmpty(data)) {
return;
}
const payload = JSON.stringify(data);
wss.clients.forEach(ws => {
ws.send(payload, err => {
if(err) {
console.log(new Date, '[WS] unable to send data to client:', err);
}
});
}
);
}
cache.set('broadcast', broadcast);
const ListManager = require('./state/listManager');
const GekkoManager = require('./state/gekkoManager');
// initialize lists and dump into cache
cache.set('imports', new ListManager);
cache.set('gekkos', new GekkoManager);
cache.set('apiKeyManager', require('./apiKeyManager'));
// setup API routes
const WEBROOT = __dirname + '/';
const ROUTE = n => WEBROOT + 'routes/' + n;
// attach routes
const apiKeys = require(ROUTE('apiKeys'));
router.get('/api/info', require(ROUTE('info')));
router.get('/api/strategies', require(ROUTE('strategies')));
router.get('/api/configPart/:part', require(ROUTE('configPart')));
router.get('/api/apiKeys', apiKeys.get);
const listWraper = require(ROUTE('list'));
router.get('/api/imports', listWraper('imports'));
router.get('/api/gekkos', listWraper('gekkos'));
router.get('/api/exchanges', require(ROUTE('exchanges')));
router.post('/api/addApiKey', apiKeys.add);
router.post('/api/removeApiKey', apiKeys.remove);
router.post('/api/scan', require(ROUTE('scanDateRange')));
router.post('/api/scansets', require(ROUTE('scanDatasets')));
router.post('/api/backtest', require(ROUTE('backtest')));
router.post('/api/import', require(ROUTE('import')));
router.post('/api/startGekko', require(ROUTE('startGekko')));
router.post('/api/stopGekko', require(ROUTE('stopGekko')));
router.post('/api/deleteGekko', require(ROUTE('deleteGekko')));
router.post('/api/getCandles', require(ROUTE('getCandles')));
// incoming WS:
// wss.on('connection', ws => {
// ws.on('message', _.noop);
// });
app
.use(cors())
.use(serve(WEBROOT + 'vue/dist'))
.use(bodyParser())
.use(require('koa-logger')())
.use(router.routes())
.use(router.allowedMethods());
server.timeout = config.api.timeout || 120000;
server.on('request', app.callback());
server.listen(config.api.port, config.api.host, '::', () => {
const host = `${config.ui.host}:${config.ui.port}${config.ui.path}`;
if(config.ui.ssl) {
var location = `https://${host}`;
} else {
var location = `http://${host}`;
}
console.log('Serving Gekko UI on ' + location + '\n');
// only open a browser when running `node gekko`
// this prevents opening the browser during development
if(!isDevServer && !config.headless) {
opn(location)
.catch(err => {
console.log('Something went wrong when trying to open your web browser. UI is running on ' + location + '.');
});
}
});
+14
View File
@@ -0,0 +1,14 @@
const _ = require('lodash');
const cache = {};
module.exports = {
set: (name, val) => {
cache[name] = val;
return true;
},
get: name => {
if(_.has(cache, name))
return cache[name];
}
}
+254
View File
@@ -0,0 +1,254 @@
const _ = require('lodash');
const moment = require('moment');
const broadcast = require('./cache').get('broadcast');
const Logger = require('./logger');
const pipelineRunner = require('../../core/workers/pipeline/parent');
const reduceState = require('./reduceState.js');
const now = () => moment().format('YYYY-MM-DD HH:mm');
const GekkoManager = function() {
this.gekkos = {};
this.instances = {};
this.loggers = {};
this.archivedGekkos = {};
}
GekkoManager.prototype.add = function({mode, config}) {
// set type
let type;
if(mode === 'realtime') {
if(config.market && config.market.type)
type = config.market.type;
else
type = 'watcher';
} else {
type = '';
}
let logType = type;
if(logType === 'leech') {
if(config.trader && config.trader.enabled)
logType = 'tradebot';
else
logType = 'papertrader';
}
const date = now().replace(' ', '-').replace(':', '-');
const n = (Math.random() + '').slice(3);
const id = `${date}-${logType}-${n}`;
// make sure we catch events happening inside te gekko instance
config.childToParent.enabled = true;
const state = {
mode,
config,
id,
type,
logType,
active: true,
stopped: false,
errored: false,
errorMessage: false,
events: {
initial: {},
latest: {}
},
start: moment()
}
this.gekkos[id] = state;
this.loggers[id] = new Logger(id);
// start the actual instance
this.instances[id] = pipelineRunner(mode, config, this.handleRawEvent(id));
// after passing API credentials to the actual instance we mask them
if(logType === 'trader') {
config.trader.key = '[REDACTED]';
config.trader.secret = '[REDACTED]';
}
console.log(`${now()} Gekko ${id} started.`);
broadcast({
type: 'gekko_new',
id,
state
});
return state;
}
GekkoManager.prototype.handleRawEvent = function(id) {
const logger = this.loggers[id];
return (err, event) => {
if(err) {
return this.handleFatalError(id, err);
}
if(!event) {
return;
}
if(event.log) {
return logger.write(event.message);
}
if(event.type) {
this.handleGekkoEvent(id, event);
}
}
}
GekkoManager.prototype.handleGekkoEvent = function(id, event) {
this.gekkos[id] = reduceState(this.gekkos[id], event);
broadcast({
type: 'gekko_event',
id,
event
});
}
GekkoManager.prototype.handleFatalError = function(id, err) {
const state = this.gekkos[id];
if(!state || state.errored || state.stopped)
return;
state.errored = true;
state.errorMessage = err;
console.error('RECEIVED ERROR IN GEKKO INSTANCE', id);
console.error(err);
broadcast({
type: 'gekko_error',
id,
error: err
});
this.archive(id);
if(state.logType === 'watcher') {
this.handleWatcherError(state, id);
}
}
// There might be leechers depending on this watcher, if so
// figure out it we can safely start a new watcher without
// the leechers noticing.
GekkoManager.prototype.handleWatcherError = function(state, id) {
console.log(`${now()} A gekko watcher crashed.`);
if(!state.events.latest.candle) {
console.log(`${now()} was unable to start.`);
}
let latestCandleTime = moment.unix(0);
if(state.events.latest && state.events.latest.candle) {
latestCandleTime = state.events.latest.candle.start;
}
const leechers = _.values(this.gekkos)
.filter(gekko => {
if(gekko.type !== 'leech') {
return false;
}
if(_.isEqual(gekko.config.watch, state.config.watch)) {
return true;
}
});
if(leechers.length) {
console.log(`${now()} ${leechers.length} leecher(s) were depending on this watcher.`);
if(moment().diff(latestCandleTime, 'm') < 60) {
console.log(`${now()} Watcher had recent data, starting a new one in a minute.`);
// after a minute try to start a new one again..
setTimeout(() => {
const mode = 'realtime';
const config = state.config;
this.add({mode, config});
}, 1000 * 60);
} else {
console.log(`${now()} Watcher did not have recent data, killing its leechers.`);
leechers.forEach(leecher => this.stop(leecher.id));
}
}
}
GekkoManager.prototype.stop = function(id) {
if(!this.gekkos[id])
return false;
console.log(`${now()} stopping Gekko ${id}`);
this.gekkos[id].stopped = true;
this.gekkos[id].active = false;
// todo: graceful shutdown (via gekkoStream's
// finish function).
this.instances[id].kill();
broadcast({
type: 'gekko_stopped',
id
});
this.archive(id);
return true;
}
GekkoManager.prototype.archive = function(id) {
this.archivedGekkos[id] = this.gekkos[id];
this.archivedGekkos[id].stopped = true;
this.archivedGekkos[id].active = false;
delete this.gekkos[id];
broadcast({
type: 'gekko_archived',
id
});
}
GekkoManager.prototype.delete = function(id) {
if(this.gekkos[id]) {
throw new Error('Cannot delete a running Gekko, stop it first.');
}
if(!this.archivedGekkos[id]) {
throw new Error('Cannot delete unknown Gekko.');
}
console.log(`${now()} deleting Gekko ${id}`);
broadcast({
type: 'gekko_deleted',
id
});
delete this.archivedGekkos[id];
return true;
}
GekkoManager.prototype.archive = function(id) {
this.archivedGekkos[id] = this.gekkos[id];
this.archivedGekkos[id].stopped = true;
this.archivedGekkos[id].active = false;
delete this.gekkos[id];
broadcast({
type: 'gekko_archived',
id
});
}
GekkoManager.prototype.list = function() {
return { live: this.gekkos, archive: this.archivedGekkos };
}
module.exports = GekkoManager;
+59
View File
@@ -0,0 +1,59 @@
// manages a list of things that change over time
// used for:
// - The currently running imports
// - etc..
const _ = require('lodash');
var ListManager = function() {
this._list = [];
}
// add an item to the list
ListManager.prototype.add = function(obj) {
if(!obj.id)
return false;
this._list.push(_.clone(obj));
return true;
}
// update some properties on an item
ListManager.prototype.update = function(id, updates) {
let item = this._list.find(i => i.id === id);
if(!item)
return false;
_.merge(item, updates);
return true;
}
// get an item from the list
ListManager.prototype.get = function(id) {
return this._list.find(i => i.id === id);
}
// push a value to a array property of an item
ListManager.prototype.push = function(id, prop, value) {
let item = this._list.find(i => i.id === id);
if(!item)
return false;
item[prop].push(value);
return true;
}
// delete an item from the list
ListManager.prototype.delete = function(id) {
let wasThere = this._list.find(i => i.id === id);
this._list = this._list.filter(i => i.id !== id);
if(wasThere)
return true;
else
return false;
}
// getter
ListManager.prototype.list = function() {
return this._list;
}
module.exports = ListManager;
+38
View File
@@ -0,0 +1,38 @@
const fs = require('fs');
const _ = require('lodash');
const BASEPATH = __dirname + '/../../logs/';
const Logger = function(id) {
this.fileName = `${id}.log`;
this.writing = false;
this.queue = [];
_.bindAll(this);
}
Logger.prototype.write = function(line) {
if(!this.writing) {
this.writing = true;
fs.appendFile(
BASEPATH + this.fileName,
line + '\n',
this.handleWriteCallback
);
} else
this.queue.push(line);
}
Logger.prototype.handleWriteCallback = function(err) {
if(err)
console.error(`ERROR WRITING LOG FILE ${this.fileName}:`, err);
this.writing = false;
if(_.size(this.queue))
this.write(this.queue.shift())
}
module.exports = Logger;
+67
View File
@@ -0,0 +1,67 @@
// Redux/vuex inspired reducer, reduces an event into a gekko state.
// NOTE: this is used by the backend as well as the frontend.
const skipInitialEvents = ['marketUpdate'];
const skipLatestEvents = ['marketStart', 'stratWarmupCompleted'];
const trackAllEvents = ['tradeCompleted', 'advice', 'roundtrip'];
const reduce = (state, event) => {
const type = event.type;
const payload = event.payload;
state = {
...state,
latestUpdate: new Date()
}
if(trackAllEvents.includes(type)) {
if(!state.events[type]) {
state = {
...state,
events: {
...state.events,
[type]: [ payload ]
}
}
} else {
state = {
...state,
events: {
...state.events,
[type]: [ ...state.events[type], payload ]
}
}
}
}
if(!state.events.initial[type] && !skipInitialEvents.includes(type)) {
state = {
...state,
events: {
...state.events,
initial: {
...state.events.initial,
[type]: payload
}
}
}
}
if(!skipLatestEvents.includes(type)) {
state = {
...state,
events: {
...state.events,
latest: {
...state.events.latest,
[type]: payload
}
}
}
}
return state;
}
// export default reduce;
module.exports = reduce;
+9
View File
@@ -0,0 +1,9 @@
module.exports = {
presets: [
'@vue/app'
],
ignore: [
'node_modules',
],
plugins : ["transform-commonjs-es2015-modules"]
}
+26
View File
@@ -0,0 +1,26 @@
// Note: this file gets copied around, make sure you edit
// the UIconfig located at `gekko/web/vue/dist/UIconfig.js`.
// This config is used by both the frontend as well as the web server.
// see https://gekko.wizb.it/docs/installation/installing_gekko_on_a_server.html#Configuring-Gekko
const CONFIG = {
headless: false,
api: {
host: '127.0.0.1',
port: 3000,
timeout: 120000 // 2 minutes
},
ui: {
ssl: false,
host: 'localhost',
port: 3000,
path: '/'
},
adapter: 'sqlite'
}
if(typeof window === 'undefined')
module.exports = CONFIG;
else
window.CONFIG = CONFIG;
+2
View File
@@ -0,0 +1,2 @@
(function(t){function e(e){for(var n,s,o=e[0],c=e[1],u=e[2],d=0,f=[];d<o.length;d++)s=o[d],r[s]&&f.push(r[s][0]),r[s]=0;for(n in c)Object.prototype.hasOwnProperty.call(c,n)&&(t[n]=c[n]);l&&l(e);while(f.length)f.shift()();return i.push.apply(i,u||[]),a()}function a(){for(var t,e=0;e<i.length;e++){for(var a=i[e],n=!0,o=1;o<a.length;o++){var c=a[o];0!==r[c]&&(n=!1)}n&&(i.splice(e--,1),t=s(s.s=a[0]))}return t}var n={},r={1:0},i=[];function s(e){if(n[e])return n[e].exports;var a=n[e]={i:e,l:!1,exports:{}};return t[e].call(a.exports,a,a.exports,s),a.l=!0,a.exports}s.m=t,s.c=n,s.d=function(t,e,a){s.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:a})},s.r=function(t){"undefined"!==typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},s.t=function(t,e){if(1&e&&(t=s(t)),8&e)return t;if(4&e&&"object"===typeof t&&t&&t.__esModule)return t;var a=Object.create(null);if(s.r(a),Object.defineProperty(a,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)s.d(a,n,function(e){return t[e]}.bind(null,n));return a},s.n=function(t){var e=t&&t.__esModule?function(){return t["default"]}:function(){return t};return s.d(e,"a",e),e},s.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},s.p="";var o=window["webpackJsonp"]=window["webpackJsonp"]||[],c=o.push.bind(o);o.push=e,o=o.slice();for(var u=0;u<o.length;u++)e(o[u]);var l=c;i.push([26,0]),a()})({"/Dpa":function(t,e,a){"use strict";var n=a("VZpO"),r=a.n(n);r.a},"/vJE":function(t,e,a){"use strict";var n=a("yuKf"),r=a.n(n);r.a},"0Bu0":function(t,e,a){"use strict";var n=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"grd-row-col-3-6"},[a("table",{staticClass:"p1"},[a("tr",[a("th",[t._v("amount of trades")]),a("td",[t._v(t._s(t.report.trades))])]),a("tr",[a("th",[t._v("sharpe ratio")]),a("td",[t._v(t._s(t.round2(t.report.sharpe)))])]),a("tr",[a("th",[t._v("start balance")]),a("td",[t._v(t._s(t.round(t.report.startBalance))+" "+t._s(t.report.currency))])]),a("tr",[a("th",[t._v("final balance")]),a("td",[t._v(t._s(t.round(t.report.balance))+" "+t._s(t.report.currency))])]),t._m(0)]),a("div",{staticClass:"big txt--right price",class:t.profitClass},[t._v(t._s(t.round(t.report.relativeProfit))+"%")])])},r=[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("tr",[a("th",[t._v("simulated profit")])])}],i={props:["report"],methods:{round2:function(t){return(+t).toFixed(2)},round:function(t){return(+t).toFixed(5)}},computed:{profitClass:function(){return this.report.relativeProfit>0?"profit":"loss"}}},s=i,o=(a("tr8z"),a("KHd+")),c=Object(o["a"])(s,n,r,!1,null,null,null);e["a"]=c.exports},"0zrD":function(t,e,a){"use strict";var n=a("jf14"),r=a.n(n);r.a},26:function(t,e,a){t.exports=a("Vtdi")},"2A8w":function(t,e,a){"use strict";var n=a("TDb6"),r=a.n(n);r.a},"2Yda":function(t,e,a){"use strict";var n=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"contain my2"},[a("h3",[t._v("Start a new gekko")]),a("gekko-config-builder",{on:{config:t.updateConfig}}),a("div",{staticClass:"hr"}),t.config.valid?a("div",{staticClass:"txt--center"},[t.pendingStratrunner?t._e():a("a",{staticClass:"w100--s my1 btn--primary",attrs:{href:"#"},on:{click:function(e){return e.preventDefault(),t.start(e)}}},[t._v("Start")]),t.pendingStratrunner?a("spinner"):t._e()],1):t._e()],1)},r=[],i=(a("Z2Ku"),a("L9s1"),a("dRSK"),a("LvDl")),s=a.n(i),o=a("Kw5r"),c=a("wiDz"),u=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"grd contain"},[a("div",{staticClass:"grd-row"},[a("div",{staticClass:"grd-row-col-3-6 mx1"},[a("h3",[t._v("Market")]),a("market-picker",{attrs:{"only-tradable":t.isTradebot},on:{market:t.updateMarketConfig}})],1),a("div",{staticClass:"grd-row-col-3-6 mx1"},[a("type-picker",{on:{type:t.updateType}})],1)]),"market watcher"!==t.type?[a("div",{staticClass:"hr"}),a("strat-picker",{staticClass:"contain my2",on:{stratConfig:t.updateStrat}}),"paper trader"===t.type?a("div",{staticClass:"hr"}):t._e(),"paper trader"===t.type?a("paper-trader",{on:{settings:t.updatePaperTrader}}):t._e()]:t._e()],2)},l=[],d=(a("91GP"),a("6BxS")),f=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",[a("h3",[t._v("Type")]),[a("label",{staticClass:"wrapper",attrs:{for:"type"}},[t._v("What do you want to do with gekko?")]),a("form",{staticClass:"radio grd"},t._l(t.types,function(e,n){return a("div",{staticClass:"grd-row m1"},[a("input",{directives:[{name:"model",rawName:"v-model",value:t.selectedTypeIndex,expression:"selectedTypeIndex"}],staticClass:"grd-row-col-1-6",attrs:{type:"radio"},domProps:{value:n,checked:t._q(t.selectedTypeIndex,n)},on:{change:function(e){t.selectedTypeIndex=n}}}),a("label",{staticClass:"grd-row-col-5-6",attrs:{for:n}},[t._v(t._s(e))])])}))]],2)},h=[],m={created:function(){this.emitType()},data:function(){return{types:["paper trader","market watcher","Line truncated
//# sourceMappingURL=app.5e99ecf7.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/components/gekko/singleGekko.vue?6cec","webpack:///./src/components/global/progressBar.vue?7bcc","webpack:///./src/components/global/paperTradeSummary.vue?13b5","webpack:///src/components/global/paperTradeSummary.vue","webpack:///./src/components/global/paperTradeSummary.vue?a8ef","webpack:///./src/components/global/paperTradeSummary.vue","webpack:///./src/components/global/configbuilder/papertrader.vue?c5cd","webpack:///./src/components/gekko/new.vue?c104","webpack:///./src/components/gekko/new.vue?367c","webpack:///./src/components/gekko/gekkoConfigBuilder.vue?035a","webpack:///./src/components/global/configbuilder/typepicker.vue?df24","webpack:///src/components/global/configbuilder/typepicker.vue","webpack:///./src/components/global/configbuilder/typepicker.vue?cf28","webpack:///./src/components/global/configbuilder/typepicker.vue","webpack:///src/components/gekko/gekkoConfigBuilder.vue","webpack:///./src/components/gekko/gekkoConfigBuilder.vue?8d92","webpack:///./src/components/gekko/gekkoConfigBuilder.vue","webpack:///src/components/gekko/new.vue","webpack:///./src/components/gekko/new.vue?ae9a","webpack:///./src/components/gekko/new.vue","webpack:///./src/components/data/data.vue?4abe","webpack:///./src/tools/marked.js","webpack:///./src/components/global/configbuilder/marketpicker.vue?d701","webpack:///src/components/global/configbuilder/marketpicker.vue","webpack:///./src/components/global/configbuilder/marketpicker.vue?200d","webpack:///./src/components/global/configbuilder/marketpicker.vue","webpack:///./src/components/global/configbuilder/stratpicker.vue?fda9","webpack:///src/components/global/configbuilder/stratpicker.vue","webpack:///./src/components/global/configbuilder/stratpicker.vue?8a34","webpack:///./src/components/global/configbuilder/stratpicker.vue","webpack:///./src/components/global/configbuilder/rangepicker.vue?ce7c","webpack:///./src/components/global/configbuilder/rangecreator.vue?8425","webpack:///src/components/global/configbuilder/rangecreator.vue","webpack:///./src/components/global/configbuilder/rangecreator.vue?3f8d","webpack:///./src/components/global/configbuilder/rangecreator.vue","webpack:///./src/components/data/import/importConfigBuilder.vue?3911","webpack:///./src/components/global/blockSpinner.vue?cca6","webpack:///src/components/global/blockSpinner.vue","webpack:///./src/components/global/blockSpinner.vue?7b17","webpack:///./src/components/global/blockSpinner.vue","webpack:///./src/App.vue?77b6","webpack:///./src/components/layout/header.vue?345a","webpack:///src/components/layout/header.vue","webpack:///./src/components/layout/header.vue?8ecd","webpack:///./src/components/layout/header.vue","webpack:///./src/components/layout/footer.vue?0614","webpack:///src/components/layout/footer.vue","webpack:///./src/components/layout/footer.vue?6aff","webpack:///./src/components/layout/footer.vue","webpack:///./src/components/layout/modal.vue?5ed7","webpack:///src/components/layout/modal.vue","webpack:///./src/components/layout/modal.vue?6e33","webpack:///./src/components/layout/modal.vue","webpack:///src/App.vue","webpack:///./src/App.vue?8f16","webpack:///./src/App.vue","webpack:///./src/store/modules/imports/mutations.js","webpack:///../state/reduceState.js","webpack:///./src/store/modules/gekkos/mutations.js","webpack:///./src/store/modules/notifications/mutations.js","webpack:///./src/store/modules/config/mutations.js","webpack:///./src/store/index.js","webpack:///./src/components/backtester/backtestConfigBuilder.vue?fda9","webpack:///./src/components/backtester/result/chartWrapper.vue?d2a0","webpack:///./src/components/global/configbuilder/rangecreator.vue?c7ad","webpack:///./src/components/layout/modal.vue?a2b4","webpack:///./src/components/backtester/result/chartWrapper.vue?cfc8","webpack:///./src/d3/chart4.js","webpack:///./src/d3/message.js","webpack:///src/components/backtester/result/chartWrapper.vue","webpack:///./src/components/backtester/result/chartWrapper.vue?414d","webpack:///./src/components/backtester/result/chartWrapper.vue","webpack:///./src/main.js","webpack:///./src/components/backtester/result/summary.vue?6f4b","webpack:///./src/components/config/config.vue?9014","webpack:///./src/components/config/apiConfigBuilder.vue?901e","webpack:///./src/components/global/configbuilder/exchangepicker.vue?f5ea","webpack:///src/components/global/configbuilder/exchangepicker.vue","webpack:///./src/components/global/configbuilder/exchangepicker.vue?f140","webpack:///./src/components/global/configbuilder/exchangepicker.vue","webpack:///src/components/config/apiConfigBuilder.vue","webpack:///./src/components/config/apiConfigBuilder.vue?a340","webpack:///./src/components/config/apiConfigBuilder.vue","webpack:///src/components/config/config.vue","webpack:///./src/components/config/config.vue?03e8","webpack:///./src/components/config/config.vue","webpack:///./src/components/gekko/gekkoConfigBuilder.Line truncated
+1
View File
@@ -0,0 +1 @@
.menu{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;margin-top:0;margin-bottom:2rem}.menu a{-webkit-box-flex:1;-ms-flex:1 1 100%;flex:1 1 100%;display:block;text-align:center;text-decoration:none;color:inherit}.menu .router-link-active{background-color:hsla(0,0%,98%,.99)}.menu a:hover{text-decoration:underline}#modal-background{position:fixed;top:0;bottom:0;left:0;right:0;background-color:#000;opacity:.5}.modal{position:fixed;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);width:600px;min-height:300px;background-color:#fff}.modal-guts{position:absolute;top:0;left:0;width:100%;height:100%;padding:20px 50px 20px 20px;overflow:auto}#app{display:-webkit-box;display:-ms-flexbox;display:flex;min-height:100vh;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.fill{-webkit-box-flex:1;-ms-flex:1;flex:1}.text{max-width:500px}input{background:none;margin-top:.5em}.params{min-height:235px;line-height:1.3em}.hr{margin-top:2rem;margin-bottom:2rem;height:10px;background-color:hsla(0,0%,98%,.99)}.contain{width:900px;margin-left:auto;margin-right:auto}.btn--primary{display:inline-block;margin-right:12px;margin-bottom:12px;height:40px;padding:0 18px;border-radius:4px;text-shadow:0 1px 3px rgba(36,180,126,.4);-webkit-box-shadow:0 4px 6px rgba(50,50,93,.11),0 1px 3px rgba(0,0,0,.08);box-shadow:0 4px 6px rgba(50,50,93,.11),0 1px 3px rgba(0,0,0,.08);line-height:40px;-webkit-transition:-webkit-transform .25s;transition:-webkit-transform .25s;transition:transform .25s;transition:transform .25s,-webkit-transform .25s}.btn--primary,.btn--primary:hover{background-color:#3498db;color:#fff;text-decoration:none}.btn--primary:hover{-webkit-transform:translateY(-1px);transform:translateY(-1px);-webkit-box-shadow:0 7px 14px rgba(50,50,93,.1),0 3px 6px rgba(0,0,0,.08);box-shadow:0 7px 14px rgba(50,50,93,.1),0 3px 6px rgba(0,0,0,.08)}.btn--primary:active,.btn--primary:focus{background-color:#3498db;color:#fff;text-decoration:none}.btn--primary:active{-webkit-transform:translateY(1px);transform:translateY(1px)}.spinner{margin:20px auto 100px;width:50px;height:40px;text-align:center;font-size:10px}.spinner>div{background-color:#333;height:100%;width:6px;display:inline-block;margin-right:4px;-webkit-animation:sk-stretchdelay 1.2s infinite ease-in-out;animation:sk-stretchdelay 1.2s infinite ease-in-out}.spinner .rect2{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.spinner .rect3{-webkit-animation-delay:-1s;animation-delay:-1s}.spinner .rect4{-webkit-animation-delay:-.9s;animation-delay:-.9s}.spinner .rect5{-webkit-animation-delay:-.8s;animation-delay:-.8s}@-webkit-keyframes sk-stretchdelay{0%,40%,to{-webkit-transform:scaleY(.4)}20%{-webkit-transform:scaleY(1)}}@keyframes sk-stretchdelay{0%,40%,to{transform:scaleY(.4);-webkit-transform:scaleY(.4)}20%{transform:scaleY(1);-webkit-transform:scaleY(1)}}td.radio{width:45px}td label{display:inline;font-size:1em}.align .custom-select select{padding:.4em 1.2em .3em .8em}.label-like{display:block;font-size:.9em;color:#777}.align{padding-left:1em}.big{font-size:1.3em}.big,.summary table{width:80%}.price.profit{color:#7fff00}.price.loss{color:red}.summary td{text-align:right}#chartWrapper.clickable{position:relative}#chartWrapper.clickable .shield{cursor:-webkit-zoom-in;cursor:zoom-in;position:absolute;top:0;bottom:0;left:0;right:0;background:grey;opacity:.1}#chart{background-color:#eee;width:100%}#chart circle{-webkit-clip-path:url(#clip);clip-path:url(#clip)}#chart .zoom{cursor:move;fill:none;pointer-events:all}#chart .line{fill:none;stroke:#4682b4;stroke-width:1.5px;-webkit-clip-path:url(#clip);clip-path:url(#clip)}#chart circle.buy{fill:#7fff00}#chart circle.sell{fill:red}.roundtrips{margin-top:50px;margin-bottom:50px}.roundtrips table{width:100%}.roundtrips table td,.roundtrips table th{border:1px solid #c6cbd1;padding:8px 12px}.roundtrips table td.loss{color:red;text-align:right}.roundtrips table td.profit{color:green;text-align:right}.roundtrips table tr:nth-child(2n){background-color:#f6f8fa}.clickable{cursor:pointer}table.full{width:100%}table.full td{padding:.5rem 0}table.full.data th{text-align:left;padding:.5rem 0}.warning p{margin:0;padding:0}.scan-btn{margin-top:80px;margin-bottom:30px}.progressbarWrapper p{text-align:center;font-size:20px}.progressbar{background-color:hsla(0,0%,85%,.99);border-radius:13px;padding:0}@-webkit-keyframes shimmer{0%{background-position:0 0}to{background-position:960px 0}}@keyframes shimmer{0%{background-position:0 0}to{background-position:960px 0}}.progressbar>div{height:20px;border-radius:10px;background-color:orange;-webkit-animation-duration:1.5s;animation-duration:1.5s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;-webkit-animation-name:shimmer;animation-nameLine truncated
+26
View File
@@ -0,0 +1,26 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([[0],{"+rLv":function(t,e,n){var r=n("dyZX").document;t.exports=r&&r.documentElement},"/yFf":function(t,e,n){"use strict";var r=n("oHnp");function i(t){if(t)return o(t)}function o(t){for(var e in i.prototype)t[e]=i.prototype[e];return t}t.exports=i,i.prototype.get=function(t){return this.header[t.toLowerCase()]},i.prototype._setHeaderProperties=function(t){var e=t["content-type"]||"";this.type=r.type(e);var n=r.params(e);for(var i in n)this[i]=n[i];this.links={};try{t.link&&(this.links=r.parseLinks(t.link))}catch(t){}},i.prototype._setStatusProperties=function(t){var e=t/100|0;this.status=this.statusCode=t,this.statusType=e,this.info=1==e,this.ok=2==e,this.redirect=3==e,this.clientError=4==e,this.serverError=5==e,this.error=(4==e||5==e)&&this.toError(),this.created=201==t,this.accepted=202==t,this.noContent=204==t,this.badRequest=400==t,this.unauthorized=401==t,this.notAcceptable=406==t,this.forbidden=403==t,this.notFound=404==t,this.unprocessableEntity=422==t}},"0/R4":function(t,e){t.exports=function(t){return"object"===typeof t?null!==t:"function"===typeof t}},"0sh+":function(t,e,n){var r=n("quPj"),i=n("vhPU");t.exports=function(t,e,n){if(r(e))throw TypeError("String#"+n+" doesn't accept regex!");return String(i(t))}},"1TsA":function(t,e){t.exports=function(t,e){return{value:e,done:!!t}}},"24Ii":function(t,e,n){var r;"undefined"!==typeof window?r=window:"undefined"!==typeof self?r=self:(console.warn("Using browser-only version of superagent in non-browser environment"),r=this);var i=n("cpc2"),o=n("kMlx"),a=n("8zgK"),u=n("/yFf"),s=n("nZbv");function c(){}var l=e=t.exports=function(t,n){return"function"==typeof n?new e.Request("GET",t).end(n):1==arguments.length?new e.Request("GET",t):new e.Request(t,n)};e.Request=_,l.getXHR=function(){if(!(!r.XMLHttpRequest||r.location&&"file:"==r.location.protocol&&r.ActiveXObject))return new XMLHttpRequest;try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(t){}try{return new ActiveXObject("Msxml2.XMLHTTP.6.0")}catch(t){}try{return new ActiveXObject("Msxml2.XMLHTTP.3.0")}catch(t){}try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(t){}throw Error("Browser-only version of superagent could not find XHR")};var f="".trim?function(t){return t.trim()}:function(t){return t.replace(/(^\s*|\s*$)/g,"")};function p(t){if(!a(t))return t;var e=[];for(var n in t)h(e,n,t[n]);return e.join("&")}function h(t,e,n){if(null!=n)if(Array.isArray(n))n.forEach(function(n){h(t,e,n)});else if(a(n))for(var r in n)h(t,e+"["+r+"]",n[r]);else t.push(encodeURIComponent(e)+"="+encodeURIComponent(n));else null===n&&t.push(encodeURIComponent(e))}function d(t){for(var e,n,r={},i=t.split("&"),o=0,a=i.length;o<a;++o)e=i[o],n=e.indexOf("="),-1==n?r[decodeURIComponent(e)]="":r[decodeURIComponent(e.slice(0,n))]=decodeURIComponent(e.slice(n+1));return r}function v(t){for(var e,n,r,i,o=t.split(/\r?\n/),a={},u=0,s=o.length;u<s;++u)n=o[u],e=n.indexOf(":"),-1!==e&&(r=n.slice(0,e).toLowerCase(),i=f(n.slice(e+1)),a[r]=i);return a}function y(t){return/[\/+]json($|[^-\w])/.test(t)}function g(t){this.req=t,this.xhr=this.req.xhr,this.text="HEAD"!=this.req.method&&(""===this.xhr.responseType||"text"===this.xhr.responseType)||"undefined"===typeof this.xhr.responseType?this.xhr.responseText:null,this.statusText=this.req.xhr.statusText;var e=this.xhr.status;1223===e&&(e=204),this._setStatusProperties(e),this.header=this.headers=v(this.xhr.getAllResponseHeaders()),this.header["content-type"]=this.xhr.getResponseHeader("content-type"),this._setHeaderProperties(this.header),null===this.text&&t._responseType?this.body=this.xhr.response:this.body="HEAD"!=this.req.method?this._parseBody(this.text?this.text:this.xhr.response):null}function _(t,e){var n=this;this._query=this._query||[],this.method=t,this.url=e,this.header={},this._header={},this.on("end",function(){var t,e=null,r=null;try{r=new g(n)}catch(t){return e=new Error("Parser is unable to parse the response"),e.parse=!0,e.original=t,n.xhr?(e.rawResponse="undefined"==typeof n.xhr.responseType?n.xhr.responseText:n.xhr.response,e.status=n.xhr.status?n.xhr.status:null,e.statusCode=e.status):(e.rawResponse=null,e.status=null),n.callback(e)}n.emit("response",r);try{n._isResponseOK(r)||(t=new Error(r.statusText||"Unsuccessful HTTP response"))}catch(e){t=e}t?(t.original=e,t.response=r,t.status=r.status,n.callback(t,r)):n.callback(null,r)})}function m(t,e,n){var r=l("DELETE",t);return"function"==typeof e&&(n=e,e=null),e&&r.send(e),n&&r.end(n),r}l.serializeObject=p,l.parseString=d,l.types={html:"text/html",json:"application/json",xml:"text/xml",urlencoded:"application/x-www-form-urlencoded",form:"application/x-www-form-urlencoded","form-data":"application/x-www-form-urlencoded"},l.serialize={"application/x-www-form-urlencoded":p,"application/json":JSON.stringify},l.parse={"application/x-www-form-urlencoded":d,"application/json":JSON.parse},u(g.prototype),g.prototype._parseBody=function(t){var e=l.parse[this.type];return Line truncated
/*!
* Vue.js v2.5.16
* (c) 2014-2018 Evan You
* Released under the MIT License.
*/
var n=Object.freeze({});function r(t){return void 0===t||null===t}function i(t){return void 0!==t&&null!==t}function o(t){return!0===t}function a(t){return!1===t}function u(t){return"string"===typeof t||"number"===typeof t||"symbol"===typeof t||"boolean"===typeof t}function s(t){return null!==t&&"object"===typeof t}var c=Object.prototype.toString;function l(t){return"[object Object]"===c.call(t)}function f(t){return"[object RegExp]"===c.call(t)}function p(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e&&isFinite(t)}function h(t){return null==t?"":"object"===typeof t?JSON.stringify(t,null,2):String(t)}function d(t){var e=parseFloat(t);return isNaN(e)?t:e}function v(t,e){for(var n=Object.create(null),r=t.split(","),i=0;i<r.length;i++)n[r[i]]=!0;return e?function(t){return n[t.toLowerCase()]}:function(t){return n[t]}}v("slot,component",!0);var y=v("key,ref,slot,slot-scope,is");function g(t,e){if(t.length){var n=t.indexOf(e);if(n>-1)return t.splice(n,1)}}var _=Object.prototype.hasOwnProperty;function m(t,e){return _.call(t,e)}function b(t){var e=Object.create(null);return function(n){var r=e[n];return r||(e[n]=t(n))}}var w=/-(\w)/g,x=b(function(t){return t.replace(w,function(t,e){return e?e.toUpperCase():""})}),k=b(function(t){return t.charAt(0).toUpperCase()+t.slice(1)}),A=/\B([A-Z])/g,O=b(function(t){return t.replace(A,"-$1").toLowerCase()});function C(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n}function E(t,e){return t.bind(e)}var j=Function.prototype.bind?E:C;function S(t,e){e=e||0;var n=t.length-e,r=new Array(n);while(n--)r[n]=t[n+e];return r}function $(t,e){for(var n in e)t[n]=e[n];return t}function T(t){for(var e={},n=0;n<t.length;n++)t[n]&&$(e,t[n]);return e}function R(t,e,n){}var L=function(t,e,n){return!1},I=function(t){return t};function P(t,e){if(t===e)return!0;var n=s(t),r=s(e);if(!n||!r)return!n&&!r&&String(t)===String(e);try{var i=Array.isArray(t),o=Array.isArray(e);if(i&&o)return t.length===e.length&&t.every(function(t,n){return P(t,e[n])});if(i||o)return!1;var a=Object.keys(t),u=Object.keys(e);return a.length===u.length&&a.every(function(n){return P(t[n],e[n])})}catch(t){return!1}}function M(t,e){for(var n=0;n<t.length;n++)if(P(t[n],e))return n;return-1}function D(t){var e=!1;return function(){e||(e=!0,t.apply(this,arguments))}}var U="data-server-rendered",z=["component","directive","filter"],q=["beforeCreate","created","beforeMount","mounted","beforeUpdate","updated","beforeDestroy","destroyed","activated","deactivated","errorCaptured"],N={optionMergeStrategies:Object.create(null),silent:!1,productionTip:!1,devtools:!1,performance:!1,errorHandler:null,warnHandler:null,ignoredElements:[],keyCodes:Object.create(null),isReservedTag:L,isReservedAttr:L,isUnknownElement:L,getTagNamespace:R,parsePlatformTagName:I,mustUseProp:L,_lifecycleHooks:q};function F(t){var e=(t+"").charCodeAt(0);return 36===e||95===e}function H(t,e,n,r){Object.defineProperty(t,e,{value:n,enumerable:!!r,writable:!0,configurable:!0})}var W=/[^\w.$]/;function B(t){if(!W.test(t)){var e=t.split(".");return function(t){for(var n=0;n<e.length;n++){if(!t)return;t=t[e[n]]}return t}}}var K,V="__proto__"in{},Z="undefined"!==typeof window,X="undefined"!==typeof WXEnvironment&&!!WXEnvironment.platform,G=X&&WXEnvironment.platform.toLowerCase(),J=Z&&window.navigator.userAgent.toLowerCase(),Y=J&&/msie|trident/.test(J),Q=J&&J.indexOf("msie 9.0")>0,tt=J&&J.indexOf("edge/")>0,et=(J&&J.indexOf("android"),J&&/iphone|ipad|ipod|ios/.test(J)||"ios"===G),nt=(J&&/chrome\/\d+/.test(J),{}.watch),rt=!1;if(Z)try{var it={};Object.defineProperty(it,"passive",{get:function(){rt=!0}}),window.addEventListener("test-passive",null,it)}catch(t){}var ot=function(){return void 0===K&&(K=!Z&&!X&&"undefined"!==typeof t&&"server"===t["process"].env.VUE_ENV),K},at=Z&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function ut(t){return"function"===typeof t&&/native code/.test(t.toString())}var st,ct="undefined"!==typeof Symbol&&ut(Symbol)&&"undefined"!==typeof Reflect&&ut(Reflect.ownKeys);st="undefined"!==typeof Set&&ut(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var lt=R,ft=0,pt=function(){this.id=ft++,this.subs=[]};pt.prototype.addSub=function(t){this.subs.push(t)},pt.prototype.removeSub=function(t){g(this.subs,t)},pt.prototype.depend=function(){pt.target&&pt.target.addDep(this)},pt.prototype.notify=function(){for(var t=this.subs.slice(),e=0,n=t.length;e<n;e++)t[e].update()},pt.target=null;var ht=[];function dt(t){pt.target&&ht.push(pt.target),pt.target=t}function vt(){pt.target=ht.pop()}var yt=function(t,e,n,r,i,o,a,u){this.tag=t,this.data=e,this.children=n,this.text=r,this.elm=i,this.ns=void 0,this.context=o,this.fnContext=void 0,this.fnOptions=void 0,this.fnScopeId=void 0,this.key=e&&e.key,this.compoLine truncated
/**
* vuex v3.0.1
* (c) 2017 Evan You
* @license MIT
*/var r=function(t){var e=Number(t.version.split(".")[0]);if(e>=2)t.mixin({beforeCreate:r});else{var n=t.prototype._init;t.prototype._init=function(t){void 0===t&&(t={}),t.init=t.init?[r].concat(t.init):r,n.call(this,t)}}function r(){var t=this.$options;t.store?this.$store="function"===typeof t.store?t.store():t.store:t.parent&&t.parent.$store&&(this.$store=t.parent.$store)}},i="undefined"!==typeof window&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function o(t){i&&(t._devtoolHook=i,i.emit("vuex:init",t),i.on("vuex:travel-to-state",function(e){t.replaceState(e)}),t.subscribe(function(t,e){i.emit("vuex:mutation",t,e)}))}function a(t,e){Object.keys(t).forEach(function(n){return e(t[n],n)})}function u(t){return null!==t&&"object"===typeof t}function s(t){return t&&"function"===typeof t.then}var c=function(t,e){this.runtime=e,this._children=Object.create(null),this._rawModule=t;var n=t.state;this.state=("function"===typeof n?n():n)||{}},l={namespaced:{configurable:!0}};l.namespaced.get=function(){return!!this._rawModule.namespaced},c.prototype.addChild=function(t,e){this._children[t]=e},c.prototype.removeChild=function(t){delete this._children[t]},c.prototype.getChild=function(t){return this._children[t]},c.prototype.update=function(t){this._rawModule.namespaced=t.namespaced,t.actions&&(this._rawModule.actions=t.actions),t.mutations&&(this._rawModule.mutations=t.mutations),t.getters&&(this._rawModule.getters=t.getters)},c.prototype.forEachChild=function(t){a(this._children,t)},c.prototype.forEachGetter=function(t){this._rawModule.getters&&a(this._rawModule.getters,t)},c.prototype.forEachAction=function(t){this._rawModule.actions&&a(this._rawModule.actions,t)},c.prototype.forEachMutation=function(t){this._rawModule.mutations&&a(this._rawModule.mutations,t)},Object.defineProperties(c.prototype,l);var f=function(t){this.register([],t,!1)};function p(t,e,n){if(e.update(n),n.modules)for(var r in n.modules){if(!e.getChild(r))return void 0;p(t.concat(r),e.getChild(r),n.modules[r])}}f.prototype.get=function(t){return t.reduce(function(t,e){return t.getChild(e)},this.root)},f.prototype.getNamespace=function(t){var e=this.root;return t.reduce(function(t,n){return e=e.getChild(n),t+(e.namespaced?n+"/":"")},"")},f.prototype.update=function(t){p([],this.root,t)},f.prototype.register=function(t,e,n){var r=this;void 0===n&&(n=!0);var i=new c(e,n);if(0===t.length)this.root=i;else{var o=this.get(t.slice(0,-1));o.addChild(t[t.length-1],i)}e.modules&&a(e.modules,function(e,i){r.register(t.concat(i),e,n)})},f.prototype.unregister=function(t){var e=this.get(t.slice(0,-1)),n=t[t.length-1];e.getChild(n).runtime&&e.removeChild(n)};var h;var d=function(t){var e=this;void 0===t&&(t={}),!h&&"undefined"!==typeof window&&window.Vue&&j(window.Vue);var n=t.plugins;void 0===n&&(n=[]);var r=t.strict;void 0===r&&(r=!1);var i=t.state;void 0===i&&(i={}),"function"===typeof i&&(i=i()||{}),this._committing=!1,this._actions=Object.create(null),this._actionSubscribers=[],this._mutations=Object.create(null),this._wrappedGetters=Object.create(null),this._modules=new f(t),this._modulesNamespaceMap=Object.create(null),this._subscribers=[],this._watcherVM=new h;var a=this,u=this,s=u.dispatch,c=u.commit;this.dispatch=function(t,e){return s.call(a,t,e)},this.commit=function(t,e,n){return c.call(a,t,e,n)},this.strict=r,m(this,i,[],this._modules.root),_(this,i),n.forEach(function(t){return t(e)}),h.config.devtools&&o(this)},v={state:{configurable:!0}};function y(t,e){return e.indexOf(t)<0&&e.push(t),function(){var n=e.indexOf(t);n>-1&&e.splice(n,1)}}function g(t,e){t._actions=Object.create(null),t._mutations=Object.create(null),t._wrappedGetters=Object.create(null),t._modulesNamespaceMap=Object.create(null);var n=t.state;m(t,n,[],t._modules.root,!0),_(t,n,e)}function _(t,e,n){var r=t._vm;t.getters={};var i=t._wrappedGetters,o={};a(i,function(e,n){o[n]=function(){return e(t)},Object.defineProperty(t.getters,n,{get:function(){return t._vm[n]},enumerable:!0})});var u=h.config.silent;h.config.silent=!0,t._vm=new h({data:{$$state:e},computed:o}),h.config.silent=u,t.strict&&O(t),r&&(n&&t._withCommit(function(){r._data.$$state=null}),h.nextTick(function(){return r.$destroy()}))}function m(t,e,n,r,i){var o=!n.length,a=t._modules.getNamespace(n);if(r.namespaced&&(t._modulesNamespaceMap[a]=r),!o&&!i){var u=C(e,n.slice(0,-1)),s=n[n.length-1];t._withCommit(function(){h.set(u,s,r.state)})}var c=r.context=b(t,a,n);r.forEachMutation(function(e,n){var r=a+n;x(t,r,e,c)}),r.forEachAction(function(e,n){var r=e.root?n:a+n,i=e.handler||e;k(t,r,i,c)}),r.forEachGetter(function(e,n){var r=a+n;A(t,r,e,c)}),r.forEachChild(function(r,o){m(t,e,n.concat(o),r,i)})}function b(t,e,n){var r=""===e,i={dispatch:r?t.dispatch:function(n,r,i){var o=E(n,r,i),a=o.payload,u=o.options,s=o.type;return u&&u.root||(s=e+s),t.dispatch(s,a)},commit:r?t.commit:function(n,r,i){var o=E(n,r,i),a=o.payload,u=o.options,s=o.type;u&&u.root||(s=e+s),t.commit(s,a,u)}};return Object.defineProperties(i,{getters:{get:r?funcLine truncated
/**
* @license
* Lodash <https://lodash.com/>
* Copyright JS Foundation and other contributors <https://js.foundation/>
* Released under MIT license <https://lodash.com/license>
* Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
* Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
*/(function(){var o,a="4.17.10",u=200,s="Unsupported core-js use. Try https://npms.io/search?q=ponyfill.",c="Expected a function",l="__lodash_hash_undefined__",f=500,p="__lodash_placeholder__",h=1,d=2,v=4,y=1,g=2,_=1,m=2,b=4,w=8,x=16,k=32,A=64,O=128,C=256,E=512,j=30,S="...",$=800,T=16,R=1,L=2,I=3,P=1/0,M=9007199254740991,D=1.7976931348623157e308,U=NaN,z=4294967295,q=z-1,N=z>>>1,F=[["ary",O],["bind",_],["bindKey",m],["curry",w],["curryRight",x],["flip",E],["partial",k],["partialRight",A],["rearg",C]],H="[object Arguments]",W="[object Array]",B="[object AsyncFunction]",K="[object Boolean]",V="[object Date]",Z="[object DOMException]",X="[object Error]",G="[object Function]",J="[object GeneratorFunction]",Y="[object Map]",Q="[object Number]",tt="[object Null]",et="[object Object]",nt="[object Promise]",rt="[object Proxy]",it="[object RegExp]",ot="[object Set]",at="[object String]",ut="[object Symbol]",st="[object Undefined]",ct="[object WeakMap]",lt="[object WeakSet]",ft="[object ArrayBuffer]",pt="[object DataView]",ht="[object Float32Array]",dt="[object Float64Array]",vt="[object Int8Array]",yt="[object Int16Array]",gt="[object Int32Array]",_t="[object Uint8Array]",mt="[object Uint8ClampedArray]",bt="[object Uint16Array]",wt="[object Uint32Array]",xt=/\b__p \+= '';/g,kt=/\b(__p \+=) '' \+/g,At=/(__e\(.*?\)|\b__t\)) \+\n'';/g,Ot=/&(?:amp|lt|gt|quot|#39);/g,Ct=/[&<>"']/g,Et=RegExp(Ot.source),jt=RegExp(Ct.source),St=/<%-([\s\S]+?)%>/g,$t=/<%([\s\S]+?)%>/g,Tt=/<%=([\s\S]+?)%>/g,Rt=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,Lt=/^\w*$/,It=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g,Pt=/[\\^$.*+?()[\]{}|]/g,Mt=RegExp(Pt.source),Dt=/^\s+|\s+$/g,Ut=/^\s+/,zt=/\s+$/,qt=/\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,Nt=/\{\n\/\* \[wrapped with (.+)\] \*/,Ft=/,? & /,Ht=/[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g,Wt=/\\(\\)?/g,Bt=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g,Kt=/\w*$/,Vt=/^[-+]0x[0-9a-f]+$/i,Zt=/^0b[01]+$/i,Xt=/^\[object .+?Constructor\]$/,Gt=/^0o[0-7]+$/i,Jt=/^(?:0|[1-9]\d*)$/,Yt=/[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g,Qt=/($^)/,te=/['\n\r\u2028\u2029\\]/g,ee="\\ud800-\\udfff",ne="\\u0300-\\u036f",re="\\ufe20-\\ufe2f",ie="\\u20d0-\\u20ff",oe=ne+re+ie,ae="\\u2700-\\u27bf",ue="a-z\\xdf-\\xf6\\xf8-\\xff",se="\\xac\\xb1\\xd7\\xf7",ce="\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf",le="\\u2000-\\u206f",fe=" \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000",pe="A-Z\\xc0-\\xd6\\xd8-\\xde",he="\\ufe0e\\ufe0f",de=se+ce+le+fe,ve="['’]",ye="["+ee+"]",ge="["+de+"]",_e="["+oe+"]",me="\\d+",be="["+ae+"]",we="["+ue+"]",xe="[^"+ee+de+me+ae+ue+pe+"]",ke="\\ud83c[\\udffb-\\udfff]",Ae="(?:"+_e+"|"+ke+")",Oe="[^"+ee+"]",Ce="(?:\\ud83c[\\udde6-\\uddff]){2}",Ee="[\\ud800-\\udbff][\\udc00-\\udfff]",je="["+pe+"]",Se="\\u200d",$e="(?:"+we+"|"+xe+")",Te="(?:"+je+"|"+xe+")",Re="(?:"+ve+"(?:d|ll|m|re|s|t|ve))?",Le="(?:"+ve+"(?:D|LL|M|RE|S|T|VE))?",Ie=Ae+"?",Pe="["+he+"]?",Me="(?:"+Se+"(?:"+[Oe,Ce,Ee].join("|")+")"+Pe+Ie+")*",De="\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])",Ue="\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])",ze=Pe+Ie+Me,qe="(?:"+[be,Ce,Ee].join("|")+")"+ze,Ne="(?:"+[Oe+_e+"?",_e,Ce,Ee,ye].join("|")+")",Fe=RegExp(ve,"g"),He=RegExp(_e,"g"),We=RegExp(ke+"(?="+ke+")|"+Ne+ze,"g"),Be=RegExp([je+"?"+we+"+"+Re+"(?="+[ge,je,"$"].join("|")+")",Te+"+"+Le+"(?="+[ge,je+$e,"$"].join("|")+")",je+"?"+$e+"+"+Re,je+"+"+Le,Ue,De,me,qe].join("|"),"g"),Ke=RegExp("["+Se+ee+oe+he+"]"),Ve=/[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/,Ze=["Array","Buffer","DataView","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Map","Math","Object","Promise","RegExp","Set","String","Symbol","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap","_","clearTimeout","isFinite","parseInt","setTimeout"],Xe=-1,Ge={};Ge[ht]=Ge[dt]=Ge[vt]=Ge[yt]=Ge[gt]=Ge[_t]=Ge[mt]=Ge[bt]=Ge[wt]=!0,Ge[H]=Ge[W]=Ge[ft]=Ge[K]=Ge[pt]=Ge[V]=Ge[X]=Ge[G]=Ge[Y]=Ge[Q]=Ge[et]=Ge[it]=Ge[ot]=Ge[at]=Ge[ct]=!1;var Je={};Je[H]=Je[W]=Je[ft]=Je[pt]=Je[K]=Je[V]=Je[ht]=Je[dt]=Je[vt]=Je[yt]=Je[gt]=Je[Y]=Je[Q]=Je[et]=Je[it]=Je[ot]=Je[at]=Je[ut]=Je[_t]=Je[mt]=Je[bt]=Je[wt]=!0,Je[X]=Je[G]=Je[ct]=!1;var Ye={"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss","Ā":"A","Ă":"A","Ą":"A","ā":"a","ă":"a","ą":"a","Ć":"C","Ĉ":"C","Ċ":"C"Line truncated
/**
* vue-router v3.0.1
* (c) 2017 Evan You
* @license MIT
*/function r(t,e){0}function i(t){return Object.prototype.toString.call(t).indexOf("Error")>-1}var o={name:"router-view",functional:!0,props:{name:{type:String,default:"default"}},render:function(t,e){var n=e.props,r=e.children,i=e.parent,o=e.data;o.routerView=!0;var s=i.$createElement,c=n.name,l=i.$route,f=i._routerViewCache||(i._routerViewCache={}),p=0,h=!1;while(i&&i._routerRoot!==i)i.$vnode&&i.$vnode.data.routerView&&p++,i._inactive&&(h=!0),i=i.$parent;if(o.routerViewDepth=p,h)return s(f[c],o,r);var d=l.matched[p];if(!d)return f[c]=null,s();var v=f[c]=d.components[c];o.registerRouteInstance=function(t,e){var n=d.instances[c];(e&&n!==t||!e&&n===t)&&(d.instances[c]=e)},(o.hook||(o.hook={})).prepatch=function(t,e){d.instances[c]=e.componentInstance};var y=o.props=a(l,d.props&&d.props[c]);if(y){y=o.props=u({},y);var g=o.attrs=o.attrs||{};for(var _ in y)v.props&&_ in v.props||(g[_]=y[_],delete y[_])}return s(v,o,r)}};function a(t,e){switch(typeof e){case"undefined":return;case"object":return e;case"function":return e(t);case"boolean":return e?t.params:void 0;default:0}}function u(t,e){for(var n in e)t[n]=e[n];return t}var s=/[!'()*]/g,c=function(t){return"%"+t.charCodeAt(0).toString(16)},l=/%2C/g,f=function(t){return encodeURIComponent(t).replace(s,c).replace(l,",")},p=decodeURIComponent;function h(t,e,n){void 0===e&&(e={});var r,i=n||d;try{r=i(t||"")}catch(t){r={}}for(var o in e)r[o]=e[o];return r}function d(t){var e={};return t=t.trim().replace(/^(\?|#|&)/,""),t?(t.split("&").forEach(function(t){var n=t.replace(/\+/g," ").split("="),r=p(n.shift()),i=n.length>0?p(n.join("=")):null;void 0===e[r]?e[r]=i:Array.isArray(e[r])?e[r].push(i):e[r]=[e[r],i]}),e):e}function v(t){var e=t?Object.keys(t).map(function(e){var n=t[e];if(void 0===n)return"";if(null===n)return f(e);if(Array.isArray(n)){var r=[];return n.forEach(function(t){void 0!==t&&(null===t?r.push(f(e)):r.push(f(e)+"="+f(t)))}),r.join("&")}return f(e)+"="+f(n)}).filter(function(t){return t.length>0}).join("&"):null;return e?"?"+e:""}var y=/\/?$/;function g(t,e,n,r){var i=r&&r.options.stringifyQuery,o=e.query||{};try{o=_(o)}catch(t){}var a={name:e.name||t&&t.name,meta:t&&t.meta||{},path:e.path||"/",hash:e.hash||"",query:o,params:e.params||{},fullPath:w(e,i),matched:t?b(t):[]};return n&&(a.redirectedFrom=w(n,i)),Object.freeze(a)}function _(t){if(Array.isArray(t))return t.map(_);if(t&&"object"===typeof t){var e={};for(var n in t)e[n]=_(t[n]);return e}return t}var m=g(null,{path:"/"});function b(t){var e=[];while(t)e.unshift(t),t=t.parent;return e}function w(t,e){var n=t.path,r=t.query;void 0===r&&(r={});var i=t.hash;void 0===i&&(i="");var o=e||v;return(n||"/")+o(r)+i}function x(t,e){return e===m?t===e:!!e&&(t.path&&e.path?t.path.replace(y,"")===e.path.replace(y,"")&&t.hash===e.hash&&k(t.query,e.query):!(!t.name||!e.name)&&(t.name===e.name&&t.hash===e.hash&&k(t.query,e.query)&&k(t.params,e.params)))}function k(t,e){if(void 0===t&&(t={}),void 0===e&&(e={}),!t||!e)return t===e;var n=Object.keys(t),r=Object.keys(e);return n.length===r.length&&n.every(function(n){var r=t[n],i=e[n];return"object"===typeof r&&"object"===typeof i?k(r,i):String(r)===String(i)})}function A(t,e){return 0===t.path.replace(y,"/").indexOf(e.path.replace(y,"/"))&&(!e.hash||t.hash===e.hash)&&O(t.query,e.query)}function O(t,e){for(var n in e)if(!(n in t))return!1;return!0}var C,E=[String,Object],j=[String,Array],S={name:"router-link",props:{to:{type:E,required:!0},tag:{type:String,default:"a"},exact:Boolean,append:Boolean,replace:Boolean,activeClass:String,exactActiveClass:String,event:{type:j,default:"click"}},render:function(t){var e=this,n=this.$router,r=this.$route,i=n.resolve(this.to,r,this.append),o=i.location,a=i.route,u=i.href,s={},c=n.options.linkActiveClass,l=n.options.linkExactActiveClass,f=null==c?"router-link-active":c,p=null==l?"router-link-exact-active":l,h=null==this.activeClass?f:this.activeClass,d=null==this.exactActiveClass?p:this.exactActiveClass,v=o.path?g(null,o,null,n):a;s[d]=x(r,v),s[h]=this.exact?s[d]:A(r,v);var y=function(t){$(t)&&(e.replace?n.replace(o):n.push(o))},_={click:$};Array.isArray(this.event)?this.event.forEach(function(t){_[t]=y}):_[this.event]=y;var m={class:s};if("a"===this.tag)m.on=_,m.attrs={href:u};else{var b=T(this.$slots.default);if(b){b.isStatic=!1;var w=C.util.extend,k=b.data=w({},b.data);k.on=_;var O=b.data.attrs=w({},b.data.attrs);O.href=u}else m.on=_}return t(this.tag,m,this.$slots.default)}};function $(t){if(!(t.metaKey||t.altKey||t.ctrlKey||t.shiftKey)&&!t.defaultPrevented&&(void 0===t.button||0===t.button)){if(t.currentTarget&&t.currentTarget.getAttribute){var e=t.currentTarget.getAttribute("target");if(/\b_blank\b/i.test(e))return}return t.preventDefault&&t.preventDefault(),!0}}function T(t){if(t)for(var e,n=0;n<t.length;n++){if(e=t[n],"a"===e.tag)return e;if(e.children&&(e=T(e.children)))return e}}function R(t){if(!R.installed||C!==t){R.installed=!0,C=t;var e=function(t){return void 0!==t},n=function(t,n){var r=t.$options._parentVnodeLine truncated
//# sourceMappingURL=chunk-vendors.b9a11975.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"sources":["webpack:///./node_modules/core-js/modules/_html.js","webpack:///./node_modules/superagent/lib/response-base.js","webpack:///./node_modules/core-js/modules/_is-object.js","webpack:///./node_modules/core-js/modules/_string-context.js","webpack:///./node_modules/core-js/modules/_iter-step.js","webpack:///./node_modules/superagent/lib/client.js","webpack:///./node_modules/core-js/modules/_a-function.js","webpack:///./node_modules/core-js/modules/_redefine-all.js","webpack:///./node_modules/core-js/modules/_enum-bug-keys.js","webpack:///./node_modules/core-js/modules/_species-constructor.js","webpack:///./node_modules/core-js/modules/_array-species-constructor.js","webpack:///./node_modules/superagent/lib/is-object.js","webpack:///./node_modules/core-js/modules/es6.object.assign.js","webpack:///./node_modules/core-js/modules/_an-instance.js","webpack:///./node_modules/core-js/modules/_iter-define.js","webpack:///./node_modules/core-js/modules/_flags.js","webpack:///./node_modules/core-js/modules/_array-methods.js","webpack:///./node_modules/core-js/modules/_object-keys.js","webpack:///./node_modules/marked/lib/marked.js","webpack:///./node_modules/core-js/modules/_is-array.js","webpack:///./node_modules/core-js/modules/_object-dps.js","webpack:///./node_modules/core-js/modules/_task.js","webpack:///./node_modules/core-js/modules/_iter-call.js","webpack:///./node_modules/core-js/modules/_classof.js","webpack:///./node_modules/core-js/modules/es6.array.find-index.js","webpack:///./node_modules/core-js/modules/_dom-create.js","webpack:///./node_modules/core-js/modules/core.get-iterator-method.js","webpack:///./node_modules/core-js/modules/_object-gops.js","webpack:///./node_modules/core-js/modules/_wks.js","webpack:///./node_modules/vue-loader/lib/runtime/componentNormalizer.js","webpack:///./node_modules/core-js/modules/_redefine.js","webpack:///./node_modules/core-js/modules/_object-create.js","webpack:///./node_modules/vue/dist/vue.runtime.esm.js","webpack:///./node_modules/vuex/dist/vuex.esm.js","webpack:///./node_modules/core-js/modules/es6.string.includes.js","webpack:///./node_modules/core-js/modules/_library.js","webpack:///./node_modules/core-js/modules/_cof.js","webpack:///./node_modules/lodash/lodash.js","webpack:///./node_modules/core-js/modules/_strict-method.js","webpack:///./node_modules/core-js/modules/_is-array-iter.js","webpack:///./node_modules/core-js/modules/_invoke.js","webpack:///./node_modules/core-js/modules/_hide.js","webpack:///./node_modules/core-js/modules/es6.regexp.flags.js","webpack:///./node_modules/core-js/modules/_object-gpo.js","webpack:///./node_modules/core-js/modules/_iter-create.js","webpack:///./node_modules/core-js/modules/_to-integer.js","webpack:///./node_modules/core-js/modules/_property-desc.js","webpack:///./node_modules/core-js/modules/_to-object.js","webpack:///./node_modules/core-js/modules/_for-of.js","webpack:///./node_modules/superagent-no-cache/index.js","webpack:///./node_modules/core-js/modules/_fails-is-regexp.js","webpack:///./node_modules/core-js/modules/_object-pie.js","webpack:///./node_modules/core-js/modules/es6.promise.js","webpack:///./node_modules/core-js/modules/_shared.js","webpack:///./node_modules/core-js/modules/es6.array.sort.js","webpack:///./node_modules/core-js/modules/_export.js","webpack:///./node_modules/core-js/modules/_iter-detect.js","webpack:///./node_modules/core-js/modules/_shared-key.js","webpack:///./node_modules/core-js/modules/_iobject.js","webpack:///(webpack)/buildin/module.js","webpack:///./node_modules/core-js/modules/es7.array.includes.js","webpack:///./node_modules/core-js/modules/es6.regexp.to-string.js","webpack:///./node_modules/core-js/modules/_to-iobject.js","webpack:///./node_modules/core-js/modules/_has.js","webpack:///./node_modules/core-js/modules/_to-primitive.js","webpack:///./node_modules/component-emitter/index.js","webpack:///./node_modules/core-js/modules/_object-assign.js","webpack:///./node_modules/core-js/modules/_to-absolute-index.js","webpack:///./node_modules/core-js/modules/es6.array.find.js","webpack:///./node_modules/core-js/modules/_global.js","webpack:///./node_modules/core-js/modules/_fails.js","webpack:///./node_modules/core-js/modules/_set-species.js","webpack:///./node_modules/core-js/modules/es6.function.name.js","webpack:///./node_modules/core-js/modules/_set-to-string-tag.js","webpack:///./node_modules/core-js/modules/_core.js","webpack:///./node_modules/core-js/modules/_microtask.js","webpack:///./node_modules/core-js/modules/_iterators.js","webpack:///./node_modules/component-ie/index.js","webpack:///./node_modules/core-js/modules/_object-dp.js","webpack:///./node_modules/@babel/runtime/helpers/builtin/es6/arrayWithoutHoles.js","webpack:///./node_modules/@babel/runtime/helpers/builtin/es6/iterableToArray.js","webpack:///./node_modules/@babel/runtime/helpers/builtin/es6/nonIterableSpread.js","webpack:///./node_modules/@babel/runtime/helpers/builtin/es6/toConsumablLine truncated
+1
View File
@@ -0,0 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=favicon.ico><link rel=stylesheet href=vendor/furtive.min.css><title>Gekko</title><link as=script href=app.5e99ecf7.js rel=preload><link as=style href=app.730569ff.css rel=preload><link as=script href=chunk-vendors.b9a11975.js rel=preload><link href=app.730569ff.css rel=stylesheet></head><body><noscript><strong>We're sorry but gekko-vue-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=UIconfig.js></script><script src=vendor/reconnecting-websocket.min.js></script><script src=vendor/moment.js></script><script src=vendor/d3.js></script><script src=vendor/toml.js></script><script src=vendor/humanize-duration.js></script><script src=chunk-vendors.b9a11975.js></script><script src=app.5e99ecf7.js></script></body></html>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

+8
View File
@@ -0,0 +1,8 @@
// https://d3js.org Version 4.3.0. Copyright 2016 Mike Bostock.
(function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.d3=t.d3||{})})(this,function(t){"use strict";function n(t){return function(n,e){return Ms(t(n),e)}}function e(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),o=r/i;return o>=Fs?i*=10:o>=Is?i*=5:o>=Ys&&(i*=2),n<t?-i:i}function r(t){return t.length}function i(){}function o(t,n){var e=new i;if(t instanceof i)t.each(function(t,n){e.set(n,t)});else if(Array.isArray(t)){var r,o=-1,u=t.length;if(null==n)for(;++o<u;)e.set(o,t[o]);else for(;++o<u;)e.set(n(r=t[o],o,t),r)}else if(t)for(var a in t)e.set(a,t[a]);return e}function u(){return{}}function a(t,n,e){t[n]=e}function c(){return o()}function s(t,n,e){t.set(n,e)}function f(){}function l(t,n){var e=new f;if(t instanceof f)t.each(function(t){e.add(t)});else if(t){var r=-1,i=t.length;if(null==n)for(;++r<i;)e.add(t[r]);else for(;++r<i;)e.add(n(t[r],r,t))}return e}function h(t){return+t}function p(t){return t*t}function d(t){return t*(2-t)}function v(t){return((t*=2)<=1?t*t:--t*(2-t)+1)/2}function _(t){return t*t*t}function y(t){return--t*t*t+1}function g(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}function m(t){return 1-Math.cos(t*Tf)}function x(t){return Math.sin(t*Tf)}function b(t){return(1-Math.cos(Mf*t))/2}function w(t){return Math.pow(2,10*t-10)}function M(t){return 1-Math.pow(2,-10*t)}function T(t){return((t*=2)<=1?Math.pow(2,10*t-10):2-Math.pow(2,10-10*t))/2}function N(t){return 1-Math.sqrt(1-t*t)}function k(t){return Math.sqrt(1- --t*t)}function S(t){return((t*=2)<=1?1-Math.sqrt(1-t*t):Math.sqrt(1-(t-=2)*t)+1)/2}function A(t){return 1-E(1-t)}function E(t){return(t=+t)<Nf?Lf*t*t:t<Sf?Lf*(t-=kf)*t+Af:t<Cf?Lf*(t-=Ef)*t+zf:Lf*(t-=Pf)*t+qf}function C(t){return((t*=2)<=1?1-E(1-t):E(t-1)+1)/2}function z(t,n){return t[0]-n[0]||t[1]-n[1]}function P(t){for(var n=t.length,e=[0,1],r=2,i=2;i<n;++i){for(;r>1&&Wf(t[e[r-2]],t[e[r-1]],t[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function q(){this._x0=this._y0=this._x1=this._y1=null,this._=[]}function L(){return new q}function R(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,u,a,c,s,f,l,h,p=t._root,d={data:r},v=t._x0,_=t._y0,y=t._x1,g=t._y1;if(!p)return t._root=d,t;for(;p.length;)if((s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u,i=p,!(p=p[l=f<<1|s]))return i[l]=d,t;if(a=+t._x.call(null,p.data),c=+t._y.call(null,p.data),n===a&&e===c)return d.next=p,i?i[l]=d:t._root=d,t;do i=i?i[l]=new Array(4):t._root=new Array(4),(s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u;while((l=f<<1|s)===(h=(c>=u)<<1|a>=o));return i[h]=p,i[l]=d,t}function U(t){var n,e,r,i,o=t.length,u=new Array(o),a=new Array(o),c=1/0,s=1/0,f=-(1/0),l=-(1/0);for(e=0;e<o;++e)isNaN(r=+this._x.call(null,n=t[e]))||isNaN(i=+this._y.call(null,n))||(u[e]=r,a[e]=i,r<c&&(c=r),r>f&&(f=r),i<s&&(s=i),i>l&&(l=i));for(f<c&&(c=this._x0,f=this._x1),l<s&&(s=this._y0,l=this._y1),this.cover(c,s).cover(f,l),e=0;e<o;++e)R(this,u[e],a[e],t[e]);return this}function D(t){for(var n=0,e=t.length;n<e;++n)this.remove(t[n]);return this}function O(t){return t[0]}function F(t){return t[1]}function I(t,n,e){var r=new Y(null==n?O:n,null==e?F:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Y(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function B(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}function j(t){if(!(t>=1))throw new Error;this._size=t,this._call=this._error=null,this._tasks=[],this._data=[],this._waiting=this._active=this._ended=this._start=0}function H(t){if(!t._start)try{X(t)}catch(n){if(t._tasks[t._ended+t._active-1])W(t,n);else if(!t._data)throw n}}function X(t){for(;t._start=t._waiting&&t._active<t._size;){var n=t._ended+t._active,e=t._tasks[n],r=e.length-1,i=e[r];e[r]=V(t,n),--t._waiting,++t._active,e=i.apply(null,e),t._tasks[n]&&(t._tasks[n]=e||_l)}}function V(t,n){return function(e,r){t._tasks[n]&&(--t._active,++t._ended,t._tasks[n]=null,null==t._error&&(null!=e?W(t,e):(t._data[n]=r,t._waiting?H(t):$(t))))}}function W(t,n){var e,r=t._tasks.length;for(t._error=n,t._data=void 0,t._waiting=NaN;--r>=0;)if((e=t._tasks[r])&&(t._tasks[r]=null,e.abort))try{e.abort()}catch(t){}t._active=NaN,$(t)}function $(t){if(!t._active&&t._call){var n=t._data;t._data=void 0,t._call(t._error,n)}}function Z(t){return new j(arguments.length?+t:1/0)}function G(t){return t.innerRadius}function J(t){return t.outerRadius}function Q(t){return t.startAngle}function K(t){return t.endAngle}function tt(t){return t&&t.padAngle}function nt(t){return t>=1?xl:t<=-1?-xl:Math.asin(t)}function et(t,n,e,r,i,o,u,a){var c=e-t,s=r-n,f=u-i,l=a-o,h=(f*(n-o)-l*(t-i))/(l*c-f*s);return[t+h*c,n+h*s]}function rt(t,n,e,r,i,o,u){var a=t-e,c=n-r,s=(u?o:-o)/Math.sqrt(a*a+c*c),f=s*c,l=-s*a,h=t+f,p=n+l,d=e+f,v=r+l,_=(h+d)/2,y=(p+v)/2,g=d-h,m=v-p,x=g*g+m*m,b=i-o,w=h*v-d*p,M=(m<0?-1:1)*Math.sqrt(Math.max(0,b*b*x-w*w)),T=(w*m-g*M)/x,N=(-w*g-m*M)/x,k=(w*m+g*M)/x,S=(-w*Line truncated
}function Pr(t){return t instanceof Date?+t:+new Date(+t)}function qr(t,n,r,i,o,u,a,c,s){function f(e){return(a(e)<e?v:u(e)<e?_:o(e)<e?y:i(e)<e?g:n(e)<e?r(e)<e?m:x:t(e)<e?b:w)(e)}function l(n,r,i,o){if(null==n&&(n=10),"number"==typeof n){var u=Math.abs(i-r)/n,a=Ts(function(t){return t[2]}).right(M,u);a===M.length?(o=e(r/o_,i/o_,n),n=t):a?(a=M[u/M[a-1][2]<M[a][2]/u?a-1:a],o=a[1],n=a[0]):(o=e(r,i,n),n=c)}return null==o?n:n.every(o)}var h=dr(cr,lp),p=h.invert,d=h.domain,v=s(".%L"),_=s(":%S"),y=s("%I:%M"),g=s("%I %p"),m=s("%a %d"),x=s("%b %d"),b=s("%B"),w=s("%Y"),M=[[a,1,Kv],[a,5,5*Kv],[a,15,15*Kv],[a,30,30*Kv],[u,1,t_],[u,5,5*t_],[u,15,15*t_],[u,30,30*t_],[o,1,n_],[o,3,3*n_],[o,6,6*n_],[o,12,12*n_],[i,1,e_],[i,2,2*e_],[r,1,r_],[n,1,i_],[n,3,3*i_],[t,1,o_]];return h.invert=function(t){return new Date(p(t))},h.domain=function(t){return arguments.length?d(Xv.call(t,Pr)):d().map(zr)},h.ticks=function(t,n){var e,r=d(),i=r[0],o=r[r.length-1],u=o<i;return u&&(e=i,i=o,o=e),e=l(t,i,o,n),e=e?e.range(i,o+1):[],u?e.reverse():e},h.tickFormat=function(t,n){return null==n?f:s(n)},h.nice=function(t,n){var e=d();return(t=l(t,e[0],e[e.length-1],n))?d(Qv(e,t)):h},h.copy=function(){return pr(h,qr(t,n,r,i,o,u,a,c,s))},h}function Lr(t){var n=t.length;return function(e){return t[Math.max(0,Math.min(n-1,Math.floor(e*n)))]}}function Rr(t){function n(n){var o=(n-e)/(r-e);return t(i?Math.max(0,Math.min(1,o)):o)}var e=0,r=1,i=!1;return n.domain=function(t){return arguments.length?(e=+t[0],r=+t[1],n):[e,r]},n.clamp=function(t){return arguments.length?(i=!!t,n):i},n.interpolator=function(e){return arguments.length?(t=e,n):t},n.copy=function(){return Rr(t).domain([e,r]).clamp(i)},vr(n)}function Ur(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===w_&&n.documentElement.namespaceURI===w_?n.createElement(t):n.createElementNS(e,t)}}function Dr(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Or(){return new Fr}function Fr(){this._="@"+(++k_).toString(36)}function Ir(t,n,e){return t=Yr(t,n,e),function(n){var e=n.relatedTarget;e&&(e===this||8&e.compareDocumentPosition(this))||t.call(this,n)}}function Yr(n,e,r){return function(i){var o=t.event;t.event=i;try{n.call(this,this.__data__,e,r)}finally{t.event=o}}}function Br(t){return t.trim().split(/^|\s+/).map(function(t){var n="",e=t.indexOf(".");return e>=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}})}function jr(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-1,o=n.length;r<o;++r)e=n[r],t.type&&e.type!==t.type||e.name!==t.name?n[++i]=e:this.removeEventListener(e.type,e.listener,e.capture);++i?n.length=i:delete this.__on}}}function Hr(t,n,e){var r=z_.hasOwnProperty(t.type)?Ir:Yr;return function(i,o,u){var a,c=this.__on,s=r(n,o,u);if(c)for(var f=0,l=c.length;f<l;++f)if((a=c[f]).type===t.type&&a.name===t.name)return this.removeEventListener(a.type,a.listener,a.capture),this.addEventListener(a.type,a.listener=s,a.capture=e),void(a.value=n);this.addEventListener(t.type,s,e),a={type:t.type,name:t.name,value:n,listener:s,capture:e},c?c.push(a):this.__on=[a]}}function Xr(n,e,r,i){var o=t.event;n.sourceEvent=t.event,t.event=n;try{return e.apply(r,i)}finally{t.event=o}}function Vr(){}function Wr(){return[]}function $r(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function Zr(t,n,e,r,i,o){for(var u,a=0,c=n.length,s=o.length;a<s;++a)(u=n[a])?(u.__data__=o[a],r[a]=u):e[a]=new $r(t,o[a]);for(;a<c;++a)(u=n[a])&&(i[a]=u)}function Gr(t,n,e,r,i,o,u){var a,c,s,f={},l=n.length,h=o.length,p=new Array(l);for(a=0;a<l;++a)(c=n[a])&&(p[a]=s=X_+u.call(c,c.__data__,a,n),s in f?i[a]=c:f[s]=c);for(a=0;a<h;++a)s=X_+u.call(t,o[a],a,o),(c=f[s])?(r[a]=c,c.__data__=o[a],f[s]=null):e[a]=new $r(t,o[a]);for(a=0;a<l;++a)(c=n[a])&&f[p[a]]===c&&(i[a]=c)}function Jr(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}function Qr(t){return function(){this.removeAttribute(t)}}function Kr(t){return function(){this.removeAttributeNS(t.space,t.local)}}function ti(t,n){return function(){this.setAttribute(t,n)}}function ni(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function ei(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function ri(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function ii(t){return function(){this.style.removeProperty(t)}}function oi(t,n,e){return function(){this.style.setProperty(t,n,e)}}function ui(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function ai(t){return function(){delete this[t]}}function ci(t,n){return function(){this[t]=n}}function si(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function fi(t){return t.trim().split(/^|\s+/)}function li(t){return t.classList||new hi(t)}function Line truncated
return c&&s?t:t(1)}):t.each(function(){var t=this,o=arguments,u=t.__brush,a=n.input("function"==typeof e?e.apply(t,o):e,u.extent),c=i(t,o).beforestart();Py(t),u.selection=null==a||da(a)?null:a,r.call(t),c.start().brush().end()})},o.prototype={beforestart:function(){return 1===++this.active&&(this.state.emitter=this,this.starting=!0),this},start:function(){return this.starting&&(this.starting=!1,this.emit("start")),this},brush:function(){return this.emit("brush"),this},end:function(){return 0===--this.active&&(delete this.state.emitter,this.emit("end")),this},emit:function(t){Xr(new xm(e,t,n.output(this.state.selection)),l.apply,l,[t,this.that,this.args])}},e.extent=function(t){return arguments.length?(s="function"==typeof t?t:mm([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),e):s},e.filter=function(t){return arguments.length?(f="function"==typeof t?t:mm(!!t),e):f},e.handleSize=function(t){return arguments.length?(h=+t,e):h},e.on=function(){var t=l.on.apply(l,arguments);return t===l?e:t},e}function ma(t){return function(n,e){return t(n.source.value+n.target.value,e.source.value+e.target.value)}}function xa(t){return t.source}function ba(t){return t.target}function wa(t){return t.radius}function Ma(t){return t.startAngle}function Ta(t){return t.endAngle}function Na(){this.reset()}function ka(t,n,e){var r=t.s=n+e,i=r-n,o=r-i;t.t=n-o+(e-i)}function Sa(t){return t>1?0:t<-1?kx:Math.acos(t)}function Aa(t){return t>1?Sx:t<-1?-Sx:Math.asin(t)}function Ea(t){return(t=Ix(t/2))*t}function Ca(){}function za(t,n){t&&Xx.hasOwnProperty(t.type)&&Xx[t.type](t,n)}function Pa(t,n,e){var r,i=-1,o=t.length-e;for(n.lineStart();++i<o;)r=t[i],n.point(r[0],r[1],r[2]);n.lineEnd()}function qa(t,n){var e=-1,r=t.length;for(n.polygonStart();++e<r;)Pa(t[e],n,1);n.polygonEnd()}function La(){Zx.point=Ua}function Ra(){Da(Vm,Wm)}function Ua(t,n){Zx.point=Da,Vm=t,Wm=n,t*=zx,n*=zx,$m=t,Zm=Rx(n=n/2+Ax),Gm=Ix(n)}function Da(t,n){t*=zx,n*=zx,n=n/2+Ax;var e=t-$m,r=e>=0?1:-1,i=r*e,o=Rx(n),u=Ix(n),a=Gm*u,c=Zm*o+a*Rx(i),s=a*r*Ix(i);Wx.add(Lx(s,c)),$m=t,Zm=o,Gm=u}function Oa(t){return[Lx(t[1],t[0]),Aa(t[2])]}function Fa(t){var n=t[0],e=t[1],r=Rx(e);return[r*Rx(n),r*Ix(n),Ix(e)]}function Ia(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function Ya(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function Ba(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function ja(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function Ha(t){var n=Bx(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function Xa(t,n){ox.push(ux=[Jm=t,Km=t]),n<Qm&&(Qm=n),n>tx&&(tx=n)}function Va(t,n){var e=Fa([t*zx,n*zx]);if(ix){var r=Ya(ix,e),i=[r[1],-r[0],0],o=Ya(i,r);Ha(o),o=Oa(o);var u,a=t-nx,c=a>0?1:-1,s=o[0]*Cx*c,f=Px(a)>180;f^(c*nx<s&&s<c*t)?(u=o[1]*Cx,u>tx&&(tx=u)):(s=(s+360)%360-180,f^(c*nx<s&&s<c*t)?(u=-o[1]*Cx,u<Qm&&(Qm=u)):(n<Qm&&(Qm=n),n>tx&&(tx=n))),f?t<nx?Qa(Jm,t)>Qa(Jm,Km)&&(Km=t):Qa(t,Km)>Qa(Jm,Km)&&(Jm=t):Km>=Jm?(t<Jm&&(Jm=t),t>Km&&(Km=t)):t>nx?Qa(Jm,t)>Qa(Jm,Km)&&(Km=t):Qa(t,Km)>Qa(Jm,Km)&&(Jm=t)}else Xa(t,n);ix=e,nx=t}function Wa(){Qx.point=Va}function $a(){ux[0]=Jm,ux[1]=Km,Qx.point=Xa,ix=null}function Za(t,n){if(ix){var e=t-nx;Jx.add(Px(e)>180?e+(e>0?360:-360):e)}else ex=t,rx=n;Zx.point(t,n),Va(t,n)}function Ga(){Zx.lineStart()}function Ja(){Za(ex,rx),Zx.lineEnd(),Px(Jx)>Tx&&(Jm=-(Km=180)),ux[0]=Jm,ux[1]=Km,ix=null}function Qa(t,n){return(n-=t)<0?n+360:n}function Ka(t,n){return t[0]-n[0]}function tc(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}function nc(t,n){t*=zx,n*=zx;var e=Rx(n);ec(e*Rx(t),e*Ix(t),Ix(n))}function ec(t,n,e){++ax,sx+=(t-sx)/ax,fx+=(n-fx)/ax,lx+=(e-lx)/ax}function rc(){tb.point=ic}function ic(t,n){t*=zx,n*=zx;var e=Rx(n);xx=e*Rx(t),bx=e*Ix(t),wx=Ix(n),tb.point=oc,ec(xx,bx,wx)}function oc(t,n){t*=zx,n*=zx;var e=Rx(n),r=e*Rx(t),i=e*Ix(t),o=Ix(n),u=Lx(Bx((u=bx*o-wx*i)*u+(u=wx*r-xx*o)*u+(u=xx*i-bx*r)*u),xx*r+bx*i+wx*o);cx+=u,hx+=u*(xx+(xx=r)),px+=u*(bx+(bx=i)),dx+=u*(wx+(wx=o)),ec(xx,bx,wx)}function uc(){tb.point=nc}function ac(){tb.point=sc}function cc(){fc(gx,mx),tb.point=nc}function sc(t,n){gx=t,mx=n,t*=zx,n*=zx,tb.point=fc;var e=Rx(n);xx=e*Rx(t),bx=e*Ix(t),wx=Ix(n),ec(xx,bx,wx)}function fc(t,n){t*=zx,n*=zx;var e=Rx(n),r=e*Rx(t),i=e*Ix(t),o=Ix(n),u=bx*o-wx*i,a=wx*r-xx*o,c=xx*i-bx*r,s=Bx(u*u+a*a+c*c),f=xx*r+bx*i+wx*o,l=s&&-Sa(f)/s,h=Lx(s,f);vx+=l*u,_x+=l*a,yx+=l*c,cx+=h,hx+=h*(xx+(xx=r)),px+=h*(bx+(bx=i)),dx+=h*(wx+(wx=o)),ec(xx,bx,wx)}function lc(t,n){return[t>kx?t-Ex:t<-kx?t+Ex:t,n]}function hc(t,n,e){return(t%=Ex)?n||e?rb(dc(t),vc(n,e)):dc(t):n||e?vc(n,e):lc}function pc(t){return function(n,e){return n+=t,[n>kx?n-Ex:n<-kx?n+Ex:n,e]}}function dc(t){var n=pc(t);return n.invert=pc(-t),n}function vc(t,n){function e(t,n){var e=Rx(n),a=Rx(t)*e,c=Ix(t)*e,s=Ix(n),f=s*r+a*i;return[Lx(c*o-f*u,a*r-s*i),Aa(f*o+c*u)]}var r=Rx(t),i=Ix(t),o=Rx(n),u=Ix(n);return e.invert=function(t,n){var e=Rx(n),a=Rx(t)*e,c=Ix(t)*e,s=Ix(n),f=s*o-c*u;return[Lx(c*o+s*u,a*r+f*i),Aa(f*r-a*i)]},e}function _c(t,n,e,r,i,o){if(e){var u=Rx(n),a=Ix(n),c=r*e;null==i?(i=n+r*Ex,o=Line truncated
return function(){return t}},gl=1e-12,ml=Math.PI,xl=ml/2,bl=2*ml,wl=function(){function t(){var t,s,f=+n.apply(this,arguments),l=+e.apply(this,arguments),h=o.apply(this,arguments)-xl,p=u.apply(this,arguments)-xl,d=Math.abs(p-h),v=p>h;if(c||(c=t=L()),l<f&&(s=l,l=f,f=s),l>gl)if(d>bl-gl)c.moveTo(l*Math.cos(h),l*Math.sin(h)),c.arc(0,0,l,h,p,!v),f>gl&&(c.moveTo(f*Math.cos(p),f*Math.sin(p)),c.arc(0,0,f,p,h,v));else{var _,y,g=h,m=p,x=h,b=p,w=d,M=d,T=a.apply(this,arguments)/2,N=T>gl&&(i?+i.apply(this,arguments):Math.sqrt(f*f+l*l)),k=Math.min(Math.abs(l-f)/2,+r.apply(this,arguments)),S=k,A=k;if(N>gl){var E=nt(N/f*Math.sin(T)),C=nt(N/l*Math.sin(T));(w-=2*E)>gl?(E*=v?1:-1,x+=E,b-=E):(w=0,x=b=(h+p)/2),(M-=2*C)>gl?(C*=v?1:-1,g+=C,m-=C):(M=0,g=m=(h+p)/2)}var z=l*Math.cos(g),P=l*Math.sin(g),q=f*Math.cos(b),R=f*Math.sin(b);if(k>gl){var U=l*Math.cos(m),D=l*Math.sin(m),O=f*Math.cos(x),F=f*Math.sin(x);if(d<ml){var I=w>gl?et(z,P,O,F,U,D,q,R):[q,R],Y=z-I[0],B=P-I[1],j=U-I[0],H=D-I[1],X=1/Math.sin(Math.acos((Y*j+B*H)/(Math.sqrt(Y*Y+B*B)*Math.sqrt(j*j+H*H)))/2),V=Math.sqrt(I[0]*I[0]+I[1]*I[1]);S=Math.min(k,(f-V)/(X-1)),A=Math.min(k,(l-V)/(X+1))}}M>gl?A>gl?(_=rt(O,F,z,P,l,A,v),y=rt(U,D,q,R,l,A,v),c.moveTo(_.cx+_.x01,_.cy+_.y01),A<k?c.arc(_.cx,_.cy,A,Math.atan2(_.y01,_.x01),Math.atan2(y.y01,y.x01),!v):(c.arc(_.cx,_.cy,A,Math.atan2(_.y01,_.x01),Math.atan2(_.y11,_.x11),!v),c.arc(0,0,l,Math.atan2(_.cy+_.y11,_.cx+_.x11),Math.atan2(y.cy+y.y11,y.cx+y.x11),!v),c.arc(y.cx,y.cy,A,Math.atan2(y.y11,y.x11),Math.atan2(y.y01,y.x01),!v))):(c.moveTo(z,P),c.arc(0,0,l,g,m,!v)):c.moveTo(z,P),f>gl&&w>gl?S>gl?(_=rt(q,R,U,D,f,-S,v),y=rt(z,P,O,F,f,-S,v),c.lineTo(_.cx+_.x01,_.cy+_.y01),S<k?c.arc(_.cx,_.cy,S,Math.atan2(_.y01,_.x01),Math.atan2(y.y01,y.x01),!v):(c.arc(_.cx,_.cy,S,Math.atan2(_.y01,_.x01),Math.atan2(_.y11,_.x11),!v),c.arc(0,0,f,Math.atan2(_.cy+_.y11,_.cx+_.x11),Math.atan2(y.cy+y.y11,y.cx+y.x11),v),c.arc(y.cx,y.cy,S,Math.atan2(y.y11,y.x11),Math.atan2(y.y01,y.x01),!v))):c.arc(0,0,f,b,x,v):c.lineTo(q,R)}else c.moveTo(0,0);if(c.closePath(),t)return c=null,t+""||null}var n=G,e=J,r=yl(0),i=null,o=Q,u=K,a=tt,c=null;return t.centroid=function(){var t=(+n.apply(this,arguments)+ +e.apply(this,arguments))/2,r=(+o.apply(this,arguments)+ +u.apply(this,arguments))/2-ml/2;return[Math.cos(r)*t,Math.sin(r)*t]},t.innerRadius=function(e){return arguments.length?(n="function"==typeof e?e:yl(+e),t):n},t.outerRadius=function(n){return arguments.length?(e="function"==typeof n?n:yl(+n),t):e},t.cornerRadius=function(n){return arguments.length?(r="function"==typeof n?n:yl(+n),t):r},t.padRadius=function(n){return arguments.length?(i=null==n?null:"function"==typeof n?n:yl(+n),t):i},t.startAngle=function(n){return arguments.length?(o="function"==typeof n?n:yl(+n),t):o},t.endAngle=function(n){return arguments.length?(u="function"==typeof n?n:yl(+n),t):u},t.padAngle=function(n){return arguments.length?(a="function"==typeof n?n:yl(+n),t):a},t.context=function(n){return arguments.length?(c=null==n?null:n,t):c},t};it.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:this._context.lineTo(t,n)}}};var Ml=function(t){return new it(t)},Tl=function(){function t(t){var a,c,s,f=t.length,l=!1;for(null==i&&(u=o(s=L())),a=0;a<=f;++a)!(a<f&&r(c=t[a],a,t))===l&&((l=!l)?u.lineStart():u.lineEnd()),l&&u.point(+n(c,a,t),+e(c,a,t));if(s)return u=null,s+""||null}var n=ot,e=ut,r=yl(!0),i=null,o=Ml,u=null;return t.x=function(e){return arguments.length?(n="function"==typeof e?e:yl(+e),t):n},t.y=function(n){return arguments.length?(e="function"==typeof n?n:yl(+n),t):e},t.defined=function(n){return arguments.length?(r="function"==typeof n?n:yl(!!n),t):r},t.curve=function(n){return arguments.length?(o=n,null!=i&&(u=o(i)),t):o},t.context=function(n){return arguments.length?(null==n?i=u=null:u=o(i=n),t):i},t},Nl=function(){function t(t){var n,f,l,h,p,d=t.length,v=!1,_=new Array(d),y=new Array(d);for(null==a&&(s=c(p=L())),n=0;n<=d;++n){if(!(n<d&&u(h=t[n],n,t))===v)if(v=!v)f=n,s.areaStart(),s.lineStart();else{for(s.lineEnd(),s.lineStart(),l=n-1;l>=f;--l)s.point(_[l],y[l]);s.lineEnd(),s.areaEnd()}v&&(_[n]=+e(h,n,t),y[n]=+i(h,n,t),s.point(r?+r(h,n,t):_[n],o?+o(h,n,t):y[n]))}if(p)return s=null,p+""||null}function n(){return Tl().defined(u).curve(c).context(a)}var e=ot,r=null,i=yl(0),o=ut,u=yl(!0),a=null,c=Ml,s=null;return t.x=function(n){return arguments.length?(e="function"==typeof n?n:yl(+n),r=null,t):e},t.x0=function(n){return arguments.length?(e="function"==typeof n?n:yl(+n),t):e},t.x1=function(n){return arguments.length?(r=null==n?null:"function"==typeof n?n:yl(+n),t):r},t.y=function(n){return arguments.length?(i="function"==typeof n?n:yl(+n),o=null,t):i},Line truncated
return e},Rp={value:function(){}};qn.prototype=Pn.prototype={constructor:qn,on:function(t,n){var e,r=this._,i=Ln(t+"",r),o=-1,u=i.length;{if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++o<u;)if(e=(t=i[o]).type)r[e]=Un(r[e],t.name,n);else if(null==n)for(e in r)r[e]=Un(r[e],t.name,null);return this}for(;++o<u;)if((e=(t=i[o]).type)&&(e=Rn(r[e],t.name)))return e}},copy:function(){var t={},n=this._;for(var e in n)t[e]=n[e].slice();return new qn(t)},call:function(t,n){if((e=arguments.length-2)>0)for(var e,r,i=new Array(e),o=0;o<e;++o)i[o]=arguments[o+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(r=this._[t],o=0,e=r.length;o<e;++o)r[o].value.apply(n,i)},apply:function(t,n,e){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],i=0,o=r.length;i<o;++i)r[i].value.apply(n,e)}};var Up,Dp,Op=function(t){function n(t,n){var r,i,o=e(t,function(t,e){return r?r(t,e-1):(i=t,void(r=n?On(t,n):Dn(t)))});return o.columns=i,o}function e(t,n){function e(){if(f>=s)return u;if(i)return i=!1,o;var n,e=f;if(34===t.charCodeAt(e)){for(var r=e;r++<s;)if(34===t.charCodeAt(r)){if(34!==t.charCodeAt(r+1))break;++r}return f=r+2,n=t.charCodeAt(r+1),13===n?(i=!0,10===t.charCodeAt(r+2)&&++f):10===n&&(i=!0),t.slice(e+1,r).replace(/""/g,'"')}for(;f<s;){var a=1;if(n=t.charCodeAt(f++),10===n)i=!0;else if(13===n)i=!0,10===t.charCodeAt(f)&&(++f,++a);else if(n!==c)continue;return t.slice(e,f-a)}return t.slice(e)}for(var r,i,o={},u={},a=[],s=t.length,f=0,l=0;(r=e())!==u;){for(var h=[];r!==o&&r!==u;)h.push(r),r=e();n&&null==(h=n(h,l++))||a.push(h)}return a}function r(n,e){return null==e&&(e=Fn(n)),[e.map(u).join(t)].concat(n.map(function(n){return e.map(function(t){return u(n[t])}).join(t)})).join("\n")}function i(t){return t.map(o).join("\n")}function o(n){return n.map(u).join(t)}function u(t){return null==t?"":a.test(t+="")?'"'+t.replace(/\"/g,'""')+'"':t}var a=new RegExp('["'+t+"\n]"),c=t.charCodeAt(0);return{parse:n,parseRows:e,format:r,formatRows:i}},Fp=Op(","),Ip=Fp.parse,Yp=Fp.parseRows,Bp=Fp.format,jp=Fp.formatRows,Hp=Op("\t"),Xp=Hp.parse,Vp=Hp.parseRows,Wp=Hp.format,$p=Hp.formatRows,Zp=function(t,n){function e(t){var n,e=f.status;if(!e&&Yn(f)||e>=200&&e<300||304===e){if(u)try{n=u.call(r,f)}catch(t){return void c.call("error",r,t)}else n=f;c.call("load",r,n)}else c.call("error",r,t)}var r,i,u,a,c=Pn("beforesend","progress","load","error"),s=o(),f=new XMLHttpRequest,l=null,h=null,p=0;if("undefined"==typeof XDomainRequest||"withCredentials"in f||!/^(http(s)?:)?\/\//.test(t)||(f=new XDomainRequest),"onload"in f?f.onload=f.onerror=f.ontimeout=e:f.onreadystatechange=function(t){f.readyState>3&&e(t)},f.onprogress=function(t){c.call("progress",r,t)},r={header:function(t,n){return t=(t+"").toLowerCase(),arguments.length<2?s.get(t):(null==n?s.remove(t):s.set(t,n+""),r)},mimeType:function(t){return arguments.length?(i=null==t?null:t+"",r):i},responseType:function(t){return arguments.length?(a=t,r):a},timeout:function(t){return arguments.length?(p=+t,r):p},user:function(t){return arguments.length<1?l:(l=null==t?null:t+"",r)},password:function(t){return arguments.length<1?h:(h=null==t?null:t+"",r)},response:function(t){return u=t,r},get:function(t,n){return r.send("GET",t,n)},post:function(t,n){return r.send("POST",t,n)},send:function(n,e,o){return f.open(n,t,!0,l,h),null==i||s.has("accept")||s.set("accept",i+",*/*"),f.setRequestHeader&&s.each(function(t,n){f.setRequestHeader(n,t)}),null!=i&&f.overrideMimeType&&f.overrideMimeType(i),null!=a&&(f.responseType=a),p>0&&(f.timeout=p),null==o&&"function"==typeof e&&(o=e,e=null),null!=o&&1===o.length&&(o=In(o)),null!=o&&r.on("error",o).on("load",function(t){o(null,t)}),c.call("beforesend",r,f),f.send(null==e?null:e),r},abort:function(){return f.abort(),r},on:function(){var t=c.on.apply(c,arguments);return t===c?r:t}},null!=n){if("function"!=typeof n)throw new Error("invalid callback: "+n);return r.get(n)}return r},Gp=function(t,n){return function(e,r){var i=Zp(e).mimeType(t).response(n);if(null!=r){if("function"!=typeof r)throw new Error("invalid callback: "+r);return i.get(r)}return i}},Jp=Gp("text/html",function(t){return document.createRange().createContextualFragment(t.responseText)}),Qp=Gp("application/json",function(t){return JSON.parse(t.responseText)}),Kp=Gp("text/plain",function(t){return t.responseText}),td=Gp("application/xml",function(t){var n=t.responseXML;if(!n)throw new Error("parse error");return n}),nd=function(t,n){return function(e,r,i){arguments.length<3&&(i=r,r=null);var o=Zp(e).mimeType(t);return o.row=function(t){return arguments.length?o.response(Bn(n,r=t)):r},o.row(r),i?o.get(i):o}},ed=nd("text/csv",Ip),rd=nd("text/tab-separated-values",Xp),id=0,od=0,ud=0,ad=1e3,cd=0,sd=0,fd=0,ld="object"==typeof performance&&performance.now?performance:Date,hd="function"==typeof requestAnimationFrame?requestAnimationFrame:function(t){setTimeout(t,17)};Xn.prototype=Vn.prototype={constructor:XLine truncated
for(var r=this._groups,i=r.length,o=[],u=[],a=0;a<i;++a)for(var c,s=r[a],f=s.length,l=0;l<f;++l)if(c=s[l]){for(var h,p=t.call(c,c.__data__,l,s),d=Ri(c,e),v=0,_=p.length;v<_;++v)(h=p[v])&&zy(h,n,e,v,p,d);o.push(p),u.push(c)}return new so(o,u,n,e)},Wy=Pi.prototype.constructor,$y=function(){return new Wy(this._groups,this._parents)},Zy=function(t,n,e){var r="transform"==(t+="")?bp:Ry;return null==n?this.styleTween(t,eo(t,r)).on("end.style."+t,ro(t)):this.styleTween(t,"function"==typeof n?oo(t,r,Fi(this,"style."+t,n)):io(t,r,n),e)},Gy=function(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,uo(t,n,null==e?"":e))},Jy=function(t){return this.tween("text","function"==typeof t?co(Fi(this,"text",t)):ao(null==t?"":t+""))},Qy=function(){for(var t=this._name,n=this._id,e=lo(),r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)if(u=a[s]){var f=Ri(u,n);zy(u,t,e,s,a,{time:f.time+f.delay+f.duration,delay:0,duration:f.duration,ease:f.ease})}return new so(r,this._parents,t,e)},Ky=0,tg=Pi.prototype;so.prototype=fo.prototype={constructor:so,select:Xy,selectAll:Vy,filter:Yy,merge:By,selection:$y,transition:Qy,call:tg.call,nodes:tg.nodes,node:tg.node,size:tg.size,empty:tg.empty,each:tg.each,on:jy,attr:Uy,attrTween:Dy,style:Zy,styleTween:Gy,text:Jy,remove:Hy,tween:Ly,delay:Oy,duration:Fy,ease:Iy};var ng={time:null,delay:0,duration:250,ease:g},eg=function(t){var n,e;t instanceof so?(n=t._id,t=t._name):(n=lo(),(e=ng).time=jn(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)(u=a[s])&&zy(u,t,n,s,a,e||ho(u,n));return new so(r,this._parents,t,n)};Pi.prototype.interrupt=qy,Pi.prototype.transition=eg;var rg=[null],ig=function(t,n){var e,r,i=t.__transition;if(i){n=null==n?null:n+"";for(r in i)if((e=i[r]).state>Ny&&e.name===n)return new so([[t]],rg,n,+r)}return null},og=Array.prototype.slice,ug=function(t){return t},ag=1,cg=2,sg=3,fg=4,lg=1e-6,hg=function(){function t(t){var o,u=0;t.eachAfter(function(t){var e=t.children;e?(t.x=To(e),t.y=ko(e)):(t.x=o?u+=n(t,o):0,t.y=0,o=t)});var a=Ao(t),c=Eo(t),s=a.x-n(a,c)/2,f=c.x+n(c,a)/2;return t.eachAfter(i?function(n){n.x=(n.x-t.x)*e,n.y=(t.y-n.y)*r}:function(n){n.x=(n.x-s)/(f-s)*e,n.y=(1-(t.y?n.y/t.y:1))*r})}var n=Mo,e=1,r=1,i=!1;return t.separation=function(e){return arguments.length?(n=e,t):n},t.size=function(n){return arguments.length?(i=!1,e=+n[0],r=+n[1],t):i?null:[e,r]},t.nodeSize=function(n){return arguments.length?(i=!0,e=+n[0],r=+n[1],t):i?[e,r]:null},t},pg=function(t){var n,e,r,i,o=this,u=[o];do for(n=u.reverse(),u=[];o=n.pop();)if(t(o),e=o.children)for(r=0,i=e.length;r<i;++r)u.push(e[r]);while(u.length);return this},dg=function(t){for(var n,e,r=this,i=[r];r=i.pop();)if(t(r),n=r.children)for(e=n.length-1;e>=0;--e)i.push(n[e]);return this},vg=function(t){for(var n,e,r,i=this,o=[i],u=[];i=o.pop();)if(u.push(i),n=i.children)for(e=0,r=n.length;e<r;++e)o.push(n[e]);for(;i=u.pop();)t(i);return this},_g=function(t){return this.eachAfter(function(n){for(var e=+t(n.data)||0,r=n.children,i=r&&r.length;--i>=0;)e+=r[i].value;n.value=e})},yg=function(t){return this.eachBefore(function(n){n.children&&n.children.sort(t)})},gg=function(t){for(var n=this,e=Co(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r},mg=function(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n},xg=function(){var t=[];return this.each(function(n){t.push(n)}),t},bg=function(){var t=[];return this.eachBefore(function(n){n.children||t.push(n)}),t},wg=function(){var t=this,n=[];return t.each(function(e){e!==t&&n.push({source:e.parent,target:e})}),n};Uo.prototype=zo.prototype={constructor:Uo,each:pg,eachAfter:vg,eachBefore:dg,sum:_g,sort:yg,path:gg,ancestors:mg,descendants:xg,leaves:bg,links:wg,copy:Po};var Mg=function(t){for(var n,e=(t=t.slice()).length,r=null,i=r;e;){var o=new Do(t[e-1]);i=i?i.next=o:r=o,t[n]=t[--e]}return{head:r,tail:i}},Tg=function(t){return Fo(Mg(t),[])},Ng=function(t){return Wo(t),t},kg=function(t){return function(){return t}},Sg=function(){function t(t){return t.x=e/2,t.y=r/2,n?t.eachBefore(Qo(n)).eachAfter(Ko(i,.5)).eachBefore(tu(1)):t.eachBefore(Qo(Jo)).eachAfter(Ko(Go,1)).eachAfter(Ko(i,t.r/Math.min(e,r))).eachBefore(tu(Math.min(e,r)/(2*t.r))),t}var n=null,e=1,r=1,i=Go;return t.radius=function(e){return arguments.length?(n=$o(e),t):n},t.size=function(n){return arguments.length?(e=+n[0],r=+n[1],t):[e,r]},t.padding=function(n){return arguments.length?(i="function"==typeof n?n:kg(+n),t):i},t},Ag=function(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)},Eg=function(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(r-n)/t.value;++a<c;)o=u[a],o.y0=e,o.y1=i,o.x0=n,o.x1=n+=o.value*s},Cg=function(){function t(t){var u=t.height+1;return t.x0=t.y0=i,t.x1=e,t.y1=r/u,t.eachBefore(n(r,u)),o&&t.eaLine truncated
},Bx=Math.sqrt,jx=Math.tan,Hx={Feature:function(t,n){za(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r<i;)za(e[r].geometry,n)}},Xx={Sphere:function(t,n){n.sphere()},Point:function(t,n){t=t.coordinates,n.point(t[0],t[1],t[2])},MultiPoint:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)t=e[r],n.point(t[0],t[1],t[2])},LineString:function(t,n){Pa(t.coordinates,n,0)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)Pa(e[r],n,0)},Polygon:function(t,n){qa(t.coordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)qa(e[r],n)},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,i=e.length;++r<i;)za(e[r],n)}},Vx=function(t,n){t&&Hx.hasOwnProperty(t.type)?Hx[t.type](t,n):za(t,n)},Wx=Xm(),$x=Xm(),Zx={point:Ca,lineStart:Ca,lineEnd:Ca,polygonStart:function(){Wx.reset(),Zx.lineStart=La,Zx.lineEnd=Ra},polygonEnd:function(){var t=+Wx;$x.add(t<0?Ex+t:t),this.lineStart=this.lineEnd=this.point=Ca},sphere:function(){$x.add(Ex)}},Gx=function(t){return $x.reset(),Vx(t,Zx),2*$x},Jx=Xm(),Qx={point:Xa,lineStart:Wa,lineEnd:$a,polygonStart:function(){Qx.point=Za,Qx.lineStart=Ga,Qx.lineEnd=Ja,Jx.reset(),Zx.polygonStart()},polygonEnd:function(){Zx.polygonEnd(),Qx.point=Xa,Qx.lineStart=Wa,Qx.lineEnd=$a,Wx<0?(Jm=-(Km=180),Qm=-(tx=90)):Jx>Tx?tx=90:Jx<-Tx&&(Qm=-90),ux[0]=Jm,ux[1]=Km}},Kx=function(t){var n,e,r,i,o,u,a;if(tx=Km=-(Jm=Qm=1/0),ox=[],Vx(t,Qx),e=ox.length){for(ox.sort(Ka),n=1,r=ox[0],o=[r];n<e;++n)i=ox[n],tc(r,i[0])||tc(r,i[1])?(Qa(r[0],i[1])>Qa(r[0],r[1])&&(r[1]=i[1]),Qa(i[0],r[1])>Qa(r[0],r[1])&&(r[0]=i[0])):o.push(r=i);for(u=-(1/0),e=o.length-1,n=0,r=o[e];n<=e;r=i,++n)i=o[n],(a=Qa(r[1],i[0]))>u&&(u=a,Jm=i[0],Km=r[1])}return ox=ux=null,Jm===1/0||Qm===1/0?[[NaN,NaN],[NaN,NaN]]:[[Jm,Qm],[Km,tx]]},tb={sphere:Ca,point:nc,lineStart:rc,lineEnd:uc,polygonStart:function(){tb.lineStart=ac,tb.lineEnd=cc},polygonEnd:function(){tb.lineStart=rc,tb.lineEnd=uc}},nb=function(t){ax=cx=sx=fx=lx=hx=px=dx=vx=_x=yx=0,Vx(t,tb);var n=vx,e=_x,r=yx,i=n*n+e*e+r*r;return i<Nx&&(n=hx,e=px,r=dx,cx<Tx&&(n=sx,e=fx,r=lx),i=n*n+e*e+r*r,i<Nx)?[NaN,NaN]:[Lx(e,n)*Cx,Aa(r/Bx(i))*Cx]},eb=function(t){return function(){return t}},rb=function(t,n){function e(e,r){return e=t(e,r),n(e[0],e[1])}return t.invert&&n.invert&&(e.invert=function(e,r){return e=n.invert(e,r),e&&t.invert(e[0],e[1])}),e};lc.invert=lc;var ib,ob,ub,ab,cb,sb,fb,lb,hb,pb,db,vb=function(t){function n(n){return n=t(n[0]*zx,n[1]*zx),n[0]*=Cx,n[1]*=Cx,n}return t=hc(t[0]*zx,t[1]*zx,t.length>2?t[2]*zx:0),n.invert=function(n){return n=t.invert(n[0]*zx,n[1]*zx),n[0]*=Cx,n[1]*=Cx,n},n},_b=function(){function t(t,n){e.push(t=r(t,n)),t[0]*=Cx,t[1]*=Cx}function n(){var t=i.apply(this,arguments),n=o.apply(this,arguments)*zx,c=u.apply(this,arguments)*zx;return e=[],r=hc(-t[0]*zx,-t[1]*zx,0).invert,_c(a,n,c,1),t={type:"Polygon",coordinates:[e]},e=r=null,t}var e,r,i=eb([0,0]),o=eb(90),u=eb(6),a={point:t};return n.center=function(t){return arguments.length?(i="function"==typeof t?t:eb([+t[0],+t[1]]),n):i},n.radius=function(t){return arguments.length?(o="function"==typeof t?t:eb(+t),n):o},n.precision=function(t){return arguments.length?(u="function"==typeof t?t:eb(+t),n):u},n},yb=function(){var t,n=[];return{point:function(n,e){t.push([n,e])},lineStart:function(){n.push(t=[])},lineEnd:Ca,rejoin:function(){n.length>1&&n.push(n.pop().concat(n.shift()))},result:function(){var e=n;return n=[],t=null,e}}},gb=function(t,n,e,r,i,o){var u,a=t[0],c=t[1],s=n[0],f=n[1],l=0,h=1,p=s-a,d=f-c;if(u=e-a,p||!(u>0)){if(u/=p,p<0){if(u<l)return;u<h&&(h=u)}else if(p>0){if(u>h)return;u>l&&(l=u)}if(u=i-a,p||!(u<0)){if(u/=p,p<0){if(u>h)return;u>l&&(l=u)}else if(p>0){if(u<l)return;u<h&&(h=u)}if(u=r-c,d||!(u>0)){if(u/=d,d<0){if(u<l)return;u<h&&(h=u)}else if(d>0){if(u>h)return;u>l&&(l=u)}if(u=o-c,d||!(u<0)){if(u/=d,d<0){if(u>h)return;u>l&&(l=u)}else if(d>0){if(u<l)return;u<h&&(h=u)}return l>0&&(t[0]=a+l*p,t[1]=c+l*d),h<1&&(n[0]=a+h*p,n[1]=c+h*d),!0}}}}},mb=function(t,n){return Px(t[0]-n[0])<Tx&&Px(t[1]-n[1])<Tx},xb=function(t,n,e,r,i){var o,u,a=[],c=[];if(t.forEach(function(t){if(!((n=t.length-1)<=0)){var n,e,r=t[0],u=t[n];if(mb(r,u)){for(i.lineStart(),o=0;o<n;++o)i.point((r=t[o])[0],r[1]);return void i.lineEnd()}a.push(e=new gc(r,t,null,!0)),c.push(e.o=new gc(r,null,e,!1)),a.push(e=new gc(u,t,null,!1)),c.push(e.o=new gc(u,null,e,!0))}}),a.length){for(c.sort(n),mc(a),mc(c),o=0,u=c.length;o<u;++o)c[o].e=e=!e;for(var s,f,l=a[0];;){for(var h=l,p=!0;h.v;)if((h=h.n)===l)return;s=h.z,i.lineStart();do{if(h.v=h.o.v=!0,h.e){if(p)for(o=0,u=s.length;o<u;++o)i.point((f=s[o])[0],f[1]);else r(h.x,h.n.x,1,i);h=h.n}else{if(p)for(s=h.p.z,o=s.length-1;o>=0;--o)i.point((f=s[o])[0],f[1]);else r(h.x,h.p.x,-1,i);h=h.p}h=h.o,s=h.z,p=!p}while(!h.v);i.lineEnd()}}},bb=1e9,wb=-bb,Mb=function(){var t,n,e,r=0,i=0,o=960,u=500;return e={stream:function(e){return t&&n===e?t:t=xc(r,i,o,u)(n=e)},extent:function(a){return arguments.length?(r=+a[0][0],i=+a[0][Line truncated
+162
View File
@@ -0,0 +1,162 @@
body{margin:0}a:active,a:hover{outline:0}code{font-size:1em}input,textarea{color:inherit;font:inherit;margin:0}input[type=submit]{-webkit-appearance:button;cursor:pointer}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}textarea{overflow:auto}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.grd{padding-left:1rem;padding-right:1rem}.grd-row{box-sizing:border-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;max-width:100%}.grd-row-col-1-6{max-width:16.66667%;-webkit-flex-basis:16.66667%;-ms-flex-preferred-size:16.66667%;flex-basis:16.66667%}.grd-row-col-2-6{max-width:33.33333%;-webkit-flex-basis:33.33333%;-ms-flex-preferred-size:33.33333%;flex-basis:33.33333%}.grd-row-col-3-6{max-width:50%;-webkit-flex-basis:50%;-ms-flex-preferred-size:50%;flex-basis:50%}.grd-row-col-4-6{max-width:66.66667%;-webkit-flex-basis:66.66667%;-ms-flex-preferred-size:66.66667%;flex-basis:66.66667%}.grd-row-col-5-6{max-width:83.33333%;-webkit-flex-basis:83.33333%;-ms-flex-preferred-size:83.33333%;flex-basis:83.33333%}.grd-row-col-6{max-width:100%;-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%}.grd-row-col-1-6,.grd-row-col-2-6,.grd-row-col-3-6,.grd-row-col-4-6,.grd-row-col-5-6,.grd-row-col-6{-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;box-sizing:border-box}*,:after,:before{box-sizing:border-box}.measure{max-width:48rem;margin:0 auto}a{color:#3498db}a:active,a:focus,a:hover{color:#217dbb}.bg--red{background-color:#e74c3c}.bg--orange{background-color:#f39c12}.bg--blue{background-color:#3498db}.bg--green{background-color:#25ba84}.bg--white{background-color:#fff}.bg--light-gray{background-color:rgba(216,216,216,.99)}.bg--mid-gray{background-color:rgba(144,144,144,.99)}.bg--dark-gray{background-color:rgba(72,72,72,.99)}.bg--off-white{background-color:rgba(250,250,250,.99)}.fnt--red{color:#e74c3c}.fnt--orange{color:#f39c12}.fnt--blue{color:#3498db}.fnt--green{color:#25ba84}.fnt--white{color:#fff}.fnt--light-gray{color:rgba(216,216,216,.99)}.fnt--mid-gray{color:rgba(144,144,144,.99)}.fnt--dark-gray{color:rgba(72,72,72,.99)}.fnt--off-white{color:rgba(250,250,250,.99)}.m0{margin:0}.m1{margin:1rem}.mx1{margin-left:1rem;margin-right:1rem}.my1{margin-top:1rem;margin-bottom:1rem}.m2{margin:2rem}.mx2{margin-left:2rem;margin-right:2rem}.my2{margin-top:2rem;margin-bottom:2rem}.p0{padding:0}.p1{padding:1rem}.px1{padding-left:1rem;padding-right:1rem}.py1{padding-top:1rem;padding-bottom:1rem}.p2{padding:2rem}.px2{padding-left:2rem;padding-right:2rem}.py2{padding-top:2rem;padding-bottom:2rem}html{font-size:12px}@media screen and (min-width:32rem) and (max-width:48rem){html{font-size:15px}}@media screen and (min-width:48rem){html{font-size:16px}}body{font-family:HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:400;line-height:1.85;color:#333}p{font-size:1rem;margin-bottom:1.3rem}.h1,.h2,.h3,.h4,h1,h2,h3,h4{margin:1.414rem 0 .5rem;font-weight:inherit;line-height:1.42}.h1,h1{margin-top:0;font-size:3.998rem}.h2,h2{font-size:2.827rem}.h3,h3{font-size:1.999rem}.h4,h4{font-size:1.414rem}.h5,table th{font-size:1.121rem}.h6,h6{font-size:.88rem}.btn--s,.small,small{font-size:.707em}code{font-family:Monaco,"Lucida Console",Courier,monospace}.italic{font-style:italic}.thin{font-weight:100}.bold{font-weight:700}.caps,table th{font-variant:small-caps}.muted{opacity:.7}.txt--center{text-align:center}.txt--right{text-align:right}.txt--left,table th{text-align:left}.oflow-y--scroll{overflow-y:scroll}.w100--s{width:100%;display:block}@media screen and (min-width:32rem){.w100--s{width:auto;display:inline-block}}img,textarea{max-width:100%}.btn,.btn--blue,.btn--gray,.btn--green,.btn--link,.btn--red{border-radius:3px}.brdr--light-gray{border:thin solid rgba(216,216,216,.99)}.brdr--mid-gray{border:thin solid rgba(144,144,144,.99)}.brdr--dark-gray{border:thin solid rgba(72,72,72,.99)}.brdr--off-white{border:thin solid rgba(250,250,250,.99)}.btn,.btn--blue,.btn--gray,.btn--green,.btn--link,.btn--red{padding:.5rem 1rem;border:2px solid #ccc;color:#333;text-decoration:none;text-align:center}.btn:active,.btn:focus,.btn:hover{background-color:rgba(0,0,0,.05);color:#000}.btn--link{border-color:transparent;color:#3498db}.btn--link:hover{background-color:transparent;color:#1d6fa5}.btn--blue{border-color:#2792d9;background-color:#3498db;color:#fff}.btn--blue:active,.btn--blue:focus,.btn--blue:hover{color:#fff;background-color:#217dbb}.btn--green{border-color:#22a977;background-color:#25ba84;color:#fff}.btn--green:active,.btn--green:focus,.btn--green:hover{color:#fff;background-color:#1d8f65}.btn--gray{border-color:rgba(59,59,59,.99);background-color:rgba(72,72,72,.99);color:#fff}.btn--gray:active,.btn--gray:focus,.btn--gray:hover{color:#fff;background-color:Line truncated
/* Label styles: style as needed */
label {
display:block;
margin-top:2em;
font-size: 0.9em;
color:#777;
}
/* Container used for styling the custom select, the buttom class adds the bg gradient, corners, etc. */
.custom-select {
position: relative;
display:block;
margin-top:0.5em;
padding:0;
}
/* This is the native select, we're making everything but the text invisible so we can see the button styles in the wrapper */
.custom-select select {
width:100%;
margin:0;
background:none;
border: 1px solid transparent;
outline: none;
/* Prefixed box-sizing rules necessary for older browsers */
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
/* Remove select styling */
appearance: none;
-webkit-appearance: none;
/* Magic font size number to prevent iOS text zoom */
font-size:16px;
/* General select styles: change as needed */
font-family: helvetica, sans-serif;
font-weight: bold;
color: #444;
/*padding: .6em 1.9em .5em .8em;*/
padding: 0.4em 1.2em .3em .8em;
line-height:1.3;
}
/* Custom arrow sits on top of the select - could be an image, SVG, icon font, etc. or the arrow could just baked into the bg image on the select */
.custom-select::after {
content: "";
position: absolute;
width: 9px;
height: 8px;
top: 50%;
right: 1em;
margin-top:-4px;
background-image: url('select-arrow.png');
background-repeat: no-repeat;
background-size: 100%;
/* These hacks make the select behind the arrow clickable in some browsers */
pointer-events:none;
}
/* IE 10/11+ - This hides native dropdown button arrow so it will have the custom appearance, IE 9 and earlier get a native select - targeting hack via http://browserhacks.com/#hack-f1070533535a12744a0381a75087a915 */
_:-ms-input-placeholder, :root .custom-select select::-ms-expand {
display: none;
}
/* Removes the odd blue bg color behind the text in the select button in IE 10/11 and sets the text color to match the focus style's - fix via http://stackoverflow.com/questions/17553300/change-ie-background-color-on-unopened-focused-select-box */
_:-ms-input-placeholder, :root .custom-select select:focus::-ms-value {
background: transparent;
color: #222;
}
/* Firefox >= 2 -- Older versions of FF (v2 - 6) won't let us hide the native select arrow, so we'll just hide the custom icon and go with native styling. Targeting hack via http://browserhacks.com/#hack-756739b33c37fb7db4cce645bbf7ea5f */
/* Show only the native arrow */
body:last-child .custom-select::after, x:-moz-any-link {
display: none;
}
/* reduce padding */
body:last-child .custom-select select, x:-moz-any-link {
padding-right: .8em;
}
/* Firefox 6+ -- Hide the native select and arrow. We've found the simplest way to hide the native styling in FF is to make the select bigger than its container and clip it. */
/* The specific FF selector used below successfully overrides the previous rule that turns off the custom icon; other FF hacky selectors we tried, like `*>.custom-select::after`, did not undo the previous rule. Targeting hack via http://browserhacks.com/#hack-443a4eb168ccf066e7c2909be4911af1 */
/* Show the custom arrow again */
_::-moz-progress-bar, body:last-child .custom-select:after {
display: block;
}
/* Hacks to hide the native select appearance */
_::-moz-progress-bar, body:last-child .custom-select select {
-moz-appearance: window;
text-indent: 0.01px;
text-overflow: "";
/* increase padding to make room for menu icon */
padding-right: 13%;
}
/* In FF 30+ -- Set overflow:hidden on the wrapper to clip the native select's arrow. Need to get extra wide (120%) because newest Firefox/Android is terrible. The downside is this makes the menu 20% wider than it should be when it opens. Hack targeting via http://browserhacks.com/#hack-cfd4c21603b122acfda8e81f41cdb320 */
@supports (-moz-appearance:meterbar) and (background-blend-mode:difference,normal) {
/* Clip select with the container */
_::-moz-progress-bar, body:last-child .custom-select {
overflow: hidden;
}
/* Make select extra wide */
_::-moz-progress-bar, body:last-child .custom-select select {
width: 120%;
}
}
/* Firefox 7+ focus style - This works around the issue that -moz-appearance: window kills the normal select focus. Using semi-opaque because outline doesn't handle rounded corners */
_::-moz-progress-bar, body:last-child .custom-select select:focus {
outline: 2px solid rgba(180,222,250, .7);
}
/* Opera - Pre-Blink nix the custom arrow, go with a native select button */
x:-o-prefocus, .custom-select::after {
display:none;
}
/* Hover style */
.custom-select:hover {
border:1px solid #888;
}
/* Focus style */
.custom-select select:focus {
outline:none;
box-shadow: 0 0 1px 3px rgba(180,222,250, 1);
background-color:transparent;
color: #222;
border:1px solid #aaa;
}
/* Firefox focus has odd artifacts around the text, this kills that */
.custom-select select:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #000;
}
.custom-select option {
font-weight:normal;
}
/* These are just demo button-y styles, style as you like */
.button {
border: 1px solid #bbb;
border-radius: .3em;
box-shadow: 0 1px 0 1px rgba(0,0,0,.04);
background: #f3f3f3; /* Old browsers */
background: -moz-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(100%,#e5e5e5)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #ffffff 0%,#e5e5e5 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #ffffff 0%,#e5e5e5 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #ffffff 0%,#e5e5e5 100%); /* IE10+ */
background: linear-gradient(to bottom, #ffffff 0%,#e5e5e5 100%); /* W3C */
}
+193
View File
@@ -0,0 +1,193 @@
// HumanizeDuration.js - http://git.io/j0HgmQ
;(function () {
var languages = {
en: {
y: function (c) { return 'year' + (c !== 1 ? 's' : '') },
mo: function (c) { return 'month' + (c !== 1 ? 's' : '') },
w: function (c) { return 'week' + (c !== 1 ? 's' : '') },
d: function (c) { return 'day' + (c !== 1 ? 's' : '') },
h: function (c) { return 'hour' + (c !== 1 ? 's' : '') },
m: function (c) { return 'minute' + (c !== 1 ? 's' : '') },
s: function (c) { return 'second' + (c !== 1 ? 's' : '') },
ms: function (c) { return 'millisecond' + (c !== 1 ? 's' : '') },
decimal: '.'
}
}
// You can create a humanizer, which returns a function with default
// parameters.
function humanizer (passedOptions) {
var result = function humanizer (ms, humanizerOptions) {
var options = extend({}, result, humanizerOptions || {})
return doHumanization(ms, options)
}
return extend(result, {
language: 'en',
delimiter: ', ',
spacer: ' ',
conjunction: '',
serialComma: true,
units: ['y', 'mo', 'w', 'd', 'h', 'm', 's'],
languages: {},
round: false,
unitMeasures: {
y: 31557600000,
mo: 2629800000,
w: 604800000,
d: 86400000,
h: 3600000,
m: 60000,
s: 1000,
ms: 1
}
}, passedOptions)
}
// The main function is just a wrapper around a default humanizer.
var humanizeDuration = humanizer({})
// doHumanization does the bulk of the work.
function doHumanization (ms, options) {
var i, len, piece
// Make sure we have a positive number.
// Has the nice sideffect of turning Number objects into primitives.
ms = Math.abs(ms)
var dictionary = options.languages[options.language] || languages[options.language]
if (!dictionary) {
throw new Error('No language ' + dictionary + '.')
}
var pieces = []
// Start at the top and keep removing units, bit by bit.
var unitName, unitMS, unitCount
for (i = 0, len = options.units.length; i < len; i++) {
unitName = options.units[i]
unitMS = options.unitMeasures[unitName]
// What's the number of full units we can fit?
if (i + 1 === len) {
unitCount = ms / unitMS
} else {
unitCount = Math.floor(ms / unitMS)
}
// Add the string.
pieces.push({
unitCount: unitCount,
unitName: unitName
})
// Remove what we just figured out.
ms -= unitCount * unitMS
}
var firstOccupiedUnitIndex = 0
for (i = 0; i < pieces.length; i++) {
if (pieces[i].unitCount) {
firstOccupiedUnitIndex = i
break
}
}
if (options.round) {
var ratioToLargerUnit, previousPiece
for (i = pieces.length - 1; i >= 0; i--) {
piece = pieces[i]
piece.unitCount = Math.round(piece.unitCount)
if (i === 0) { break }
previousPiece = pieces[i - 1]
ratioToLargerUnit = options.unitMeasures[previousPiece.unitName] / options.unitMeasures[piece.unitName]
if ((piece.unitCount % ratioToLargerUnit) === 0 || (options.largest && ((options.largest - 1) < (i - firstOccupiedUnitIndex)))) {
previousPiece.unitCount += piece.unitCount / ratioToLargerUnit
piece.unitCount = 0
}
}
}
var result = []
for (i = 0, pieces.length; i < len; i++) {
piece = pieces[i]
if (piece.unitCount) {
result.push(render(piece.unitCount, piece.unitName, dictionary, options))
}
if (result.length === options.largest) { break }
}
if (result.length) {
if (!options.conjunction || result.length === 1) {
return result.join(options.delimiter)
} else if (result.length === 2) {
return result.join(options.conjunction)
} else if (result.length > 2) {
return result.slice(0, -1).join(options.delimiter) + (options.serialComma ? ',' : '') + options.conjunction + result.slice(-1)
}
} else {
return render(0, options.units[options.units.length - 1], dictionary, options)
}
}
function render (count, type, dictionary, options) {
var decimal
if (options.decimal === void 0) {
decimal = dictionary.decimal
} else {
decimal = options.decimal
}
var countStr = count.toString().replace('.', decimal)
var dictionaryValue = dictionary[type]
var word
if (typeof dictionaryValue === 'function') {
word = dictionaryValue(count)
} else {
word = dictionaryValue
}
return countStr + options.spacer + word
}
function extend (destination) {
var source
for (var i = 1; i < arguments.length; i++) {
source = arguments[i]
for (var prop in source) {
if (source.hasOwnProperty(prop)) {
destination[prop] = source[prop]
}
}
}
return destination
}
humanizeDuration.getSupportedLanguages = function getSupportedLanguages () {
var result = []
for (var language in languages) {
if (languages.hasOwnProperty(language)) {
result.push(language)
}
}
return result
}
humanizeDuration.humanizer = humanizer
if (typeof define === 'function' && define.amd) {
define(function () {
return humanizeDuration
})
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = humanizeDuration
} else {
this.humanizeDuration = humanizeDuration
}
})(); // eslint-disable-line semi
+548
View File
@@ -0,0 +1,548 @@
//! moment.js
//! version : 2.15.2
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return md.apply(null,arguments)}
// This is done to register the method called with moment()
// without creating circular dependencies.
function b(a){md=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){
// IE8 will treat undefined and null as object if it wasn't for
// input != null
return null!=a&&"[object Object]"===Object.prototype.toString.call(a)}function e(a){var b;for(b in a)
// even if its not own property I'd still call it non-empty
return!1;return!0}function f(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function g(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function h(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function i(a,b){for(var c in b)h(b,c)&&(a[c]=b[c]);return h(b,"toString")&&(a.toString=b.toString),h(b,"valueOf")&&(a.valueOf=b.valueOf),a}function j(a,b,c,d){return qb(a,b,c,d,!0).utc()}function k(){
// We need to deep clone this object.
return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function l(a){return null==a._pf&&(a._pf=k()),a._pf}function m(a){if(null==a._isValid){var b=l(a),c=nd.call(b.parsedDateParts,function(a){return null!=a}),d=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.invalidWeekday&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated&&(!b.meridiem||b.meridiem&&c);if(a._strict&&(d=d&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour),null!=Object.isFrozen&&Object.isFrozen(a))return d;a._isValid=d}return a._isValid}function n(a){var b=j(NaN);return null!=a?i(l(b),a):l(b).userInvalidated=!0,b}function o(a){return void 0===a}function p(a,b){var c,d,e;if(o(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),o(b._i)||(a._i=b._i),o(b._f)||(a._f=b._f),o(b._l)||(a._l=b._l),o(b._strict)||(a._strict=b._strict),o(b._tzm)||(a._tzm=b._tzm),o(b._isUTC)||(a._isUTC=b._isUTC),o(b._offset)||(a._offset=b._offset),o(b._pf)||(a._pf=l(b)),o(b._locale)||(a._locale=b._locale),od.length>0)for(c in od)d=od[c],e=b[d],o(e)||(a[d]=e);return a}
// Moment prototype object
function q(b){p(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),
// Prevent infinite loop in case updateOffset creates new moment
// objects.
pd===!1&&(pd=!0,a.updateOffset(this),pd=!1)}function r(a){return a instanceof q||null!=a&&null!=a._isAMomentObject}function s(a){return a<0?Math.ceil(a)||0:Math.floor(a)}function t(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=s(b)),c}
// compare two arrays, return the number of differences
function u(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;d<e;d++)(c&&a[d]!==b[d]||!c&&t(a[d])!==t(b[d]))&&g++;return g+f}function v(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function w(b,c){var d=!0;return i(function(){if(null!=a.deprecationHandler&&a.deprecationHandler(null,b),d){for(var e,f=[],g=0;g<arguments.length;g++){if(e="","object"==typeof arguments[g]){e+="\n["+g+"] ";for(var h in arguments[0])e+=h+": "+arguments[0][h]+", ";e=e.slice(0,-2)}else e=arguments[g];f.push(e)}v(b+"\nArguments: "+Array.prototype.slice.call(f).join("")+"\n"+(new Error).stack),d=!1}return c.apply(this,arguments)},c)}function x(b,c){null!=a.deprecationHandler&&a.deprecationHandler(b,c),qd[b]||(v(c),qd[b]=!0)}function y(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}function z(a){var b,c;for(c in a)b=a[c],y(b)?this[c]=b:this["_"+c]=b;this._config=a,
// Lenient ordinal parsing accepts just a number in addition to
// number + (possibly) stuff coming from _ordinalParseLenient.
this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function A(a,b){var c,e=i({},a);for(c in b)h(b,c)&&(d(a[c])&&d(b[c])?(e[c]={},i(e[c],a[c]),i(e[c],b[c])):null!=b[c]?e[c]=b[c]:delete e[c]);for(c in a)h(a,c)&&!h(b,c)&&d(a[c])&&(
// make sure changes to properties don't modify parent config
e[c]=i({},e[c]));return e}function B(a){null!=a&&this.set(a)}function C(a,b,c){var d=this._calendar[a]||this._calendar.sameElse;return y(d)?d.call(b,c):d}function D(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function E(){return this._invalidDate}function F(a){return this._ordinal.replace("%d",a)}function G(a,b,c,d){var e=this._relativeTime[c];return y(e)?e(a,b,c,d):e.replace(/%d/i,a)}function H(a,b){var c=this._relativeTime[a>0?"future":"past"];return y(c)?c(b):c.replace(/%s/i,b)}function I(a,b){var c=a.toLowerCase();zd[c]=zd[c+"s"]=zd[b]=a}function J(a){return"string"==typeof a?zd[a]||zd[a.toLowerCase()]:void 0}function K(a){var b,c,d={};for(c in a)h(a,c)&&(b=J(c),b&&(d[b]=a[c]));return d}function L(a,b){Ad[a]=b}function M(a){var b=[];for(var c in a)b.push({unit:c,priority:Ad[c]});return b.sort(function(a,b){return a.priority-b.priority}),b}function N(b,c){return function(d){return null!=d?(P(this,b,d),a.updateOffset(this,c),this):O(this,b)}}function O(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}function P(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)}
// MOMENTS
function Q(a){return a=J(a),y(this[a])?this[a]():this}function R(a,b){if("object"==typeof a){a=K(a);for(var c=M(a),d=0;d<c.length;d++)this[c[d].unit](a[c[d].unit])}else if(a=J(a),y(this[a]))return this[a](b);return this}function S(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}
// token: 'M'
// padded: ['MM', 2]
// ordinal: 'Mo'
// callback: function () { this.month() + 1 }
function T(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Ed[a]=e),b&&(Ed[b[0]]=function(){return S(e.apply(this,arguments),b[1],b[2])}),c&&(Ed[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function U(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function V(a){var b,c,d=a.match(Bd);for(b=0,c=d.length;b<c;b++)Ed[d[b]]?d[b]=Ed[d[b]]:d[b]=U(d[b]);return function(b){var e,f="";for(e=0;e<c;e++)f+=d[e]instanceof Function?d[e].call(b,a):d[e];return f}}
// format date using native date object
function W(a,b){return a.isValid()?(b=X(b,a.localeData()),Dd[b]=Dd[b]||V(b),Dd[b](a)):a.localeData().invalidDate()}function X(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Cd.lastIndex=0;d>=0&&Cd.test(a);)a=a.replace(Cd,c),Cd.lastIndex=0,d-=1;return a}function Y(a,b,c){Wd[a]=y(b)?b:function(a,d){return a&&c?c:b}}function Z(a,b){return h(Wd,a)?Wd[a](b._strict,b._locale):new RegExp($(a))}
// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
function $(a){return _(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}))}function _(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function aa(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=t(a)}),c=0;c<a.length;c++)Xd[a[c]]=d}function ba(a,b){aa(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function ca(a,b,c){null!=b&&h(Xd,a)&&Xd[a](b,c._a,c,a)}function da(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function ea(a,b){return a?c(this._months)?this._months[a.month()]:this._months[(this._months.isFormat||fe).test(b)?"format":"standalone"][a.month()]:this._months}function fa(a,b){return a?c(this._monthsShort)?this._monthsShort[a.month()]:this._monthsShort[fe.test(b)?"format":"standalone"][a.month()]:this._monthsShort}function ga(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._monthsParse)for(
// this is not used
this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],d=0;d<12;++d)f=j([2e3,d]),this._shortMonthsParse[d]=this.monthsShort(f,"").toLocaleLowerCase(),this._longMonthsParse[d]=this.months(f,"").toLocaleLowerCase();return c?"MMM"===b?(e=sd.call(this._shortMonthsParse,g),e!==-1?e:null):(e=sd.call(this._longMonthsParse,g),e!==-1?e:null):"MMM"===b?(e=sd.call(this._shortMonthsParse,g),e!==-1?e:(e=sd.call(this._longMonthsParse,g),e!==-1?e:null)):(e=sd.call(this._longMonthsParse,g),e!==-1?e:(e=sd.call(this._shortMonthsParse,g),e!==-1?e:null))}function ha(a,b,c){var d,e,f;if(this._monthsParseExact)return ga.call(this,a,b,c);
// TODO: add sorting
// Sorting makes sure if one month (or abbr) is a prefix of another
// see sorting in computeMonthsParse
for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;d<12;d++){
// test the regex
if(
// make the regex if we don't have it already
e=j([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}
// MOMENTS
function ia(a,b){var c;if(!a.isValid())
// No op
return a;if("string"==typeof b)if(/^\d+$/.test(b))b=t(b);else
// TODO: Another silent failure?
if(b=a.localeData().monthsParse(b),"number"!=typeof b)return a;return c=Math.min(a.date(),da(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a}function ja(b){return null!=b?(ia(this,b),a.updateOffset(this,!0),this):O(this,"Month")}function ka(){return da(this.year(),this.month())}function la(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na.call(this),a?this._monthsShortStrictRegex:this._monthsShortRegex):(h(this,"_monthsShortRegex")||(this._monthsShortRegex=ie),this._monthsShortStrictRegex&&a?this._monthsShortStrictRegex:this._monthsShortRegex)}function ma(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na.call(this),a?this._monthsStrictRegex:this._monthsRegex):(h(this,"_monthsRegex")||(this._monthsRegex=je),this._monthsStrictRegex&&a?this._monthsStrictRegex:this._monthsRegex)}function na(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[],f=[];for(b=0;b<12;b++)
// make the regex if we don't have it already
c=j([2e3,b]),d.push(this.monthsShort(c,"")),e.push(this.months(c,"")),f.push(this.months(c,"")),f.push(this.monthsShort(c,""));for(
// Sorting makes sure if one month (or abbr) is a prefix of another it
// will match the longer piece.
d.sort(a),e.sort(a),f.sort(a),b=0;b<12;b++)d[b]=_(d[b]),e[b]=_(e[b]);for(b=0;b<24;b++)f[b]=_(f[b]);this._monthsRegex=new RegExp("^("+f.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+e.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+d.join("|")+")","i")}
// HELPERS
function oa(a){return pa(a)?366:365}function pa(a){return a%4===0&&a%100!==0||a%400===0}function qa(){return pa(this.year())}function ra(a,b,c,d,e,f,g){
//can't just apply() to create a date:
//http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
var h=new Date(a,b,c,d,e,f,g);
//the date constructor remaps years 0-99 to 1900-1999
return a<100&&a>=0&&isFinite(h.getFullYear())&&h.setFullYear(a),h}function sa(a){var b=new Date(Date.UTC.apply(null,arguments));
//the Date.UTC function remaps years 0-99 to 1900-1999
return a<100&&a>=0&&isFinite(b.getUTCFullYear())&&b.setUTCFullYear(a),b}
// start-of-first-week - start-of-year
function ta(a,b,c){var// first-week day -- which january is always in the first week (4 for iso, 1 for other)
d=7+b-c,
// first-week day local weekday -- which local weekday is fwd
e=(7+sa(a,0,d).getUTCDay()-b)%7;return-e+d-1}
//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
function ua(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ta(a,d,e),j=1+7*(b-1)+h+i;return j<=0?(f=a-1,g=oa(f)+j):j>oa(a)?(f=a+1,g=j-oa(a)):(f=a,g=j),{year:f,dayOfYear:g}}function va(a,b,c){var d,e,f=ta(a.year(),b,c),g=Math.floor((a.dayOfYear()-f-1)/7)+1;return g<1?(e=a.year()-1,d=g+wa(e,b,c)):g>wa(a.year(),b,c)?(d=g-wa(a.year(),b,c),e=a.year()+1):(e=a.year(),d=g),{week:d,year:e}}function wa(a,b,c){var d=ta(a,b,c),e=ta(a+1,b,c);return(oa(a)-d+e)/7}
// HELPERS
// LOCALES
function xa(a){return va(a,this._week.dow,this._week.doy).week}function ya(){return this._week.dow}function za(){return this._week.doy}
// MOMENTS
function Aa(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function Ba(a){var b=va(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}
// HELPERS
function Ca(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function Da(a,b){return"string"==typeof a?b.weekdaysParse(a)%7||7:isNaN(a)?null:a}function Ea(a,b){return a?c(this._weekdays)?this._weekdays[a.day()]:this._weekdays[this._weekdays.isFormat.test(b)?"format":"standalone"][a.day()]:this._weekdays}function Fa(a){return a?this._weekdaysShort[a.day()]:this._weekdaysShort}function Ga(a){return a?this._weekdaysMin[a.day()]:this._weekdaysMin}function Ha(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],d=0;d<7;++d)f=j([2e3,1]).day(d),this._minWeekdaysParse[d]=this.weekdaysMin(f,"").toLocaleLowerCase(),this._shortWeekdaysParse[d]=this.weekdaysShort(f,"").toLocaleLowerCase(),this._weekdaysParse[d]=this.weekdays(f,"").toLocaleLowerCase();return c?"dddd"===b?(e=sd.call(this._weekdaysParse,g),e!==-1?e:null):"ddd"===b?(e=sd.call(this._shortWeekdaysParse,g),e!==-1?e:null):(e=sd.call(this._minWeekdaysParse,g),e!==-1?e:null):"dddd"===b?(e=sd.call(this._weekdaysParse,g),e!==-1?e:(e=sd.call(this._shortWeekdaysParse,g),e!==-1?e:(e=sd.call(this._minWeekdaysParse,g),e!==-1?e:null))):"ddd"===b?(e=sd.call(this._shortWeekdaysParse,g),e!==-1?e:(e=sd.call(this._weekdaysParse,g),e!==-1?e:(e=sd.call(this._minWeekdaysParse,g),e!==-1?e:null))):(e=sd.call(this._minWeekdaysParse,g),e!==-1?e:(e=sd.call(this._weekdaysParse,g),e!==-1?e:(e=sd.call(this._shortWeekdaysParse,g),e!==-1?e:null)))}function Ia(a,b,c){var d,e,f;if(this._weekdaysParseExact)return Ha.call(this,a,b,c);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),d=0;d<7;d++){
// test the regex
if(
// make the regex if we don't have it already
e=j([2e3,1]).day(d),c&&!this._fullWeekdaysParse[d]&&(this._fullWeekdaysParse[d]=new RegExp("^"+this.weekdays(e,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[d]=new RegExp("^"+this.weekdaysShort(e,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[d]=new RegExp("^"+this.weekdaysMin(e,"").replace(".",".?")+"$","i")),this._weekdaysParse[d]||(f="^"+this.weekdays(e,"")+"|^"+this.weekdaysShort(e,"")+"|^"+this.weekdaysMin(e,""),this._weekdaysParse[d]=new RegExp(f.replace(".",""),"i")),c&&"dddd"===b&&this._fullWeekdaysParse[d].test(a))return d;if(c&&"ddd"===b&&this._shortWeekdaysParse[d].test(a))return d;if(c&&"dd"===b&&this._minWeekdaysParse[d].test(a))return d;if(!c&&this._weekdaysParse[d].test(a))return d}}
// MOMENTS
function Ja(a){if(!this.isValid())return null!=a?this:NaN;var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Ca(a,this.localeData()),this.add(a-b,"d")):b}function Ka(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function La(a){if(!this.isValid())return null!=a?this:NaN;
// behaves the same as moment#day except
// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
// as a setter, sunday should belong to the previous week.
if(null!=a){var b=Da(a,this.localeData());return this.day(this.day()%7?b:b-7)}return this.day()||7}function Ma(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysStrictRegex:this._weekdaysRegex):(h(this,"_weekdaysRegex")||(this._weekdaysRegex=pe),this._weekdaysStrictRegex&&a?this._weekdaysStrictRegex:this._weekdaysRegex)}function Na(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(h(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=qe),this._weekdaysShortStrictRegex&&a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Oa(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(h(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=re),this._weekdaysMinStrictRegex&&a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Pa(){function a(a,b){return b.length-a.length}var b,c,d,e,f,g=[],h=[],i=[],k=[];for(b=0;b<7;b++)
// make the regex if we don't have it already
c=j([2e3,1]).day(b),d=this.weekdaysMin(c,""),e=this.weekdaysShort(c,""),f=this.weekdays(c,""),g.push(d),h.push(e),i.push(f),k.push(d),k.push(e),k.push(f);for(
// Sorting makes sure if one weekday (or abbr) is a prefix of another it
// will match the longer piece.
g.sort(a),h.sort(a),i.sort(a),k.sort(a),b=0;b<7;b++)h[b]=_(h[b]),i[b]=_(i[b]),k[b]=_(k[b]);this._weekdaysRegex=new RegExp("^("+k.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+g.join("|")+")","i")}
// FORMATTING
function Qa(){return this.hours()%12||12}function Ra(){return this.hours()||24}function Sa(a,b){T(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}
// PARSING
function Ta(a,b){return b._meridiemParse}
// LOCALES
function Ua(a){
// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
// Using charAt should be more compatible.
return"p"===(a+"").toLowerCase().charAt(0)}function Va(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Wa(a){return a?a.toLowerCase().replace("_","-"):a}
// pick the locale from the array
// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
function Xa(a){for(var b,c,d,e,f=0;f<a.length;){for(e=Wa(a[f]).split("-"),b=e.length,c=Wa(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=Ya(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&u(e,c,!0)>=b-1)
//the next array item is better than a shallower substring of this one
break;b--}f++}return null}function Ya(a){var b=null;
// TODO: Find a better way to register and load all the locales in Node
if(!we[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=se._abbr,require("./locale/"+a),
// because defineLocale currently also sets the global locale, we
// want to undo that for lazy loaded locales
Za(b)}catch(a){}return we[a]}
// This function will load locale and then set the global locale. If
// no arguments are passed in, it will simply return the current global
// locale key.
function Za(a,b){var c;
// moment.duration._locale = moment._locale = data;
return a&&(c=o(b)?ab(a):$a(a,b),c&&(se=c)),se._abbr}function $a(a,b){if(null!==b){var c=ve;
// treat as if there is no base config
// backwards compat for now: also set the locale
return b.abbr=a,null!=we[a]?(x("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),c=we[a]._config):null!=b.parentLocale&&(null!=we[b.parentLocale]?c=we[b.parentLocale]._config:x("parentLocaleUndefined","specified parentLocale is not defined yet. See http://momentjs.com/guides/#/warnings/parent-locale/")),we[a]=new B(A(c,b)),Za(a),we[a]}
// useful for testing
return delete we[a],null}function _a(a,b){if(null!=b){var c,d=ve;
// MERGE
null!=we[a]&&(d=we[a]._config),b=A(d,b),c=new B(b),c.parentLocale=we[a],we[a]=c,
// backwards compat for now: also set the locale
Za(a)}else
// pass null for config to unupdate, useful for tests
null!=we[a]&&(null!=we[a].parentLocale?we[a]=we[a].parentLocale:null!=we[a]&&delete we[a]);return we[a]}
// returns locale data
function ab(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return se;if(!c(a)){if(
//short-circuit everything else
b=Ya(a))return b;a=[a]}return Xa(a)}function bb(){return rd(we)}function cb(a){var b,c=a._a;return c&&l(a).overflow===-2&&(b=c[Zd]<0||c[Zd]>11?Zd:c[$d]<1||c[$d]>da(c[Yd],c[Zd])?$d:c[_d]<0||c[_d]>24||24===c[_d]&&(0!==c[ae]||0!==c[be]||0!==c[ce])?_d:c[ae]<0||c[ae]>59?ae:c[be]<0||c[be]>59?be:c[ce]<0||c[ce]>999?ce:-1,l(a)._overflowDayOfYear&&(b<Yd||b>$d)&&(b=$d),l(a)._overflowWeeks&&b===-1&&(b=de),l(a)._overflowWeekday&&b===-1&&(b=ee),l(a).overflow=b),a}
// date from iso format
function db(a){var b,c,d,e,f,g,h=a._i,i=xe.exec(h)||ye.exec(h);if(i){for(l(a).iso=!0,b=0,c=Ae.length;b<c;b++)if(Ae[b][1].exec(i[1])){e=Ae[b][0],d=Ae[b][2]!==!1;break}if(null==e)return void(a._isValid=!1);if(i[3]){for(b=0,c=Be.length;b<c;b++)if(Be[b][1].exec(i[3])){
// match[2] should be 'T' or space
f=(i[2]||" ")+Be[b][0];break}if(null==f)return void(a._isValid=!1)}if(!d&&null!=f)return void(a._isValid=!1);if(i[4]){if(!ze.exec(i[4]))return void(a._isValid=!1);g="Z"}a._f=e+(f||"")+(g||""),jb(a)}else a._isValid=!1}
// date from iso format or fallback
function eb(b){var c=Ce.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(db(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}
// Pick the first defined of two or three arguments.
function fb(a,b,c){return null!=a?a:null!=b?b:c}function gb(b){
// hooks is actually the exported moment object
var c=new Date(a.now());return b._useUTC?[c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()]:[c.getFullYear(),c.getMonth(),c.getDate()]}
// convert an array to a date.
// the array should mirror the parameters below
// note: all values past the year are optional and will default to the lowest possible value.
// [year, month, day , hour, minute, second, millisecond]
function hb(a){var b,c,d,e,f=[];if(!a._d){
// Default to current date.
// * if no year, month, day of month are given, default to today
// * if day of month is given, default month and year
// * if month is given, default only year
// * if year is given, don't default anything
for(d=gb(a),
//compute day of the year from weeks and weekdays
a._w&&null==a._a[$d]&&null==a._a[Zd]&&ib(a),
//if the day of the year is set, figure out what it is
a._dayOfYear&&(e=fb(a._a[Yd],d[Yd]),a._dayOfYear>oa(e)&&(l(a)._overflowDayOfYear=!0),c=sa(e,0,a._dayOfYear),a._a[Zd]=c.getUTCMonth(),a._a[$d]=c.getUTCDate()),b=0;b<3&&null==a._a[b];++b)a._a[b]=f[b]=d[b];
// Zero out whatever was not defaulted, including time
for(;b<7;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];
// Check for 24:00:00.000
24===a._a[_d]&&0===a._a[ae]&&0===a._a[be]&&0===a._a[ce]&&(a._nextDay=!0,a._a[_d]=0),a._d=(a._useUTC?sa:ra).apply(null,f),
// Apply timezone offset from input. The actual utcOffset can be changed
// with parseZone.
null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[_d]=24)}}function ib(a){var b,c,d,e,f,g,h,i;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,
// TODO: We need to take the current isoWeekYear, but that depends on
// how we interpret now (local, utc, fixed offset). So create
// a now version of current config (take local/utc/offset flags, and
// create now).
c=fb(b.GG,a._a[Yd],va(rb(),1,4).year),d=fb(b.W,1),e=fb(b.E,1),(e<1||e>7)&&(i=!0)):(f=a._locale._week.dow,g=a._locale._week.doy,c=fb(b.gg,a._a[Yd],va(rb(),f,g).year),d=fb(b.w,1),null!=b.d?(
// weekday -- low day numbers are considered next week
e=b.d,(e<0||e>6)&&(i=!0)):null!=b.e?(
// local weekday -- counting starts from begining of week
e=b.e+f,(b.e<0||b.e>6)&&(i=!0)):
// default to begining of week
e=f),d<1||d>wa(c,f,g)?l(a)._overflowWeeks=!0:null!=i?l(a)._overflowWeekday=!0:(h=ua(c,d,e,f,g),a._a[Yd]=h.year,a._dayOfYear=h.dayOfYear)}
// date from string and format string
function jb(b){
// TODO: Move this to another part of the creation flow to prevent circular deps
if(b._f===a.ISO_8601)return void db(b);b._a=[],l(b).empty=!0;
// This array is used to make a Date, either with `new Date` or `Date.UTC`
var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=X(b._f,b._locale).match(Bd)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(Z(f,b))||[])[0],
// console.log('token', token, 'parsedInput', parsedInput,
// 'regex', getParseRegexForToken(token, config));
d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&l(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),
// don't parse if it's not a known token
Ed[f]?(d?l(b).empty=!1:l(b).unusedTokens.push(f),ca(f,d,b)):b._strict&&!d&&l(b).unusedTokens.push(f);
// add remaining unparsed input length to the string
l(b).charsLeftOver=i-j,h.length>0&&l(b).unusedInput.push(h),
// clear _12h flag if hour is <= 12
b._a[_d]<=12&&l(b).bigHour===!0&&b._a[_d]>0&&(l(b).bigHour=void 0),l(b).parsedDateParts=b._a.slice(0),l(b).meridiem=b._meridiem,
// handle meridiem
b._a[_d]=kb(b._locale,b._a[_d],b._meridiem),hb(b),cb(b)}function kb(a,b,c){var d;
// Fallback
return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&b<12&&(b+=12),d||12!==b||(b=0),b):b}
// date from string and array of format strings
function lb(a){var b,c,d,e,f;if(0===a._f.length)return l(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=p({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],jb(b),m(b)&&(
// if there is any input that was not parsed add a penalty for that format
f+=l(b).charsLeftOver,
//or tokens
f+=10*l(b).unusedTokens.length,l(b).score=f,(null==d||f<d)&&(d=f,c=b));i(a,c||b)}function mb(a){if(!a._d){var b=K(a._i);a._a=g([b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],function(a){return a&&parseInt(a,10)}),hb(a)}}function nb(a){var b=new q(cb(ob(a)));
// Adding is smart enough around DST
return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function ob(a){var b=a._i,d=a._f;return a._locale=a._locale||ab(a._l),null===b||void 0===d&&""===b?n({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),r(b)?new q(cb(b)):(c(d)?lb(a):f(b)?a._d=b:d?jb(a):pb(a),m(a)||(a._d=null),a))}function pb(b){var d=b._i;void 0===d?b._d=new Date(a.now()):f(d)?b._d=new Date(d.valueOf()):"string"==typeof d?eb(b):c(d)?(b._a=g(d.slice(0),function(a){return parseInt(a,10)}),hb(b)):"object"==typeof d?mb(b):"number"==typeof d?
// from milliseconds
b._d=new Date(d):a.createFromInputFallback(b)}function qb(a,b,f,g,h){var i={};
// object construction must be done this way.
// https://github.com/moment/moment/issues/1423
return"boolean"==typeof f&&(g=f,f=void 0),(d(a)&&e(a)||c(a)&&0===a.length)&&(a=void 0),i._isAMomentObject=!0,i._useUTC=i._isUTC=h,i._l=f,i._i=a,i._f=b,i._strict=g,nb(i)}function rb(a,b,c,d){return qb(a,b,c,d,!1)}
// Pick a moment m from moments so that m[fn](other) is true for all
// other. This relies on the function fn to be transitive.
//
// moments should either be an array of moment objects or an array, whose
// first element is an array of moment objects.
function sb(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return rb();for(d=b[0],e=1;e<b.length;++e)b[e].isValid()&&!b[e][a](d)||(d=b[e]);return d}
// TODO: Use [].sort instead?
function tb(){var a=[].slice.call(arguments,0);return sb("isBefore",a)}function ub(){var a=[].slice.call(arguments,0);return sb("isAfter",a)}function vb(a){var b=K(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;
// representation for dateAddRemove
this._milliseconds=+k+1e3*j+// 1000
6e4*i+// 1000 * 60
1e3*h*60*60,//using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
// Because of dateAddRemove treats 24 hours as different from a
// day when working around DST, we need to store them separately
this._days=+g+7*f,
// It is impossible translate months into days without knowing
// which months you are are talking about, so we have to store
// it separately.
this._months=+e+3*d+12*c,this._data={},this._locale=ab(),this._bubble()}function wb(a){return a instanceof vb}function xb(a){return a<0?Math.round(-1*a)*-1:Math.round(a)}
// FORMATTING
function yb(a,b){T(a,0,0,function(){var a=this.utcOffset(),c="+";return a<0&&(a=-a,c="-"),c+S(~~(a/60),2)+b+S(~~a%60,2)})}function zb(a,b){var c=(b||"").match(a)||[],d=c[c.length-1]||[],e=(d+"").match(Ge)||["-",0,0],f=+(60*e[1])+t(e[2]);return"+"===e[0]?f:-f}
// Return a moment from input, that is local/utc/zone equivalent to model.
function Ab(b,c){var d,e;
// Use low-level api, because this fn is low-level api.
return c._isUTC?(d=c.clone(),e=(r(b)||f(b)?b.valueOf():rb(b).valueOf())-d.valueOf(),d._d.setTime(d._d.valueOf()+e),a.updateOffset(d,!1),d):rb(b).local()}function Bb(a){
// On Firefox.24 Date#getTimezoneOffset returns a floating point.
// https://github.com/moment/moment/pull/1871
return 15*-Math.round(a._d.getTimezoneOffset()/15)}
// MOMENTS
// keepLocalTime = true means only change the timezone, without
// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
// +0200, so we adjust the time as needed, to be valid.
//
// Keeping the time actually adds/subtracts (one hour)
// from the actual represented time. That is why we call updateOffset
// a second time. In case it wants us to change the offset again
// _changeInProgress == true case, then we have to adjust, because
// there is no such time in the given timezone.
function Cb(b,c){var d,e=this._offset||0;return this.isValid()?null!=b?("string"==typeof b?b=zb(Td,b):Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Bb(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?Sb(this,Nb(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Bb(this):null!=b?this:NaN}function Db(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Eb(a){return this.utcOffset(0,a)}function Fb(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Bb(this),"m")),this}function Gb(){if(this._tzm)this.utcOffset(this._tzm);else if("string"==typeof this._i){var a=zb(Sd,this._i);0===a?this.utcOffset(0,!0):this.utcOffset(zb(Sd,this._i))}return this}function Hb(a){return!!this.isValid()&&(a=a?rb(a).utcOffset():0,(this.utcOffset()-a)%60===0)}function Ib(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Jb(){if(!o(this._isDSTShifted))return this._isDSTShifted;var a={};if(p(a,this),a=ob(a),a._a){var b=a._isUTC?j(a._a):rb(a._a);this._isDSTShifted=this.isValid()&&u(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Kb(){return!!this.isValid()&&!this._isUTC}function Lb(){return!!this.isValid()&&this._isUTC}function Mb(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function Nb(a,b){var c,d,e,f=a,
// matching against regexp is expensive, do it on demand
g=null;// checks for null or undefined
return wb(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(g=He.exec(a))?(c="-"===g[1]?-1:1,f={y:0,d:t(g[$d])*c,h:t(g[_d])*c,m:t(g[ae])*c,s:t(g[be])*c,ms:t(xb(1e3*g[ce]))*c}):(g=Ie.exec(a))?(c="-"===g[1]?-1:1,f={y:Ob(g[2],c),M:Ob(g[3],c),w:Ob(g[4],c),d:Ob(g[5],c),h:Ob(g[6],c),m:Ob(g[7],c),s:Ob(g[8],c)}):null==f?f={}:"object"==typeof f&&("from"in f||"to"in f)&&(e=Qb(rb(f.from),rb(f.to)),f={},f.ms=e.milliseconds,f.M=e.months),d=new vb(f),wb(a)&&h(a,"_locale")&&(d._locale=a._locale),d}function Ob(a,b){
// We'd normally use ~~inp for this, but unfortunately it also
// converts floats to ints.
// inp may be undefined, so careful calling replace on it.
var c=a&&parseFloat(a.replace(",","."));
// apply sign while we're at it
return(isNaN(c)?0:c)*b}function Pb(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Qb(a,b){var c;return a.isValid()&&b.isValid()?(b=Ab(b,a),a.isBefore(b)?c=Pb(a,b):(c=Pb(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}
// TODO: remove 'name' arg after deprecation is removed
function Rb(a,b){return function(c,d){var e,f;
//invert the arguments, but complain about it
return null===d||isNaN(+d)||(x(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Nb(c,d),Sb(this,e,a),this}}function Sb(b,c,d,e){var f=c._milliseconds,g=xb(c._days),h=xb(c._months);b.isValid()&&(e=null==e||e,f&&b._d.setTime(b._d.valueOf()+f*d),g&&P(b,"Date",O(b,"Date")+g*d),h&&ia(b,O(b,"Month")+h*d),e&&a.updateOffset(b,g||h))}function Tb(a,b){var c=a.diff(b,"days",!0);return c<-6?"sameElse":c<-1?"lastWeek":c<0?"lastDay":c<1?"sameDay":c<2?"nextDay":c<7?"nextWeek":"sameElse"}function Ub(b,c){
// We want to compare the start of today, vs this.
// Getting start-of-today depends on whether we're local/utc/offset or not.
var d=b||rb(),e=Ab(d,this).startOf("day"),f=a.calendarFormat(this,e)||"sameElse",g=c&&(y(c[f])?c[f].call(this,d):c[f]);return this.format(g||this.localeData().calendar(f,this,rb(d)))}function Vb(){return new q(this)}function Wb(a,b){var c=r(a)?a:rb(a);return!(!this.isValid()||!c.isValid())&&(b=J(o(b)?"millisecond":b),"millisecond"===b?this.valueOf()>c.valueOf():c.valueOf()<this.clone().startOf(b).valueOf())}function Xb(a,b){var c=r(a)?a:rb(a);return!(!this.isValid()||!c.isValid())&&(b=J(o(b)?"millisecond":b),"millisecond"===b?this.valueOf()<c.valueOf():this.clone().endOf(b).valueOf()<c.valueOf())}function Yb(a,b,c,d){return d=d||"()",("("===d[0]?this.isAfter(a,c):!this.isBefore(a,c))&&(")"===d[1]?this.isBefore(b,c):!this.isAfter(b,c))}function Zb(a,b){var c,d=r(a)?a:rb(a);return!(!this.isValid()||!d.isValid())&&(b=J(b||"millisecond"),"millisecond"===b?this.valueOf()===d.valueOf():(c=d.valueOf(),this.clone().startOf(b).valueOf()<=c&&c<=this.clone().endOf(b).valueOf()))}function $b(a,b){return this.isSame(a,b)||this.isAfter(a,b)}function _b(a,b){return this.isSame(a,b)||this.isBefore(a,b)}function ac(a,b,c){var d,e,f,g;// 1000
// 1000 * 60
// 1000 * 60 * 60
// 1000 * 60 * 60 * 24, negate dst
// 1000 * 60 * 60 * 24 * 7, negate dst
return this.isValid()?(d=Ab(a,this),d.isValid()?(e=6e4*(d.utcOffset()-this.utcOffset()),b=J(b),"year"===b||"month"===b||"quarter"===b?(g=bc(this,d),"quarter"===b?g/=3:"year"===b&&(g/=12)):(f=this-d,g="second"===b?f/1e3:"minute"===b?f/6e4:"hour"===b?f/36e5:"day"===b?(f-e)/864e5:"week"===b?(f-e)/6048e5:f),c?g:s(g)):NaN):NaN}function bc(a,b){
// difference in months
var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),
// b is in (anchor - 1 month, anchor + 1 month)
f=a.clone().add(e,"months");
//check for negative zero, return zero if negative zero
// linear across the month
// linear across the month
return b-f<0?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)||0}function cc(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function dc(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?y(Date.prototype.toISOString)?this.toDate().toISOString():W(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):W(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function ec(b){b||(b=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var c=W(this,b);return this.localeData().postformat(c)}function fc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isValid())?Nb({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function gc(a){return this.from(rb(),a)}function hc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isValid())?Nb({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function ic(a){return this.to(rb(),a)}
// If passed a locale key, it will set the locale for this
// instance. Otherwise, it will return the locale configuration
// variables for this instance.
function jc(a){var b;return void 0===a?this._locale._abbr:(b=ab(a),null!=b&&(this._locale=b),this)}function kc(){return this._locale}function lc(a){
// the following switch intentionally omits break keywords
// to utilize falling through the cases.
switch(a=J(a)){case"year":this.month(0);/* falls through */
case"quarter":case"month":this.date(1);/* falls through */
case"week":case"isoWeek":case"day":case"date":this.hours(0);/* falls through */
case"hour":this.minutes(0);/* falls through */
case"minute":this.seconds(0);/* falls through */
case"second":this.milliseconds(0)}
// weeks are a special case
// quarters are also special
return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function mc(a){
// 'date' is an alias for 'day', so it should be considered as such.
return a=J(a),void 0===a||"millisecond"===a?this:("date"===a&&(a="day"),this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms"))}function nc(){return this._d.valueOf()-6e4*(this._offset||0)}function oc(){return Math.floor(this.valueOf()/1e3)}function pc(){return new Date(this.valueOf())}function qc(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function rc(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function sc(){
// new Date(NaN).toJSON() === null
return this.isValid()?this.toISOString():null}function tc(){return m(this)}function uc(){return i({},l(this))}function vc(){return l(this).overflow}function wc(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function xc(a,b){T(0,[a,a.length],0,b)}
// MOMENTS
function yc(a){return Cc.call(this,a,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function zc(a){return Cc.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}function Ac(){return wa(this.year(),1,4)}function Bc(){var a=this.localeData()._week;return wa(this.year(),a.dow,a.doy)}function Cc(a,b,c,d,e){var f;return null==a?va(this,d,e).year:(f=wa(a,d,e),b>f&&(b=f),Dc.call(this,a,b,c,d,e))}function Dc(a,b,c,d,e){var f=ua(a,b,c,d,e),g=sa(f.year,0,f.dayOfYear);return this.year(g.getUTCFullYear()),this.month(g.getUTCMonth()),this.date(g.getUTCDate()),this}
// MOMENTS
function Ec(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}
// HELPERS
// MOMENTS
function Fc(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function Gc(a,b){b[ce]=t(1e3*("0."+a))}
// MOMENTS
function Hc(){return this._isUTC?"UTC":""}function Ic(){return this._isUTC?"Coordinated Universal Time":""}function Jc(a){return rb(1e3*a)}function Kc(){return rb.apply(null,arguments).parseZone()}function Lc(a){return a}function Mc(a,b,c,d){var e=ab(),f=j().set(d,b);return e[c](f,a)}function Nc(a,b,c){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return Mc(a,b,c,"month");var d,e=[];for(d=0;d<12;d++)e[d]=Mc(a,d,c,"month");return e}
// ()
// (5)
// (fmt, 5)
// (fmt)
// (true)
// (true, 5)
// (true, fmt, 5)
// (true, fmt)
function Oc(a,b,c,d){"boolean"==typeof a?("number"==typeof b&&(c=b,b=void 0),b=b||""):(b=a,c=b,a=!1,"number"==typeof b&&(c=b,b=void 0),b=b||"");var e=ab(),f=a?e._week.dow:0;if(null!=c)return Mc(b,(c+f)%7,d,"day");var g,h=[];for(g=0;g<7;g++)h[g]=Mc(b,(g+f)%7,d,"day");return h}function Pc(a,b){return Nc(a,b,"months")}function Qc(a,b){return Nc(a,b,"monthsShort")}function Rc(a,b,c){return Oc(a,b,c,"weekdays")}function Sc(a,b,c){return Oc(a,b,c,"weekdaysShort")}function Tc(a,b,c){return Oc(a,b,c,"weekdaysMin")}function Uc(){var a=this._data;return this._milliseconds=Ue(this._milliseconds),this._days=Ue(this._days),this._months=Ue(this._months),a.milliseconds=Ue(a.milliseconds),a.seconds=Ue(a.seconds),a.minutes=Ue(a.minutes),a.hours=Ue(a.hours),a.months=Ue(a.months),a.years=Ue(a.years),this}function Vc(a,b,c,d){var e=Nb(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}
// supports only 2.0-style add(1, 's') or add(duration)
function Wc(a,b){return Vc(this,a,b,1)}
// supports only 2.0-style subtract(1, 's') or subtract(duration)
function Xc(a,b){return Vc(this,a,b,-1)}function Yc(a){return a<0?Math.floor(a):Math.ceil(a)}function Zc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;
// if we have a mix of positive and negative values, bubble down first
// check: https://github.com/moment/moment/issues/2166
// The following code bubbles up values, see the tests for
// examples of what that means.
// convert days to months
// 12 months -> 1 year
return f>=0&&g>=0&&h>=0||f<=0&&g<=0&&h<=0||(f+=864e5*Yc(_c(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=s(f/1e3),i.seconds=a%60,b=s(a/60),i.minutes=b%60,c=s(b/60),i.hours=c%24,g+=s(c/24),e=s($c(g)),h+=e,g-=Yc(_c(e)),d=s(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function $c(a){
// 400 years have 146097 days (taking into account leap year rules)
// 400 years have 12 months === 4800
return 4800*a/146097}function _c(a){
// the reverse of daysToMonths
return 146097*a/4800}function ad(a){var b,c,d=this._milliseconds;if(a=J(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+$c(b),"month"===a?c:c/12;switch(
// handle milliseconds separately because of floating point math errors (issue #1867)
b=this._days+Math.round(_c(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;
// Math.floor prevents floating point math errors here
case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}
// TODO: Use this.as('ms')?
function bd(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*t(this._months/12)}function cd(a){return function(){return this.as(a)}}function dd(a){return a=J(a),this[a+"s"]()}function ed(a){return function(){return this._data[a]}}function fd(){return s(this.days()/7)}
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
function gd(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function hd(a,b,c){var d=Nb(a).abs(),e=jf(d.as("s")),f=jf(d.as("m")),g=jf(d.as("h")),h=jf(d.as("d")),i=jf(d.as("M")),j=jf(d.as("y")),k=e<kf.s&&["s",e]||f<=1&&["m"]||f<kf.m&&["mm",f]||g<=1&&["h"]||g<kf.h&&["hh",g]||h<=1&&["d"]||h<kf.d&&["dd",h]||i<=1&&["M"]||i<kf.M&&["MM",i]||j<=1&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,gd.apply(null,k)}
// This function allows you to set the rounding function for relative time strings
function id(a){return void 0===a?jf:"function"==typeof a&&(jf=a,!0)}
// This function allows you to set a threshold for relative time strings
function jd(a,b){return void 0!==kf[a]&&(void 0===b?kf[a]:(kf[a]=b,!0))}function kd(a){var b=this.localeData(),c=hd(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function ld(){
// for ISO strings we do not use the normal bubbling rules:
// * milliseconds bubble up until they become hours
// * days do not bubble at all
// * months bubble up until they become years
// This is because there is no context-free conversion between hours and days
// (think of clock changes)
// and also not between days and months (28-31 days per month)
var a,b,c,d=lf(this._milliseconds)/1e3,e=lf(this._days),f=lf(this._months);
// 3600 seconds -> 60 minutes -> 1 hour
a=s(d/60),b=s(a/60),d%=60,a%=60,
// 12 months -> 1 year
c=s(f/12),f%=12;
// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(m<0?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var md,nd;nd=Array.prototype.some?Array.prototype.some:function(a){for(var b=Object(this),c=b.length>>>0,d=0;d<c;d++)if(d in b&&a.call(this,b[d],d,b))return!0;return!1};
// Plugins that add properties should also add the key here (null value),
// so we can properly clone ourselves.
var od=a.momentProperties=[],pd=!1,qd={};a.suppressDeprecationWarnings=!1,a.deprecationHandler=null;var rd;rd=Object.keys?Object.keys:function(a){var b,c=[];for(b in a)h(a,b)&&c.push(b);return c};var sd,td={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},ud={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},vd="Invalid date",wd="%d",xd=/\d{1,2}/,yd={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},zd={},Ad={},Bd=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Cd=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Dd={},Ed={},Fd=/\d/,Gd=/\d\d/,Hd=/\d{3}/,Id=/\d{4}/,Jd=/[+-]?\d{6}/,Kd=/\d\d?/,Ld=/\d\d\d\d?/,Md=/\d\d\d\d\d\d?/,Nd=/\d{1,3}/,Od=/\d{1,4}/,Pd=/[+-]?\d{1,6}/,Qd=/\d+/,Rd=/[+-]?\d+/,Sd=/Z|[+-]\d\d:?\d\d/gi,Td=/Z|[+-]\d\d(?::?\d\d)?/gi,Ud=/[+-]?\d+(\.\d{1,3})?/,Vd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Wd={},Xd={},Yd=0,Zd=1,$d=2,_d=3,ae=4,be=5,ce=6,de=7,ee=8;sd=Array.prototype.indexOf?Array.prototype.indexOf:function(a){
// I know
var b;for(b=0;b<this.length;++b)if(this[b]===a)return b;return-1},
// FORMATTING
T("M",["MM",2],"Mo",function(){return this.month()+1}),T("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),T("MMMM",0,0,function(a){return this.localeData().months(this,a)}),
// ALIASES
I("month","M"),
// PRIORITY
L("month",8),
// PARSING
Y("M",Kd),Y("MM",Kd,Gd),Y("MMM",function(a,b){return b.monthsShortRegex(a)}),Y("MMMM",function(a,b){return b.monthsRegex(a)}),aa(["M","MM"],function(a,b){b[Zd]=t(a)-1}),aa(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);
// if we didn't find a month name, mark the date as invalid.
null!=e?b[Zd]=e:l(c).invalidMonth=a});
// LOCALES
var fe=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,ge="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),he="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),ie=Vd,je=Vd;
// FORMATTING
T("Y",0,0,function(){var a=this.year();return a<=9999?""+a:"+"+a}),T(0,["YY",2],0,function(){return this.year()%100}),T(0,["YYYY",4],0,"year"),T(0,["YYYYY",5],0,"year"),T(0,["YYYYYY",6,!0],0,"year"),
// ALIASES
I("year","y"),
// PRIORITIES
L("year",1),
// PARSING
Y("Y",Rd),Y("YY",Kd,Gd),Y("YYYY",Od,Id),Y("YYYYY",Pd,Jd),Y("YYYYYY",Pd,Jd),aa(["YYYYY","YYYYYY"],Yd),aa("YYYY",function(b,c){c[Yd]=2===b.length?a.parseTwoDigitYear(b):t(b)}),aa("YY",function(b,c){c[Yd]=a.parseTwoDigitYear(b)}),aa("Y",function(a,b){b[Yd]=parseInt(a,10)}),
// HOOKS
a.parseTwoDigitYear=function(a){return t(a)+(t(a)>68?1900:2e3)};
// MOMENTS
var ke=N("FullYear",!0);
// FORMATTING
T("w",["ww",2],"wo","week"),T("W",["WW",2],"Wo","isoWeek"),
// ALIASES
I("week","w"),I("isoWeek","W"),
// PRIORITIES
L("week",5),L("isoWeek",5),
// PARSING
Y("w",Kd),Y("ww",Kd,Gd),Y("W",Kd),Y("WW",Kd,Gd),ba(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=t(a)});var le={dow:0,// Sunday is the first day of the week.
doy:6};
// FORMATTING
T("d",0,"do","day"),T("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),T("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),T("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),T("e",0,0,"weekday"),T("E",0,0,"isoWeekday"),
// ALIASES
I("day","d"),I("weekday","e"),I("isoWeekday","E"),
// PRIORITY
L("day",11),L("weekday",11),L("isoWeekday",11),
// PARSING
Y("d",Kd),Y("e",Kd),Y("E",Kd),Y("dd",function(a,b){return b.weekdaysMinRegex(a)}),Y("ddd",function(a,b){return b.weekdaysShortRegex(a)}),Y("dddd",function(a,b){return b.weekdaysRegex(a)}),ba(["dd","ddd","dddd"],function(a,b,c,d){var e=c._locale.weekdaysParse(a,d,c._strict);
// if we didn't get a weekday name, mark the date as invalid
null!=e?b.d=e:l(c).invalidWeekday=a}),ba(["d","e","E"],function(a,b,c,d){b[d]=t(a)});
// LOCALES
var me="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),ne="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),oe="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),pe=Vd,qe=Vd,re=Vd;T("H",["HH",2],0,"hour"),T("h",["hh",2],0,Qa),T("k",["kk",2],0,Ra),T("hmm",0,0,function(){return""+Qa.apply(this)+S(this.minutes(),2)}),T("hmmss",0,0,function(){return""+Qa.apply(this)+S(this.minutes(),2)+S(this.seconds(),2)}),T("Hmm",0,0,function(){return""+this.hours()+S(this.minutes(),2)}),T("Hmmss",0,0,function(){return""+this.hours()+S(this.minutes(),2)+S(this.seconds(),2)}),Sa("a",!0),Sa("A",!1),
// ALIASES
I("hour","h"),
// PRIORITY
L("hour",13),Y("a",Ta),Y("A",Ta),Y("H",Kd),Y("h",Kd),Y("HH",Kd,Gd),Y("hh",Kd,Gd),Y("hmm",Ld),Y("hmmss",Md),Y("Hmm",Ld),Y("Hmmss",Md),aa(["H","HH"],_d),aa(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),aa(["h","hh"],function(a,b,c){b[_d]=t(a),l(c).bigHour=!0}),aa("hmm",function(a,b,c){var d=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d)),l(c).bigHour=!0}),aa("hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d,2)),b[be]=t(a.substr(e)),l(c).bigHour=!0}),aa("Hmm",function(a,b,c){var d=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d))}),aa("Hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d,2)),b[be]=t(a.substr(e))});var se,te=/[ap]\.?m?\.?/i,ue=N("Hours",!0),ve={calendar:td,longDateFormat:ud,invalidDate:vd,ordinal:wd,ordinalParse:xd,relativeTime:yd,months:ge,monthsShort:he,week:le,weekdays:me,weekdaysMin:oe,weekdaysShort:ne,meridiemParse:te},we={},xe=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,ye=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,ze=/Z|[+-]\d\d(?::?\d\d)?/,Ae=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],
// YYYYMM is NOT allowed by the standard
["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Be=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Ce=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=w("value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),
// constant that refers to the ISO standard
a.ISO_8601=function(){};var De=w("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=rb.apply(null,arguments);return this.isValid()&&a.isValid()?a<this?this:a:n()}),Ee=w("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=rb.apply(null,arguments);return this.isValid()&&a.isValid()?a>this?this:a:n()}),Fe=function(){return Date.now?Date.now():+new Date};yb("Z",":"),yb("ZZ",""),
// PARSING
Y("Z",Td),Y("ZZ",Td),aa(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=zb(Td,a)});
// HELPERS
// timezone chunker
// '+10:00' > ['10', '00']
// '-1530' > ['-15', '30']
var Ge=/([\+\-]|\d\d)/gi;
// HOOKS
// This function will be called whenever a moment is mutated.
// It is intended to keep the offset in sync with the timezone.
a.updateOffset=function(){};
// ASP.NET json date format regex
var He=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Ie=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Nb.fn=vb.prototype;var Je=Rb(1,"add"),Ke=Rb(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Le=w("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});
// FORMATTING
T(0,["gg",2],0,function(){return this.weekYear()%100}),T(0,["GG",2],0,function(){return this.isoWeekYear()%100}),xc("gggg","weekYear"),xc("ggggg","weekYear"),xc("GGGG","isoWeekYear"),xc("GGGGG","isoWeekYear"),
// ALIASES
I("weekYear","gg"),I("isoWeekYear","GG"),
// PRIORITY
L("weekYear",1),L("isoWeekYear",1),
// PARSING
Y("G",Rd),Y("g",Rd),Y("GG",Kd,Gd),Y("gg",Kd,Gd),Y("GGGG",Od,Id),Y("gggg",Od,Id),Y("GGGGG",Pd,Jd),Y("ggggg",Pd,Jd),ba(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=t(a)}),ba(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),
// FORMATTING
T("Q",0,"Qo","quarter"),
// ALIASES
I("quarter","Q"),
// PRIORITY
L("quarter",7),
// PARSING
Y("Q",Fd),aa("Q",function(a,b){b[Zd]=3*(t(a)-1)}),
// FORMATTING
T("D",["DD",2],"Do","date"),
// ALIASES
I("date","D"),
// PRIOROITY
L("date",9),
// PARSING
Y("D",Kd),Y("DD",Kd,Gd),Y("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),aa(["D","DD"],$d),aa("Do",function(a,b){b[$d]=t(a.match(Kd)[0],10)});
// MOMENTS
var Me=N("Date",!0);
// FORMATTING
T("DDD",["DDDD",3],"DDDo","dayOfYear"),
// ALIASES
I("dayOfYear","DDD"),
// PRIORITY
L("dayOfYear",4),
// PARSING
Y("DDD",Nd),Y("DDDD",Hd),aa(["DDD","DDDD"],function(a,b,c){c._dayOfYear=t(a)}),
// FORMATTING
T("m",["mm",2],0,"minute"),
// ALIASES
I("minute","m"),
// PRIORITY
L("minute",14),
// PARSING
Y("m",Kd),Y("mm",Kd,Gd),aa(["m","mm"],ae);
// MOMENTS
var Ne=N("Minutes",!1);
// FORMATTING
T("s",["ss",2],0,"second"),
// ALIASES
I("second","s"),
// PRIORITY
L("second",15),
// PARSING
Y("s",Kd),Y("ss",Kd,Gd),aa(["s","ss"],be);
// MOMENTS
var Oe=N("Seconds",!1);
// FORMATTING
T("S",0,0,function(){return~~(this.millisecond()/100)}),T(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),T(0,["SSS",3],0,"millisecond"),T(0,["SSSS",4],0,function(){return 10*this.millisecond()}),T(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),T(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),T(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),T(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),T(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),
// ALIASES
I("millisecond","ms"),
// PRIORITY
L("millisecond",16),
// PARSING
Y("S",Nd,Fd),Y("SS",Nd,Gd),Y("SSS",Nd,Hd);var Pe;for(Pe="SSSS";Pe.length<=9;Pe+="S")Y(Pe,Qd);for(Pe="S";Pe.length<=9;Pe+="S")aa(Pe,Gc);
// MOMENTS
var Qe=N("Milliseconds",!1);
// FORMATTING
T("z",0,0,"zoneAbbr"),T("zz",0,0,"zoneName");var Re=q.prototype;Re.add=Je,Re.calendar=Ub,Re.clone=Vb,Re.diff=ac,Re.endOf=mc,Re.format=ec,Re.from=fc,Re.fromNow=gc,Re.to=hc,Re.toNow=ic,Re.get=Q,Re.invalidAt=vc,Re.isAfter=Wb,Re.isBefore=Xb,Re.isBetween=Yb,Re.isSame=Zb,Re.isSameOrAfter=$b,Re.isSameOrBefore=_b,Re.isValid=tc,Re.lang=Le,Re.locale=jc,Re.localeData=kc,Re.max=Ee,Re.min=De,Re.parsingFlags=uc,Re.set=R,Re.startOf=lc,Re.subtract=Ke,Re.toArray=qc,Re.toObject=rc,Re.toDate=pc,Re.toISOString=dc,Re.toJSON=sc,Re.toString=cc,Re.unix=oc,Re.valueOf=nc,Re.creationData=wc,
// Year
Re.year=ke,Re.isLeapYear=qa,
// Week Year
Re.weekYear=yc,Re.isoWeekYear=zc,
// Quarter
Re.quarter=Re.quarters=Ec,
// Month
Re.month=ja,Re.daysInMonth=ka,
// Week
Re.week=Re.weeks=Aa,Re.isoWeek=Re.isoWeeks=Ba,Re.weeksInYear=Bc,Re.isoWeeksInYear=Ac,
// Day
Re.date=Me,Re.day=Re.days=Ja,Re.weekday=Ka,Re.isoWeekday=La,Re.dayOfYear=Fc,
// Hour
Re.hour=Re.hours=ue,
// Minute
Re.minute=Re.minutes=Ne,
// Second
Re.second=Re.seconds=Oe,
// Millisecond
Re.millisecond=Re.milliseconds=Qe,
// Offset
Re.utcOffset=Cb,Re.utc=Eb,Re.local=Fb,Re.parseZone=Gb,Re.hasAlignedHourOffset=Hb,Re.isDST=Ib,Re.isLocal=Kb,Re.isUtcOffset=Lb,Re.isUtc=Mb,Re.isUTC=Mb,
// Timezone
Re.zoneAbbr=Hc,Re.zoneName=Ic,
// Deprecations
Re.dates=w("dates accessor is deprecated. Use date instead.",Me),Re.months=w("months accessor is deprecated. Use month instead",ja),Re.years=w("years accessor is deprecated. Use year instead",ke),Re.zone=w("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Db),Re.isDSTShifted=w("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Jb);var Se=Re,Te=B.prototype;Te.calendar=C,Te.longDateFormat=D,Te.invalidDate=E,Te.ordinal=F,Te.preparse=Lc,Te.postformat=Lc,Te.relativeTime=G,Te.pastFuture=H,Te.set=z,
// Month
Te.months=ea,Te.monthsShort=fa,Te.monthsParse=ha,Te.monthsRegex=ma,Te.monthsShortRegex=la,
// Week
Te.week=xa,Te.firstDayOfYear=za,Te.firstDayOfWeek=ya,
// Day of Week
Te.weekdays=Ea,Te.weekdaysMin=Ga,Te.weekdaysShort=Fa,Te.weekdaysParse=Ia,Te.weekdaysRegex=Ma,Te.weekdaysShortRegex=Na,Te.weekdaysMinRegex=Oa,
// Hours
Te.isPM=Ua,Te.meridiem=Va,Za("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===t(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),
// Side effect imports
a.lang=w("moment.lang is deprecated. Use moment.locale instead.",Za),a.langData=w("moment.langData is deprecated. Use moment.localeData instead.",ab);var Ue=Math.abs,Ve=cd("ms"),We=cd("s"),Xe=cd("m"),Ye=cd("h"),Ze=cd("d"),$e=cd("w"),_e=cd("M"),af=cd("y"),bf=ed("milliseconds"),cf=ed("seconds"),df=ed("minutes"),ef=ed("hours"),ff=ed("days"),gf=ed("months"),hf=ed("years"),jf=Math.round,kf={s:45,// seconds to minute
m:45,// minutes to hour
h:22,// hours to day
d:26,// days to month
M:11},lf=Math.abs,mf=vb.prototype;mf.abs=Uc,mf.add=Wc,mf.subtract=Xc,mf.as=ad,mf.asMilliseconds=Ve,mf.asSeconds=We,mf.asMinutes=Xe,mf.asHours=Ye,mf.asDays=Ze,mf.asWeeks=$e,mf.asMonths=_e,mf.asYears=af,mf.valueOf=bd,mf._bubble=Zc,mf.get=dd,mf.milliseconds=bf,mf.seconds=cf,mf.minutes=df,mf.hours=ef,mf.days=ff,mf.weeks=fd,mf.months=gf,mf.years=hf,mf.humanize=kd,mf.toISOString=ld,mf.toString=ld,mf.toJSON=ld,mf.locale=jc,mf.localeData=kc,
// Deprecations
mf.toIsoString=w("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ld),mf.lang=Le,
// Side effect imports
// FORMATTING
T("X",0,0,"unix"),T("x",0,0,"valueOf"),
// PARSING
Y("x",Rd),Y("X",Ud),aa("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),aa("x",function(a,b,c){c._d=new Date(t(a))}),
// Side effect imports
a.version="2.15.2",b(rb),a.fn=Se,a.min=tb,a.max=ub,a.now=Fe,a.utc=j,a.unix=Jc,a.months=Pc,a.isDate=f,a.locale=Za,a.invalid=n,a.duration=Nb,a.isMoment=r,a.weekdays=Rc,a.parseZone=Kc,a.localeData=ab,a.isDuration=wb,a.monthsShort=Qc,a.weekdaysMin=Tc,a.defineLocale=$a,a.updateLocale=_a,a.locales=bb,a.weekdaysShort=Sc,a.normalizeUnits=J,a.relativeTimeRounding=id,a.relativeTimeThreshold=jd,a.calendarFormat=Tb,a.prototype=Se;var nf=a;return nf});
+2
View File
@@ -0,0 +1,2 @@
// https://raw.githubusercontent.com/joewalnes/reconnecting-websocket/master/reconnecting-websocket.min.js
!function(a,b){"function"==typeof define&&define.amd?define([],b):"undefined"!=typeof module&&module.exports?module.exports=b():a.ReconnectingWebSocket=b()}(this,function(){function a(b,c,d){function l(a,b){var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!1,!1,b),c}var e={debug:!1,automaticOpen:!0,reconnectInterval:1e3,maxReconnectInterval:3e4,reconnectDecay:1.5,timeoutInterval:2e3};d||(d={});for(var f in e)this[f]="undefined"!=typeof d[f]?d[f]:e[f];this.url=b,this.reconnectAttempts=0,this.readyState=WebSocket.CONNECTING,this.protocol=null;var h,g=this,i=!1,j=!1,k=document.createElement("div");k.addEventListener("open",function(a){g.onopen(a)}),k.addEventListener("close",function(a){g.onclose(a)}),k.addEventListener("connecting",function(a){g.onconnecting(a)}),k.addEventListener("message",function(a){g.onmessage(a)}),k.addEventListener("error",function(a){g.onerror(a)}),this.addEventListener=k.addEventListener.bind(k),this.removeEventListener=k.removeEventListener.bind(k),this.dispatchEvent=k.dispatchEvent.bind(k),this.open=function(b){h=new WebSocket(g.url,c||[]),b||k.dispatchEvent(l("connecting")),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","attempt-connect",g.url);var d=h,e=setTimeout(function(){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","connection-timeout",g.url),j=!0,d.close(),j=!1},g.timeoutInterval);h.onopen=function(){clearTimeout(e),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onopen",g.url),g.protocol=h.protocol,g.readyState=WebSocket.OPEN,g.reconnectAttempts=0;var d=l("open");d.isReconnect=b,b=!1,k.dispatchEvent(d)},h.onclose=function(c){if(clearTimeout(e),h=null,i)g.readyState=WebSocket.CLOSED,k.dispatchEvent(l("close"));else{g.readyState=WebSocket.CONNECTING;var d=l("connecting");d.code=c.code,d.reason=c.reason,d.wasClean=c.wasClean,k.dispatchEvent(d),b||j||((g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onclose",g.url),k.dispatchEvent(l("close")));var e=g.reconnectInterval*Math.pow(g.reconnectDecay,g.reconnectAttempts);setTimeout(function(){g.reconnectAttempts++,g.open(!0)},e>g.maxReconnectInterval?g.maxReconnectInterval:e)}},h.onmessage=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onmessage",g.url,b.data);var c=l("message");c.data=b.data,k.dispatchEvent(c)},h.onerror=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onerror",g.url,b),k.dispatchEvent(l("error"))}},1==this.automaticOpen&&this.open(!1),this.send=function(b){if(h)return(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","send",g.url,b),h.send(b);throw"INVALID_STATE_ERR : Pausing to reconnect websocket"},this.close=function(a,b){"undefined"==typeof a&&(a=1e3),i=!0,h&&h.close(a,b)},this.refresh=function(){h&&h.close()}}return a.prototype.onopen=function(){},a.prototype.onclose=function(){},a.prototype.onconnecting=function(){},a.prototype.onmessage=function(){},a.prototype.onerror=function(){},a.debugAll=!1,a.CONNECTING=WebSocket.CONNECTING,a.OPEN=WebSocket.OPEN,a.CLOSING=WebSocket.CLOSING,a.CLOSED=WebSocket.CLOSED,a});
Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

+2
View File
@@ -0,0 +1,2 @@
// https://github.com/jakwings/toml-j0.4
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r;r="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,r.toml=e()}}(function(){return function e(r,t,n){function i(u,a){if(!t[u]){if(!r[u]){var c="function"==typeof require&&require;if(!a&&c)return c(u,!0);if(o)return o(u,!0);var s=new Error("Cannot find module '"+u+"'");throw s.code="MODULE_NOT_FOUND",s}var l=t[u]={exports:{}};r[u][0].call(l.exports,function(e){var t=r[u][1][e];return i(t?t:e)},l,l.exports,e,r,t,n)}return t[u].exports}for(var o="function"==typeof require&&require,u=0;u<n.length;u++)i(n[u]);return i}({1:[function(e,r,t){r.exports=function(){function e(e,r){function t(){this.constructor=e}t.prototype=r.prototype,e.prototype=new t}function r(e,r,t,n,i,o){this.message=e,this.expected=r,this.found=t,this.offset=n,this.line=i,this.column=o,this.name="SyntaxError"}function t(e){function t(){return e.substring(Ot,Dt)}function n(e){throw u(e,null,Ot)}function i(r){function t(r,t,n){var i,o;for(i=t;n>i;i++)o=e.charAt(i),"\n"===o?(r.seenCR||r.line++,r.column=1,r.seenCR=!1):"\r"===o||"\u2028"===o||"\u2029"===o?(r.line++,r.column=1,r.seenCR=!0):(r.column++,r.seenCR=!1)}return Tt!==r&&(Tt>r&&(Tt=0,jt={line:1,column:1,seenCR:!1}),t(jt,Tt,r),Tt=r),jt}function o(e){Nt>Dt||(Dt>Nt&&(Nt=Dt,Ut=[]),Ut.push(e))}function u(t,n,o){function u(e){var r=1;for(e.sort(function(e,r){return e.description<r.description?-1:e.description>r.description?1:0});r<e.length;)e[r-1]===e[r]?e.splice(r,1):r++}function a(e,r){function t(e){function r(e){return e.charCodeAt(0).toString(16).toUpperCase()}return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\x08/g,"\\b").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\f/g,"\\f").replace(/\r/g,"\\r").replace(/[\x00-\x07\x0B\x0E\x0F]/g,function(e){return"\\x0"+r(e)}).replace(/[\x10-\x1F\x80-\xFF]/g,function(e){return"\\x"+r(e)}).replace(/[\u0180-\u0FFF]/g,function(e){return"\\u0"+r(e)}).replace(/[\u1080-\uFFFF]/g,function(e){return"\\u"+r(e)})}var n,i,o,u=new Array(e.length);for(o=0;o<e.length;o++)u[o]=e[o].description;return n=e.length>1?u.slice(0,-1).join(", ")+" or "+u[e.length-1]:u[0],i=r?'"'+t(r)+'"':"end of input","Expected "+n+" but "+i+" found."}var c=i(o),s=o<e.length?e.charAt(o):null;return null!==n&&u(n),new r(null!==t?t:a(n,s),n,s,o,c.line,c.column)}function a(){var e,r,t,n,i,o,u,p;for(e=Dt,r=[],t=l(),t===ye&&(t=s(),t===ye&&(t=f()));t!==ye;)r.push(t),t=l(),t===ye&&(t=s(),t===ye&&(t=f()));if(r!==ye){if(t=Dt,n=c(),n!==ye){for(i=[],o=l(),o===ye&&(o=f());o!==ye;)i.push(o),o=l(),o===ye&&(o=f());i!==ye?(o=Dt,u=s(),u!==ye?(p=a(),p!==ye?(u=[u,p],o=u):(Dt=o,o=Ce)):(Dt=o,o=Ce),o===ye&&(o=be),o!==ye?(n=[n,i,o],t=n):(Dt=t,t=Ce)):(Dt=t,t=Ce)}else Dt=t,t=Ce;t===ye&&(t=be),t!==ye?(Ot=e,r=xe(),e=r):(Dt=e,e=Ce)}else Dt=e,e=Ce;return e}function c(){var e,r;return e=Dt,r=pe(),r!==ye&&(Ot=e,r=me(r)),e=r,e===ye&&(e=Dt,r=he(),r!==ye&&(Ot=e,r=Fe(r)),e=r,e===ye&&(e=Dt,r=p(),r!==ye&&(Ot=e,r=Se(r)),e=r)),e}function s(){var r,t;return Zt++,10===e.charCodeAt(Dt)?(r=Ee,Dt++):(r=ye,0===Zt&&o(Re)),r===ye&&(e.substr(Dt,2)===_e?(r=_e,Dt+=2):(r=ye,0===Zt&&o(De))),Zt--,r===ye&&(t=ye,0===Zt&&o(we)),r}function l(){var r,t;return Zt++,Te.test(e.charAt(Dt))?(r=e.charAt(Dt),Dt++):(r=ye,0===Zt&&o(je)),Zt--,r===ye&&(t=ye,0===Zt&&o(Oe)),r}function f(){var r,t,n,i,u,a;if(Zt++,r=Dt,35===e.charCodeAt(Dt)?(t=Ue,Dt++):(t=ye,0===Zt&&o(Ze)),t!==ye){for(n=[],i=Dt,u=Dt,Zt++,a=s(),Zt--,a===ye?u=He:(Dt=u,u=Ce),u!==ye?(e.length>Dt?(a=e.charAt(Dt),Dt++):(a=ye,0===Zt&&o(Me)),a!==ye?(u=[u,a],i=u):(Dt=i,i=Ce)):(Dt=i,i=Ce);i!==ye;)n.push(i),i=Dt,u=Dt,Zt++,a=s(),Zt--,a===ye?u=He:(Dt=u,u=Ce),u!==ye?(e.length>Dt?(a=e.charAt(Dt),Dt++):(a=ye,0===Zt&&o(Me)),a!==ye?(u=[u,a],i=u):(Dt=i,i=Ce)):(Dt=i,i=Ce);n!==ye?(t=[t,n],r=t):(Dt=r,r=Ce)}else Dt=r,r=Ce;return Zt--,r===ye&&(t=ye,0===Zt&&o(Ne)),r}function p(){var r,t,n,i,u,a;if(r=Dt,t=h(),t!==ye){for(n=[],i=l();i!==ye;)n.push(i),i=l();if(n!==ye)if(61===e.charCodeAt(Dt)?(i=Ie,Dt++):(i=ye,0===Zt&&o(qe)),i!==ye){for(u=[],a=l();a!==ye;)u.push(a),a=l();u!==ye?(a=x(),a!==ye?(Ot=r,t=ze(t,a),r=t):(Dt=r,r=Ce)):(Dt=r,r=Ce)}else Dt=r,r=Ce;else Dt=r,r=Ce}else Dt=r,r=Ce;return r}function h(){var e;return e=d(),e===ye&&(e=y()),e}function d(){var e,r,t;if(e=Dt,r=[],t=v(),t!==ye)for(;t!==ye;)r.push(t),t=v();else r=Ce;return r!==ye&&(Ot=e,r=Be()),e=r}function v(){var r,t;return Zt++,Ye.test(e.charAt(Dt))?(r=e.charAt(Dt),Dt++):(r=ye,0===Zt&&o(Je)),Zt--,r===ye&&(t=ye,0===Zt&&o(Qe)),r}function y(){var e,r,t,n;if(e=Dt,r=g(),r!==ye){if(t=[],n=S(),n!==ye)for(;n!==ye;)t.push(n),n=S();else t=Ce;t!==ye?(n=g(),n!==ye?(Ot=e,r=Pe(t),e=r):(Dt=e,e=Ce)):(Dt=e,e=Ce)}else Dt=e,e=Ce;return e}function g(){var r,t;return Zt++,34===e.charCodeAt(Dt)?(r=Le,Dt++):(r=ye,0===Zt&&o(Ve)),Zt--,r===ye&&(t=ye,0===Zt&&o(ke)),r}function A(){var r,t;return Zt++,39===e.charCodeAt(Dt)?(r=Ge,Dt++):(r=ye,0===Zt&&o(Ke)),Zt--,r===ye&&(tLine truncated
+13491
View File
File diff suppressed because it is too large. Load diff
+36
View File
@@ -0,0 +1,36 @@
{
"name": "gekko-vue-ui",
"version": "0.2.3",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"marked": "^0.4.0",
"superagent": "^3.8.3",
"superagent-no-cache": "github:uditalias/superagent-no-cache",
"vue": "^2.5.16",
"vue-router": "^3.0.1",
"vuex": "^3.0.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^3.0.0-beta.15",
"@vue/cli-service": "^3.0.0-beta.15",
"babel-plugin-transform-commonjs-es2015-modules": "^4.0.1",
"copy-webpack-plugin": "^4.5.2",
"pug": "^2.0.3",
"pug-plain-loader": "^1.0.0",
"vue-template-compiler": "^2.5.16"
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
+26
View File
@@ -0,0 +1,26 @@
// Note: this file gets copied around, make sure you edit
// the UIconfig located at `gekko/web/vue/dist/UIconfig.js`.
// This config is used by both the frontend as well as the web server.
// see https://gekko.wizb.it/docs/installation/installing_gekko_on_a_server.html#Configuring-Gekko
const CONFIG = {
headless: false,
api: {
host: '127.0.0.1',
port: 3000,
timeout: 120000 // 2 minutes
},
ui: {
ssl: false,
host: 'localhost',
port: 3000,
path: '/'
},
adapter: 'sqlite'
}
if(typeof window === 'undefined')
module.exports = CONFIG;
else
window.CONFIG = CONFIG;
+24
View File
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<link rel="stylesheet" href="vendor/furtive.min.css">
<title>Gekko</title>
</head>
<body>
<noscript>
<strong>We're sorry but gekko-vue-ui doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<script src='UIconfig.js'></script>
<script src='vendor/reconnecting-websocket.min.js'></script>
<script src='vendor/moment.js'></script>
<script src='vendor/d3.js'></script>
<script src='vendor/toml.js'></script>
<script src='vendor/humanize-duration.js'></script>
<!-- built files will be auto injected -->
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

+8
View File
@@ -0,0 +1,8 @@
// https://d3js.org Version 4.3.0. Copyright 2016 Mike Bostock.
(function(t,n){"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n(t.d3=t.d3||{})})(this,function(t){"use strict";function n(t){return function(n,e){return Ms(t(n),e)}}function e(t,n,e){var r=Math.abs(n-t)/Math.max(0,e),i=Math.pow(10,Math.floor(Math.log(r)/Math.LN10)),o=r/i;return o>=Fs?i*=10:o>=Is?i*=5:o>=Ys&&(i*=2),n<t?-i:i}function r(t){return t.length}function i(){}function o(t,n){var e=new i;if(t instanceof i)t.each(function(t,n){e.set(n,t)});else if(Array.isArray(t)){var r,o=-1,u=t.length;if(null==n)for(;++o<u;)e.set(o,t[o]);else for(;++o<u;)e.set(n(r=t[o],o,t),r)}else if(t)for(var a in t)e.set(a,t[a]);return e}function u(){return{}}function a(t,n,e){t[n]=e}function c(){return o()}function s(t,n,e){t.set(n,e)}function f(){}function l(t,n){var e=new f;if(t instanceof f)t.each(function(t){e.add(t)});else if(t){var r=-1,i=t.length;if(null==n)for(;++r<i;)e.add(t[r]);else for(;++r<i;)e.add(n(t[r],r,t))}return e}function h(t){return+t}function p(t){return t*t}function d(t){return t*(2-t)}function v(t){return((t*=2)<=1?t*t:--t*(2-t)+1)/2}function _(t){return t*t*t}function y(t){return--t*t*t+1}function g(t){return((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2}function m(t){return 1-Math.cos(t*Tf)}function x(t){return Math.sin(t*Tf)}function b(t){return(1-Math.cos(Mf*t))/2}function w(t){return Math.pow(2,10*t-10)}function M(t){return 1-Math.pow(2,-10*t)}function T(t){return((t*=2)<=1?Math.pow(2,10*t-10):2-Math.pow(2,10-10*t))/2}function N(t){return 1-Math.sqrt(1-t*t)}function k(t){return Math.sqrt(1- --t*t)}function S(t){return((t*=2)<=1?1-Math.sqrt(1-t*t):Math.sqrt(1-(t-=2)*t)+1)/2}function A(t){return 1-E(1-t)}function E(t){return(t=+t)<Nf?Lf*t*t:t<Sf?Lf*(t-=kf)*t+Af:t<Cf?Lf*(t-=Ef)*t+zf:Lf*(t-=Pf)*t+qf}function C(t){return((t*=2)<=1?1-E(1-t):E(t-1)+1)/2}function z(t,n){return t[0]-n[0]||t[1]-n[1]}function P(t){for(var n=t.length,e=[0,1],r=2,i=2;i<n;++i){for(;r>1&&Wf(t[e[r-2]],t[e[r-1]],t[i])<=0;)--r;e[r++]=i}return e.slice(0,r)}function q(){this._x0=this._y0=this._x1=this._y1=null,this._=[]}function L(){return new q}function R(t,n,e,r){if(isNaN(n)||isNaN(e))return t;var i,o,u,a,c,s,f,l,h,p=t._root,d={data:r},v=t._x0,_=t._y0,y=t._x1,g=t._y1;if(!p)return t._root=d,t;for(;p.length;)if((s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u,i=p,!(p=p[l=f<<1|s]))return i[l]=d,t;if(a=+t._x.call(null,p.data),c=+t._y.call(null,p.data),n===a&&e===c)return d.next=p,i?i[l]=d:t._root=d,t;do i=i?i[l]=new Array(4):t._root=new Array(4),(s=n>=(o=(v+y)/2))?v=o:y=o,(f=e>=(u=(_+g)/2))?_=u:g=u;while((l=f<<1|s)===(h=(c>=u)<<1|a>=o));return i[h]=p,i[l]=d,t}function U(t){var n,e,r,i,o=t.length,u=new Array(o),a=new Array(o),c=1/0,s=1/0,f=-(1/0),l=-(1/0);for(e=0;e<o;++e)isNaN(r=+this._x.call(null,n=t[e]))||isNaN(i=+this._y.call(null,n))||(u[e]=r,a[e]=i,r<c&&(c=r),r>f&&(f=r),i<s&&(s=i),i>l&&(l=i));for(f<c&&(c=this._x0,f=this._x1),l<s&&(s=this._y0,l=this._y1),this.cover(c,s).cover(f,l),e=0;e<o;++e)R(this,u[e],a[e],t[e]);return this}function D(t){for(var n=0,e=t.length;n<e;++n)this.remove(t[n]);return this}function O(t){return t[0]}function F(t){return t[1]}function I(t,n,e){var r=new Y(null==n?O:n,null==e?F:e,NaN,NaN,NaN,NaN);return null==t?r:r.addAll(t)}function Y(t,n,e,r,i,o){this._x=t,this._y=n,this._x0=e,this._y0=r,this._x1=i,this._y1=o,this._root=void 0}function B(t){for(var n={data:t.data},e=n;t=t.next;)e=e.next={data:t.data};return n}function j(t){if(!(t>=1))throw new Error;this._size=t,this._call=this._error=null,this._tasks=[],this._data=[],this._waiting=this._active=this._ended=this._start=0}function H(t){if(!t._start)try{X(t)}catch(n){if(t._tasks[t._ended+t._active-1])W(t,n);else if(!t._data)throw n}}function X(t){for(;t._start=t._waiting&&t._active<t._size;){var n=t._ended+t._active,e=t._tasks[n],r=e.length-1,i=e[r];e[r]=V(t,n),--t._waiting,++t._active,e=i.apply(null,e),t._tasks[n]&&(t._tasks[n]=e||_l)}}function V(t,n){return function(e,r){t._tasks[n]&&(--t._active,++t._ended,t._tasks[n]=null,null==t._error&&(null!=e?W(t,e):(t._data[n]=r,t._waiting?H(t):$(t))))}}function W(t,n){var e,r=t._tasks.length;for(t._error=n,t._data=void 0,t._waiting=NaN;--r>=0;)if((e=t._tasks[r])&&(t._tasks[r]=null,e.abort))try{e.abort()}catch(t){}t._active=NaN,$(t)}function $(t){if(!t._active&&t._call){var n=t._data;t._data=void 0,t._call(t._error,n)}}function Z(t){return new j(arguments.length?+t:1/0)}function G(t){return t.innerRadius}function J(t){return t.outerRadius}function Q(t){return t.startAngle}function K(t){return t.endAngle}function tt(t){return t&&t.padAngle}function nt(t){return t>=1?xl:t<=-1?-xl:Math.asin(t)}function et(t,n,e,r,i,o,u,a){var c=e-t,s=r-n,f=u-i,l=a-o,h=(f*(n-o)-l*(t-i))/(l*c-f*s);return[t+h*c,n+h*s]}function rt(t,n,e,r,i,o,u){var a=t-e,c=n-r,s=(u?o:-o)/Math.sqrt(a*a+c*c),f=s*c,l=-s*a,h=t+f,p=n+l,d=e+f,v=r+l,_=(h+d)/2,y=(p+v)/2,g=d-h,m=v-p,x=g*g+m*m,b=i-o,w=h*v-d*p,M=(m<0?-1:1)*Math.sqrt(Math.max(0,b*b*x-w*w)),T=(w*m-g*M)/x,N=(-w*g-m*M)/x,k=(w*m+g*M)/x,S=(-w*Line truncated
}function Pr(t){return t instanceof Date?+t:+new Date(+t)}function qr(t,n,r,i,o,u,a,c,s){function f(e){return(a(e)<e?v:u(e)<e?_:o(e)<e?y:i(e)<e?g:n(e)<e?r(e)<e?m:x:t(e)<e?b:w)(e)}function l(n,r,i,o){if(null==n&&(n=10),"number"==typeof n){var u=Math.abs(i-r)/n,a=Ts(function(t){return t[2]}).right(M,u);a===M.length?(o=e(r/o_,i/o_,n),n=t):a?(a=M[u/M[a-1][2]<M[a][2]/u?a-1:a],o=a[1],n=a[0]):(o=e(r,i,n),n=c)}return null==o?n:n.every(o)}var h=dr(cr,lp),p=h.invert,d=h.domain,v=s(".%L"),_=s(":%S"),y=s("%I:%M"),g=s("%I %p"),m=s("%a %d"),x=s("%b %d"),b=s("%B"),w=s("%Y"),M=[[a,1,Kv],[a,5,5*Kv],[a,15,15*Kv],[a,30,30*Kv],[u,1,t_],[u,5,5*t_],[u,15,15*t_],[u,30,30*t_],[o,1,n_],[o,3,3*n_],[o,6,6*n_],[o,12,12*n_],[i,1,e_],[i,2,2*e_],[r,1,r_],[n,1,i_],[n,3,3*i_],[t,1,o_]];return h.invert=function(t){return new Date(p(t))},h.domain=function(t){return arguments.length?d(Xv.call(t,Pr)):d().map(zr)},h.ticks=function(t,n){var e,r=d(),i=r[0],o=r[r.length-1],u=o<i;return u&&(e=i,i=o,o=e),e=l(t,i,o,n),e=e?e.range(i,o+1):[],u?e.reverse():e},h.tickFormat=function(t,n){return null==n?f:s(n)},h.nice=function(t,n){var e=d();return(t=l(t,e[0],e[e.length-1],n))?d(Qv(e,t)):h},h.copy=function(){return pr(h,qr(t,n,r,i,o,u,a,c,s))},h}function Lr(t){var n=t.length;return function(e){return t[Math.max(0,Math.min(n-1,Math.floor(e*n)))]}}function Rr(t){function n(n){var o=(n-e)/(r-e);return t(i?Math.max(0,Math.min(1,o)):o)}var e=0,r=1,i=!1;return n.domain=function(t){return arguments.length?(e=+t[0],r=+t[1],n):[e,r]},n.clamp=function(t){return arguments.length?(i=!!t,n):i},n.interpolator=function(e){return arguments.length?(t=e,n):t},n.copy=function(){return Rr(t).domain([e,r]).clamp(i)},vr(n)}function Ur(t){return function(){var n=this.ownerDocument,e=this.namespaceURI;return e===w_&&n.documentElement.namespaceURI===w_?n.createElement(t):n.createElementNS(e,t)}}function Dr(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Or(){return new Fr}function Fr(){this._="@"+(++k_).toString(36)}function Ir(t,n,e){return t=Yr(t,n,e),function(n){var e=n.relatedTarget;e&&(e===this||8&e.compareDocumentPosition(this))||t.call(this,n)}}function Yr(n,e,r){return function(i){var o=t.event;t.event=i;try{n.call(this,this.__data__,e,r)}finally{t.event=o}}}function Br(t){return t.trim().split(/^|\s+/).map(function(t){var n="",e=t.indexOf(".");return e>=0&&(n=t.slice(e+1),t=t.slice(0,e)),{type:t,name:n}})}function jr(t){return function(){var n=this.__on;if(n){for(var e,r=0,i=-1,o=n.length;r<o;++r)e=n[r],t.type&&e.type!==t.type||e.name!==t.name?n[++i]=e:this.removeEventListener(e.type,e.listener,e.capture);++i?n.length=i:delete this.__on}}}function Hr(t,n,e){var r=z_.hasOwnProperty(t.type)?Ir:Yr;return function(i,o,u){var a,c=this.__on,s=r(n,o,u);if(c)for(var f=0,l=c.length;f<l;++f)if((a=c[f]).type===t.type&&a.name===t.name)return this.removeEventListener(a.type,a.listener,a.capture),this.addEventListener(a.type,a.listener=s,a.capture=e),void(a.value=n);this.addEventListener(t.type,s,e),a={type:t.type,name:t.name,value:n,listener:s,capture:e},c?c.push(a):this.__on=[a]}}function Xr(n,e,r,i){var o=t.event;n.sourceEvent=t.event,t.event=n;try{return e.apply(r,i)}finally{t.event=o}}function Vr(){}function Wr(){return[]}function $r(t,n){this.ownerDocument=t.ownerDocument,this.namespaceURI=t.namespaceURI,this._next=null,this._parent=t,this.__data__=n}function Zr(t,n,e,r,i,o){for(var u,a=0,c=n.length,s=o.length;a<s;++a)(u=n[a])?(u.__data__=o[a],r[a]=u):e[a]=new $r(t,o[a]);for(;a<c;++a)(u=n[a])&&(i[a]=u)}function Gr(t,n,e,r,i,o,u){var a,c,s,f={},l=n.length,h=o.length,p=new Array(l);for(a=0;a<l;++a)(c=n[a])&&(p[a]=s=X_+u.call(c,c.__data__,a,n),s in f?i[a]=c:f[s]=c);for(a=0;a<h;++a)s=X_+u.call(t,o[a],a,o),(c=f[s])?(r[a]=c,c.__data__=o[a],f[s]=null):e[a]=new $r(t,o[a]);for(a=0;a<l;++a)(c=n[a])&&f[p[a]]===c&&(i[a]=c)}function Jr(t,n){return t<n?-1:t>n?1:t>=n?0:NaN}function Qr(t){return function(){this.removeAttribute(t)}}function Kr(t){return function(){this.removeAttributeNS(t.space,t.local)}}function ti(t,n){return function(){this.setAttribute(t,n)}}function ni(t,n){return function(){this.setAttributeNS(t.space,t.local,n)}}function ei(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}}function ri(t,n){return function(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}}function ii(t){return function(){this.style.removeProperty(t)}}function oi(t,n,e){return function(){this.style.setProperty(t,n,e)}}function ui(t,n,e){return function(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}}function ai(t){return function(){delete this[t]}}function ci(t,n){return function(){this[t]=n}}function si(t,n){return function(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}}function fi(t){return t.trim().split(/^|\s+/)}function li(t){return t.classList||new hi(t)}function Line truncated
return c&&s?t:t(1)}):t.each(function(){var t=this,o=arguments,u=t.__brush,a=n.input("function"==typeof e?e.apply(t,o):e,u.extent),c=i(t,o).beforestart();Py(t),u.selection=null==a||da(a)?null:a,r.call(t),c.start().brush().end()})},o.prototype={beforestart:function(){return 1===++this.active&&(this.state.emitter=this,this.starting=!0),this},start:function(){return this.starting&&(this.starting=!1,this.emit("start")),this},brush:function(){return this.emit("brush"),this},end:function(){return 0===--this.active&&(delete this.state.emitter,this.emit("end")),this},emit:function(t){Xr(new xm(e,t,n.output(this.state.selection)),l.apply,l,[t,this.that,this.args])}},e.extent=function(t){return arguments.length?(s="function"==typeof t?t:mm([[+t[0][0],+t[0][1]],[+t[1][0],+t[1][1]]]),e):s},e.filter=function(t){return arguments.length?(f="function"==typeof t?t:mm(!!t),e):f},e.handleSize=function(t){return arguments.length?(h=+t,e):h},e.on=function(){var t=l.on.apply(l,arguments);return t===l?e:t},e}function ma(t){return function(n,e){return t(n.source.value+n.target.value,e.source.value+e.target.value)}}function xa(t){return t.source}function ba(t){return t.target}function wa(t){return t.radius}function Ma(t){return t.startAngle}function Ta(t){return t.endAngle}function Na(){this.reset()}function ka(t,n,e){var r=t.s=n+e,i=r-n,o=r-i;t.t=n-o+(e-i)}function Sa(t){return t>1?0:t<-1?kx:Math.acos(t)}function Aa(t){return t>1?Sx:t<-1?-Sx:Math.asin(t)}function Ea(t){return(t=Ix(t/2))*t}function Ca(){}function za(t,n){t&&Xx.hasOwnProperty(t.type)&&Xx[t.type](t,n)}function Pa(t,n,e){var r,i=-1,o=t.length-e;for(n.lineStart();++i<o;)r=t[i],n.point(r[0],r[1],r[2]);n.lineEnd()}function qa(t,n){var e=-1,r=t.length;for(n.polygonStart();++e<r;)Pa(t[e],n,1);n.polygonEnd()}function La(){Zx.point=Ua}function Ra(){Da(Vm,Wm)}function Ua(t,n){Zx.point=Da,Vm=t,Wm=n,t*=zx,n*=zx,$m=t,Zm=Rx(n=n/2+Ax),Gm=Ix(n)}function Da(t,n){t*=zx,n*=zx,n=n/2+Ax;var e=t-$m,r=e>=0?1:-1,i=r*e,o=Rx(n),u=Ix(n),a=Gm*u,c=Zm*o+a*Rx(i),s=a*r*Ix(i);Wx.add(Lx(s,c)),$m=t,Zm=o,Gm=u}function Oa(t){return[Lx(t[1],t[0]),Aa(t[2])]}function Fa(t){var n=t[0],e=t[1],r=Rx(e);return[r*Rx(n),r*Ix(n),Ix(e)]}function Ia(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function Ya(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function Ba(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function ja(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function Ha(t){var n=Bx(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function Xa(t,n){ox.push(ux=[Jm=t,Km=t]),n<Qm&&(Qm=n),n>tx&&(tx=n)}function Va(t,n){var e=Fa([t*zx,n*zx]);if(ix){var r=Ya(ix,e),i=[r[1],-r[0],0],o=Ya(i,r);Ha(o),o=Oa(o);var u,a=t-nx,c=a>0?1:-1,s=o[0]*Cx*c,f=Px(a)>180;f^(c*nx<s&&s<c*t)?(u=o[1]*Cx,u>tx&&(tx=u)):(s=(s+360)%360-180,f^(c*nx<s&&s<c*t)?(u=-o[1]*Cx,u<Qm&&(Qm=u)):(n<Qm&&(Qm=n),n>tx&&(tx=n))),f?t<nx?Qa(Jm,t)>Qa(Jm,Km)&&(Km=t):Qa(t,Km)>Qa(Jm,Km)&&(Jm=t):Km>=Jm?(t<Jm&&(Jm=t),t>Km&&(Km=t)):t>nx?Qa(Jm,t)>Qa(Jm,Km)&&(Km=t):Qa(t,Km)>Qa(Jm,Km)&&(Jm=t)}else Xa(t,n);ix=e,nx=t}function Wa(){Qx.point=Va}function $a(){ux[0]=Jm,ux[1]=Km,Qx.point=Xa,ix=null}function Za(t,n){if(ix){var e=t-nx;Jx.add(Px(e)>180?e+(e>0?360:-360):e)}else ex=t,rx=n;Zx.point(t,n),Va(t,n)}function Ga(){Zx.lineStart()}function Ja(){Za(ex,rx),Zx.lineEnd(),Px(Jx)>Tx&&(Jm=-(Km=180)),ux[0]=Jm,ux[1]=Km,ix=null}function Qa(t,n){return(n-=t)<0?n+360:n}function Ka(t,n){return t[0]-n[0]}function tc(t,n){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}function nc(t,n){t*=zx,n*=zx;var e=Rx(n);ec(e*Rx(t),e*Ix(t),Ix(n))}function ec(t,n,e){++ax,sx+=(t-sx)/ax,fx+=(n-fx)/ax,lx+=(e-lx)/ax}function rc(){tb.point=ic}function ic(t,n){t*=zx,n*=zx;var e=Rx(n);xx=e*Rx(t),bx=e*Ix(t),wx=Ix(n),tb.point=oc,ec(xx,bx,wx)}function oc(t,n){t*=zx,n*=zx;var e=Rx(n),r=e*Rx(t),i=e*Ix(t),o=Ix(n),u=Lx(Bx((u=bx*o-wx*i)*u+(u=wx*r-xx*o)*u+(u=xx*i-bx*r)*u),xx*r+bx*i+wx*o);cx+=u,hx+=u*(xx+(xx=r)),px+=u*(bx+(bx=i)),dx+=u*(wx+(wx=o)),ec(xx,bx,wx)}function uc(){tb.point=nc}function ac(){tb.point=sc}function cc(){fc(gx,mx),tb.point=nc}function sc(t,n){gx=t,mx=n,t*=zx,n*=zx,tb.point=fc;var e=Rx(n);xx=e*Rx(t),bx=e*Ix(t),wx=Ix(n),ec(xx,bx,wx)}function fc(t,n){t*=zx,n*=zx;var e=Rx(n),r=e*Rx(t),i=e*Ix(t),o=Ix(n),u=bx*o-wx*i,a=wx*r-xx*o,c=xx*i-bx*r,s=Bx(u*u+a*a+c*c),f=xx*r+bx*i+wx*o,l=s&&-Sa(f)/s,h=Lx(s,f);vx+=l*u,_x+=l*a,yx+=l*c,cx+=h,hx+=h*(xx+(xx=r)),px+=h*(bx+(bx=i)),dx+=h*(wx+(wx=o)),ec(xx,bx,wx)}function lc(t,n){return[t>kx?t-Ex:t<-kx?t+Ex:t,n]}function hc(t,n,e){return(t%=Ex)?n||e?rb(dc(t),vc(n,e)):dc(t):n||e?vc(n,e):lc}function pc(t){return function(n,e){return n+=t,[n>kx?n-Ex:n<-kx?n+Ex:n,e]}}function dc(t){var n=pc(t);return n.invert=pc(-t),n}function vc(t,n){function e(t,n){var e=Rx(n),a=Rx(t)*e,c=Ix(t)*e,s=Ix(n),f=s*r+a*i;return[Lx(c*o-f*u,a*r-s*i),Aa(f*o+c*u)]}var r=Rx(t),i=Ix(t),o=Rx(n),u=Ix(n);return e.invert=function(t,n){var e=Rx(n),a=Rx(t)*e,c=Ix(t)*e,s=Ix(n),f=s*o-c*u;return[Lx(c*o+s*u,a*r+f*i),Aa(f*r-a*i)]},e}function _c(t,n,e,r,i,o){if(e){var u=Rx(n),a=Ix(n),c=r*e;null==i?(i=n+r*Ex,o=Line truncated
return function(){return t}},gl=1e-12,ml=Math.PI,xl=ml/2,bl=2*ml,wl=function(){function t(){var t,s,f=+n.apply(this,arguments),l=+e.apply(this,arguments),h=o.apply(this,arguments)-xl,p=u.apply(this,arguments)-xl,d=Math.abs(p-h),v=p>h;if(c||(c=t=L()),l<f&&(s=l,l=f,f=s),l>gl)if(d>bl-gl)c.moveTo(l*Math.cos(h),l*Math.sin(h)),c.arc(0,0,l,h,p,!v),f>gl&&(c.moveTo(f*Math.cos(p),f*Math.sin(p)),c.arc(0,0,f,p,h,v));else{var _,y,g=h,m=p,x=h,b=p,w=d,M=d,T=a.apply(this,arguments)/2,N=T>gl&&(i?+i.apply(this,arguments):Math.sqrt(f*f+l*l)),k=Math.min(Math.abs(l-f)/2,+r.apply(this,arguments)),S=k,A=k;if(N>gl){var E=nt(N/f*Math.sin(T)),C=nt(N/l*Math.sin(T));(w-=2*E)>gl?(E*=v?1:-1,x+=E,b-=E):(w=0,x=b=(h+p)/2),(M-=2*C)>gl?(C*=v?1:-1,g+=C,m-=C):(M=0,g=m=(h+p)/2)}var z=l*Math.cos(g),P=l*Math.sin(g),q=f*Math.cos(b),R=f*Math.sin(b);if(k>gl){var U=l*Math.cos(m),D=l*Math.sin(m),O=f*Math.cos(x),F=f*Math.sin(x);if(d<ml){var I=w>gl?et(z,P,O,F,U,D,q,R):[q,R],Y=z-I[0],B=P-I[1],j=U-I[0],H=D-I[1],X=1/Math.sin(Math.acos((Y*j+B*H)/(Math.sqrt(Y*Y+B*B)*Math.sqrt(j*j+H*H)))/2),V=Math.sqrt(I[0]*I[0]+I[1]*I[1]);S=Math.min(k,(f-V)/(X-1)),A=Math.min(k,(l-V)/(X+1))}}M>gl?A>gl?(_=rt(O,F,z,P,l,A,v),y=rt(U,D,q,R,l,A,v),c.moveTo(_.cx+_.x01,_.cy+_.y01),A<k?c.arc(_.cx,_.cy,A,Math.atan2(_.y01,_.x01),Math.atan2(y.y01,y.x01),!v):(c.arc(_.cx,_.cy,A,Math.atan2(_.y01,_.x01),Math.atan2(_.y11,_.x11),!v),c.arc(0,0,l,Math.atan2(_.cy+_.y11,_.cx+_.x11),Math.atan2(y.cy+y.y11,y.cx+y.x11),!v),c.arc(y.cx,y.cy,A,Math.atan2(y.y11,y.x11),Math.atan2(y.y01,y.x01),!v))):(c.moveTo(z,P),c.arc(0,0,l,g,m,!v)):c.moveTo(z,P),f>gl&&w>gl?S>gl?(_=rt(q,R,U,D,f,-S,v),y=rt(z,P,O,F,f,-S,v),c.lineTo(_.cx+_.x01,_.cy+_.y01),S<k?c.arc(_.cx,_.cy,S,Math.atan2(_.y01,_.x01),Math.atan2(y.y01,y.x01),!v):(c.arc(_.cx,_.cy,S,Math.atan2(_.y01,_.x01),Math.atan2(_.y11,_.x11),!v),c.arc(0,0,f,Math.atan2(_.cy+_.y11,_.cx+_.x11),Math.atan2(y.cy+y.y11,y.cx+y.x11),v),c.arc(y.cx,y.cy,S,Math.atan2(y.y11,y.x11),Math.atan2(y.y01,y.x01),!v))):c.arc(0,0,f,b,x,v):c.lineTo(q,R)}else c.moveTo(0,0);if(c.closePath(),t)return c=null,t+""||null}var n=G,e=J,r=yl(0),i=null,o=Q,u=K,a=tt,c=null;return t.centroid=function(){var t=(+n.apply(this,arguments)+ +e.apply(this,arguments))/2,r=(+o.apply(this,arguments)+ +u.apply(this,arguments))/2-ml/2;return[Math.cos(r)*t,Math.sin(r)*t]},t.innerRadius=function(e){return arguments.length?(n="function"==typeof e?e:yl(+e),t):n},t.outerRadius=function(n){return arguments.length?(e="function"==typeof n?n:yl(+n),t):e},t.cornerRadius=function(n){return arguments.length?(r="function"==typeof n?n:yl(+n),t):r},t.padRadius=function(n){return arguments.length?(i=null==n?null:"function"==typeof n?n:yl(+n),t):i},t.startAngle=function(n){return arguments.length?(o="function"==typeof n?n:yl(+n),t):o},t.endAngle=function(n){return arguments.length?(u="function"==typeof n?n:yl(+n),t):u},t.padAngle=function(n){return arguments.length?(a="function"==typeof n?n:yl(+n),t):a},t.context=function(n){return arguments.length?(c=null==n?null:n,t):c},t};it.prototype={areaStart:function(){this._line=0},areaEnd:function(){this._line=NaN},lineStart:function(){this._point=0},lineEnd:function(){(this._line||0!==this._line&&1===this._point)&&this._context.closePath(),this._line=1-this._line},point:function(t,n){switch(t=+t,n=+n,this._point){case 0:this._point=1,this._line?this._context.lineTo(t,n):this._context.moveTo(t,n);break;case 1:this._point=2;default:this._context.lineTo(t,n)}}};var Ml=function(t){return new it(t)},Tl=function(){function t(t){var a,c,s,f=t.length,l=!1;for(null==i&&(u=o(s=L())),a=0;a<=f;++a)!(a<f&&r(c=t[a],a,t))===l&&((l=!l)?u.lineStart():u.lineEnd()),l&&u.point(+n(c,a,t),+e(c,a,t));if(s)return u=null,s+""||null}var n=ot,e=ut,r=yl(!0),i=null,o=Ml,u=null;return t.x=function(e){return arguments.length?(n="function"==typeof e?e:yl(+e),t):n},t.y=function(n){return arguments.length?(e="function"==typeof n?n:yl(+n),t):e},t.defined=function(n){return arguments.length?(r="function"==typeof n?n:yl(!!n),t):r},t.curve=function(n){return arguments.length?(o=n,null!=i&&(u=o(i)),t):o},t.context=function(n){return arguments.length?(null==n?i=u=null:u=o(i=n),t):i},t},Nl=function(){function t(t){var n,f,l,h,p,d=t.length,v=!1,_=new Array(d),y=new Array(d);for(null==a&&(s=c(p=L())),n=0;n<=d;++n){if(!(n<d&&u(h=t[n],n,t))===v)if(v=!v)f=n,s.areaStart(),s.lineStart();else{for(s.lineEnd(),s.lineStart(),l=n-1;l>=f;--l)s.point(_[l],y[l]);s.lineEnd(),s.areaEnd()}v&&(_[n]=+e(h,n,t),y[n]=+i(h,n,t),s.point(r?+r(h,n,t):_[n],o?+o(h,n,t):y[n]))}if(p)return s=null,p+""||null}function n(){return Tl().defined(u).curve(c).context(a)}var e=ot,r=null,i=yl(0),o=ut,u=yl(!0),a=null,c=Ml,s=null;return t.x=function(n){return arguments.length?(e="function"==typeof n?n:yl(+n),r=null,t):e},t.x0=function(n){return arguments.length?(e="function"==typeof n?n:yl(+n),t):e},t.x1=function(n){return arguments.length?(r=null==n?null:"function"==typeof n?n:yl(+n),t):r},t.y=function(n){return arguments.length?(i="function"==typeof n?n:yl(+n),o=null,t):i},Line truncated
return e},Rp={value:function(){}};qn.prototype=Pn.prototype={constructor:qn,on:function(t,n){var e,r=this._,i=Ln(t+"",r),o=-1,u=i.length;{if(!(arguments.length<2)){if(null!=n&&"function"!=typeof n)throw new Error("invalid callback: "+n);for(;++o<u;)if(e=(t=i[o]).type)r[e]=Un(r[e],t.name,n);else if(null==n)for(e in r)r[e]=Un(r[e],t.name,null);return this}for(;++o<u;)if((e=(t=i[o]).type)&&(e=Rn(r[e],t.name)))return e}},copy:function(){var t={},n=this._;for(var e in n)t[e]=n[e].slice();return new qn(t)},call:function(t,n){if((e=arguments.length-2)>0)for(var e,r,i=new Array(e),o=0;o<e;++o)i[o]=arguments[o+2];if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(r=this._[t],o=0,e=r.length;o<e;++o)r[o].value.apply(n,i)},apply:function(t,n,e){if(!this._.hasOwnProperty(t))throw new Error("unknown type: "+t);for(var r=this._[t],i=0,o=r.length;i<o;++i)r[i].value.apply(n,e)}};var Up,Dp,Op=function(t){function n(t,n){var r,i,o=e(t,function(t,e){return r?r(t,e-1):(i=t,void(r=n?On(t,n):Dn(t)))});return o.columns=i,o}function e(t,n){function e(){if(f>=s)return u;if(i)return i=!1,o;var n,e=f;if(34===t.charCodeAt(e)){for(var r=e;r++<s;)if(34===t.charCodeAt(r)){if(34!==t.charCodeAt(r+1))break;++r}return f=r+2,n=t.charCodeAt(r+1),13===n?(i=!0,10===t.charCodeAt(r+2)&&++f):10===n&&(i=!0),t.slice(e+1,r).replace(/""/g,'"')}for(;f<s;){var a=1;if(n=t.charCodeAt(f++),10===n)i=!0;else if(13===n)i=!0,10===t.charCodeAt(f)&&(++f,++a);else if(n!==c)continue;return t.slice(e,f-a)}return t.slice(e)}for(var r,i,o={},u={},a=[],s=t.length,f=0,l=0;(r=e())!==u;){for(var h=[];r!==o&&r!==u;)h.push(r),r=e();n&&null==(h=n(h,l++))||a.push(h)}return a}function r(n,e){return null==e&&(e=Fn(n)),[e.map(u).join(t)].concat(n.map(function(n){return e.map(function(t){return u(n[t])}).join(t)})).join("\n")}function i(t){return t.map(o).join("\n")}function o(n){return n.map(u).join(t)}function u(t){return null==t?"":a.test(t+="")?'"'+t.replace(/\"/g,'""')+'"':t}var a=new RegExp('["'+t+"\n]"),c=t.charCodeAt(0);return{parse:n,parseRows:e,format:r,formatRows:i}},Fp=Op(","),Ip=Fp.parse,Yp=Fp.parseRows,Bp=Fp.format,jp=Fp.formatRows,Hp=Op("\t"),Xp=Hp.parse,Vp=Hp.parseRows,Wp=Hp.format,$p=Hp.formatRows,Zp=function(t,n){function e(t){var n,e=f.status;if(!e&&Yn(f)||e>=200&&e<300||304===e){if(u)try{n=u.call(r,f)}catch(t){return void c.call("error",r,t)}else n=f;c.call("load",r,n)}else c.call("error",r,t)}var r,i,u,a,c=Pn("beforesend","progress","load","error"),s=o(),f=new XMLHttpRequest,l=null,h=null,p=0;if("undefined"==typeof XDomainRequest||"withCredentials"in f||!/^(http(s)?:)?\/\//.test(t)||(f=new XDomainRequest),"onload"in f?f.onload=f.onerror=f.ontimeout=e:f.onreadystatechange=function(t){f.readyState>3&&e(t)},f.onprogress=function(t){c.call("progress",r,t)},r={header:function(t,n){return t=(t+"").toLowerCase(),arguments.length<2?s.get(t):(null==n?s.remove(t):s.set(t,n+""),r)},mimeType:function(t){return arguments.length?(i=null==t?null:t+"",r):i},responseType:function(t){return arguments.length?(a=t,r):a},timeout:function(t){return arguments.length?(p=+t,r):p},user:function(t){return arguments.length<1?l:(l=null==t?null:t+"",r)},password:function(t){return arguments.length<1?h:(h=null==t?null:t+"",r)},response:function(t){return u=t,r},get:function(t,n){return r.send("GET",t,n)},post:function(t,n){return r.send("POST",t,n)},send:function(n,e,o){return f.open(n,t,!0,l,h),null==i||s.has("accept")||s.set("accept",i+",*/*"),f.setRequestHeader&&s.each(function(t,n){f.setRequestHeader(n,t)}),null!=i&&f.overrideMimeType&&f.overrideMimeType(i),null!=a&&(f.responseType=a),p>0&&(f.timeout=p),null==o&&"function"==typeof e&&(o=e,e=null),null!=o&&1===o.length&&(o=In(o)),null!=o&&r.on("error",o).on("load",function(t){o(null,t)}),c.call("beforesend",r,f),f.send(null==e?null:e),r},abort:function(){return f.abort(),r},on:function(){var t=c.on.apply(c,arguments);return t===c?r:t}},null!=n){if("function"!=typeof n)throw new Error("invalid callback: "+n);return r.get(n)}return r},Gp=function(t,n){return function(e,r){var i=Zp(e).mimeType(t).response(n);if(null!=r){if("function"!=typeof r)throw new Error("invalid callback: "+r);return i.get(r)}return i}},Jp=Gp("text/html",function(t){return document.createRange().createContextualFragment(t.responseText)}),Qp=Gp("application/json",function(t){return JSON.parse(t.responseText)}),Kp=Gp("text/plain",function(t){return t.responseText}),td=Gp("application/xml",function(t){var n=t.responseXML;if(!n)throw new Error("parse error");return n}),nd=function(t,n){return function(e,r,i){arguments.length<3&&(i=r,r=null);var o=Zp(e).mimeType(t);return o.row=function(t){return arguments.length?o.response(Bn(n,r=t)):r},o.row(r),i?o.get(i):o}},ed=nd("text/csv",Ip),rd=nd("text/tab-separated-values",Xp),id=0,od=0,ud=0,ad=1e3,cd=0,sd=0,fd=0,ld="object"==typeof performance&&performance.now?performance:Date,hd="function"==typeof requestAnimationFrame?requestAnimationFrame:function(t){setTimeout(t,17)};Xn.prototype=Vn.prototype={constructor:XLine truncated
for(var r=this._groups,i=r.length,o=[],u=[],a=0;a<i;++a)for(var c,s=r[a],f=s.length,l=0;l<f;++l)if(c=s[l]){for(var h,p=t.call(c,c.__data__,l,s),d=Ri(c,e),v=0,_=p.length;v<_;++v)(h=p[v])&&zy(h,n,e,v,p,d);o.push(p),u.push(c)}return new so(o,u,n,e)},Wy=Pi.prototype.constructor,$y=function(){return new Wy(this._groups,this._parents)},Zy=function(t,n,e){var r="transform"==(t+="")?bp:Ry;return null==n?this.styleTween(t,eo(t,r)).on("end.style."+t,ro(t)):this.styleTween(t,"function"==typeof n?oo(t,r,Fi(this,"style."+t,n)):io(t,r,n),e)},Gy=function(t,n,e){var r="style."+(t+="");if(arguments.length<2)return(r=this.tween(r))&&r._value;if(null==n)return this.tween(r,null);if("function"!=typeof n)throw new Error;return this.tween(r,uo(t,n,null==e?"":e))},Jy=function(t){return this.tween("text","function"==typeof t?co(Fi(this,"text",t)):ao(null==t?"":t+""))},Qy=function(){for(var t=this._name,n=this._id,e=lo(),r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)if(u=a[s]){var f=Ri(u,n);zy(u,t,e,s,a,{time:f.time+f.delay+f.duration,delay:0,duration:f.duration,ease:f.ease})}return new so(r,this._parents,t,e)},Ky=0,tg=Pi.prototype;so.prototype=fo.prototype={constructor:so,select:Xy,selectAll:Vy,filter:Yy,merge:By,selection:$y,transition:Qy,call:tg.call,nodes:tg.nodes,node:tg.node,size:tg.size,empty:tg.empty,each:tg.each,on:jy,attr:Uy,attrTween:Dy,style:Zy,styleTween:Gy,text:Jy,remove:Hy,tween:Ly,delay:Oy,duration:Fy,ease:Iy};var ng={time:null,delay:0,duration:250,ease:g},eg=function(t){var n,e;t instanceof so?(n=t._id,t=t._name):(n=lo(),(e=ng).time=jn(),t=null==t?null:t+"");for(var r=this._groups,i=r.length,o=0;o<i;++o)for(var u,a=r[o],c=a.length,s=0;s<c;++s)(u=a[s])&&zy(u,t,n,s,a,e||ho(u,n));return new so(r,this._parents,t,n)};Pi.prototype.interrupt=qy,Pi.prototype.transition=eg;var rg=[null],ig=function(t,n){var e,r,i=t.__transition;if(i){n=null==n?null:n+"";for(r in i)if((e=i[r]).state>Ny&&e.name===n)return new so([[t]],rg,n,+r)}return null},og=Array.prototype.slice,ug=function(t){return t},ag=1,cg=2,sg=3,fg=4,lg=1e-6,hg=function(){function t(t){var o,u=0;t.eachAfter(function(t){var e=t.children;e?(t.x=To(e),t.y=ko(e)):(t.x=o?u+=n(t,o):0,t.y=0,o=t)});var a=Ao(t),c=Eo(t),s=a.x-n(a,c)/2,f=c.x+n(c,a)/2;return t.eachAfter(i?function(n){n.x=(n.x-t.x)*e,n.y=(t.y-n.y)*r}:function(n){n.x=(n.x-s)/(f-s)*e,n.y=(1-(t.y?n.y/t.y:1))*r})}var n=Mo,e=1,r=1,i=!1;return t.separation=function(e){return arguments.length?(n=e,t):n},t.size=function(n){return arguments.length?(i=!1,e=+n[0],r=+n[1],t):i?null:[e,r]},t.nodeSize=function(n){return arguments.length?(i=!0,e=+n[0],r=+n[1],t):i?[e,r]:null},t},pg=function(t){var n,e,r,i,o=this,u=[o];do for(n=u.reverse(),u=[];o=n.pop();)if(t(o),e=o.children)for(r=0,i=e.length;r<i;++r)u.push(e[r]);while(u.length);return this},dg=function(t){for(var n,e,r=this,i=[r];r=i.pop();)if(t(r),n=r.children)for(e=n.length-1;e>=0;--e)i.push(n[e]);return this},vg=function(t){for(var n,e,r,i=this,o=[i],u=[];i=o.pop();)if(u.push(i),n=i.children)for(e=0,r=n.length;e<r;++e)o.push(n[e]);for(;i=u.pop();)t(i);return this},_g=function(t){return this.eachAfter(function(n){for(var e=+t(n.data)||0,r=n.children,i=r&&r.length;--i>=0;)e+=r[i].value;n.value=e})},yg=function(t){return this.eachBefore(function(n){n.children&&n.children.sort(t)})},gg=function(t){for(var n=this,e=Co(n,t),r=[n];n!==e;)n=n.parent,r.push(n);for(var i=r.length;t!==e;)r.splice(i,0,t),t=t.parent;return r},mg=function(){for(var t=this,n=[t];t=t.parent;)n.push(t);return n},xg=function(){var t=[];return this.each(function(n){t.push(n)}),t},bg=function(){var t=[];return this.eachBefore(function(n){n.children||t.push(n)}),t},wg=function(){var t=this,n=[];return t.each(function(e){e!==t&&n.push({source:e.parent,target:e})}),n};Uo.prototype=zo.prototype={constructor:Uo,each:pg,eachAfter:vg,eachBefore:dg,sum:_g,sort:yg,path:gg,ancestors:mg,descendants:xg,leaves:bg,links:wg,copy:Po};var Mg=function(t){for(var n,e=(t=t.slice()).length,r=null,i=r;e;){var o=new Do(t[e-1]);i=i?i.next=o:r=o,t[n]=t[--e]}return{head:r,tail:i}},Tg=function(t){return Fo(Mg(t),[])},Ng=function(t){return Wo(t),t},kg=function(t){return function(){return t}},Sg=function(){function t(t){return t.x=e/2,t.y=r/2,n?t.eachBefore(Qo(n)).eachAfter(Ko(i,.5)).eachBefore(tu(1)):t.eachBefore(Qo(Jo)).eachAfter(Ko(Go,1)).eachAfter(Ko(i,t.r/Math.min(e,r))).eachBefore(tu(Math.min(e,r)/(2*t.r))),t}var n=null,e=1,r=1,i=Go;return t.radius=function(e){return arguments.length?(n=$o(e),t):n},t.size=function(n){return arguments.length?(e=+n[0],r=+n[1],t):[e,r]},t.padding=function(n){return arguments.length?(i="function"==typeof n?n:kg(+n),t):i},t},Ag=function(t){t.x0=Math.round(t.x0),t.y0=Math.round(t.y0),t.x1=Math.round(t.x1),t.y1=Math.round(t.y1)},Eg=function(t,n,e,r,i){for(var o,u=t.children,a=-1,c=u.length,s=t.value&&(r-n)/t.value;++a<c;)o=u[a],o.y0=e,o.y1=i,o.x0=n,o.x1=n+=o.value*s},Cg=function(){function t(t){var u=t.height+1;return t.x0=t.y0=i,t.x1=e,t.y1=r/u,t.eachBefore(n(r,u)),o&&t.eaLine truncated
},Bx=Math.sqrt,jx=Math.tan,Hx={Feature:function(t,n){za(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;++r<i;)za(e[r].geometry,n)}},Xx={Sphere:function(t,n){n.sphere()},Point:function(t,n){t=t.coordinates,n.point(t[0],t[1],t[2])},MultiPoint:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)t=e[r],n.point(t[0],t[1],t[2])},LineString:function(t,n){Pa(t.coordinates,n,0)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)Pa(e[r],n,0)},Polygon:function(t,n){qa(t.coordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;++r<i;)qa(e[r],n)},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,i=e.length;++r<i;)za(e[r],n)}},Vx=function(t,n){t&&Hx.hasOwnProperty(t.type)?Hx[t.type](t,n):za(t,n)},Wx=Xm(),$x=Xm(),Zx={point:Ca,lineStart:Ca,lineEnd:Ca,polygonStart:function(){Wx.reset(),Zx.lineStart=La,Zx.lineEnd=Ra},polygonEnd:function(){var t=+Wx;$x.add(t<0?Ex+t:t),this.lineStart=this.lineEnd=this.point=Ca},sphere:function(){$x.add(Ex)}},Gx=function(t){return $x.reset(),Vx(t,Zx),2*$x},Jx=Xm(),Qx={point:Xa,lineStart:Wa,lineEnd:$a,polygonStart:function(){Qx.point=Za,Qx.lineStart=Ga,Qx.lineEnd=Ja,Jx.reset(),Zx.polygonStart()},polygonEnd:function(){Zx.polygonEnd(),Qx.point=Xa,Qx.lineStart=Wa,Qx.lineEnd=$a,Wx<0?(Jm=-(Km=180),Qm=-(tx=90)):Jx>Tx?tx=90:Jx<-Tx&&(Qm=-90),ux[0]=Jm,ux[1]=Km}},Kx=function(t){var n,e,r,i,o,u,a;if(tx=Km=-(Jm=Qm=1/0),ox=[],Vx(t,Qx),e=ox.length){for(ox.sort(Ka),n=1,r=ox[0],o=[r];n<e;++n)i=ox[n],tc(r,i[0])||tc(r,i[1])?(Qa(r[0],i[1])>Qa(r[0],r[1])&&(r[1]=i[1]),Qa(i[0],r[1])>Qa(r[0],r[1])&&(r[0]=i[0])):o.push(r=i);for(u=-(1/0),e=o.length-1,n=0,r=o[e];n<=e;r=i,++n)i=o[n],(a=Qa(r[1],i[0]))>u&&(u=a,Jm=i[0],Km=r[1])}return ox=ux=null,Jm===1/0||Qm===1/0?[[NaN,NaN],[NaN,NaN]]:[[Jm,Qm],[Km,tx]]},tb={sphere:Ca,point:nc,lineStart:rc,lineEnd:uc,polygonStart:function(){tb.lineStart=ac,tb.lineEnd=cc},polygonEnd:function(){tb.lineStart=rc,tb.lineEnd=uc}},nb=function(t){ax=cx=sx=fx=lx=hx=px=dx=vx=_x=yx=0,Vx(t,tb);var n=vx,e=_x,r=yx,i=n*n+e*e+r*r;return i<Nx&&(n=hx,e=px,r=dx,cx<Tx&&(n=sx,e=fx,r=lx),i=n*n+e*e+r*r,i<Nx)?[NaN,NaN]:[Lx(e,n)*Cx,Aa(r/Bx(i))*Cx]},eb=function(t){return function(){return t}},rb=function(t,n){function e(e,r){return e=t(e,r),n(e[0],e[1])}return t.invert&&n.invert&&(e.invert=function(e,r){return e=n.invert(e,r),e&&t.invert(e[0],e[1])}),e};lc.invert=lc;var ib,ob,ub,ab,cb,sb,fb,lb,hb,pb,db,vb=function(t){function n(n){return n=t(n[0]*zx,n[1]*zx),n[0]*=Cx,n[1]*=Cx,n}return t=hc(t[0]*zx,t[1]*zx,t.length>2?t[2]*zx:0),n.invert=function(n){return n=t.invert(n[0]*zx,n[1]*zx),n[0]*=Cx,n[1]*=Cx,n},n},_b=function(){function t(t,n){e.push(t=r(t,n)),t[0]*=Cx,t[1]*=Cx}function n(){var t=i.apply(this,arguments),n=o.apply(this,arguments)*zx,c=u.apply(this,arguments)*zx;return e=[],r=hc(-t[0]*zx,-t[1]*zx,0).invert,_c(a,n,c,1),t={type:"Polygon",coordinates:[e]},e=r=null,t}var e,r,i=eb([0,0]),o=eb(90),u=eb(6),a={point:t};return n.center=function(t){return arguments.length?(i="function"==typeof t?t:eb([+t[0],+t[1]]),n):i},n.radius=function(t){return arguments.length?(o="function"==typeof t?t:eb(+t),n):o},n.precision=function(t){return arguments.length?(u="function"==typeof t?t:eb(+t),n):u},n},yb=function(){var t,n=[];return{point:function(n,e){t.push([n,e])},lineStart:function(){n.push(t=[])},lineEnd:Ca,rejoin:function(){n.length>1&&n.push(n.pop().concat(n.shift()))},result:function(){var e=n;return n=[],t=null,e}}},gb=function(t,n,e,r,i,o){var u,a=t[0],c=t[1],s=n[0],f=n[1],l=0,h=1,p=s-a,d=f-c;if(u=e-a,p||!(u>0)){if(u/=p,p<0){if(u<l)return;u<h&&(h=u)}else if(p>0){if(u>h)return;u>l&&(l=u)}if(u=i-a,p||!(u<0)){if(u/=p,p<0){if(u>h)return;u>l&&(l=u)}else if(p>0){if(u<l)return;u<h&&(h=u)}if(u=r-c,d||!(u>0)){if(u/=d,d<0){if(u<l)return;u<h&&(h=u)}else if(d>0){if(u>h)return;u>l&&(l=u)}if(u=o-c,d||!(u<0)){if(u/=d,d<0){if(u>h)return;u>l&&(l=u)}else if(d>0){if(u<l)return;u<h&&(h=u)}return l>0&&(t[0]=a+l*p,t[1]=c+l*d),h<1&&(n[0]=a+h*p,n[1]=c+h*d),!0}}}}},mb=function(t,n){return Px(t[0]-n[0])<Tx&&Px(t[1]-n[1])<Tx},xb=function(t,n,e,r,i){var o,u,a=[],c=[];if(t.forEach(function(t){if(!((n=t.length-1)<=0)){var n,e,r=t[0],u=t[n];if(mb(r,u)){for(i.lineStart(),o=0;o<n;++o)i.point((r=t[o])[0],r[1]);return void i.lineEnd()}a.push(e=new gc(r,t,null,!0)),c.push(e.o=new gc(r,null,e,!1)),a.push(e=new gc(u,t,null,!1)),c.push(e.o=new gc(u,null,e,!0))}}),a.length){for(c.sort(n),mc(a),mc(c),o=0,u=c.length;o<u;++o)c[o].e=e=!e;for(var s,f,l=a[0];;){for(var h=l,p=!0;h.v;)if((h=h.n)===l)return;s=h.z,i.lineStart();do{if(h.v=h.o.v=!0,h.e){if(p)for(o=0,u=s.length;o<u;++o)i.point((f=s[o])[0],f[1]);else r(h.x,h.n.x,1,i);h=h.n}else{if(p)for(s=h.p.z,o=s.length-1;o>=0;--o)i.point((f=s[o])[0],f[1]);else r(h.x,h.p.x,-1,i);h=h.p}h=h.o,s=h.z,p=!p}while(!h.v);i.lineEnd()}}},bb=1e9,wb=-bb,Mb=function(){var t,n,e,r=0,i=0,o=960,u=500;return e={stream:function(e){return t&&n===e?t:t=xc(r,i,o,u)(n=e)},extent:function(a){return arguments.length?(r=+a[0][0],i=+a[0][Line truncated
+162
View File
@@ -0,0 +1,162 @@
body{margin:0}a:active,a:hover{outline:0}code{font-size:1em}input,textarea{color:inherit;font:inherit;margin:0}input[type=submit]{-webkit-appearance:button;cursor:pointer}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}textarea{overflow:auto}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}.grd{padding-left:1rem;padding-right:1rem}.grd-row{box-sizing:border-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;max-width:100%}.grd-row-col-1-6{max-width:16.66667%;-webkit-flex-basis:16.66667%;-ms-flex-preferred-size:16.66667%;flex-basis:16.66667%}.grd-row-col-2-6{max-width:33.33333%;-webkit-flex-basis:33.33333%;-ms-flex-preferred-size:33.33333%;flex-basis:33.33333%}.grd-row-col-3-6{max-width:50%;-webkit-flex-basis:50%;-ms-flex-preferred-size:50%;flex-basis:50%}.grd-row-col-4-6{max-width:66.66667%;-webkit-flex-basis:66.66667%;-ms-flex-preferred-size:66.66667%;flex-basis:66.66667%}.grd-row-col-5-6{max-width:83.33333%;-webkit-flex-basis:83.33333%;-ms-flex-preferred-size:83.33333%;flex-basis:83.33333%}.grd-row-col-6{max-width:100%;-webkit-flex-basis:100%;-ms-flex-preferred-size:100%;flex-basis:100%}.grd-row-col-1-6,.grd-row-col-2-6,.grd-row-col-3-6,.grd-row-col-4-6,.grd-row-col-5-6,.grd-row-col-6{-webkit-flex:1;-ms-flex:1;flex:1;-webkit-flex-direction:column;-ms-flex-direction:column;flex-direction:column;box-sizing:border-box}*,:after,:before{box-sizing:border-box}.measure{max-width:48rem;margin:0 auto}a{color:#3498db}a:active,a:focus,a:hover{color:#217dbb}.bg--red{background-color:#e74c3c}.bg--orange{background-color:#f39c12}.bg--blue{background-color:#3498db}.bg--green{background-color:#25ba84}.bg--white{background-color:#fff}.bg--light-gray{background-color:rgba(216,216,216,.99)}.bg--mid-gray{background-color:rgba(144,144,144,.99)}.bg--dark-gray{background-color:rgba(72,72,72,.99)}.bg--off-white{background-color:rgba(250,250,250,.99)}.fnt--red{color:#e74c3c}.fnt--orange{color:#f39c12}.fnt--blue{color:#3498db}.fnt--green{color:#25ba84}.fnt--white{color:#fff}.fnt--light-gray{color:rgba(216,216,216,.99)}.fnt--mid-gray{color:rgba(144,144,144,.99)}.fnt--dark-gray{color:rgba(72,72,72,.99)}.fnt--off-white{color:rgba(250,250,250,.99)}.m0{margin:0}.m1{margin:1rem}.mx1{margin-left:1rem;margin-right:1rem}.my1{margin-top:1rem;margin-bottom:1rem}.m2{margin:2rem}.mx2{margin-left:2rem;margin-right:2rem}.my2{margin-top:2rem;margin-bottom:2rem}.p0{padding:0}.p1{padding:1rem}.px1{padding-left:1rem;padding-right:1rem}.py1{padding-top:1rem;padding-bottom:1rem}.p2{padding:2rem}.px2{padding-left:2rem;padding-right:2rem}.py2{padding-top:2rem;padding-bottom:2rem}html{font-size:12px}@media screen and (min-width:32rem) and (max-width:48rem){html{font-size:15px}}@media screen and (min-width:48rem){html{font-size:16px}}body{font-family:HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:400;line-height:1.85;color:#333}p{font-size:1rem;margin-bottom:1.3rem}.h1,.h2,.h3,.h4,h1,h2,h3,h4{margin:1.414rem 0 .5rem;font-weight:inherit;line-height:1.42}.h1,h1{margin-top:0;font-size:3.998rem}.h2,h2{font-size:2.827rem}.h3,h3{font-size:1.999rem}.h4,h4{font-size:1.414rem}.h5,table th{font-size:1.121rem}.h6,h6{font-size:.88rem}.btn--s,.small,small{font-size:.707em}code{font-family:Monaco,"Lucida Console",Courier,monospace}.italic{font-style:italic}.thin{font-weight:100}.bold{font-weight:700}.caps,table th{font-variant:small-caps}.muted{opacity:.7}.txt--center{text-align:center}.txt--right{text-align:right}.txt--left,table th{text-align:left}.oflow-y--scroll{overflow-y:scroll}.w100--s{width:100%;display:block}@media screen and (min-width:32rem){.w100--s{width:auto;display:inline-block}}img,textarea{max-width:100%}.btn,.btn--blue,.btn--gray,.btn--green,.btn--link,.btn--red{border-radius:3px}.brdr--light-gray{border:thin solid rgba(216,216,216,.99)}.brdr--mid-gray{border:thin solid rgba(144,144,144,.99)}.brdr--dark-gray{border:thin solid rgba(72,72,72,.99)}.brdr--off-white{border:thin solid rgba(250,250,250,.99)}.btn,.btn--blue,.btn--gray,.btn--green,.btn--link,.btn--red{padding:.5rem 1rem;border:2px solid #ccc;color:#333;text-decoration:none;text-align:center}.btn:active,.btn:focus,.btn:hover{background-color:rgba(0,0,0,.05);color:#000}.btn--link{border-color:transparent;color:#3498db}.btn--link:hover{background-color:transparent;color:#1d6fa5}.btn--blue{border-color:#2792d9;background-color:#3498db;color:#fff}.btn--blue:active,.btn--blue:focus,.btn--blue:hover{color:#fff;background-color:#217dbb}.btn--green{border-color:#22a977;background-color:#25ba84;color:#fff}.btn--green:active,.btn--green:focus,.btn--green:hover{color:#fff;background-color:#1d8f65}.btn--gray{border-color:rgba(59,59,59,.99);background-color:rgba(72,72,72,.99);color:#fff}.btn--gray:active,.btn--gray:focus,.btn--gray:hover{color:#fff;background-color:Line truncated
/* Label styles: style as needed */
label {
display:block;
margin-top:2em;
font-size: 0.9em;
color:#777;
}
/* Container used for styling the custom select, the buttom class adds the bg gradient, corners, etc. */
.custom-select {
position: relative;
display:block;
margin-top:0.5em;
padding:0;
}
/* This is the native select, we're making everything but the text invisible so we can see the button styles in the wrapper */
.custom-select select {
width:100%;
margin:0;
background:none;
border: 1px solid transparent;
outline: none;
/* Prefixed box-sizing rules necessary for older browsers */
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
/* Remove select styling */
appearance: none;
-webkit-appearance: none;
/* Magic font size number to prevent iOS text zoom */
font-size:16px;
/* General select styles: change as needed */
font-family: helvetica, sans-serif;
font-weight: bold;
color: #444;
/*padding: .6em 1.9em .5em .8em;*/
padding: 0.4em 1.2em .3em .8em;
line-height:1.3;
}
/* Custom arrow sits on top of the select - could be an image, SVG, icon font, etc. or the arrow could just baked into the bg image on the select */
.custom-select::after {
content: "";
position: absolute;
width: 9px;
height: 8px;
top: 50%;
right: 1em;
margin-top:-4px;
background-image: url('select-arrow.png');
background-repeat: no-repeat;
background-size: 100%;
/* These hacks make the select behind the arrow clickable in some browsers */
pointer-events:none;
}
/* IE 10/11+ - This hides native dropdown button arrow so it will have the custom appearance, IE 9 and earlier get a native select - targeting hack via http://browserhacks.com/#hack-f1070533535a12744a0381a75087a915 */
_:-ms-input-placeholder, :root .custom-select select::-ms-expand {
display: none;
}
/* Removes the odd blue bg color behind the text in the select button in IE 10/11 and sets the text color to match the focus style's - fix via http://stackoverflow.com/questions/17553300/change-ie-background-color-on-unopened-focused-select-box */
_:-ms-input-placeholder, :root .custom-select select:focus::-ms-value {
background: transparent;
color: #222;
}
/* Firefox >= 2 -- Older versions of FF (v2 - 6) won't let us hide the native select arrow, so we'll just hide the custom icon and go with native styling. Targeting hack via http://browserhacks.com/#hack-756739b33c37fb7db4cce645bbf7ea5f */
/* Show only the native arrow */
body:last-child .custom-select::after, x:-moz-any-link {
display: none;
}
/* reduce padding */
body:last-child .custom-select select, x:-moz-any-link {
padding-right: .8em;
}
/* Firefox 6+ -- Hide the native select and arrow. We've found the simplest way to hide the native styling in FF is to make the select bigger than its container and clip it. */
/* The specific FF selector used below successfully overrides the previous rule that turns off the custom icon; other FF hacky selectors we tried, like `*>.custom-select::after`, did not undo the previous rule. Targeting hack via http://browserhacks.com/#hack-443a4eb168ccf066e7c2909be4911af1 */
/* Show the custom arrow again */
_::-moz-progress-bar, body:last-child .custom-select:after {
display: block;
}
/* Hacks to hide the native select appearance */
_::-moz-progress-bar, body:last-child .custom-select select {
-moz-appearance: window;
text-indent: 0.01px;
text-overflow: "";
/* increase padding to make room for menu icon */
padding-right: 13%;
}
/* In FF 30+ -- Set overflow:hidden on the wrapper to clip the native select's arrow. Need to get extra wide (120%) because newest Firefox/Android is terrible. The downside is this makes the menu 20% wider than it should be when it opens. Hack targeting via http://browserhacks.com/#hack-cfd4c21603b122acfda8e81f41cdb320 */
@supports (-moz-appearance:meterbar) and (background-blend-mode:difference,normal) {
/* Clip select with the container */
_::-moz-progress-bar, body:last-child .custom-select {
overflow: hidden;
}
/* Make select extra wide */
_::-moz-progress-bar, body:last-child .custom-select select {
width: 120%;
}
}
/* Firefox 7+ focus style - This works around the issue that -moz-appearance: window kills the normal select focus. Using semi-opaque because outline doesn't handle rounded corners */
_::-moz-progress-bar, body:last-child .custom-select select:focus {
outline: 2px solid rgba(180,222,250, .7);
}
/* Opera - Pre-Blink nix the custom arrow, go with a native select button */
x:-o-prefocus, .custom-select::after {
display:none;
}
/* Hover style */
.custom-select:hover {
border:1px solid #888;
}
/* Focus style */
.custom-select select:focus {
outline:none;
box-shadow: 0 0 1px 3px rgba(180,222,250, 1);
background-color:transparent;
color: #222;
border:1px solid #aaa;
}
/* Firefox focus has odd artifacts around the text, this kills that */
.custom-select select:-moz-focusring {
color: transparent;
text-shadow: 0 0 0 #000;
}
.custom-select option {
font-weight:normal;
}
/* These are just demo button-y styles, style as you like */
.button {
border: 1px solid #bbb;
border-radius: .3em;
box-shadow: 0 1px 0 1px rgba(0,0,0,.04);
background: #f3f3f3; /* Old browsers */
background: -moz-linear-gradient(top, #ffffff 0%, #e5e5e5 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(100%,#e5e5e5)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #ffffff 0%,#e5e5e5 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #ffffff 0%,#e5e5e5 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #ffffff 0%,#e5e5e5 100%); /* IE10+ */
background: linear-gradient(to bottom, #ffffff 0%,#e5e5e5 100%); /* W3C */
}
+193
View File
@@ -0,0 +1,193 @@
// HumanizeDuration.js - http://git.io/j0HgmQ
;(function () {
var languages = {
en: {
y: function (c) { return 'year' + (c !== 1 ? 's' : '') },
mo: function (c) { return 'month' + (c !== 1 ? 's' : '') },
w: function (c) { return 'week' + (c !== 1 ? 's' : '') },
d: function (c) { return 'day' + (c !== 1 ? 's' : '') },
h: function (c) { return 'hour' + (c !== 1 ? 's' : '') },
m: function (c) { return 'minute' + (c !== 1 ? 's' : '') },
s: function (c) { return 'second' + (c !== 1 ? 's' : '') },
ms: function (c) { return 'millisecond' + (c !== 1 ? 's' : '') },
decimal: '.'
}
}
// You can create a humanizer, which returns a function with default
// parameters.
function humanizer (passedOptions) {
var result = function humanizer (ms, humanizerOptions) {
var options = extend({}, result, humanizerOptions || {})
return doHumanization(ms, options)
}
return extend(result, {
language: 'en',
delimiter: ', ',
spacer: ' ',
conjunction: '',
serialComma: true,
units: ['y', 'mo', 'w', 'd', 'h', 'm', 's'],
languages: {},
round: false,
unitMeasures: {
y: 31557600000,
mo: 2629800000,
w: 604800000,
d: 86400000,
h: 3600000,
m: 60000,
s: 1000,
ms: 1
}
}, passedOptions)
}
// The main function is just a wrapper around a default humanizer.
var humanizeDuration = humanizer({})
// doHumanization does the bulk of the work.
function doHumanization (ms, options) {
var i, len, piece
// Make sure we have a positive number.
// Has the nice sideffect of turning Number objects into primitives.
ms = Math.abs(ms)
var dictionary = options.languages[options.language] || languages[options.language]
if (!dictionary) {
throw new Error('No language ' + dictionary + '.')
}
var pieces = []
// Start at the top and keep removing units, bit by bit.
var unitName, unitMS, unitCount
for (i = 0, len = options.units.length; i < len; i++) {
unitName = options.units[i]
unitMS = options.unitMeasures[unitName]
// What's the number of full units we can fit?
if (i + 1 === len) {
unitCount = ms / unitMS
} else {
unitCount = Math.floor(ms / unitMS)
}
// Add the string.
pieces.push({
unitCount: unitCount,
unitName: unitName
})
// Remove what we just figured out.
ms -= unitCount * unitMS
}
var firstOccupiedUnitIndex = 0
for (i = 0; i < pieces.length; i++) {
if (pieces[i].unitCount) {
firstOccupiedUnitIndex = i
break
}
}
if (options.round) {
var ratioToLargerUnit, previousPiece
for (i = pieces.length - 1; i >= 0; i--) {
piece = pieces[i]
piece.unitCount = Math.round(piece.unitCount)
if (i === 0) { break }
previousPiece = pieces[i - 1]
ratioToLargerUnit = options.unitMeasures[previousPiece.unitName] / options.unitMeasures[piece.unitName]
if ((piece.unitCount % ratioToLargerUnit) === 0 || (options.largest && ((options.largest - 1) < (i - firstOccupiedUnitIndex)))) {
previousPiece.unitCount += piece.unitCount / ratioToLargerUnit
piece.unitCount = 0
}
}
}
var result = []
for (i = 0, pieces.length; i < len; i++) {
piece = pieces[i]
if (piece.unitCount) {
result.push(render(piece.unitCount, piece.unitName, dictionary, options))
}
if (result.length === options.largest) { break }
}
if (result.length) {
if (!options.conjunction || result.length === 1) {
return result.join(options.delimiter)
} else if (result.length === 2) {
return result.join(options.conjunction)
} else if (result.length > 2) {
return result.slice(0, -1).join(options.delimiter) + (options.serialComma ? ',' : '') + options.conjunction + result.slice(-1)
}
} else {
return render(0, options.units[options.units.length - 1], dictionary, options)
}
}
function render (count, type, dictionary, options) {
var decimal
if (options.decimal === void 0) {
decimal = dictionary.decimal
} else {
decimal = options.decimal
}
var countStr = count.toString().replace('.', decimal)
var dictionaryValue = dictionary[type]
var word
if (typeof dictionaryValue === 'function') {
word = dictionaryValue(count)
} else {
word = dictionaryValue
}
return countStr + options.spacer + word
}
function extend (destination) {
var source
for (var i = 1; i < arguments.length; i++) {
source = arguments[i]
for (var prop in source) {
if (source.hasOwnProperty(prop)) {
destination[prop] = source[prop]
}
}
}
return destination
}
humanizeDuration.getSupportedLanguages = function getSupportedLanguages () {
var result = []
for (var language in languages) {
if (languages.hasOwnProperty(language)) {
result.push(language)
}
}
return result
}
humanizeDuration.humanizer = humanizer
if (typeof define === 'function' && define.amd) {
define(function () {
return humanizeDuration
})
} else if (typeof module !== 'undefined' && module.exports) {
module.exports = humanizeDuration
} else {
this.humanizeDuration = humanizeDuration
}
})(); // eslint-disable-line semi
+548
View File
@@ -0,0 +1,548 @@
//! moment.js
//! version : 2.15.2
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return md.apply(null,arguments)}
// This is done to register the method called with moment()
// without creating circular dependencies.
function b(a){md=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){
// IE8 will treat undefined and null as object if it wasn't for
// input != null
return null!=a&&"[object Object]"===Object.prototype.toString.call(a)}function e(a){var b;for(b in a)
// even if its not own property I'd still call it non-empty
return!1;return!0}function f(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function g(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c],c));return d}function h(a,b){return Object.prototype.hasOwnProperty.call(a,b)}function i(a,b){for(var c in b)h(b,c)&&(a[c]=b[c]);return h(b,"toString")&&(a.toString=b.toString),h(b,"valueOf")&&(a.valueOf=b.valueOf),a}function j(a,b,c,d){return qb(a,b,c,d,!0).utc()}function k(){
// We need to deep clone this object.
return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],meridiem:null}}function l(a){return null==a._pf&&(a._pf=k()),a._pf}function m(a){if(null==a._isValid){var b=l(a),c=nd.call(b.parsedDateParts,function(a){return null!=a}),d=!isNaN(a._d.getTime())&&b.overflow<0&&!b.empty&&!b.invalidMonth&&!b.invalidWeekday&&!b.nullInput&&!b.invalidFormat&&!b.userInvalidated&&(!b.meridiem||b.meridiem&&c);if(a._strict&&(d=d&&0===b.charsLeftOver&&0===b.unusedTokens.length&&void 0===b.bigHour),null!=Object.isFrozen&&Object.isFrozen(a))return d;a._isValid=d}return a._isValid}function n(a){var b=j(NaN);return null!=a?i(l(b),a):l(b).userInvalidated=!0,b}function o(a){return void 0===a}function p(a,b){var c,d,e;if(o(b._isAMomentObject)||(a._isAMomentObject=b._isAMomentObject),o(b._i)||(a._i=b._i),o(b._f)||(a._f=b._f),o(b._l)||(a._l=b._l),o(b._strict)||(a._strict=b._strict),o(b._tzm)||(a._tzm=b._tzm),o(b._isUTC)||(a._isUTC=b._isUTC),o(b._offset)||(a._offset=b._offset),o(b._pf)||(a._pf=l(b)),o(b._locale)||(a._locale=b._locale),od.length>0)for(c in od)d=od[c],e=b[d],o(e)||(a[d]=e);return a}
// Moment prototype object
function q(b){p(this,b),this._d=new Date(null!=b._d?b._d.getTime():NaN),
// Prevent infinite loop in case updateOffset creates new moment
// objects.
pd===!1&&(pd=!0,a.updateOffset(this),pd=!1)}function r(a){return a instanceof q||null!=a&&null!=a._isAMomentObject}function s(a){return a<0?Math.ceil(a)||0:Math.floor(a)}function t(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=s(b)),c}
// compare two arrays, return the number of differences
function u(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;d<e;d++)(c&&a[d]!==b[d]||!c&&t(a[d])!==t(b[d]))&&g++;return g+f}function v(b){a.suppressDeprecationWarnings===!1&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+b)}function w(b,c){var d=!0;return i(function(){if(null!=a.deprecationHandler&&a.deprecationHandler(null,b),d){for(var e,f=[],g=0;g<arguments.length;g++){if(e="","object"==typeof arguments[g]){e+="\n["+g+"] ";for(var h in arguments[0])e+=h+": "+arguments[0][h]+", ";e=e.slice(0,-2)}else e=arguments[g];f.push(e)}v(b+"\nArguments: "+Array.prototype.slice.call(f).join("")+"\n"+(new Error).stack),d=!1}return c.apply(this,arguments)},c)}function x(b,c){null!=a.deprecationHandler&&a.deprecationHandler(b,c),qd[b]||(v(c),qd[b]=!0)}function y(a){return a instanceof Function||"[object Function]"===Object.prototype.toString.call(a)}function z(a){var b,c;for(c in a)b=a[c],y(b)?this[c]=b:this["_"+c]=b;this._config=a,
// Lenient ordinal parsing accepts just a number in addition to
// number + (possibly) stuff coming from _ordinalParseLenient.
this._ordinalParseLenient=new RegExp(this._ordinalParse.source+"|"+/\d{1,2}/.source)}function A(a,b){var c,e=i({},a);for(c in b)h(b,c)&&(d(a[c])&&d(b[c])?(e[c]={},i(e[c],a[c]),i(e[c],b[c])):null!=b[c]?e[c]=b[c]:delete e[c]);for(c in a)h(a,c)&&!h(b,c)&&d(a[c])&&(
// make sure changes to properties don't modify parent config
e[c]=i({},e[c]));return e}function B(a){null!=a&&this.set(a)}function C(a,b,c){var d=this._calendar[a]||this._calendar.sameElse;return y(d)?d.call(b,c):d}function D(a){var b=this._longDateFormat[a],c=this._longDateFormat[a.toUpperCase()];return b||!c?b:(this._longDateFormat[a]=c.replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a])}function E(){return this._invalidDate}function F(a){return this._ordinal.replace("%d",a)}function G(a,b,c,d){var e=this._relativeTime[c];return y(e)?e(a,b,c,d):e.replace(/%d/i,a)}function H(a,b){var c=this._relativeTime[a>0?"future":"past"];return y(c)?c(b):c.replace(/%s/i,b)}function I(a,b){var c=a.toLowerCase();zd[c]=zd[c+"s"]=zd[b]=a}function J(a){return"string"==typeof a?zd[a]||zd[a.toLowerCase()]:void 0}function K(a){var b,c,d={};for(c in a)h(a,c)&&(b=J(c),b&&(d[b]=a[c]));return d}function L(a,b){Ad[a]=b}function M(a){var b=[];for(var c in a)b.push({unit:c,priority:Ad[c]});return b.sort(function(a,b){return a.priority-b.priority}),b}function N(b,c){return function(d){return null!=d?(P(this,b,d),a.updateOffset(this,c),this):O(this,b)}}function O(a,b){return a.isValid()?a._d["get"+(a._isUTC?"UTC":"")+b]():NaN}function P(a,b,c){a.isValid()&&a._d["set"+(a._isUTC?"UTC":"")+b](c)}
// MOMENTS
function Q(a){return a=J(a),y(this[a])?this[a]():this}function R(a,b){if("object"==typeof a){a=K(a);for(var c=M(a),d=0;d<c.length;d++)this[c[d].unit](a[c[d].unit])}else if(a=J(a),y(this[a]))return this[a](b);return this}function S(a,b,c){var d=""+Math.abs(a),e=b-d.length,f=a>=0;return(f?c?"+":"":"-")+Math.pow(10,Math.max(0,e)).toString().substr(1)+d}
// token: 'M'
// padded: ['MM', 2]
// ordinal: 'Mo'
// callback: function () { this.month() + 1 }
function T(a,b,c,d){var e=d;"string"==typeof d&&(e=function(){return this[d]()}),a&&(Ed[a]=e),b&&(Ed[b[0]]=function(){return S(e.apply(this,arguments),b[1],b[2])}),c&&(Ed[c]=function(){return this.localeData().ordinal(e.apply(this,arguments),a)})}function U(a){return a.match(/\[[\s\S]/)?a.replace(/^\[|\]$/g,""):a.replace(/\\/g,"")}function V(a){var b,c,d=a.match(Bd);for(b=0,c=d.length;b<c;b++)Ed[d[b]]?d[b]=Ed[d[b]]:d[b]=U(d[b]);return function(b){var e,f="";for(e=0;e<c;e++)f+=d[e]instanceof Function?d[e].call(b,a):d[e];return f}}
// format date using native date object
function W(a,b){return a.isValid()?(b=X(b,a.localeData()),Dd[b]=Dd[b]||V(b),Dd[b](a)):a.localeData().invalidDate()}function X(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(Cd.lastIndex=0;d>=0&&Cd.test(a);)a=a.replace(Cd,c),Cd.lastIndex=0,d-=1;return a}function Y(a,b,c){Wd[a]=y(b)?b:function(a,d){return a&&c?c:b}}function Z(a,b){return h(Wd,a)?Wd[a](b._strict,b._locale):new RegExp($(a))}
// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
function $(a){return _(a.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(a,b,c,d,e){return b||c||d||e}))}function _(a){return a.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}function aa(a,b){var c,d=b;for("string"==typeof a&&(a=[a]),"number"==typeof b&&(d=function(a,c){c[b]=t(a)}),c=0;c<a.length;c++)Xd[a[c]]=d}function ba(a,b){aa(a,function(a,c,d,e){d._w=d._w||{},b(a,d._w,d,e)})}function ca(a,b,c){null!=b&&h(Xd,a)&&Xd[a](b,c._a,c,a)}function da(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function ea(a,b){return a?c(this._months)?this._months[a.month()]:this._months[(this._months.isFormat||fe).test(b)?"format":"standalone"][a.month()]:this._months}function fa(a,b){return a?c(this._monthsShort)?this._monthsShort[a.month()]:this._monthsShort[fe.test(b)?"format":"standalone"][a.month()]:this._monthsShort}function ga(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._monthsParse)for(
// this is not used
this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],d=0;d<12;++d)f=j([2e3,d]),this._shortMonthsParse[d]=this.monthsShort(f,"").toLocaleLowerCase(),this._longMonthsParse[d]=this.months(f,"").toLocaleLowerCase();return c?"MMM"===b?(e=sd.call(this._shortMonthsParse,g),e!==-1?e:null):(e=sd.call(this._longMonthsParse,g),e!==-1?e:null):"MMM"===b?(e=sd.call(this._shortMonthsParse,g),e!==-1?e:(e=sd.call(this._longMonthsParse,g),e!==-1?e:null)):(e=sd.call(this._longMonthsParse,g),e!==-1?e:(e=sd.call(this._shortMonthsParse,g),e!==-1?e:null))}function ha(a,b,c){var d,e,f;if(this._monthsParseExact)return ga.call(this,a,b,c);
// TODO: add sorting
// Sorting makes sure if one month (or abbr) is a prefix of another
// see sorting in computeMonthsParse
for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),d=0;d<12;d++){
// test the regex
if(
// make the regex if we don't have it already
e=j([2e3,d]),c&&!this._longMonthsParse[d]&&(this._longMonthsParse[d]=new RegExp("^"+this.months(e,"").replace(".","")+"$","i"),this._shortMonthsParse[d]=new RegExp("^"+this.monthsShort(e,"").replace(".","")+"$","i")),c||this._monthsParse[d]||(f="^"+this.months(e,"")+"|^"+this.monthsShort(e,""),this._monthsParse[d]=new RegExp(f.replace(".",""),"i")),c&&"MMMM"===b&&this._longMonthsParse[d].test(a))return d;if(c&&"MMM"===b&&this._shortMonthsParse[d].test(a))return d;if(!c&&this._monthsParse[d].test(a))return d}}
// MOMENTS
function ia(a,b){var c;if(!a.isValid())
// No op
return a;if("string"==typeof b)if(/^\d+$/.test(b))b=t(b);else
// TODO: Another silent failure?
if(b=a.localeData().monthsParse(b),"number"!=typeof b)return a;return c=Math.min(a.date(),da(a.year(),b)),a._d["set"+(a._isUTC?"UTC":"")+"Month"](b,c),a}function ja(b){return null!=b?(ia(this,b),a.updateOffset(this,!0),this):O(this,"Month")}function ka(){return da(this.year(),this.month())}function la(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na.call(this),a?this._monthsShortStrictRegex:this._monthsShortRegex):(h(this,"_monthsShortRegex")||(this._monthsShortRegex=ie),this._monthsShortStrictRegex&&a?this._monthsShortStrictRegex:this._monthsShortRegex)}function ma(a){return this._monthsParseExact?(h(this,"_monthsRegex")||na.call(this),a?this._monthsStrictRegex:this._monthsRegex):(h(this,"_monthsRegex")||(this._monthsRegex=je),this._monthsStrictRegex&&a?this._monthsStrictRegex:this._monthsRegex)}function na(){function a(a,b){return b.length-a.length}var b,c,d=[],e=[],f=[];for(b=0;b<12;b++)
// make the regex if we don't have it already
c=j([2e3,b]),d.push(this.monthsShort(c,"")),e.push(this.months(c,"")),f.push(this.months(c,"")),f.push(this.monthsShort(c,""));for(
// Sorting makes sure if one month (or abbr) is a prefix of another it
// will match the longer piece.
d.sort(a),e.sort(a),f.sort(a),b=0;b<12;b++)d[b]=_(d[b]),e[b]=_(e[b]);for(b=0;b<24;b++)f[b]=_(f[b]);this._monthsRegex=new RegExp("^("+f.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+e.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+d.join("|")+")","i")}
// HELPERS
function oa(a){return pa(a)?366:365}function pa(a){return a%4===0&&a%100!==0||a%400===0}function qa(){return pa(this.year())}function ra(a,b,c,d,e,f,g){
//can't just apply() to create a date:
//http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
var h=new Date(a,b,c,d,e,f,g);
//the date constructor remaps years 0-99 to 1900-1999
return a<100&&a>=0&&isFinite(h.getFullYear())&&h.setFullYear(a),h}function sa(a){var b=new Date(Date.UTC.apply(null,arguments));
//the Date.UTC function remaps years 0-99 to 1900-1999
return a<100&&a>=0&&isFinite(b.getUTCFullYear())&&b.setUTCFullYear(a),b}
// start-of-first-week - start-of-year
function ta(a,b,c){var// first-week day -- which january is always in the first week (4 for iso, 1 for other)
d=7+b-c,
// first-week day local weekday -- which local weekday is fwd
e=(7+sa(a,0,d).getUTCDay()-b)%7;return-e+d-1}
//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
function ua(a,b,c,d,e){var f,g,h=(7+c-d)%7,i=ta(a,d,e),j=1+7*(b-1)+h+i;return j<=0?(f=a-1,g=oa(f)+j):j>oa(a)?(f=a+1,g=j-oa(a)):(f=a,g=j),{year:f,dayOfYear:g}}function va(a,b,c){var d,e,f=ta(a.year(),b,c),g=Math.floor((a.dayOfYear()-f-1)/7)+1;return g<1?(e=a.year()-1,d=g+wa(e,b,c)):g>wa(a.year(),b,c)?(d=g-wa(a.year(),b,c),e=a.year()+1):(e=a.year(),d=g),{week:d,year:e}}function wa(a,b,c){var d=ta(a,b,c),e=ta(a+1,b,c);return(oa(a)-d+e)/7}
// HELPERS
// LOCALES
function xa(a){return va(a,this._week.dow,this._week.doy).week}function ya(){return this._week.dow}function za(){return this._week.doy}
// MOMENTS
function Aa(a){var b=this.localeData().week(this);return null==a?b:this.add(7*(a-b),"d")}function Ba(a){var b=va(this,1,4).week;return null==a?b:this.add(7*(a-b),"d")}
// HELPERS
function Ca(a,b){return"string"!=typeof a?a:isNaN(a)?(a=b.weekdaysParse(a),"number"==typeof a?a:null):parseInt(a,10)}function Da(a,b){return"string"==typeof a?b.weekdaysParse(a)%7||7:isNaN(a)?null:a}function Ea(a,b){return a?c(this._weekdays)?this._weekdays[a.day()]:this._weekdays[this._weekdays.isFormat.test(b)?"format":"standalone"][a.day()]:this._weekdays}function Fa(a){return a?this._weekdaysShort[a.day()]:this._weekdaysShort}function Ga(a){return a?this._weekdaysMin[a.day()]:this._weekdaysMin}function Ha(a,b,c){var d,e,f,g=a.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],d=0;d<7;++d)f=j([2e3,1]).day(d),this._minWeekdaysParse[d]=this.weekdaysMin(f,"").toLocaleLowerCase(),this._shortWeekdaysParse[d]=this.weekdaysShort(f,"").toLocaleLowerCase(),this._weekdaysParse[d]=this.weekdays(f,"").toLocaleLowerCase();return c?"dddd"===b?(e=sd.call(this._weekdaysParse,g),e!==-1?e:null):"ddd"===b?(e=sd.call(this._shortWeekdaysParse,g),e!==-1?e:null):(e=sd.call(this._minWeekdaysParse,g),e!==-1?e:null):"dddd"===b?(e=sd.call(this._weekdaysParse,g),e!==-1?e:(e=sd.call(this._shortWeekdaysParse,g),e!==-1?e:(e=sd.call(this._minWeekdaysParse,g),e!==-1?e:null))):"ddd"===b?(e=sd.call(this._shortWeekdaysParse,g),e!==-1?e:(e=sd.call(this._weekdaysParse,g),e!==-1?e:(e=sd.call(this._minWeekdaysParse,g),e!==-1?e:null))):(e=sd.call(this._minWeekdaysParse,g),e!==-1?e:(e=sd.call(this._weekdaysParse,g),e!==-1?e:(e=sd.call(this._shortWeekdaysParse,g),e!==-1?e:null)))}function Ia(a,b,c){var d,e,f;if(this._weekdaysParseExact)return Ha.call(this,a,b,c);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),d=0;d<7;d++){
// test the regex
if(
// make the regex if we don't have it already
e=j([2e3,1]).day(d),c&&!this._fullWeekdaysParse[d]&&(this._fullWeekdaysParse[d]=new RegExp("^"+this.weekdays(e,"").replace(".",".?")+"$","i"),this._shortWeekdaysParse[d]=new RegExp("^"+this.weekdaysShort(e,"").replace(".",".?")+"$","i"),this._minWeekdaysParse[d]=new RegExp("^"+this.weekdaysMin(e,"").replace(".",".?")+"$","i")),this._weekdaysParse[d]||(f="^"+this.weekdays(e,"")+"|^"+this.weekdaysShort(e,"")+"|^"+this.weekdaysMin(e,""),this._weekdaysParse[d]=new RegExp(f.replace(".",""),"i")),c&&"dddd"===b&&this._fullWeekdaysParse[d].test(a))return d;if(c&&"ddd"===b&&this._shortWeekdaysParse[d].test(a))return d;if(c&&"dd"===b&&this._minWeekdaysParse[d].test(a))return d;if(!c&&this._weekdaysParse[d].test(a))return d}}
// MOMENTS
function Ja(a){if(!this.isValid())return null!=a?this:NaN;var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=Ca(a,this.localeData()),this.add(a-b,"d")):b}function Ka(a){if(!this.isValid())return null!=a?this:NaN;var b=(this.day()+7-this.localeData()._week.dow)%7;return null==a?b:this.add(a-b,"d")}function La(a){if(!this.isValid())return null!=a?this:NaN;
// behaves the same as moment#day except
// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
// as a setter, sunday should belong to the previous week.
if(null!=a){var b=Da(a,this.localeData());return this.day(this.day()%7?b:b-7)}return this.day()||7}function Ma(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysStrictRegex:this._weekdaysRegex):(h(this,"_weekdaysRegex")||(this._weekdaysRegex=pe),this._weekdaysStrictRegex&&a?this._weekdaysStrictRegex:this._weekdaysRegex)}function Na(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(h(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=qe),this._weekdaysShortStrictRegex&&a?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)}function Oa(a){return this._weekdaysParseExact?(h(this,"_weekdaysRegex")||Pa.call(this),a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(h(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=re),this._weekdaysMinStrictRegex&&a?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)}function Pa(){function a(a,b){return b.length-a.length}var b,c,d,e,f,g=[],h=[],i=[],k=[];for(b=0;b<7;b++)
// make the regex if we don't have it already
c=j([2e3,1]).day(b),d=this.weekdaysMin(c,""),e=this.weekdaysShort(c,""),f=this.weekdays(c,""),g.push(d),h.push(e),i.push(f),k.push(d),k.push(e),k.push(f);for(
// Sorting makes sure if one weekday (or abbr) is a prefix of another it
// will match the longer piece.
g.sort(a),h.sort(a),i.sort(a),k.sort(a),b=0;b<7;b++)h[b]=_(h[b]),i[b]=_(i[b]),k[b]=_(k[b]);this._weekdaysRegex=new RegExp("^("+k.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+h.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+g.join("|")+")","i")}
// FORMATTING
function Qa(){return this.hours()%12||12}function Ra(){return this.hours()||24}function Sa(a,b){T(a,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),b)})}
// PARSING
function Ta(a,b){return b._meridiemParse}
// LOCALES
function Ua(a){
// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
// Using charAt should be more compatible.
return"p"===(a+"").toLowerCase().charAt(0)}function Va(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"}function Wa(a){return a?a.toLowerCase().replace("_","-"):a}
// pick the locale from the array
// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
function Xa(a){for(var b,c,d,e,f=0;f<a.length;){for(e=Wa(a[f]).split("-"),b=e.length,c=Wa(a[f+1]),c=c?c.split("-"):null;b>0;){if(d=Ya(e.slice(0,b).join("-")))return d;if(c&&c.length>=b&&u(e,c,!0)>=b-1)
//the next array item is better than a shallower substring of this one
break;b--}f++}return null}function Ya(a){var b=null;
// TODO: Find a better way to register and load all the locales in Node
if(!we[a]&&"undefined"!=typeof module&&module&&module.exports)try{b=se._abbr,require("./locale/"+a),
// because defineLocale currently also sets the global locale, we
// want to undo that for lazy loaded locales
Za(b)}catch(a){}return we[a]}
// This function will load locale and then set the global locale. If
// no arguments are passed in, it will simply return the current global
// locale key.
function Za(a,b){var c;
// moment.duration._locale = moment._locale = data;
return a&&(c=o(b)?ab(a):$a(a,b),c&&(se=c)),se._abbr}function $a(a,b){if(null!==b){var c=ve;
// treat as if there is no base config
// backwards compat for now: also set the locale
return b.abbr=a,null!=we[a]?(x("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),c=we[a]._config):null!=b.parentLocale&&(null!=we[b.parentLocale]?c=we[b.parentLocale]._config:x("parentLocaleUndefined","specified parentLocale is not defined yet. See http://momentjs.com/guides/#/warnings/parent-locale/")),we[a]=new B(A(c,b)),Za(a),we[a]}
// useful for testing
return delete we[a],null}function _a(a,b){if(null!=b){var c,d=ve;
// MERGE
null!=we[a]&&(d=we[a]._config),b=A(d,b),c=new B(b),c.parentLocale=we[a],we[a]=c,
// backwards compat for now: also set the locale
Za(a)}else
// pass null for config to unupdate, useful for tests
null!=we[a]&&(null!=we[a].parentLocale?we[a]=we[a].parentLocale:null!=we[a]&&delete we[a]);return we[a]}
// returns locale data
function ab(a){var b;if(a&&a._locale&&a._locale._abbr&&(a=a._locale._abbr),!a)return se;if(!c(a)){if(
//short-circuit everything else
b=Ya(a))return b;a=[a]}return Xa(a)}function bb(){return rd(we)}function cb(a){var b,c=a._a;return c&&l(a).overflow===-2&&(b=c[Zd]<0||c[Zd]>11?Zd:c[$d]<1||c[$d]>da(c[Yd],c[Zd])?$d:c[_d]<0||c[_d]>24||24===c[_d]&&(0!==c[ae]||0!==c[be]||0!==c[ce])?_d:c[ae]<0||c[ae]>59?ae:c[be]<0||c[be]>59?be:c[ce]<0||c[ce]>999?ce:-1,l(a)._overflowDayOfYear&&(b<Yd||b>$d)&&(b=$d),l(a)._overflowWeeks&&b===-1&&(b=de),l(a)._overflowWeekday&&b===-1&&(b=ee),l(a).overflow=b),a}
// date from iso format
function db(a){var b,c,d,e,f,g,h=a._i,i=xe.exec(h)||ye.exec(h);if(i){for(l(a).iso=!0,b=0,c=Ae.length;b<c;b++)if(Ae[b][1].exec(i[1])){e=Ae[b][0],d=Ae[b][2]!==!1;break}if(null==e)return void(a._isValid=!1);if(i[3]){for(b=0,c=Be.length;b<c;b++)if(Be[b][1].exec(i[3])){
// match[2] should be 'T' or space
f=(i[2]||" ")+Be[b][0];break}if(null==f)return void(a._isValid=!1)}if(!d&&null!=f)return void(a._isValid=!1);if(i[4]){if(!ze.exec(i[4]))return void(a._isValid=!1);g="Z"}a._f=e+(f||"")+(g||""),jb(a)}else a._isValid=!1}
// date from iso format or fallback
function eb(b){var c=Ce.exec(b._i);return null!==c?void(b._d=new Date(+c[1])):(db(b),void(b._isValid===!1&&(delete b._isValid,a.createFromInputFallback(b))))}
// Pick the first defined of two or three arguments.
function fb(a,b,c){return null!=a?a:null!=b?b:c}function gb(b){
// hooks is actually the exported moment object
var c=new Date(a.now());return b._useUTC?[c.getUTCFullYear(),c.getUTCMonth(),c.getUTCDate()]:[c.getFullYear(),c.getMonth(),c.getDate()]}
// convert an array to a date.
// the array should mirror the parameters below
// note: all values past the year are optional and will default to the lowest possible value.
// [year, month, day , hour, minute, second, millisecond]
function hb(a){var b,c,d,e,f=[];if(!a._d){
// Default to current date.
// * if no year, month, day of month are given, default to today
// * if day of month is given, default month and year
// * if month is given, default only year
// * if year is given, don't default anything
for(d=gb(a),
//compute day of the year from weeks and weekdays
a._w&&null==a._a[$d]&&null==a._a[Zd]&&ib(a),
//if the day of the year is set, figure out what it is
a._dayOfYear&&(e=fb(a._a[Yd],d[Yd]),a._dayOfYear>oa(e)&&(l(a)._overflowDayOfYear=!0),c=sa(e,0,a._dayOfYear),a._a[Zd]=c.getUTCMonth(),a._a[$d]=c.getUTCDate()),b=0;b<3&&null==a._a[b];++b)a._a[b]=f[b]=d[b];
// Zero out whatever was not defaulted, including time
for(;b<7;b++)a._a[b]=f[b]=null==a._a[b]?2===b?1:0:a._a[b];
// Check for 24:00:00.000
24===a._a[_d]&&0===a._a[ae]&&0===a._a[be]&&0===a._a[ce]&&(a._nextDay=!0,a._a[_d]=0),a._d=(a._useUTC?sa:ra).apply(null,f),
// Apply timezone offset from input. The actual utcOffset can be changed
// with parseZone.
null!=a._tzm&&a._d.setUTCMinutes(a._d.getUTCMinutes()-a._tzm),a._nextDay&&(a._a[_d]=24)}}function ib(a){var b,c,d,e,f,g,h,i;b=a._w,null!=b.GG||null!=b.W||null!=b.E?(f=1,g=4,
// TODO: We need to take the current isoWeekYear, but that depends on
// how we interpret now (local, utc, fixed offset). So create
// a now version of current config (take local/utc/offset flags, and
// create now).
c=fb(b.GG,a._a[Yd],va(rb(),1,4).year),d=fb(b.W,1),e=fb(b.E,1),(e<1||e>7)&&(i=!0)):(f=a._locale._week.dow,g=a._locale._week.doy,c=fb(b.gg,a._a[Yd],va(rb(),f,g).year),d=fb(b.w,1),null!=b.d?(
// weekday -- low day numbers are considered next week
e=b.d,(e<0||e>6)&&(i=!0)):null!=b.e?(
// local weekday -- counting starts from begining of week
e=b.e+f,(b.e<0||b.e>6)&&(i=!0)):
// default to begining of week
e=f),d<1||d>wa(c,f,g)?l(a)._overflowWeeks=!0:null!=i?l(a)._overflowWeekday=!0:(h=ua(c,d,e,f,g),a._a[Yd]=h.year,a._dayOfYear=h.dayOfYear)}
// date from string and format string
function jb(b){
// TODO: Move this to another part of the creation flow to prevent circular deps
if(b._f===a.ISO_8601)return void db(b);b._a=[],l(b).empty=!0;
// This array is used to make a Date, either with `new Date` or `Date.UTC`
var c,d,e,f,g,h=""+b._i,i=h.length,j=0;for(e=X(b._f,b._locale).match(Bd)||[],c=0;c<e.length;c++)f=e[c],d=(h.match(Z(f,b))||[])[0],
// console.log('token', token, 'parsedInput', parsedInput,
// 'regex', getParseRegexForToken(token, config));
d&&(g=h.substr(0,h.indexOf(d)),g.length>0&&l(b).unusedInput.push(g),h=h.slice(h.indexOf(d)+d.length),j+=d.length),
// don't parse if it's not a known token
Ed[f]?(d?l(b).empty=!1:l(b).unusedTokens.push(f),ca(f,d,b)):b._strict&&!d&&l(b).unusedTokens.push(f);
// add remaining unparsed input length to the string
l(b).charsLeftOver=i-j,h.length>0&&l(b).unusedInput.push(h),
// clear _12h flag if hour is <= 12
b._a[_d]<=12&&l(b).bigHour===!0&&b._a[_d]>0&&(l(b).bigHour=void 0),l(b).parsedDateParts=b._a.slice(0),l(b).meridiem=b._meridiem,
// handle meridiem
b._a[_d]=kb(b._locale,b._a[_d],b._meridiem),hb(b),cb(b)}function kb(a,b,c){var d;
// Fallback
return null==c?b:null!=a.meridiemHour?a.meridiemHour(b,c):null!=a.isPM?(d=a.isPM(c),d&&b<12&&(b+=12),d||12!==b||(b=0),b):b}
// date from string and array of format strings
function lb(a){var b,c,d,e,f;if(0===a._f.length)return l(a).invalidFormat=!0,void(a._d=new Date(NaN));for(e=0;e<a._f.length;e++)f=0,b=p({},a),null!=a._useUTC&&(b._useUTC=a._useUTC),b._f=a._f[e],jb(b),m(b)&&(
// if there is any input that was not parsed add a penalty for that format
f+=l(b).charsLeftOver,
//or tokens
f+=10*l(b).unusedTokens.length,l(b).score=f,(null==d||f<d)&&(d=f,c=b));i(a,c||b)}function mb(a){if(!a._d){var b=K(a._i);a._a=g([b.year,b.month,b.day||b.date,b.hour,b.minute,b.second,b.millisecond],function(a){return a&&parseInt(a,10)}),hb(a)}}function nb(a){var b=new q(cb(ob(a)));
// Adding is smart enough around DST
return b._nextDay&&(b.add(1,"d"),b._nextDay=void 0),b}function ob(a){var b=a._i,d=a._f;return a._locale=a._locale||ab(a._l),null===b||void 0===d&&""===b?n({nullInput:!0}):("string"==typeof b&&(a._i=b=a._locale.preparse(b)),r(b)?new q(cb(b)):(c(d)?lb(a):f(b)?a._d=b:d?jb(a):pb(a),m(a)||(a._d=null),a))}function pb(b){var d=b._i;void 0===d?b._d=new Date(a.now()):f(d)?b._d=new Date(d.valueOf()):"string"==typeof d?eb(b):c(d)?(b._a=g(d.slice(0),function(a){return parseInt(a,10)}),hb(b)):"object"==typeof d?mb(b):"number"==typeof d?
// from milliseconds
b._d=new Date(d):a.createFromInputFallback(b)}function qb(a,b,f,g,h){var i={};
// object construction must be done this way.
// https://github.com/moment/moment/issues/1423
return"boolean"==typeof f&&(g=f,f=void 0),(d(a)&&e(a)||c(a)&&0===a.length)&&(a=void 0),i._isAMomentObject=!0,i._useUTC=i._isUTC=h,i._l=f,i._i=a,i._f=b,i._strict=g,nb(i)}function rb(a,b,c,d){return qb(a,b,c,d,!1)}
// Pick a moment m from moments so that m[fn](other) is true for all
// other. This relies on the function fn to be transitive.
//
// moments should either be an array of moment objects or an array, whose
// first element is an array of moment objects.
function sb(a,b){var d,e;if(1===b.length&&c(b[0])&&(b=b[0]),!b.length)return rb();for(d=b[0],e=1;e<b.length;++e)b[e].isValid()&&!b[e][a](d)||(d=b[e]);return d}
// TODO: Use [].sort instead?
function tb(){var a=[].slice.call(arguments,0);return sb("isBefore",a)}function ub(){var a=[].slice.call(arguments,0);return sb("isAfter",a)}function vb(a){var b=K(a),c=b.year||0,d=b.quarter||0,e=b.month||0,f=b.week||0,g=b.day||0,h=b.hour||0,i=b.minute||0,j=b.second||0,k=b.millisecond||0;
// representation for dateAddRemove
this._milliseconds=+k+1e3*j+// 1000
6e4*i+// 1000 * 60
1e3*h*60*60,//using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
// Because of dateAddRemove treats 24 hours as different from a
// day when working around DST, we need to store them separately
this._days=+g+7*f,
// It is impossible translate months into days without knowing
// which months you are are talking about, so we have to store
// it separately.
this._months=+e+3*d+12*c,this._data={},this._locale=ab(),this._bubble()}function wb(a){return a instanceof vb}function xb(a){return a<0?Math.round(-1*a)*-1:Math.round(a)}
// FORMATTING
function yb(a,b){T(a,0,0,function(){var a=this.utcOffset(),c="+";return a<0&&(a=-a,c="-"),c+S(~~(a/60),2)+b+S(~~a%60,2)})}function zb(a,b){var c=(b||"").match(a)||[],d=c[c.length-1]||[],e=(d+"").match(Ge)||["-",0,0],f=+(60*e[1])+t(e[2]);return"+"===e[0]?f:-f}
// Return a moment from input, that is local/utc/zone equivalent to model.
function Ab(b,c){var d,e;
// Use low-level api, because this fn is low-level api.
return c._isUTC?(d=c.clone(),e=(r(b)||f(b)?b.valueOf():rb(b).valueOf())-d.valueOf(),d._d.setTime(d._d.valueOf()+e),a.updateOffset(d,!1),d):rb(b).local()}function Bb(a){
// On Firefox.24 Date#getTimezoneOffset returns a floating point.
// https://github.com/moment/moment/pull/1871
return 15*-Math.round(a._d.getTimezoneOffset()/15)}
// MOMENTS
// keepLocalTime = true means only change the timezone, without
// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
// +0200, so we adjust the time as needed, to be valid.
//
// Keeping the time actually adds/subtracts (one hour)
// from the actual represented time. That is why we call updateOffset
// a second time. In case it wants us to change the offset again
// _changeInProgress == true case, then we have to adjust, because
// there is no such time in the given timezone.
function Cb(b,c){var d,e=this._offset||0;return this.isValid()?null!=b?("string"==typeof b?b=zb(Td,b):Math.abs(b)<16&&(b=60*b),!this._isUTC&&c&&(d=Bb(this)),this._offset=b,this._isUTC=!0,null!=d&&this.add(d,"m"),e!==b&&(!c||this._changeInProgress?Sb(this,Nb(b-e,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,a.updateOffset(this,!0),this._changeInProgress=null)),this):this._isUTC?e:Bb(this):null!=b?this:NaN}function Db(a,b){return null!=a?("string"!=typeof a&&(a=-a),this.utcOffset(a,b),this):-this.utcOffset()}function Eb(a){return this.utcOffset(0,a)}function Fb(a){return this._isUTC&&(this.utcOffset(0,a),this._isUTC=!1,a&&this.subtract(Bb(this),"m")),this}function Gb(){if(this._tzm)this.utcOffset(this._tzm);else if("string"==typeof this._i){var a=zb(Sd,this._i);0===a?this.utcOffset(0,!0):this.utcOffset(zb(Sd,this._i))}return this}function Hb(a){return!!this.isValid()&&(a=a?rb(a).utcOffset():0,(this.utcOffset()-a)%60===0)}function Ib(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()}function Jb(){if(!o(this._isDSTShifted))return this._isDSTShifted;var a={};if(p(a,this),a=ob(a),a._a){var b=a._isUTC?j(a._a):rb(a._a);this._isDSTShifted=this.isValid()&&u(a._a,b.toArray())>0}else this._isDSTShifted=!1;return this._isDSTShifted}function Kb(){return!!this.isValid()&&!this._isUTC}function Lb(){return!!this.isValid()&&this._isUTC}function Mb(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}function Nb(a,b){var c,d,e,f=a,
// matching against regexp is expensive, do it on demand
g=null;// checks for null or undefined
return wb(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(g=He.exec(a))?(c="-"===g[1]?-1:1,f={y:0,d:t(g[$d])*c,h:t(g[_d])*c,m:t(g[ae])*c,s:t(g[be])*c,ms:t(xb(1e3*g[ce]))*c}):(g=Ie.exec(a))?(c="-"===g[1]?-1:1,f={y:Ob(g[2],c),M:Ob(g[3],c),w:Ob(g[4],c),d:Ob(g[5],c),h:Ob(g[6],c),m:Ob(g[7],c),s:Ob(g[8],c)}):null==f?f={}:"object"==typeof f&&("from"in f||"to"in f)&&(e=Qb(rb(f.from),rb(f.to)),f={},f.ms=e.milliseconds,f.M=e.months),d=new vb(f),wb(a)&&h(a,"_locale")&&(d._locale=a._locale),d}function Ob(a,b){
// We'd normally use ~~inp for this, but unfortunately it also
// converts floats to ints.
// inp may be undefined, so careful calling replace on it.
var c=a&&parseFloat(a.replace(",","."));
// apply sign while we're at it
return(isNaN(c)?0:c)*b}function Pb(a,b){var c={milliseconds:0,months:0};return c.months=b.month()-a.month()+12*(b.year()-a.year()),a.clone().add(c.months,"M").isAfter(b)&&--c.months,c.milliseconds=+b-+a.clone().add(c.months,"M"),c}function Qb(a,b){var c;return a.isValid()&&b.isValid()?(b=Ab(b,a),a.isBefore(b)?c=Pb(a,b):(c=Pb(b,a),c.milliseconds=-c.milliseconds,c.months=-c.months),c):{milliseconds:0,months:0}}
// TODO: remove 'name' arg after deprecation is removed
function Rb(a,b){return function(c,d){var e,f;
//invert the arguments, but complain about it
return null===d||isNaN(+d)||(x(b,"moment()."+b+"(period, number) is deprecated. Please use moment()."+b+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),f=c,c=d,d=f),c="string"==typeof c?+c:c,e=Nb(c,d),Sb(this,e,a),this}}function Sb(b,c,d,e){var f=c._milliseconds,g=xb(c._days),h=xb(c._months);b.isValid()&&(e=null==e||e,f&&b._d.setTime(b._d.valueOf()+f*d),g&&P(b,"Date",O(b,"Date")+g*d),h&&ia(b,O(b,"Month")+h*d),e&&a.updateOffset(b,g||h))}function Tb(a,b){var c=a.diff(b,"days",!0);return c<-6?"sameElse":c<-1?"lastWeek":c<0?"lastDay":c<1?"sameDay":c<2?"nextDay":c<7?"nextWeek":"sameElse"}function Ub(b,c){
// We want to compare the start of today, vs this.
// Getting start-of-today depends on whether we're local/utc/offset or not.
var d=b||rb(),e=Ab(d,this).startOf("day"),f=a.calendarFormat(this,e)||"sameElse",g=c&&(y(c[f])?c[f].call(this,d):c[f]);return this.format(g||this.localeData().calendar(f,this,rb(d)))}function Vb(){return new q(this)}function Wb(a,b){var c=r(a)?a:rb(a);return!(!this.isValid()||!c.isValid())&&(b=J(o(b)?"millisecond":b),"millisecond"===b?this.valueOf()>c.valueOf():c.valueOf()<this.clone().startOf(b).valueOf())}function Xb(a,b){var c=r(a)?a:rb(a);return!(!this.isValid()||!c.isValid())&&(b=J(o(b)?"millisecond":b),"millisecond"===b?this.valueOf()<c.valueOf():this.clone().endOf(b).valueOf()<c.valueOf())}function Yb(a,b,c,d){return d=d||"()",("("===d[0]?this.isAfter(a,c):!this.isBefore(a,c))&&(")"===d[1]?this.isBefore(b,c):!this.isAfter(b,c))}function Zb(a,b){var c,d=r(a)?a:rb(a);return!(!this.isValid()||!d.isValid())&&(b=J(b||"millisecond"),"millisecond"===b?this.valueOf()===d.valueOf():(c=d.valueOf(),this.clone().startOf(b).valueOf()<=c&&c<=this.clone().endOf(b).valueOf()))}function $b(a,b){return this.isSame(a,b)||this.isAfter(a,b)}function _b(a,b){return this.isSame(a,b)||this.isBefore(a,b)}function ac(a,b,c){var d,e,f,g;// 1000
// 1000 * 60
// 1000 * 60 * 60
// 1000 * 60 * 60 * 24, negate dst
// 1000 * 60 * 60 * 24 * 7, negate dst
return this.isValid()?(d=Ab(a,this),d.isValid()?(e=6e4*(d.utcOffset()-this.utcOffset()),b=J(b),"year"===b||"month"===b||"quarter"===b?(g=bc(this,d),"quarter"===b?g/=3:"year"===b&&(g/=12)):(f=this-d,g="second"===b?f/1e3:"minute"===b?f/6e4:"hour"===b?f/36e5:"day"===b?(f-e)/864e5:"week"===b?(f-e)/6048e5:f),c?g:s(g)):NaN):NaN}function bc(a,b){
// difference in months
var c,d,e=12*(b.year()-a.year())+(b.month()-a.month()),
// b is in (anchor - 1 month, anchor + 1 month)
f=a.clone().add(e,"months");
//check for negative zero, return zero if negative zero
// linear across the month
// linear across the month
return b-f<0?(c=a.clone().add(e-1,"months"),d=(b-f)/(f-c)):(c=a.clone().add(e+1,"months"),d=(b-f)/(c-f)),-(e+d)||0}function cc(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")}function dc(){var a=this.clone().utc();return 0<a.year()&&a.year()<=9999?y(Date.prototype.toISOString)?this.toDate().toISOString():W(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):W(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")}function ec(b){b||(b=this.isUtc()?a.defaultFormatUtc:a.defaultFormat);var c=W(this,b);return this.localeData().postformat(c)}function fc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isValid())?Nb({to:this,from:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function gc(a){return this.from(rb(),a)}function hc(a,b){return this.isValid()&&(r(a)&&a.isValid()||rb(a).isValid())?Nb({from:this,to:a}).locale(this.locale()).humanize(!b):this.localeData().invalidDate()}function ic(a){return this.to(rb(),a)}
// If passed a locale key, it will set the locale for this
// instance. Otherwise, it will return the locale configuration
// variables for this instance.
function jc(a){var b;return void 0===a?this._locale._abbr:(b=ab(a),null!=b&&(this._locale=b),this)}function kc(){return this._locale}function lc(a){
// the following switch intentionally omits break keywords
// to utilize falling through the cases.
switch(a=J(a)){case"year":this.month(0);/* falls through */
case"quarter":case"month":this.date(1);/* falls through */
case"week":case"isoWeek":case"day":case"date":this.hours(0);/* falls through */
case"hour":this.minutes(0);/* falls through */
case"minute":this.seconds(0);/* falls through */
case"second":this.milliseconds(0)}
// weeks are a special case
// quarters are also special
return"week"===a&&this.weekday(0),"isoWeek"===a&&this.isoWeekday(1),"quarter"===a&&this.month(3*Math.floor(this.month()/3)),this}function mc(a){
// 'date' is an alias for 'day', so it should be considered as such.
return a=J(a),void 0===a||"millisecond"===a?this:("date"===a&&(a="day"),this.startOf(a).add(1,"isoWeek"===a?"week":a).subtract(1,"ms"))}function nc(){return this._d.valueOf()-6e4*(this._offset||0)}function oc(){return Math.floor(this.valueOf()/1e3)}function pc(){return new Date(this.valueOf())}function qc(){var a=this;return[a.year(),a.month(),a.date(),a.hour(),a.minute(),a.second(),a.millisecond()]}function rc(){var a=this;return{years:a.year(),months:a.month(),date:a.date(),hours:a.hours(),minutes:a.minutes(),seconds:a.seconds(),milliseconds:a.milliseconds()}}function sc(){
// new Date(NaN).toJSON() === null
return this.isValid()?this.toISOString():null}function tc(){return m(this)}function uc(){return i({},l(this))}function vc(){return l(this).overflow}function wc(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}}function xc(a,b){T(0,[a,a.length],0,b)}
// MOMENTS
function yc(a){return Cc.call(this,a,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)}function zc(a){return Cc.call(this,a,this.isoWeek(),this.isoWeekday(),1,4)}function Ac(){return wa(this.year(),1,4)}function Bc(){var a=this.localeData()._week;return wa(this.year(),a.dow,a.doy)}function Cc(a,b,c,d,e){var f;return null==a?va(this,d,e).year:(f=wa(a,d,e),b>f&&(b=f),Dc.call(this,a,b,c,d,e))}function Dc(a,b,c,d,e){var f=ua(a,b,c,d,e),g=sa(f.year,0,f.dayOfYear);return this.year(g.getUTCFullYear()),this.month(g.getUTCMonth()),this.date(g.getUTCDate()),this}
// MOMENTS
function Ec(a){return null==a?Math.ceil((this.month()+1)/3):this.month(3*(a-1)+this.month()%3)}
// HELPERS
// MOMENTS
function Fc(a){var b=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==a?b:this.add(a-b,"d")}function Gc(a,b){b[ce]=t(1e3*("0."+a))}
// MOMENTS
function Hc(){return this._isUTC?"UTC":""}function Ic(){return this._isUTC?"Coordinated Universal Time":""}function Jc(a){return rb(1e3*a)}function Kc(){return rb.apply(null,arguments).parseZone()}function Lc(a){return a}function Mc(a,b,c,d){var e=ab(),f=j().set(d,b);return e[c](f,a)}function Nc(a,b,c){if("number"==typeof a&&(b=a,a=void 0),a=a||"",null!=b)return Mc(a,b,c,"month");var d,e=[];for(d=0;d<12;d++)e[d]=Mc(a,d,c,"month");return e}
// ()
// (5)
// (fmt, 5)
// (fmt)
// (true)
// (true, 5)
// (true, fmt, 5)
// (true, fmt)
function Oc(a,b,c,d){"boolean"==typeof a?("number"==typeof b&&(c=b,b=void 0),b=b||""):(b=a,c=b,a=!1,"number"==typeof b&&(c=b,b=void 0),b=b||"");var e=ab(),f=a?e._week.dow:0;if(null!=c)return Mc(b,(c+f)%7,d,"day");var g,h=[];for(g=0;g<7;g++)h[g]=Mc(b,(g+f)%7,d,"day");return h}function Pc(a,b){return Nc(a,b,"months")}function Qc(a,b){return Nc(a,b,"monthsShort")}function Rc(a,b,c){return Oc(a,b,c,"weekdays")}function Sc(a,b,c){return Oc(a,b,c,"weekdaysShort")}function Tc(a,b,c){return Oc(a,b,c,"weekdaysMin")}function Uc(){var a=this._data;return this._milliseconds=Ue(this._milliseconds),this._days=Ue(this._days),this._months=Ue(this._months),a.milliseconds=Ue(a.milliseconds),a.seconds=Ue(a.seconds),a.minutes=Ue(a.minutes),a.hours=Ue(a.hours),a.months=Ue(a.months),a.years=Ue(a.years),this}function Vc(a,b,c,d){var e=Nb(b,c);return a._milliseconds+=d*e._milliseconds,a._days+=d*e._days,a._months+=d*e._months,a._bubble()}
// supports only 2.0-style add(1, 's') or add(duration)
function Wc(a,b){return Vc(this,a,b,1)}
// supports only 2.0-style subtract(1, 's') or subtract(duration)
function Xc(a,b){return Vc(this,a,b,-1)}function Yc(a){return a<0?Math.floor(a):Math.ceil(a)}function Zc(){var a,b,c,d,e,f=this._milliseconds,g=this._days,h=this._months,i=this._data;
// if we have a mix of positive and negative values, bubble down first
// check: https://github.com/moment/moment/issues/2166
// The following code bubbles up values, see the tests for
// examples of what that means.
// convert days to months
// 12 months -> 1 year
return f>=0&&g>=0&&h>=0||f<=0&&g<=0&&h<=0||(f+=864e5*Yc(_c(h)+g),g=0,h=0),i.milliseconds=f%1e3,a=s(f/1e3),i.seconds=a%60,b=s(a/60),i.minutes=b%60,c=s(b/60),i.hours=c%24,g+=s(c/24),e=s($c(g)),h+=e,g-=Yc(_c(e)),d=s(h/12),h%=12,i.days=g,i.months=h,i.years=d,this}function $c(a){
// 400 years have 146097 days (taking into account leap year rules)
// 400 years have 12 months === 4800
return 4800*a/146097}function _c(a){
// the reverse of daysToMonths
return 146097*a/4800}function ad(a){var b,c,d=this._milliseconds;if(a=J(a),"month"===a||"year"===a)return b=this._days+d/864e5,c=this._months+$c(b),"month"===a?c:c/12;switch(
// handle milliseconds separately because of floating point math errors (issue #1867)
b=this._days+Math.round(_c(this._months)),a){case"week":return b/7+d/6048e5;case"day":return b+d/864e5;case"hour":return 24*b+d/36e5;case"minute":return 1440*b+d/6e4;case"second":return 86400*b+d/1e3;
// Math.floor prevents floating point math errors here
case"millisecond":return Math.floor(864e5*b)+d;default:throw new Error("Unknown unit "+a)}}
// TODO: Use this.as('ms')?
function bd(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*t(this._months/12)}function cd(a){return function(){return this.as(a)}}function dd(a){return a=J(a),this[a+"s"]()}function ed(a){return function(){return this._data[a]}}function fd(){return s(this.days()/7)}
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
function gd(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function hd(a,b,c){var d=Nb(a).abs(),e=jf(d.as("s")),f=jf(d.as("m")),g=jf(d.as("h")),h=jf(d.as("d")),i=jf(d.as("M")),j=jf(d.as("y")),k=e<kf.s&&["s",e]||f<=1&&["m"]||f<kf.m&&["mm",f]||g<=1&&["h"]||g<kf.h&&["hh",g]||h<=1&&["d"]||h<kf.d&&["dd",h]||i<=1&&["M"]||i<kf.M&&["MM",i]||j<=1&&["y"]||["yy",j];return k[2]=b,k[3]=+a>0,k[4]=c,gd.apply(null,k)}
// This function allows you to set the rounding function for relative time strings
function id(a){return void 0===a?jf:"function"==typeof a&&(jf=a,!0)}
// This function allows you to set a threshold for relative time strings
function jd(a,b){return void 0!==kf[a]&&(void 0===b?kf[a]:(kf[a]=b,!0))}function kd(a){var b=this.localeData(),c=hd(this,!a,b);return a&&(c=b.pastFuture(+this,c)),b.postformat(c)}function ld(){
// for ISO strings we do not use the normal bubbling rules:
// * milliseconds bubble up until they become hours
// * days do not bubble at all
// * months bubble up until they become years
// This is because there is no context-free conversion between hours and days
// (think of clock changes)
// and also not between days and months (28-31 days per month)
var a,b,c,d=lf(this._milliseconds)/1e3,e=lf(this._days),f=lf(this._months);
// 3600 seconds -> 60 minutes -> 1 hour
a=s(d/60),b=s(a/60),d%=60,a%=60,
// 12 months -> 1 year
c=s(f/12),f%=12;
// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
var g=c,h=f,i=e,j=b,k=a,l=d,m=this.asSeconds();return m?(m<0?"-":"")+"P"+(g?g+"Y":"")+(h?h+"M":"")+(i?i+"D":"")+(j||k||l?"T":"")+(j?j+"H":"")+(k?k+"M":"")+(l?l+"S":""):"P0D"}var md,nd;nd=Array.prototype.some?Array.prototype.some:function(a){for(var b=Object(this),c=b.length>>>0,d=0;d<c;d++)if(d in b&&a.call(this,b[d],d,b))return!0;return!1};
// Plugins that add properties should also add the key here (null value),
// so we can properly clone ourselves.
var od=a.momentProperties=[],pd=!1,qd={};a.suppressDeprecationWarnings=!1,a.deprecationHandler=null;var rd;rd=Object.keys?Object.keys:function(a){var b,c=[];for(b in a)h(a,b)&&c.push(b);return c};var sd,td={sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},ud={LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},vd="Invalid date",wd="%d",xd=/\d{1,2}/,yd={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},zd={},Ad={},Bd=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,Cd=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,Dd={},Ed={},Fd=/\d/,Gd=/\d\d/,Hd=/\d{3}/,Id=/\d{4}/,Jd=/[+-]?\d{6}/,Kd=/\d\d?/,Ld=/\d\d\d\d?/,Md=/\d\d\d\d\d\d?/,Nd=/\d{1,3}/,Od=/\d{1,4}/,Pd=/[+-]?\d{1,6}/,Qd=/\d+/,Rd=/[+-]?\d+/,Sd=/Z|[+-]\d\d:?\d\d/gi,Td=/Z|[+-]\d\d(?::?\d\d)?/gi,Ud=/[+-]?\d+(\.\d{1,3})?/,Vd=/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i,Wd={},Xd={},Yd=0,Zd=1,$d=2,_d=3,ae=4,be=5,ce=6,de=7,ee=8;sd=Array.prototype.indexOf?Array.prototype.indexOf:function(a){
// I know
var b;for(b=0;b<this.length;++b)if(this[b]===a)return b;return-1},
// FORMATTING
T("M",["MM",2],"Mo",function(){return this.month()+1}),T("MMM",0,0,function(a){return this.localeData().monthsShort(this,a)}),T("MMMM",0,0,function(a){return this.localeData().months(this,a)}),
// ALIASES
I("month","M"),
// PRIORITY
L("month",8),
// PARSING
Y("M",Kd),Y("MM",Kd,Gd),Y("MMM",function(a,b){return b.monthsShortRegex(a)}),Y("MMMM",function(a,b){return b.monthsRegex(a)}),aa(["M","MM"],function(a,b){b[Zd]=t(a)-1}),aa(["MMM","MMMM"],function(a,b,c,d){var e=c._locale.monthsParse(a,d,c._strict);
// if we didn't find a month name, mark the date as invalid.
null!=e?b[Zd]=e:l(c).invalidMonth=a});
// LOCALES
var fe=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,ge="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),he="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),ie=Vd,je=Vd;
// FORMATTING
T("Y",0,0,function(){var a=this.year();return a<=9999?""+a:"+"+a}),T(0,["YY",2],0,function(){return this.year()%100}),T(0,["YYYY",4],0,"year"),T(0,["YYYYY",5],0,"year"),T(0,["YYYYYY",6,!0],0,"year"),
// ALIASES
I("year","y"),
// PRIORITIES
L("year",1),
// PARSING
Y("Y",Rd),Y("YY",Kd,Gd),Y("YYYY",Od,Id),Y("YYYYY",Pd,Jd),Y("YYYYYY",Pd,Jd),aa(["YYYYY","YYYYYY"],Yd),aa("YYYY",function(b,c){c[Yd]=2===b.length?a.parseTwoDigitYear(b):t(b)}),aa("YY",function(b,c){c[Yd]=a.parseTwoDigitYear(b)}),aa("Y",function(a,b){b[Yd]=parseInt(a,10)}),
// HOOKS
a.parseTwoDigitYear=function(a){return t(a)+(t(a)>68?1900:2e3)};
// MOMENTS
var ke=N("FullYear",!0);
// FORMATTING
T("w",["ww",2],"wo","week"),T("W",["WW",2],"Wo","isoWeek"),
// ALIASES
I("week","w"),I("isoWeek","W"),
// PRIORITIES
L("week",5),L("isoWeek",5),
// PARSING
Y("w",Kd),Y("ww",Kd,Gd),Y("W",Kd),Y("WW",Kd,Gd),ba(["w","ww","W","WW"],function(a,b,c,d){b[d.substr(0,1)]=t(a)});var le={dow:0,// Sunday is the first day of the week.
doy:6};
// FORMATTING
T("d",0,"do","day"),T("dd",0,0,function(a){return this.localeData().weekdaysMin(this,a)}),T("ddd",0,0,function(a){return this.localeData().weekdaysShort(this,a)}),T("dddd",0,0,function(a){return this.localeData().weekdays(this,a)}),T("e",0,0,"weekday"),T("E",0,0,"isoWeekday"),
// ALIASES
I("day","d"),I("weekday","e"),I("isoWeekday","E"),
// PRIORITY
L("day",11),L("weekday",11),L("isoWeekday",11),
// PARSING
Y("d",Kd),Y("e",Kd),Y("E",Kd),Y("dd",function(a,b){return b.weekdaysMinRegex(a)}),Y("ddd",function(a,b){return b.weekdaysShortRegex(a)}),Y("dddd",function(a,b){return b.weekdaysRegex(a)}),ba(["dd","ddd","dddd"],function(a,b,c,d){var e=c._locale.weekdaysParse(a,d,c._strict);
// if we didn't get a weekday name, mark the date as invalid
null!=e?b.d=e:l(c).invalidWeekday=a}),ba(["d","e","E"],function(a,b,c,d){b[d]=t(a)});
// LOCALES
var me="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),ne="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),oe="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),pe=Vd,qe=Vd,re=Vd;T("H",["HH",2],0,"hour"),T("h",["hh",2],0,Qa),T("k",["kk",2],0,Ra),T("hmm",0,0,function(){return""+Qa.apply(this)+S(this.minutes(),2)}),T("hmmss",0,0,function(){return""+Qa.apply(this)+S(this.minutes(),2)+S(this.seconds(),2)}),T("Hmm",0,0,function(){return""+this.hours()+S(this.minutes(),2)}),T("Hmmss",0,0,function(){return""+this.hours()+S(this.minutes(),2)+S(this.seconds(),2)}),Sa("a",!0),Sa("A",!1),
// ALIASES
I("hour","h"),
// PRIORITY
L("hour",13),Y("a",Ta),Y("A",Ta),Y("H",Kd),Y("h",Kd),Y("HH",Kd,Gd),Y("hh",Kd,Gd),Y("hmm",Ld),Y("hmmss",Md),Y("Hmm",Ld),Y("Hmmss",Md),aa(["H","HH"],_d),aa(["a","A"],function(a,b,c){c._isPm=c._locale.isPM(a),c._meridiem=a}),aa(["h","hh"],function(a,b,c){b[_d]=t(a),l(c).bigHour=!0}),aa("hmm",function(a,b,c){var d=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d)),l(c).bigHour=!0}),aa("hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d,2)),b[be]=t(a.substr(e)),l(c).bigHour=!0}),aa("Hmm",function(a,b,c){var d=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d))}),aa("Hmmss",function(a,b,c){var d=a.length-4,e=a.length-2;b[_d]=t(a.substr(0,d)),b[ae]=t(a.substr(d,2)),b[be]=t(a.substr(e))});var se,te=/[ap]\.?m?\.?/i,ue=N("Hours",!0),ve={calendar:td,longDateFormat:ud,invalidDate:vd,ordinal:wd,ordinalParse:xd,relativeTime:yd,months:ge,monthsShort:he,week:le,weekdays:me,weekdaysMin:oe,weekdaysShort:ne,meridiemParse:te},we={},xe=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,ye=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/,ze=/Z|[+-]\d\d(?::?\d\d)?/,Ae=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],
// YYYYMM is NOT allowed by the standard
["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/]],Be=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],Ce=/^\/?Date\((\-?\d+)/i;a.createFromInputFallback=w("value provided is not in a recognized ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non ISO date formats are discouraged and will be removed in an upcoming major release. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(a){a._d=new Date(a._i+(a._useUTC?" UTC":""))}),
// constant that refers to the ISO standard
a.ISO_8601=function(){};var De=w("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=rb.apply(null,arguments);return this.isValid()&&a.isValid()?a<this?this:a:n()}),Ee=w("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var a=rb.apply(null,arguments);return this.isValid()&&a.isValid()?a>this?this:a:n()}),Fe=function(){return Date.now?Date.now():+new Date};yb("Z",":"),yb("ZZ",""),
// PARSING
Y("Z",Td),Y("ZZ",Td),aa(["Z","ZZ"],function(a,b,c){c._useUTC=!0,c._tzm=zb(Td,a)});
// HELPERS
// timezone chunker
// '+10:00' > ['10', '00']
// '-1530' > ['-15', '30']
var Ge=/([\+\-]|\d\d)/gi;
// HOOKS
// This function will be called whenever a moment is mutated.
// It is intended to keep the offset in sync with the timezone.
a.updateOffset=function(){};
// ASP.NET json date format regex
var He=/^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/,Ie=/^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;Nb.fn=vb.prototype;var Je=Rb(1,"add"),Ke=Rb(-1,"subtract");a.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",a.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Le=w("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(a){return void 0===a?this.localeData():this.locale(a)});
// FORMATTING
T(0,["gg",2],0,function(){return this.weekYear()%100}),T(0,["GG",2],0,function(){return this.isoWeekYear()%100}),xc("gggg","weekYear"),xc("ggggg","weekYear"),xc("GGGG","isoWeekYear"),xc("GGGGG","isoWeekYear"),
// ALIASES
I("weekYear","gg"),I("isoWeekYear","GG"),
// PRIORITY
L("weekYear",1),L("isoWeekYear",1),
// PARSING
Y("G",Rd),Y("g",Rd),Y("GG",Kd,Gd),Y("gg",Kd,Gd),Y("GGGG",Od,Id),Y("gggg",Od,Id),Y("GGGGG",Pd,Jd),Y("ggggg",Pd,Jd),ba(["gggg","ggggg","GGGG","GGGGG"],function(a,b,c,d){b[d.substr(0,2)]=t(a)}),ba(["gg","GG"],function(b,c,d,e){c[e]=a.parseTwoDigitYear(b)}),
// FORMATTING
T("Q",0,"Qo","quarter"),
// ALIASES
I("quarter","Q"),
// PRIORITY
L("quarter",7),
// PARSING
Y("Q",Fd),aa("Q",function(a,b){b[Zd]=3*(t(a)-1)}),
// FORMATTING
T("D",["DD",2],"Do","date"),
// ALIASES
I("date","D"),
// PRIOROITY
L("date",9),
// PARSING
Y("D",Kd),Y("DD",Kd,Gd),Y("Do",function(a,b){return a?b._ordinalParse:b._ordinalParseLenient}),aa(["D","DD"],$d),aa("Do",function(a,b){b[$d]=t(a.match(Kd)[0],10)});
// MOMENTS
var Me=N("Date",!0);
// FORMATTING
T("DDD",["DDDD",3],"DDDo","dayOfYear"),
// ALIASES
I("dayOfYear","DDD"),
// PRIORITY
L("dayOfYear",4),
// PARSING
Y("DDD",Nd),Y("DDDD",Hd),aa(["DDD","DDDD"],function(a,b,c){c._dayOfYear=t(a)}),
// FORMATTING
T("m",["mm",2],0,"minute"),
// ALIASES
I("minute","m"),
// PRIORITY
L("minute",14),
// PARSING
Y("m",Kd),Y("mm",Kd,Gd),aa(["m","mm"],ae);
// MOMENTS
var Ne=N("Minutes",!1);
// FORMATTING
T("s",["ss",2],0,"second"),
// ALIASES
I("second","s"),
// PRIORITY
L("second",15),
// PARSING
Y("s",Kd),Y("ss",Kd,Gd),aa(["s","ss"],be);
// MOMENTS
var Oe=N("Seconds",!1);
// FORMATTING
T("S",0,0,function(){return~~(this.millisecond()/100)}),T(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),T(0,["SSS",3],0,"millisecond"),T(0,["SSSS",4],0,function(){return 10*this.millisecond()}),T(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),T(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),T(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),T(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),T(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),
// ALIASES
I("millisecond","ms"),
// PRIORITY
L("millisecond",16),
// PARSING
Y("S",Nd,Fd),Y("SS",Nd,Gd),Y("SSS",Nd,Hd);var Pe;for(Pe="SSSS";Pe.length<=9;Pe+="S")Y(Pe,Qd);for(Pe="S";Pe.length<=9;Pe+="S")aa(Pe,Gc);
// MOMENTS
var Qe=N("Milliseconds",!1);
// FORMATTING
T("z",0,0,"zoneAbbr"),T("zz",0,0,"zoneName");var Re=q.prototype;Re.add=Je,Re.calendar=Ub,Re.clone=Vb,Re.diff=ac,Re.endOf=mc,Re.format=ec,Re.from=fc,Re.fromNow=gc,Re.to=hc,Re.toNow=ic,Re.get=Q,Re.invalidAt=vc,Re.isAfter=Wb,Re.isBefore=Xb,Re.isBetween=Yb,Re.isSame=Zb,Re.isSameOrAfter=$b,Re.isSameOrBefore=_b,Re.isValid=tc,Re.lang=Le,Re.locale=jc,Re.localeData=kc,Re.max=Ee,Re.min=De,Re.parsingFlags=uc,Re.set=R,Re.startOf=lc,Re.subtract=Ke,Re.toArray=qc,Re.toObject=rc,Re.toDate=pc,Re.toISOString=dc,Re.toJSON=sc,Re.toString=cc,Re.unix=oc,Re.valueOf=nc,Re.creationData=wc,
// Year
Re.year=ke,Re.isLeapYear=qa,
// Week Year
Re.weekYear=yc,Re.isoWeekYear=zc,
// Quarter
Re.quarter=Re.quarters=Ec,
// Month
Re.month=ja,Re.daysInMonth=ka,
// Week
Re.week=Re.weeks=Aa,Re.isoWeek=Re.isoWeeks=Ba,Re.weeksInYear=Bc,Re.isoWeeksInYear=Ac,
// Day
Re.date=Me,Re.day=Re.days=Ja,Re.weekday=Ka,Re.isoWeekday=La,Re.dayOfYear=Fc,
// Hour
Re.hour=Re.hours=ue,
// Minute
Re.minute=Re.minutes=Ne,
// Second
Re.second=Re.seconds=Oe,
// Millisecond
Re.millisecond=Re.milliseconds=Qe,
// Offset
Re.utcOffset=Cb,Re.utc=Eb,Re.local=Fb,Re.parseZone=Gb,Re.hasAlignedHourOffset=Hb,Re.isDST=Ib,Re.isLocal=Kb,Re.isUtcOffset=Lb,Re.isUtc=Mb,Re.isUTC=Mb,
// Timezone
Re.zoneAbbr=Hc,Re.zoneName=Ic,
// Deprecations
Re.dates=w("dates accessor is deprecated. Use date instead.",Me),Re.months=w("months accessor is deprecated. Use month instead",ja),Re.years=w("years accessor is deprecated. Use year instead",ke),Re.zone=w("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",Db),Re.isDSTShifted=w("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",Jb);var Se=Re,Te=B.prototype;Te.calendar=C,Te.longDateFormat=D,Te.invalidDate=E,Te.ordinal=F,Te.preparse=Lc,Te.postformat=Lc,Te.relativeTime=G,Te.pastFuture=H,Te.set=z,
// Month
Te.months=ea,Te.monthsShort=fa,Te.monthsParse=ha,Te.monthsRegex=ma,Te.monthsShortRegex=la,
// Week
Te.week=xa,Te.firstDayOfYear=za,Te.firstDayOfWeek=ya,
// Day of Week
Te.weekdays=Ea,Te.weekdaysMin=Ga,Te.weekdaysShort=Fa,Te.weekdaysParse=Ia,Te.weekdaysRegex=Ma,Te.weekdaysShortRegex=Na,Te.weekdaysMinRegex=Oa,
// Hours
Te.isPM=Ua,Te.meridiem=Va,Za("en",{ordinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(a){var b=a%10,c=1===t(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),
// Side effect imports
a.lang=w("moment.lang is deprecated. Use moment.locale instead.",Za),a.langData=w("moment.langData is deprecated. Use moment.localeData instead.",ab);var Ue=Math.abs,Ve=cd("ms"),We=cd("s"),Xe=cd("m"),Ye=cd("h"),Ze=cd("d"),$e=cd("w"),_e=cd("M"),af=cd("y"),bf=ed("milliseconds"),cf=ed("seconds"),df=ed("minutes"),ef=ed("hours"),ff=ed("days"),gf=ed("months"),hf=ed("years"),jf=Math.round,kf={s:45,// seconds to minute
m:45,// minutes to hour
h:22,// hours to day
d:26,// days to month
M:11},lf=Math.abs,mf=vb.prototype;mf.abs=Uc,mf.add=Wc,mf.subtract=Xc,mf.as=ad,mf.asMilliseconds=Ve,mf.asSeconds=We,mf.asMinutes=Xe,mf.asHours=Ye,mf.asDays=Ze,mf.asWeeks=$e,mf.asMonths=_e,mf.asYears=af,mf.valueOf=bd,mf._bubble=Zc,mf.get=dd,mf.milliseconds=bf,mf.seconds=cf,mf.minutes=df,mf.hours=ef,mf.days=ff,mf.weeks=fd,mf.months=gf,mf.years=hf,mf.humanize=kd,mf.toISOString=ld,mf.toString=ld,mf.toJSON=ld,mf.locale=jc,mf.localeData=kc,
// Deprecations
mf.toIsoString=w("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",ld),mf.lang=Le,
// Side effect imports
// FORMATTING
T("X",0,0,"unix"),T("x",0,0,"valueOf"),
// PARSING
Y("x",Rd),Y("X",Ud),aa("X",function(a,b,c){c._d=new Date(1e3*parseFloat(a,10))}),aa("x",function(a,b,c){c._d=new Date(t(a))}),
// Side effect imports
a.version="2.15.2",b(rb),a.fn=Se,a.min=tb,a.max=ub,a.now=Fe,a.utc=j,a.unix=Jc,a.months=Pc,a.isDate=f,a.locale=Za,a.invalid=n,a.duration=Nb,a.isMoment=r,a.weekdays=Rc,a.parseZone=Kc,a.localeData=ab,a.isDuration=wb,a.monthsShort=Qc,a.weekdaysMin=Tc,a.defineLocale=$a,a.updateLocale=_a,a.locales=bb,a.weekdaysShort=Sc,a.normalizeUnits=J,a.relativeTimeRounding=id,a.relativeTimeThreshold=jd,a.calendarFormat=Tb,a.prototype=Se;var nf=a;return nf});
+2
View File
@@ -0,0 +1,2 @@
// https://raw.githubusercontent.com/joewalnes/reconnecting-websocket/master/reconnecting-websocket.min.js
!function(a,b){"function"==typeof define&&define.amd?define([],b):"undefined"!=typeof module&&module.exports?module.exports=b():a.ReconnectingWebSocket=b()}(this,function(){function a(b,c,d){function l(a,b){var c=document.createEvent("CustomEvent");return c.initCustomEvent(a,!1,!1,b),c}var e={debug:!1,automaticOpen:!0,reconnectInterval:1e3,maxReconnectInterval:3e4,reconnectDecay:1.5,timeoutInterval:2e3};d||(d={});for(var f in e)this[f]="undefined"!=typeof d[f]?d[f]:e[f];this.url=b,this.reconnectAttempts=0,this.readyState=WebSocket.CONNECTING,this.protocol=null;var h,g=this,i=!1,j=!1,k=document.createElement("div");k.addEventListener("open",function(a){g.onopen(a)}),k.addEventListener("close",function(a){g.onclose(a)}),k.addEventListener("connecting",function(a){g.onconnecting(a)}),k.addEventListener("message",function(a){g.onmessage(a)}),k.addEventListener("error",function(a){g.onerror(a)}),this.addEventListener=k.addEventListener.bind(k),this.removeEventListener=k.removeEventListener.bind(k),this.dispatchEvent=k.dispatchEvent.bind(k),this.open=function(b){h=new WebSocket(g.url,c||[]),b||k.dispatchEvent(l("connecting")),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","attempt-connect",g.url);var d=h,e=setTimeout(function(){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","connection-timeout",g.url),j=!0,d.close(),j=!1},g.timeoutInterval);h.onopen=function(){clearTimeout(e),(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onopen",g.url),g.protocol=h.protocol,g.readyState=WebSocket.OPEN,g.reconnectAttempts=0;var d=l("open");d.isReconnect=b,b=!1,k.dispatchEvent(d)},h.onclose=function(c){if(clearTimeout(e),h=null,i)g.readyState=WebSocket.CLOSED,k.dispatchEvent(l("close"));else{g.readyState=WebSocket.CONNECTING;var d=l("connecting");d.code=c.code,d.reason=c.reason,d.wasClean=c.wasClean,k.dispatchEvent(d),b||j||((g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onclose",g.url),k.dispatchEvent(l("close")));var e=g.reconnectInterval*Math.pow(g.reconnectDecay,g.reconnectAttempts);setTimeout(function(){g.reconnectAttempts++,g.open(!0)},e>g.maxReconnectInterval?g.maxReconnectInterval:e)}},h.onmessage=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onmessage",g.url,b.data);var c=l("message");c.data=b.data,k.dispatchEvent(c)},h.onerror=function(b){(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","onerror",g.url,b),k.dispatchEvent(l("error"))}},1==this.automaticOpen&&this.open(!1),this.send=function(b){if(h)return(g.debug||a.debugAll)&&console.debug("ReconnectingWebSocket","send",g.url,b),h.send(b);throw"INVALID_STATE_ERR : Pausing to reconnect websocket"},this.close=function(a,b){"undefined"==typeof a&&(a=1e3),i=!0,h&&h.close(a,b)},this.refresh=function(){h&&h.close()}}return a.prototype.onopen=function(){},a.prototype.onclose=function(){},a.prototype.onconnecting=function(){},a.prototype.onmessage=function(){},a.prototype.onerror=function(){},a.debugAll=!1,a.CONNECTING=WebSocket.CONNECTING,a.OPEN=WebSocket.OPEN,a.CLOSING=WebSocket.CLOSING,a.CLOSED=WebSocket.CLOSED,a});
Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

+2
View File
@@ -0,0 +1,2 @@
// https://github.com/jakwings/toml-j0.4
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var r;r="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,r.toml=e()}}(function(){return function e(r,t,n){function i(u,a){if(!t[u]){if(!r[u]){var c="function"==typeof require&&require;if(!a&&c)return c(u,!0);if(o)return o(u,!0);var s=new Error("Cannot find module '"+u+"'");throw s.code="MODULE_NOT_FOUND",s}var l=t[u]={exports:{}};r[u][0].call(l.exports,function(e){var t=r[u][1][e];return i(t?t:e)},l,l.exports,e,r,t,n)}return t[u].exports}for(var o="function"==typeof require&&require,u=0;u<n.length;u++)i(n[u]);return i}({1:[function(e,r,t){r.exports=function(){function e(e,r){function t(){this.constructor=e}t.prototype=r.prototype,e.prototype=new t}function r(e,r,t,n,i,o){this.message=e,this.expected=r,this.found=t,this.offset=n,this.line=i,this.column=o,this.name="SyntaxError"}function t(e){function t(){return e.substring(Ot,Dt)}function n(e){throw u(e,null,Ot)}function i(r){function t(r,t,n){var i,o;for(i=t;n>i;i++)o=e.charAt(i),"\n"===o?(r.seenCR||r.line++,r.column=1,r.seenCR=!1):"\r"===o||"\u2028"===o||"\u2029"===o?(r.line++,r.column=1,r.seenCR=!0):(r.column++,r.seenCR=!1)}return Tt!==r&&(Tt>r&&(Tt=0,jt={line:1,column:1,seenCR:!1}),t(jt,Tt,r),Tt=r),jt}function o(e){Nt>Dt||(Dt>Nt&&(Nt=Dt,Ut=[]),Ut.push(e))}function u(t,n,o){function u(e){var r=1;for(e.sort(function(e,r){return e.description<r.description?-1:e.description>r.description?1:0});r<e.length;)e[r-1]===e[r]?e.splice(r,1):r++}function a(e,r){function t(e){function r(e){return e.charCodeAt(0).toString(16).toUpperCase()}return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\x08/g,"\\b").replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\f/g,"\\f").replace(/\r/g,"\\r").replace(/[\x00-\x07\x0B\x0E\x0F]/g,function(e){return"\\x0"+r(e)}).replace(/[\x10-\x1F\x80-\xFF]/g,function(e){return"\\x"+r(e)}).replace(/[\u0180-\u0FFF]/g,function(e){return"\\u0"+r(e)}).replace(/[\u1080-\uFFFF]/g,function(e){return"\\u"+r(e)})}var n,i,o,u=new Array(e.length);for(o=0;o<e.length;o++)u[o]=e[o].description;return n=e.length>1?u.slice(0,-1).join(", ")+" or "+u[e.length-1]:u[0],i=r?'"'+t(r)+'"':"end of input","Expected "+n+" but "+i+" found."}var c=i(o),s=o<e.length?e.charAt(o):null;return null!==n&&u(n),new r(null!==t?t:a(n,s),n,s,o,c.line,c.column)}function a(){var e,r,t,n,i,o,u,p;for(e=Dt,r=[],t=l(),t===ye&&(t=s(),t===ye&&(t=f()));t!==ye;)r.push(t),t=l(),t===ye&&(t=s(),t===ye&&(t=f()));if(r!==ye){if(t=Dt,n=c(),n!==ye){for(i=[],o=l(),o===ye&&(o=f());o!==ye;)i.push(o),o=l(),o===ye&&(o=f());i!==ye?(o=Dt,u=s(),u!==ye?(p=a(),p!==ye?(u=[u,p],o=u):(Dt=o,o=Ce)):(Dt=o,o=Ce),o===ye&&(o=be),o!==ye?(n=[n,i,o],t=n):(Dt=t,t=Ce)):(Dt=t,t=Ce)}else Dt=t,t=Ce;t===ye&&(t=be),t!==ye?(Ot=e,r=xe(),e=r):(Dt=e,e=Ce)}else Dt=e,e=Ce;return e}function c(){var e,r;return e=Dt,r=pe(),r!==ye&&(Ot=e,r=me(r)),e=r,e===ye&&(e=Dt,r=he(),r!==ye&&(Ot=e,r=Fe(r)),e=r,e===ye&&(e=Dt,r=p(),r!==ye&&(Ot=e,r=Se(r)),e=r)),e}function s(){var r,t;return Zt++,10===e.charCodeAt(Dt)?(r=Ee,Dt++):(r=ye,0===Zt&&o(Re)),r===ye&&(e.substr(Dt,2)===_e?(r=_e,Dt+=2):(r=ye,0===Zt&&o(De))),Zt--,r===ye&&(t=ye,0===Zt&&o(we)),r}function l(){var r,t;return Zt++,Te.test(e.charAt(Dt))?(r=e.charAt(Dt),Dt++):(r=ye,0===Zt&&o(je)),Zt--,r===ye&&(t=ye,0===Zt&&o(Oe)),r}function f(){var r,t,n,i,u,a;if(Zt++,r=Dt,35===e.charCodeAt(Dt)?(t=Ue,Dt++):(t=ye,0===Zt&&o(Ze)),t!==ye){for(n=[],i=Dt,u=Dt,Zt++,a=s(),Zt--,a===ye?u=He:(Dt=u,u=Ce),u!==ye?(e.length>Dt?(a=e.charAt(Dt),Dt++):(a=ye,0===Zt&&o(Me)),a!==ye?(u=[u,a],i=u):(Dt=i,i=Ce)):(Dt=i,i=Ce);i!==ye;)n.push(i),i=Dt,u=Dt,Zt++,a=s(),Zt--,a===ye?u=He:(Dt=u,u=Ce),u!==ye?(e.length>Dt?(a=e.charAt(Dt),Dt++):(a=ye,0===Zt&&o(Me)),a!==ye?(u=[u,a],i=u):(Dt=i,i=Ce)):(Dt=i,i=Ce);n!==ye?(t=[t,n],r=t):(Dt=r,r=Ce)}else Dt=r,r=Ce;return Zt--,r===ye&&(t=ye,0===Zt&&o(Ne)),r}function p(){var r,t,n,i,u,a;if(r=Dt,t=h(),t!==ye){for(n=[],i=l();i!==ye;)n.push(i),i=l();if(n!==ye)if(61===e.charCodeAt(Dt)?(i=Ie,Dt++):(i=ye,0===Zt&&o(qe)),i!==ye){for(u=[],a=l();a!==ye;)u.push(a),a=l();u!==ye?(a=x(),a!==ye?(Ot=r,t=ze(t,a),r=t):(Dt=r,r=Ce)):(Dt=r,r=Ce)}else Dt=r,r=Ce;else Dt=r,r=Ce}else Dt=r,r=Ce;return r}function h(){var e;return e=d(),e===ye&&(e=y()),e}function d(){var e,r,t;if(e=Dt,r=[],t=v(),t!==ye)for(;t!==ye;)r.push(t),t=v();else r=Ce;return r!==ye&&(Ot=e,r=Be()),e=r}function v(){var r,t;return Zt++,Ye.test(e.charAt(Dt))?(r=e.charAt(Dt),Dt++):(r=ye,0===Zt&&o(Je)),Zt--,r===ye&&(t=ye,0===Zt&&o(Qe)),r}function y(){var e,r,t,n;if(e=Dt,r=g(),r!==ye){if(t=[],n=S(),n!==ye)for(;n!==ye;)t.push(n),n=S();else t=Ce;t!==ye?(n=g(),n!==ye?(Ot=e,r=Pe(t),e=r):(Dt=e,e=Ce)):(Dt=e,e=Ce)}else Dt=e,e=Ce;return e}function g(){var r,t;return Zt++,34===e.charCodeAt(Dt)?(r=Le,Dt++):(r=ye,0===Zt&&o(Ve)),Zt--,r===ye&&(t=ye,0===Zt&&o(ke)),r}function A(){var r,t;return Zt++,39===e.charCodeAt(Dt)?(r=Ge,Dt++):(r=ye,0===Zt&&o(Ke)),Zt--,r===ye&&(tLine truncated
+99
View File
@@ -0,0 +1,99 @@
<script>
import top from './components/layout/header.vue'
import bottom from './components/layout/footer.vue'
import modal from './components/layout/modal.vue'
export default {
name: 'app',
components: {
top,
bottom,
modal
}
}
</script>
<template lang='pug'>
#app
top
.fill
router-view.view
bottom
modal
</template>
<style>
#app {
display: flex;
min-height: 100vh;
flex-direction: column;
}
.fill {
flex: 1;
}
.text {
max-width: 500px;
}
input {
background: none;
margin-top: 0.5em;
}
.params {
min-height: 235px;
line-height: 1.3em;
}
.hr {
margin-top: 2rem;
margin-bottom: 2rem;
height: 10px;
background-color: rgba(250,250,250,.99);
}
.contain {
width: 900px;
margin-left: auto;
margin-right: auto;
}
.btn--primary {
display: inline-block;
margin-right: 12px;
margin-bottom: 12px;
height: 40px;
padding: 0 18px;
border-radius: 4px;
background-color: #3498db;
text-shadow: 0 1px 3px rgba(36,180,126,.4);
box-shadow: 0 4px 6px rgba(50,50,93,.11), 0 1px 3px rgba(0,0,0,.08);
color: #fff;
text-decoration: none;
line-height: 40px;
transition: transform 250ms;
}
.btn--primary:hover {
transform: translateY(-1px);
box-shadow: 0 7px 14px rgba(50,50,93,.1), 0 3px 6px rgba(0,0,0,.08);
background-color: #3498db;
color: #fff;
text-decoration: none;
}
.btn--primary:active,
.btn--primary:focus {
background-color: #3498db;
color: #fff;
text-decoration: none;
}
.btn--primary:active {
transform: translateY(1px);
}
</style>
@@ -0,0 +1,139 @@
<template lang='pug'>
div
dataset-picker.my2(v-on:dataset='updateDataset').contain
.hr
strat-picker.my2(v-on:stratConfig='updateStrat').contain
.hr
paper-trader(v-on:settings='updatePaperTrader').contain
.hr
</template>
<script>
import datasetPicker from '../global/configbuilder/datasetpicker.vue'
import stratPicker from '../global/configbuilder/stratpicker.vue'
import paperTrader from '../global/configbuilder/papertrader.vue'
import _ from 'lodash'
import { get } from '../../tools/ajax'
export default {
created: function() {
get('configPart/performanceAnalyzer', (error, response) => {
this.performanceAnalyzer = toml.parse(response.part);
this.performanceAnalyzer.enabled = true;
});
},
data: () => {
return {
dataset: {},
strat: {},
paperTrader: {},
performanceAnalyzer: {}
}
},
components: {
stratPicker,
datasetPicker,
paperTrader
},
computed: {
market: function() {
if(!this.dataset.exchange)
return {};
return {
exchange: this.dataset.exchange,
currency: this.dataset.currency,
asset: this.dataset.asset
}
},
range: function() {
if(!this.dataset.exchange)
return {};
return {
from: this.dataset.from,
to: this.dataset.to
}
},
config: function() {
let config = {};
Object.assign(
config,
{ watch: this.market },
{ paperTrader: this.paperTrader },
this.strat,
{
backtest: {
daterange: this.range
},
backtestResultExporter: {
enabled: true,
writeToDisk: false,
data: {
stratUpdates: false,
roundtrips: true,
stratCandles: true,
stratCandleProps: ['open'],
trades: true
}
}
},
{ performanceAnalyzer: this.performanceAnalyzer },
);
config.valid = this.validConfig(config);
config.backtestResultExporter.enabled = true;
return config;
}
},
methods: {
validConfig: function(config) {
if(!config.backtest)
return false;
if(!config.backtest.daterange)
return false;
if(_.isEmpty(config.backtest.daterange))
return false;
if(!config.watch)
return false;
if(!config.tradingAdvisor)
return false;
let strat = config.tradingAdvisor.method;
if(_.isEmpty(config[ strat ]))
return false;
if(config.tradingAdvisor) {
if(_.isNaN(config.tradingAdvisor.candleSize))
return false;
else if(config.tradingAdvisor.candleSize == 0)
return false;
}
return true;
},
updateDataset: function(set) {
this.dataset = set;
this.$emit('config', this.config);
},
updateStrat: function(sc) {
this.strat = sc;
this.$emit('config', this.config);
},
updatePaperTrader: function(pt) {
this.paperTrader = pt;
this.paperTrader.enabled = true;
this.$emit('config', this.config);
},
}
}
</script>
<style>
</style>
@@ -0,0 +1,55 @@
<template lang='pug'>
div
h2.contain Backtest
.hr
config-builder(v-on:config='check')
div(v-if='backtestable')
.txt--center
a.w100--s.my1.btn--primary(href='#', v-if='backtestState !== "fetching"', v-on:click.prevent='run') Backtest
div(v-if='backtestState === "fetching"').scan-btn
p Running backtest..
spinner
result(v-if='backtestResult && backtestState === "fetched"', :result='backtestResult')
</template>
<script>
import configBuilder from './backtestConfigBuilder.vue'
import result from './result/result.vue'
import { post } from '../../tools/ajax'
import spinner from '../global/blockSpinner.vue'
export default {
data: () => {
return {
backtestable: false,
backtestState: 'idle',
backtestResult: false,
config: false,
}
},
methods: {
check: function(config) {
// console.log('CHECK', config);
this.config = config;
if(!config.valid)
return this.backtestable = false;
this.backtestable = true;
},
run: function() {
this.backtestState = 'fetching';
post('backtest', this.config, (error, response) => {
this.backtestState = 'fetched';
this.backtestResult = response;
});
}
},
components: {
configBuilder,
result,
spinner
}
}
</script>
@@ -0,0 +1,104 @@
<template lang='pug'>
#chartWrapper(v-bind:class='{ clickable: !isClicked }')
.shield(v-on:click.prevent='click')
svg#chart(width='960', :height='height')
</template>
<script>
import chart from '../../../d3/chart4'
import { draw as drawMessage, clear as clearMessage } from '../../../d3/message'
const MIN_CANDLES = 4;
export default {
props: ['data', 'height'],
data: function() {
return {
isClicked: false
}
},
watch: {
data: function() { this.render() },
},
created: function() { setTimeout( this.render, 100) },
beforeDestroy: function() {
this.remove();
},
methods: {
click: function() {
this.isClicked = true;
},
render: function() {
this.remove();
if(_.size(this.data.candles) < MIN_CANDLES) {
drawMessage('Not enough data to spawn chart');
} else {
chart(this.data.candles, this.data.trades, this.height);
}
},
remove: function() {
d3.select('#chart').html('');
}
}
}
</script>
<style>
#chartWrapper.clickable {
position: relative;
}
#chartWrapper.clickable .shield {
cursor: zoom-in;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: grey;
opacity: 0.1;
}
#chart {
background-color: #eee;
width: 100%;
}
#chart circle {
clip-path: url(#clip);
}
#chart .zoom {
cursor: move;
fill: none;
pointer-events: all;
}
#chart .line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
clip-path: url(#clip);
}
/*#chart .price.line {
stroke-width: 2.5px;
}*/
#chart circle.buy {
fill: #7FFF00;
}
#chart circle.sell {
fill: red;
}
</style>
@@ -0,0 +1,41 @@
<template lang='pug'>
div
.hr.contain
div.contain
h3 Backtest result
result-summary(:report='result.performanceReport')
.hr.contain
chart(:data='candles', height='500')
.hr.contain
roundtripTable(:roundtrips='result.roundtrips')
</template>
<script>
import resultSummary from './summary.vue'
import chart from './chartWrapper.vue'
import roundtripTable from './roundtripTable.vue'
export default {
props: ['result'],
data: () => {
return {}
},
methods: {},
components: {
roundtripTable,
resultSummary,
chart
},
computed: {
candles: function() {
return {
candles: this.result.stratCandles,
trades: this.result.trades
};
}
}
}
</script>
<style>
</style>
@@ -0,0 +1,93 @@
<template lang='pug'>
.contain.roundtrips
h2 Roundtrips
table(v-if='roundtrips.length')
thead
tr
th Entry at (UTC)
th Exit at (UTC)
th Exposure
th Entry balance
th Exit balance
th P&amp;L
th Profit
tr(v-for='rt in roundtrips')
td {{ fmt(rt.entryAt) }}
td {{ fmt(rt.exitAt) }}
td {{ diff(rt.duration) }}
td {{ round(rt.entryBalance) }}
td {{ round(rt.exitBalance) }}
template(v-if="Math.sign(rt.pnl)===-1")
td.loss {{ Math.sign(rt.pnl)*rt.pnl.toFixed(2) }}
td.loss {{ rt.profit.toFixed(2) }}%
template(v-else)
td.profit {{ rt.pnl.toFixed(2) }}
td.profit {{ rt.profit.toFixed(2) }}%
div(v-if='!roundtrips.length')
p Not enough data to display
</template>
<script>
import _ from 'lodash'
export default {
props: ['roundtrips'],
data: () => {
return {}
},
methods: {
diff: n => moment.duration(n).humanize(),
humanizeDuration: (n) => window.humanizeDuration(n),
fmt: date => {
// roundtrips coming out of a backtest
// are unix timestamp, live roundtrips
// are date strings.
// TODO: normalize
let mom;
if(_.isNumber(date)) {
mom = moment.unix(date);
} else {
mom = moment(date).utc();
}
return mom.utc().format('YYYY-MM-DD HH:mm');
},
round: n => (+n).toFixed(3),
},
}
</script>
<style>
.roundtrips {
margin-top: 50px;
margin-bottom: 50px;
}
.roundtrips table {
width: 100%;
}
.roundtrips table th,
.roundtrips table td {
border: 1px solid #c6cbd1;
padding: 8px 12px;
}
.roundtrips table td.loss {
color: red;
text-align: right;
}
.roundtrips table td.profit {
color: green;
text-align: right;
}
.roundtrips table tr:nth-child(2n) {
background-color: #f6f8fa;
}
</style>
@@ -0,0 +1,58 @@
<template lang='pug'>
div.contain
.grd-row.summary
.grd-row-col-3-6
table.p1
tr
th start time
td {{ report.startTime }}
tr
th end time
td {{ report.endTime }}
tr
th timespan
td {{ report.timespan }}
tr
th start price
td {{ round(report.startPrice) }} {{ report.currency }}
tr
th end price
td {{ round(report.endPrice) }} {{ report.currency }}
tr
th market
td {{ round(report.market) }}%
paperTradeSummary(:report='report')
</template>
<script>
import paperTradeSummary from '../../global/paperTradeSummary.vue'
export default {
props: ['report'],
components: {
paperTradeSummary
},
methods: {
round: n => (+n).toFixed(5)
},
computed: {
profitClass: function() {
if(this.report.relativeProfit > 0)
return 'profit'
else
return 'loss'
}
}
}
</script>
<style>
.summary td {
text-align: right;
}
</style>
@@ -0,0 +1,96 @@
<template lang='pug'>
.grd.contain
h3 Add an API key
p Make sure that the API key has the permissions to create and cancel orders and view balances.
.grd-row
.grd-row-col-3-6.mx1
h3 Exchange
exchange-picker(v-on:exchange='updateExchange', only-tradable='true')
.grd-row-col-3-6.mx1
h3 Credentials
template(v-for='cred in requires')
label {{ cred }}
input(v-model='credentials[cred]')
.txt--center
a.w100--s.my1.btn--primary(href='#', v-on:click.prevent='upload') Add
</template>
<script>
import exchangePicker from '../global/configbuilder/exchangepicker.vue'
import _ from 'lodash'
import { post } from '../../tools/ajax';
export default {
data: () => {
return {
exchange: false,
credentials: {}
}
},
components: {
exchangePicker
},
computed: {
apiKeySets: function() {
return this.$store.state.apiKeys;
},
exchanges: function() {
return this.$store.state.exchanges;
},
requires: function() {
if(!this.exchanges)
return [];
if(!this.exchange)
return [];
return this.exchanges[this.exchange].requires;
},
config: function() {
let config = {
exchange: this.exchange,
values: this.credentials
};
return config;
}
},
watch: {
credentials: function() {
this.emitConfig();
}
},
methods: {
updateExchange: function(exchange) {
this.credentials = {};
this.exchange = exchange;
this.emitConfig();
},
emitConfig: function() {
this.$emit('config', this.config);
},
upload: function() {
let exchange = this.config.exchange;
if(
this.exchanges &&
this.apiKeySets.includes(exchange) &&
!confirm(`You already have API keys for ${exchange} defined, do you want to overwrite them?`)
)
return;
post('addApiKey', this.config, (error, response) => {
if(error)
return alert(error);
this.credentials = {};
});
}
}
}
</script>
<style>
</style>
+58
View File
@@ -0,0 +1,58 @@
<template lang='pug'>
div.contain
h2 Config
.hr
h3 Available API keys
p(v-if='!apiKeySets.length')
em You don't have any API keys yet.
ul
li(v-for='exchange in apiKeySets') {{ exchange }} (
a(href='#', v-on:click.prevent='removeApiKey(exchange)') remove
| )
a.btn--primary(href='#', v-if='!addApiToggle', v-on:click.prevent='openAddApi') Add an API key
template(v-if='addApiToggle')
.hr
apiConfigBuilder
.hr
</template>
<script>
import apiConfigBuilder from './apiConfigBuilder.vue';
import { post } from '../../tools/ajax';
export default {
components: {
apiConfigBuilder
},
data: () => {
return {
addApiToggle: false,
}
},
methods: {
openAddApi: function() {
this.addApiToggle = true;
},
removeApiKey: function(exchange) {
if(!confirm('Are you sure you want to delete these API keys?'))
return;
post('removeApiKey', {exchange}, (error, response) => {
if(error)
return alert(error);
});
}
},
computed: {
apiKeySets: function() {
return this.$store.state.apiKeys
}
},
watch: {
apiKeySets: function() {
this.addApiToggle = false;
}
}
}
</script>
+103
View File
@@ -0,0 +1,103 @@
<template lang='pug'>
.contain
.text(v-html='intro')
.hr
h2 Available datasets
.txt--center.my2(v-if='datasetScanstate === "idle"')
a.w100--s.btn--primary.scan-btn(href='#', v-on:click.prevent='scan') Scan available data
.txt--center.my2(v-if='datasetScanstate === "scanning"')
spinner
.my2(v-if='datasetScanstate === "scanned"')
.bg--orange.p1.warning.my1(v-if='unscannableMakets.length')
p.clickable(v-if='!viewUnscannable', v-on:click.prevent='toggleUnscannable') Some markets were unscannable, click here for details.
template(v-if='viewUnscannable')
p Unable to find datasets in the following markets:
.mx2(v-for='market in unscannableMakets')
| - {{ market.exchange }}:{{ market.currency }}:{{ market.asset }}
template(v-if='datasets.length')
table.full.data
thead
tr
th exchange
th currency
th asset
th from
th to
th duration
tbody
tr(v-for='set in datasets')
td {{ set.exchange }}
td {{ set.currency }}
td {{ set.asset }}
td {{ fmt(set.from) }}
td {{ fmt(set.to) }}
td {{ humanizeDuration(set.to.diff(set.from)) }}
template(v-if='!datasets.length')
p It looks like you don't have any local data yet.
.my2
h2 Import more data
p.text You can easily import more market data directly from exchanges using the importer.
router-link.btn--primary(to='/data/importer') Go to the importer!
</template>
<script>
import spinner from '../global/blockSpinner.vue'
import marked from '../../tools/marked'
import dataset from '../global/mixins/dataset'
// global moment
// global humanizeDuration
let intro = marked(`
## Local data
Gekko needs local market data in order to backtest strategies. The local
data can also be used in a warmup period when running a strategy against a
live market.
`);
export default {
mixins: [ dataset ],
components: {
spinner
},
data: () => {
return {
intro,
viewUnscannable: false
}
},
methods: {
toggleUnscannable: function() { this.viewUnscannable = true },
humanizeDuration: (n) => window.humanizeDuration(n),
fmt: mom => mom.format('YYYY-MM-DD HH:mm'),
}
}
</script>
<style>
.clickable {
cursor: pointer;
}
table.full {
width: 100%;
}
table.full td {
padding: 0.5rem 0;
}
table.full.data th {
text-align: left;
padding: 0.5rem 0;
}
.warning p {
margin: 0;
padding: 0;
}
</style>
@@ -0,0 +1,65 @@
<template lang='pug'>
.grd.contain
.grd-row
.grd-row-col-3-6.mx1
h3 Market
market-picker(v-on:market='updateMarketConfig', only-importable='true')
.grd-row-col-3-6.mx1
range-creator(v-on:range='updateRange')
</template>
<script>
import marketPicker from '../../global/configbuilder/marketpicker.vue'
import rangeCreator from '../../global/configbuilder/rangecreator.vue'
import _ from 'lodash'
export default {
data: () => {
return {
market: {},
range: {}
}
},
components: {
marketPicker,
rangeCreator
},
computed: {
config: function() {
let config = {};
Object.assign(
config,
this.market,
{
importer: {
daterange: this.range
}
},
{
candleWriter: { enabled: true }
}
);
return config;
}
},
methods: {
updateMarketConfig: function(mc) {
this.market = mc;
this.emitConfig();
},
updateRange: function(range) {
this.range = range;
this.emitConfig();
},
emitConfig: function() {
this.$emit('config', this.config);
}
}
}
</script>
<style>
</style>
@@ -0,0 +1,90 @@
<template lang='pug'>
div.contain.my2
div.text(v-html='intro')
.hr
h3 Currently running imports
p(v-if='imports.length === 0') You currently don't have any imports running.
ul(v-if='imports.length')
li(v-for='_import in imports')
router-link(:to='"/data/importer/import/" + _import.id') {{ _import.watch.exchange }}:{{ _import.watch.currency }}/{{ _import.watch.asset }}
.hr
h3 Start a new import
import-config-builder(v-on:config='updateConfig')
.hr
.txt--center
a.w100--s.my1.btn--primary(href='#', v-on:click.prevent='run') Import
</template>
<script>
import { post } from '../../../tools/ajax'
import spinner from '../../global/blockSpinner.vue'
import importConfigBuilder from './importConfigBuilder.vue'
import marked from '../../../tools/marked'
let intro = marked(`
## Import data
The importer can download historical market data directly from the exchange.
`)
export default {
components: {
importConfigBuilder,
spinner
},
data: () => {
return {
intro,
config: {}
}
},
computed: {
imports: function() {
return this.$store.state.imports
}
},
methods: {
daysApart: function(range) {
let to = moment(range.to);
let from = moment(range.from);
return to.diff(from, 'days');
},
updateConfig: function(config) {
this.config = config;
},
run: function() {
let daysApart = this.daysApart(this.config.importer.daterange);
if(daysApart < 1)
return alert('You can only import at least one day of data..')
let exchange = this.$store.state.exchanges[this.config.watch.exchange];
if ("exchangeMaxHistoryAge" in exchange) {
if (moment(this.config.importer.daterange.from) < moment().subtract(exchange.exchangeMaxHistoryAge, "days")) {
return alert('Your date from is too old for ' + this.config.watch.exchange + '. It supports only the last ' + exchange.exchangeMaxHistoryAge + ' days..');
}
}
post('import', this.config, (error, response) => {
if(error)
return alert(error);
this.$store.commit('addImport', response);
this.$router.push({
path: `/data/importer/import/${response.id}`,
})
});
}
}
}
</script>
<style>
</style>
@@ -0,0 +1,110 @@
<template lang='pug'>
div.contain.my2
div(v-if='data && !data.done')
h2 Importing data..
.grd
.grd-row
.grd-row-col-2-6 <strong>Market:</strong>
.grd-row-col-4-6 {{ data.watch.exchange }}
.grd-row
.grd-row-col-2-6 <strong>Currency/Asset:</strong>
.grd-row-col-4-6 {{ data.watch.currency }}/{{ data.watch.asset }}
.grd
.grd-row
.grd-row-col-2-6 <strong>From:</strong>
.grd-row-col-4-6 {{ fmt(from) }}
.grd-row
.grd-row-col-2-6 <strong>To:</strong>
.grd-row-col-4-6 {{ fmt(to) }}
.grd-row(v-if='initialized')
.grd-row-col-2-6 <strong>Imported data until:</strong>
.grd-row-col-4-6 {{ fmt(latest) }}
.grd-row(v-if='initialized')
.grd-row-col-2-6 <strong>Remaining:</strong>
.grd-row-col-4-6 {{ fromEnd }}
spinner(v-if='!initialized')
.contain(v-if='initialized')
progressBar(:progress='progress')
p
em (you don't have to wait until the import is done,
| you can already start
router-link(to='/backtest') backtesting
| ).
div(v-if='data && data.done').txt--center
h2 Import done
p
| Go and
router-link(to='/backtest') backtest
| with your new data!
div(v-if='!data').txt--center
h2 ERROR: Unknown import
p
I don't know this import..
</template>
<script>
import _ from 'lodash';
import progressBar from '../../global/progressBar.vue'
import spinner from '../../global/blockSpinner.vue'
export default {
components: {
progressBar,
spinner
},
computed: {
data: function() {
return _.find(
this.$store.state.imports,
{ id: this.$route.params.id }
);
},
initialized: function() {
if(this.data && this.latest.isValid())
return true
},
latest: function() {
if(this.data)
return this.mom(this.data.latest);
},
fromEndMs: function() {
if(this.data)
return this.to.diff(this.latest);
},
fromEnd: function() {
if(!this.latest)
return 'LOADING'
return humanizeDuration(this.fromEndMs);
},
from: function() {
if(this.data)
return this.mom(this.data.from)
},
to: function() {
if(this.data)
return this.mom(this.data.to)
},
timespan: function() {
if(this.data)
return this.to.diff(this.from)
},
progress: function() {
if(!this.data)
return;
const current = this.timespan - this.fromEndMs;
return 100 * current / this.timespan;
}
},
methods: {
fmt: mom => { return mom.format('YYYY-MM-DD HH:mm:ss') },
mom: str => moment.utc(str)
}
}
</script>
<style>
</style>
@@ -0,0 +1,123 @@
<template lang='pug'>
.grd.contain
.grd-row
.grd-row-col-3-6.mx1
h3 Market
market-picker(v-on:market='updateMarketConfig', :only-tradable='isTradebot')
.grd-row-col-3-6.mx1
type-picker(v-on:type='updateType')
template(v-if='type !== "market watcher"')
.hr
strat-picker.contain.my2(v-on:stratConfig='updateStrat')
.hr(v-if='type === "paper trader"')
paper-trader(v-on:settings='updatePaperTrader', v-if='type === "paper trader"')
</template>
<script>
import marketPicker from '../global/configbuilder/marketpicker.vue'
import typePicker from '../global/configbuilder/typepicker.vue'
import stratPicker from '../global/configbuilder/stratpicker.vue'
import paperTrader from '../global/configbuilder/papertrader.vue'
import { get } from '../../tools/ajax'
import _ from 'lodash'
export default {
created: function() {
get('configPart/candleWriter', (error, response) => {
this.candleWriter = toml.parse(response.part);
});
get('configPart/performanceAnalyzer', (error, response) => {
this.performanceAnalyzer = toml.parse(response.part);
this.performanceAnalyzer.enabled = true;
});
},
data: () => {
return {
market: {},
range: {},
type: '',
strat: {},
paperTrader: {},
candleWriter: {},
performanceAnalyzer: {}
}
},
components: {
marketPicker,
typePicker,
stratPicker,
paperTrader
},
computed: {
isTradebot: function() {
return this.type === 'tradebot';
},
config: function() {
let config = {};
Object.assign(
config,
this.market,
this.strat,
{ paperTrader: this.paperTrader },
{ candleWriter: this.candleWriter },
{ type: this.type },
{ performanceAnalyzer: this.performanceAnalyzer }
);
if(this.isTradebot) {
delete config.paperTrader;
config.trader = { enabled: true }
}
config.valid = this.validConfig(config);
return config;
}
},
methods: {
validConfig: config => {
if(config.type === 'market watcher')
return true;
if(!config.tradingAdvisor)
return false;
if(_.isNaN(config.tradingAdvisor.candleSize))
return false;
else if(config.tradingAdvisor.candleSize == 0)
return false;
let strat = config.tradingAdvisor.method;
if(_.isEmpty(config[ strat ]))
return false;
return true;
},
updateMarketConfig: function(mc) {
this.market = mc;
this.emitConfig();
},
updateType: function(type) {
this.type = type;
this.emitConfig();
},
updateStrat: function(strat) {
this.strat = strat;
this.emitConfig();
},
updatePaperTrader: function(pt) {
this.paperTrader = pt;
this.paperTrader.enabled = true;
this.emitConfig();
},
emitConfig: function() {
this.$emit('config', this.config);
}
}
}
</script>
<style>
</style>
+143
View File
@@ -0,0 +1,143 @@
<template lang='pug'>
.contain.py2
h3 Market watchers
.text(v-if='!watchers.length')
p You don't have any market watchers.
table.full.clickable(v-if='watchers.length')
thead
tr
th exchange
th currency
th asset
th status
th started at
th last update
th duration
tbody
tr.clickable(v-for='gekko in watchers', v-on:click='$router.push({path: `/live-gekkos/${gekko.id}`})')
td {{ gekko.config.watch.exchange }}
td {{ gekko.config.watch.currency }}
td {{ gekko.config.watch.asset }}
td {{ status(gekko) }}
td
template(v-if='gekko.events.initial.candle') {{ fmt(gekko.events.initial.candle.start) }}
td
template(v-if='gekko.events.latest.candle') {{ fmt(gekko.events.latest.candle.start) }}
td
template(v-if='gekko.events.initial.candle && gekko.events.latest.candle') {{ timespan(gekko.events.latest.candle.start, gekko.events.initial.candle.start) }}
h3 Strat runners
.text(v-if='!stratrunners.length')
p You don't have any stratrunners.
table.full(v-if='stratrunners.length')
thead
tr
th exchange
th currency
th asset
th status
th duration
th strategy
th PnL
th type
th trades
tbody
tr.clickable(v-for='gekko in stratrunners', v-on:click='$router.push({path: `/live-gekkos/${gekko.id}`})')
td {{ gekko.config.watch.exchange }}
td {{ gekko.config.watch.currency }}
td {{ gekko.config.watch.asset }}
td {{ status(gekko) }}
td
template(v-if='gekko.events.initial.candle && gekko.events.latest.candle') {{ timespan(gekko.events.latest.candle.start, gekko.events.initial.candle.start) }}
td {{ gekko.config.tradingAdvisor.method }}
td
template(v-if='!report(gekko)') 0
template(v-if='report(gekko)') {{ round(report(gekko).profit) }} {{ report(gekko).currency }}
td {{ gekko.logType }}
td
template(v-if='!gekko.events.tradeCompleted') 0
template(v-if='gekko.events.tradeCompleted') {{ gekko.events.tradeCompleted.length }}
.hr
h2 Start a new live Gekko
router-link.btn--primary(to='/live-gekkos/new') Start a new live Gekko!
</template>
<script>
// global moment
// global humanizeDuration
export default {
created: function() {
this.timer = setInterval(() => {
this.now = moment();
}, 1000)
},
destroyed: function() {
clearTimeout(this.timer);
},
data: () => {
return {
timer: false,
now: moment()
}
},
computed: {
stratrunners: function() {
return _.values(this.$store.state.gekkos)
.concat(_.values(this.$store.state.archivedGekkos))
.filter(g => {
if(g.logType === 'papertrader')
return true;
if(g.logType === 'tradebot')
return true;
return false;
})
},
watchers: function() {
return _.values(this.$store.state.gekkos)
.concat(_.values(this.$store.state.archivedGekkos))
.filter(g => g.logType === 'watcher')
}
},
methods: {
humanizeDuration: (n) => window.humanizeDuration(n),
moment: mom => moment.utc(mom),
fmt: mom => moment.utc(mom).format('YYYY-MM-DD HH:mm'),
round: n => (+n).toFixed(3),
timespan: function(a, b) {
return this.humanizeDuration(this.moment(a).diff(this.moment(b)))
},
status: state => {
if(state.errored)
return 'errored';
if(state.stopped)
return 'stopped';
if(state.active)
return 'running';
console.log('unknown state:', state);
},
report: state => {
return _.get(state, 'events.latest.performanceReport');
}
}
}
</script>
<style>
table.clickable {
border-collapse: separate;
}
tr.clickable td:nth-child(1) {
padding-left: 5px;
}
tr.clickable {
cursor: pointer;
}
tr.clickable:hover {
background: rgba(216,216,216,.99);
}
</style>
+200
View File
@@ -0,0 +1,200 @@
<template lang='pug'>
div.contain.my2
h3 Start a new gekko
gekko-config-builder(v-on:config='updateConfig')
.hr
.txt--center(v-if='config.valid')
a.w100--s.my1.btn--primary(href='#', v-on:click.prevent='start', v-if="!pendingStratrunner") Start
spinner(v-if='pendingStratrunner')
</template>
<script>
import _ from 'lodash'
import Vue from 'vue'
import { post } from '../../tools/ajax'
import gekkoConfigBuilder from './gekkoConfigBuilder.vue'
import spinner from '../global/blockSpinner.vue'
export default {
components: {
gekkoConfigBuilder,
spinner
},
data: () => {
return {
pendingStratrunner: false,
config: {}
}
},
computed: {
gekkos: function() {
return this.$store.state.gekkos;
},
watchConfig: function() {
let raw = _.pick(this.config, 'watch', 'candleWriter');
let watchConfig = Vue.util.extend({}, raw);
watchConfig.type = 'market watcher';
watchConfig.mode = 'realtime';
return watchConfig;
},
requiredHistoricalData: function() {
if(!this.config.tradingAdvisor || !this.config.valid)
return;
let stratSettings = this.config.tradingAdvisor;
return stratSettings.candleSize * stratSettings.historySize;
},
gekkoConfig: function() {
var startAt;
if(!this.existingMarketWatcher)
return;
if(!this.requiredHistoricalData)
startAt = moment().utc().startOf('minute').format();
else {
// TODO: figure out whether we can stitch data
// without looking at the existing watcher
const optimal = moment().utc().startOf('minute')
.subtract(this.requiredHistoricalData, 'minutes')
.unix();
const available = moment
.utc(this.existingMarketWatcher.events.initial.candle.start)
.unix();
startAt = moment.unix(Math.max(optimal, available)).utc().format();
}
const gekkoConfig = Vue.util.extend({
market: {
type: 'leech',
from: startAt
},
mode: 'realtime'
}, this.config);
return gekkoConfig;
},
existingMarketWatcher: function() {
const market = Vue.util.extend({}, this.watchConfig.watch);
return _.find(this.gekkos, {config: {watch: market}});
},
exchange: function() {
return this.watchConfig.watch.exchange;
},
existingTradebot: function() {
return _.find(
this.gekkos,
g => {
if(g.logType === 'tradebot' && g.config.watch.exchange === this.exchange) {
return true;
}
return false;
}
);
},
availableApiKeys: function() {
return this.$store.state.apiKeys;
}
},
watch: {
// start the stratrunner
existingMarketWatcher: function(val, prev) {
if(!this.pendingStratrunner)
return;
const gekko = this.existingMarketWatcher;
if(gekko.events.latest.candle) {
this.pendingStratrunner = false;
this.startGekko((err, resp) => {
this.$router.push({
path: `/live-gekkos/${resp.id}`
});
});
}
}
},
methods: {
updateConfig: function(config) {
this.config = config;
},
start: function() {
// if the user starts a tradebot we do some
// checks first.
if(this.config.type === 'tradebot') {
if(this.existingTradebot) {
let str = 'You already have a tradebot running on this exchange';
str += ', you can only run one tradebot per exchange.';
return alert(str);
}
if(!this.availableApiKeys.includes(this.exchange))
return alert('Please first configure API keys for this exchange in the config page.')
}
// internally a live gekko consists of two parts:
//
// - a market watcher
// - a live gekko (strat runner + (paper) trader)
//
// however if the user selected type "market watcher"
// the second part won't be created
if(this.config.type === 'market watcher') {
// check if the specified market is already being watched
if(this.existingMarketWatcher) {
alert('This market is already being watched, redirecting you now...');
this.$router.push({
path: `/live-gekkos/${this.existingMarketWatcher.id}`
});
} else {
this.startWatcher((error, resp) => {
this.$router.push({
path: `/live-gekkos/${resp.id}`
});
});
}
} else {
if(this.existingMarketWatcher) {
// the specified market is already being watched,
// just start a gekko!
this.startGekko(this.routeToGekko);
} else {
// the specified market is not yet being watched,
// we need to create a watcher
this.startWatcher((err, resp) => {
this.pendingStratrunner = resp.id;
// now we just wait for the watcher to be properly initialized
// (see the `watch.existingMarketWatcher` method)
});
}
}
},
routeToGekko: function(err, resp) {
if(err || resp.error)
return console.error(err, resp.error);
this.$router.push({
path: `/live-gekkos/${resp.id}`
});
},
startWatcher: function(next) {
post('startGekko', this.watchConfig, next);
},
startGekko: function(next) {
post('startGekko', this.gekkoConfig, next);
}
}
}
</script>
<style>
</style>
@@ -0,0 +1,361 @@
<template lang='pug'>
div.my2
.contain(v-if='!data')
h1 Unknown Gekko instance
p Gekko doesn't know what gekko this is...
div(v-if='data')
h2.contain Gekko {{ type }}
div(v-if='isArchived', class='contain brdr--mid-gray p1 bg--orange')
| This is an archived Gekko, it is currently not running anymore.
div(v-if='data.errorMessage', class='contain brdr--mid-gray p1 bg--orange')
| This is Gekko crashed with the following error: {{ data.errorMessage }}
.grd.contain
.grd-row
.grd-row-col-3-6
h3 Market
.grd-row
.grd-row-col-3-6 Exchange
.grd-row-col-3-6 {{ config.watch.exchange }}
.grd-row
.grd-row-col-3-6 Currency
.grd-row-col-3-6 {{ config.watch.currency }}
.grd-row
.grd-row-col-3-6 Asset
.grd-row-col-3-6 {{ config.watch.asset }}
.grd-row
.grd-row-col-3-6 Type
.grd-row-col-3-6 {{ type }}
.grd-row-col-3-6
h3 Runtime
spinner(v-if='isLoading')
template(v-if='!isLoading')
.grd-row(v-if='initialEvents.candle')
.grd-row-col-2-6 Watching since
.grd-row-col-4-6 {{ fmt(initialEvents.candle.start) }}
.grd-row(v-if='latestEvents.candle')
.grd-row-col-2-6 Received data until
.grd-row-col-4-6 {{ fmt(latestEvents.candle.start) }}
.grd-row(v-if='latestEvents.candle')
.grd-row-col-2-6 Data spanning
.grd-row-col-4-6 {{ humanizeDuration(moment(latestEvents.candle.start).diff(moment(initialEvents.candle.start))) }}
template(v-if='isStratrunner')
.grd-row
.grd-row-col-2-6 Amount of trades
.grd-row-col-4-6 {{ trades.length }}
.grd-row
.grd-row-col-2-6 Candle size
.grd-row-col-4-6 {{ config.tradingAdvisor.candleSize }}
.grd-row
.grd-row-col-2-6 History size
.grd-row-col-4-6 {{ config.tradingAdvisor.historySize }}
div(v-if='warmupRemaining', class='contain brdr--mid-gray p1 bg--orange')
| This stratrunner is still warming up for the next
i {{ warmupRemaining.replace(',', ' and ') }}
| , it will not trade until it is warmed up.
.grd-row(v-if='isStratrunner')
.grd-row-col-3-6
h3 Strategy
.grd-row
.grd-row-col-3-6 Name
.grd-row-col-3-6
strong {{ stratName }}
| Parameters
pre {{ stratParams }}
.grd-row-col-3-6
h3 Profit report
template(v-if='!report')
p
em(v-if='isArchived') This Gekko never executed a trade..
em(v-if='!isArchived') Waiting for at least one trade..
template(v-if='report')
.grd-row
.grd-row-col-3-6 Start balance
.grd-row-col-3-6 {{ round(report.startBalance) }}
.grd-row
.grd-row-col-3-6 Current balance
.grd-row-col-3-6 {{ round(report.balance) }}
.grd-row
.grd-row-col-3-6 Market
.grd-row-col-3-6 {{round(report.market / 100 * report.startPrice)}} {{ config.watch.currency }} ({{ round(report.market) }} %)
.grd-row
.grd-row-col-3-6 Profit
.grd-row-col-3-6 {{ round(report.profit) }} {{ config.watch.currency }} ({{ round(report.relativeProfit) }} %)
.grd-row
.grd-row-col-3-6 Alpha
.grd-row-col-3-6 {{ round(report.alpha) }} {{ config.watch.currency }}
p(v-if='isStratrunner && !watcher && !isArchived') WARNING: stale gekko, not attached to a watcher, please report
a(href='https://github.com/askmike/gekko/issues') here
| .
p(v-if='!isArchived')
a(v-on:click='stopGekko', class='w100--s my1 btn--red') Stop Gekko
p(v-if='isArchived')
a(v-on:click='deleteGekko', class='w100--s my1 btn--red') Delete Gekko
p(v-if='isStratrunner && watcher && !isArchived')
em This gekko gets market data from
router-link(:to='"/live-gekkos/" + watcher.id') this market watcher
| .
template(v-if='!isLoading')
h3.contain Market graph
spinner(v-if='candleFetch === "fetching"')
template(v-if='candleFetch === "fetched"')
chart(:data='chartData', :height='300')
roundtrips(v-if='isStratrunner', :roundtrips='roundtrips')
</template>
<script>
import Vue from 'vue'
import _ from 'lodash'
import { post } from '../../tools/ajax'
import spinner from '../global/blockSpinner.vue'
import chart from '../backtester/result/chartWrapper.vue'
import roundtrips from '../backtester/result/roundtripTable.vue'
import paperTradeSummary from '../global/paperTradeSummary.vue'
// global moment
export default {
created: function() {
if(!this.isLoading)
this.getCandles();
},
components: {
spinner,
chart,
paperTradeSummary,
roundtrips
},
data: () => {
return {
candleFetch: 'idle',
candles: false
}
},
computed: {
id: function() {
return this.$route.params.id;
},
gekkos: function() {
return this.$store.state.gekkos;
},
archivedGekkos: function() {
return this.$store.state.archivedGekkos;
},
data: function() {
if(!this.gekkos)
return false;
if(_.has(this.gekkos, this.id))
return this.gekkos[this.id];
if(_.has(this.archivedGekkos, this.id))
return this.archivedGekkos[this.id];
return false;
},
config: function() {
return _.get(this, 'data.config');
},
latestEvents: function() {
return _.get(this, 'data.events.latest');
},
initialEvents: function() {
return _.get(this, 'data.events.initial');
},
trades: function() {
return _.get(this, 'data.events.tradeCompleted') || [];
},
roundtrips: function() {
return _.get(this, 'data.events.roundtrip') || [];
},
isLive: function() {
return _.has(this.gekkos, this.id);
},
type: function() {
return this.data.logType;
},
isStratrunner: function() {
return this.type !== 'watcher';
},
isArchived: function() {
return this.data.stopped;
},
warmupRemaining: function() {
if(!this.isStratrunner) {
return false;
}
if(this.isArchived) {
return false;
}
if(this.initialEvents.stratWarmupCompleted) {
return false;
}
if(!this.initialEvents.candle) {
return false;
}
const historySize = _.get(this.config, 'tradingAdvisor.historySize');
if(!historySize) {
return false;
}
const warmupTime = _.get(this.config, 'tradingAdvisor.candleSize') * historySize;
return humanizeDuration(
moment(this.initialEvents.candle.start).add(warmupTime, 'm').diff(moment()),
{ largest: 2 }
);
},
chartData: function() {
return {
candles: this.candles,
trades: this.trades
}
},
report: function() {
return _.get(this.latestEvents, 'performanceReport');
},
stratName: function() {
if(this.data)
return this.data.config.tradingAdvisor.method;
},
stratParams: function() {
if(!this.data)
return 'Loading...';
let stratParams = Vue.util.extend({}, this.data.config[this.stratName]);
delete stratParams.__empty;
if(_.isEmpty(stratParams))
return 'No parameters'
return JSON.stringify(stratParams, null, 4);
},
isLoading: function() {
if(!this.data)
return true;
if(!_.get(this.data, 'events.initial.candle'))
return true;
if(!_.get(this.data, 'events.latest.candle'))
return true;
return false;
},
watcher: function() {
if(!this.isStratrunner) {
return false;
}
let watch = Vue.util.extend({}, this.data.config.watch);
return _.find(this.gekkos, g => {
if(g.id === this.id)
return false;
return _.isEqual(watch, g.config.watch);
});
},
hasLeechers: function() {
if(this.isStratrunner) {
return false;
}
let watch = Vue.util.extend({}, this.data.config.watch);
return _.find(this.gekkos, g => {
if(g.id === this.id)
return false;
return _.isEqual(watch, g.config.watch);
});
}
},
watch: {
'data.events.latest.candle.start': function() {
setTimeout(this.getCandles, _.random(100, 2000));
}
},
methods: {
round: n => (+n).toFixed(5),
humanizeDuration: (n, x) => window.humanizeDuration(n, x),
moment: mom => moment.utc(mom),
fmt: mom => moment.utc(mom).format('YYYY-MM-DD HH:mm'),
getCandles: function() {
if(this.isLoading) {
return;
}
if(this.candleFetch === 'fetching') {
return;
}
this.candleFetch = 'fetching';
let to = this.data.events.latest.candle.start;
let from = this.data.events.initial.candle.start;
let candleSize = 1;
if(this.type !== 'watcher') {
candleSize = this.data.config.tradingAdvisor.candleSize;
}
let config = {
watch: this.data.config.watch,
daterange: {
to, from
},
candleSize
};
// We timeout because of 2 reasons:
// - In case we get a batch of candles we only fetch once
// - This way we give the db (mostly sqlite) some time to write
// the result before we query it.
setTimeout(() => {
post('getCandles', config, (err, res) => {
this.candleFetch = 'fetched';
if(!res || res.error || !_.isArray(res))
return console.log(res);
this.candles = res.map(c => {
c.start = moment.unix(c.start).utc().format();
return c;
});
})
}, _.random(150, 2500));
},
stopGekko: function() {
if(this.hasLeechers) {
return alert('This Gekko is fetching market data for multiple stratrunners, stop these first.');
}
if(!confirm('Are you sure you want to stop this Gekko?')) {
return;
}
post('stopGekko', { id: this.data.id }, (err, res) => {
console.log('stopped gekko');
});
},
deleteGekko: function() {
if(!this.isArchived) {
return alert('This Gekko is still running, stop it first!');
}
if(!confirm('Are you sure you want to delete this Gekko?')) {
return;
}
post('deleteGekko', { id: this.data.id }, (err, res) => {
this.$router.push({
path: `/live-gekkos/`
});
});
}
}
}
</script>
<style>
</style>
@@ -0,0 +1,153 @@
<template lang='pug'>
div.my2
.contain(v-if='!data')
h1 Unknown Watcher
p Gekko doesn't know what whatcher this is...
div(v-if='data')
h2.contain Market Watcher
.grd.contain
h3 Market
.grd-row
.grd-row-col-2-6 Exchange
.grd-row-col-4-6 {{ data.watch.exchange }}
.grd-row
.grd-row-col-2-6 Currency
.grd-row-col-4-6 {{ data.watch.currency }}
.grd-row
.grd-row-col-2-6 Asset
.grd-row-col-4-6 {{ data.watch.asset }}
h3 Statistics
spinner(v-if='isLoading')
template(v-if='!isLoading')
.grd-row(v-if='data.firstCandle')
.grd-row-col-2-6 Watching since
.grd-row-col-4-6 {{ fmt(data.firstCandle.start) }}
.grd-row(v-if='data.lastCandle')
.grd-row-col-2-6 Received data until
.grd-row-col-4-6 {{ fmt(data.lastCandle.start) }}
.grd-row(v-if='data.lastCandle && data.firstCandle')
.grd-row-col-2-6 Data spanning
.grd-row-col-4-6 {{ humanizeDuration(moment(data.lastCandle.start).diff(moment(data.firstCandle.start))) }}
template(v-if='!isLoading')
h3.contain Market graph
spinner(v-if='candleFetch === "fetching"')
template(v-if='candles.length')
chart(:data='chartData', :height='500')
</template>
<script>
import { post } from '../../tools/ajax'
import _ from 'lodash'
import spinner from '../global/blockSpinner.vue'
import Vue from 'vue'
import chart from '../backtester/result/chartWrapper.vue'
// global moment
export default {
created: function() {
if(!this.isLoading)
this.getCandles();
},
components: {
spinner,
chart
},
data: () => {
return {
candleFetch: 'idle',
candles: []
}
},
computed: {
watchers: function() {
return this.$store.state.watchers;
},
data: function() {
return _.find(this.watchers, {id: this.$route.params.id});
},
chartData: function() {
return {
candles: this.candles,
trades: []
}
},
isLoading: function() {
if(!this.data)
return true;
if(!_.isObject(this.data.firstCandle))
return true;
if(!_.isObject(this.data.lastCandle))
return true;
return false;
},
},
watch: {
'data.lastCandle.start': function() {
this.candleFetch = 'dirty';
},
data: function(val, prev) {
let complete = val && val.firstCandle && val.lastCandle;
if(!complete)
return;
if(this.candleFetch !== 'fetched' )
this.getCandles();
}
},
methods: {
humanizeDuration: (n) => window.humanizeDuration(n),
moment: mom => moment.utc(mom),
fmt: mom => moment.utc(mom).format('YYYY-MM-DD HH:mm'),
getCandles: function() {
this.candleFetch = 'fetching';
// up unto we have data
let to = moment.utc(
this.data.lastCandle.start
).unix();
// max 7 days of data
let from = Math.max(
moment.utc(this.data.firstCandle.start).unix(),
moment.utc(to).subtract(7, 'days').unix()
);
// TODO...
const diff = to - from;
let candleSize = 60;
if(diff < 60 * 60 * 24) // a day
if(diff < 60 * 60 * 12) // 3 hours
candleSize = 1;
else
candleSize = 5;
from = moment.unix(from).utc().format();
to = moment.unix(to).utc().format();
let config = {
watch: this.data.watch,
daterange: {
to, from
},
// hourly candles
candleSize
};
post('getCandles', config, (err, res) => {
this.candleFetch = 'fetched';
this.candles = res.map(c => {
c.start = moment.unix(c.start).utc().format();
return c;
});
})
}
}
}
</script>
<style>
</style>
@@ -0,0 +1,69 @@
// http://tobiasahlin.com/spinkit/
<template lang='pug'>
.spinner
.rect1
.rect2
.rect3
.rect4
</template>
<script>
export default {}
</script>
<style>
.spinner {
margin: 20px auto 100px auto;
width: 50px;
height: 40px;
text-align: center;
font-size: 10px;
}
.spinner > div {
background-color: #333;
height: 100%;
width: 6px;
display: inline-block;
margin-right: 4px;
-webkit-animation: sk-stretchdelay 1.2s infinite ease-in-out;
animation: sk-stretchdelay 1.2s infinite ease-in-out;
}
.spinner .rect2 {
-webkit-animation-delay: -1.1s;
animation-delay: -1.1s;
}
.spinner .rect3 {
-webkit-animation-delay: -1.0s;
animation-delay: -1.0s;
}
.spinner .rect4 {
-webkit-animation-delay: -0.9s;
animation-delay: -0.9s;
}
.spinner .rect5 {
-webkit-animation-delay: -0.8s;
animation-delay: -0.8s;
}
@-webkit-keyframes sk-stretchdelay {
0%, 40%, 100% { -webkit-transform: scaleY(0.4) }
20% { -webkit-transform: scaleY(1.0) }
}
@keyframes sk-stretchdelay {
0%, 40%, 100% {
transform: scaleY(0.4);
-webkit-transform: scaleY(0.4);
} 20% {
transform: scaleY(1.0);
-webkit-transform: scaleY(1.0);
}
}
</style>
@@ -0,0 +1,131 @@
<template lang='pug'>
div
h3 Select a dataset
.txt--center.my2(v-if='datasetScanstate === "idle"')
a.w100--s.btn--primary.scan-btn(href='#', v-on:click.prevent='scan') Scan available data
.txt--center.my2(v-if='datasetScanstate === "scanning"')
spinner
.my2(v-if='datasetScanstate === "scanned"')
div(v-if='datasets.length != 0')
table.full
thead
tr
th
th exchange
th currency
th asset
th from
th to
th duration
tbody
tr(v-for='(set, i) in datasets')
td.radio
input(type='radio', name='dataset', :value='i', v-model='setIndex', v-bind:id='set.id')
td
label(v-bind:for='set.id') {{ set.exchange }}
td
label(v-bind:for='set.id') {{ set.currency }}
td
label(v-bind:for='set.id') {{ set.asset }}
td
label(v-bind:for='set.id') {{ fmt(set.from) }}
td
label(v-bind:for='set.id') {{ fmt(set.to) }}
td
label(v-bind:for='set.id') {{ humanizeDuration(set.to.diff(set.from)) }}
a.btn--primary(href='#', v-on:click.prevent='openRange', v-if='!rangeVisible') Adjust range
template(v-if='rangeVisible')
div
label(for='customFrom') From:
input(v-model='customFrom')
div
label(for='customTo') To:
input(v-model='customTo')
em(v-else) No Data found
a(href='#/data/importer') Lets add some
</template>
<script>
import _ from 'lodash'
import Vue from 'vue'
import { post } from '../../../tools/ajax'
import spinner from '../../global/blockSpinner.vue'
import dataset from '../../global/mixins/dataset'
export default {
components: {
spinner
},
data: () => {
return {
setIndex: -1,
customTo: false,
customFrom: false,
rangeVisible: false,
set: false
};
},
mixins: [ dataset ],
methods: {
humanizeDuration: (n) => {
return window.humanizeDuration(n, {largest: 4});
},
fmt: mom => mom.utc().format('YYYY-MM-DD HH:mm'),
openRange: function() {
if(this.setIndex === -1)
return alert('Select a dataset to adjust range');
this.updateCustomRange();
this.rangeVisible = true;
},
updateCustomRange: function() {
this.customTo = this.fmt(this.set.to);
this.customFrom = this.fmt(this.set.from);
},
emitSet: function(val) {
if(!val)
return;
let set;
if(!this.customTo)
set = val;
else {
set = Vue.util.extend({}, val);
set.to = moment.utc(this.customTo, 'YYYY-MM-DD HH:mm').format();
set.from = moment.utc(this.customFrom, 'YYYY-MM-DD HH:mm').format();
}
this.$emit('dataset', set);
}
},
watch: {
setIndex: function() {
this.set = this.datasets[this.setIndex];
this.updateCustomRange();
this.emitSet(this.set);
},
customTo: function() { this.emitSet(this.set); },
customFrom: function() { this.emitSet(this.set); }
}
}
</script>
<style>
td.radio {
width: 45px;
}
td label{
display: inline;
font-size: 1em;
}
</style>
@@ -0,0 +1,65 @@
<template lang='pug'>
div
.mx1
label(for='exchange').wrapper Exchange:
.custom-select.button
select(v-model='exchange')
option(v-for='(market, e) in exchanges') {{ e }}
</template>
<script>
import _ from 'lodash'
import rangePicker from './rangepicker.vue'
import rangeCreator from './rangecreator.vue'
import { get } from '../../../tools/ajax'
export default {
props: ['onlyTradable', 'onlyImportable'],
data: () => {
return {
exchange: 'poloniex',
};
},
created: function() {
this.emitExchange();
},
computed: {
exchanges: function() {
let exchanges = Object.assign({}, this.$store.state.exchanges);
if(_.isEmpty(exchanges))
return false;
if(this.onlyTradable) {
_.each(exchanges, (e, name) => {
if(!e.tradable)
delete exchanges[name];
});
}
if(this.onlyImportable) {
_.each(exchanges, (e, name) => {
if(!e.importable)
delete exchanges[name];
});
}
return exchanges;
}
},
watch: {
exchanges: function() { this.emitExchange() },
exchange: function() { this.emitExchange() }
},
methods: {
emitExchange: function() {
this.$emit('exchange', this.exchange);
}
}
}
</script>
</style>
@@ -0,0 +1,102 @@
<template lang='pug'>
div
.mx1
label(for='exchange').wrapper Exchange:
.custom-select.button
select(v-model='exchange')
option(v-for='(market, e) in exchanges') {{ e }}
.grd-row
.grd-row-col-3-6.mx1
label(for='currency') Currency:
.custom-select.button
select(v-model='currency')
option(v-for='cur in currencies') {{ cur }}
.grd-row-col-3-6.mx1
label(for='asset') Asset:
.custom-select.button
select(v-model='asset')
option(v-for='asst in assets') {{ asst }}
</template>
<script>
import _ from 'lodash'
import rangePicker from './rangepicker.vue'
import rangeCreator from './rangecreator.vue'
import { get } from '../../../tools/ajax'
export default {
props: ['onlyTradable', 'onlyImportable'],
data: () => {
return {
// defaults:
exchange: 'poloniex',
currency: 'USDT',
asset: 'BTC',
};
},
created: function() {
this.emitConfig();
},
computed: {
exchanges: function() {
let exchanges = Object.assign({}, this.$store.state.exchanges);
if(_.isEmpty(exchanges))
return false;
if(this.onlyTradable) {
_.each(exchanges, (e, name) => {
if(!e.tradable)
delete exchanges[name];
});
}
if(this.onlyImportable) {
_.each(exchanges, (e, name) => {
if(!e.importable)
delete exchanges[name];
});
}
return exchanges;
},
markets: function() {
return this.exchanges ? this.exchanges[ this.exchange ] : null;
},
assets: function() {
return this.exchanges ? this.exchanges[this.exchange].markets[this.currency] : null;
},
currencies: function() {
return this.exchanges ? _.keys( this.exchanges[this.exchange].markets ) : null;
},
watchConfig: function() {
return {
watch: {
exchange: this.exchange,
currency: this.currency,
asset: this.asset,
}
}
}
},
watch: {
currency: function() { this.emitConfig() },
asset: function() { this.emitConfig() },
market: function() { this.emitConfig() },
exchanges: function() { this.emitConfig() },
exchange: function() { this.emitConfig() }
},
methods: {
emitConfig: function() {
this.$emit('market', this.watchConfig);
}
}
}
</script>
</style>
@@ -0,0 +1,72 @@
<template lang='pug'>
.grd
.px1
h3 Paper trader
a.btn--primary(href='#', v-on:click.prevent='switchToggle', v-if='toggle === "closed"') Change paper trader settings
template(v-if='toggle === "open"')
p Settings:
textarea.params(v-model='rawPaperTraderParams')
p.bg--red.p1(v-if='rawPaperTraderParamsError') {{ rawPaperTraderParamsError.message }}
</template>
<script>
import _ from 'lodash'
import { get } from '../../../tools/ajax'
export default {
created: function() {
get('configPart/paperTrader', (error, response) => {
this.rawPaperTraderParams = response.part;
});
},
data: () => {
return {
rawPaperTraderParams: '',
rawPaperTraderParamsError: false,
paperTraderParams: {},
toggle: 'closed'
};
},
watch: {
rawPaperTraderParams: function() { this.emitConfig() }
},
methods: {
switchToggle: function() {
if(this.toggle === 'open')
this.toggle = 'closed';
else
this.toggle = 'open';
},
emitConfig: function() {
this.parseParams();
this.$emit('settings', this.paperTraderParams);
},
parseParams: function() {
try {
this.paperTraderParams = toml.parse(this.rawPaperTraderParams);
this.paperTraderParams.reportRoundtrips = true;
this.rawPaperTraderParamsError = false;
} catch(e) {
this.rawPaperTraderParamsError = e;
this.paperTraderParams = {};
}
}
}
}
</script>
<style>
.align .custom-select select {
padding: 0.4em 1.2em .3em .8em;
}
.label-like {
display: block;
font-size: 0.9em;
color: #777;
}
.align {
padding-left: 1em;
}
</style>
@@ -0,0 +1,93 @@
<template lang='pug'>
div
h3 Daterange
div
label(for='from') From
input(v-model='from')
div
label(for='to') To
input(v-model='to')
</template>
<script>
import _ from 'lodash'
import { post } from '../../../tools/ajax'
// global moment
export default {
data: function() {
return {
from: '',
to: ''
}
},
created: function() {
let now = moment().startOf('minute');
let then = now.clone().subtract(3, 'months');
this.to = this.fmt(now);
this.from = this.fmt(then);
this.emitRange();
},
methods: {
fmtTs: (mom) => moment.unix(mom).utc(),
fmt: (mom) => mom.utc().format('YYYY-MM-DD HH:mm'),
emitRange: function() {
this.$emit('range', {
from: this.fmtTs(this.from),
to: this.fmtTs(this.to)
});
},
emitManualEntry: function() {
if(this.from.length < '4' || this.from.length < '4')
return this.$emit('range', {})
let from = moment.utc(this.from);
let to = moment.utc(this.to);
if(from.isValid() && to.isValid()) {
this.$emit('range', {
from: this.fmt(from),
to: this.fmt(to)
})
} else {
this.$emit('range', {})
}
}
},
watch: {
from: function() {
this.emitManualEntry();
},
to: function() {
this.emitManualEntry();
},
config: function() {
this.scanned = false;
},
tab: function() {
this.scanned = false;
this.$emit('range', {})
},
selectedRangeIndex: function() {
let selectedRange = this.ranges[this.selectedRangeIndex];
if(selectedRange)
this.emitRange(selectedRange);
}
}
}
</script>
<style>
.scan-btn {
margin-top: 80px;
margin-bottom: 30px;
}
.radio label {
margin-top: 0;
}
</style>
@@ -0,0 +1,138 @@
<template lang='pug'>
div
h3 Daterange
template(v-if='tab === "scan"')
.txt--center(v-if='!scanned')
a.w100--s.btn--primary.scan-btn(href='#', v-on:click.prevent='scan') Scan available data
.txt--center(v-if='scanned == "fetching"')
p.scan-btn Scanning..
template(v-if='scanned == true')
template(v-if='ranges.length === 0')
p
strong Unable to find any local data, do you have local data available for
| "{{ config.watch.exchange }}:{{ config.watch.currency }}/{{ config.watch.asset }}"?
template(v-else)
label(for='exchange').wrapper Run simulation over:
form.radio.grd
div.grd-row(v-for='(range, i) in ranges').m1
input.grd-row-col-1-6(type='radio', :value='i', v-model='selectedRangeIndex')
label.grd-row-col-5-6(:for='i') {{ printRange(range) }}
p
em
a(href='#', v-on:click.prevent='scan') rescan
p.txt--center
em
a(href='#', v-on:click.prevent='tab = "manual"') Or manually set a daterange
template(v-if='tab === "manual"')
div
label(for='from') From:
input(v-model='from')
div
label(for='to') To:
input(v-model='to')
p.txt--center
em
a(href='#', v-on:click.prevent='tab = "scan"') Or scan for a daterange
</template>
<script>
import _ from 'lodash'
import { post } from '../../../tools/ajax'
// global moment
export default {
props: ['config'],
data: () => {
return {
scanned: false, // 'fetching', true
ranges: [],
selectedRangeIndex: -1,
tab: 'scan',
from: '',
to: ''
}
},
methods: {
scan: function() {
this.scanned = 'fetching';
this.selectedRangeIndex = -1;
post('scan', this.config, (err, response) => {
this.scanned = true;
this.ranges = response;
this.selectedRangeIndex = 0;
});
},
printRange: function(range) {
let fmt = mom => mom.format('YYYY-MM-DD HH:mm')
let from = moment.unix(range.from);
let to = moment.unix(range.to);
let diff = moment.duration(to.diff(from)).humanize();
return `${fmt(from)} to ${fmt(to)} (${diff})`;
},
fmtTs: (mom) => moment.unix(mom).utc(),
fmt: (mom) => mom.utc().format(),
emitRange: function(range) {
this.$emit('range', {
from: this.fmtTs(range.from),
to: this.fmtTs(range.to)
});
},
emitManualEntry: function() {
if(this.from.length < '4' || this.from.length < '4')
// this cannot possibly be a valid date
return this.$emit('range', {})
let from = moment.utc(this.from);
let to = moment.utc(this.to);
if(from.isValid() && to.isValid()) {
this.$emit('range', {
from: this.fmt(from),
to: this.fmt(to)
})
} else {
this.$emit('range', {});
}
},
reset: function() {
this.scanned = false;
this.$emit('range', {})
}
},
watch: {
from: function() {
this.emitManualEntry();
},
to: function() {
this.emitManualEntry();
},
config: function() {
this.reset();
},
tab: function() {
this.reset();
},
selectedRangeIndex: function() {
let selectedRange = this.ranges[this.selectedRangeIndex];
if(selectedRange)
this.emitRange(selectedRange);
}
}
}
</script>
<style>
.scan-btn {
margin-top: 80px;
margin-bottom: 30px;
}
.radio label {
margin-top: 0;
}
</style>
@@ -0,0 +1,145 @@
<template lang='pug'>
.grd
.grd-row
.grd-row-col-3-6.px1
h3 Strategy
div
label(for='strat').wrapper Strategy:
.custom-select.button
select(v-model='strategy')
option(v-for='strat in strategies') {{ strat.name }}
div
label(for='candleSize') Candle Size
.grd-row
.grd-row-col-3-6
input(v-model='rawCandleSize')
.grd-row-col-3-6.align
.custom-select.button
select(v-model='candleSizeUnit')
option minutes
option hours
option days
div
label(for='historySize') Warmup period (in {{ rawCandleSize }} {{ singularCandleSizeUnit }} candles):
input(v-model='historySize')
em.label-like (will use {{ humanizeDuration(candleSize * historySize * 1000 * 60) }} of data as history)
.grd-row-col-3-6.px1
div
h3 Parameters
p {{ strategy }} Parameters:
textarea.params(v-model='rawStratParams')
p.bg--red.p1(v-if='rawStratParamsError') {{ rawStratParamsError.message }}
</template>
<script>
import _ from 'lodash'
import { get } from '../../../tools/ajax'
export default {
data: () => {
return {
strategies: [],
candleSizeUnit: 'hours',
rawCandleSize: 1,
strategy: 'MACD',
historySize: 10,
rawStratParams: '',
rawStratParamsError: false,
emptyStrat: false,
stratParams: {}
};
},
created: function () {
get('strategies', (err, data) => {
this.strategies = data;
_.each(this.strategies, function(s) {
s.empty = s.params === '';
});
this.rawStratParams = _.find(this.strategies, { name: this.strategy }).params;
this.emptyStrat = _.find(this.strategies, { name: this.strategy }).empty;
this.emitConfig();
});
},
watch: {
strategy: function(strat) {
strat = _.find(this.strategies, { name: strat });
this.rawStratParams = strat.params;
this.emptyStrat = strat.empty;
this.emitConfig();
},
candleSize: function() { this.emitConfig() },
historySize: function() { this.emitConfig() },
rawStratParams: function() { this.emitConfig() }
},
computed: {
candleSize: function() {
if(this.candleSizeUnit === 'minutes')
return this.rawCandleSize;
else if(this.candleSizeUnit === 'hours')
return this.rawCandleSize * 60;
else if(this.candleSizeUnit === 'days')
return this.rawCandleSize * 60 * 24;
},
singularCandleSizeUnit: function() {
// hours -> hour
return this.candleSizeUnit.slice(0, -1);
},
config: function() {
let config = {
tradingAdvisor: {
enabled: true,
method: this.strategy,
candleSize: +this.candleSize,
historySize: +this.historySize
}
}
if(this.emptyStrat)
config[this.strategy] = {__empty: true}
else
config[this.strategy] = this.stratParams;
return config;
}
},
methods: {
humanizeDuration: (n) => window.humanizeDuration(n),
emitConfig: function() {
this.parseParams();
this.$emit('stratConfig', this.config);
},
parseParams: function() {
try {
this.stratParams = toml.parse(this.rawStratParams);
this.rawStratParamsError = false;
} catch(e) {
this.rawStratParamsError = e;
this.stratParams = {};
}
}
}
}
</script>
<style>
.align .custom-select select {
padding: 0.4em 1.2em .3em .8em;
}
.label-like {
display: block;
font-size: 0.9em;
color: #777;
}
.align {
padding-left: 1em;
}
</style>
@@ -0,0 +1,48 @@
<template lang='pug'>
div
h3 Type
template
label(for='type').wrapper What do you want to do with gekko?
form.radio.grd
div.grd-row(v-for='(type, i) in types').m1
input.grd-row-col-1-6(type='radio', :value='i', v-model='selectedTypeIndex')
label.grd-row-col-5-6(:for='i') {{ type }}
</template>
<script>
export default {
created: function() {
this.emitType();
},
data: () => {
return {
types: ['paper trader', 'market watcher', 'tradebot'],
selectedTypeIndex: 0,
}
},
methods: {
emitType: function() {
this.$emit('type', this.type);
}
},
watch: {
type: function() {
this.emitType();
}
},
computed: {
type: function() {
return this.types[ this.selectedTypeIndex ];
}
}
}
</script>
<style>
.radio label {
margin-top: 0;
}
</style>
@@ -0,0 +1,60 @@
import { post } from '../../../tools/ajax'
var mixin = {
data: () => {
return {
datasets: [],
datasetScanstate: 'idle',
unscannableMakets: []
}
},
methods: {
scan: function() {
this.datasetScanstate = 'scanning';
post('scansets', {}, (error, response) => {
this.datasetScanstate = 'scanned';
this.unscannableMakets = response.errors;
let sets = [];
response.datasets.forEach(market => {
market.ranges.forEach((range, i) => {
sets.push({
exchange: market.exchange,
currency: market.currency,
asset: market.asset,
from: moment.unix(range.from).utc(),
to: moment.unix(range.to).utc(),
id: market.exchange + market.asset + market.currency + i
});
});
});
// for now, filter out sets smaller than 3 hours..
sets = sets.filter(set => {
if(set.to.diff(set.from, 'hours') > 2)
return true;
});
sets = sets.sort((a, b) => {
let adiff = a.to.diff(a.from);
let bdiff = b.to.diff(b.from);
if(adiff < bdiff)
return -1;
if(adiff > bdiff)
return 1;
return 0;
}).reverse();
this.datasets = sets;
})
}
}
}
export default mixin;
@@ -0,0 +1,64 @@
<template lang='pug'>
.grd-row-col-3-6
table.p1
tr
th amount of trades
td {{ report.trades }}
tr
th sharpe ratio
td {{ round2(report.sharpe) }}
tr
th start balance
td {{ round(report.startBalance) }} {{ report.currency }}
tr
th final balance
td {{ round(report.balance) }} {{ report.currency }}
tr
th simulated profit
.big.txt--right.price(:class='profitClass') {{ round(report.relativeProfit) }}%
</template>
<script>
export default {
props: ['report'],
methods: {
round2: n => (+n).toFixed(2),
round: n => (+n).toFixed(5)
},
computed: {
profitClass: function() {
if(this.report.relativeProfit > 0)
return 'profit'
else
return 'loss'
}
}
}
</script>
<style>
.summary td {
text-align: right;
}
.big {
font-size: 1.3em;
width: 80%;
}
.summary table {
width: 80%;
}
.price.profit {
color: #7FFF00;
}
.price.loss {
color: red;
}
</style>
@@ -0,0 +1,57 @@
// http://stackoverflow.com/questions/7190898/progress-bar-with-html-and-css
<template lang='pug'>
.progressbarWrapper(v-if='progress')
p <strong>{{ round(progress) }}%</strong>
.progressbar
div(:style='{width: progress + "%"}')
</template>
<script>
export default {
props: ['progress'],
methods: {
round: n => (+n).toFixed(2)
}
}
</script>
<style>
.progressbarWrapper p {
text-align: center;
font-size: 20px;
}
.progressbar {
background-color: rgba(216,216,216,.99);
border-radius: 13px; /* (height of inner div) / 2 + padding */
padding: 0px;
}
@keyframes shimmer{
0%{
background-position: 0px 0
}
100%{
background-position: 960px 0
}
}
.progressbar > div {
height: 20px;
border-radius: 10px;
/* Progress bar animation */
background-color: #FFA500;
animation-duration: 1500ms;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: shimmer;
animation-timing-function: linear;
background: #f6f7f8;
background: linear-gradient(to right, #FFA500 10%, #ffce77 25%, #FFA500 40%);
background-size: 960px 50px;
background-position: left;
position: relative;
}
</style>
+60
View File
@@ -0,0 +1,60 @@
import _ from 'lodash'
import Vue from 'vue'
import { wsPath } from '../../tools/api'
import initializeState from '../../store/init'
var socket = null;
export const bus = new Vue();
bus.$on('gekko_update', data => console.log(data))
bus.$on('import_update', data => console.log(data))
bus.$on('import_error', data => {
alert('IMPORT ERROR: ' + data.error);
});
const info = {
connected: false
}
export const connect = () => {
socket = new ReconnectingWebSocket(wsPath, null, { maxReconnectInterval: 4000 });
setTimeout(() => {
// in case we cannot connect
if(!info.connected) {
initializeState();
bus.$emit('WS_STATUS_CHANGE', info);
}
}, 500);
socket.onopen = () => {
if(info.connected)
return;
info.connected = true;
bus.$emit('WS_STATUS_CHANGE', info);
initializeState();
}
socket.onclose = () => {
if(!info.connected)
return;
info.connected = false;
bus.$emit('WS_STATUS_CHANGE', info);
}
socket.onerror = () => {
if(!info.connected)
return;
info.connected = false;
bus.$emit('WS_STATUS_CHANGE', info);
}
socket.onmessage = function(message) {
const payload = JSON.parse(message.data);
// console.log('ws message:', payload);
bus.$emit(payload.type, payload);
};
}
+23
View File
@@ -0,0 +1,23 @@
<template lang='pug'>
footer.p2.bg--off-white
.contain
p
em Use Gekko at your own risk.
p Using Gekko v{{ version.gekko }} and Gekko UI v{{ version.ui }}.
</template>
<script>
const gekkoPackage = require('../../../../../package.json');
const uiPackage = require('../../../package.json');
export default {
data: () => {
return {
version: {
gekko: gekkoPackage.version,
ui: uiPackage.version
}
}
}
}
</script>
+46
View File
@@ -0,0 +1,46 @@
<template lang='pug'>
div
#top
header.bg--off-white.grd
.contain.grd-row
h3.py1.px2.col-2 Gekko UI
nav.bg--light-gray
.menu.contain
router-link(to='/home').py1 Home
router-link(to='/live-gekkos').py1 Live Gekkos
router-link(to='/backtest').py1 Backtest
router-link(to='/data').py1 Local data
router-link(to='/config').py1 Config
a(href='https://gekko.wizb.it/docs/introduction/about_gekko.html', target='_blank').py1 Documentation
</template>
<script>
export default {}
</script>
<style>
.menu {
display: flex;
flex-direction: row;
margin-top: 0;
margin-bottom: 2rem;
}
.menu a {
flex: 1 1 100%;
display: block;
text-align: center;
text-decoration: none;
color: inherit;
}
.menu .router-link-active {
background-color: rgba(250,250,250,.99);
}
.menu a:hover {
text-decoration: underline;
}
</style>
+34
View File
@@ -0,0 +1,34 @@
<template lang='pug'>
section.contain.grd-row
.grd-row-col-3-6(v-html='left')
.grd-row-col-3-6.txt--center
img(src='static/gekko.jpg')
p
em The most valuable commodity I know of is information.
</template>
<script>
import marked from '../../tools/marked';
const left = marked(`
## Gekko
Gekko is a Bitcoin trading bot and backtesting platform that
connects to popular Bitcoin exchanges. It is written in javascript
and runs on nodejs.
[Find out more](https://gekko.wizb.it/).
*Gekko is 100% free (open source), if you paid for this you have been scammed.*
`);
export default {
data: () => {
return {
left
}
}
}
</script>
+80
View File
@@ -0,0 +1,80 @@
<template lang='pug'>
div(v-if='active')
#modal-background
#modal.modal
.modal-guts(v-html='content')
</template>
<script>
import marked from '../../tools/marked';
const messages = {
disconnected: marked(`
## Disconnected
Something happened to either Gekko or the connection.
Please check the terminal where Gekko is running or
your network connection.
*This message is shown when the UI is unable to open a websocket connection with the Gekko Server.*
`)
}
export default {
computed: {
active: function() {
return !this.$store.state.warnings.connected;
},
content: function() {
if(!this.$store.state.warnings.connected)
return messages.disconnected;
return '';
}
}
}
</script>
<style>
#modal-background {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: black;
opacity: 0.5
}
.modal {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 600px;
min-height: 300px;
background-color: white;
}
.modal-guts {
/* other stuff we already covered */
/* cover the modal */
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
/* spacing as needed */
padding: 20px 50px 20px 20px;
/* let it scroll */
overflow: auto;
}
</style>
+149
View File
@@ -0,0 +1,149 @@
import _ from 'lodash'
// techanjs based cancle chart, unused at the moment
export default function(_data, _trades) {
let MAX_WIDTH = window.innerWidth - 20;
var margin = {top: 20, right: 20, bottom: 30, left: 50},
width = MAX_WIDTH - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = techan.scale.financetime()
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
var zoom = d3.zoom()
.on("zoom", zoomed);
var zoomableInit;
var candlestick = techan.plot.candlestick()
.xScale(x)
.yScale(y);
var tradearrow = techan.plot.tradearrow()
.xScale(x)
.yScale(y)
.orient(function(d) { return d.type.startsWith("buy") ? "up" : "down"; })
.on("mouseenter", enter)
.on("mouseout", out);
var xAxis = d3.axisBottom(x);
var yAxis = d3.axisLeft(y);
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("x", 0)
.attr("y", y(1))
.attr("width", width)
.attr("height", y(0) - y(1));
svg.append("g")
.attr("class", "candlestick")
.attr("clip-path", "url(#clip)");
svg.append("g")
.attr("class", "tradearrow")
.attr("clip-path", "url(#clip)");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")");
svg.append("g")
.attr("class", "y axis")
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Price ($)");
svg.append("rect")
.attr("class", "pane")
.attr("width", width)
.attr("height", height)
.call(zoom);
var accessor = candlestick.accessor();
const data = _data.map(function(d) {
return {
date: new Date(d.start),
open: +d.open,
high: +d.high,
low: +d.low,
close: +d.close,
volume: +d.volume
};
}).sort(function(a, b) { return d3.ascending(accessor.d(a), accessor.d(b)); });
const trades = _trades.map(function(t) {
let trade = _.pick(t, ['price']);
trade.quantity = 1;
trade.type = t.action;
trade.date = new Date(t.date);
return trade;
});
console.log(trades);
x.domain(data.map(accessor.d));
y.domain(techan.scale.plot.ohlc(data, accessor).domain());
svg.select("g.tradearrow").datum(trades);
svg.select("g.candlestick").datum(data);
draw();
// Associate the zoom with the scale after a domain has been applied
// Stash initial settings to store as baseline for zooming
zoomableInit = x.zoomable().clamp(false).copy();
function zoomed() {
var rescaledY = d3.event.transform.rescaleY(y);
yAxis.scale(rescaledY);
candlestick.yScale(rescaledY);
tradearrow.yScale(rescaledY);
// Emulates D3 behaviour, required for financetime due to secondary zoomable scale
x.zoomable().domain(d3.event.transform.rescaleX(zoomableInit).domain());
draw();
}
function draw() {
svg.select("g.tradearrow").call(tradearrow);
svg.select("g.candlestick").call(candlestick);
// using refresh method is more efficient as it does not perform any data joins
// Use this if underlying data is not changing
// svg.select("g.candlestick").call(candlestick.refresh);
svg.select("g.x.axis").call(xAxis);
svg.select("g.y.axis").call(yAxis)
}
function enter(d) {
valueText.style("display", "inline");
refreshText(d);
}
function out() {
valueText.style("display", "none");
}
function refreshText(d) {
valueText.text("Trade: " + dateFormat(d.date) + ", " + d.type + ", " + valueFormat(d.price));
}
};
+204
View File
@@ -0,0 +1,204 @@
import _ from 'lodash';
// global moment
export default function(_data, _trades, _height) {
const toDate = i => {
if(_.isNumber(i)) {
return moment.unix(i).utc().toDate();
} else {
return moment.utc(i).toDate();
}
}
const trades = _trades.map(t => {
return {
price: t.price,
date: toDate(t.date),
action: t.action
}
});
const data = _data.map(c => {
return {
price: c.open,
date: toDate(c.start)
}
});
var dates = data.map(c => +c.date);
var prices = data.map(c => +c.price)
var svg = d3.select("#chart");
svg.attr("width", window.innerWidth - 20);
var margin = {top: 20, right: 20, bottom: 110, left: 40};
var height = _height - margin.top - margin.bottom;
var margin2 = {top: _height - 70, right: 20, bottom: 30, left: 40};
var width = +svg.attr("width") - margin.left - margin.right;
var height2 = _height - margin2.top - margin2.bottom;
var x = d3.scaleUtc().range([0, width]),
x2 = d3.scaleUtc().range([0, width]),
y = d3.scaleLinear().range([height, 0]),
y2 = d3.scaleLinear().range([height2, 0]);
var xAxis = d3.axisBottom(x),
xAxis2 = d3.axisBottom(x2),
yAxis = d3.axisLeft(y).ticks(_height / 50);
var brush = d3.brushX()
.extent([[0, 0], [width, height2]])
.on("brush end", brushed);
var zoom = d3.zoom()
.scaleExtent([1, 100])
.translateExtent([[0, 0], [width, height]])
.extent([[0, 0], [width, height]])
.on("zoom", zoomed);
var line = d3.line()
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.price); });
var line2 = d3.line()
.x(function(d) { return x2(d.date); })
.y(function(d) { return y2(d.price); });
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var context = svg.append("g")
.attr("class", "context")
.attr("transform", "translate(" + margin2.left + "," + margin2.top + ")");
x.domain(d3.extent(data, function(d) { return d.date; }));
y.domain([
d3.min(prices) * 0.99,
d3.max(prices) * 1.01
]);
x2.domain(x.domain());
y2.domain(y.domain());
focus.append("path")
.datum(data)
.attr("class", "line price")
.attr("d", line);
focus.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
focus.append("g")
.attr("class", "axis axis--y")
.call(yAxis);
context.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line2);
context.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height2 + ")")
.call(xAxis2);
var circles = svg
.append('g')
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.selectAll("circle")
.data(trades)
.enter().append("circle")
.attr('class', function(d) { return d.action })
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.price); })
.attr('r', 5);
var brushCircles = context
.append('g')
// .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.selectAll("circle")
.data(trades)
.enter().append("circle")
.attr('class', function(d) { return d.action })
.attr("cx", function(d) { return x2(d.date); })
.attr("cy", function(d) { return y2(d.price); })
.attr('r', 3);
context.append("g")
.attr("class", "brush")
.call(brush)
.call(brush.move, x.range());
svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
function brushed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
var s = d3.event.selection || x2.range();
x.domain(s.map(x2.invert, x2));
scaleY(x.domain());
svg.select(".axis--y")
.call(yAxis);
circles
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.price); })
focus.select(".line").attr("d", line);
focus.select(".axis--x").call(xAxis);
svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
.scale(width / (s[1] - s[0]))
.translate(-s[0], 0));
}
function scaleY(domain) {
let [min, max] = domain;
let minIndex = _.sortedIndex(dates, min);
let maxIndex = _.sortedIndex(dates, max);
let set = prices.slice(minIndex, maxIndex);
y.domain([
d3.min(set) * 0.9995,
d3.max(set) * 1.0005
]);
}
function zoomed() {
if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
var t = d3.event.transform;
scaleY(t.rescaleX(x2).domain());
svg.select(".axis--y")
.call(yAxis);
x.domain(t.rescaleX(x2).domain());
focus.select(".line").attr("d", line);
circles
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.price); })
focus.select(".axis--x").call(xAxis);
context.select(".brush").call(brush.move, x.range().map(t.invertX, t));
}
}
+11
View File
@@ -0,0 +1,11 @@
export const draw = function(message) {
d3.select("#chart").append("text")
.attr('class', 'message')
.attr('x', 150)
.attr('y', 150)
.text(message);
}
export const clear = function() {
d3.select("#chart").find('text').remove();
}
+47
View File
@@ -0,0 +1,47 @@
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter);
import store from './store'
import backtester from './components/backtester/backtester.vue'
import home from './components/layout/home.vue'
import data from './components/data/data.vue'
import importer from './components/data/import/importer.vue'
import singleImport from './components/data/import/single.vue'
import config from './components/config/config.vue'
import gekkoList from './components/gekko/list.vue'
import newGekko from './components/gekko/new.vue'
import singleGekko from './components/gekko/singleGekko.vue'
import { connect as connectWS } from './components/global/ws'
const router = new VueRouter({
mode: 'hash',
base: __dirname,
routes: [
{ path: '/', redirect: '/home' },
{ path: '/home', component: home },
{ path: '/backtest', component: backtester },
{ path: '/config', component: config },
{ path: '/data', component: data },
{ path: '/data/importer', component: importer },
{ path: '/data/importer/import/:id', component: singleImport },
{ path: '/live-gekkos', component: gekkoList },
{ path: '/live-gekkos/new', component: newGekko },
{ path: '/live-gekkos/:id', component: singleGekko },
]
});
// setup some stuff
connectWS();
new Vue({
router,
store,
el: '#app',
render: h => h(App)
})
+38
View File
@@ -0,0 +1,38 @@
import Vue from 'vue'
import Vuex from 'vuex'
import _ from 'lodash'
import * as importMutations from './modules/imports/mutations'
import * as gekkoMutations from './modules/gekkos/mutations'
import * as notificationMutations from './modules/notifications/mutations'
import * as configMutations from './modules/config/mutations'
Vue.use(Vuex);
const debug = process.env.NODE_ENV !== 'production'
let mutations = {};
_.merge(mutations, importMutations);
_.merge(mutations, gekkoMutations);
_.merge(mutations, notificationMutations);
_.merge(mutations, configMutations);
export default new Vuex.Store({
state: {
warnings: {
connected: true, // assume we will connect
},
imports: [],
gekkos: {},
archivedGekkos: {},
connection: {
disconnected: false,
reconnected: false
},
apiKeys: [],
exchanges: {}
},
mutations,
strict: debug
})
+14
View File
@@ -0,0 +1,14 @@
import Vue from 'vue'
import Vuex from 'vuex'
import syncImports from './modules/imports/sync'
import syncGekkos from './modules/gekkos/sync'
import syncNotifications from './modules/notifications/sync'
import syncConfig from './modules/config/sync'
export default function() {
syncImports();
syncGekkos();
syncNotifications();
syncConfig();
}
@@ -0,0 +1,11 @@
import Vue from 'vue'
export const syncApiKeys = (state, apiKeys) => {
Vue.set(state, 'apiKeys', apiKeys);
return state;
}
export const syncExchanges = (state, exchanges) => {
Vue.set(state, 'exchanges', exchanges);
return state;
}
+54
View File
@@ -0,0 +1,54 @@
import { get } from '../../../tools/ajax'
import store from '../../'
import { bus } from '../../../components/global/ws'
const transformMarkets = backendData => {
if(!backendData) {
return {};
}
var exchangesRaw = backendData;
var exchangesTemp = {};
exchangesRaw.forEach(e => {
exchangesTemp[e.slug] = exchangesTemp[e.slug] || {markets: {}};
e.markets.forEach( pair => {
let [ currency, asset ] = pair['pair'];
exchangesTemp[e.slug].markets[currency] = exchangesTemp[e.slug].markets[currency] || [];
exchangesTemp[e.slug].markets[currency].push( asset );
});
if ("exchangeMaxHistoryAge" in e) {
exchangesTemp[e.slug].exchangeMaxHistoryAge = e.exchangeMaxHistoryAge;
}
exchangesTemp[e.slug].importable = e.providesFullHistory ? true : false;
exchangesTemp[e.slug].tradable = e.tradable ? true : false;
exchangesTemp[e.slug].requires = e.requires;
});
return exchangesTemp;
}
const init = () => {
get('apiKeys', (err, resp) => {
store.commit('syncApiKeys', resp);
});
get('exchanges', (err, resp) => {
store.commit('syncExchanges', transformMarkets(resp));
})
}
const sync = () => {
bus.$on('apiKeys', data => {
store.commit('syncApiKeys', data.exchanges);
});
}
export default function() {
init();
sync();
}
@@ -0,0 +1,77 @@
import Vue from 'vue'
import _ from 'lodash';
const reduceState = require('../../../../../state/reduceState');
export const syncGekkos = (state, data) => {
if(!data) {
return state;
}
state.gekkos = data.live;
state.archivedGekkos = data.archive;
return state;
}
export const addGekko = (state, gekko) => {
state.gekkos = {
...state.gekkos,
[gekko.id]: gekko
}
return state;
}
export const updateGekko = (state, update) => {
if(!update.id || !_.has(state.gekkos, update.id)) {
return console.error('cannot update unknown gekko..');;
}
state.gekkos = {
...state.gekkos,
[update.id]: reduceState(state.gekkos[update.id], update.event)
}
return state;
}
export const archiveGekko = (state, id) => {
if(!_.has(state.gekkos, id)) {
return console.error('cannot archive unknown gekko..');
}
state.archivedGekkos = {
...state.archivedGekkos,
[id]: {
...state.gekkos[id],
stopped: true,
active: false
}
}
state.gekkos = _.omit(state.gekkos, id);
return state;
}
export const errorGekko = (state, data) => {
if(!_.has(state.gekkos, data.id)) {
return console.error('cannot error unknown gekko..');
}
state.gekkos = {
...state.gekkos,
[data.id]: {
...state.gekkos[data.id],
errored: true,
errorMessage: data.error
}
}
return state;
}
export const deleteGekko = (state, id) => {
if(!_.has(state.archivedGekkos, id)) {
return console.error('cannot delete unknown gekko..');
}
state.archivedGekkos = _.omit(state.archivedGekkos, id);
return state;
}
+28
View File
@@ -0,0 +1,28 @@
import { get } from '../../../tools/ajax'
import store from '../../'
import { bus } from '../../../components/global/ws'
import _ from 'lodash'
const init = () => {
get('gekkos', (err, resp) => {
const gekkos = resp;
store.commit('syncGekkos', gekkos);
});
}
const sync = () => {
bus.$on('gekko_new', data => store.commit('addGekko', data.state));
bus.$on('gekko_event', data => store.commit('updateGekko', data));
bus.$on('gekko_archived', data => store.commit('archiveGekko', data.id));
bus.$on('gekko_error', data => store.commit('errorGekko', data));
bus.$on('gekko_deleted', data => store.commit('deleteGekko', data.id));
// unused:
// bus.$on('gekko_stopped', data => store.commit('x', data.id));
// bus.$on('gekko_deleted', data => store.commit('x', data.id));
}
export default function() {
init();
sync();
}
@@ -0,0 +1,23 @@
import Vue from 'vue'
export const addImport = (state, imp) => {
state.imports.push(imp);
return state;
}
export const syncImports = (state, imports) => {
state.imports = imports;
return state;
}
export const updateImport = (state, update) => {
let index = state.imports.findIndex(i => i.id === update.import_id);
let item = state.imports[index];
if(!item)
return state;
let updated = Vue.util.extend(item, update.updates);
Vue.set(state.imports, index, updated);
return state;
}
+20
View File
@@ -0,0 +1,20 @@
import { get } from '../../../tools/ajax'
import store from '../../'
import { bus } from '../../../components/global/ws'
const init = () => {
get('imports', (err, resp) => {
store.commit('syncImports', resp);
});
}
const sync = () => {
bus.$on('import_update', data => {
store.commit('updateImport', data);
});
}
export default function() {
init();
sync();
}
Whitespace-only changes.
Loaded 100 of 386 files, more files were not shown because too many files have changed in this diff. Show more