commit e5deb10808ce4f11e1d25eba10fdfd06eb8b415a
parent 0e22ff2d1919f92710845813cdaa3e50213c5fd6
Author: Chris Bracken <chris@bracken.jp>
Date: Fri, 12 Nov 2021 17:41:23 -0800
Add HTML dashboard endpoint
Adds an HTML dashboard at /dashboard that serves up plots of
temperature, humidity, and pressure. Uses chart.js to plot the data.
Diffstat:
9 files changed, 18996 insertions(+), 0 deletions(-)
diff --git a/http/http.go b/http/http.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"net/http"
+ "path/filepath"
"time"
"git.bracken.jp/tempestas/airrohr"
@@ -12,6 +13,10 @@ import (
"goji.io/pat"
)
+const (
+ staticResourceDir = "static"
+)
+
type HttpServer struct {
ds storage.DataStore
}
@@ -27,6 +32,10 @@ func (s HttpServer) ListenAndServe(addr string) error {
mux.HandleFunc(pat.Post("/sensor/airrohr/"), s.PostAirrohr)
mux.HandleFunc(pat.Get("/sensor/reading/:sensorId/:readingType"), s.QueryReadings)
mux.HandleFunc(pat.Get("/sensor/sensors/"), s.QuerySensors)
+ mux.HandleFunc(pat.Get("/dashboard/"), s.PresentDashboard)
+
+ fs := http.FileServer(http.Dir(staticResourceDir))
+ mux.Handle(pat.Get("/static/*"), http.StripPrefix("/static", fs))
return http.ListenAndServe(addr, mux)
}
@@ -84,6 +93,10 @@ func (s HttpServer) QuerySensors(w http.ResponseWriter, r *http.Request) {
writeResponse(w, resp, http.StatusOK)
}
+func (s HttpServer) PresentDashboard(w http.ResponseWriter, r *http.Request) {
+ http.ServeFile(w, r, filepath.Join(staticResourceDir, "dashboard.html"))
+}
+
func errorResponse(w http.ResponseWriter, message string, httpStatusCode int) {
resp := make(map[string]string)
resp["message"] = message
@@ -92,6 +105,7 @@ func errorResponse(w http.ResponseWriter, message string, httpStatusCode int) {
}
func writeResponse(w http.ResponseWriter, resp []byte, httpStatusCode int) {
+ w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(httpStatusCode)
w.Write(resp)
diff --git a/static/chart.js b/static/chart.js
@@ -0,0 +1,13097 @@
+/*!
+ * Chart.js v3.6.0
+ * https://www.chartjs.org
+ * (c) 2021 Chart.js Contributors
+ * Released under the MIT License
+ */
+(function (global, factory) {
+typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+typeof define === 'function' && define.amd ? define(factory) :
+(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Chart = factory());
+}(this, (function () { 'use strict';
+
+function fontString(pixelSize, fontStyle, fontFamily) {
+ return fontStyle + ' ' + pixelSize + 'px ' + fontFamily;
+}
+const requestAnimFrame = (function() {
+ if (typeof window === 'undefined') {
+ return function(callback) {
+ return callback();
+ };
+ }
+ return window.requestAnimationFrame;
+}());
+function throttled(fn, thisArg, updateFn) {
+ const updateArgs = updateFn || ((args) => Array.prototype.slice.call(args));
+ let ticking = false;
+ let args = [];
+ return function(...rest) {
+ args = updateArgs(rest);
+ if (!ticking) {
+ ticking = true;
+ requestAnimFrame.call(window, () => {
+ ticking = false;
+ fn.apply(thisArg, args);
+ });
+ }
+ };
+}
+function debounce(fn, delay) {
+ let timeout;
+ return function(...args) {
+ if (delay) {
+ clearTimeout(timeout);
+ timeout = setTimeout(fn, delay, args);
+ } else {
+ fn.apply(this, args);
+ }
+ return delay;
+ };
+}
+const _toLeftRightCenter = (align) => align === 'start' ? 'left' : align === 'end' ? 'right' : 'center';
+const _alignStartEnd = (align, start, end) => align === 'start' ? start : align === 'end' ? end : (start + end) / 2;
+const _textX = (align, left, right, rtl) => {
+ const check = rtl ? 'left' : 'right';
+ return align === check ? right : align === 'center' ? (left + right) / 2 : left;
+};
+
+class Animator {
+ constructor() {
+ this._request = null;
+ this._charts = new Map();
+ this._running = false;
+ this._lastDate = undefined;
+ }
+ _notify(chart, anims, date, type) {
+ const callbacks = anims.listeners[type];
+ const numSteps = anims.duration;
+ callbacks.forEach(fn => fn({
+ chart,
+ initial: anims.initial,
+ numSteps,
+ currentStep: Math.min(date - anims.start, numSteps)
+ }));
+ }
+ _refresh() {
+ if (this._request) {
+ return;
+ }
+ this._running = true;
+ this._request = requestAnimFrame.call(window, () => {
+ this._update();
+ this._request = null;
+ if (this._running) {
+ this._refresh();
+ }
+ });
+ }
+ _update(date = Date.now()) {
+ let remaining = 0;
+ this._charts.forEach((anims, chart) => {
+ if (!anims.running || !anims.items.length) {
+ return;
+ }
+ const items = anims.items;
+ let i = items.length - 1;
+ let draw = false;
+ let item;
+ for (; i >= 0; --i) {
+ item = items[i];
+ if (item._active) {
+ if (item._total > anims.duration) {
+ anims.duration = item._total;
+ }
+ item.tick(date);
+ draw = true;
+ } else {
+ items[i] = items[items.length - 1];
+ items.pop();
+ }
+ }
+ if (draw) {
+ chart.draw();
+ this._notify(chart, anims, date, 'progress');
+ }
+ if (!items.length) {
+ anims.running = false;
+ this._notify(chart, anims, date, 'complete');
+ anims.initial = false;
+ }
+ remaining += items.length;
+ });
+ this._lastDate = date;
+ if (remaining === 0) {
+ this._running = false;
+ }
+ }
+ _getAnims(chart) {
+ const charts = this._charts;
+ let anims = charts.get(chart);
+ if (!anims) {
+ anims = {
+ running: false,
+ initial: true,
+ items: [],
+ listeners: {
+ complete: [],
+ progress: []
+ }
+ };
+ charts.set(chart, anims);
+ }
+ return anims;
+ }
+ listen(chart, event, cb) {
+ this._getAnims(chart).listeners[event].push(cb);
+ }
+ add(chart, items) {
+ if (!items || !items.length) {
+ return;
+ }
+ this._getAnims(chart).items.push(...items);
+ }
+ has(chart) {
+ return this._getAnims(chart).items.length > 0;
+ }
+ start(chart) {
+ const anims = this._charts.get(chart);
+ if (!anims) {
+ return;
+ }
+ anims.running = true;
+ anims.start = Date.now();
+ anims.duration = anims.items.reduce((acc, cur) => Math.max(acc, cur._duration), 0);
+ this._refresh();
+ }
+ running(chart) {
+ if (!this._running) {
+ return false;
+ }
+ const anims = this._charts.get(chart);
+ if (!anims || !anims.running || !anims.items.length) {
+ return false;
+ }
+ return true;
+ }
+ stop(chart) {
+ const anims = this._charts.get(chart);
+ if (!anims || !anims.items.length) {
+ return;
+ }
+ const items = anims.items;
+ let i = items.length - 1;
+ for (; i >= 0; --i) {
+ items[i].cancel();
+ }
+ anims.items = [];
+ this._notify(chart, anims, Date.now(), 'complete');
+ }
+ remove(chart) {
+ return this._charts.delete(chart);
+ }
+}
+var animator = new Animator();
+
+/*!
+ * @kurkle/color v0.1.9
+ * https://github.com/kurkle/color#readme
+ * (c) 2020 Jukka Kurkela
+ * Released under the MIT License
+ */
+const map$1 = {0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, A: 10, B: 11, C: 12, D: 13, E: 14, F: 15, a: 10, b: 11, c: 12, d: 13, e: 14, f: 15};
+const hex = '0123456789ABCDEF';
+const h1 = (b) => hex[b & 0xF];
+const h2 = (b) => hex[(b & 0xF0) >> 4] + hex[b & 0xF];
+const eq = (b) => (((b & 0xF0) >> 4) === (b & 0xF));
+function isShort(v) {
+ return eq(v.r) && eq(v.g) && eq(v.b) && eq(v.a);
+}
+function hexParse(str) {
+ var len = str.length;
+ var ret;
+ if (str[0] === '#') {
+ if (len === 4 || len === 5) {
+ ret = {
+ r: 255 & map$1[str[1]] * 17,
+ g: 255 & map$1[str[2]] * 17,
+ b: 255 & map$1[str[3]] * 17,
+ a: len === 5 ? map$1[str[4]] * 17 : 255
+ };
+ } else if (len === 7 || len === 9) {
+ ret = {
+ r: map$1[str[1]] << 4 | map$1[str[2]],
+ g: map$1[str[3]] << 4 | map$1[str[4]],
+ b: map$1[str[5]] << 4 | map$1[str[6]],
+ a: len === 9 ? (map$1[str[7]] << 4 | map$1[str[8]]) : 255
+ };
+ }
+ }
+ return ret;
+}
+function hexString(v) {
+ var f = isShort(v) ? h1 : h2;
+ return v
+ ? '#' + f(v.r) + f(v.g) + f(v.b) + (v.a < 255 ? f(v.a) : '')
+ : v;
+}
+function round(v) {
+ return v + 0.5 | 0;
+}
+const lim = (v, l, h) => Math.max(Math.min(v, h), l);
+function p2b(v) {
+ return lim(round(v * 2.55), 0, 255);
+}
+function n2b(v) {
+ return lim(round(v * 255), 0, 255);
+}
+function b2n(v) {
+ return lim(round(v / 2.55) / 100, 0, 1);
+}
+function n2p(v) {
+ return lim(round(v * 100), 0, 100);
+}
+const RGB_RE = /^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;
+function rgbParse(str) {
+ const m = RGB_RE.exec(str);
+ let a = 255;
+ let r, g, b;
+ if (!m) {
+ return;
+ }
+ if (m[7] !== r) {
+ const v = +m[7];
+ a = 255 & (m[8] ? p2b(v) : v * 255);
+ }
+ r = +m[1];
+ g = +m[3];
+ b = +m[5];
+ r = 255 & (m[2] ? p2b(r) : r);
+ g = 255 & (m[4] ? p2b(g) : g);
+ b = 255 & (m[6] ? p2b(b) : b);
+ return {
+ r: r,
+ g: g,
+ b: b,
+ a: a
+ };
+}
+function rgbString(v) {
+ return v && (
+ v.a < 255
+ ? `rgba(${v.r}, ${v.g}, ${v.b}, ${b2n(v.a)})`
+ : `rgb(${v.r}, ${v.g}, ${v.b})`
+ );
+}
+const HUE_RE = /^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;
+function hsl2rgbn(h, s, l) {
+ const a = s * Math.min(l, 1 - l);
+ const f = (n, k = (n + h / 30) % 12) => l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
+ return [f(0), f(8), f(4)];
+}
+function hsv2rgbn(h, s, v) {
+ const f = (n, k = (n + h / 60) % 6) => v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
+ return [f(5), f(3), f(1)];
+}
+function hwb2rgbn(h, w, b) {
+ const rgb = hsl2rgbn(h, 1, 0.5);
+ let i;
+ if (w + b > 1) {
+ i = 1 / (w + b);
+ w *= i;
+ b *= i;
+ }
+ for (i = 0; i < 3; i++) {
+ rgb[i] *= 1 - w - b;
+ rgb[i] += w;
+ }
+ return rgb;
+}
+function rgb2hsl(v) {
+ const range = 255;
+ const r = v.r / range;
+ const g = v.g / range;
+ const b = v.b / range;
+ const max = Math.max(r, g, b);
+ const min = Math.min(r, g, b);
+ const l = (max + min) / 2;
+ let h, s, d;
+ if (max !== min) {
+ d = max - min;
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
+ h = max === r
+ ? ((g - b) / d) + (g < b ? 6 : 0)
+ : max === g
+ ? (b - r) / d + 2
+ : (r - g) / d + 4;
+ h = h * 60 + 0.5;
+ }
+ return [h | 0, s || 0, l];
+}
+function calln(f, a, b, c) {
+ return (
+ Array.isArray(a)
+ ? f(a[0], a[1], a[2])
+ : f(a, b, c)
+ ).map(n2b);
+}
+function hsl2rgb(h, s, l) {
+ return calln(hsl2rgbn, h, s, l);
+}
+function hwb2rgb(h, w, b) {
+ return calln(hwb2rgbn, h, w, b);
+}
+function hsv2rgb(h, s, v) {
+ return calln(hsv2rgbn, h, s, v);
+}
+function hue(h) {
+ return (h % 360 + 360) % 360;
+}
+function hueParse(str) {
+ const m = HUE_RE.exec(str);
+ let a = 255;
+ let v;
+ if (!m) {
+ return;
+ }
+ if (m[5] !== v) {
+ a = m[6] ? p2b(+m[5]) : n2b(+m[5]);
+ }
+ const h = hue(+m[2]);
+ const p1 = +m[3] / 100;
+ const p2 = +m[4] / 100;
+ if (m[1] === 'hwb') {
+ v = hwb2rgb(h, p1, p2);
+ } else if (m[1] === 'hsv') {
+ v = hsv2rgb(h, p1, p2);
+ } else {
+ v = hsl2rgb(h, p1, p2);
+ }
+ return {
+ r: v[0],
+ g: v[1],
+ b: v[2],
+ a: a
+ };
+}
+function rotate(v, deg) {
+ var h = rgb2hsl(v);
+ h[0] = hue(h[0] + deg);
+ h = hsl2rgb(h);
+ v.r = h[0];
+ v.g = h[1];
+ v.b = h[2];
+}
+function hslString(v) {
+ if (!v) {
+ return;
+ }
+ const a = rgb2hsl(v);
+ const h = a[0];
+ const s = n2p(a[1]);
+ const l = n2p(a[2]);
+ return v.a < 255
+ ? `hsla(${h}, ${s}%, ${l}%, ${b2n(v.a)})`
+ : `hsl(${h}, ${s}%, ${l}%)`;
+}
+const map$1$1 = {
+ x: 'dark',
+ Z: 'light',
+ Y: 're',
+ X: 'blu',
+ W: 'gr',
+ V: 'medium',
+ U: 'slate',
+ A: 'ee',
+ T: 'ol',
+ S: 'or',
+ B: 'ra',
+ C: 'lateg',
+ D: 'ights',
+ R: 'in',
+ Q: 'turquois',
+ E: 'hi',
+ P: 'ro',
+ O: 'al',
+ N: 'le',
+ M: 'de',
+ L: 'yello',
+ F: 'en',
+ K: 'ch',
+ G: 'arks',
+ H: 'ea',
+ I: 'ightg',
+ J: 'wh'
+};
+const names = {
+ OiceXe: 'f0f8ff',
+ antiquewEte: 'faebd7',
+ aqua: 'ffff',
+ aquamarRe: '7fffd4',
+ azuY: 'f0ffff',
+ beige: 'f5f5dc',
+ bisque: 'ffe4c4',
+ black: '0',
+ blanKedOmond: 'ffebcd',
+ Xe: 'ff',
+ XeviTet: '8a2be2',
+ bPwn: 'a52a2a',
+ burlywood: 'deb887',
+ caMtXe: '5f9ea0',
+ KartYuse: '7fff00',
+ KocTate: 'd2691e',
+ cSO: 'ff7f50',
+ cSnflowerXe: '6495ed',
+ cSnsilk: 'fff8dc',
+ crimson: 'dc143c',
+ cyan: 'ffff',
+ xXe: '8b',
+ xcyan: '8b8b',
+ xgTMnPd: 'b8860b',
+ xWay: 'a9a9a9',
+ xgYF: '6400',
+ xgYy: 'a9a9a9',
+ xkhaki: 'bdb76b',
+ xmagFta: '8b008b',
+ xTivegYF: '556b2f',
+ xSange: 'ff8c00',
+ xScEd: '9932cc',
+ xYd: '8b0000',
+ xsOmon: 'e9967a',
+ xsHgYF: '8fbc8f',
+ xUXe: '483d8b',
+ xUWay: '2f4f4f',
+ xUgYy: '2f4f4f',
+ xQe: 'ced1',
+ xviTet: '9400d3',
+ dAppRk: 'ff1493',
+ dApskyXe: 'bfff',
+ dimWay: '696969',
+ dimgYy: '696969',
+ dodgerXe: '1e90ff',
+ fiYbrick: 'b22222',
+ flSOwEte: 'fffaf0',
+ foYstWAn: '228b22',
+ fuKsia: 'ff00ff',
+ gaRsbSo: 'dcdcdc',
+ ghostwEte: 'f8f8ff',
+ gTd: 'ffd700',
+ gTMnPd: 'daa520',
+ Way: '808080',
+ gYF: '8000',
+ gYFLw: 'adff2f',
+ gYy: '808080',
+ honeyMw: 'f0fff0',
+ hotpRk: 'ff69b4',
+ RdianYd: 'cd5c5c',
+ Rdigo: '4b0082',
+ ivSy: 'fffff0',
+ khaki: 'f0e68c',
+ lavFMr: 'e6e6fa',
+ lavFMrXsh: 'fff0f5',
+ lawngYF: '7cfc00',
+ NmoncEffon: 'fffacd',
+ ZXe: 'add8e6',
+ ZcSO: 'f08080',
+ Zcyan: 'e0ffff',
+ ZgTMnPdLw: 'fafad2',
+ ZWay: 'd3d3d3',
+ ZgYF: '90ee90',
+ ZgYy: 'd3d3d3',
+ ZpRk: 'ffb6c1',
+ ZsOmon: 'ffa07a',
+ ZsHgYF: '20b2aa',
+ ZskyXe: '87cefa',
+ ZUWay: '778899',
+ ZUgYy: '778899',
+ ZstAlXe: 'b0c4de',
+ ZLw: 'ffffe0',
+ lime: 'ff00',
+ limegYF: '32cd32',
+ lRF: 'faf0e6',
+ magFta: 'ff00ff',
+ maPon: '800000',
+ VaquamarRe: '66cdaa',
+ VXe: 'cd',
+ VScEd: 'ba55d3',
+ VpurpN: '9370db',
+ VsHgYF: '3cb371',
+ VUXe: '7b68ee',
+ VsprRggYF: 'fa9a',
+ VQe: '48d1cc',
+ VviTetYd: 'c71585',
+ midnightXe: '191970',
+ mRtcYam: 'f5fffa',
+ mistyPse: 'ffe4e1',
+ moccasR: 'ffe4b5',
+ navajowEte: 'ffdead',
+ navy: '80',
+ Tdlace: 'fdf5e6',
+ Tive: '808000',
+ TivedBb: '6b8e23',
+ Sange: 'ffa500',
+ SangeYd: 'ff4500',
+ ScEd: 'da70d6',
+ pOegTMnPd: 'eee8aa',
+ pOegYF: '98fb98',
+ pOeQe: 'afeeee',
+ pOeviTetYd: 'db7093',
+ papayawEp: 'ffefd5',
+ pHKpuff: 'ffdab9',
+ peru: 'cd853f',
+ pRk: 'ffc0cb',
+ plum: 'dda0dd',
+ powMrXe: 'b0e0e6',
+ purpN: '800080',
+ YbeccapurpN: '663399',
+ Yd: 'ff0000',
+ Psybrown: 'bc8f8f',
+ PyOXe: '4169e1',
+ saddNbPwn: '8b4513',
+ sOmon: 'fa8072',
+ sandybPwn: 'f4a460',
+ sHgYF: '2e8b57',
+ sHshell: 'fff5ee',
+ siFna: 'a0522d',
+ silver: 'c0c0c0',
+ skyXe: '87ceeb',
+ UXe: '6a5acd',
+ UWay: '708090',
+ UgYy: '708090',
+ snow: 'fffafa',
+ sprRggYF: 'ff7f',
+ stAlXe: '4682b4',
+ tan: 'd2b48c',
+ teO: '8080',
+ tEstN: 'd8bfd8',
+ tomato: 'ff6347',
+ Qe: '40e0d0',
+ viTet: 'ee82ee',
+ JHt: 'f5deb3',
+ wEte: 'ffffff',
+ wEtesmoke: 'f5f5f5',
+ Lw: 'ffff00',
+ LwgYF: '9acd32'
+};
+function unpack() {
+ const unpacked = {};
+ const keys = Object.keys(names);
+ const tkeys = Object.keys(map$1$1);
+ let i, j, k, ok, nk;
+ for (i = 0; i < keys.length; i++) {
+ ok = nk = keys[i];
+ for (j = 0; j < tkeys.length; j++) {
+ k = tkeys[j];
+ nk = nk.replace(k, map$1$1[k]);
+ }
+ k = parseInt(names[ok], 16);
+ unpacked[nk] = [k >> 16 & 0xFF, k >> 8 & 0xFF, k & 0xFF];
+ }
+ return unpacked;
+}
+let names$1;
+function nameParse(str) {
+ if (!names$1) {
+ names$1 = unpack();
+ names$1.transparent = [0, 0, 0, 0];
+ }
+ const a = names$1[str.toLowerCase()];
+ return a && {
+ r: a[0],
+ g: a[1],
+ b: a[2],
+ a: a.length === 4 ? a[3] : 255
+ };
+}
+function modHSL(v, i, ratio) {
+ if (v) {
+ let tmp = rgb2hsl(v);
+ tmp[i] = Math.max(0, Math.min(tmp[i] + tmp[i] * ratio, i === 0 ? 360 : 1));
+ tmp = hsl2rgb(tmp);
+ v.r = tmp[0];
+ v.g = tmp[1];
+ v.b = tmp[2];
+ }
+}
+function clone$1(v, proto) {
+ return v ? Object.assign(proto || {}, v) : v;
+}
+function fromObject(input) {
+ var v = {r: 0, g: 0, b: 0, a: 255};
+ if (Array.isArray(input)) {
+ if (input.length >= 3) {
+ v = {r: input[0], g: input[1], b: input[2], a: 255};
+ if (input.length > 3) {
+ v.a = n2b(input[3]);
+ }
+ }
+ } else {
+ v = clone$1(input, {r: 0, g: 0, b: 0, a: 1});
+ v.a = n2b(v.a);
+ }
+ return v;
+}
+function functionParse(str) {
+ if (str.charAt(0) === 'r') {
+ return rgbParse(str);
+ }
+ return hueParse(str);
+}
+class Color {
+ constructor(input) {
+ if (input instanceof Color) {
+ return input;
+ }
+ const type = typeof input;
+ let v;
+ if (type === 'object') {
+ v = fromObject(input);
+ } else if (type === 'string') {
+ v = hexParse(input) || nameParse(input) || functionParse(input);
+ }
+ this._rgb = v;
+ this._valid = !!v;
+ }
+ get valid() {
+ return this._valid;
+ }
+ get rgb() {
+ var v = clone$1(this._rgb);
+ if (v) {
+ v.a = b2n(v.a);
+ }
+ return v;
+ }
+ set rgb(obj) {
+ this._rgb = fromObject(obj);
+ }
+ rgbString() {
+ return this._valid ? rgbString(this._rgb) : this._rgb;
+ }
+ hexString() {
+ return this._valid ? hexString(this._rgb) : this._rgb;
+ }
+ hslString() {
+ return this._valid ? hslString(this._rgb) : this._rgb;
+ }
+ mix(color, weight) {
+ const me = this;
+ if (color) {
+ const c1 = me.rgb;
+ const c2 = color.rgb;
+ let w2;
+ const p = weight === w2 ? 0.5 : weight;
+ const w = 2 * p - 1;
+ const a = c1.a - c2.a;
+ const w1 = ((w * a === -1 ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
+ w2 = 1 - w1;
+ c1.r = 0xFF & w1 * c1.r + w2 * c2.r + 0.5;
+ c1.g = 0xFF & w1 * c1.g + w2 * c2.g + 0.5;
+ c1.b = 0xFF & w1 * c1.b + w2 * c2.b + 0.5;
+ c1.a = p * c1.a + (1 - p) * c2.a;
+ me.rgb = c1;
+ }
+ return me;
+ }
+ clone() {
+ return new Color(this.rgb);
+ }
+ alpha(a) {
+ this._rgb.a = n2b(a);
+ return this;
+ }
+ clearer(ratio) {
+ const rgb = this._rgb;
+ rgb.a *= 1 - ratio;
+ return this;
+ }
+ greyscale() {
+ const rgb = this._rgb;
+ const val = round(rgb.r * 0.3 + rgb.g * 0.59 + rgb.b * 0.11);
+ rgb.r = rgb.g = rgb.b = val;
+ return this;
+ }
+ opaquer(ratio) {
+ const rgb = this._rgb;
+ rgb.a *= 1 + ratio;
+ return this;
+ }
+ negate() {
+ const v = this._rgb;
+ v.r = 255 - v.r;
+ v.g = 255 - v.g;
+ v.b = 255 - v.b;
+ return this;
+ }
+ lighten(ratio) {
+ modHSL(this._rgb, 2, ratio);
+ return this;
+ }
+ darken(ratio) {
+ modHSL(this._rgb, 2, -ratio);
+ return this;
+ }
+ saturate(ratio) {
+ modHSL(this._rgb, 1, ratio);
+ return this;
+ }
+ desaturate(ratio) {
+ modHSL(this._rgb, 1, -ratio);
+ return this;
+ }
+ rotate(deg) {
+ rotate(this._rgb, deg);
+ return this;
+ }
+}
+function index_esm(input) {
+ return new Color(input);
+}
+
+const isPatternOrGradient = (value) => value instanceof CanvasGradient || value instanceof CanvasPattern;
+function color(value) {
+ return isPatternOrGradient(value) ? value : index_esm(value);
+}
+function getHoverColor(value) {
+ return isPatternOrGradient(value)
+ ? value
+ : index_esm(value).saturate(0.5).darken(0.1).hexString();
+}
+
+function noop() {}
+const uid = (function() {
+ let id = 0;
+ return function() {
+ return id++;
+ };
+}());
+function isNullOrUndef(value) {
+ return value === null || typeof value === 'undefined';
+}
+function isArray(value) {
+ if (Array.isArray && Array.isArray(value)) {
+ return true;
+ }
+ const type = Object.prototype.toString.call(value);
+ if (type.substr(0, 7) === '[object' && type.substr(-6) === 'Array]') {
+ return true;
+ }
+ return false;
+}
+function isObject(value) {
+ return value !== null && Object.prototype.toString.call(value) === '[object Object]';
+}
+const isNumberFinite = (value) => (typeof value === 'number' || value instanceof Number) && isFinite(+value);
+function finiteOrDefault(value, defaultValue) {
+ return isNumberFinite(value) ? value : defaultValue;
+}
+function valueOrDefault(value, defaultValue) {
+ return typeof value === 'undefined' ? defaultValue : value;
+}
+const toPercentage = (value, dimension) =>
+ typeof value === 'string' && value.endsWith('%') ?
+ parseFloat(value) / 100
+ : value / dimension;
+const toDimension = (value, dimension) =>
+ typeof value === 'string' && value.endsWith('%') ?
+ parseFloat(value) / 100 * dimension
+ : +value;
+function callback(fn, args, thisArg) {
+ if (fn && typeof fn.call === 'function') {
+ return fn.apply(thisArg, args);
+ }
+}
+function each(loopable, fn, thisArg, reverse) {
+ let i, len, keys;
+ if (isArray(loopable)) {
+ len = loopable.length;
+ if (reverse) {
+ for (i = len - 1; i >= 0; i--) {
+ fn.call(thisArg, loopable[i], i);
+ }
+ } else {
+ for (i = 0; i < len; i++) {
+ fn.call(thisArg, loopable[i], i);
+ }
+ }
+ } else if (isObject(loopable)) {
+ keys = Object.keys(loopable);
+ len = keys.length;
+ for (i = 0; i < len; i++) {
+ fn.call(thisArg, loopable[keys[i]], keys[i]);
+ }
+ }
+}
+function _elementsEqual(a0, a1) {
+ let i, ilen, v0, v1;
+ if (!a0 || !a1 || a0.length !== a1.length) {
+ return false;
+ }
+ for (i = 0, ilen = a0.length; i < ilen; ++i) {
+ v0 = a0[i];
+ v1 = a1[i];
+ if (v0.datasetIndex !== v1.datasetIndex || v0.index !== v1.index) {
+ return false;
+ }
+ }
+ return true;
+}
+function clone(source) {
+ if (isArray(source)) {
+ return source.map(clone);
+ }
+ if (isObject(source)) {
+ const target = Object.create(null);
+ const keys = Object.keys(source);
+ const klen = keys.length;
+ let k = 0;
+ for (; k < klen; ++k) {
+ target[keys[k]] = clone(source[keys[k]]);
+ }
+ return target;
+ }
+ return source;
+}
+function isValidKey(key) {
+ return ['__proto__', 'prototype', 'constructor'].indexOf(key) === -1;
+}
+function _merger(key, target, source, options) {
+ if (!isValidKey(key)) {
+ return;
+ }
+ const tval = target[key];
+ const sval = source[key];
+ if (isObject(tval) && isObject(sval)) {
+ merge(tval, sval, options);
+ } else {
+ target[key] = clone(sval);
+ }
+}
+function merge(target, source, options) {
+ const sources = isArray(source) ? source : [source];
+ const ilen = sources.length;
+ if (!isObject(target)) {
+ return target;
+ }
+ options = options || {};
+ const merger = options.merger || _merger;
+ for (let i = 0; i < ilen; ++i) {
+ source = sources[i];
+ if (!isObject(source)) {
+ continue;
+ }
+ const keys = Object.keys(source);
+ for (let k = 0, klen = keys.length; k < klen; ++k) {
+ merger(keys[k], target, source, options);
+ }
+ }
+ return target;
+}
+function mergeIf(target, source) {
+ return merge(target, source, {merger: _mergerIf});
+}
+function _mergerIf(key, target, source) {
+ if (!isValidKey(key)) {
+ return;
+ }
+ const tval = target[key];
+ const sval = source[key];
+ if (isObject(tval) && isObject(sval)) {
+ mergeIf(tval, sval);
+ } else if (!Object.prototype.hasOwnProperty.call(target, key)) {
+ target[key] = clone(sval);
+ }
+}
+function _deprecated(scope, value, previous, current) {
+ if (value !== undefined) {
+ console.warn(scope + ': "' + previous +
+ '" is deprecated. Please use "' + current + '" instead');
+ }
+}
+const emptyString = '';
+const dot = '.';
+function indexOfDotOrLength(key, start) {
+ const idx = key.indexOf(dot, start);
+ return idx === -1 ? key.length : idx;
+}
+function resolveObjectKey(obj, key) {
+ if (key === emptyString) {
+ return obj;
+ }
+ let pos = 0;
+ let idx = indexOfDotOrLength(key, pos);
+ while (obj && idx > pos) {
+ obj = obj[key.substr(pos, idx - pos)];
+ pos = idx + 1;
+ idx = indexOfDotOrLength(key, pos);
+ }
+ return obj;
+}
+function _capitalize(str) {
+ return str.charAt(0).toUpperCase() + str.slice(1);
+}
+const defined = (value) => typeof value !== 'undefined';
+const isFunction = (value) => typeof value === 'function';
+const setsEqual = (a, b) => {
+ if (a.size !== b.size) {
+ return false;
+ }
+ for (const item of a) {
+ if (!b.has(item)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+const overrides = Object.create(null);
+const descriptors = Object.create(null);
+function getScope$1(node, key) {
+ if (!key) {
+ return node;
+ }
+ const keys = key.split('.');
+ for (let i = 0, n = keys.length; i < n; ++i) {
+ const k = keys[i];
+ node = node[k] || (node[k] = Object.create(null));
+ }
+ return node;
+}
+function set(root, scope, values) {
+ if (typeof scope === 'string') {
+ return merge(getScope$1(root, scope), values);
+ }
+ return merge(getScope$1(root, ''), scope);
+}
+class Defaults {
+ constructor(_descriptors) {
+ this.animation = undefined;
+ this.backgroundColor = 'rgba(0,0,0,0.1)';
+ this.borderColor = 'rgba(0,0,0,0.1)';
+ this.color = '#666';
+ this.datasets = {};
+ this.devicePixelRatio = (context) => context.chart.platform.getDevicePixelRatio();
+ this.elements = {};
+ this.events = [
+ 'mousemove',
+ 'mouseout',
+ 'click',
+ 'touchstart',
+ 'touchmove'
+ ];
+ this.font = {
+ family: "'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",
+ size: 12,
+ style: 'normal',
+ lineHeight: 1.2,
+ weight: null
+ };
+ this.hover = {};
+ this.hoverBackgroundColor = (ctx, options) => getHoverColor(options.backgroundColor);
+ this.hoverBorderColor = (ctx, options) => getHoverColor(options.borderColor);
+ this.hoverColor = (ctx, options) => getHoverColor(options.color);
+ this.indexAxis = 'x';
+ this.interaction = {
+ mode: 'nearest',
+ intersect: true
+ };
+ this.maintainAspectRatio = true;
+ this.onHover = null;
+ this.onClick = null;
+ this.parsing = true;
+ this.plugins = {};
+ this.responsive = true;
+ this.scale = undefined;
+ this.scales = {};
+ this.showLine = true;
+ this.describe(_descriptors);
+ }
+ set(scope, values) {
+ return set(this, scope, values);
+ }
+ get(scope) {
+ return getScope$1(this, scope);
+ }
+ describe(scope, values) {
+ return set(descriptors, scope, values);
+ }
+ override(scope, values) {
+ return set(overrides, scope, values);
+ }
+ route(scope, name, targetScope, targetName) {
+ const scopeObject = getScope$1(this, scope);
+ const targetScopeObject = getScope$1(this, targetScope);
+ const privateName = '_' + name;
+ Object.defineProperties(scopeObject, {
+ [privateName]: {
+ value: scopeObject[name],
+ writable: true
+ },
+ [name]: {
+ enumerable: true,
+ get() {
+ const local = this[privateName];
+ const target = targetScopeObject[targetName];
+ if (isObject(local)) {
+ return Object.assign({}, target, local);
+ }
+ return valueOrDefault(local, target);
+ },
+ set(value) {
+ this[privateName] = value;
+ }
+ }
+ });
+ }
+}
+var defaults = new Defaults({
+ _scriptable: (name) => !name.startsWith('on'),
+ _indexable: (name) => name !== 'events',
+ hover: {
+ _fallback: 'interaction'
+ },
+ interaction: {
+ _scriptable: false,
+ _indexable: false,
+ }
+});
+
+const PI = Math.PI;
+const TAU = 2 * PI;
+const PITAU = TAU + PI;
+const INFINITY = Number.POSITIVE_INFINITY;
+const RAD_PER_DEG = PI / 180;
+const HALF_PI = PI / 2;
+const QUARTER_PI = PI / 4;
+const TWO_THIRDS_PI = PI * 2 / 3;
+const log10 = Math.log10;
+const sign = Math.sign;
+function niceNum(range) {
+ const roundedRange = Math.round(range);
+ range = almostEquals(range, roundedRange, range / 1000) ? roundedRange : range;
+ const niceRange = Math.pow(10, Math.floor(log10(range)));
+ const fraction = range / niceRange;
+ const niceFraction = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 5 ? 5 : 10;
+ return niceFraction * niceRange;
+}
+function _factorize(value) {
+ const result = [];
+ const sqrt = Math.sqrt(value);
+ let i;
+ for (i = 1; i < sqrt; i++) {
+ if (value % i === 0) {
+ result.push(i);
+ result.push(value / i);
+ }
+ }
+ if (sqrt === (sqrt | 0)) {
+ result.push(sqrt);
+ }
+ result.sort((a, b) => a - b).pop();
+ return result;
+}
+function isNumber(n) {
+ return !isNaN(parseFloat(n)) && isFinite(n);
+}
+function almostEquals(x, y, epsilon) {
+ return Math.abs(x - y) < epsilon;
+}
+function almostWhole(x, epsilon) {
+ const rounded = Math.round(x);
+ return ((rounded - epsilon) <= x) && ((rounded + epsilon) >= x);
+}
+function _setMinAndMaxByKey(array, target, property) {
+ let i, ilen, value;
+ for (i = 0, ilen = array.length; i < ilen; i++) {
+ value = array[i][property];
+ if (!isNaN(value)) {
+ target.min = Math.min(target.min, value);
+ target.max = Math.max(target.max, value);
+ }
+ }
+}
+function toRadians(degrees) {
+ return degrees * (PI / 180);
+}
+function toDegrees(radians) {
+ return radians * (180 / PI);
+}
+function _decimalPlaces(x) {
+ if (!isNumberFinite(x)) {
+ return;
+ }
+ let e = 1;
+ let p = 0;
+ while (Math.round(x * e) / e !== x) {
+ e *= 10;
+ p++;
+ }
+ return p;
+}
+function getAngleFromPoint(centrePoint, anglePoint) {
+ const distanceFromXCenter = anglePoint.x - centrePoint.x;
+ const distanceFromYCenter = anglePoint.y - centrePoint.y;
+ const radialDistanceFromCenter = Math.sqrt(distanceFromXCenter * distanceFromXCenter + distanceFromYCenter * distanceFromYCenter);
+ let angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);
+ if (angle < (-0.5 * PI)) {
+ angle += TAU;
+ }
+ return {
+ angle,
+ distance: radialDistanceFromCenter
+ };
+}
+function distanceBetweenPoints(pt1, pt2) {
+ return Math.sqrt(Math.pow(pt2.x - pt1.x, 2) + Math.pow(pt2.y - pt1.y, 2));
+}
+function _angleDiff(a, b) {
+ return (a - b + PITAU) % TAU - PI;
+}
+function _normalizeAngle(a) {
+ return (a % TAU + TAU) % TAU;
+}
+function _angleBetween(angle, start, end, sameAngleIsFullCircle) {
+ const a = _normalizeAngle(angle);
+ const s = _normalizeAngle(start);
+ const e = _normalizeAngle(end);
+ const angleToStart = _normalizeAngle(s - a);
+ const angleToEnd = _normalizeAngle(e - a);
+ const startToAngle = _normalizeAngle(a - s);
+ const endToAngle = _normalizeAngle(a - e);
+ return a === s || a === e || (sameAngleIsFullCircle && s === e)
+ || (angleToStart > angleToEnd && startToAngle < endToAngle);
+}
+function _limitValue(value, min, max) {
+ return Math.max(min, Math.min(max, value));
+}
+function _int16Range(value) {
+ return _limitValue(value, -32768, 32767);
+}
+
+function toFontString(font) {
+ if (!font || isNullOrUndef(font.size) || isNullOrUndef(font.family)) {
+ return null;
+ }
+ return (font.style ? font.style + ' ' : '')
+ + (font.weight ? font.weight + ' ' : '')
+ + font.size + 'px '
+ + font.family;
+}
+function _measureText(ctx, data, gc, longest, string) {
+ let textWidth = data[string];
+ if (!textWidth) {
+ textWidth = data[string] = ctx.measureText(string).width;
+ gc.push(string);
+ }
+ if (textWidth > longest) {
+ longest = textWidth;
+ }
+ return longest;
+}
+function _longestText(ctx, font, arrayOfThings, cache) {
+ cache = cache || {};
+ let data = cache.data = cache.data || {};
+ let gc = cache.garbageCollect = cache.garbageCollect || [];
+ if (cache.font !== font) {
+ data = cache.data = {};
+ gc = cache.garbageCollect = [];
+ cache.font = font;
+ }
+ ctx.save();
+ ctx.font = font;
+ let longest = 0;
+ const ilen = arrayOfThings.length;
+ let i, j, jlen, thing, nestedThing;
+ for (i = 0; i < ilen; i++) {
+ thing = arrayOfThings[i];
+ if (thing !== undefined && thing !== null && isArray(thing) !== true) {
+ longest = _measureText(ctx, data, gc, longest, thing);
+ } else if (isArray(thing)) {
+ for (j = 0, jlen = thing.length; j < jlen; j++) {
+ nestedThing = thing[j];
+ if (nestedThing !== undefined && nestedThing !== null && !isArray(nestedThing)) {
+ longest = _measureText(ctx, data, gc, longest, nestedThing);
+ }
+ }
+ }
+ }
+ ctx.restore();
+ const gcLen = gc.length / 2;
+ if (gcLen > arrayOfThings.length) {
+ for (i = 0; i < gcLen; i++) {
+ delete data[gc[i]];
+ }
+ gc.splice(0, gcLen);
+ }
+ return longest;
+}
+function _alignPixel(chart, pixel, width) {
+ const devicePixelRatio = chart.currentDevicePixelRatio;
+ const halfWidth = width !== 0 ? Math.max(width / 2, 0.5) : 0;
+ return Math.round((pixel - halfWidth) * devicePixelRatio) / devicePixelRatio + halfWidth;
+}
+function clearCanvas(canvas, ctx) {
+ ctx = ctx || canvas.getContext('2d');
+ ctx.save();
+ ctx.resetTransform();
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
+ ctx.restore();
+}
+function drawPoint(ctx, options, x, y) {
+ let type, xOffset, yOffset, size, cornerRadius;
+ const style = options.pointStyle;
+ const rotation = options.rotation;
+ const radius = options.radius;
+ let rad = (rotation || 0) * RAD_PER_DEG;
+ if (style && typeof style === 'object') {
+ type = style.toString();
+ if (type === '[object HTMLImageElement]' || type === '[object HTMLCanvasElement]') {
+ ctx.save();
+ ctx.translate(x, y);
+ ctx.rotate(rad);
+ ctx.drawImage(style, -style.width / 2, -style.height / 2, style.width, style.height);
+ ctx.restore();
+ return;
+ }
+ }
+ if (isNaN(radius) || radius <= 0) {
+ return;
+ }
+ ctx.beginPath();
+ switch (style) {
+ default:
+ ctx.arc(x, y, radius, 0, TAU);
+ ctx.closePath();
+ break;
+ case 'triangle':
+ ctx.moveTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);
+ rad += TWO_THIRDS_PI;
+ ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);
+ rad += TWO_THIRDS_PI;
+ ctx.lineTo(x + Math.sin(rad) * radius, y - Math.cos(rad) * radius);
+ ctx.closePath();
+ break;
+ case 'rectRounded':
+ cornerRadius = radius * 0.516;
+ size = radius - cornerRadius;
+ xOffset = Math.cos(rad + QUARTER_PI) * size;
+ yOffset = Math.sin(rad + QUARTER_PI) * size;
+ ctx.arc(x - xOffset, y - yOffset, cornerRadius, rad - PI, rad - HALF_PI);
+ ctx.arc(x + yOffset, y - xOffset, cornerRadius, rad - HALF_PI, rad);
+ ctx.arc(x + xOffset, y + yOffset, cornerRadius, rad, rad + HALF_PI);
+ ctx.arc(x - yOffset, y + xOffset, cornerRadius, rad + HALF_PI, rad + PI);
+ ctx.closePath();
+ break;
+ case 'rect':
+ if (!rotation) {
+ size = Math.SQRT1_2 * radius;
+ ctx.rect(x - size, y - size, 2 * size, 2 * size);
+ break;
+ }
+ rad += QUARTER_PI;
+ case 'rectRot':
+ xOffset = Math.cos(rad) * radius;
+ yOffset = Math.sin(rad) * radius;
+ ctx.moveTo(x - xOffset, y - yOffset);
+ ctx.lineTo(x + yOffset, y - xOffset);
+ ctx.lineTo(x + xOffset, y + yOffset);
+ ctx.lineTo(x - yOffset, y + xOffset);
+ ctx.closePath();
+ break;
+ case 'crossRot':
+ rad += QUARTER_PI;
+ case 'cross':
+ xOffset = Math.cos(rad) * radius;
+ yOffset = Math.sin(rad) * radius;
+ ctx.moveTo(x - xOffset, y - yOffset);
+ ctx.lineTo(x + xOffset, y + yOffset);
+ ctx.moveTo(x + yOffset, y - xOffset);
+ ctx.lineTo(x - yOffset, y + xOffset);
+ break;
+ case 'star':
+ xOffset = Math.cos(rad) * radius;
+ yOffset = Math.sin(rad) * radius;
+ ctx.moveTo(x - xOffset, y - yOffset);
+ ctx.lineTo(x + xOffset, y + yOffset);
+ ctx.moveTo(x + yOffset, y - xOffset);
+ ctx.lineTo(x - yOffset, y + xOffset);
+ rad += QUARTER_PI;
+ xOffset = Math.cos(rad) * radius;
+ yOffset = Math.sin(rad) * radius;
+ ctx.moveTo(x - xOffset, y - yOffset);
+ ctx.lineTo(x + xOffset, y + yOffset);
+ ctx.moveTo(x + yOffset, y - xOffset);
+ ctx.lineTo(x - yOffset, y + xOffset);
+ break;
+ case 'line':
+ xOffset = Math.cos(rad) * radius;
+ yOffset = Math.sin(rad) * radius;
+ ctx.moveTo(x - xOffset, y - yOffset);
+ ctx.lineTo(x + xOffset, y + yOffset);
+ break;
+ case 'dash':
+ ctx.moveTo(x, y);
+ ctx.lineTo(x + Math.cos(rad) * radius, y + Math.sin(rad) * radius);
+ break;
+ }
+ ctx.fill();
+ if (options.borderWidth > 0) {
+ ctx.stroke();
+ }
+}
+function _isPointInArea(point, area, margin) {
+ margin = margin || 0.5;
+ return !area || (point && point.x > area.left - margin && point.x < area.right + margin &&
+ point.y > area.top - margin && point.y < area.bottom + margin);
+}
+function clipArea(ctx, area) {
+ ctx.save();
+ ctx.beginPath();
+ ctx.rect(area.left, area.top, area.right - area.left, area.bottom - area.top);
+ ctx.clip();
+}
+function unclipArea(ctx) {
+ ctx.restore();
+}
+function _steppedLineTo(ctx, previous, target, flip, mode) {
+ if (!previous) {
+ return ctx.lineTo(target.x, target.y);
+ }
+ if (mode === 'middle') {
+ const midpoint = (previous.x + target.x) / 2.0;
+ ctx.lineTo(midpoint, previous.y);
+ ctx.lineTo(midpoint, target.y);
+ } else if (mode === 'after' !== !!flip) {
+ ctx.lineTo(previous.x, target.y);
+ } else {
+ ctx.lineTo(target.x, previous.y);
+ }
+ ctx.lineTo(target.x, target.y);
+}
+function _bezierCurveTo(ctx, previous, target, flip) {
+ if (!previous) {
+ return ctx.lineTo(target.x, target.y);
+ }
+ ctx.bezierCurveTo(
+ flip ? previous.cp1x : previous.cp2x,
+ flip ? previous.cp1y : previous.cp2y,
+ flip ? target.cp2x : target.cp1x,
+ flip ? target.cp2y : target.cp1y,
+ target.x,
+ target.y);
+}
+function renderText(ctx, text, x, y, font, opts = {}) {
+ const lines = isArray(text) ? text : [text];
+ const stroke = opts.strokeWidth > 0 && opts.strokeColor !== '';
+ let i, line;
+ ctx.save();
+ ctx.font = font.string;
+ setRenderOpts(ctx, opts);
+ for (i = 0; i < lines.length; ++i) {
+ line = lines[i];
+ if (stroke) {
+ if (opts.strokeColor) {
+ ctx.strokeStyle = opts.strokeColor;
+ }
+ if (!isNullOrUndef(opts.strokeWidth)) {
+ ctx.lineWidth = opts.strokeWidth;
+ }
+ ctx.strokeText(line, x, y, opts.maxWidth);
+ }
+ ctx.fillText(line, x, y, opts.maxWidth);
+ decorateText(ctx, x, y, line, opts);
+ y += font.lineHeight;
+ }
+ ctx.restore();
+}
+function setRenderOpts(ctx, opts) {
+ if (opts.translation) {
+ ctx.translate(opts.translation[0], opts.translation[1]);
+ }
+ if (!isNullOrUndef(opts.rotation)) {
+ ctx.rotate(opts.rotation);
+ }
+ if (opts.color) {
+ ctx.fillStyle = opts.color;
+ }
+ if (opts.textAlign) {
+ ctx.textAlign = opts.textAlign;
+ }
+ if (opts.textBaseline) {
+ ctx.textBaseline = opts.textBaseline;
+ }
+}
+function decorateText(ctx, x, y, line, opts) {
+ if (opts.strikethrough || opts.underline) {
+ const metrics = ctx.measureText(line);
+ const left = x - metrics.actualBoundingBoxLeft;
+ const right = x + metrics.actualBoundingBoxRight;
+ const top = y - metrics.actualBoundingBoxAscent;
+ const bottom = y + metrics.actualBoundingBoxDescent;
+ const yDecoration = opts.strikethrough ? (top + bottom) / 2 : bottom;
+ ctx.strokeStyle = ctx.fillStyle;
+ ctx.beginPath();
+ ctx.lineWidth = opts.decorationWidth || 2;
+ ctx.moveTo(left, yDecoration);
+ ctx.lineTo(right, yDecoration);
+ ctx.stroke();
+ }
+}
+function addRoundedRectPath(ctx, rect) {
+ const {x, y, w, h, radius} = rect;
+ ctx.arc(x + radius.topLeft, y + radius.topLeft, radius.topLeft, -HALF_PI, PI, true);
+ ctx.lineTo(x, y + h - radius.bottomLeft);
+ ctx.arc(x + radius.bottomLeft, y + h - radius.bottomLeft, radius.bottomLeft, PI, HALF_PI, true);
+ ctx.lineTo(x + w - radius.bottomRight, y + h);
+ ctx.arc(x + w - radius.bottomRight, y + h - radius.bottomRight, radius.bottomRight, HALF_PI, 0, true);
+ ctx.lineTo(x + w, y + radius.topRight);
+ ctx.arc(x + w - radius.topRight, y + radius.topRight, radius.topRight, 0, -HALF_PI, true);
+ ctx.lineTo(x + radius.topLeft, y);
+}
+
+function _lookup(table, value, cmp) {
+ cmp = cmp || ((index) => table[index] < value);
+ let hi = table.length - 1;
+ let lo = 0;
+ let mid;
+ while (hi - lo > 1) {
+ mid = (lo + hi) >> 1;
+ if (cmp(mid)) {
+ lo = mid;
+ } else {
+ hi = mid;
+ }
+ }
+ return {lo, hi};
+}
+const _lookupByKey = (table, key, value) =>
+ _lookup(table, value, index => table[index][key] < value);
+const _rlookupByKey = (table, key, value) =>
+ _lookup(table, value, index => table[index][key] >= value);
+function _filterBetween(values, min, max) {
+ let start = 0;
+ let end = values.length;
+ while (start < end && values[start] < min) {
+ start++;
+ }
+ while (end > start && values[end - 1] > max) {
+ end--;
+ }
+ return start > 0 || end < values.length
+ ? values.slice(start, end)
+ : values;
+}
+const arrayEvents = ['push', 'pop', 'shift', 'splice', 'unshift'];
+function listenArrayEvents(array, listener) {
+ if (array._chartjs) {
+ array._chartjs.listeners.push(listener);
+ return;
+ }
+ Object.defineProperty(array, '_chartjs', {
+ configurable: true,
+ enumerable: false,
+ value: {
+ listeners: [listener]
+ }
+ });
+ arrayEvents.forEach((key) => {
+ const method = '_onData' + _capitalize(key);
+ const base = array[key];
+ Object.defineProperty(array, key, {
+ configurable: true,
+ enumerable: false,
+ value(...args) {
+ const res = base.apply(this, args);
+ array._chartjs.listeners.forEach((object) => {
+ if (typeof object[method] === 'function') {
+ object[method](...args);
+ }
+ });
+ return res;
+ }
+ });
+ });
+}
+function unlistenArrayEvents(array, listener) {
+ const stub = array._chartjs;
+ if (!stub) {
+ return;
+ }
+ const listeners = stub.listeners;
+ const index = listeners.indexOf(listener);
+ if (index !== -1) {
+ listeners.splice(index, 1);
+ }
+ if (listeners.length > 0) {
+ return;
+ }
+ arrayEvents.forEach((key) => {
+ delete array[key];
+ });
+ delete array._chartjs;
+}
+function _arrayUnique(items) {
+ const set = new Set();
+ let i, ilen;
+ for (i = 0, ilen = items.length; i < ilen; ++i) {
+ set.add(items[i]);
+ }
+ if (set.size === ilen) {
+ return items;
+ }
+ return Array.from(set);
+}
+
+function _isDomSupported() {
+ return typeof window !== 'undefined' && typeof document !== 'undefined';
+}
+function _getParentNode(domNode) {
+ let parent = domNode.parentNode;
+ if (parent && parent.toString() === '[object ShadowRoot]') {
+ parent = parent.host;
+ }
+ return parent;
+}
+function parseMaxStyle(styleValue, node, parentProperty) {
+ let valueInPixels;
+ if (typeof styleValue === 'string') {
+ valueInPixels = parseInt(styleValue, 10);
+ if (styleValue.indexOf('%') !== -1) {
+ valueInPixels = valueInPixels / 100 * node.parentNode[parentProperty];
+ }
+ } else {
+ valueInPixels = styleValue;
+ }
+ return valueInPixels;
+}
+const getComputedStyle = (element) => window.getComputedStyle(element, null);
+function getStyle(el, property) {
+ return getComputedStyle(el).getPropertyValue(property);
+}
+const positions = ['top', 'right', 'bottom', 'left'];
+function getPositionedStyle(styles, style, suffix) {
+ const result = {};
+ suffix = suffix ? '-' + suffix : '';
+ for (let i = 0; i < 4; i++) {
+ const pos = positions[i];
+ result[pos] = parseFloat(styles[style + '-' + pos + suffix]) || 0;
+ }
+ result.width = result.left + result.right;
+ result.height = result.top + result.bottom;
+ return result;
+}
+const useOffsetPos = (x, y, target) => (x > 0 || y > 0) && (!target || !target.shadowRoot);
+function getCanvasPosition(evt, canvas) {
+ const e = evt.native || evt;
+ const touches = e.touches;
+ const source = touches && touches.length ? touches[0] : e;
+ const {offsetX, offsetY} = source;
+ let box = false;
+ let x, y;
+ if (useOffsetPos(offsetX, offsetY, e.target)) {
+ x = offsetX;
+ y = offsetY;
+ } else {
+ const rect = canvas.getBoundingClientRect();
+ x = source.clientX - rect.left;
+ y = source.clientY - rect.top;
+ box = true;
+ }
+ return {x, y, box};
+}
+function getRelativePosition$1(evt, chart) {
+ const {canvas, currentDevicePixelRatio} = chart;
+ const style = getComputedStyle(canvas);
+ const borderBox = style.boxSizing === 'border-box';
+ const paddings = getPositionedStyle(style, 'padding');
+ const borders = getPositionedStyle(style, 'border', 'width');
+ const {x, y, box} = getCanvasPosition(evt, canvas);
+ const xOffset = paddings.left + (box && borders.left);
+ const yOffset = paddings.top + (box && borders.top);
+ let {width, height} = chart;
+ if (borderBox) {
+ width -= paddings.width + borders.width;
+ height -= paddings.height + borders.height;
+ }
+ return {
+ x: Math.round((x - xOffset) / width * canvas.width / currentDevicePixelRatio),
+ y: Math.round((y - yOffset) / height * canvas.height / currentDevicePixelRatio)
+ };
+}
+function getContainerSize(canvas, width, height) {
+ let maxWidth, maxHeight;
+ if (width === undefined || height === undefined) {
+ const container = _getParentNode(canvas);
+ if (!container) {
+ width = canvas.clientWidth;
+ height = canvas.clientHeight;
+ } else {
+ const rect = container.getBoundingClientRect();
+ const containerStyle = getComputedStyle(container);
+ const containerBorder = getPositionedStyle(containerStyle, 'border', 'width');
+ const containerPadding = getPositionedStyle(containerStyle, 'padding');
+ width = rect.width - containerPadding.width - containerBorder.width;
+ height = rect.height - containerPadding.height - containerBorder.height;
+ maxWidth = parseMaxStyle(containerStyle.maxWidth, container, 'clientWidth');
+ maxHeight = parseMaxStyle(containerStyle.maxHeight, container, 'clientHeight');
+ }
+ }
+ return {
+ width,
+ height,
+ maxWidth: maxWidth || INFINITY,
+ maxHeight: maxHeight || INFINITY
+ };
+}
+const round1 = v => Math.round(v * 10) / 10;
+function getMaximumSize(canvas, bbWidth, bbHeight, aspectRatio) {
+ const style = getComputedStyle(canvas);
+ const margins = getPositionedStyle(style, 'margin');
+ const maxWidth = parseMaxStyle(style.maxWidth, canvas, 'clientWidth') || INFINITY;
+ const maxHeight = parseMaxStyle(style.maxHeight, canvas, 'clientHeight') || INFINITY;
+ const containerSize = getContainerSize(canvas, bbWidth, bbHeight);
+ let {width, height} = containerSize;
+ if (style.boxSizing === 'content-box') {
+ const borders = getPositionedStyle(style, 'border', 'width');
+ const paddings = getPositionedStyle(style, 'padding');
+ width -= paddings.width + borders.width;
+ height -= paddings.height + borders.height;
+ }
+ width = Math.max(0, width - margins.width);
+ height = Math.max(0, aspectRatio ? Math.floor(width / aspectRatio) : height - margins.height);
+ width = round1(Math.min(width, maxWidth, containerSize.maxWidth));
+ height = round1(Math.min(height, maxHeight, containerSize.maxHeight));
+ if (width && !height) {
+ height = round1(width / 2);
+ }
+ return {
+ width,
+ height
+ };
+}
+function retinaScale(chart, forceRatio, forceStyle) {
+ const pixelRatio = forceRatio || 1;
+ const deviceHeight = Math.floor(chart.height * pixelRatio);
+ const deviceWidth = Math.floor(chart.width * pixelRatio);
+ chart.height = deviceHeight / pixelRatio;
+ chart.width = deviceWidth / pixelRatio;
+ const canvas = chart.canvas;
+ if (canvas.style && (forceStyle || (!canvas.style.height && !canvas.style.width))) {
+ canvas.style.height = `${chart.height}px`;
+ canvas.style.width = `${chart.width}px`;
+ }
+ if (chart.currentDevicePixelRatio !== pixelRatio
+ || canvas.height !== deviceHeight
+ || canvas.width !== deviceWidth) {
+ chart.currentDevicePixelRatio = pixelRatio;
+ canvas.height = deviceHeight;
+ canvas.width = deviceWidth;
+ chart.ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
+ return true;
+ }
+ return false;
+}
+const supportsEventListenerOptions = (function() {
+ let passiveSupported = false;
+ try {
+ const options = {
+ get passive() {
+ passiveSupported = true;
+ return false;
+ }
+ };
+ window.addEventListener('test', null, options);
+ window.removeEventListener('test', null, options);
+ } catch (e) {
+ }
+ return passiveSupported;
+}());
+function readUsedSize(element, property) {
+ const value = getStyle(element, property);
+ const matches = value && value.match(/^(\d+)(\.\d+)?px$/);
+ return matches ? +matches[1] : undefined;
+}
+
+function getRelativePosition(e, chart) {
+ if ('native' in e) {
+ return {
+ x: e.x,
+ y: e.y
+ };
+ }
+ return getRelativePosition$1(e, chart);
+}
+function evaluateAllVisibleItems(chart, handler) {
+ const metasets = chart.getSortedVisibleDatasetMetas();
+ let index, data, element;
+ for (let i = 0, ilen = metasets.length; i < ilen; ++i) {
+ ({index, data} = metasets[i]);
+ for (let j = 0, jlen = data.length; j < jlen; ++j) {
+ element = data[j];
+ if (!element.skip) {
+ handler(element, index, j);
+ }
+ }
+ }
+}
+function binarySearch(metaset, axis, value, intersect) {
+ const {controller, data, _sorted} = metaset;
+ const iScale = controller._cachedMeta.iScale;
+ if (iScale && axis === iScale.axis && _sorted && data.length) {
+ const lookupMethod = iScale._reversePixels ? _rlookupByKey : _lookupByKey;
+ if (!intersect) {
+ return lookupMethod(data, axis, value);
+ } else if (controller._sharedOptions) {
+ const el = data[0];
+ const range = typeof el.getRange === 'function' && el.getRange(axis);
+ if (range) {
+ const start = lookupMethod(data, axis, value - range);
+ const end = lookupMethod(data, axis, value + range);
+ return {lo: start.lo, hi: end.hi};
+ }
+ }
+ }
+ return {lo: 0, hi: data.length - 1};
+}
+function optimizedEvaluateItems(chart, axis, position, handler, intersect) {
+ const metasets = chart.getSortedVisibleDatasetMetas();
+ const value = position[axis];
+ for (let i = 0, ilen = metasets.length; i < ilen; ++i) {
+ const {index, data} = metasets[i];
+ const {lo, hi} = binarySearch(metasets[i], axis, value, intersect);
+ for (let j = lo; j <= hi; ++j) {
+ const element = data[j];
+ if (!element.skip) {
+ handler(element, index, j);
+ }
+ }
+ }
+}
+function getDistanceMetricForAxis(axis) {
+ const useX = axis.indexOf('x') !== -1;
+ const useY = axis.indexOf('y') !== -1;
+ return function(pt1, pt2) {
+ const deltaX = useX ? Math.abs(pt1.x - pt2.x) : 0;
+ const deltaY = useY ? Math.abs(pt1.y - pt2.y) : 0;
+ return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
+ };
+}
+function getIntersectItems(chart, position, axis, useFinalPosition) {
+ const items = [];
+ if (!_isPointInArea(position, chart.chartArea, chart._minPadding)) {
+ return items;
+ }
+ const evaluationFunc = function(element, datasetIndex, index) {
+ if (element.inRange(position.x, position.y, useFinalPosition)) {
+ items.push({element, datasetIndex, index});
+ }
+ };
+ optimizedEvaluateItems(chart, axis, position, evaluationFunc, true);
+ return items;
+}
+function getNearestItems(chart, position, axis, intersect, useFinalPosition) {
+ const distanceMetric = getDistanceMetricForAxis(axis);
+ let minDistance = Number.POSITIVE_INFINITY;
+ let items = [];
+ if (!_isPointInArea(position, chart.chartArea, chart._minPadding)) {
+ return items;
+ }
+ const evaluationFunc = function(element, datasetIndex, index) {
+ if (intersect && !element.inRange(position.x, position.y, useFinalPosition)) {
+ return;
+ }
+ const center = element.getCenterPoint(useFinalPosition);
+ if (!_isPointInArea(center, chart.chartArea, chart._minPadding) && !element.inRange(position.x, position.y, useFinalPosition)) {
+ return;
+ }
+ const distance = distanceMetric(position, center);
+ if (distance < minDistance) {
+ items = [{element, datasetIndex, index}];
+ minDistance = distance;
+ } else if (distance === minDistance) {
+ items.push({element, datasetIndex, index});
+ }
+ };
+ optimizedEvaluateItems(chart, axis, position, evaluationFunc);
+ return items;
+}
+function getAxisItems(chart, e, options, useFinalPosition) {
+ const position = getRelativePosition(e, chart);
+ const items = [];
+ const axis = options.axis;
+ const rangeMethod = axis === 'x' ? 'inXRange' : 'inYRange';
+ let intersectsItem = false;
+ evaluateAllVisibleItems(chart, (element, datasetIndex, index) => {
+ if (element[rangeMethod](position[axis], useFinalPosition)) {
+ items.push({element, datasetIndex, index});
+ }
+ if (element.inRange(position.x, position.y, useFinalPosition)) {
+ intersectsItem = true;
+ }
+ });
+ if (options.intersect && !intersectsItem) {
+ return [];
+ }
+ return items;
+}
+var Interaction = {
+ modes: {
+ index(chart, e, options, useFinalPosition) {
+ const position = getRelativePosition(e, chart);
+ const axis = options.axis || 'x';
+ const items = options.intersect
+ ? getIntersectItems(chart, position, axis, useFinalPosition)
+ : getNearestItems(chart, position, axis, false, useFinalPosition);
+ const elements = [];
+ if (!items.length) {
+ return [];
+ }
+ chart.getSortedVisibleDatasetMetas().forEach((meta) => {
+ const index = items[0].index;
+ const element = meta.data[index];
+ if (element && !element.skip) {
+ elements.push({element, datasetIndex: meta.index, index});
+ }
+ });
+ return elements;
+ },
+ dataset(chart, e, options, useFinalPosition) {
+ const position = getRelativePosition(e, chart);
+ const axis = options.axis || 'xy';
+ let items = options.intersect
+ ? getIntersectItems(chart, position, axis, useFinalPosition) :
+ getNearestItems(chart, position, axis, false, useFinalPosition);
+ if (items.length > 0) {
+ const datasetIndex = items[0].datasetIndex;
+ const data = chart.getDatasetMeta(datasetIndex).data;
+ items = [];
+ for (let i = 0; i < data.length; ++i) {
+ items.push({element: data[i], datasetIndex, index: i});
+ }
+ }
+ return items;
+ },
+ point(chart, e, options, useFinalPosition) {
+ const position = getRelativePosition(e, chart);
+ const axis = options.axis || 'xy';
+ return getIntersectItems(chart, position, axis, useFinalPosition);
+ },
+ nearest(chart, e, options, useFinalPosition) {
+ const position = getRelativePosition(e, chart);
+ const axis = options.axis || 'xy';
+ return getNearestItems(chart, position, axis, options.intersect, useFinalPosition);
+ },
+ x(chart, e, options, useFinalPosition) {
+ options.axis = 'x';
+ return getAxisItems(chart, e, options, useFinalPosition);
+ },
+ y(chart, e, options, useFinalPosition) {
+ options.axis = 'y';
+ return getAxisItems(chart, e, options, useFinalPosition);
+ }
+ }
+};
+
+const LINE_HEIGHT = new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/);
+const FONT_STYLE = new RegExp(/^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/);
+function toLineHeight(value, size) {
+ const matches = ('' + value).match(LINE_HEIGHT);
+ if (!matches || matches[1] === 'normal') {
+ return size * 1.2;
+ }
+ value = +matches[2];
+ switch (matches[3]) {
+ case 'px':
+ return value;
+ case '%':
+ value /= 100;
+ break;
+ }
+ return size * value;
+}
+const numberOrZero$1 = v => +v || 0;
+function _readValueToProps(value, props) {
+ const ret = {};
+ const objProps = isObject(props);
+ const keys = objProps ? Object.keys(props) : props;
+ const read = isObject(value)
+ ? objProps
+ ? prop => valueOrDefault(value[prop], value[props[prop]])
+ : prop => value[prop]
+ : () => value;
+ for (const prop of keys) {
+ ret[prop] = numberOrZero$1(read(prop));
+ }
+ return ret;
+}
+function toTRBL(value) {
+ return _readValueToProps(value, {top: 'y', right: 'x', bottom: 'y', left: 'x'});
+}
+function toTRBLCorners(value) {
+ return _readValueToProps(value, ['topLeft', 'topRight', 'bottomLeft', 'bottomRight']);
+}
+function toPadding(value) {
+ const obj = toTRBL(value);
+ obj.width = obj.left + obj.right;
+ obj.height = obj.top + obj.bottom;
+ return obj;
+}
+function toFont(options, fallback) {
+ options = options || {};
+ fallback = fallback || defaults.font;
+ let size = valueOrDefault(options.size, fallback.size);
+ if (typeof size === 'string') {
+ size = parseInt(size, 10);
+ }
+ let style = valueOrDefault(options.style, fallback.style);
+ if (style && !('' + style).match(FONT_STYLE)) {
+ console.warn('Invalid font style specified: "' + style + '"');
+ style = '';
+ }
+ const font = {
+ family: valueOrDefault(options.family, fallback.family),
+ lineHeight: toLineHeight(valueOrDefault(options.lineHeight, fallback.lineHeight), size),
+ size,
+ style,
+ weight: valueOrDefault(options.weight, fallback.weight),
+ string: ''
+ };
+ font.string = toFontString(font);
+ return font;
+}
+function resolve(inputs, context, index, info) {
+ let cacheable = true;
+ let i, ilen, value;
+ for (i = 0, ilen = inputs.length; i < ilen; ++i) {
+ value = inputs[i];
+ if (value === undefined) {
+ continue;
+ }
+ if (context !== undefined && typeof value === 'function') {
+ value = value(context);
+ cacheable = false;
+ }
+ if (index !== undefined && isArray(value)) {
+ value = value[index % value.length];
+ cacheable = false;
+ }
+ if (value !== undefined) {
+ if (info && !cacheable) {
+ info.cacheable = false;
+ }
+ return value;
+ }
+ }
+}
+function _addGrace(minmax, grace, beginAtZero) {
+ const {min, max} = minmax;
+ const change = toDimension(grace, (max - min) / 2);
+ const keepZero = (value, add) => beginAtZero && value === 0 ? 0 : value + add;
+ return {
+ min: keepZero(min, -Math.abs(change)),
+ max: keepZero(max, change)
+ };
+}
+function createContext(parentContext, context) {
+ return Object.assign(Object.create(parentContext), context);
+}
+
+const STATIC_POSITIONS = ['left', 'top', 'right', 'bottom'];
+function filterByPosition(array, position) {
+ return array.filter(v => v.pos === position);
+}
+function filterDynamicPositionByAxis(array, axis) {
+ return array.filter(v => STATIC_POSITIONS.indexOf(v.pos) === -1 && v.box.axis === axis);
+}
+function sortByWeight(array, reverse) {
+ return array.sort((a, b) => {
+ const v0 = reverse ? b : a;
+ const v1 = reverse ? a : b;
+ return v0.weight === v1.weight ?
+ v0.index - v1.index :
+ v0.weight - v1.weight;
+ });
+}
+function wrapBoxes(boxes) {
+ const layoutBoxes = [];
+ let i, ilen, box, pos, stack, stackWeight;
+ for (i = 0, ilen = (boxes || []).length; i < ilen; ++i) {
+ box = boxes[i];
+ ({position: pos, options: {stack, stackWeight = 1}} = box);
+ layoutBoxes.push({
+ index: i,
+ box,
+ pos,
+ horizontal: box.isHorizontal(),
+ weight: box.weight,
+ stack: stack && (pos + stack),
+ stackWeight
+ });
+ }
+ return layoutBoxes;
+}
+function buildStacks(layouts) {
+ const stacks = {};
+ for (const wrap of layouts) {
+ const {stack, pos, stackWeight} = wrap;
+ if (!stack || !STATIC_POSITIONS.includes(pos)) {
+ continue;
+ }
+ const _stack = stacks[stack] || (stacks[stack] = {count: 0, placed: 0, weight: 0, size: 0});
+ _stack.count++;
+ _stack.weight += stackWeight;
+ }
+ return stacks;
+}
+function setLayoutDims(layouts, params) {
+ const stacks = buildStacks(layouts);
+ const {vBoxMaxWidth, hBoxMaxHeight} = params;
+ let i, ilen, layout;
+ for (i = 0, ilen = layouts.length; i < ilen; ++i) {
+ layout = layouts[i];
+ const {fullSize} = layout.box;
+ const stack = stacks[layout.stack];
+ const factor = stack && layout.stackWeight / stack.weight;
+ if (layout.horizontal) {
+ layout.width = factor ? factor * vBoxMaxWidth : fullSize && params.availableWidth;
+ layout.height = hBoxMaxHeight;
+ } else {
+ layout.width = vBoxMaxWidth;
+ layout.height = factor ? factor * hBoxMaxHeight : fullSize && params.availableHeight;
+ }
+ }
+ return stacks;
+}
+function buildLayoutBoxes(boxes) {
+ const layoutBoxes = wrapBoxes(boxes);
+ const fullSize = sortByWeight(layoutBoxes.filter(wrap => wrap.box.fullSize), true);
+ const left = sortByWeight(filterByPosition(layoutBoxes, 'left'), true);
+ const right = sortByWeight(filterByPosition(layoutBoxes, 'right'));
+ const top = sortByWeight(filterByPosition(layoutBoxes, 'top'), true);
+ const bottom = sortByWeight(filterByPosition(layoutBoxes, 'bottom'));
+ const centerHorizontal = filterDynamicPositionByAxis(layoutBoxes, 'x');
+ const centerVertical = filterDynamicPositionByAxis(layoutBoxes, 'y');
+ return {
+ fullSize,
+ leftAndTop: left.concat(top),
+ rightAndBottom: right.concat(centerVertical).concat(bottom).concat(centerHorizontal),
+ chartArea: filterByPosition(layoutBoxes, 'chartArea'),
+ vertical: left.concat(right).concat(centerVertical),
+ horizontal: top.concat(bottom).concat(centerHorizontal)
+ };
+}
+function getCombinedMax(maxPadding, chartArea, a, b) {
+ return Math.max(maxPadding[a], chartArea[a]) + Math.max(maxPadding[b], chartArea[b]);
+}
+function updateMaxPadding(maxPadding, boxPadding) {
+ maxPadding.top = Math.max(maxPadding.top, boxPadding.top);
+ maxPadding.left = Math.max(maxPadding.left, boxPadding.left);
+ maxPadding.bottom = Math.max(maxPadding.bottom, boxPadding.bottom);
+ maxPadding.right = Math.max(maxPadding.right, boxPadding.right);
+}
+function updateDims(chartArea, params, layout, stacks) {
+ const {pos, box} = layout;
+ const maxPadding = chartArea.maxPadding;
+ if (!isObject(pos)) {
+ if (layout.size) {
+ chartArea[pos] -= layout.size;
+ }
+ const stack = stacks[layout.stack] || {size: 0, count: 1};
+ stack.size = Math.max(stack.size, layout.horizontal ? box.height : box.width);
+ layout.size = stack.size / stack.count;
+ chartArea[pos] += layout.size;
+ }
+ if (box.getPadding) {
+ updateMaxPadding(maxPadding, box.getPadding());
+ }
+ const newWidth = Math.max(0, params.outerWidth - getCombinedMax(maxPadding, chartArea, 'left', 'right'));
+ const newHeight = Math.max(0, params.outerHeight - getCombinedMax(maxPadding, chartArea, 'top', 'bottom'));
+ const widthChanged = newWidth !== chartArea.w;
+ const heightChanged = newHeight !== chartArea.h;
+ chartArea.w = newWidth;
+ chartArea.h = newHeight;
+ return layout.horizontal
+ ? {same: widthChanged, other: heightChanged}
+ : {same: heightChanged, other: widthChanged};
+}
+function handleMaxPadding(chartArea) {
+ const maxPadding = chartArea.maxPadding;
+ function updatePos(pos) {
+ const change = Math.max(maxPadding[pos] - chartArea[pos], 0);
+ chartArea[pos] += change;
+ return change;
+ }
+ chartArea.y += updatePos('top');
+ chartArea.x += updatePos('left');
+ updatePos('right');
+ updatePos('bottom');
+}
+function getMargins(horizontal, chartArea) {
+ const maxPadding = chartArea.maxPadding;
+ function marginForPositions(positions) {
+ const margin = {left: 0, top: 0, right: 0, bottom: 0};
+ positions.forEach((pos) => {
+ margin[pos] = Math.max(chartArea[pos], maxPadding[pos]);
+ });
+ return margin;
+ }
+ return horizontal
+ ? marginForPositions(['left', 'right'])
+ : marginForPositions(['top', 'bottom']);
+}
+function fitBoxes(boxes, chartArea, params, stacks) {
+ const refitBoxes = [];
+ let i, ilen, layout, box, refit, changed;
+ for (i = 0, ilen = boxes.length, refit = 0; i < ilen; ++i) {
+ layout = boxes[i];
+ box = layout.box;
+ box.update(
+ layout.width || chartArea.w,
+ layout.height || chartArea.h,
+ getMargins(layout.horizontal, chartArea)
+ );
+ const {same, other} = updateDims(chartArea, params, layout, stacks);
+ refit |= same && refitBoxes.length;
+ changed = changed || other;
+ if (!box.fullSize) {
+ refitBoxes.push(layout);
+ }
+ }
+ return refit && fitBoxes(refitBoxes, chartArea, params, stacks) || changed;
+}
+function setBoxDims(box, left, top, width, height) {
+ box.top = top;
+ box.left = left;
+ box.right = left + width;
+ box.bottom = top + height;
+ box.width = width;
+ box.height = height;
+}
+function placeBoxes(boxes, chartArea, params, stacks) {
+ const userPadding = params.padding;
+ let {x, y} = chartArea;
+ for (const layout of boxes) {
+ const box = layout.box;
+ const stack = stacks[layout.stack] || {count: 1, placed: 0, weight: 1};
+ const weight = (layout.stackWeight / stack.weight) || 1;
+ if (layout.horizontal) {
+ const width = chartArea.w * weight;
+ const height = stack.size || box.height;
+ if (defined(stack.start)) {
+ y = stack.start;
+ }
+ if (box.fullSize) {
+ setBoxDims(box, userPadding.left, y, params.outerWidth - userPadding.right - userPadding.left, height);
+ } else {
+ setBoxDims(box, chartArea.left + stack.placed, y, width, height);
+ }
+ stack.start = y;
+ stack.placed += width;
+ y = box.bottom;
+ } else {
+ const height = chartArea.h * weight;
+ const width = stack.size || box.width;
+ if (defined(stack.start)) {
+ x = stack.start;
+ }
+ if (box.fullSize) {
+ setBoxDims(box, x, userPadding.top, width, params.outerHeight - userPadding.bottom - userPadding.top);
+ } else {
+ setBoxDims(box, x, chartArea.top + stack.placed, width, height);
+ }
+ stack.start = x;
+ stack.placed += height;
+ x = box.right;
+ }
+ }
+ chartArea.x = x;
+ chartArea.y = y;
+}
+defaults.set('layout', {
+ autoPadding: true,
+ padding: {
+ top: 0,
+ right: 0,
+ bottom: 0,
+ left: 0
+ }
+});
+var layouts = {
+ addBox(chart, item) {
+ if (!chart.boxes) {
+ chart.boxes = [];
+ }
+ item.fullSize = item.fullSize || false;
+ item.position = item.position || 'top';
+ item.weight = item.weight || 0;
+ item._layers = item._layers || function() {
+ return [{
+ z: 0,
+ draw(chartArea) {
+ item.draw(chartArea);
+ }
+ }];
+ };
+ chart.boxes.push(item);
+ },
+ removeBox(chart, layoutItem) {
+ const index = chart.boxes ? chart.boxes.indexOf(layoutItem) : -1;
+ if (index !== -1) {
+ chart.boxes.splice(index, 1);
+ }
+ },
+ configure(chart, item, options) {
+ item.fullSize = options.fullSize;
+ item.position = options.position;
+ item.weight = options.weight;
+ },
+ update(chart, width, height, minPadding) {
+ if (!chart) {
+ return;
+ }
+ const padding = toPadding(chart.options.layout.padding);
+ const availableWidth = Math.max(width - padding.width, 0);
+ const availableHeight = Math.max(height - padding.height, 0);
+ const boxes = buildLayoutBoxes(chart.boxes);
+ const verticalBoxes = boxes.vertical;
+ const horizontalBoxes = boxes.horizontal;
+ each(chart.boxes, box => {
+ if (typeof box.beforeLayout === 'function') {
+ box.beforeLayout();
+ }
+ });
+ const visibleVerticalBoxCount = verticalBoxes.reduce((total, wrap) =>
+ wrap.box.options && wrap.box.options.display === false ? total : total + 1, 0) || 1;
+ const params = Object.freeze({
+ outerWidth: width,
+ outerHeight: height,
+ padding,
+ availableWidth,
+ availableHeight,
+ vBoxMaxWidth: availableWidth / 2 / visibleVerticalBoxCount,
+ hBoxMaxHeight: availableHeight / 2
+ });
+ const maxPadding = Object.assign({}, padding);
+ updateMaxPadding(maxPadding, toPadding(minPadding));
+ const chartArea = Object.assign({
+ maxPadding,
+ w: availableWidth,
+ h: availableHeight,
+ x: padding.left,
+ y: padding.top
+ }, padding);
+ const stacks = setLayoutDims(verticalBoxes.concat(horizontalBoxes), params);
+ fitBoxes(boxes.fullSize, chartArea, params, stacks);
+ fitBoxes(verticalBoxes, chartArea, params, stacks);
+ if (fitBoxes(horizontalBoxes, chartArea, params, stacks)) {
+ fitBoxes(verticalBoxes, chartArea, params, stacks);
+ }
+ handleMaxPadding(chartArea);
+ placeBoxes(boxes.leftAndTop, chartArea, params, stacks);
+ chartArea.x += chartArea.w;
+ chartArea.y += chartArea.h;
+ placeBoxes(boxes.rightAndBottom, chartArea, params, stacks);
+ chart.chartArea = {
+ left: chartArea.left,
+ top: chartArea.top,
+ right: chartArea.left + chartArea.w,
+ bottom: chartArea.top + chartArea.h,
+ height: chartArea.h,
+ width: chartArea.w,
+ };
+ each(boxes.chartArea, (layout) => {
+ const box = layout.box;
+ Object.assign(box, chart.chartArea);
+ box.update(chartArea.w, chartArea.h);
+ });
+ }
+};
+
+function _createResolver(scopes, prefixes = [''], rootScopes = scopes, fallback, getTarget = () => scopes[0]) {
+ if (!defined(fallback)) {
+ fallback = _resolve('_fallback', scopes);
+ }
+ const cache = {
+ [Symbol.toStringTag]: 'Object',
+ _cacheable: true,
+ _scopes: scopes,
+ _rootScopes: rootScopes,
+ _fallback: fallback,
+ _getTarget: getTarget,
+ override: (scope) => _createResolver([scope, ...scopes], prefixes, rootScopes, fallback),
+ };
+ return new Proxy(cache, {
+ deleteProperty(target, prop) {
+ delete target[prop];
+ delete target._keys;
+ delete scopes[0][prop];
+ return true;
+ },
+ get(target, prop) {
+ return _cached(target, prop,
+ () => _resolveWithPrefixes(prop, prefixes, scopes, target));
+ },
+ getOwnPropertyDescriptor(target, prop) {
+ return Reflect.getOwnPropertyDescriptor(target._scopes[0], prop);
+ },
+ getPrototypeOf() {
+ return Reflect.getPrototypeOf(scopes[0]);
+ },
+ has(target, prop) {
+ return getKeysFromAllScopes(target).includes(prop);
+ },
+ ownKeys(target) {
+ return getKeysFromAllScopes(target);
+ },
+ set(target, prop, value) {
+ const storage = target._storage || (target._storage = getTarget());
+ storage[prop] = value;
+ delete target[prop];
+ delete target._keys;
+ return true;
+ }
+ });
+}
+function _attachContext(proxy, context, subProxy, descriptorDefaults) {
+ const cache = {
+ _cacheable: false,
+ _proxy: proxy,
+ _context: context,
+ _subProxy: subProxy,
+ _stack: new Set(),
+ _descriptors: _descriptors(proxy, descriptorDefaults),
+ setContext: (ctx) => _attachContext(proxy, ctx, subProxy, descriptorDefaults),
+ override: (scope) => _attachContext(proxy.override(scope), context, subProxy, descriptorDefaults)
+ };
+ return new Proxy(cache, {
+ deleteProperty(target, prop) {
+ delete target[prop];
+ delete proxy[prop];
+ return true;
+ },
+ get(target, prop, receiver) {
+ return _cached(target, prop,
+ () => _resolveWithContext(target, prop, receiver));
+ },
+ getOwnPropertyDescriptor(target, prop) {
+ return target._descriptors.allKeys
+ ? Reflect.has(proxy, prop) ? {enumerable: true, configurable: true} : undefined
+ : Reflect.getOwnPropertyDescriptor(proxy, prop);
+ },
+ getPrototypeOf() {
+ return Reflect.getPrototypeOf(proxy);
+ },
+ has(target, prop) {
+ return Reflect.has(proxy, prop);
+ },
+ ownKeys() {
+ return Reflect.ownKeys(proxy);
+ },
+ set(target, prop, value) {
+ proxy[prop] = value;
+ delete target[prop];
+ return true;
+ }
+ });
+}
+function _descriptors(proxy, defaults = {scriptable: true, indexable: true}) {
+ const {_scriptable = defaults.scriptable, _indexable = defaults.indexable, _allKeys = defaults.allKeys} = proxy;
+ return {
+ allKeys: _allKeys,
+ scriptable: _scriptable,
+ indexable: _indexable,
+ isScriptable: isFunction(_scriptable) ? _scriptable : () => _scriptable,
+ isIndexable: isFunction(_indexable) ? _indexable : () => _indexable
+ };
+}
+const readKey = (prefix, name) => prefix ? prefix + _capitalize(name) : name;
+const needsSubResolver = (prop, value) => isObject(value) && prop !== 'adapters';
+function _cached(target, prop, resolve) {
+ if (Object.prototype.hasOwnProperty.call(target, prop)) {
+ return target[prop];
+ }
+ const value = resolve();
+ target[prop] = value;
+ return value;
+}
+function _resolveWithContext(target, prop, receiver) {
+ const {_proxy, _context, _subProxy, _descriptors: descriptors} = target;
+ let value = _proxy[prop];
+ if (isFunction(value) && descriptors.isScriptable(prop)) {
+ value = _resolveScriptable(prop, value, target, receiver);
+ }
+ if (isArray(value) && value.length) {
+ value = _resolveArray(prop, value, target, descriptors.isIndexable);
+ }
+ if (needsSubResolver(prop, value)) {
+ value = _attachContext(value, _context, _subProxy && _subProxy[prop], descriptors);
+ }
+ return value;
+}
+function _resolveScriptable(prop, value, target, receiver) {
+ const {_proxy, _context, _subProxy, _stack} = target;
+ if (_stack.has(prop)) {
+ throw new Error('Recursion detected: ' + Array.from(_stack).join('->') + '->' + prop);
+ }
+ _stack.add(prop);
+ value = value(_context, _subProxy || receiver);
+ _stack.delete(prop);
+ if (isObject(value)) {
+ value = createSubResolver(_proxy._scopes, _proxy, prop, value);
+ }
+ return value;
+}
+function _resolveArray(prop, value, target, isIndexable) {
+ const {_proxy, _context, _subProxy, _descriptors: descriptors} = target;
+ if (defined(_context.index) && isIndexable(prop)) {
+ value = value[_context.index % value.length];
+ } else if (isObject(value[0])) {
+ const arr = value;
+ const scopes = _proxy._scopes.filter(s => s !== arr);
+ value = [];
+ for (const item of arr) {
+ const resolver = createSubResolver(scopes, _proxy, prop, item);
+ value.push(_attachContext(resolver, _context, _subProxy && _subProxy[prop], descriptors));
+ }
+ }
+ return value;
+}
+function resolveFallback(fallback, prop, value) {
+ return isFunction(fallback) ? fallback(prop, value) : fallback;
+}
+const getScope = (key, parent) => key === true ? parent
+ : typeof key === 'string' ? resolveObjectKey(parent, key) : undefined;
+function addScopes(set, parentScopes, key, parentFallback) {
+ for (const parent of parentScopes) {
+ const scope = getScope(key, parent);
+ if (scope) {
+ set.add(scope);
+ const fallback = resolveFallback(scope._fallback, key, scope);
+ if (defined(fallback) && fallback !== key && fallback !== parentFallback) {
+ return fallback;
+ }
+ } else if (scope === false && defined(parentFallback) && key !== parentFallback) {
+ return null;
+ }
+ }
+ return false;
+}
+function createSubResolver(parentScopes, resolver, prop, value) {
+ const rootScopes = resolver._rootScopes;
+ const fallback = resolveFallback(resolver._fallback, prop, value);
+ const allScopes = [...parentScopes, ...rootScopes];
+ const set = new Set();
+ set.add(value);
+ let key = addScopesFromKey(set, allScopes, prop, fallback || prop);
+ if (key === null) {
+ return false;
+ }
+ if (defined(fallback) && fallback !== prop) {
+ key = addScopesFromKey(set, allScopes, fallback, key);
+ if (key === null) {
+ return false;
+ }
+ }
+ return _createResolver(Array.from(set), [''], rootScopes, fallback,
+ () => subGetTarget(resolver, prop, value));
+}
+function addScopesFromKey(set, allScopes, key, fallback) {
+ while (key) {
+ key = addScopes(set, allScopes, key, fallback);
+ }
+ return key;
+}
+function subGetTarget(resolver, prop, value) {
+ const parent = resolver._getTarget();
+ if (!(prop in parent)) {
+ parent[prop] = {};
+ }
+ const target = parent[prop];
+ if (isArray(target) && isObject(value)) {
+ return value;
+ }
+ return target;
+}
+function _resolveWithPrefixes(prop, prefixes, scopes, proxy) {
+ let value;
+ for (const prefix of prefixes) {
+ value = _resolve(readKey(prefix, prop), scopes);
+ if (defined(value)) {
+ return needsSubResolver(prop, value)
+ ? createSubResolver(scopes, proxy, prop, value)
+ : value;
+ }
+ }
+}
+function _resolve(key, scopes) {
+ for (const scope of scopes) {
+ if (!scope) {
+ continue;
+ }
+ const value = scope[key];
+ if (defined(value)) {
+ return value;
+ }
+ }
+}
+function getKeysFromAllScopes(target) {
+ let keys = target._keys;
+ if (!keys) {
+ keys = target._keys = resolveKeysFromAllScopes(target._scopes);
+ }
+ return keys;
+}
+function resolveKeysFromAllScopes(scopes) {
+ const set = new Set();
+ for (const scope of scopes) {
+ for (const key of Object.keys(scope).filter(k => !k.startsWith('_'))) {
+ set.add(key);
+ }
+ }
+ return Array.from(set);
+}
+
+const EPSILON = Number.EPSILON || 1e-14;
+const getPoint = (points, i) => i < points.length && !points[i].skip && points[i];
+const getValueAxis = (indexAxis) => indexAxis === 'x' ? 'y' : 'x';
+function splineCurve(firstPoint, middlePoint, afterPoint, t) {
+ const previous = firstPoint.skip ? middlePoint : firstPoint;
+ const current = middlePoint;
+ const next = afterPoint.skip ? middlePoint : afterPoint;
+ const d01 = distanceBetweenPoints(current, previous);
+ const d12 = distanceBetweenPoints(next, current);
+ let s01 = d01 / (d01 + d12);
+ let s12 = d12 / (d01 + d12);
+ s01 = isNaN(s01) ? 0 : s01;
+ s12 = isNaN(s12) ? 0 : s12;
+ const fa = t * s01;
+ const fb = t * s12;
+ return {
+ previous: {
+ x: current.x - fa * (next.x - previous.x),
+ y: current.y - fa * (next.y - previous.y)
+ },
+ next: {
+ x: current.x + fb * (next.x - previous.x),
+ y: current.y + fb * (next.y - previous.y)
+ }
+ };
+}
+function monotoneAdjust(points, deltaK, mK) {
+ const pointsLen = points.length;
+ let alphaK, betaK, tauK, squaredMagnitude, pointCurrent;
+ let pointAfter = getPoint(points, 0);
+ for (let i = 0; i < pointsLen - 1; ++i) {
+ pointCurrent = pointAfter;
+ pointAfter = getPoint(points, i + 1);
+ if (!pointCurrent || !pointAfter) {
+ continue;
+ }
+ if (almostEquals(deltaK[i], 0, EPSILON)) {
+ mK[i] = mK[i + 1] = 0;
+ continue;
+ }
+ alphaK = mK[i] / deltaK[i];
+ betaK = mK[i + 1] / deltaK[i];
+ squaredMagnitude = Math.pow(alphaK, 2) + Math.pow(betaK, 2);
+ if (squaredMagnitude <= 9) {
+ continue;
+ }
+ tauK = 3 / Math.sqrt(squaredMagnitude);
+ mK[i] = alphaK * tauK * deltaK[i];
+ mK[i + 1] = betaK * tauK * deltaK[i];
+ }
+}
+function monotoneCompute(points, mK, indexAxis = 'x') {
+ const valueAxis = getValueAxis(indexAxis);
+ const pointsLen = points.length;
+ let delta, pointBefore, pointCurrent;
+ let pointAfter = getPoint(points, 0);
+ for (let i = 0; i < pointsLen; ++i) {
+ pointBefore = pointCurrent;
+ pointCurrent = pointAfter;
+ pointAfter = getPoint(points, i + 1);
+ if (!pointCurrent) {
+ continue;
+ }
+ const iPixel = pointCurrent[indexAxis];
+ const vPixel = pointCurrent[valueAxis];
+ if (pointBefore) {
+ delta = (iPixel - pointBefore[indexAxis]) / 3;
+ pointCurrent[`cp1${indexAxis}`] = iPixel - delta;
+ pointCurrent[`cp1${valueAxis}`] = vPixel - delta * mK[i];
+ }
+ if (pointAfter) {
+ delta = (pointAfter[indexAxis] - iPixel) / 3;
+ pointCurrent[`cp2${indexAxis}`] = iPixel + delta;
+ pointCurrent[`cp2${valueAxis}`] = vPixel + delta * mK[i];
+ }
+ }
+}
+function splineCurveMonotone(points, indexAxis = 'x') {
+ const valueAxis = getValueAxis(indexAxis);
+ const pointsLen = points.length;
+ const deltaK = Array(pointsLen).fill(0);
+ const mK = Array(pointsLen);
+ let i, pointBefore, pointCurrent;
+ let pointAfter = getPoint(points, 0);
+ for (i = 0; i < pointsLen; ++i) {
+ pointBefore = pointCurrent;
+ pointCurrent = pointAfter;
+ pointAfter = getPoint(points, i + 1);
+ if (!pointCurrent) {
+ continue;
+ }
+ if (pointAfter) {
+ const slopeDelta = pointAfter[indexAxis] - pointCurrent[indexAxis];
+ deltaK[i] = slopeDelta !== 0 ? (pointAfter[valueAxis] - pointCurrent[valueAxis]) / slopeDelta : 0;
+ }
+ mK[i] = !pointBefore ? deltaK[i]
+ : !pointAfter ? deltaK[i - 1]
+ : (sign(deltaK[i - 1]) !== sign(deltaK[i])) ? 0
+ : (deltaK[i - 1] + deltaK[i]) / 2;
+ }
+ monotoneAdjust(points, deltaK, mK);
+ monotoneCompute(points, mK, indexAxis);
+}
+function capControlPoint(pt, min, max) {
+ return Math.max(Math.min(pt, max), min);
+}
+function capBezierPoints(points, area) {
+ let i, ilen, point, inArea, inAreaPrev;
+ let inAreaNext = _isPointInArea(points[0], area);
+ for (i = 0, ilen = points.length; i < ilen; ++i) {
+ inAreaPrev = inArea;
+ inArea = inAreaNext;
+ inAreaNext = i < ilen - 1 && _isPointInArea(points[i + 1], area);
+ if (!inArea) {
+ continue;
+ }
+ point = points[i];
+ if (inAreaPrev) {
+ point.cp1x = capControlPoint(point.cp1x, area.left, area.right);
+ point.cp1y = capControlPoint(point.cp1y, area.top, area.bottom);
+ }
+ if (inAreaNext) {
+ point.cp2x = capControlPoint(point.cp2x, area.left, area.right);
+ point.cp2y = capControlPoint(point.cp2y, area.top, area.bottom);
+ }
+ }
+}
+function _updateBezierControlPoints(points, options, area, loop, indexAxis) {
+ let i, ilen, point, controlPoints;
+ if (options.spanGaps) {
+ points = points.filter((pt) => !pt.skip);
+ }
+ if (options.cubicInterpolationMode === 'monotone') {
+ splineCurveMonotone(points, indexAxis);
+ } else {
+ let prev = loop ? points[points.length - 1] : points[0];
+ for (i = 0, ilen = points.length; i < ilen; ++i) {
+ point = points[i];
+ controlPoints = splineCurve(
+ prev,
+ point,
+ points[Math.min(i + 1, ilen - (loop ? 0 : 1)) % ilen],
+ options.tension
+ );
+ point.cp1x = controlPoints.previous.x;
+ point.cp1y = controlPoints.previous.y;
+ point.cp2x = controlPoints.next.x;
+ point.cp2y = controlPoints.next.y;
+ prev = point;
+ }
+ }
+ if (options.capBezierPoints) {
+ capBezierPoints(points, area);
+ }
+}
+
+const atEdge = (t) => t === 0 || t === 1;
+const elasticIn = (t, s, p) => -(Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * TAU / p));
+const elasticOut = (t, s, p) => Math.pow(2, -10 * t) * Math.sin((t - s) * TAU / p) + 1;
+const effects = {
+ linear: t => t,
+ easeInQuad: t => t * t,
+ easeOutQuad: t => -t * (t - 2),
+ easeInOutQuad: t => ((t /= 0.5) < 1)
+ ? 0.5 * t * t
+ : -0.5 * ((--t) * (t - 2) - 1),
+ easeInCubic: t => t * t * t,
+ easeOutCubic: t => (t -= 1) * t * t + 1,
+ easeInOutCubic: t => ((t /= 0.5) < 1)
+ ? 0.5 * t * t * t
+ : 0.5 * ((t -= 2) * t * t + 2),
+ easeInQuart: t => t * t * t * t,
+ easeOutQuart: t => -((t -= 1) * t * t * t - 1),
+ easeInOutQuart: t => ((t /= 0.5) < 1)
+ ? 0.5 * t * t * t * t
+ : -0.5 * ((t -= 2) * t * t * t - 2),
+ easeInQuint: t => t * t * t * t * t,
+ easeOutQuint: t => (t -= 1) * t * t * t * t + 1,
+ easeInOutQuint: t => ((t /= 0.5) < 1)
+ ? 0.5 * t * t * t * t * t
+ : 0.5 * ((t -= 2) * t * t * t * t + 2),
+ easeInSine: t => -Math.cos(t * HALF_PI) + 1,
+ easeOutSine: t => Math.sin(t * HALF_PI),
+ easeInOutSine: t => -0.5 * (Math.cos(PI * t) - 1),
+ easeInExpo: t => (t === 0) ? 0 : Math.pow(2, 10 * (t - 1)),
+ easeOutExpo: t => (t === 1) ? 1 : -Math.pow(2, -10 * t) + 1,
+ easeInOutExpo: t => atEdge(t) ? t : t < 0.5
+ ? 0.5 * Math.pow(2, 10 * (t * 2 - 1))
+ : 0.5 * (-Math.pow(2, -10 * (t * 2 - 1)) + 2),
+ easeInCirc: t => (t >= 1) ? t : -(Math.sqrt(1 - t * t) - 1),
+ easeOutCirc: t => Math.sqrt(1 - (t -= 1) * t),
+ easeInOutCirc: t => ((t /= 0.5) < 1)
+ ? -0.5 * (Math.sqrt(1 - t * t) - 1)
+ : 0.5 * (Math.sqrt(1 - (t -= 2) * t) + 1),
+ easeInElastic: t => atEdge(t) ? t : elasticIn(t, 0.075, 0.3),
+ easeOutElastic: t => atEdge(t) ? t : elasticOut(t, 0.075, 0.3),
+ easeInOutElastic(t) {
+ const s = 0.1125;
+ const p = 0.45;
+ return atEdge(t) ? t :
+ t < 0.5
+ ? 0.5 * elasticIn(t * 2, s, p)
+ : 0.5 + 0.5 * elasticOut(t * 2 - 1, s, p);
+ },
+ easeInBack(t) {
+ const s = 1.70158;
+ return t * t * ((s + 1) * t - s);
+ },
+ easeOutBack(t) {
+ const s = 1.70158;
+ return (t -= 1) * t * ((s + 1) * t + s) + 1;
+ },
+ easeInOutBack(t) {
+ let s = 1.70158;
+ if ((t /= 0.5) < 1) {
+ return 0.5 * (t * t * (((s *= (1.525)) + 1) * t - s));
+ }
+ return 0.5 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2);
+ },
+ easeInBounce: t => 1 - effects.easeOutBounce(1 - t),
+ easeOutBounce(t) {
+ const m = 7.5625;
+ const d = 2.75;
+ if (t < (1 / d)) {
+ return m * t * t;
+ }
+ if (t < (2 / d)) {
+ return m * (t -= (1.5 / d)) * t + 0.75;
+ }
+ if (t < (2.5 / d)) {
+ return m * (t -= (2.25 / d)) * t + 0.9375;
+ }
+ return m * (t -= (2.625 / d)) * t + 0.984375;
+ },
+ easeInOutBounce: t => (t < 0.5)
+ ? effects.easeInBounce(t * 2) * 0.5
+ : effects.easeOutBounce(t * 2 - 1) * 0.5 + 0.5,
+};
+
+function _pointInLine(p1, p2, t, mode) {
+ return {
+ x: p1.x + t * (p2.x - p1.x),
+ y: p1.y + t * (p2.y - p1.y)
+ };
+}
+function _steppedInterpolation(p1, p2, t, mode) {
+ return {
+ x: p1.x + t * (p2.x - p1.x),
+ y: mode === 'middle' ? t < 0.5 ? p1.y : p2.y
+ : mode === 'after' ? t < 1 ? p1.y : p2.y
+ : t > 0 ? p2.y : p1.y
+ };
+}
+function _bezierInterpolation(p1, p2, t, mode) {
+ const cp1 = {x: p1.cp2x, y: p1.cp2y};
+ const cp2 = {x: p2.cp1x, y: p2.cp1y};
+ const a = _pointInLine(p1, cp1, t);
+ const b = _pointInLine(cp1, cp2, t);
+ const c = _pointInLine(cp2, p2, t);
+ const d = _pointInLine(a, b, t);
+ const e = _pointInLine(b, c, t);
+ return _pointInLine(d, e, t);
+}
+
+const intlCache = new Map();
+function getNumberFormat(locale, options) {
+ options = options || {};
+ const cacheKey = locale + JSON.stringify(options);
+ let formatter = intlCache.get(cacheKey);
+ if (!formatter) {
+ formatter = new Intl.NumberFormat(locale, options);
+ intlCache.set(cacheKey, formatter);
+ }
+ return formatter;
+}
+function formatNumber(num, locale, options) {
+ return getNumberFormat(locale, options).format(num);
+}
+
+const getRightToLeftAdapter = function(rectX, width) {
+ return {
+ x(x) {
+ return rectX + rectX + width - x;
+ },
+ setWidth(w) {
+ width = w;
+ },
+ textAlign(align) {
+ if (align === 'center') {
+ return align;
+ }
+ return align === 'right' ? 'left' : 'right';
+ },
+ xPlus(x, value) {
+ return x - value;
+ },
+ leftForLtr(x, itemWidth) {
+ return x - itemWidth;
+ },
+ };
+};
+const getLeftToRightAdapter = function() {
+ return {
+ x(x) {
+ return x;
+ },
+ setWidth(w) {
+ },
+ textAlign(align) {
+ return align;
+ },
+ xPlus(x, value) {
+ return x + value;
+ },
+ leftForLtr(x, _itemWidth) {
+ return x;
+ },
+ };
+};
+function getRtlAdapter(rtl, rectX, width) {
+ return rtl ? getRightToLeftAdapter(rectX, width) : getLeftToRightAdapter();
+}
+function overrideTextDirection(ctx, direction) {
+ let style, original;
+ if (direction === 'ltr' || direction === 'rtl') {
+ style = ctx.canvas.style;
+ original = [
+ style.getPropertyValue('direction'),
+ style.getPropertyPriority('direction'),
+ ];
+ style.setProperty('direction', direction, 'important');
+ ctx.prevTextDirection = original;
+ }
+}
+function restoreTextDirection(ctx, original) {
+ if (original !== undefined) {
+ delete ctx.prevTextDirection;
+ ctx.canvas.style.setProperty('direction', original[0], original[1]);
+ }
+}
+
+function propertyFn(property) {
+ if (property === 'angle') {
+ return {
+ between: _angleBetween,
+ compare: _angleDiff,
+ normalize: _normalizeAngle,
+ };
+ }
+ return {
+ between: (n, s, e) => n >= Math.min(s, e) && n <= Math.max(e, s),
+ compare: (a, b) => a - b,
+ normalize: x => x
+ };
+}
+function normalizeSegment({start, end, count, loop, style}) {
+ return {
+ start: start % count,
+ end: end % count,
+ loop: loop && (end - start + 1) % count === 0,
+ style
+ };
+}
+function getSegment(segment, points, bounds) {
+ const {property, start: startBound, end: endBound} = bounds;
+ const {between, normalize} = propertyFn(property);
+ const count = points.length;
+ let {start, end, loop} = segment;
+ let i, ilen;
+ if (loop) {
+ start += count;
+ end += count;
+ for (i = 0, ilen = count; i < ilen; ++i) {
+ if (!between(normalize(points[start % count][property]), startBound, endBound)) {
+ break;
+ }
+ start--;
+ end--;
+ }
+ start %= count;
+ end %= count;
+ }
+ if (end < start) {
+ end += count;
+ }
+ return {start, end, loop, style: segment.style};
+}
+function _boundSegment(segment, points, bounds) {
+ if (!bounds) {
+ return [segment];
+ }
+ const {property, start: startBound, end: endBound} = bounds;
+ const count = points.length;
+ const {compare, between, normalize} = propertyFn(property);
+ const {start, end, loop, style} = getSegment(segment, points, bounds);
+ const result = [];
+ let inside = false;
+ let subStart = null;
+ let value, point, prevValue;
+ const startIsBefore = () => between(startBound, prevValue, value) && compare(startBound, prevValue) !== 0;
+ const endIsBefore = () => compare(endBound, value) === 0 || between(endBound, prevValue, value);
+ const shouldStart = () => inside || startIsBefore();
+ const shouldStop = () => !inside || endIsBefore();
+ for (let i = start, prev = start; i <= end; ++i) {
+ point = points[i % count];
+ if (point.skip) {
+ continue;
+ }
+ value = normalize(point[property]);
+ if (value === prevValue) {
+ continue;
+ }
+ inside = between(value, startBound, endBound);
+ if (subStart === null && shouldStart()) {
+ subStart = compare(value, startBound) === 0 ? i : prev;
+ }
+ if (subStart !== null && shouldStop()) {
+ result.push(normalizeSegment({start: subStart, end: i, loop, count, style}));
+ subStart = null;
+ }
+ prev = i;
+ prevValue = value;
+ }
+ if (subStart !== null) {
+ result.push(normalizeSegment({start: subStart, end, loop, count, style}));
+ }
+ return result;
+}
+function _boundSegments(line, bounds) {
+ const result = [];
+ const segments = line.segments;
+ for (let i = 0; i < segments.length; i++) {
+ const sub = _boundSegment(segments[i], line.points, bounds);
+ if (sub.length) {
+ result.push(...sub);
+ }
+ }
+ return result;
+}
+function findStartAndEnd(points, count, loop, spanGaps) {
+ let start = 0;
+ let end = count - 1;
+ if (loop && !spanGaps) {
+ while (start < count && !points[start].skip) {
+ start++;
+ }
+ }
+ while (start < count && points[start].skip) {
+ start++;
+ }
+ start %= count;
+ if (loop) {
+ end += start;
+ }
+ while (end > start && points[end % count].skip) {
+ end--;
+ }
+ end %= count;
+ return {start, end};
+}
+function solidSegments(points, start, max, loop) {
+ const count = points.length;
+ const result = [];
+ let last = start;
+ let prev = points[start];
+ let end;
+ for (end = start + 1; end <= max; ++end) {
+ const cur = points[end % count];
+ if (cur.skip || cur.stop) {
+ if (!prev.skip) {
+ loop = false;
+ result.push({start: start % count, end: (end - 1) % count, loop});
+ start = last = cur.stop ? end : null;
+ }
+ } else {
+ last = end;
+ if (prev.skip) {
+ start = end;
+ }
+ }
+ prev = cur;
+ }
+ if (last !== null) {
+ result.push({start: start % count, end: last % count, loop});
+ }
+ return result;
+}
+function _computeSegments(line, segmentOptions) {
+ const points = line.points;
+ const spanGaps = line.options.spanGaps;
+ const count = points.length;
+ if (!count) {
+ return [];
+ }
+ const loop = !!line._loop;
+ const {start, end} = findStartAndEnd(points, count, loop, spanGaps);
+ if (spanGaps === true) {
+ return splitByStyles(line, [{start, end, loop}], points, segmentOptions);
+ }
+ const max = end < start ? end + count : end;
+ const completeLoop = !!line._fullLoop && start === 0 && end === count - 1;
+ return splitByStyles(line, solidSegments(points, start, max, completeLoop), points, segmentOptions);
+}
+function splitByStyles(line, segments, points, segmentOptions) {
+ if (!segmentOptions || !segmentOptions.setContext || !points) {
+ return segments;
+ }
+ return doSplitByStyles(line, segments, points, segmentOptions);
+}
+function doSplitByStyles(line, segments, points, segmentOptions) {
+ const chartContext = line._chart.getContext();
+ const baseStyle = readStyle(line.options);
+ const {_datasetIndex: datasetIndex, options: {spanGaps}} = line;
+ const count = points.length;
+ const result = [];
+ let prevStyle = baseStyle;
+ let start = segments[0].start;
+ let i = start;
+ function addStyle(s, e, l, st) {
+ const dir = spanGaps ? -1 : 1;
+ if (s === e) {
+ return;
+ }
+ s += count;
+ while (points[s % count].skip) {
+ s -= dir;
+ }
+ while (points[e % count].skip) {
+ e += dir;
+ }
+ if (s % count !== e % count) {
+ result.push({start: s % count, end: e % count, loop: l, style: st});
+ prevStyle = st;
+ start = e % count;
+ }
+ }
+ for (const segment of segments) {
+ start = spanGaps ? start : segment.start;
+ let prev = points[start % count];
+ let style;
+ for (i = start + 1; i <= segment.end; i++) {
+ const pt = points[i % count];
+ style = readStyle(segmentOptions.setContext(createContext(chartContext, {
+ type: 'segment',
+ p0: prev,
+ p1: pt,
+ p0DataIndex: (i - 1) % count,
+ p1DataIndex: i % count,
+ datasetIndex
+ })));
+ if (styleChanged(style, prevStyle)) {
+ addStyle(start, i - 1, segment.loop, prevStyle);
+ }
+ prev = pt;
+ prevStyle = style;
+ }
+ if (start < i - 1) {
+ addStyle(start, i - 1, segment.loop, prevStyle);
+ }
+ }
+ return result;
+}
+function readStyle(options) {
+ return {
+ backgroundColor: options.backgroundColor,
+ borderCapStyle: options.borderCapStyle,
+ borderDash: options.borderDash,
+ borderDashOffset: options.borderDashOffset,
+ borderJoinStyle: options.borderJoinStyle,
+ borderWidth: options.borderWidth,
+ borderColor: options.borderColor
+ };
+}
+function styleChanged(style, prevStyle) {
+ return prevStyle && JSON.stringify(style) !== JSON.stringify(prevStyle);
+}
+
+var helpers = /*#__PURE__*/Object.freeze({
+__proto__: null,
+easingEffects: effects,
+color: color,
+getHoverColor: getHoverColor,
+noop: noop,
+uid: uid,
+isNullOrUndef: isNullOrUndef,
+isArray: isArray,
+isObject: isObject,
+isFinite: isNumberFinite,
+finiteOrDefault: finiteOrDefault,
+valueOrDefault: valueOrDefault,
+toPercentage: toPercentage,
+toDimension: toDimension,
+callback: callback,
+each: each,
+_elementsEqual: _elementsEqual,
+clone: clone,
+_merger: _merger,
+merge: merge,
+mergeIf: mergeIf,
+_mergerIf: _mergerIf,
+_deprecated: _deprecated,
+resolveObjectKey: resolveObjectKey,
+_capitalize: _capitalize,
+defined: defined,
+isFunction: isFunction,
+setsEqual: setsEqual,
+toFontString: toFontString,
+_measureText: _measureText,
+_longestText: _longestText,
+_alignPixel: _alignPixel,
+clearCanvas: clearCanvas,
+drawPoint: drawPoint,
+_isPointInArea: _isPointInArea,
+clipArea: clipArea,
+unclipArea: unclipArea,
+_steppedLineTo: _steppedLineTo,
+_bezierCurveTo: _bezierCurveTo,
+renderText: renderText,
+addRoundedRectPath: addRoundedRectPath,
+_lookup: _lookup,
+_lookupByKey: _lookupByKey,
+_rlookupByKey: _rlookupByKey,
+_filterBetween: _filterBetween,
+listenArrayEvents: listenArrayEvents,
+unlistenArrayEvents: unlistenArrayEvents,
+_arrayUnique: _arrayUnique,
+_createResolver: _createResolver,
+_attachContext: _attachContext,
+_descriptors: _descriptors,
+splineCurve: splineCurve,
+splineCurveMonotone: splineCurveMonotone,
+_updateBezierControlPoints: _updateBezierControlPoints,
+_isDomSupported: _isDomSupported,
+_getParentNode: _getParentNode,
+getStyle: getStyle,
+getRelativePosition: getRelativePosition$1,
+getMaximumSize: getMaximumSize,
+retinaScale: retinaScale,
+supportsEventListenerOptions: supportsEventListenerOptions,
+readUsedSize: readUsedSize,
+fontString: fontString,
+requestAnimFrame: requestAnimFrame,
+throttled: throttled,
+debounce: debounce,
+_toLeftRightCenter: _toLeftRightCenter,
+_alignStartEnd: _alignStartEnd,
+_textX: _textX,
+_pointInLine: _pointInLine,
+_steppedInterpolation: _steppedInterpolation,
+_bezierInterpolation: _bezierInterpolation,
+formatNumber: formatNumber,
+toLineHeight: toLineHeight,
+_readValueToProps: _readValueToProps,
+toTRBL: toTRBL,
+toTRBLCorners: toTRBLCorners,
+toPadding: toPadding,
+toFont: toFont,
+resolve: resolve,
+_addGrace: _addGrace,
+createContext: createContext,
+PI: PI,
+TAU: TAU,
+PITAU: PITAU,
+INFINITY: INFINITY,
+RAD_PER_DEG: RAD_PER_DEG,
+HALF_PI: HALF_PI,
+QUARTER_PI: QUARTER_PI,
+TWO_THIRDS_PI: TWO_THIRDS_PI,
+log10: log10,
+sign: sign,
+niceNum: niceNum,
+_factorize: _factorize,
+isNumber: isNumber,
+almostEquals: almostEquals,
+almostWhole: almostWhole,
+_setMinAndMaxByKey: _setMinAndMaxByKey,
+toRadians: toRadians,
+toDegrees: toDegrees,
+_decimalPlaces: _decimalPlaces,
+getAngleFromPoint: getAngleFromPoint,
+distanceBetweenPoints: distanceBetweenPoints,
+_angleDiff: _angleDiff,
+_normalizeAngle: _normalizeAngle,
+_angleBetween: _angleBetween,
+_limitValue: _limitValue,
+_int16Range: _int16Range,
+getRtlAdapter: getRtlAdapter,
+overrideTextDirection: overrideTextDirection,
+restoreTextDirection: restoreTextDirection,
+_boundSegment: _boundSegment,
+_boundSegments: _boundSegments,
+_computeSegments: _computeSegments
+});
+
+class BasePlatform {
+ acquireContext(canvas, aspectRatio) {}
+ releaseContext(context) {
+ return false;
+ }
+ addEventListener(chart, type, listener) {}
+ removeEventListener(chart, type, listener) {}
+ getDevicePixelRatio() {
+ return 1;
+ }
+ getMaximumSize(element, width, height, aspectRatio) {
+ width = Math.max(0, width || element.width);
+ height = height || element.height;
+ return {
+ width,
+ height: Math.max(0, aspectRatio ? Math.floor(width / aspectRatio) : height)
+ };
+ }
+ isAttached(canvas) {
+ return true;
+ }
+ updateConfig(config) {
+ }
+}
+
+class BasicPlatform extends BasePlatform {
+ acquireContext(item) {
+ return item && item.getContext && item.getContext('2d') || null;
+ }
+ updateConfig(config) {
+ config.options.animation = false;
+ }
+}
+
+const EXPANDO_KEY = '$chartjs';
+const EVENT_TYPES = {
+ touchstart: 'mousedown',
+ touchmove: 'mousemove',
+ touchend: 'mouseup',
+ pointerenter: 'mouseenter',
+ pointerdown: 'mousedown',
+ pointermove: 'mousemove',
+ pointerup: 'mouseup',
+ pointerleave: 'mouseout',
+ pointerout: 'mouseout'
+};
+const isNullOrEmpty = value => value === null || value === '';
+function initCanvas(canvas, aspectRatio) {
+ const style = canvas.style;
+ const renderHeight = canvas.getAttribute('height');
+ const renderWidth = canvas.getAttribute('width');
+ canvas[EXPANDO_KEY] = {
+ initial: {
+ height: renderHeight,
+ width: renderWidth,
+ style: {
+ display: style.display,
+ height: style.height,
+ width: style.width
+ }
+ }
+ };
+ style.display = style.display || 'block';
+ style.boxSizing = style.boxSizing || 'border-box';
+ if (isNullOrEmpty(renderWidth)) {
+ const displayWidth = readUsedSize(canvas, 'width');
+ if (displayWidth !== undefined) {
+ canvas.width = displayWidth;
+ }
+ }
+ if (isNullOrEmpty(renderHeight)) {
+ if (canvas.style.height === '') {
+ canvas.height = canvas.width / (aspectRatio || 2);
+ } else {
+ const displayHeight = readUsedSize(canvas, 'height');
+ if (displayHeight !== undefined) {
+ canvas.height = displayHeight;
+ }
+ }
+ }
+ return canvas;
+}
+const eventListenerOptions = supportsEventListenerOptions ? {passive: true} : false;
+function addListener(node, type, listener) {
+ node.addEventListener(type, listener, eventListenerOptions);
+}
+function removeListener(chart, type, listener) {
+ chart.canvas.removeEventListener(type, listener, eventListenerOptions);
+}
+function fromNativeEvent(event, chart) {
+ const type = EVENT_TYPES[event.type] || event.type;
+ const {x, y} = getRelativePosition$1(event, chart);
+ return {
+ type,
+ chart,
+ native: event,
+ x: x !== undefined ? x : null,
+ y: y !== undefined ? y : null,
+ };
+}
+function createAttachObserver(chart, type, listener) {
+ const canvas = chart.canvas;
+ const observer = new MutationObserver(entries => {
+ for (const entry of entries) {
+ for (const node of entry.addedNodes) {
+ if (node === canvas || node.contains(canvas)) {
+ return listener();
+ }
+ }
+ }
+ });
+ observer.observe(document, {childList: true, subtree: true});
+ return observer;
+}
+function createDetachObserver(chart, type, listener) {
+ const canvas = chart.canvas;
+ const observer = new MutationObserver(entries => {
+ for (const entry of entries) {
+ for (const node of entry.removedNodes) {
+ if (node === canvas || node.contains(canvas)) {
+ return listener();
+ }
+ }
+ }
+ });
+ observer.observe(document, {childList: true, subtree: true});
+ return observer;
+}
+const drpListeningCharts = new Map();
+let oldDevicePixelRatio = 0;
+function onWindowResize() {
+ const dpr = window.devicePixelRatio;
+ if (dpr === oldDevicePixelRatio) {
+ return;
+ }
+ oldDevicePixelRatio = dpr;
+ drpListeningCharts.forEach((resize, chart) => {
+ if (chart.currentDevicePixelRatio !== dpr) {
+ resize();
+ }
+ });
+}
+function listenDevicePixelRatioChanges(chart, resize) {
+ if (!drpListeningCharts.size) {
+ window.addEventListener('resize', onWindowResize);
+ }
+ drpListeningCharts.set(chart, resize);
+}
+function unlistenDevicePixelRatioChanges(chart) {
+ drpListeningCharts.delete(chart);
+ if (!drpListeningCharts.size) {
+ window.removeEventListener('resize', onWindowResize);
+ }
+}
+function createResizeObserver(chart, type, listener) {
+ const canvas = chart.canvas;
+ const container = canvas && _getParentNode(canvas);
+ if (!container) {
+ return;
+ }
+ const resize = throttled((width, height) => {
+ const w = container.clientWidth;
+ listener(width, height);
+ if (w < container.clientWidth) {
+ listener();
+ }
+ }, window);
+ const observer = new ResizeObserver(entries => {
+ const entry = entries[0];
+ const width = entry.contentRect.width;
+ const height = entry.contentRect.height;
+ if (width === 0 && height === 0) {
+ return;
+ }
+ resize(width, height);
+ });
+ observer.observe(container);
+ listenDevicePixelRatioChanges(chart, resize);
+ return observer;
+}
+function releaseObserver(chart, type, observer) {
+ if (observer) {
+ observer.disconnect();
+ }
+ if (type === 'resize') {
+ unlistenDevicePixelRatioChanges(chart);
+ }
+}
+function createProxyAndListen(chart, type, listener) {
+ const canvas = chart.canvas;
+ const proxy = throttled((event) => {
+ if (chart.ctx !== null) {
+ listener(fromNativeEvent(event, chart));
+ }
+ }, chart, (args) => {
+ const event = args[0];
+ return [event, event.offsetX, event.offsetY];
+ });
+ addListener(canvas, type, proxy);
+ return proxy;
+}
+class DomPlatform extends BasePlatform {
+ acquireContext(canvas, aspectRatio) {
+ const context = canvas && canvas.getContext && canvas.getContext('2d');
+ if (context && context.canvas === canvas) {
+ initCanvas(canvas, aspectRatio);
+ return context;
+ }
+ return null;
+ }
+ releaseContext(context) {
+ const canvas = context.canvas;
+ if (!canvas[EXPANDO_KEY]) {
+ return false;
+ }
+ const initial = canvas[EXPANDO_KEY].initial;
+ ['height', 'width'].forEach((prop) => {
+ const value = initial[prop];
+ if (isNullOrUndef(value)) {
+ canvas.removeAttribute(prop);
+ } else {
+ canvas.setAttribute(prop, value);
+ }
+ });
+ const style = initial.style || {};
+ Object.keys(style).forEach((key) => {
+ canvas.style[key] = style[key];
+ });
+ canvas.width = canvas.width;
+ delete canvas[EXPANDO_KEY];
+ return true;
+ }
+ addEventListener(chart, type, listener) {
+ this.removeEventListener(chart, type);
+ const proxies = chart.$proxies || (chart.$proxies = {});
+ const handlers = {
+ attach: createAttachObserver,
+ detach: createDetachObserver,
+ resize: createResizeObserver
+ };
+ const handler = handlers[type] || createProxyAndListen;
+ proxies[type] = handler(chart, type, listener);
+ }
+ removeEventListener(chart, type) {
+ const proxies = chart.$proxies || (chart.$proxies = {});
+ const proxy = proxies[type];
+ if (!proxy) {
+ return;
+ }
+ const handlers = {
+ attach: releaseObserver,
+ detach: releaseObserver,
+ resize: releaseObserver
+ };
+ const handler = handlers[type] || removeListener;
+ handler(chart, type, proxy);
+ proxies[type] = undefined;
+ }
+ getDevicePixelRatio() {
+ return window.devicePixelRatio;
+ }
+ getMaximumSize(canvas, width, height, aspectRatio) {
+ return getMaximumSize(canvas, width, height, aspectRatio);
+ }
+ isAttached(canvas) {
+ const container = _getParentNode(canvas);
+ return !!(container && container.isConnected);
+ }
+}
+
+function _detectPlatform(canvas) {
+ if (!_isDomSupported() || (typeof OffscreenCanvas !== 'undefined' && canvas instanceof OffscreenCanvas)) {
+ return BasicPlatform;
+ }
+ return DomPlatform;
+}
+
+var platforms = /*#__PURE__*/Object.freeze({
+__proto__: null,
+_detectPlatform: _detectPlatform,
+BasePlatform: BasePlatform,
+BasicPlatform: BasicPlatform,
+DomPlatform: DomPlatform
+});
+
+const transparent = 'transparent';
+const interpolators = {
+ boolean(from, to, factor) {
+ return factor > 0.5 ? to : from;
+ },
+ color(from, to, factor) {
+ const c0 = color(from || transparent);
+ const c1 = c0.valid && color(to || transparent);
+ return c1 && c1.valid
+ ? c1.mix(c0, factor).hexString()
+ : to;
+ },
+ number(from, to, factor) {
+ return from + (to - from) * factor;
+ }
+};
+class Animation {
+ constructor(cfg, target, prop, to) {
+ const currentValue = target[prop];
+ to = resolve([cfg.to, to, currentValue, cfg.from]);
+ const from = resolve([cfg.from, currentValue, to]);
+ this._active = true;
+ this._fn = cfg.fn || interpolators[cfg.type || typeof from];
+ this._easing = effects[cfg.easing] || effects.linear;
+ this._start = Math.floor(Date.now() + (cfg.delay || 0));
+ this._duration = this._total = Math.floor(cfg.duration);
+ this._loop = !!cfg.loop;
+ this._target = target;
+ this._prop = prop;
+ this._from = from;
+ this._to = to;
+ this._promises = undefined;
+ }
+ active() {
+ return this._active;
+ }
+ update(cfg, to, date) {
+ if (this._active) {
+ this._notify(false);
+ const currentValue = this._target[this._prop];
+ const elapsed = date - this._start;
+ const remain = this._duration - elapsed;
+ this._start = date;
+ this._duration = Math.floor(Math.max(remain, cfg.duration));
+ this._total += elapsed;
+ this._loop = !!cfg.loop;
+ this._to = resolve([cfg.to, to, currentValue, cfg.from]);
+ this._from = resolve([cfg.from, currentValue, to]);
+ }
+ }
+ cancel() {
+ if (this._active) {
+ this.tick(Date.now());
+ this._active = false;
+ this._notify(false);
+ }
+ }
+ tick(date) {
+ const elapsed = date - this._start;
+ const duration = this._duration;
+ const prop = this._prop;
+ const from = this._from;
+ const loop = this._loop;
+ const to = this._to;
+ let factor;
+ this._active = from !== to && (loop || (elapsed < duration));
+ if (!this._active) {
+ this._target[prop] = to;
+ this._notify(true);
+ return;
+ }
+ if (elapsed < 0) {
+ this._target[prop] = from;
+ return;
+ }
+ factor = (elapsed / duration) % 2;
+ factor = loop && factor > 1 ? 2 - factor : factor;
+ factor = this._easing(Math.min(1, Math.max(0, factor)));
+ this._target[prop] = this._fn(from, to, factor);
+ }
+ wait() {
+ const promises = this._promises || (this._promises = []);
+ return new Promise((res, rej) => {
+ promises.push({res, rej});
+ });
+ }
+ _notify(resolved) {
+ const method = resolved ? 'res' : 'rej';
+ const promises = this._promises || [];
+ for (let i = 0; i < promises.length; i++) {
+ promises[i][method]();
+ }
+ }
+}
+
+const numbers = ['x', 'y', 'borderWidth', 'radius', 'tension'];
+const colors = ['color', 'borderColor', 'backgroundColor'];
+defaults.set('animation', {
+ delay: undefined,
+ duration: 1000,
+ easing: 'easeOutQuart',
+ fn: undefined,
+ from: undefined,
+ loop: undefined,
+ to: undefined,
+ type: undefined,
+});
+const animationOptions = Object.keys(defaults.animation);
+defaults.describe('animation', {
+ _fallback: false,
+ _indexable: false,
+ _scriptable: (name) => name !== 'onProgress' && name !== 'onComplete' && name !== 'fn',
+});
+defaults.set('animations', {
+ colors: {
+ type: 'color',
+ properties: colors
+ },
+ numbers: {
+ type: 'number',
+ properties: numbers
+ },
+});
+defaults.describe('animations', {
+ _fallback: 'animation',
+});
+defaults.set('transitions', {
+ active: {
+ animation: {
+ duration: 400
+ }
+ },
+ resize: {
+ animation: {
+ duration: 0
+ }
+ },
+ show: {
+ animations: {
+ colors: {
+ from: 'transparent'
+ },
+ visible: {
+ type: 'boolean',
+ duration: 0
+ },
+ }
+ },
+ hide: {
+ animations: {
+ colors: {
+ to: 'transparent'
+ },
+ visible: {
+ type: 'boolean',
+ easing: 'linear',
+ fn: v => v | 0
+ },
+ }
+ }
+});
+class Animations {
+ constructor(chart, config) {
+ this._chart = chart;
+ this._properties = new Map();
+ this.configure(config);
+ }
+ configure(config) {
+ if (!isObject(config)) {
+ return;
+ }
+ const animatedProps = this._properties;
+ Object.getOwnPropertyNames(config).forEach(key => {
+ const cfg = config[key];
+ if (!isObject(cfg)) {
+ return;
+ }
+ const resolved = {};
+ for (const option of animationOptions) {
+ resolved[option] = cfg[option];
+ }
+ (isArray(cfg.properties) && cfg.properties || [key]).forEach((prop) => {
+ if (prop === key || !animatedProps.has(prop)) {
+ animatedProps.set(prop, resolved);
+ }
+ });
+ });
+ }
+ _animateOptions(target, values) {
+ const newOptions = values.options;
+ const options = resolveTargetOptions(target, newOptions);
+ if (!options) {
+ return [];
+ }
+ const animations = this._createAnimations(options, newOptions);
+ if (newOptions.$shared) {
+ awaitAll(target.options.$animations, newOptions).then(() => {
+ target.options = newOptions;
+ }, () => {
+ });
+ }
+ return animations;
+ }
+ _createAnimations(target, values) {
+ const animatedProps = this._properties;
+ const animations = [];
+ const running = target.$animations || (target.$animations = {});
+ const props = Object.keys(values);
+ const date = Date.now();
+ let i;
+ for (i = props.length - 1; i >= 0; --i) {
+ const prop = props[i];
+ if (prop.charAt(0) === '$') {
+ continue;
+ }
+ if (prop === 'options') {
+ animations.push(...this._animateOptions(target, values));
+ continue;
+ }
+ const value = values[prop];
+ let animation = running[prop];
+ const cfg = animatedProps.get(prop);
+ if (animation) {
+ if (cfg && animation.active()) {
+ animation.update(cfg, value, date);
+ continue;
+ } else {
+ animation.cancel();
+ }
+ }
+ if (!cfg || !cfg.duration) {
+ target[prop] = value;
+ continue;
+ }
+ running[prop] = animation = new Animation(cfg, target, prop, value);
+ animations.push(animation);
+ }
+ return animations;
+ }
+ update(target, values) {
+ if (this._properties.size === 0) {
+ Object.assign(target, values);
+ return;
+ }
+ const animations = this._createAnimations(target, values);
+ if (animations.length) {
+ animator.add(this._chart, animations);
+ return true;
+ }
+ }
+}
+function awaitAll(animations, properties) {
+ const running = [];
+ const keys = Object.keys(properties);
+ for (let i = 0; i < keys.length; i++) {
+ const anim = animations[keys[i]];
+ if (anim && anim.active()) {
+ running.push(anim.wait());
+ }
+ }
+ return Promise.all(running);
+}
+function resolveTargetOptions(target, newOptions) {
+ if (!newOptions) {
+ return;
+ }
+ let options = target.options;
+ if (!options) {
+ target.options = newOptions;
+ return;
+ }
+ if (options.$shared) {
+ target.options = options = Object.assign({}, options, {$shared: false, $animations: {}});
+ }
+ return options;
+}
+
+function scaleClip(scale, allowedOverflow) {
+ const opts = scale && scale.options || {};
+ const reverse = opts.reverse;
+ const min = opts.min === undefined ? allowedOverflow : 0;
+ const max = opts.max === undefined ? allowedOverflow : 0;
+ return {
+ start: reverse ? max : min,
+ end: reverse ? min : max
+ };
+}
+function defaultClip(xScale, yScale, allowedOverflow) {
+ if (allowedOverflow === false) {
+ return false;
+ }
+ const x = scaleClip(xScale, allowedOverflow);
+ const y = scaleClip(yScale, allowedOverflow);
+ return {
+ top: y.end,
+ right: x.end,
+ bottom: y.start,
+ left: x.start
+ };
+}
+function toClip(value) {
+ let t, r, b, l;
+ if (isObject(value)) {
+ t = value.top;
+ r = value.right;
+ b = value.bottom;
+ l = value.left;
+ } else {
+ t = r = b = l = value;
+ }
+ return {
+ top: t,
+ right: r,
+ bottom: b,
+ left: l,
+ disabled: value === false
+ };
+}
+function getSortedDatasetIndices(chart, filterVisible) {
+ const keys = [];
+ const metasets = chart._getSortedDatasetMetas(filterVisible);
+ let i, ilen;
+ for (i = 0, ilen = metasets.length; i < ilen; ++i) {
+ keys.push(metasets[i].index);
+ }
+ return keys;
+}
+function applyStack(stack, value, dsIndex, options = {}) {
+ const keys = stack.keys;
+ const singleMode = options.mode === 'single';
+ let i, ilen, datasetIndex, otherValue;
+ if (value === null) {
+ return;
+ }
+ for (i = 0, ilen = keys.length; i < ilen; ++i) {
+ datasetIndex = +keys[i];
+ if (datasetIndex === dsIndex) {
+ if (options.all) {
+ continue;
+ }
+ break;
+ }
+ otherValue = stack.values[datasetIndex];
+ if (isNumberFinite(otherValue) && (singleMode || (value === 0 || sign(value) === sign(otherValue)))) {
+ value += otherValue;
+ }
+ }
+ return value;
+}
+function convertObjectDataToArray(data) {
+ const keys = Object.keys(data);
+ const adata = new Array(keys.length);
+ let i, ilen, key;
+ for (i = 0, ilen = keys.length; i < ilen; ++i) {
+ key = keys[i];
+ adata[i] = {
+ x: key,
+ y: data[key]
+ };
+ }
+ return adata;
+}
+function isStacked(scale, meta) {
+ const stacked = scale && scale.options.stacked;
+ return stacked || (stacked === undefined && meta.stack !== undefined);
+}
+function getStackKey(indexScale, valueScale, meta) {
+ return `${indexScale.id}.${valueScale.id}.${meta.stack || meta.type}`;
+}
+function getUserBounds(scale) {
+ const {min, max, minDefined, maxDefined} = scale.getUserBounds();
+ return {
+ min: minDefined ? min : Number.NEGATIVE_INFINITY,
+ max: maxDefined ? max : Number.POSITIVE_INFINITY
+ };
+}
+function getOrCreateStack(stacks, stackKey, indexValue) {
+ const subStack = stacks[stackKey] || (stacks[stackKey] = {});
+ return subStack[indexValue] || (subStack[indexValue] = {});
+}
+function getLastIndexInStack(stack, vScale, positive, type) {
+ for (const meta of vScale.getMatchingVisibleMetas(type).reverse()) {
+ const value = stack[meta.index];
+ if ((positive && value > 0) || (!positive && value < 0)) {
+ return meta.index;
+ }
+ }
+ return null;
+}
+function updateStacks(controller, parsed) {
+ const {chart, _cachedMeta: meta} = controller;
+ const stacks = chart._stacks || (chart._stacks = {});
+ const {iScale, vScale, index: datasetIndex} = meta;
+ const iAxis = iScale.axis;
+ const vAxis = vScale.axis;
+ const key = getStackKey(iScale, vScale, meta);
+ const ilen = parsed.length;
+ let stack;
+ for (let i = 0; i < ilen; ++i) {
+ const item = parsed[i];
+ const {[iAxis]: index, [vAxis]: value} = item;
+ const itemStacks = item._stacks || (item._stacks = {});
+ stack = itemStacks[vAxis] = getOrCreateStack(stacks, key, index);
+ stack[datasetIndex] = value;
+ stack._top = getLastIndexInStack(stack, vScale, true, meta.type);
+ stack._bottom = getLastIndexInStack(stack, vScale, false, meta.type);
+ }
+}
+function getFirstScaleId(chart, axis) {
+ const scales = chart.scales;
+ return Object.keys(scales).filter(key => scales[key].axis === axis).shift();
+}
+function createDatasetContext(parent, index) {
+ return createContext(parent,
+ {
+ active: false,
+ dataset: undefined,
+ datasetIndex: index,
+ index,
+ mode: 'default',
+ type: 'dataset'
+ }
+ );
+}
+function createDataContext(parent, index, element) {
+ return createContext(parent, {
+ active: false,
+ dataIndex: index,
+ parsed: undefined,
+ raw: undefined,
+ element,
+ index,
+ mode: 'default',
+ type: 'data'
+ });
+}
+function clearStacks(meta, items) {
+ const datasetIndex = meta.controller.index;
+ const axis = meta.vScale && meta.vScale.axis;
+ if (!axis) {
+ return;
+ }
+ items = items || meta._parsed;
+ for (const parsed of items) {
+ const stacks = parsed._stacks;
+ if (!stacks || stacks[axis] === undefined || stacks[axis][datasetIndex] === undefined) {
+ return;
+ }
+ delete stacks[axis][datasetIndex];
+ }
+}
+const isDirectUpdateMode = (mode) => mode === 'reset' || mode === 'none';
+const cloneIfNotShared = (cached, shared) => shared ? cached : Object.assign({}, cached);
+const createStack = (canStack, meta, chart) => canStack && !meta.hidden && meta._stacked
+ && {keys: getSortedDatasetIndices(chart, true), values: null};
+class DatasetController {
+ constructor(chart, datasetIndex) {
+ this.chart = chart;
+ this._ctx = chart.ctx;
+ this.index = datasetIndex;
+ this._cachedDataOpts = {};
+ this._cachedMeta = this.getMeta();
+ this._type = this._cachedMeta.type;
+ this.options = undefined;
+ this._parsing = false;
+ this._data = undefined;
+ this._objectData = undefined;
+ this._sharedOptions = undefined;
+ this._drawStart = undefined;
+ this._drawCount = undefined;
+ this.enableOptionSharing = false;
+ this.$context = undefined;
+ this._syncList = [];
+ this.initialize();
+ }
+ initialize() {
+ const meta = this._cachedMeta;
+ this.configure();
+ this.linkScales();
+ meta._stacked = isStacked(meta.vScale, meta);
+ this.addElements();
+ }
+ updateIndex(datasetIndex) {
+ if (this.index !== datasetIndex) {
+ clearStacks(this._cachedMeta);
+ }
+ this.index = datasetIndex;
+ }
+ linkScales() {
+ const chart = this.chart;
+ const meta = this._cachedMeta;
+ const dataset = this.getDataset();
+ const chooseId = (axis, x, y, r) => axis === 'x' ? x : axis === 'r' ? r : y;
+ const xid = meta.xAxisID = valueOrDefault(dataset.xAxisID, getFirstScaleId(chart, 'x'));
+ const yid = meta.yAxisID = valueOrDefault(dataset.yAxisID, getFirstScaleId(chart, 'y'));
+ const rid = meta.rAxisID = valueOrDefault(dataset.rAxisID, getFirstScaleId(chart, 'r'));
+ const indexAxis = meta.indexAxis;
+ const iid = meta.iAxisID = chooseId(indexAxis, xid, yid, rid);
+ const vid = meta.vAxisID = chooseId(indexAxis, yid, xid, rid);
+ meta.xScale = this.getScaleForId(xid);
+ meta.yScale = this.getScaleForId(yid);
+ meta.rScale = this.getScaleForId(rid);
+ meta.iScale = this.getScaleForId(iid);
+ meta.vScale = this.getScaleForId(vid);
+ }
+ getDataset() {
+ return this.chart.data.datasets[this.index];
+ }
+ getMeta() {
+ return this.chart.getDatasetMeta(this.index);
+ }
+ getScaleForId(scaleID) {
+ return this.chart.scales[scaleID];
+ }
+ _getOtherScale(scale) {
+ const meta = this._cachedMeta;
+ return scale === meta.iScale
+ ? meta.vScale
+ : meta.iScale;
+ }
+ reset() {
+ this._update('reset');
+ }
+ _destroy() {
+ const meta = this._cachedMeta;
+ if (this._data) {
+ unlistenArrayEvents(this._data, this);
+ }
+ if (meta._stacked) {
+ clearStacks(meta);
+ }
+ }
+ _dataCheck() {
+ const dataset = this.getDataset();
+ const data = dataset.data || (dataset.data = []);
+ const _data = this._data;
+ if (isObject(data)) {
+ this._data = convertObjectDataToArray(data);
+ } else if (_data !== data) {
+ if (_data) {
+ unlistenArrayEvents(_data, this);
+ const meta = this._cachedMeta;
+ clearStacks(meta);
+ meta._parsed = [];
+ }
+ if (data && Object.isExtensible(data)) {
+ listenArrayEvents(data, this);
+ }
+ this._syncList = [];
+ this._data = data;
+ }
+ }
+ addElements() {
+ const meta = this._cachedMeta;
+ this._dataCheck();
+ if (this.datasetElementType) {
+ meta.dataset = new this.datasetElementType();
+ }
+ }
+ buildOrUpdateElements(resetNewElements) {
+ const meta = this._cachedMeta;
+ const dataset = this.getDataset();
+ let stackChanged = false;
+ this._dataCheck();
+ const oldStacked = meta._stacked;
+ meta._stacked = isStacked(meta.vScale, meta);
+ if (meta.stack !== dataset.stack) {
+ stackChanged = true;
+ clearStacks(meta);
+ meta.stack = dataset.stack;
+ }
+ this._resyncElements(resetNewElements);
+ if (stackChanged || oldStacked !== meta._stacked) {
+ updateStacks(this, meta._parsed);
+ }
+ }
+ configure() {
+ const config = this.chart.config;
+ const scopeKeys = config.datasetScopeKeys(this._type);
+ const scopes = config.getOptionScopes(this.getDataset(), scopeKeys, true);
+ this.options = config.createResolver(scopes, this.getContext());
+ this._parsing = this.options.parsing;
+ }
+ parse(start, count) {
+ const {_cachedMeta: meta, _data: data} = this;
+ const {iScale, _stacked} = meta;
+ const iAxis = iScale.axis;
+ let sorted = start === 0 && count === data.length ? true : meta._sorted;
+ let prev = start > 0 && meta._parsed[start - 1];
+ let i, cur, parsed;
+ if (this._parsing === false) {
+ meta._parsed = data;
+ meta._sorted = true;
+ parsed = data;
+ } else {
+ if (isArray(data[start])) {
+ parsed = this.parseArrayData(meta, data, start, count);
+ } else if (isObject(data[start])) {
+ parsed = this.parseObjectData(meta, data, start, count);
+ } else {
+ parsed = this.parsePrimitiveData(meta, data, start, count);
+ }
+ const isNotInOrderComparedToPrev = () => cur[iAxis] === null || (prev && cur[iAxis] < prev[iAxis]);
+ for (i = 0; i < count; ++i) {
+ meta._parsed[i + start] = cur = parsed[i];
+ if (sorted) {
+ if (isNotInOrderComparedToPrev()) {
+ sorted = false;
+ }
+ prev = cur;
+ }
+ }
+ meta._sorted = sorted;
+ }
+ if (_stacked) {
+ updateStacks(this, parsed);
+ }
+ }
+ parsePrimitiveData(meta, data, start, count) {
+ const {iScale, vScale} = meta;
+ const iAxis = iScale.axis;
+ const vAxis = vScale.axis;
+ const labels = iScale.getLabels();
+ const singleScale = iScale === vScale;
+ const parsed = new Array(count);
+ let i, ilen, index;
+ for (i = 0, ilen = count; i < ilen; ++i) {
+ index = i + start;
+ parsed[i] = {
+ [iAxis]: singleScale || iScale.parse(labels[index], index),
+ [vAxis]: vScale.parse(data[index], index)
+ };
+ }
+ return parsed;
+ }
+ parseArrayData(meta, data, start, count) {
+ const {xScale, yScale} = meta;
+ const parsed = new Array(count);
+ let i, ilen, index, item;
+ for (i = 0, ilen = count; i < ilen; ++i) {
+ index = i + start;
+ item = data[index];
+ parsed[i] = {
+ x: xScale.parse(item[0], index),
+ y: yScale.parse(item[1], index)
+ };
+ }
+ return parsed;
+ }
+ parseObjectData(meta, data, start, count) {
+ const {xScale, yScale} = meta;
+ const {xAxisKey = 'x', yAxisKey = 'y'} = this._parsing;
+ const parsed = new Array(count);
+ let i, ilen, index, item;
+ for (i = 0, ilen = count; i < ilen; ++i) {
+ index = i + start;
+ item = data[index];
+ parsed[i] = {
+ x: xScale.parse(resolveObjectKey(item, xAxisKey), index),
+ y: yScale.parse(resolveObjectKey(item, yAxisKey), index)
+ };
+ }
+ return parsed;
+ }
+ getParsed(index) {
+ return this._cachedMeta._parsed[index];
+ }
+ getDataElement(index) {
+ return this._cachedMeta.data[index];
+ }
+ applyStack(scale, parsed, mode) {
+ const chart = this.chart;
+ const meta = this._cachedMeta;
+ const value = parsed[scale.axis];
+ const stack = {
+ keys: getSortedDatasetIndices(chart, true),
+ values: parsed._stacks[scale.axis]
+ };
+ return applyStack(stack, value, meta.index, {mode});
+ }
+ updateRangeFromParsed(range, scale, parsed, stack) {
+ const parsedValue = parsed[scale.axis];
+ let value = parsedValue === null ? NaN : parsedValue;
+ const values = stack && parsed._stacks[scale.axis];
+ if (stack && values) {
+ stack.values = values;
+ value = applyStack(stack, parsedValue, this._cachedMeta.index);
+ }
+ range.min = Math.min(range.min, value);
+ range.max = Math.max(range.max, value);
+ }
+ getMinMax(scale, canStack) {
+ const meta = this._cachedMeta;
+ const _parsed = meta._parsed;
+ const sorted = meta._sorted && scale === meta.iScale;
+ const ilen = _parsed.length;
+ const otherScale = this._getOtherScale(scale);
+ const stack = createStack(canStack, meta, this.chart);
+ const range = {min: Number.POSITIVE_INFINITY, max: Number.NEGATIVE_INFINITY};
+ const {min: otherMin, max: otherMax} = getUserBounds(otherScale);
+ let i, parsed;
+ function _skip() {
+ parsed = _parsed[i];
+ const otherValue = parsed[otherScale.axis];
+ return !isNumberFinite(parsed[scale.axis]) || otherMin > otherValue || otherMax < otherValue;
+ }
+ for (i = 0; i < ilen; ++i) {
+ if (_skip()) {
+ continue;
+ }
+ this.updateRangeFromParsed(range, scale, parsed, stack);
+ if (sorted) {
+ break;
+ }
+ }
+ if (sorted) {
+ for (i = ilen - 1; i >= 0; --i) {
+ if (_skip()) {
+ continue;
+ }
+ this.updateRangeFromParsed(range, scale, parsed, stack);
+ break;
+ }
+ }
+ return range;
+ }
+ getAllParsedValues(scale) {
+ const parsed = this._cachedMeta._parsed;
+ const values = [];
+ let i, ilen, value;
+ for (i = 0, ilen = parsed.length; i < ilen; ++i) {
+ value = parsed[i][scale.axis];
+ if (isNumberFinite(value)) {
+ values.push(value);
+ }
+ }
+ return values;
+ }
+ getMaxOverflow() {
+ return false;
+ }
+ getLabelAndValue(index) {
+ const meta = this._cachedMeta;
+ const iScale = meta.iScale;
+ const vScale = meta.vScale;
+ const parsed = this.getParsed(index);
+ return {
+ label: iScale ? '' + iScale.getLabelForValue(parsed[iScale.axis]) : '',
+ value: vScale ? '' + vScale.getLabelForValue(parsed[vScale.axis]) : ''
+ };
+ }
+ _update(mode) {
+ const meta = this._cachedMeta;
+ this.configure();
+ this._cachedDataOpts = {};
+ this.update(mode || 'default');
+ meta._clip = toClip(valueOrDefault(this.options.clip, defaultClip(meta.xScale, meta.yScale, this.getMaxOverflow())));
+ }
+ update(mode) {}
+ draw() {
+ const ctx = this._ctx;
+ const chart = this.chart;
+ const meta = this._cachedMeta;
+ const elements = meta.data || [];
+ const area = chart.chartArea;
+ const active = [];
+ const start = this._drawStart || 0;
+ const count = this._drawCount || (elements.length - start);
+ let i;
+ if (meta.dataset) {
+ meta.dataset.draw(ctx, area, start, count);
+ }
+ for (i = start; i < start + count; ++i) {
+ const element = elements[i];
+ if (element.hidden) {
+ continue;
+ }
+ if (element.active) {
+ active.push(element);
+ } else {
+ element.draw(ctx, area);
+ }
+ }
+ for (i = 0; i < active.length; ++i) {
+ active[i].draw(ctx, area);
+ }
+ }
+ getStyle(index, active) {
+ const mode = active ? 'active' : 'default';
+ return index === undefined && this._cachedMeta.dataset
+ ? this.resolveDatasetElementOptions(mode)
+ : this.resolveDataElementOptions(index || 0, mode);
+ }
+ getContext(index, active, mode) {
+ const dataset = this.getDataset();
+ let context;
+ if (index >= 0 && index < this._cachedMeta.data.length) {
+ const element = this._cachedMeta.data[index];
+ context = element.$context ||
+ (element.$context = createDataContext(this.getContext(), index, element));
+ context.parsed = this.getParsed(index);
+ context.raw = dataset.data[index];
+ context.index = context.dataIndex = index;
+ } else {
+ context = this.$context ||
+ (this.$context = createDatasetContext(this.chart.getContext(), this.index));
+ context.dataset = dataset;
+ context.index = context.datasetIndex = this.index;
+ }
+ context.active = !!active;
+ context.mode = mode;
+ return context;
+ }
+ resolveDatasetElementOptions(mode) {
+ return this._resolveElementOptions(this.datasetElementType.id, mode);
+ }
+ resolveDataElementOptions(index, mode) {
+ return this._resolveElementOptions(this.dataElementType.id, mode, index);
+ }
+ _resolveElementOptions(elementType, mode = 'default', index) {
+ const active = mode === 'active';
+ const cache = this._cachedDataOpts;
+ const cacheKey = elementType + '-' + mode;
+ const cached = cache[cacheKey];
+ const sharing = this.enableOptionSharing && defined(index);
+ if (cached) {
+ return cloneIfNotShared(cached, sharing);
+ }
+ const config = this.chart.config;
+ const scopeKeys = config.datasetElementScopeKeys(this._type, elementType);
+ const prefixes = active ? [`${elementType}Hover`, 'hover', elementType, ''] : [elementType, ''];
+ const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);
+ const names = Object.keys(defaults.elements[elementType]);
+ const context = () => this.getContext(index, active);
+ const values = config.resolveNamedOptions(scopes, names, context, prefixes);
+ if (values.$shared) {
+ values.$shared = sharing;
+ cache[cacheKey] = Object.freeze(cloneIfNotShared(values, sharing));
+ }
+ return values;
+ }
+ _resolveAnimations(index, transition, active) {
+ const chart = this.chart;
+ const cache = this._cachedDataOpts;
+ const cacheKey = `animation-${transition}`;
+ const cached = cache[cacheKey];
+ if (cached) {
+ return cached;
+ }
+ let options;
+ if (chart.options.animation !== false) {
+ const config = this.chart.config;
+ const scopeKeys = config.datasetAnimationScopeKeys(this._type, transition);
+ const scopes = config.getOptionScopes(this.getDataset(), scopeKeys);
+ options = config.createResolver(scopes, this.getContext(index, active, transition));
+ }
+ const animations = new Animations(chart, options && options.animations);
+ if (options && options._cacheable) {
+ cache[cacheKey] = Object.freeze(animations);
+ }
+ return animations;
+ }
+ getSharedOptions(options) {
+ if (!options.$shared) {
+ return;
+ }
+ return this._sharedOptions || (this._sharedOptions = Object.assign({}, options));
+ }
+ includeOptions(mode, sharedOptions) {
+ return !sharedOptions || isDirectUpdateMode(mode) || this.chart._animationsDisabled;
+ }
+ updateElement(element, index, properties, mode) {
+ if (isDirectUpdateMode(mode)) {
+ Object.assign(element, properties);
+ } else {
+ this._resolveAnimations(index, mode).update(element, properties);
+ }
+ }
+ updateSharedOptions(sharedOptions, mode, newOptions) {
+ if (sharedOptions && !isDirectUpdateMode(mode)) {
+ this._resolveAnimations(undefined, mode).update(sharedOptions, newOptions);
+ }
+ }
+ _setStyle(element, index, mode, active) {
+ element.active = active;
+ const options = this.getStyle(index, active);
+ this._resolveAnimations(index, mode, active).update(element, {
+ options: (!active && this.getSharedOptions(options)) || options
+ });
+ }
+ removeHoverStyle(element, datasetIndex, index) {
+ this._setStyle(element, index, 'active', false);
+ }
+ setHoverStyle(element, datasetIndex, index) {
+ this._setStyle(element, index, 'active', true);
+ }
+ _removeDatasetHoverStyle() {
+ const element = this._cachedMeta.dataset;
+ if (element) {
+ this._setStyle(element, undefined, 'active', false);
+ }
+ }
+ _setDatasetHoverStyle() {
+ const element = this._cachedMeta.dataset;
+ if (element) {
+ this._setStyle(element, undefined, 'active', true);
+ }
+ }
+ _resyncElements(resetNewElements) {
+ const data = this._data;
+ const elements = this._cachedMeta.data;
+ for (const [method, arg1, arg2] of this._syncList) {
+ this[method](arg1, arg2);
+ }
+ this._syncList = [];
+ const numMeta = elements.length;
+ const numData = data.length;
+ const count = Math.min(numData, numMeta);
+ if (count) {
+ this.parse(0, count);
+ }
+ if (numData > numMeta) {
+ this._insertElements(numMeta, numData - numMeta, resetNewElements);
+ } else if (numData < numMeta) {
+ this._removeElements(numData, numMeta - numData);
+ }
+ }
+ _insertElements(start, count, resetNewElements = true) {
+ const meta = this._cachedMeta;
+ const data = meta.data;
+ const end = start + count;
+ let i;
+ const move = (arr) => {
+ arr.length += count;
+ for (i = arr.length - 1; i >= end; i--) {
+ arr[i] = arr[i - count];
+ }
+ };
+ move(data);
+ for (i = start; i < end; ++i) {
+ data[i] = new this.dataElementType();
+ }
+ if (this._parsing) {
+ move(meta._parsed);
+ }
+ this.parse(start, count);
+ if (resetNewElements) {
+ this.updateElements(data, start, count, 'reset');
+ }
+ }
+ updateElements(element, start, count, mode) {}
+ _removeElements(start, count) {
+ const meta = this._cachedMeta;
+ if (this._parsing) {
+ const removed = meta._parsed.splice(start, count);
+ if (meta._stacked) {
+ clearStacks(meta, removed);
+ }
+ }
+ meta.data.splice(start, count);
+ }
+ _sync(args) {
+ if (this._parsing) {
+ this._syncList.push(args);
+ } else {
+ const [method, arg1, arg2] = args;
+ this[method](arg1, arg2);
+ }
+ }
+ _onDataPush() {
+ const count = arguments.length;
+ this._sync(['_insertElements', this.getDataset().data.length - count, count]);
+ }
+ _onDataPop() {
+ this._sync(['_removeElements', this._cachedMeta.data.length - 1, 1]);
+ }
+ _onDataShift() {
+ this._sync(['_removeElements', 0, 1]);
+ }
+ _onDataSplice(start, count) {
+ this._sync(['_removeElements', start, count]);
+ this._sync(['_insertElements', start, arguments.length - 2]);
+ }
+ _onDataUnshift() {
+ this._sync(['_insertElements', 0, arguments.length]);
+ }
+}
+DatasetController.defaults = {};
+DatasetController.prototype.datasetElementType = null;
+DatasetController.prototype.dataElementType = null;
+
+class Element {
+ constructor() {
+ this.x = undefined;
+ this.y = undefined;
+ this.active = false;
+ this.options = undefined;
+ this.$animations = undefined;
+ }
+ tooltipPosition(useFinalPosition) {
+ const {x, y} = this.getProps(['x', 'y'], useFinalPosition);
+ return {x, y};
+ }
+ hasValue() {
+ return isNumber(this.x) && isNumber(this.y);
+ }
+ getProps(props, final) {
+ const anims = this.$animations;
+ if (!final || !anims) {
+ return this;
+ }
+ const ret = {};
+ props.forEach(prop => {
+ ret[prop] = anims[prop] && anims[prop].active() ? anims[prop]._to : this[prop];
+ });
+ return ret;
+ }
+}
+Element.defaults = {};
+Element.defaultRoutes = undefined;
+
+const formatters = {
+ values(value) {
+ return isArray(value) ? value : '' + value;
+ },
+ numeric(tickValue, index, ticks) {
+ if (tickValue === 0) {
+ return '0';
+ }
+ const locale = this.chart.options.locale;
+ let notation;
+ let delta = tickValue;
+ if (ticks.length > 1) {
+ const maxTick = Math.max(Math.abs(ticks[0].value), Math.abs(ticks[ticks.length - 1].value));
+ if (maxTick < 1e-4 || maxTick > 1e+15) {
+ notation = 'scientific';
+ }
+ delta = calculateDelta(tickValue, ticks);
+ }
+ const logDelta = log10(Math.abs(delta));
+ const numDecimal = Math.max(Math.min(-1 * Math.floor(logDelta), 20), 0);
+ const options = {notation, minimumFractionDigits: numDecimal, maximumFractionDigits: numDecimal};
+ Object.assign(options, this.options.ticks.format);
+ return formatNumber(tickValue, locale, options);
+ },
+ logarithmic(tickValue, index, ticks) {
+ if (tickValue === 0) {
+ return '0';
+ }
+ const remain = tickValue / (Math.pow(10, Math.floor(log10(tickValue))));
+ if (remain === 1 || remain === 2 || remain === 5) {
+ return formatters.numeric.call(this, tickValue, index, ticks);
+ }
+ return '';
+ }
+};
+function calculateDelta(tickValue, ticks) {
+ let delta = ticks.length > 3 ? ticks[2].value - ticks[1].value : ticks[1].value - ticks[0].value;
+ if (Math.abs(delta) >= 1 && tickValue !== Math.floor(tickValue)) {
+ delta = tickValue - Math.floor(tickValue);
+ }
+ return delta;
+}
+var Ticks = {formatters};
+
+defaults.set('scale', {
+ display: true,
+ offset: false,
+ reverse: false,
+ beginAtZero: false,
+ bounds: 'ticks',
+ grace: 0,
+ grid: {
+ display: true,
+ lineWidth: 1,
+ drawBorder: true,
+ drawOnChartArea: true,
+ drawTicks: true,
+ tickLength: 8,
+ tickWidth: (_ctx, options) => options.lineWidth,
+ tickColor: (_ctx, options) => options.color,
+ offset: false,
+ borderDash: [],
+ borderDashOffset: 0.0,
+ borderWidth: 1
+ },
+ title: {
+ display: false,
+ text: '',
+ padding: {
+ top: 4,
+ bottom: 4
+ }
+ },
+ ticks: {
+ minRotation: 0,
+ maxRotation: 50,
+ mirror: false,
+ textStrokeWidth: 0,
+ textStrokeColor: '',
+ padding: 3,
+ display: true,
+ autoSkip: true,
+ autoSkipPadding: 3,
+ labelOffset: 0,
+ callback: Ticks.formatters.values,
+ minor: {},
+ major: {},
+ align: 'center',
+ crossAlign: 'near',
+ showLabelBackdrop: false,
+ backdropColor: 'rgba(255, 255, 255, 0.75)',
+ backdropPadding: 2,
+ }
+});
+defaults.route('scale.ticks', 'color', '', 'color');
+defaults.route('scale.grid', 'color', '', 'borderColor');
+defaults.route('scale.grid', 'borderColor', '', 'borderColor');
+defaults.route('scale.title', 'color', '', 'color');
+defaults.describe('scale', {
+ _fallback: false,
+ _scriptable: (name) => !name.startsWith('before') && !name.startsWith('after') && name !== 'callback' && name !== 'parser',
+ _indexable: (name) => name !== 'borderDash' && name !== 'tickBorderDash',
+});
+defaults.describe('scales', {
+ _fallback: 'scale',
+});
+defaults.describe('scale.ticks', {
+ _scriptable: (name) => name !== 'backdropPadding' && name !== 'callback',
+ _indexable: (name) => name !== 'backdropPadding',
+});
+
+function autoSkip(scale, ticks) {
+ const tickOpts = scale.options.ticks;
+ const ticksLimit = tickOpts.maxTicksLimit || determineMaxTicks(scale);
+ const majorIndices = tickOpts.major.enabled ? getMajorIndices(ticks) : [];
+ const numMajorIndices = majorIndices.length;
+ const first = majorIndices[0];
+ const last = majorIndices[numMajorIndices - 1];
+ const newTicks = [];
+ if (numMajorIndices > ticksLimit) {
+ skipMajors(ticks, newTicks, majorIndices, numMajorIndices / ticksLimit);
+ return newTicks;
+ }
+ const spacing = calculateSpacing(majorIndices, ticks, ticksLimit);
+ if (numMajorIndices > 0) {
+ let i, ilen;
+ const avgMajorSpacing = numMajorIndices > 1 ? Math.round((last - first) / (numMajorIndices - 1)) : null;
+ skip(ticks, newTicks, spacing, isNullOrUndef(avgMajorSpacing) ? 0 : first - avgMajorSpacing, first);
+ for (i = 0, ilen = numMajorIndices - 1; i < ilen; i++) {
+ skip(ticks, newTicks, spacing, majorIndices[i], majorIndices[i + 1]);
+ }
+ skip(ticks, newTicks, spacing, last, isNullOrUndef(avgMajorSpacing) ? ticks.length : last + avgMajorSpacing);
+ return newTicks;
+ }
+ skip(ticks, newTicks, spacing);
+ return newTicks;
+}
+function determineMaxTicks(scale) {
+ const offset = scale.options.offset;
+ const tickLength = scale._tickSize();
+ const maxScale = scale._length / tickLength + (offset ? 0 : 1);
+ const maxChart = scale._maxLength / tickLength;
+ return Math.floor(Math.min(maxScale, maxChart));
+}
+function calculateSpacing(majorIndices, ticks, ticksLimit) {
+ const evenMajorSpacing = getEvenSpacing(majorIndices);
+ const spacing = ticks.length / ticksLimit;
+ if (!evenMajorSpacing) {
+ return Math.max(spacing, 1);
+ }
+ const factors = _factorize(evenMajorSpacing);
+ for (let i = 0, ilen = factors.length - 1; i < ilen; i++) {
+ const factor = factors[i];
+ if (factor > spacing) {
+ return factor;
+ }
+ }
+ return Math.max(spacing, 1);
+}
+function getMajorIndices(ticks) {
+ const result = [];
+ let i, ilen;
+ for (i = 0, ilen = ticks.length; i < ilen; i++) {
+ if (ticks[i].major) {
+ result.push(i);
+ }
+ }
+ return result;
+}
+function skipMajors(ticks, newTicks, majorIndices, spacing) {
+ let count = 0;
+ let next = majorIndices[0];
+ let i;
+ spacing = Math.ceil(spacing);
+ for (i = 0; i < ticks.length; i++) {
+ if (i === next) {
+ newTicks.push(ticks[i]);
+ count++;
+ next = majorIndices[count * spacing];
+ }
+ }
+}
+function skip(ticks, newTicks, spacing, majorStart, majorEnd) {
+ const start = valueOrDefault(majorStart, 0);
+ const end = Math.min(valueOrDefault(majorEnd, ticks.length), ticks.length);
+ let count = 0;
+ let length, i, next;
+ spacing = Math.ceil(spacing);
+ if (majorEnd) {
+ length = majorEnd - majorStart;
+ spacing = length / Math.floor(length / spacing);
+ }
+ next = start;
+ while (next < 0) {
+ count++;
+ next = Math.round(start + count * spacing);
+ }
+ for (i = Math.max(start, 0); i < end; i++) {
+ if (i === next) {
+ newTicks.push(ticks[i]);
+ count++;
+ next = Math.round(start + count * spacing);
+ }
+ }
+}
+function getEvenSpacing(arr) {
+ const len = arr.length;
+ let i, diff;
+ if (len < 2) {
+ return false;
+ }
+ for (diff = arr[0], i = 1; i < len; ++i) {
+ if (arr[i] - arr[i - 1] !== diff) {
+ return false;
+ }
+ }
+ return diff;
+}
+
+const reverseAlign = (align) => align === 'left' ? 'right' : align === 'right' ? 'left' : align;
+const offsetFromEdge = (scale, edge, offset) => edge === 'top' || edge === 'left' ? scale[edge] + offset : scale[edge] - offset;
+function sample(arr, numItems) {
+ const result = [];
+ const increment = arr.length / numItems;
+ const len = arr.length;
+ let i = 0;
+ for (; i < len; i += increment) {
+ result.push(arr[Math.floor(i)]);
+ }
+ return result;
+}
+function getPixelForGridLine(scale, index, offsetGridLines) {
+ const length = scale.ticks.length;
+ const validIndex = Math.min(index, length - 1);
+ const start = scale._startPixel;
+ const end = scale._endPixel;
+ const epsilon = 1e-6;
+ let lineValue = scale.getPixelForTick(validIndex);
+ let offset;
+ if (offsetGridLines) {
+ if (length === 1) {
+ offset = Math.max(lineValue - start, end - lineValue);
+ } else if (index === 0) {
+ offset = (scale.getPixelForTick(1) - lineValue) / 2;
+ } else {
+ offset = (lineValue - scale.getPixelForTick(validIndex - 1)) / 2;
+ }
+ lineValue += validIndex < index ? offset : -offset;
+ if (lineValue < start - epsilon || lineValue > end + epsilon) {
+ return;
+ }
+ }
+ return lineValue;
+}
+function garbageCollect(caches, length) {
+ each(caches, (cache) => {
+ const gc = cache.gc;
+ const gcLen = gc.length / 2;
+ let i;
+ if (gcLen > length) {
+ for (i = 0; i < gcLen; ++i) {
+ delete cache.data[gc[i]];
+ }
+ gc.splice(0, gcLen);
+ }
+ });
+}
+function getTickMarkLength(options) {
+ return options.drawTicks ? options.tickLength : 0;
+}
+function getTitleHeight(options, fallback) {
+ if (!options.display) {
+ return 0;
+ }
+ const font = toFont(options.font, fallback);
+ const padding = toPadding(options.padding);
+ const lines = isArray(options.text) ? options.text.length : 1;
+ return (lines * font.lineHeight) + padding.height;
+}
+function createScaleContext(parent, scale) {
+ return createContext(parent, {
+ scale,
+ type: 'scale'
+ });
+}
+function createTickContext(parent, index, tick) {
+ return createContext(parent, {
+ tick,
+ index,
+ type: 'tick'
+ });
+}
+function titleAlign(align, position, reverse) {
+ let ret = _toLeftRightCenter(align);
+ if ((reverse && position !== 'right') || (!reverse && position === 'right')) {
+ ret = reverseAlign(ret);
+ }
+ return ret;
+}
+function titleArgs(scale, offset, position, align) {
+ const {top, left, bottom, right, chart} = scale;
+ const {chartArea, scales} = chart;
+ let rotation = 0;
+ let maxWidth, titleX, titleY;
+ const height = bottom - top;
+ const width = right - left;
+ if (scale.isHorizontal()) {
+ titleX = _alignStartEnd(align, left, right);
+ if (isObject(position)) {
+ const positionAxisID = Object.keys(position)[0];
+ const value = position[positionAxisID];
+ titleY = scales[positionAxisID].getPixelForValue(value) + height - offset;
+ } else if (position === 'center') {
+ titleY = (chartArea.bottom + chartArea.top) / 2 + height - offset;
+ } else {
+ titleY = offsetFromEdge(scale, position, offset);
+ }
+ maxWidth = right - left;
+ } else {
+ if (isObject(position)) {
+ const positionAxisID = Object.keys(position)[0];
+ const value = position[positionAxisID];
+ titleX = scales[positionAxisID].getPixelForValue(value) - width + offset;
+ } else if (position === 'center') {
+ titleX = (chartArea.left + chartArea.right) / 2 - width + offset;
+ } else {
+ titleX = offsetFromEdge(scale, position, offset);
+ }
+ titleY = _alignStartEnd(align, bottom, top);
+ rotation = position === 'left' ? -HALF_PI : HALF_PI;
+ }
+ return {titleX, titleY, maxWidth, rotation};
+}
+class Scale extends Element {
+ constructor(cfg) {
+ super();
+ this.id = cfg.id;
+ this.type = cfg.type;
+ this.options = undefined;
+ this.ctx = cfg.ctx;
+ this.chart = cfg.chart;
+ this.top = undefined;
+ this.bottom = undefined;
+ this.left = undefined;
+ this.right = undefined;
+ this.width = undefined;
+ this.height = undefined;
+ this._margins = {
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0
+ };
+ this.maxWidth = undefined;
+ this.maxHeight = undefined;
+ this.paddingTop = undefined;
+ this.paddingBottom = undefined;
+ this.paddingLeft = undefined;
+ this.paddingRight = undefined;
+ this.axis = undefined;
+ this.labelRotation = undefined;
+ this.min = undefined;
+ this.max = undefined;
+ this._range = undefined;
+ this.ticks = [];
+ this._gridLineItems = null;
+ this._labelItems = null;
+ this._labelSizes = null;
+ this._length = 0;
+ this._maxLength = 0;
+ this._longestTextCache = {};
+ this._startPixel = undefined;
+ this._endPixel = undefined;
+ this._reversePixels = false;
+ this._userMax = undefined;
+ this._userMin = undefined;
+ this._suggestedMax = undefined;
+ this._suggestedMin = undefined;
+ this._ticksLength = 0;
+ this._borderValue = 0;
+ this._cache = {};
+ this._dataLimitsCached = false;
+ this.$context = undefined;
+ }
+ init(options) {
+ this.options = options.setContext(this.getContext());
+ this.axis = options.axis;
+ this._userMin = this.parse(options.min);
+ this._userMax = this.parse(options.max);
+ this._suggestedMin = this.parse(options.suggestedMin);
+ this._suggestedMax = this.parse(options.suggestedMax);
+ }
+ parse(raw, index) {
+ return raw;
+ }
+ getUserBounds() {
+ let {_userMin, _userMax, _suggestedMin, _suggestedMax} = this;
+ _userMin = finiteOrDefault(_userMin, Number.POSITIVE_INFINITY);
+ _userMax = finiteOrDefault(_userMax, Number.NEGATIVE_INFINITY);
+ _suggestedMin = finiteOrDefault(_suggestedMin, Number.POSITIVE_INFINITY);
+ _suggestedMax = finiteOrDefault(_suggestedMax, Number.NEGATIVE_INFINITY);
+ return {
+ min: finiteOrDefault(_userMin, _suggestedMin),
+ max: finiteOrDefault(_userMax, _suggestedMax),
+ minDefined: isNumberFinite(_userMin),
+ maxDefined: isNumberFinite(_userMax)
+ };
+ }
+ getMinMax(canStack) {
+ let {min, max, minDefined, maxDefined} = this.getUserBounds();
+ let range;
+ if (minDefined && maxDefined) {
+ return {min, max};
+ }
+ const metas = this.getMatchingVisibleMetas();
+ for (let i = 0, ilen = metas.length; i < ilen; ++i) {
+ range = metas[i].controller.getMinMax(this, canStack);
+ if (!minDefined) {
+ min = Math.min(min, range.min);
+ }
+ if (!maxDefined) {
+ max = Math.max(max, range.max);
+ }
+ }
+ min = maxDefined && min > max ? max : min;
+ max = minDefined && min > max ? min : max;
+ return {
+ min: finiteOrDefault(min, finiteOrDefault(max, min)),
+ max: finiteOrDefault(max, finiteOrDefault(min, max))
+ };
+ }
+ getPadding() {
+ return {
+ left: this.paddingLeft || 0,
+ top: this.paddingTop || 0,
+ right: this.paddingRight || 0,
+ bottom: this.paddingBottom || 0
+ };
+ }
+ getTicks() {
+ return this.ticks;
+ }
+ getLabels() {
+ const data = this.chart.data;
+ return this.options.labels || (this.isHorizontal() ? data.xLabels : data.yLabels) || data.labels || [];
+ }
+ beforeLayout() {
+ this._cache = {};
+ this._dataLimitsCached = false;
+ }
+ beforeUpdate() {
+ callback(this.options.beforeUpdate, [this]);
+ }
+ update(maxWidth, maxHeight, margins) {
+ const {beginAtZero, grace, ticks: tickOpts} = this.options;
+ const sampleSize = tickOpts.sampleSize;
+ this.beforeUpdate();
+ this.maxWidth = maxWidth;
+ this.maxHeight = maxHeight;
+ this._margins = margins = Object.assign({
+ left: 0,
+ right: 0,
+ top: 0,
+ bottom: 0
+ }, margins);
+ this.ticks = null;
+ this._labelSizes = null;
+ this._gridLineItems = null;
+ this._labelItems = null;
+ this.beforeSetDimensions();
+ this.setDimensions();
+ this.afterSetDimensions();
+ this._maxLength = this.isHorizontal()
+ ? this.width + margins.left + margins.right
+ : this.height + margins.top + margins.bottom;
+ if (!this._dataLimitsCached) {
+ this.beforeDataLimits();
+ this.determineDataLimits();
+ this.afterDataLimits();
+ this._range = _addGrace(this, grace, beginAtZero);
+ this._dataLimitsCached = true;
+ }
+ this.beforeBuildTicks();
+ this.ticks = this.buildTicks() || [];
+ this.afterBuildTicks();
+ const samplingEnabled = sampleSize < this.ticks.length;
+ this._convertTicksToLabels(samplingEnabled ? sample(this.ticks, sampleSize) : this.ticks);
+ this.configure();
+ this.beforeCalculateLabelRotation();
+ this.calculateLabelRotation();
+ this.afterCalculateLabelRotation();
+ if (tickOpts.display && (tickOpts.autoSkip || tickOpts.source === 'auto')) {
+ this.ticks = autoSkip(this, this.ticks);
+ this._labelSizes = null;
+ }
+ if (samplingEnabled) {
+ this._convertTicksToLabels(this.ticks);
+ }
+ this.beforeFit();
+ this.fit();
+ this.afterFit();
+ this.afterUpdate();
+ }
+ configure() {
+ let reversePixels = this.options.reverse;
+ let startPixel, endPixel;
+ if (this.isHorizontal()) {
+ startPixel = this.left;
+ endPixel = this.right;
+ } else {
+ startPixel = this.top;
+ endPixel = this.bottom;
+ reversePixels = !reversePixels;
+ }
+ this._startPixel = startPixel;
+ this._endPixel = endPixel;
+ this._reversePixels = reversePixels;
+ this._length = endPixel - startPixel;
+ this._alignToPixels = this.options.alignToPixels;
+ }
+ afterUpdate() {
+ callback(this.options.afterUpdate, [this]);
+ }
+ beforeSetDimensions() {
+ callback(this.options.beforeSetDimensions, [this]);
+ }
+ setDimensions() {
+ if (this.isHorizontal()) {
+ this.width = this.maxWidth;
+ this.left = 0;
+ this.right = this.width;
+ } else {
+ this.height = this.maxHeight;
+ this.top = 0;
+ this.bottom = this.height;
+ }
+ this.paddingLeft = 0;
+ this.paddingTop = 0;
+ this.paddingRight = 0;
+ this.paddingBottom = 0;
+ }
+ afterSetDimensions() {
+ callback(this.options.afterSetDimensions, [this]);
+ }
+ _callHooks(name) {
+ this.chart.notifyPlugins(name, this.getContext());
+ callback(this.options[name], [this]);
+ }
+ beforeDataLimits() {
+ this._callHooks('beforeDataLimits');
+ }
+ determineDataLimits() {}
+ afterDataLimits() {
+ this._callHooks('afterDataLimits');
+ }
+ beforeBuildTicks() {
+ this._callHooks('beforeBuildTicks');
+ }
+ buildTicks() {
+ return [];
+ }
+ afterBuildTicks() {
+ this._callHooks('afterBuildTicks');
+ }
+ beforeTickToLabelConversion() {
+ callback(this.options.beforeTickToLabelConversion, [this]);
+ }
+ generateTickLabels(ticks) {
+ const tickOpts = this.options.ticks;
+ let i, ilen, tick;
+ for (i = 0, ilen = ticks.length; i < ilen; i++) {
+ tick = ticks[i];
+ tick.label = callback(tickOpts.callback, [tick.value, i, ticks], this);
+ }
+ }
+ afterTickToLabelConversion() {
+ callback(this.options.afterTickToLabelConversion, [this]);
+ }
+ beforeCalculateLabelRotation() {
+ callback(this.options.beforeCalculateLabelRotation, [this]);
+ }
+ calculateLabelRotation() {
+ const options = this.options;
+ const tickOpts = options.ticks;
+ const numTicks = this.ticks.length;
+ const minRotation = tickOpts.minRotation || 0;
+ const maxRotation = tickOpts.maxRotation;
+ let labelRotation = minRotation;
+ let tickWidth, maxHeight, maxLabelDiagonal;
+ if (!this._isVisible() || !tickOpts.display || minRotation >= maxRotation || numTicks <= 1 || !this.isHorizontal()) {
+ this.labelRotation = minRotation;
+ return;
+ }
+ const labelSizes = this._getLabelSizes();
+ const maxLabelWidth = labelSizes.widest.width;
+ const maxLabelHeight = labelSizes.highest.height;
+ const maxWidth = _limitValue(this.chart.width - maxLabelWidth, 0, this.maxWidth);
+ tickWidth = options.offset ? this.maxWidth / numTicks : maxWidth / (numTicks - 1);
+ if (maxLabelWidth + 6 > tickWidth) {
+ tickWidth = maxWidth / (numTicks - (options.offset ? 0.5 : 1));
+ maxHeight = this.maxHeight - getTickMarkLength(options.grid)
+ - tickOpts.padding - getTitleHeight(options.title, this.chart.options.font);
+ maxLabelDiagonal = Math.sqrt(maxLabelWidth * maxLabelWidth + maxLabelHeight * maxLabelHeight);
+ labelRotation = toDegrees(Math.min(
+ Math.asin(_limitValue((labelSizes.highest.height + 6) / tickWidth, -1, 1)),
+ Math.asin(_limitValue(maxHeight / maxLabelDiagonal, -1, 1)) - Math.asin(_limitValue(maxLabelHeight / maxLabelDiagonal, -1, 1))
+ ));
+ labelRotation = Math.max(minRotation, Math.min(maxRotation, labelRotation));
+ }
+ this.labelRotation = labelRotation;
+ }
+ afterCalculateLabelRotation() {
+ callback(this.options.afterCalculateLabelRotation, [this]);
+ }
+ beforeFit() {
+ callback(this.options.beforeFit, [this]);
+ }
+ fit() {
+ const minSize = {
+ width: 0,
+ height: 0
+ };
+ const {chart, options: {ticks: tickOpts, title: titleOpts, grid: gridOpts}} = this;
+ const display = this._isVisible();
+ const isHorizontal = this.isHorizontal();
+ if (display) {
+ const titleHeight = getTitleHeight(titleOpts, chart.options.font);
+ if (isHorizontal) {
+ minSize.width = this.maxWidth;
+ minSize.height = getTickMarkLength(gridOpts) + titleHeight;
+ } else {
+ minSize.height = this.maxHeight;
+ minSize.width = getTickMarkLength(gridOpts) + titleHeight;
+ }
+ if (tickOpts.display && this.ticks.length) {
+ const {first, last, widest, highest} = this._getLabelSizes();
+ const tickPadding = tickOpts.padding * 2;
+ const angleRadians = toRadians(this.labelRotation);
+ const cos = Math.cos(angleRadians);
+ const sin = Math.sin(angleRadians);
+ if (isHorizontal) {
+ const labelHeight = tickOpts.mirror ? 0 : sin * widest.width + cos * highest.height;
+ minSize.height = Math.min(this.maxHeight, minSize.height + labelHeight + tickPadding);
+ } else {
+ const labelWidth = tickOpts.mirror ? 0 : cos * widest.width + sin * highest.height;
+ minSize.width = Math.min(this.maxWidth, minSize.width + labelWidth + tickPadding);
+ }
+ this._calculatePadding(first, last, sin, cos);
+ }
+ }
+ this._handleMargins();
+ if (isHorizontal) {
+ this.width = this._length = chart.width - this._margins.left - this._margins.right;
+ this.height = minSize.height;
+ } else {
+ this.width = minSize.width;
+ this.height = this._length = chart.height - this._margins.top - this._margins.bottom;
+ }
+ }
+ _calculatePadding(first, last, sin, cos) {
+ const {ticks: {align, padding}, position} = this.options;
+ const isRotated = this.labelRotation !== 0;
+ const labelsBelowTicks = position !== 'top' && this.axis === 'x';
+ if (this.isHorizontal()) {
+ const offsetLeft = this.getPixelForTick(0) - this.left;
+ const offsetRight = this.right - this.getPixelForTick(this.ticks.length - 1);
+ let paddingLeft = 0;
+ let paddingRight = 0;
+ if (isRotated) {
+ if (labelsBelowTicks) {
+ paddingLeft = cos * first.width;
+ paddingRight = sin * last.height;
+ } else {
+ paddingLeft = sin * first.height;
+ paddingRight = cos * last.width;
+ }
+ } else if (align === 'start') {
+ paddingRight = last.width;
+ } else if (align === 'end') {
+ paddingLeft = first.width;
+ } else {
+ paddingLeft = first.width / 2;
+ paddingRight = last.width / 2;
+ }
+ this.paddingLeft = Math.max((paddingLeft - offsetLeft + padding) * this.width / (this.width - offsetLeft), 0);
+ this.paddingRight = Math.max((paddingRight - offsetRight + padding) * this.width / (this.width - offsetRight), 0);
+ } else {
+ let paddingTop = last.height / 2;
+ let paddingBottom = first.height / 2;
+ if (align === 'start') {
+ paddingTop = 0;
+ paddingBottom = first.height;
+ } else if (align === 'end') {
+ paddingTop = last.height;
+ paddingBottom = 0;
+ }
+ this.paddingTop = paddingTop + padding;
+ this.paddingBottom = paddingBottom + padding;
+ }
+ }
+ _handleMargins() {
+ if (this._margins) {
+ this._margins.left = Math.max(this.paddingLeft, this._margins.left);
+ this._margins.top = Math.max(this.paddingTop, this._margins.top);
+ this._margins.right = Math.max(this.paddingRight, this._margins.right);
+ this._margins.bottom = Math.max(this.paddingBottom, this._margins.bottom);
+ }
+ }
+ afterFit() {
+ callback(this.options.afterFit, [this]);
+ }
+ isHorizontal() {
+ const {axis, position} = this.options;
+ return position === 'top' || position === 'bottom' || axis === 'x';
+ }
+ isFullSize() {
+ return this.options.fullSize;
+ }
+ _convertTicksToLabels(ticks) {
+ this.beforeTickToLabelConversion();
+ this.generateTickLabels(ticks);
+ let i, ilen;
+ for (i = 0, ilen = ticks.length; i < ilen; i++) {
+ if (isNullOrUndef(ticks[i].label)) {
+ ticks.splice(i, 1);
+ ilen--;
+ i--;
+ }
+ }
+ this.afterTickToLabelConversion();
+ }
+ _getLabelSizes() {
+ let labelSizes = this._labelSizes;
+ if (!labelSizes) {
+ const sampleSize = this.options.ticks.sampleSize;
+ let ticks = this.ticks;
+ if (sampleSize < ticks.length) {
+ ticks = sample(ticks, sampleSize);
+ }
+ this._labelSizes = labelSizes = this._computeLabelSizes(ticks, ticks.length);
+ }
+ return labelSizes;
+ }
+ _computeLabelSizes(ticks, length) {
+ const {ctx, _longestTextCache: caches} = this;
+ const widths = [];
+ const heights = [];
+ let widestLabelSize = 0;
+ let highestLabelSize = 0;
+ let i, j, jlen, label, tickFont, fontString, cache, lineHeight, width, height, nestedLabel;
+ for (i = 0; i < length; ++i) {
+ label = ticks[i].label;
+ tickFont = this._resolveTickFontOptions(i);
+ ctx.font = fontString = tickFont.string;
+ cache = caches[fontString] = caches[fontString] || {data: {}, gc: []};
+ lineHeight = tickFont.lineHeight;
+ width = height = 0;
+ if (!isNullOrUndef(label) && !isArray(label)) {
+ width = _measureText(ctx, cache.data, cache.gc, width, label);
+ height = lineHeight;
+ } else if (isArray(label)) {
+ for (j = 0, jlen = label.length; j < jlen; ++j) {
+ nestedLabel = label[j];
+ if (!isNullOrUndef(nestedLabel) && !isArray(nestedLabel)) {
+ width = _measureText(ctx, cache.data, cache.gc, width, nestedLabel);
+ height += lineHeight;
+ }
+ }
+ }
+ widths.push(width);
+ heights.push(height);
+ widestLabelSize = Math.max(width, widestLabelSize);
+ highestLabelSize = Math.max(height, highestLabelSize);
+ }
+ garbageCollect(caches, length);
+ const widest = widths.indexOf(widestLabelSize);
+ const highest = heights.indexOf(highestLabelSize);
+ const valueAt = (idx) => ({width: widths[idx] || 0, height: heights[idx] || 0});
+ return {
+ first: valueAt(0),
+ last: valueAt(length - 1),
+ widest: valueAt(widest),
+ highest: valueAt(highest),
+ widths,
+ heights,
+ };
+ }
+ getLabelForValue(value) {
+ return value;
+ }
+ getPixelForValue(value, index) {
+ return NaN;
+ }
+ getValueForPixel(pixel) {}
+ getPixelForTick(index) {
+ const ticks = this.ticks;
+ if (index < 0 || index > ticks.length - 1) {
+ return null;
+ }
+ return this.getPixelForValue(ticks[index].value);
+ }
+ getPixelForDecimal(decimal) {
+ if (this._reversePixels) {
+ decimal = 1 - decimal;
+ }
+ const pixel = this._startPixel + decimal * this._length;
+ return _int16Range(this._alignToPixels ? _alignPixel(this.chart, pixel, 0) : pixel);
+ }
+ getDecimalForPixel(pixel) {
+ const decimal = (pixel - this._startPixel) / this._length;
+ return this._reversePixels ? 1 - decimal : decimal;
+ }
+ getBasePixel() {
+ return this.getPixelForValue(this.getBaseValue());
+ }
+ getBaseValue() {
+ const {min, max} = this;
+ return min < 0 && max < 0 ? max :
+ min > 0 && max > 0 ? min :
+ 0;
+ }
+ getContext(index) {
+ const ticks = this.ticks || [];
+ if (index >= 0 && index < ticks.length) {
+ const tick = ticks[index];
+ return tick.$context ||
+ (tick.$context = createTickContext(this.getContext(), index, tick));
+ }
+ return this.$context ||
+ (this.$context = createScaleContext(this.chart.getContext(), this));
+ }
+ _tickSize() {
+ const optionTicks = this.options.ticks;
+ const rot = toRadians(this.labelRotation);
+ const cos = Math.abs(Math.cos(rot));
+ const sin = Math.abs(Math.sin(rot));
+ const labelSizes = this._getLabelSizes();
+ const padding = optionTicks.autoSkipPadding || 0;
+ const w = labelSizes ? labelSizes.widest.width + padding : 0;
+ const h = labelSizes ? labelSizes.highest.height + padding : 0;
+ return this.isHorizontal()
+ ? h * cos > w * sin ? w / cos : h / sin
+ : h * sin < w * cos ? h / cos : w / sin;
+ }
+ _isVisible() {
+ const display = this.options.display;
+ if (display !== 'auto') {
+ return !!display;
+ }
+ return this.getMatchingVisibleMetas().length > 0;
+ }
+ _computeGridLineItems(chartArea) {
+ const axis = this.axis;
+ const chart = this.chart;
+ const options = this.options;
+ const {grid, position} = options;
+ const offset = grid.offset;
+ const isHorizontal = this.isHorizontal();
+ const ticks = this.ticks;
+ const ticksLength = ticks.length + (offset ? 1 : 0);
+ const tl = getTickMarkLength(grid);
+ const items = [];
+ const borderOpts = grid.setContext(this.getContext());
+ const axisWidth = borderOpts.drawBorder ? borderOpts.borderWidth : 0;
+ const axisHalfWidth = axisWidth / 2;
+ const alignBorderValue = function(pixel) {
+ return _alignPixel(chart, pixel, axisWidth);
+ };
+ let borderValue, i, lineValue, alignedLineValue;
+ let tx1, ty1, tx2, ty2, x1, y1, x2, y2;
+ if (position === 'top') {
+ borderValue = alignBorderValue(this.bottom);
+ ty1 = this.bottom - tl;
+ ty2 = borderValue - axisHalfWidth;
+ y1 = alignBorderValue(chartArea.top) + axisHalfWidth;
+ y2 = chartArea.bottom;
+ } else if (position === 'bottom') {
+ borderValue = alignBorderValue(this.top);
+ y1 = chartArea.top;
+ y2 = alignBorderValue(chartArea.bottom) - axisHalfWidth;
+ ty1 = borderValue + axisHalfWidth;
+ ty2 = this.top + tl;
+ } else if (position === 'left') {
+ borderValue = alignBorderValue(this.right);
+ tx1 = this.right - tl;
+ tx2 = borderValue - axisHalfWidth;
+ x1 = alignBorderValue(chartArea.left) + axisHalfWidth;
+ x2 = chartArea.right;
+ } else if (position === 'right') {
+ borderValue = alignBorderValue(this.left);
+ x1 = chartArea.left;
+ x2 = alignBorderValue(chartArea.right) - axisHalfWidth;
+ tx1 = borderValue + axisHalfWidth;
+ tx2 = this.left + tl;
+ } else if (axis === 'x') {
+ if (position === 'center') {
+ borderValue = alignBorderValue((chartArea.top + chartArea.bottom) / 2 + 0.5);
+ } else if (isObject(position)) {
+ const positionAxisID = Object.keys(position)[0];
+ const value = position[positionAxisID];
+ borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));
+ }
+ y1 = chartArea.top;
+ y2 = chartArea.bottom;
+ ty1 = borderValue + axisHalfWidth;
+ ty2 = ty1 + tl;
+ } else if (axis === 'y') {
+ if (position === 'center') {
+ borderValue = alignBorderValue((chartArea.left + chartArea.right) / 2);
+ } else if (isObject(position)) {
+ const positionAxisID = Object.keys(position)[0];
+ const value = position[positionAxisID];
+ borderValue = alignBorderValue(this.chart.scales[positionAxisID].getPixelForValue(value));
+ }
+ tx1 = borderValue - axisHalfWidth;
+ tx2 = tx1 - tl;
+ x1 = chartArea.left;
+ x2 = chartArea.right;
+ }
+ const limit = valueOrDefault(options.ticks.maxTicksLimit, ticksLength);
+ const step = Math.max(1, Math.ceil(ticksLength / limit));
+ for (i = 0; i < ticksLength; i += step) {
+ const optsAtIndex = grid.setContext(this.getContext(i));
+ const lineWidth = optsAtIndex.lineWidth;
+ const lineColor = optsAtIndex.color;
+ const borderDash = grid.borderDash || [];
+ const borderDashOffset = optsAtIndex.borderDashOffset;
+ const tickWidth = optsAtIndex.tickWidth;
+ const tickColor = optsAtIndex.tickColor;
+ const tickBorderDash = optsAtIndex.tickBorderDash || [];
+ const tickBorderDashOffset = optsAtIndex.tickBorderDashOffset;
+ lineValue = getPixelForGridLine(this, i, offset);
+ if (lineValue === undefined) {
+ continue;
+ }
+ alignedLineValue = _alignPixel(chart, lineValue, lineWidth);
+ if (isHorizontal) {
+ tx1 = tx2 = x1 = x2 = alignedLineValue;
+ } else {
+ ty1 = ty2 = y1 = y2 = alignedLineValue;
+ }
+ items.push({
+ tx1,
+ ty1,
+ tx2,
+ ty2,
+ x1,
+ y1,
+ x2,
+ y2,
+ width: lineWidth,
+ color: lineColor,
+ borderDash,
+ borderDashOffset,
+ tickWidth,
+ tickColor,
+ tickBorderDash,
+ tickBorderDashOffset,
+ });
+ }
+ this._ticksLength = ticksLength;
+ this._borderValue = borderValue;
+ return items;
+ }
+ _computeLabelItems(chartArea) {
+ const axis = this.axis;
+ const options = this.options;
+ const {position, ticks: optionTicks} = options;
+ const isHorizontal = this.isHorizontal();
+ const ticks = this.ticks;
+ const {align, crossAlign, padding, mirror} = optionTicks;
+ const tl = getTickMarkLength(options.grid);
+ const tickAndPadding = tl + padding;
+ const hTickAndPadding = mirror ? -padding : tickAndPadding;
+ const rotation = -toRadians(this.labelRotation);
+ const items = [];
+ let i, ilen, tick, label, x, y, textAlign, pixel, font, lineHeight, lineCount, textOffset;
+ let textBaseline = 'middle';
+ if (position === 'top') {
+ y = this.bottom - hTickAndPadding;
+ textAlign = this._getXAxisLabelAlignment();
+ } else if (position === 'bottom') {
+ y = this.top + hTickAndPadding;
+ textAlign = this._getXAxisLabelAlignment();
+ } else if (position === 'left') {
+ const ret = this._getYAxisLabelAlignment(tl);
+ textAlign = ret.textAlign;
+ x = ret.x;
+ } else if (position === 'right') {
+ const ret = this._getYAxisLabelAlignment(tl);
+ textAlign = ret.textAlign;
+ x = ret.x;
+ } else if (axis === 'x') {
+ if (position === 'center') {
+ y = ((chartArea.top + chartArea.bottom) / 2) + tickAndPadding;
+ } else if (isObject(position)) {
+ const positionAxisID = Object.keys(position)[0];
+ const value = position[positionAxisID];
+ y = this.chart.scales[positionAxisID].getPixelForValue(value) + tickAndPadding;
+ }
+ textAlign = this._getXAxisLabelAlignment();
+ } else if (axis === 'y') {
+ if (position === 'center') {
+ x = ((chartArea.left + chartArea.right) / 2) - tickAndPadding;
+ } else if (isObject(position)) {
+ const positionAxisID = Object.keys(position)[0];
+ const value = position[positionAxisID];
+ x = this.chart.scales[positionAxisID].getPixelForValue(value);
+ }
+ textAlign = this._getYAxisLabelAlignment(tl).textAlign;
+ }
+ if (axis === 'y') {
+ if (align === 'start') {
+ textBaseline = 'top';
+ } else if (align === 'end') {
+ textBaseline = 'bottom';
+ }
+ }
+ const labelSizes = this._getLabelSizes();
+ for (i = 0, ilen = ticks.length; i < ilen; ++i) {
+ tick = ticks[i];
+ label = tick.label;
+ const optsAtIndex = optionTicks.setContext(this.getContext(i));
+ pixel = this.getPixelForTick(i) + optionTicks.labelOffset;
+ font = this._resolveTickFontOptions(i);
+ lineHeight = font.lineHeight;
+ lineCount = isArray(label) ? label.length : 1;
+ const halfCount = lineCount / 2;
+ const color = optsAtIndex.color;
+ const strokeColor = optsAtIndex.textStrokeColor;
+ const strokeWidth = optsAtIndex.textStrokeWidth;
+ if (isHorizontal) {
+ x = pixel;
+ if (position === 'top') {
+ if (crossAlign === 'near' || rotation !== 0) {
+ textOffset = -lineCount * lineHeight + lineHeight / 2;
+ } else if (crossAlign === 'center') {
+ textOffset = -labelSizes.highest.height / 2 - halfCount * lineHeight + lineHeight;
+ } else {
+ textOffset = -labelSizes.highest.height + lineHeight / 2;
+ }
+ } else {
+ if (crossAlign === 'near' || rotation !== 0) {
+ textOffset = lineHeight / 2;
+ } else if (crossAlign === 'center') {
+ textOffset = labelSizes.highest.height / 2 - halfCount * lineHeight;
+ } else {
+ textOffset = labelSizes.highest.height - lineCount * lineHeight;
+ }
+ }
+ if (mirror) {
+ textOffset *= -1;
+ }
+ } else {
+ y = pixel;
+ textOffset = (1 - lineCount) * lineHeight / 2;
+ }
+ let backdrop;
+ if (optsAtIndex.showLabelBackdrop) {
+ const labelPadding = toPadding(optsAtIndex.backdropPadding);
+ const height = labelSizes.heights[i];
+ const width = labelSizes.widths[i];
+ let top = y + textOffset - labelPadding.top;
+ let left = x - labelPadding.left;
+ switch (textBaseline) {
+ case 'middle':
+ top -= height / 2;
+ break;
+ case 'bottom':
+ top -= height;
+ break;
+ }
+ switch (textAlign) {
+ case 'center':
+ left -= width / 2;
+ break;
+ case 'right':
+ left -= width;
+ break;
+ }
+ backdrop = {
+ left,
+ top,
+ width: width + labelPadding.width,
+ height: height + labelPadding.height,
+ color: optsAtIndex.backdropColor,
+ };
+ }
+ items.push({
+ rotation,
+ label,
+ font,
+ color,
+ strokeColor,
+ strokeWidth,
+ textOffset,
+ textAlign,
+ textBaseline,
+ translation: [x, y],
+ backdrop,
+ });
+ }
+ return items;
+ }
+ _getXAxisLabelAlignment() {
+ const {position, ticks} = this.options;
+ const rotation = -toRadians(this.labelRotation);
+ if (rotation) {
+ return position === 'top' ? 'left' : 'right';
+ }
+ let align = 'center';
+ if (ticks.align === 'start') {
+ align = 'left';
+ } else if (ticks.align === 'end') {
+ align = 'right';
+ }
+ return align;
+ }
+ _getYAxisLabelAlignment(tl) {
+ const {position, ticks: {crossAlign, mirror, padding}} = this.options;
+ const labelSizes = this._getLabelSizes();
+ const tickAndPadding = tl + padding;
+ const widest = labelSizes.widest.width;
+ let textAlign;
+ let x;
+ if (position === 'left') {
+ if (mirror) {
+ x = this.right + padding;
+ if (crossAlign === 'near') {
+ textAlign = 'left';
+ } else if (crossAlign === 'center') {
+ textAlign = 'center';
+ x += (widest / 2);
+ } else {
+ textAlign = 'right';
+ x += widest;
+ }
+ } else {
+ x = this.right - tickAndPadding;
+ if (crossAlign === 'near') {
+ textAlign = 'right';
+ } else if (crossAlign === 'center') {
+ textAlign = 'center';
+ x -= (widest / 2);
+ } else {
+ textAlign = 'left';
+ x = this.left;
+ }
+ }
+ } else if (position === 'right') {
+ if (mirror) {
+ x = this.left + padding;
+ if (crossAlign === 'near') {
+ textAlign = 'right';
+ } else if (crossAlign === 'center') {
+ textAlign = 'center';
+ x -= (widest / 2);
+ } else {
+ textAlign = 'left';
+ x -= widest;
+ }
+ } else {
+ x = this.left + tickAndPadding;
+ if (crossAlign === 'near') {
+ textAlign = 'left';
+ } else if (crossAlign === 'center') {
+ textAlign = 'center';
+ x += widest / 2;
+ } else {
+ textAlign = 'right';
+ x = this.right;
+ }
+ }
+ } else {
+ textAlign = 'right';
+ }
+ return {textAlign, x};
+ }
+ _computeLabelArea() {
+ if (this.options.ticks.mirror) {
+ return;
+ }
+ const chart = this.chart;
+ const position = this.options.position;
+ if (position === 'left' || position === 'right') {
+ return {top: 0, left: this.left, bottom: chart.height, right: this.right};
+ } if (position === 'top' || position === 'bottom') {
+ return {top: this.top, left: 0, bottom: this.bottom, right: chart.width};
+ }
+ }
+ drawBackground() {
+ const {ctx, options: {backgroundColor}, left, top, width, height} = this;
+ if (backgroundColor) {
+ ctx.save();
+ ctx.fillStyle = backgroundColor;
+ ctx.fillRect(left, top, width, height);
+ ctx.restore();
+ }
+ }
+ getLineWidthForValue(value) {
+ const grid = this.options.grid;
+ if (!this._isVisible() || !grid.display) {
+ return 0;
+ }
+ const ticks = this.ticks;
+ const index = ticks.findIndex(t => t.value === value);
+ if (index >= 0) {
+ const opts = grid.setContext(this.getContext(index));
+ return opts.lineWidth;
+ }
+ return 0;
+ }
+ drawGrid(chartArea) {
+ const grid = this.options.grid;
+ const ctx = this.ctx;
+ const items = this._gridLineItems || (this._gridLineItems = this._computeGridLineItems(chartArea));
+ let i, ilen;
+ const drawLine = (p1, p2, style) => {
+ if (!style.width || !style.color) {
+ return;
+ }
+ ctx.save();
+ ctx.lineWidth = style.width;
+ ctx.strokeStyle = style.color;
+ ctx.setLineDash(style.borderDash || []);
+ ctx.lineDashOffset = style.borderDashOffset;
+ ctx.beginPath();
+ ctx.moveTo(p1.x, p1.y);
+ ctx.lineTo(p2.x, p2.y);
+ ctx.stroke();
+ ctx.restore();
+ };
+ if (grid.display) {
+ for (i = 0, ilen = items.length; i < ilen; ++i) {
+ const item = items[i];
+ if (grid.drawOnChartArea) {
+ drawLine(
+ {x: item.x1, y: item.y1},
+ {x: item.x2, y: item.y2},
+ item
+ );
+ }
+ if (grid.drawTicks) {
+ drawLine(
+ {x: item.tx1, y: item.ty1},
+ {x: item.tx2, y: item.ty2},
+ {
+ color: item.tickColor,
+ width: item.tickWidth,
+ borderDash: item.tickBorderDash,
+ borderDashOffset: item.tickBorderDashOffset
+ }
+ );
+ }
+ }
+ }
+ }
+ drawBorder() {
+ const {chart, ctx, options: {grid}} = this;
+ const borderOpts = grid.setContext(this.getContext());
+ const axisWidth = grid.drawBorder ? borderOpts.borderWidth : 0;
+ if (!axisWidth) {
+ return;
+ }
+ const lastLineWidth = grid.setContext(this.getContext(0)).lineWidth;
+ const borderValue = this._borderValue;
+ let x1, x2, y1, y2;
+ if (this.isHorizontal()) {
+ x1 = _alignPixel(chart, this.left, axisWidth) - axisWidth / 2;
+ x2 = _alignPixel(chart, this.right, lastLineWidth) + lastLineWidth / 2;
+ y1 = y2 = borderValue;
+ } else {
+ y1 = _alignPixel(chart, this.top, axisWidth) - axisWidth / 2;
+ y2 = _alignPixel(chart, this.bottom, lastLineWidth) + lastLineWidth / 2;
+ x1 = x2 = borderValue;
+ }
+ ctx.save();
+ ctx.lineWidth = borderOpts.borderWidth;
+ ctx.strokeStyle = borderOpts.borderColor;
+ ctx.beginPath();
+ ctx.moveTo(x1, y1);
+ ctx.lineTo(x2, y2);
+ ctx.stroke();
+ ctx.restore();
+ }
+ drawLabels(chartArea) {
+ const optionTicks = this.options.ticks;
+ if (!optionTicks.display) {
+ return;
+ }
+ const ctx = this.ctx;
+ const area = this._computeLabelArea();
+ if (area) {
+ clipArea(ctx, area);
+ }
+ const items = this._labelItems || (this._labelItems = this._computeLabelItems(chartArea));
+ let i, ilen;
+ for (i = 0, ilen = items.length; i < ilen; ++i) {
+ const item = items[i];
+ const tickFont = item.font;
+ const label = item.label;
+ if (item.backdrop) {
+ ctx.fillStyle = item.backdrop.color;
+ ctx.fillRect(item.backdrop.left, item.backdrop.top, item.backdrop.width, item.backdrop.height);
+ }
+ let y = item.textOffset;
+ renderText(ctx, label, 0, y, tickFont, item);
+ }
+ if (area) {
+ unclipArea(ctx);
+ }
+ }
+ drawTitle() {
+ const {ctx, options: {position, title, reverse}} = this;
+ if (!title.display) {
+ return;
+ }
+ const font = toFont(title.font);
+ const padding = toPadding(title.padding);
+ const align = title.align;
+ let offset = font.lineHeight / 2;
+ if (position === 'bottom' || position === 'center' || isObject(position)) {
+ offset += padding.bottom;
+ if (isArray(title.text)) {
+ offset += font.lineHeight * (title.text.length - 1);
+ }
+ } else {
+ offset += padding.top;
+ }
+ const {titleX, titleY, maxWidth, rotation} = titleArgs(this, offset, position, align);
+ renderText(ctx, title.text, 0, 0, font, {
+ color: title.color,
+ maxWidth,
+ rotation,
+ textAlign: titleAlign(align, position, reverse),
+ textBaseline: 'middle',
+ translation: [titleX, titleY],
+ });
+ }
+ draw(chartArea) {
+ if (!this._isVisible()) {
+ return;
+ }
+ this.drawBackground();
+ this.drawGrid(chartArea);
+ this.drawBorder();
+ this.drawTitle();
+ this.drawLabels(chartArea);
+ }
+ _layers() {
+ const opts = this.options;
+ const tz = opts.ticks && opts.ticks.z || 0;
+ const gz = valueOrDefault(opts.grid && opts.grid.z, -1);
+ if (!this._isVisible() || this.draw !== Scale.prototype.draw) {
+ return [{
+ z: tz,
+ draw: (chartArea) => {
+ this.draw(chartArea);
+ }
+ }];
+ }
+ return [{
+ z: gz,
+ draw: (chartArea) => {
+ this.drawBackground();
+ this.drawGrid(chartArea);
+ this.drawTitle();
+ }
+ }, {
+ z: gz + 1,
+ draw: () => {
+ this.drawBorder();
+ }
+ }, {
+ z: tz,
+ draw: (chartArea) => {
+ this.drawLabels(chartArea);
+ }
+ }];
+ }
+ getMatchingVisibleMetas(type) {
+ const metas = this.chart.getSortedVisibleDatasetMetas();
+ const axisID = this.axis + 'AxisID';
+ const result = [];
+ let i, ilen;
+ for (i = 0, ilen = metas.length; i < ilen; ++i) {
+ const meta = metas[i];
+ if (meta[axisID] === this.id && (!type || meta.type === type)) {
+ result.push(meta);
+ }
+ }
+ return result;
+ }
+ _resolveTickFontOptions(index) {
+ const opts = this.options.ticks.setContext(this.getContext(index));
+ return toFont(opts.font);
+ }
+ _maxDigits() {
+ const fontSize = this._resolveTickFontOptions(0).lineHeight;
+ return (this.isHorizontal() ? this.width : this.height) / fontSize;
+ }
+}
+
+class TypedRegistry {
+ constructor(type, scope, override) {
+ this.type = type;
+ this.scope = scope;
+ this.override = override;
+ this.items = Object.create(null);
+ }
+ isForType(type) {
+ return Object.prototype.isPrototypeOf.call(this.type.prototype, type.prototype);
+ }
+ register(item) {
+ const proto = Object.getPrototypeOf(item);
+ let parentScope;
+ if (isIChartComponent(proto)) {
+ parentScope = this.register(proto);
+ }
+ const items = this.items;
+ const id = item.id;
+ const scope = this.scope + '.' + id;
+ if (!id) {
+ throw new Error('class does not have id: ' + item);
+ }
+ if (id in items) {
+ return scope;
+ }
+ items[id] = item;
+ registerDefaults(item, scope, parentScope);
+ if (this.override) {
+ defaults.override(item.id, item.overrides);
+ }
+ return scope;
+ }
+ get(id) {
+ return this.items[id];
+ }
+ unregister(item) {
+ const items = this.items;
+ const id = item.id;
+ const scope = this.scope;
+ if (id in items) {
+ delete items[id];
+ }
+ if (scope && id in defaults[scope]) {
+ delete defaults[scope][id];
+ if (this.override) {
+ delete overrides[id];
+ }
+ }
+ }
+}
+function registerDefaults(item, scope, parentScope) {
+ const itemDefaults = merge(Object.create(null), [
+ parentScope ? defaults.get(parentScope) : {},
+ defaults.get(scope),
+ item.defaults
+ ]);
+ defaults.set(scope, itemDefaults);
+ if (item.defaultRoutes) {
+ routeDefaults(scope, item.defaultRoutes);
+ }
+ if (item.descriptors) {
+ defaults.describe(scope, item.descriptors);
+ }
+}
+function routeDefaults(scope, routes) {
+ Object.keys(routes).forEach(property => {
+ const propertyParts = property.split('.');
+ const sourceName = propertyParts.pop();
+ const sourceScope = [scope].concat(propertyParts).join('.');
+ const parts = routes[property].split('.');
+ const targetName = parts.pop();
+ const targetScope = parts.join('.');
+ defaults.route(sourceScope, sourceName, targetScope, targetName);
+ });
+}
+function isIChartComponent(proto) {
+ return 'id' in proto && 'defaults' in proto;
+}
+
+class Registry {
+ constructor() {
+ this.controllers = new TypedRegistry(DatasetController, 'datasets', true);
+ this.elements = new TypedRegistry(Element, 'elements');
+ this.plugins = new TypedRegistry(Object, 'plugins');
+ this.scales = new TypedRegistry(Scale, 'scales');
+ this._typedRegistries = [this.controllers, this.scales, this.elements];
+ }
+ add(...args) {
+ this._each('register', args);
+ }
+ remove(...args) {
+ this._each('unregister', args);
+ }
+ addControllers(...args) {
+ this._each('register', args, this.controllers);
+ }
+ addElements(...args) {
+ this._each('register', args, this.elements);
+ }
+ addPlugins(...args) {
+ this._each('register', args, this.plugins);
+ }
+ addScales(...args) {
+ this._each('register', args, this.scales);
+ }
+ getController(id) {
+ return this._get(id, this.controllers, 'controller');
+ }
+ getElement(id) {
+ return this._get(id, this.elements, 'element');
+ }
+ getPlugin(id) {
+ return this._get(id, this.plugins, 'plugin');
+ }
+ getScale(id) {
+ return this._get(id, this.scales, 'scale');
+ }
+ removeControllers(...args) {
+ this._each('unregister', args, this.controllers);
+ }
+ removeElements(...args) {
+ this._each('unregister', args, this.elements);
+ }
+ removePlugins(...args) {
+ this._each('unregister', args, this.plugins);
+ }
+ removeScales(...args) {
+ this._each('unregister', args, this.scales);
+ }
+ _each(method, args, typedRegistry) {
+ [...args].forEach(arg => {
+ const reg = typedRegistry || this._getRegistryForType(arg);
+ if (typedRegistry || reg.isForType(arg) || (reg === this.plugins && arg.id)) {
+ this._exec(method, reg, arg);
+ } else {
+ each(arg, item => {
+ const itemReg = typedRegistry || this._getRegistryForType(item);
+ this._exec(method, itemReg, item);
+ });
+ }
+ });
+ }
+ _exec(method, registry, component) {
+ const camelMethod = _capitalize(method);
+ callback(component['before' + camelMethod], [], component);
+ registry[method](component);
+ callback(component['after' + camelMethod], [], component);
+ }
+ _getRegistryForType(type) {
+ for (let i = 0; i < this._typedRegistries.length; i++) {
+ const reg = this._typedRegistries[i];
+ if (reg.isForType(type)) {
+ return reg;
+ }
+ }
+ return this.plugins;
+ }
+ _get(id, typedRegistry, type) {
+ const item = typedRegistry.get(id);
+ if (item === undefined) {
+ throw new Error('"' + id + '" is not a registered ' + type + '.');
+ }
+ return item;
+ }
+}
+var registry = new Registry();
+
+class PluginService {
+ constructor() {
+ this._init = [];
+ }
+ notify(chart, hook, args, filter) {
+ if (hook === 'beforeInit') {
+ this._init = this._createDescriptors(chart, true);
+ this._notify(this._init, chart, 'install');
+ }
+ const descriptors = filter ? this._descriptors(chart).filter(filter) : this._descriptors(chart);
+ const result = this._notify(descriptors, chart, hook, args);
+ if (hook === 'destroy') {
+ this._notify(descriptors, chart, 'stop');
+ this._notify(this._init, chart, 'uninstall');
+ }
+ return result;
+ }
+ _notify(descriptors, chart, hook, args) {
+ args = args || {};
+ for (const descriptor of descriptors) {
+ const plugin = descriptor.plugin;
+ const method = plugin[hook];
+ const params = [chart, args, descriptor.options];
+ if (callback(method, params, plugin) === false && args.cancelable) {
+ return false;
+ }
+ }
+ return true;
+ }
+ invalidate() {
+ if (!isNullOrUndef(this._cache)) {
+ this._oldCache = this._cache;
+ this._cache = undefined;
+ }
+ }
+ _descriptors(chart) {
+ if (this._cache) {
+ return this._cache;
+ }
+ const descriptors = this._cache = this._createDescriptors(chart);
+ this._notifyStateChanges(chart);
+ return descriptors;
+ }
+ _createDescriptors(chart, all) {
+ const config = chart && chart.config;
+ const options = valueOrDefault(config.options && config.options.plugins, {});
+ const plugins = allPlugins(config);
+ return options === false && !all ? [] : createDescriptors(chart, plugins, options, all);
+ }
+ _notifyStateChanges(chart) {
+ const previousDescriptors = this._oldCache || [];
+ const descriptors = this._cache;
+ const diff = (a, b) => a.filter(x => !b.some(y => x.plugin.id === y.plugin.id));
+ this._notify(diff(previousDescriptors, descriptors), chart, 'stop');
+ this._notify(diff(descriptors, previousDescriptors), chart, 'start');
+ }
+}
+function allPlugins(config) {
+ const plugins = [];
+ const keys = Object.keys(registry.plugins.items);
+ for (let i = 0; i < keys.length; i++) {
+ plugins.push(registry.getPlugin(keys[i]));
+ }
+ const local = config.plugins || [];
+ for (let i = 0; i < local.length; i++) {
+ const plugin = local[i];
+ if (plugins.indexOf(plugin) === -1) {
+ plugins.push(plugin);
+ }
+ }
+ return plugins;
+}
+function getOpts(options, all) {
+ if (!all && options === false) {
+ return null;
+ }
+ if (options === true) {
+ return {};
+ }
+ return options;
+}
+function createDescriptors(chart, plugins, options, all) {
+ const result = [];
+ const context = chart.getContext();
+ for (let i = 0; i < plugins.length; i++) {
+ const plugin = plugins[i];
+ const id = plugin.id;
+ const opts = getOpts(options[id], all);
+ if (opts === null) {
+ continue;
+ }
+ result.push({
+ plugin,
+ options: pluginOpts(chart.config, plugin, opts, context)
+ });
+ }
+ return result;
+}
+function pluginOpts(config, plugin, opts, context) {
+ const keys = config.pluginScopeKeys(plugin);
+ const scopes = config.getOptionScopes(opts, keys);
+ return config.createResolver(scopes, context, [''], {scriptable: false, indexable: false, allKeys: true});
+}
+
+function getIndexAxis(type, options) {
+ const datasetDefaults = defaults.datasets[type] || {};
+ const datasetOptions = (options.datasets || {})[type] || {};
+ return datasetOptions.indexAxis || options.indexAxis || datasetDefaults.indexAxis || 'x';
+}
+function getAxisFromDefaultScaleID(id, indexAxis) {
+ let axis = id;
+ if (id === '_index_') {
+ axis = indexAxis;
+ } else if (id === '_value_') {
+ axis = indexAxis === 'x' ? 'y' : 'x';
+ }
+ return axis;
+}
+function getDefaultScaleIDFromAxis(axis, indexAxis) {
+ return axis === indexAxis ? '_index_' : '_value_';
+}
+function axisFromPosition(position) {
+ if (position === 'top' || position === 'bottom') {
+ return 'x';
+ }
+ if (position === 'left' || position === 'right') {
+ return 'y';
+ }
+}
+function determineAxis(id, scaleOptions) {
+ if (id === 'x' || id === 'y') {
+ return id;
+ }
+ return scaleOptions.axis || axisFromPosition(scaleOptions.position) || id.charAt(0).toLowerCase();
+}
+function mergeScaleConfig(config, options) {
+ const chartDefaults = overrides[config.type] || {scales: {}};
+ const configScales = options.scales || {};
+ const chartIndexAxis = getIndexAxis(config.type, options);
+ const firstIDs = Object.create(null);
+ const scales = Object.create(null);
+ Object.keys(configScales).forEach(id => {
+ const scaleConf = configScales[id];
+ if (!isObject(scaleConf)) {
+ return console.error(`Invalid scale configuration for scale: ${id}`);
+ }
+ if (scaleConf._proxy) {
+ return console.warn(`Ignoring resolver passed as options for scale: ${id}`);
+ }
+ const axis = determineAxis(id, scaleConf);
+ const defaultId = getDefaultScaleIDFromAxis(axis, chartIndexAxis);
+ const defaultScaleOptions = chartDefaults.scales || {};
+ firstIDs[axis] = firstIDs[axis] || id;
+ scales[id] = mergeIf(Object.create(null), [{axis}, scaleConf, defaultScaleOptions[axis], defaultScaleOptions[defaultId]]);
+ });
+ config.data.datasets.forEach(dataset => {
+ const type = dataset.type || config.type;
+ const indexAxis = dataset.indexAxis || getIndexAxis(type, options);
+ const datasetDefaults = overrides[type] || {};
+ const defaultScaleOptions = datasetDefaults.scales || {};
+ Object.keys(defaultScaleOptions).forEach(defaultID => {
+ const axis = getAxisFromDefaultScaleID(defaultID, indexAxis);
+ const id = dataset[axis + 'AxisID'] || firstIDs[axis] || axis;
+ scales[id] = scales[id] || Object.create(null);
+ mergeIf(scales[id], [{axis}, configScales[id], defaultScaleOptions[defaultID]]);
+ });
+ });
+ Object.keys(scales).forEach(key => {
+ const scale = scales[key];
+ mergeIf(scale, [defaults.scales[scale.type], defaults.scale]);
+ });
+ return scales;
+}
+function initOptions(config) {
+ const options = config.options || (config.options = {});
+ options.plugins = valueOrDefault(options.plugins, {});
+ options.scales = mergeScaleConfig(config, options);
+}
+function initData(data) {
+ data = data || {};
+ data.datasets = data.datasets || [];
+ data.labels = data.labels || [];
+ return data;
+}
+function initConfig(config) {
+ config = config || {};
+ config.data = initData(config.data);
+ initOptions(config);
+ return config;
+}
+const keyCache = new Map();
+const keysCached = new Set();
+function cachedKeys(cacheKey, generate) {
+ let keys = keyCache.get(cacheKey);
+ if (!keys) {
+ keys = generate();
+ keyCache.set(cacheKey, keys);
+ keysCached.add(keys);
+ }
+ return keys;
+}
+const addIfFound = (set, obj, key) => {
+ const opts = resolveObjectKey(obj, key);
+ if (opts !== undefined) {
+ set.add(opts);
+ }
+};
+class Config {
+ constructor(config) {
+ this._config = initConfig(config);
+ this._scopeCache = new Map();
+ this._resolverCache = new Map();
+ }
+ get platform() {
+ return this._config.platform;
+ }
+ get type() {
+ return this._config.type;
+ }
+ set type(type) {
+ this._config.type = type;
+ }
+ get data() {
+ return this._config.data;
+ }
+ set data(data) {
+ this._config.data = initData(data);
+ }
+ get options() {
+ return this._config.options;
+ }
+ set options(options) {
+ this._config.options = options;
+ }
+ get plugins() {
+ return this._config.plugins;
+ }
+ update() {
+ const config = this._config;
+ this.clearCache();
+ initOptions(config);
+ }
+ clearCache() {
+ this._scopeCache.clear();
+ this._resolverCache.clear();
+ }
+ datasetScopeKeys(datasetType) {
+ return cachedKeys(datasetType,
+ () => [[
+ `datasets.${datasetType}`,
+ ''
+ ]]);
+ }
+ datasetAnimationScopeKeys(datasetType, transition) {
+ return cachedKeys(`${datasetType}.transition.${transition}`,
+ () => [
+ [
+ `datasets.${datasetType}.transitions.${transition}`,
+ `transitions.${transition}`,
+ ],
+ [
+ `datasets.${datasetType}`,
+ ''
+ ]
+ ]);
+ }
+ datasetElementScopeKeys(datasetType, elementType) {
+ return cachedKeys(`${datasetType}-${elementType}`,
+ () => [[
+ `datasets.${datasetType}.elements.${elementType}`,
+ `datasets.${datasetType}`,
+ `elements.${elementType}`,
+ ''
+ ]]);
+ }
+ pluginScopeKeys(plugin) {
+ const id = plugin.id;
+ const type = this.type;
+ return cachedKeys(`${type}-plugin-${id}`,
+ () => [[
+ `plugins.${id}`,
+ ...plugin.additionalOptionScopes || [],
+ ]]);
+ }
+ _cachedScopes(mainScope, resetCache) {
+ const _scopeCache = this._scopeCache;
+ let cache = _scopeCache.get(mainScope);
+ if (!cache || resetCache) {
+ cache = new Map();
+ _scopeCache.set(mainScope, cache);
+ }
+ return cache;
+ }
+ getOptionScopes(mainScope, keyLists, resetCache) {
+ const {options, type} = this;
+ const cache = this._cachedScopes(mainScope, resetCache);
+ const cached = cache.get(keyLists);
+ if (cached) {
+ return cached;
+ }
+ const scopes = new Set();
+ keyLists.forEach(keys => {
+ if (mainScope) {
+ scopes.add(mainScope);
+ keys.forEach(key => addIfFound(scopes, mainScope, key));
+ }
+ keys.forEach(key => addIfFound(scopes, options, key));
+ keys.forEach(key => addIfFound(scopes, overrides[type] || {}, key));
+ keys.forEach(key => addIfFound(scopes, defaults, key));
+ keys.forEach(key => addIfFound(scopes, descriptors, key));
+ });
+ const array = Array.from(scopes);
+ if (array.length === 0) {
+ array.push(Object.create(null));
+ }
+ if (keysCached.has(keyLists)) {
+ cache.set(keyLists, array);
+ }
+ return array;
+ }
+ chartOptionScopes() {
+ const {options, type} = this;
+ return [
+ options,
+ overrides[type] || {},
+ defaults.datasets[type] || {},
+ {type},
+ defaults,
+ descriptors
+ ];
+ }
+ resolveNamedOptions(scopes, names, context, prefixes = ['']) {
+ const result = {$shared: true};
+ const {resolver, subPrefixes} = getResolver(this._resolverCache, scopes, prefixes);
+ let options = resolver;
+ if (needContext(resolver, names)) {
+ result.$shared = false;
+ context = isFunction(context) ? context() : context;
+ const subResolver = this.createResolver(scopes, context, subPrefixes);
+ options = _attachContext(resolver, context, subResolver);
+ }
+ for (const prop of names) {
+ result[prop] = options[prop];
+ }
+ return result;
+ }
+ createResolver(scopes, context, prefixes = [''], descriptorDefaults) {
+ const {resolver} = getResolver(this._resolverCache, scopes, prefixes);
+ return isObject(context)
+ ? _attachContext(resolver, context, undefined, descriptorDefaults)
+ : resolver;
+ }
+}
+function getResolver(resolverCache, scopes, prefixes) {
+ let cache = resolverCache.get(scopes);
+ if (!cache) {
+ cache = new Map();
+ resolverCache.set(scopes, cache);
+ }
+ const cacheKey = prefixes.join();
+ let cached = cache.get(cacheKey);
+ if (!cached) {
+ const resolver = _createResolver(scopes, prefixes);
+ cached = {
+ resolver,
+ subPrefixes: prefixes.filter(p => !p.toLowerCase().includes('hover'))
+ };
+ cache.set(cacheKey, cached);
+ }
+ return cached;
+}
+const hasFunction = value => isObject(value)
+ && Object.getOwnPropertyNames(value).reduce((acc, key) => acc || isFunction(value[key]), false);
+function needContext(proxy, names) {
+ const {isScriptable, isIndexable} = _descriptors(proxy);
+ for (const prop of names) {
+ const scriptable = isScriptable(prop);
+ const indexable = isIndexable(prop);
+ const value = (indexable || scriptable) && proxy[prop];
+ if ((scriptable && (isFunction(value) || hasFunction(value)))
+ || (indexable && isArray(value))) {
+ return true;
+ }
+ }
+ return false;
+}
+
+var version = "3.6.0";
+
+const KNOWN_POSITIONS = ['top', 'bottom', 'left', 'right', 'chartArea'];
+function positionIsHorizontal(position, axis) {
+ return position === 'top' || position === 'bottom' || (KNOWN_POSITIONS.indexOf(position) === -1 && axis === 'x');
+}
+function compare2Level(l1, l2) {
+ return function(a, b) {
+ return a[l1] === b[l1]
+ ? a[l2] - b[l2]
+ : a[l1] - b[l1];
+ };
+}
+function onAnimationsComplete(context) {
+ const chart = context.chart;
+ const animationOptions = chart.options.animation;
+ chart.notifyPlugins('afterRender');
+ callback(animationOptions && animationOptions.onComplete, [context], chart);
+}
+function onAnimationProgress(context) {
+ const chart = context.chart;
+ const animationOptions = chart.options.animation;
+ callback(animationOptions && animationOptions.onProgress, [context], chart);
+}
+function getCanvas(item) {
+ if (_isDomSupported() && typeof item === 'string') {
+ item = document.getElementById(item);
+ } else if (item && item.length) {
+ item = item[0];
+ }
+ if (item && item.canvas) {
+ item = item.canvas;
+ }
+ return item;
+}
+const instances = {};
+const getChart = (key) => {
+ const canvas = getCanvas(key);
+ return Object.values(instances).filter((c) => c.canvas === canvas).pop();
+};
+class Chart {
+ constructor(item, userConfig) {
+ const config = this.config = new Config(userConfig);
+ const initialCanvas = getCanvas(item);
+ const existingChart = getChart(initialCanvas);
+ if (existingChart) {
+ throw new Error(
+ 'Canvas is already in use. Chart with ID \'' + existingChart.id + '\'' +
+ ' must be destroyed before the canvas can be reused.'
+ );
+ }
+ const options = config.createResolver(config.chartOptionScopes(), this.getContext());
+ this.platform = new (config.platform || _detectPlatform(initialCanvas))();
+ this.platform.updateConfig(config);
+ const context = this.platform.acquireContext(initialCanvas, options.aspectRatio);
+ const canvas = context && context.canvas;
+ const height = canvas && canvas.height;
+ const width = canvas && canvas.width;
+ this.id = uid();
+ this.ctx = context;
+ this.canvas = canvas;
+ this.width = width;
+ this.height = height;
+ this._options = options;
+ this._aspectRatio = this.aspectRatio;
+ this._layers = [];
+ this._metasets = [];
+ this._stacks = undefined;
+ this.boxes = [];
+ this.currentDevicePixelRatio = undefined;
+ this.chartArea = undefined;
+ this._active = [];
+ this._lastEvent = undefined;
+ this._listeners = {};
+ this._responsiveListeners = undefined;
+ this._sortedMetasets = [];
+ this.scales = {};
+ this._plugins = new PluginService();
+ this.$proxies = {};
+ this._hiddenIndices = {};
+ this.attached = false;
+ this._animationsDisabled = undefined;
+ this.$context = undefined;
+ this._doResize = debounce(mode => this.update(mode), options.resizeDelay || 0);
+ instances[this.id] = this;
+ if (!context || !canvas) {
+ console.error("Failed to create chart: can't acquire context from the given item");
+ return;
+ }
+ animator.listen(this, 'complete', onAnimationsComplete);
+ animator.listen(this, 'progress', onAnimationProgress);
+ this._initialize();
+ if (this.attached) {
+ this.update();
+ }
+ }
+ get aspectRatio() {
+ const {options: {aspectRatio, maintainAspectRatio}, width, height, _aspectRatio} = this;
+ if (!isNullOrUndef(aspectRatio)) {
+ return aspectRatio;
+ }
+ if (maintainAspectRatio && _aspectRatio) {
+ return _aspectRatio;
+ }
+ return height ? width / height : null;
+ }
+ get data() {
+ return this.config.data;
+ }
+ set data(data) {
+ this.config.data = data;
+ }
+ get options() {
+ return this._options;
+ }
+ set options(options) {
+ this.config.options = options;
+ }
+ _initialize() {
+ this.notifyPlugins('beforeInit');
+ if (this.options.responsive) {
+ this.resize();
+ } else {
+ retinaScale(this, this.options.devicePixelRatio);
+ }
+ this.bindEvents();
+ this.notifyPlugins('afterInit');
+ return this;
+ }
+ clear() {
+ clearCanvas(this.canvas, this.ctx);
+ return this;
+ }
+ stop() {
+ animator.stop(this);
+ return this;
+ }
+ resize(width, height) {
+ if (!animator.running(this)) {
+ this._resize(width, height);
+ } else {
+ this._resizeBeforeDraw = {width, height};
+ }
+ }
+ _resize(width, height) {
+ const options = this.options;
+ const canvas = this.canvas;
+ const aspectRatio = options.maintainAspectRatio && this.aspectRatio;
+ const newSize = this.platform.getMaximumSize(canvas, width, height, aspectRatio);
+ const newRatio = options.devicePixelRatio || this.platform.getDevicePixelRatio();
+ const mode = this.width ? 'resize' : 'attach';
+ this.width = newSize.width;
+ this.height = newSize.height;
+ this._aspectRatio = this.aspectRatio;
+ if (!retinaScale(this, newRatio, true)) {
+ return;
+ }
+ this.notifyPlugins('resize', {size: newSize});
+ callback(options.onResize, [this, newSize], this);
+ if (this.attached) {
+ if (this._doResize(mode)) {
+ this.render();
+ }
+ }
+ }
+ ensureScalesHaveIDs() {
+ const options = this.options;
+ const scalesOptions = options.scales || {};
+ each(scalesOptions, (axisOptions, axisID) => {
+ axisOptions.id = axisID;
+ });
+ }
+ buildOrUpdateScales() {
+ const options = this.options;
+ const scaleOpts = options.scales;
+ const scales = this.scales;
+ const updated = Object.keys(scales).reduce((obj, id) => {
+ obj[id] = false;
+ return obj;
+ }, {});
+ let items = [];
+ if (scaleOpts) {
+ items = items.concat(
+ Object.keys(scaleOpts).map((id) => {
+ const scaleOptions = scaleOpts[id];
+ const axis = determineAxis(id, scaleOptions);
+ const isRadial = axis === 'r';
+ const isHorizontal = axis === 'x';
+ return {
+ options: scaleOptions,
+ dposition: isRadial ? 'chartArea' : isHorizontal ? 'bottom' : 'left',
+ dtype: isRadial ? 'radialLinear' : isHorizontal ? 'category' : 'linear'
+ };
+ })
+ );
+ }
+ each(items, (item) => {
+ const scaleOptions = item.options;
+ const id = scaleOptions.id;
+ const axis = determineAxis(id, scaleOptions);
+ const scaleType = valueOrDefault(scaleOptions.type, item.dtype);
+ if (scaleOptions.position === undefined || positionIsHorizontal(scaleOptions.position, axis) !== positionIsHorizontal(item.dposition)) {
+ scaleOptions.position = item.dposition;
+ }
+ updated[id] = true;
+ let scale = null;
+ if (id in scales && scales[id].type === scaleType) {
+ scale = scales[id];
+ } else {
+ const scaleClass = registry.getScale(scaleType);
+ scale = new scaleClass({
+ id,
+ type: scaleType,
+ ctx: this.ctx,
+ chart: this
+ });
+ scales[scale.id] = scale;
+ }
+ scale.init(scaleOptions, options);
+ });
+ each(updated, (hasUpdated, id) => {
+ if (!hasUpdated) {
+ delete scales[id];
+ }
+ });
+ each(scales, (scale) => {
+ layouts.configure(this, scale, scale.options);
+ layouts.addBox(this, scale);
+ });
+ }
+ _updateMetasets() {
+ const metasets = this._metasets;
+ const numData = this.data.datasets.length;
+ const numMeta = metasets.length;
+ metasets.sort((a, b) => a.index - b.index);
+ if (numMeta > numData) {
+ for (let i = numData; i < numMeta; ++i) {
+ this._destroyDatasetMeta(i);
+ }
+ metasets.splice(numData, numMeta - numData);
+ }
+ this._sortedMetasets = metasets.slice(0).sort(compare2Level('order', 'index'));
+ }
+ _removeUnreferencedMetasets() {
+ const {_metasets: metasets, data: {datasets}} = this;
+ if (metasets.length > datasets.length) {
+ delete this._stacks;
+ }
+ metasets.forEach((meta, index) => {
+ if (datasets.filter(x => x === meta._dataset).length === 0) {
+ this._destroyDatasetMeta(index);
+ }
+ });
+ }
+ buildOrUpdateControllers() {
+ const newControllers = [];
+ const datasets = this.data.datasets;
+ let i, ilen;
+ this._removeUnreferencedMetasets();
+ for (i = 0, ilen = datasets.length; i < ilen; i++) {
+ const dataset = datasets[i];
+ let meta = this.getDatasetMeta(i);
+ const type = dataset.type || this.config.type;
+ if (meta.type && meta.type !== type) {
+ this._destroyDatasetMeta(i);
+ meta = this.getDatasetMeta(i);
+ }
+ meta.type = type;
+ meta.indexAxis = dataset.indexAxis || getIndexAxis(type, this.options);
+ meta.order = dataset.order || 0;
+ meta.index = i;
+ meta.label = '' + dataset.label;
+ meta.visible = this.isDatasetVisible(i);
+ if (meta.controller) {
+ meta.controller.updateIndex(i);
+ meta.controller.linkScales();
+ } else {
+ const ControllerClass = registry.getController(type);
+ const {datasetElementType, dataElementType} = defaults.datasets[type];
+ Object.assign(ControllerClass.prototype, {
+ dataElementType: registry.getElement(dataElementType),
+ datasetElementType: datasetElementType && registry.getElement(datasetElementType)
+ });
+ meta.controller = new ControllerClass(this, i);
+ newControllers.push(meta.controller);
+ }
+ }
+ this._updateMetasets();
+ return newControllers;
+ }
+ _resetElements() {
+ each(this.data.datasets, (dataset, datasetIndex) => {
+ this.getDatasetMeta(datasetIndex).controller.reset();
+ }, this);
+ }
+ reset() {
+ this._resetElements();
+ this.notifyPlugins('reset');
+ }
+ update(mode) {
+ const config = this.config;
+ config.update();
+ const options = this._options = config.createResolver(config.chartOptionScopes(), this.getContext());
+ each(this.scales, (scale) => {
+ layouts.removeBox(this, scale);
+ });
+ const animsDisabled = this._animationsDisabled = !options.animation;
+ this.ensureScalesHaveIDs();
+ this.buildOrUpdateScales();
+ const existingEvents = new Set(Object.keys(this._listeners));
+ const newEvents = new Set(options.events);
+ if (!setsEqual(existingEvents, newEvents) || !!this._responsiveListeners !== options.responsive) {
+ this.unbindEvents();
+ this.bindEvents();
+ }
+ this._plugins.invalidate();
+ if (this.notifyPlugins('beforeUpdate', {mode, cancelable: true}) === false) {
+ return;
+ }
+ const newControllers = this.buildOrUpdateControllers();
+ this.notifyPlugins('beforeElementsUpdate');
+ let minPadding = 0;
+ for (let i = 0, ilen = this.data.datasets.length; i < ilen; i++) {
+ const {controller} = this.getDatasetMeta(i);
+ const reset = !animsDisabled && newControllers.indexOf(controller) === -1;
+ controller.buildOrUpdateElements(reset);
+ minPadding = Math.max(+controller.getMaxOverflow(), minPadding);
+ }
+ minPadding = this._minPadding = options.layout.autoPadding ? minPadding : 0;
+ this._updateLayout(minPadding);
+ if (!animsDisabled) {
+ each(newControllers, (controller) => {
+ controller.reset();
+ });
+ }
+ this._updateDatasets(mode);
+ this.notifyPlugins('afterUpdate', {mode});
+ this._layers.sort(compare2Level('z', '_idx'));
+ if (this._lastEvent) {
+ this._eventHandler(this._lastEvent, true);
+ }
+ this.render();
+ }
+ _updateLayout(minPadding) {
+ if (this.notifyPlugins('beforeLayout', {cancelable: true}) === false) {
+ return;
+ }
+ layouts.update(this, this.width, this.height, minPadding);
+ const area = this.chartArea;
+ const noArea = area.width <= 0 || area.height <= 0;
+ this._layers = [];
+ each(this.boxes, (box) => {
+ if (noArea && box.position === 'chartArea') {
+ return;
+ }
+ if (box.configure) {
+ box.configure();
+ }
+ this._layers.push(...box._layers());
+ }, this);
+ this._layers.forEach((item, index) => {
+ item._idx = index;
+ });
+ this.notifyPlugins('afterLayout');
+ }
+ _updateDatasets(mode) {
+ if (this.notifyPlugins('beforeDatasetsUpdate', {mode, cancelable: true}) === false) {
+ return;
+ }
+ for (let i = 0, ilen = this.data.datasets.length; i < ilen; ++i) {
+ this._updateDataset(i, isFunction(mode) ? mode({datasetIndex: i}) : mode);
+ }
+ this.notifyPlugins('afterDatasetsUpdate', {mode});
+ }
+ _updateDataset(index, mode) {
+ const meta = this.getDatasetMeta(index);
+ const args = {meta, index, mode, cancelable: true};
+ if (this.notifyPlugins('beforeDatasetUpdate', args) === false) {
+ return;
+ }
+ meta.controller._update(mode);
+ args.cancelable = false;
+ this.notifyPlugins('afterDatasetUpdate', args);
+ }
+ render() {
+ if (this.notifyPlugins('beforeRender', {cancelable: true}) === false) {
+ return;
+ }
+ if (animator.has(this)) {
+ if (this.attached && !animator.running(this)) {
+ animator.start(this);
+ }
+ } else {
+ this.draw();
+ onAnimationsComplete({chart: this});
+ }
+ }
+ draw() {
+ let i;
+ if (this._resizeBeforeDraw) {
+ const {width, height} = this._resizeBeforeDraw;
+ this._resize(width, height);
+ this._resizeBeforeDraw = null;
+ }
+ this.clear();
+ if (this.width <= 0 || this.height <= 0) {
+ return;
+ }
+ if (this.notifyPlugins('beforeDraw', {cancelable: true}) === false) {
+ return;
+ }
+ const layers = this._layers;
+ for (i = 0; i < layers.length && layers[i].z <= 0; ++i) {
+ layers[i].draw(this.chartArea);
+ }
+ this._drawDatasets();
+ for (; i < layers.length; ++i) {
+ layers[i].draw(this.chartArea);
+ }
+ this.notifyPlugins('afterDraw');
+ }
+ _getSortedDatasetMetas(filterVisible) {
+ const metasets = this._sortedMetasets;
+ const result = [];
+ let i, ilen;
+ for (i = 0, ilen = metasets.length; i < ilen; ++i) {
+ const meta = metasets[i];
+ if (!filterVisible || meta.visible) {
+ result.push(meta);
+ }
+ }
+ return result;
+ }
+ getSortedVisibleDatasetMetas() {
+ return this._getSortedDatasetMetas(true);
+ }
+ _drawDatasets() {
+ if (this.notifyPlugins('beforeDatasetsDraw', {cancelable: true}) === false) {
+ return;
+ }
+ const metasets = this.getSortedVisibleDatasetMetas();
+ for (let i = metasets.length - 1; i >= 0; --i) {
+ this._drawDataset(metasets[i]);
+ }
+ this.notifyPlugins('afterDatasetsDraw');
+ }
+ _drawDataset(meta) {
+ const ctx = this.ctx;
+ const clip = meta._clip;
+ const useClip = !clip.disabled;
+ const area = this.chartArea;
+ const args = {
+ meta,
+ index: meta.index,
+ cancelable: true
+ };
+ if (this.notifyPlugins('beforeDatasetDraw', args) === false) {
+ return;
+ }
+ if (useClip) {
+ clipArea(ctx, {
+ left: clip.left === false ? 0 : area.left - clip.left,
+ right: clip.right === false ? this.width : area.right + clip.right,
+ top: clip.top === false ? 0 : area.top - clip.top,
+ bottom: clip.bottom === false ? this.height : area.bottom + clip.bottom
+ });
+ }
+ meta.controller.draw();
+ if (useClip) {
+ unclipArea(ctx);
+ }
+ args.cancelable = false;
+ this.notifyPlugins('afterDatasetDraw', args);
+ }
+ getElementsAtEventForMode(e, mode, options, useFinalPosition) {
+ const method = Interaction.modes[mode];
+ if (typeof method === 'function') {
+ return method(this, e, options, useFinalPosition);
+ }
+ return [];
+ }
+ getDatasetMeta(datasetIndex) {
+ const dataset = this.data.datasets[datasetIndex];
+ const metasets = this._metasets;
+ let meta = metasets.filter(x => x && x._dataset === dataset).pop();
+ if (!meta) {
+ meta = {
+ type: null,
+ data: [],
+ dataset: null,
+ controller: null,
+ hidden: null,
+ xAxisID: null,
+ yAxisID: null,
+ order: dataset && dataset.order || 0,
+ index: datasetIndex,
+ _dataset: dataset,
+ _parsed: [],
+ _sorted: false
+ };
+ metasets.push(meta);
+ }
+ return meta;
+ }
+ getContext() {
+ return this.$context || (this.$context = createContext(null, {chart: this, type: 'chart'}));
+ }
+ getVisibleDatasetCount() {
+ return this.getSortedVisibleDatasetMetas().length;
+ }
+ isDatasetVisible(datasetIndex) {
+ const dataset = this.data.datasets[datasetIndex];
+ if (!dataset) {
+ return false;
+ }
+ const meta = this.getDatasetMeta(datasetIndex);
+ return typeof meta.hidden === 'boolean' ? !meta.hidden : !dataset.hidden;
+ }
+ setDatasetVisibility(datasetIndex, visible) {
+ const meta = this.getDatasetMeta(datasetIndex);
+ meta.hidden = !visible;
+ }
+ toggleDataVisibility(index) {
+ this._hiddenIndices[index] = !this._hiddenIndices[index];
+ }
+ getDataVisibility(index) {
+ return !this._hiddenIndices[index];
+ }
+ _updateVisibility(datasetIndex, dataIndex, visible) {
+ const mode = visible ? 'show' : 'hide';
+ const meta = this.getDatasetMeta(datasetIndex);
+ const anims = meta.controller._resolveAnimations(undefined, mode);
+ if (defined(dataIndex)) {
+ meta.data[dataIndex].hidden = !visible;
+ this.update();
+ } else {
+ this.setDatasetVisibility(datasetIndex, visible);
+ anims.update(meta, {visible});
+ this.update((ctx) => ctx.datasetIndex === datasetIndex ? mode : undefined);
+ }
+ }
+ hide(datasetIndex, dataIndex) {
+ this._updateVisibility(datasetIndex, dataIndex, false);
+ }
+ show(datasetIndex, dataIndex) {
+ this._updateVisibility(datasetIndex, dataIndex, true);
+ }
+ _destroyDatasetMeta(datasetIndex) {
+ const meta = this._metasets[datasetIndex];
+ if (meta && meta.controller) {
+ meta.controller._destroy();
+ }
+ delete this._metasets[datasetIndex];
+ }
+ _stop() {
+ let i, ilen;
+ this.stop();
+ animator.remove(this);
+ for (i = 0, ilen = this.data.datasets.length; i < ilen; ++i) {
+ this._destroyDatasetMeta(i);
+ }
+ }
+ destroy() {
+ const {canvas, ctx} = this;
+ this._stop();
+ this.config.clearCache();
+ if (canvas) {
+ this.unbindEvents();
+ clearCanvas(canvas, ctx);
+ this.platform.releaseContext(ctx);
+ this.canvas = null;
+ this.ctx = null;
+ }
+ this.notifyPlugins('destroy');
+ delete instances[this.id];
+ }
+ toBase64Image(...args) {
+ return this.canvas.toDataURL(...args);
+ }
+ bindEvents() {
+ this.bindUserEvents();
+ if (this.options.responsive) {
+ this.bindResponsiveEvents();
+ } else {
+ this.attached = true;
+ }
+ }
+ bindUserEvents() {
+ const listeners = this._listeners;
+ const platform = this.platform;
+ const _add = (type, listener) => {
+ platform.addEventListener(this, type, listener);
+ listeners[type] = listener;
+ };
+ const listener = (e, x, y) => {
+ e.offsetX = x;
+ e.offsetY = y;
+ this._eventHandler(e);
+ };
+ each(this.options.events, (type) => _add(type, listener));
+ }
+ bindResponsiveEvents() {
+ if (!this._responsiveListeners) {
+ this._responsiveListeners = {};
+ }
+ const listeners = this._responsiveListeners;
+ const platform = this.platform;
+ const _add = (type, listener) => {
+ platform.addEventListener(this, type, listener);
+ listeners[type] = listener;
+ };
+ const _remove = (type, listener) => {
+ if (listeners[type]) {
+ platform.removeEventListener(this, type, listener);
+ delete listeners[type];
+ }
+ };
+ const listener = (width, height) => {
+ if (this.canvas) {
+ this.resize(width, height);
+ }
+ };
+ let detached;
+ const attached = () => {
+ _remove('attach', attached);
+ this.attached = true;
+ this.resize();
+ _add('resize', listener);
+ _add('detach', detached);
+ };
+ detached = () => {
+ this.attached = false;
+ _remove('resize', listener);
+ this._stop();
+ this._resize(0, 0);
+ _add('attach', attached);
+ };
+ if (platform.isAttached(this.canvas)) {
+ attached();
+ } else {
+ detached();
+ }
+ }
+ unbindEvents() {
+ each(this._listeners, (listener, type) => {
+ this.platform.removeEventListener(this, type, listener);
+ });
+ this._listeners = {};
+ each(this._responsiveListeners, (listener, type) => {
+ this.platform.removeEventListener(this, type, listener);
+ });
+ this._responsiveListeners = undefined;
+ }
+ updateHoverStyle(items, mode, enabled) {
+ const prefix = enabled ? 'set' : 'remove';
+ let meta, item, i, ilen;
+ if (mode === 'dataset') {
+ meta = this.getDatasetMeta(items[0].datasetIndex);
+ meta.controller['_' + prefix + 'DatasetHoverStyle']();
+ }
+ for (i = 0, ilen = items.length; i < ilen; ++i) {
+ item = items[i];
+ const controller = item && this.getDatasetMeta(item.datasetIndex).controller;
+ if (controller) {
+ controller[prefix + 'HoverStyle'](item.element, item.datasetIndex, item.index);
+ }
+ }
+ }
+ getActiveElements() {
+ return this._active || [];
+ }
+ setActiveElements(activeElements) {
+ const lastActive = this._active || [];
+ const active = activeElements.map(({datasetIndex, index}) => {
+ const meta = this.getDatasetMeta(datasetIndex);
+ if (!meta) {
+ throw new Error('No dataset found at index ' + datasetIndex);
+ }
+ return {
+ datasetIndex,
+ element: meta.data[index],
+ index,
+ };
+ });
+ const changed = !_elementsEqual(active, lastActive);
+ if (changed) {
+ this._active = active;
+ this._updateHoverStyles(active, lastActive);
+ }
+ }
+ notifyPlugins(hook, args, filter) {
+ return this._plugins.notify(this, hook, args, filter);
+ }
+ _updateHoverStyles(active, lastActive, replay) {
+ const hoverOptions = this.options.hover;
+ const diff = (a, b) => a.filter(x => !b.some(y => x.datasetIndex === y.datasetIndex && x.index === y.index));
+ const deactivated = diff(lastActive, active);
+ const activated = replay ? active : diff(active, lastActive);
+ if (deactivated.length) {
+ this.updateHoverStyle(deactivated, hoverOptions.mode, false);
+ }
+ if (activated.length && hoverOptions.mode) {
+ this.updateHoverStyle(activated, hoverOptions.mode, true);
+ }
+ }
+ _eventHandler(e, replay) {
+ const args = {event: e, replay, cancelable: true};
+ const eventFilter = (plugin) => (plugin.options.events || this.options.events).includes(e.native.type);
+ if (this.notifyPlugins('beforeEvent', args, eventFilter) === false) {
+ return;
+ }
+ const changed = this._handleEvent(e, replay);
+ args.cancelable = false;
+ this.notifyPlugins('afterEvent', args, eventFilter);
+ if (changed || args.changed) {
+ this.render();
+ }
+ return this;
+ }
+ _handleEvent(e, replay) {
+ const {_active: lastActive = [], options} = this;
+ const hoverOptions = options.hover;
+ const useFinalPosition = replay;
+ let active = [];
+ let changed = false;
+ let lastEvent = null;
+ if (e.type !== 'mouseout') {
+ active = this.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions, useFinalPosition);
+ lastEvent = e.type === 'click' ? this._lastEvent : e;
+ }
+ this._lastEvent = null;
+ if (_isPointInArea(e, this.chartArea, this._minPadding)) {
+ callback(options.onHover, [e, active, this], this);
+ if (e.type === 'mouseup' || e.type === 'click' || e.type === 'contextmenu') {
+ callback(options.onClick, [e, active, this], this);
+ }
+ }
+ changed = !_elementsEqual(active, lastActive);
+ if (changed || replay) {
+ this._active = active;
+ this._updateHoverStyles(active, lastActive, replay);
+ }
+ this._lastEvent = lastEvent;
+ return changed;
+ }
+}
+const invalidatePlugins = () => each(Chart.instances, (chart) => chart._plugins.invalidate());
+const enumerable = true;
+Object.defineProperties(Chart, {
+ defaults: {
+ enumerable,
+ value: defaults
+ },
+ instances: {
+ enumerable,
+ value: instances
+ },
+ overrides: {
+ enumerable,
+ value: overrides
+ },
+ registry: {
+ enumerable,
+ value: registry
+ },
+ version: {
+ enumerable,
+ value: version
+ },
+ getChart: {
+ enumerable,
+ value: getChart
+ },
+ register: {
+ enumerable,
+ value: (...items) => {
+ registry.add(...items);
+ invalidatePlugins();
+ }
+ },
+ unregister: {
+ enumerable,
+ value: (...items) => {
+ registry.remove(...items);
+ invalidatePlugins();
+ }
+ }
+});
+
+function abstract() {
+ throw new Error('This method is not implemented: Check that a complete date adapter is provided.');
+}
+class DateAdapter {
+ constructor(options) {
+ this.options = options || {};
+ }
+ formats() {
+ return abstract();
+ }
+ parse(value, format) {
+ return abstract();
+ }
+ format(timestamp, format) {
+ return abstract();
+ }
+ add(timestamp, amount, unit) {
+ return abstract();
+ }
+ diff(a, b, unit) {
+ return abstract();
+ }
+ startOf(timestamp, unit, weekday) {
+ return abstract();
+ }
+ endOf(timestamp, unit) {
+ return abstract();
+ }
+}
+DateAdapter.override = function(members) {
+ Object.assign(DateAdapter.prototype, members);
+};
+var _adapters = {
+ _date: DateAdapter
+};
+
+function getAllScaleValues(scale, type) {
+ if (!scale._cache.$bar) {
+ const visibleMetas = scale.getMatchingVisibleMetas(type);
+ let values = [];
+ for (let i = 0, ilen = visibleMetas.length; i < ilen; i++) {
+ values = values.concat(visibleMetas[i].controller.getAllParsedValues(scale));
+ }
+ scale._cache.$bar = _arrayUnique(values.sort((a, b) => a - b));
+ }
+ return scale._cache.$bar;
+}
+function computeMinSampleSize(meta) {
+ const scale = meta.iScale;
+ const values = getAllScaleValues(scale, meta.type);
+ let min = scale._length;
+ let i, ilen, curr, prev;
+ const updateMinAndPrev = () => {
+ if (curr === 32767 || curr === -32768) {
+ return;
+ }
+ if (defined(prev)) {
+ min = Math.min(min, Math.abs(curr - prev) || min);
+ }
+ prev = curr;
+ };
+ for (i = 0, ilen = values.length; i < ilen; ++i) {
+ curr = scale.getPixelForValue(values[i]);
+ updateMinAndPrev();
+ }
+ prev = undefined;
+ for (i = 0, ilen = scale.ticks.length; i < ilen; ++i) {
+ curr = scale.getPixelForTick(i);
+ updateMinAndPrev();
+ }
+ return min;
+}
+function computeFitCategoryTraits(index, ruler, options, stackCount) {
+ const thickness = options.barThickness;
+ let size, ratio;
+ if (isNullOrUndef(thickness)) {
+ size = ruler.min * options.categoryPercentage;
+ ratio = options.barPercentage;
+ } else {
+ size = thickness * stackCount;
+ ratio = 1;
+ }
+ return {
+ chunk: size / stackCount,
+ ratio,
+ start: ruler.pixels[index] - (size / 2)
+ };
+}
+function computeFlexCategoryTraits(index, ruler, options, stackCount) {
+ const pixels = ruler.pixels;
+ const curr = pixels[index];
+ let prev = index > 0 ? pixels[index - 1] : null;
+ let next = index < pixels.length - 1 ? pixels[index + 1] : null;
+ const percent = options.categoryPercentage;
+ if (prev === null) {
+ prev = curr - (next === null ? ruler.end - ruler.start : next - curr);
+ }
+ if (next === null) {
+ next = curr + curr - prev;
+ }
+ const start = curr - (curr - Math.min(prev, next)) / 2 * percent;
+ const size = Math.abs(next - prev) / 2 * percent;
+ return {
+ chunk: size / stackCount,
+ ratio: options.barPercentage,
+ start
+ };
+}
+function parseFloatBar(entry, item, vScale, i) {
+ const startValue = vScale.parse(entry[0], i);
+ const endValue = vScale.parse(entry[1], i);
+ const min = Math.min(startValue, endValue);
+ const max = Math.max(startValue, endValue);
+ let barStart = min;
+ let barEnd = max;
+ if (Math.abs(min) > Math.abs(max)) {
+ barStart = max;
+ barEnd = min;
+ }
+ item[vScale.axis] = barEnd;
+ item._custom = {
+ barStart,
+ barEnd,
+ start: startValue,
+ end: endValue,
+ min,
+ max
+ };
+}
+function parseValue(entry, item, vScale, i) {
+ if (isArray(entry)) {
+ parseFloatBar(entry, item, vScale, i);
+ } else {
+ item[vScale.axis] = vScale.parse(entry, i);
+ }
+ return item;
+}
+function parseArrayOrPrimitive(meta, data, start, count) {
+ const iScale = meta.iScale;
+ const vScale = meta.vScale;
+ const labels = iScale.getLabels();
+ const singleScale = iScale === vScale;
+ const parsed = [];
+ let i, ilen, item, entry;
+ for (i = start, ilen = start + count; i < ilen; ++i) {
+ entry = data[i];
+ item = {};
+ item[iScale.axis] = singleScale || iScale.parse(labels[i], i);
+ parsed.push(parseValue(entry, item, vScale, i));
+ }
+ return parsed;
+}
+function isFloatBar(custom) {
+ return custom && custom.barStart !== undefined && custom.barEnd !== undefined;
+}
+function barSign(size, vScale, actualBase) {
+ if (size !== 0) {
+ return sign(size);
+ }
+ return (vScale.isHorizontal() ? 1 : -1) * (vScale.min >= actualBase ? 1 : -1);
+}
+function borderProps(properties) {
+ let reverse, start, end, top, bottom;
+ if (properties.horizontal) {
+ reverse = properties.base > properties.x;
+ start = 'left';
+ end = 'right';
+ } else {
+ reverse = properties.base < properties.y;
+ start = 'bottom';
+ end = 'top';
+ }
+ if (reverse) {
+ top = 'end';
+ bottom = 'start';
+ } else {
+ top = 'start';
+ bottom = 'end';
+ }
+ return {start, end, reverse, top, bottom};
+}
+function setBorderSkipped(properties, options, stack, index) {
+ let edge = options.borderSkipped;
+ const res = {};
+ if (!edge) {
+ properties.borderSkipped = res;
+ return;
+ }
+ const {start, end, reverse, top, bottom} = borderProps(properties);
+ if (edge === 'middle' && stack) {
+ properties.enableBorderRadius = true;
+ if ((stack._top || 0) === index) {
+ edge = top;
+ } else if ((stack._bottom || 0) === index) {
+ edge = bottom;
+ } else {
+ res[parseEdge(bottom, start, end, reverse)] = true;
+ edge = top;
+ }
+ }
+ res[parseEdge(edge, start, end, reverse)] = true;
+ properties.borderSkipped = res;
+}
+function parseEdge(edge, a, b, reverse) {
+ if (reverse) {
+ edge = swap(edge, a, b);
+ edge = startEnd(edge, b, a);
+ } else {
+ edge = startEnd(edge, a, b);
+ }
+ return edge;
+}
+function swap(orig, v1, v2) {
+ return orig === v1 ? v2 : orig === v2 ? v1 : orig;
+}
+function startEnd(v, start, end) {
+ return v === 'start' ? start : v === 'end' ? end : v;
+}
+function setInflateAmount(properties, {inflateAmount}, ratio) {
+ properties.inflateAmount = inflateAmount === 'auto'
+ ? ratio === 1 ? 0.33 : 0
+ : inflateAmount;
+}
+class BarController extends DatasetController {
+ parsePrimitiveData(meta, data, start, count) {
+ return parseArrayOrPrimitive(meta, data, start, count);
+ }
+ parseArrayData(meta, data, start, count) {
+ return parseArrayOrPrimitive(meta, data, start, count);
+ }
+ parseObjectData(meta, data, start, count) {
+ const {iScale, vScale} = meta;
+ const {xAxisKey = 'x', yAxisKey = 'y'} = this._parsing;
+ const iAxisKey = iScale.axis === 'x' ? xAxisKey : yAxisKey;
+ const vAxisKey = vScale.axis === 'x' ? xAxisKey : yAxisKey;
+ const parsed = [];
+ let i, ilen, item, obj;
+ for (i = start, ilen = start + count; i < ilen; ++i) {
+ obj = data[i];
+ item = {};
+ item[iScale.axis] = iScale.parse(resolveObjectKey(obj, iAxisKey), i);
+ parsed.push(parseValue(resolveObjectKey(obj, vAxisKey), item, vScale, i));
+ }
+ return parsed;
+ }
+ updateRangeFromParsed(range, scale, parsed, stack) {
+ super.updateRangeFromParsed(range, scale, parsed, stack);
+ const custom = parsed._custom;
+ if (custom && scale === this._cachedMeta.vScale) {
+ range.min = Math.min(range.min, custom.min);
+ range.max = Math.max(range.max, custom.max);
+ }
+ }
+ getMaxOverflow() {
+ return 0;
+ }
+ getLabelAndValue(index) {
+ const meta = this._cachedMeta;
+ const {iScale, vScale} = meta;
+ const parsed = this.getParsed(index);
+ const custom = parsed._custom;
+ const value = isFloatBar(custom)
+ ? '[' + custom.start + ', ' + custom.end + ']'
+ : '' + vScale.getLabelForValue(parsed[vScale.axis]);
+ return {
+ label: '' + iScale.getLabelForValue(parsed[iScale.axis]),
+ value
+ };
+ }
+ initialize() {
+ this.enableOptionSharing = true;
+ super.initialize();
+ const meta = this._cachedMeta;
+ meta.stack = this.getDataset().stack;
+ }
+ update(mode) {
+ const meta = this._cachedMeta;
+ this.updateElements(meta.data, 0, meta.data.length, mode);
+ }
+ updateElements(bars, start, count, mode) {
+ const reset = mode === 'reset';
+ const {index, _cachedMeta: {vScale}} = this;
+ const base = vScale.getBasePixel();
+ const horizontal = vScale.isHorizontal();
+ const ruler = this._getRuler();
+ const firstOpts = this.resolveDataElementOptions(start, mode);
+ const sharedOptions = this.getSharedOptions(firstOpts);
+ const includeOptions = this.includeOptions(mode, sharedOptions);
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
+ for (let i = start; i < start + count; i++) {
+ const parsed = this.getParsed(i);
+ const vpixels = reset || isNullOrUndef(parsed[vScale.axis]) ? {base, head: base} : this._calculateBarValuePixels(i);
+ const ipixels = this._calculateBarIndexPixels(i, ruler);
+ const stack = (parsed._stacks || {})[vScale.axis];
+ const properties = {
+ horizontal,
+ base: vpixels.base,
+ enableBorderRadius: !stack || isFloatBar(parsed._custom) || (index === stack._top || index === stack._bottom),
+ x: horizontal ? vpixels.head : ipixels.center,
+ y: horizontal ? ipixels.center : vpixels.head,
+ height: horizontal ? ipixels.size : Math.abs(vpixels.size),
+ width: horizontal ? Math.abs(vpixels.size) : ipixels.size
+ };
+ if (includeOptions) {
+ properties.options = sharedOptions || this.resolveDataElementOptions(i, bars[i].active ? 'active' : mode);
+ }
+ const options = properties.options || bars[i].options;
+ setBorderSkipped(properties, options, stack, index);
+ setInflateAmount(properties, options, ruler.ratio);
+ this.updateElement(bars[i], i, properties, mode);
+ }
+ }
+ _getStacks(last, dataIndex) {
+ const meta = this._cachedMeta;
+ const iScale = meta.iScale;
+ const metasets = iScale.getMatchingVisibleMetas(this._type);
+ const stacked = iScale.options.stacked;
+ const ilen = metasets.length;
+ const stacks = [];
+ let i, item;
+ for (i = 0; i < ilen; ++i) {
+ item = metasets[i];
+ if (!item.controller.options.grouped) {
+ continue;
+ }
+ if (typeof dataIndex !== 'undefined') {
+ const val = item.controller.getParsed(dataIndex)[
+ item.controller._cachedMeta.vScale.axis
+ ];
+ if (isNullOrUndef(val) || isNaN(val)) {
+ continue;
+ }
+ }
+ if (stacked === false || stacks.indexOf(item.stack) === -1 ||
+ (stacked === undefined && item.stack === undefined)) {
+ stacks.push(item.stack);
+ }
+ if (item.index === last) {
+ break;
+ }
+ }
+ if (!stacks.length) {
+ stacks.push(undefined);
+ }
+ return stacks;
+ }
+ _getStackCount(index) {
+ return this._getStacks(undefined, index).length;
+ }
+ _getStackIndex(datasetIndex, name, dataIndex) {
+ const stacks = this._getStacks(datasetIndex, dataIndex);
+ const index = (name !== undefined)
+ ? stacks.indexOf(name)
+ : -1;
+ return (index === -1)
+ ? stacks.length - 1
+ : index;
+ }
+ _getRuler() {
+ const opts = this.options;
+ const meta = this._cachedMeta;
+ const iScale = meta.iScale;
+ const pixels = [];
+ let i, ilen;
+ for (i = 0, ilen = meta.data.length; i < ilen; ++i) {
+ pixels.push(iScale.getPixelForValue(this.getParsed(i)[iScale.axis], i));
+ }
+ const barThickness = opts.barThickness;
+ const min = barThickness || computeMinSampleSize(meta);
+ return {
+ min,
+ pixels,
+ start: iScale._startPixel,
+ end: iScale._endPixel,
+ stackCount: this._getStackCount(),
+ scale: iScale,
+ grouped: opts.grouped,
+ ratio: barThickness ? 1 : opts.categoryPercentage * opts.barPercentage
+ };
+ }
+ _calculateBarValuePixels(index) {
+ const {_cachedMeta: {vScale, _stacked}, options: {base: baseValue, minBarLength}} = this;
+ const actualBase = baseValue || 0;
+ const parsed = this.getParsed(index);
+ const custom = parsed._custom;
+ const floating = isFloatBar(custom);
+ let value = parsed[vScale.axis];
+ let start = 0;
+ let length = _stacked ? this.applyStack(vScale, parsed, _stacked) : value;
+ let head, size;
+ if (length !== value) {
+ start = length - value;
+ length = value;
+ }
+ if (floating) {
+ value = custom.barStart;
+ length = custom.barEnd - custom.barStart;
+ if (value !== 0 && sign(value) !== sign(custom.barEnd)) {
+ start = 0;
+ }
+ start += value;
+ }
+ const startValue = !isNullOrUndef(baseValue) && !floating ? baseValue : start;
+ let base = vScale.getPixelForValue(startValue);
+ if (this.chart.getDataVisibility(index)) {
+ head = vScale.getPixelForValue(start + length);
+ } else {
+ head = base;
+ }
+ size = head - base;
+ if (Math.abs(size) < minBarLength) {
+ size = barSign(size, vScale, actualBase) * minBarLength;
+ if (value === actualBase) {
+ base -= size / 2;
+ }
+ head = base + size;
+ }
+ if (base === vScale.getPixelForValue(actualBase)) {
+ const halfGrid = sign(size) * vScale.getLineWidthForValue(actualBase) / 2;
+ base += halfGrid;
+ size -= halfGrid;
+ }
+ return {
+ size,
+ base,
+ head,
+ center: head + size / 2
+ };
+ }
+ _calculateBarIndexPixels(index, ruler) {
+ const scale = ruler.scale;
+ const options = this.options;
+ const skipNull = options.skipNull;
+ const maxBarThickness = valueOrDefault(options.maxBarThickness, Infinity);
+ let center, size;
+ if (ruler.grouped) {
+ const stackCount = skipNull ? this._getStackCount(index) : ruler.stackCount;
+ const range = options.barThickness === 'flex'
+ ? computeFlexCategoryTraits(index, ruler, options, stackCount)
+ : computeFitCategoryTraits(index, ruler, options, stackCount);
+ const stackIndex = this._getStackIndex(this.index, this._cachedMeta.stack, skipNull ? index : undefined);
+ center = range.start + (range.chunk * stackIndex) + (range.chunk / 2);
+ size = Math.min(maxBarThickness, range.chunk * range.ratio);
+ } else {
+ center = scale.getPixelForValue(this.getParsed(index)[scale.axis], index);
+ size = Math.min(maxBarThickness, ruler.min * ruler.ratio);
+ }
+ return {
+ base: center - size / 2,
+ head: center + size / 2,
+ center,
+ size
+ };
+ }
+ draw() {
+ const meta = this._cachedMeta;
+ const vScale = meta.vScale;
+ const rects = meta.data;
+ const ilen = rects.length;
+ let i = 0;
+ for (; i < ilen; ++i) {
+ if (this.getParsed(i)[vScale.axis] !== null) {
+ rects[i].draw(this._ctx);
+ }
+ }
+ }
+}
+BarController.id = 'bar';
+BarController.defaults = {
+ datasetElementType: false,
+ dataElementType: 'bar',
+ categoryPercentage: 0.8,
+ barPercentage: 0.9,
+ grouped: true,
+ animations: {
+ numbers: {
+ type: 'number',
+ properties: ['x', 'y', 'base', 'width', 'height']
+ }
+ }
+};
+BarController.overrides = {
+ scales: {
+ _index_: {
+ type: 'category',
+ offset: true,
+ grid: {
+ offset: true
+ }
+ },
+ _value_: {
+ type: 'linear',
+ beginAtZero: true,
+ }
+ }
+};
+
+class BubbleController extends DatasetController {
+ initialize() {
+ this.enableOptionSharing = true;
+ super.initialize();
+ }
+ parsePrimitiveData(meta, data, start, count) {
+ const parsed = super.parsePrimitiveData(meta, data, start, count);
+ for (let i = 0; i < parsed.length; i++) {
+ parsed[i]._custom = this.resolveDataElementOptions(i + start).radius;
+ }
+ return parsed;
+ }
+ parseArrayData(meta, data, start, count) {
+ const parsed = super.parseArrayData(meta, data, start, count);
+ for (let i = 0; i < parsed.length; i++) {
+ const item = data[start + i];
+ parsed[i]._custom = valueOrDefault(item[2], this.resolveDataElementOptions(i + start).radius);
+ }
+ return parsed;
+ }
+ parseObjectData(meta, data, start, count) {
+ const parsed = super.parseObjectData(meta, data, start, count);
+ for (let i = 0; i < parsed.length; i++) {
+ const item = data[start + i];
+ parsed[i]._custom = valueOrDefault(item && item.r && +item.r, this.resolveDataElementOptions(i + start).radius);
+ }
+ return parsed;
+ }
+ getMaxOverflow() {
+ const data = this._cachedMeta.data;
+ let max = 0;
+ for (let i = data.length - 1; i >= 0; --i) {
+ max = Math.max(max, data[i].size(this.resolveDataElementOptions(i)) / 2);
+ }
+ return max > 0 && max;
+ }
+ getLabelAndValue(index) {
+ const meta = this._cachedMeta;
+ const {xScale, yScale} = meta;
+ const parsed = this.getParsed(index);
+ const x = xScale.getLabelForValue(parsed.x);
+ const y = yScale.getLabelForValue(parsed.y);
+ const r = parsed._custom;
+ return {
+ label: meta.label,
+ value: '(' + x + ', ' + y + (r ? ', ' + r : '') + ')'
+ };
+ }
+ update(mode) {
+ const points = this._cachedMeta.data;
+ this.updateElements(points, 0, points.length, mode);
+ }
+ updateElements(points, start, count, mode) {
+ const reset = mode === 'reset';
+ const {iScale, vScale} = this._cachedMeta;
+ const firstOpts = this.resolveDataElementOptions(start, mode);
+ const sharedOptions = this.getSharedOptions(firstOpts);
+ const includeOptions = this.includeOptions(mode, sharedOptions);
+ const iAxis = iScale.axis;
+ const vAxis = vScale.axis;
+ for (let i = start; i < start + count; i++) {
+ const point = points[i];
+ const parsed = !reset && this.getParsed(i);
+ const properties = {};
+ const iPixel = properties[iAxis] = reset ? iScale.getPixelForDecimal(0.5) : iScale.getPixelForValue(parsed[iAxis]);
+ const vPixel = properties[vAxis] = reset ? vScale.getBasePixel() : vScale.getPixelForValue(parsed[vAxis]);
+ properties.skip = isNaN(iPixel) || isNaN(vPixel);
+ if (includeOptions) {
+ properties.options = this.resolveDataElementOptions(i, point.active ? 'active' : mode);
+ if (reset) {
+ properties.options.radius = 0;
+ }
+ }
+ this.updateElement(point, i, properties, mode);
+ }
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
+ }
+ resolveDataElementOptions(index, mode) {
+ const parsed = this.getParsed(index);
+ let values = super.resolveDataElementOptions(index, mode);
+ if (values.$shared) {
+ values = Object.assign({}, values, {$shared: false});
+ }
+ const radius = values.radius;
+ if (mode !== 'active') {
+ values.radius = 0;
+ }
+ values.radius += valueOrDefault(parsed && parsed._custom, radius);
+ return values;
+ }
+}
+BubbleController.id = 'bubble';
+BubbleController.defaults = {
+ datasetElementType: false,
+ dataElementType: 'point',
+ animations: {
+ numbers: {
+ type: 'number',
+ properties: ['x', 'y', 'borderWidth', 'radius']
+ }
+ }
+};
+BubbleController.overrides = {
+ scales: {
+ x: {
+ type: 'linear'
+ },
+ y: {
+ type: 'linear'
+ }
+ },
+ plugins: {
+ tooltip: {
+ callbacks: {
+ title() {
+ return '';
+ }
+ }
+ }
+ }
+};
+
+function getRatioAndOffset(rotation, circumference, cutout) {
+ let ratioX = 1;
+ let ratioY = 1;
+ let offsetX = 0;
+ let offsetY = 0;
+ if (circumference < TAU) {
+ const startAngle = rotation;
+ const endAngle = startAngle + circumference;
+ const startX = Math.cos(startAngle);
+ const startY = Math.sin(startAngle);
+ const endX = Math.cos(endAngle);
+ const endY = Math.sin(endAngle);
+ const calcMax = (angle, a, b) => _angleBetween(angle, startAngle, endAngle, true) ? 1 : Math.max(a, a * cutout, b, b * cutout);
+ const calcMin = (angle, a, b) => _angleBetween(angle, startAngle, endAngle, true) ? -1 : Math.min(a, a * cutout, b, b * cutout);
+ const maxX = calcMax(0, startX, endX);
+ const maxY = calcMax(HALF_PI, startY, endY);
+ const minX = calcMin(PI, startX, endX);
+ const minY = calcMin(PI + HALF_PI, startY, endY);
+ ratioX = (maxX - minX) / 2;
+ ratioY = (maxY - minY) / 2;
+ offsetX = -(maxX + minX) / 2;
+ offsetY = -(maxY + minY) / 2;
+ }
+ return {ratioX, ratioY, offsetX, offsetY};
+}
+class DoughnutController extends DatasetController {
+ constructor(chart, datasetIndex) {
+ super(chart, datasetIndex);
+ this.enableOptionSharing = true;
+ this.innerRadius = undefined;
+ this.outerRadius = undefined;
+ this.offsetX = undefined;
+ this.offsetY = undefined;
+ }
+ linkScales() {}
+ parse(start, count) {
+ const data = this.getDataset().data;
+ const meta = this._cachedMeta;
+ if (this._parsing === false) {
+ meta._parsed = data;
+ } else {
+ let getter = (i) => +data[i];
+ if (isObject(data[start])) {
+ const {key = 'value'} = this._parsing;
+ getter = (i) => +resolveObjectKey(data[i], key);
+ }
+ let i, ilen;
+ for (i = start, ilen = start + count; i < ilen; ++i) {
+ meta._parsed[i] = getter(i);
+ }
+ }
+ }
+ _getRotation() {
+ return toRadians(this.options.rotation - 90);
+ }
+ _getCircumference() {
+ return toRadians(this.options.circumference);
+ }
+ _getRotationExtents() {
+ let min = TAU;
+ let max = -TAU;
+ for (let i = 0; i < this.chart.data.datasets.length; ++i) {
+ if (this.chart.isDatasetVisible(i)) {
+ const controller = this.chart.getDatasetMeta(i).controller;
+ const rotation = controller._getRotation();
+ const circumference = controller._getCircumference();
+ min = Math.min(min, rotation);
+ max = Math.max(max, rotation + circumference);
+ }
+ }
+ return {
+ rotation: min,
+ circumference: max - min,
+ };
+ }
+ update(mode) {
+ const chart = this.chart;
+ const {chartArea} = chart;
+ const meta = this._cachedMeta;
+ const arcs = meta.data;
+ const spacing = this.getMaxBorderWidth() + this.getMaxOffset(arcs) + this.options.spacing;
+ const maxSize = Math.max((Math.min(chartArea.width, chartArea.height) - spacing) / 2, 0);
+ const cutout = Math.min(toPercentage(this.options.cutout, maxSize), 1);
+ const chartWeight = this._getRingWeight(this.index);
+ const {circumference, rotation} = this._getRotationExtents();
+ const {ratioX, ratioY, offsetX, offsetY} = getRatioAndOffset(rotation, circumference, cutout);
+ const maxWidth = (chartArea.width - spacing) / ratioX;
+ const maxHeight = (chartArea.height - spacing) / ratioY;
+ const maxRadius = Math.max(Math.min(maxWidth, maxHeight) / 2, 0);
+ const outerRadius = toDimension(this.options.radius, maxRadius);
+ const innerRadius = Math.max(outerRadius * cutout, 0);
+ const radiusLength = (outerRadius - innerRadius) / this._getVisibleDatasetWeightTotal();
+ this.offsetX = offsetX * outerRadius;
+ this.offsetY = offsetY * outerRadius;
+ meta.total = this.calculateTotal();
+ this.outerRadius = outerRadius - radiusLength * this._getRingWeightOffset(this.index);
+ this.innerRadius = Math.max(this.outerRadius - radiusLength * chartWeight, 0);
+ this.updateElements(arcs, 0, arcs.length, mode);
+ }
+ _circumference(i, reset) {
+ const opts = this.options;
+ const meta = this._cachedMeta;
+ const circumference = this._getCircumference();
+ if ((reset && opts.animation.animateRotate) || !this.chart.getDataVisibility(i) || meta._parsed[i] === null || meta.data[i].hidden) {
+ return 0;
+ }
+ return this.calculateCircumference(meta._parsed[i] * circumference / TAU);
+ }
+ updateElements(arcs, start, count, mode) {
+ const reset = mode === 'reset';
+ const chart = this.chart;
+ const chartArea = chart.chartArea;
+ const opts = chart.options;
+ const animationOpts = opts.animation;
+ const centerX = (chartArea.left + chartArea.right) / 2;
+ const centerY = (chartArea.top + chartArea.bottom) / 2;
+ const animateScale = reset && animationOpts.animateScale;
+ const innerRadius = animateScale ? 0 : this.innerRadius;
+ const outerRadius = animateScale ? 0 : this.outerRadius;
+ const firstOpts = this.resolveDataElementOptions(start, mode);
+ const sharedOptions = this.getSharedOptions(firstOpts);
+ const includeOptions = this.includeOptions(mode, sharedOptions);
+ let startAngle = this._getRotation();
+ let i;
+ for (i = 0; i < start; ++i) {
+ startAngle += this._circumference(i, reset);
+ }
+ for (i = start; i < start + count; ++i) {
+ const circumference = this._circumference(i, reset);
+ const arc = arcs[i];
+ const properties = {
+ x: centerX + this.offsetX,
+ y: centerY + this.offsetY,
+ startAngle,
+ endAngle: startAngle + circumference,
+ circumference,
+ outerRadius,
+ innerRadius
+ };
+ if (includeOptions) {
+ properties.options = sharedOptions || this.resolveDataElementOptions(i, arc.active ? 'active' : mode);
+ }
+ startAngle += circumference;
+ this.updateElement(arc, i, properties, mode);
+ }
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
+ }
+ calculateTotal() {
+ const meta = this._cachedMeta;
+ const metaData = meta.data;
+ let total = 0;
+ let i;
+ for (i = 0; i < metaData.length; i++) {
+ const value = meta._parsed[i];
+ if (value !== null && !isNaN(value) && this.chart.getDataVisibility(i) && !metaData[i].hidden) {
+ total += Math.abs(value);
+ }
+ }
+ return total;
+ }
+ calculateCircumference(value) {
+ const total = this._cachedMeta.total;
+ if (total > 0 && !isNaN(value)) {
+ return TAU * (Math.abs(value) / total);
+ }
+ return 0;
+ }
+ getLabelAndValue(index) {
+ const meta = this._cachedMeta;
+ const chart = this.chart;
+ const labels = chart.data.labels || [];
+ const value = formatNumber(meta._parsed[index], chart.options.locale);
+ return {
+ label: labels[index] || '',
+ value,
+ };
+ }
+ getMaxBorderWidth(arcs) {
+ let max = 0;
+ const chart = this.chart;
+ let i, ilen, meta, controller, options;
+ if (!arcs) {
+ for (i = 0, ilen = chart.data.datasets.length; i < ilen; ++i) {
+ if (chart.isDatasetVisible(i)) {
+ meta = chart.getDatasetMeta(i);
+ arcs = meta.data;
+ controller = meta.controller;
+ if (controller !== this) {
+ controller.configure();
+ }
+ break;
+ }
+ }
+ }
+ if (!arcs) {
+ return 0;
+ }
+ for (i = 0, ilen = arcs.length; i < ilen; ++i) {
+ options = controller.resolveDataElementOptions(i);
+ if (options.borderAlign !== 'inner') {
+ max = Math.max(max, options.borderWidth || 0, options.hoverBorderWidth || 0);
+ }
+ }
+ return max;
+ }
+ getMaxOffset(arcs) {
+ let max = 0;
+ for (let i = 0, ilen = arcs.length; i < ilen; ++i) {
+ const options = this.resolveDataElementOptions(i);
+ max = Math.max(max, options.offset || 0, options.hoverOffset || 0);
+ }
+ return max;
+ }
+ _getRingWeightOffset(datasetIndex) {
+ let ringWeightOffset = 0;
+ for (let i = 0; i < datasetIndex; ++i) {
+ if (this.chart.isDatasetVisible(i)) {
+ ringWeightOffset += this._getRingWeight(i);
+ }
+ }
+ return ringWeightOffset;
+ }
+ _getRingWeight(datasetIndex) {
+ return Math.max(valueOrDefault(this.chart.data.datasets[datasetIndex].weight, 1), 0);
+ }
+ _getVisibleDatasetWeightTotal() {
+ return this._getRingWeightOffset(this.chart.data.datasets.length) || 1;
+ }
+}
+DoughnutController.id = 'doughnut';
+DoughnutController.defaults = {
+ datasetElementType: false,
+ dataElementType: 'arc',
+ animation: {
+ animateRotate: true,
+ animateScale: false
+ },
+ animations: {
+ numbers: {
+ type: 'number',
+ properties: ['circumference', 'endAngle', 'innerRadius', 'outerRadius', 'startAngle', 'x', 'y', 'offset', 'borderWidth', 'spacing']
+ },
+ },
+ cutout: '50%',
+ rotation: 0,
+ circumference: 360,
+ radius: '100%',
+ spacing: 0,
+ indexAxis: 'r',
+};
+DoughnutController.descriptors = {
+ _scriptable: (name) => name !== 'spacing',
+ _indexable: (name) => name !== 'spacing',
+};
+DoughnutController.overrides = {
+ aspectRatio: 1,
+ plugins: {
+ legend: {
+ labels: {
+ generateLabels(chart) {
+ const data = chart.data;
+ if (data.labels.length && data.datasets.length) {
+ const {labels: {pointStyle}} = chart.legend.options;
+ return data.labels.map((label, i) => {
+ const meta = chart.getDatasetMeta(0);
+ const style = meta.controller.getStyle(i);
+ return {
+ text: label,
+ fillStyle: style.backgroundColor,
+ strokeStyle: style.borderColor,
+ lineWidth: style.borderWidth,
+ pointStyle: pointStyle,
+ hidden: !chart.getDataVisibility(i),
+ index: i
+ };
+ });
+ }
+ return [];
+ }
+ },
+ onClick(e, legendItem, legend) {
+ legend.chart.toggleDataVisibility(legendItem.index);
+ legend.chart.update();
+ }
+ },
+ tooltip: {
+ callbacks: {
+ title() {
+ return '';
+ },
+ label(tooltipItem) {
+ let dataLabel = tooltipItem.label;
+ const value = ': ' + tooltipItem.formattedValue;
+ if (isArray(dataLabel)) {
+ dataLabel = dataLabel.slice();
+ dataLabel[0] += value;
+ } else {
+ dataLabel += value;
+ }
+ return dataLabel;
+ }
+ }
+ }
+ }
+};
+
+class LineController extends DatasetController {
+ initialize() {
+ this.enableOptionSharing = true;
+ super.initialize();
+ }
+ update(mode) {
+ const meta = this._cachedMeta;
+ const {dataset: line, data: points = [], _dataset} = meta;
+ const animationsDisabled = this.chart._animationsDisabled;
+ let {start, count} = getStartAndCountOfVisiblePoints(meta, points, animationsDisabled);
+ this._drawStart = start;
+ this._drawCount = count;
+ if (scaleRangesChanged(meta)) {
+ start = 0;
+ count = points.length;
+ }
+ line._chart = this.chart;
+ line._datasetIndex = this.index;
+ line._decimated = !!_dataset._decimated;
+ line.points = points;
+ const options = this.resolveDatasetElementOptions(mode);
+ if (!this.options.showLine) {
+ options.borderWidth = 0;
+ }
+ options.segment = this.options.segment;
+ this.updateElement(line, undefined, {
+ animated: !animationsDisabled,
+ options
+ }, mode);
+ this.updateElements(points, start, count, mode);
+ }
+ updateElements(points, start, count, mode) {
+ const reset = mode === 'reset';
+ const {iScale, vScale, _stacked, _dataset} = this._cachedMeta;
+ const firstOpts = this.resolveDataElementOptions(start, mode);
+ const sharedOptions = this.getSharedOptions(firstOpts);
+ const includeOptions = this.includeOptions(mode, sharedOptions);
+ const iAxis = iScale.axis;
+ const vAxis = vScale.axis;
+ const {spanGaps, segment} = this.options;
+ const maxGapLength = isNumber(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY;
+ const directUpdate = this.chart._animationsDisabled || reset || mode === 'none';
+ let prevParsed = start > 0 && this.getParsed(start - 1);
+ for (let i = start; i < start + count; ++i) {
+ const point = points[i];
+ const parsed = this.getParsed(i);
+ const properties = directUpdate ? point : {};
+ const nullData = isNullOrUndef(parsed[vAxis]);
+ const iPixel = properties[iAxis] = iScale.getPixelForValue(parsed[iAxis], i);
+ const vPixel = properties[vAxis] = reset || nullData ? vScale.getBasePixel() : vScale.getPixelForValue(_stacked ? this.applyStack(vScale, parsed, _stacked) : parsed[vAxis], i);
+ properties.skip = isNaN(iPixel) || isNaN(vPixel) || nullData;
+ properties.stop = i > 0 && (parsed[iAxis] - prevParsed[iAxis]) > maxGapLength;
+ if (segment) {
+ properties.parsed = parsed;
+ properties.raw = _dataset.data[i];
+ }
+ if (includeOptions) {
+ properties.options = sharedOptions || this.resolveDataElementOptions(i, point.active ? 'active' : mode);
+ }
+ if (!directUpdate) {
+ this.updateElement(point, i, properties, mode);
+ }
+ prevParsed = parsed;
+ }
+ this.updateSharedOptions(sharedOptions, mode, firstOpts);
+ }
+ getMaxOverflow() {
+ const meta = this._cachedMeta;
+ const dataset = meta.dataset;
+ const border = dataset.options && dataset.options.borderWidth || 0;
+ const data = meta.data || [];
+ if (!data.length) {
+ return border;
+ }
+ const firstPoint = data[0].size(this.resolveDataElementOptions(0));
+ const lastPoint = data[data.length - 1].size(this.resolveDataElementOptions(data.length - 1));
+ return Math.max(border, firstPoint, lastPoint) / 2;
+ }
+ draw() {
+ const meta = this._cachedMeta;
+ meta.dataset.updateControlPoints(this.chart.chartArea, meta.iScale.axis);
+ super.draw();
+ }
+}
+LineController.id = 'line';
+LineController.defaults = {
+ datasetElementType: 'line',
+ dataElementType: 'point',
+ showLine: true,
+ spanGaps: false,
+};
+LineController.overrides = {
+ scales: {
+ _index_: {
+ type: 'category',
+ },
+ _value_: {
+ type: 'linear',
+ },
+ }
+};
+function getStartAndCountOfVisiblePoints(meta, points, animationsDisabled) {
+ const pointCount = points.length;
+ let start = 0;
+ let count = pointCount;
+ if (meta._sorted) {
+ const {iScale, _parsed} = meta;
+ const axis = iScale.axis;
+ const {min, max, minDefined, maxDefined} = iScale.getUserBounds();
+ if (minDefined) {
+ start = _limitValue(Math.min(
+ _lookupByKey(_parsed, iScale.axis, min).lo,
+ animationsDisabled ? pointCount : _lookupByKey(points, axis, iScale.getPixelForValue(min)).lo),
+ 0, pointCount - 1);
+ }
+ if (maxDefined) {
+ count = _limitValue(Math.max(
+ _lookupByKey(_parsed, iScale.axis, max).hi + 1,
+ animationsDisabled ? 0 : _lookupByKey(points, axis, iScale.getPixelForValue(max)).hi + 1),
+ start, pointCount) - start;
+ } else {
+ count = pointCount - start;
+ }
+ }
+ return {start, count};
+}
+function scaleRangesChanged(meta) {
+ const {xScale, yScale, _scaleRanges} = meta;
+ const newRanges = {
+ xmin: xScale.min,
+ xmax: xScale.max,
+ ymin: yScale.min,
+ ymax: yScale.max
+ };
+ if (!_scaleRanges) {
+ meta._scaleRanges = newRanges;
+ return true;
+ }
+ const changed = _scaleRanges.xmin !== xScale.min
+ || _scaleRanges.xmax !== xScale.max
+ || _scaleRanges.ymin !== yScale.min
+ || _scaleRanges.ymax !== yScale.max;
+ Object.assign(_scaleRanges, newRanges);
+ return changed;
+}
+
+class PolarAreaController extends DatasetController {
+ constructor(chart, datasetIndex) {
+ super(chart, datasetIndex);
+ this.innerRadius = undefined;
+ this.outerRadius = undefined;
+ }
+ getLabelAndValue(index) {
+ const meta = this._cachedMeta;
+ const chart = this.chart;
+ const labels = chart.data.labels || [];
+ const value = formatNumber(meta._parsed[index].r, chart.options.locale);
+ return {
+ label: labels[index] || '',
+ value,
+ };
+ }
+ update(mode) {
+ const arcs = this._cachedMeta.data;
+ this._updateRadius();
+ this.updateElements(arcs, 0, arcs.length, mode);
+ }
+ _updateRadius() {
+ const chart = this.chart;
+ const chartArea = chart.chartArea;
+ const opts = chart.options;
+ const minSize = Math.min(chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
+ const outerRadius = Math.max(minSize / 2, 0);
+ const innerRadius = Math.max(opts.cutoutPercentage ? (outerRadius / 100) * (opts.cutoutPercentage) : 1, 0);
+ const radiusLength = (outerRadius - innerRadius) / chart.getVisibleDatasetCount();
+ this.outerRadius = outerRadius - (radiusLength * this.index);
+ this.innerRadius = this.outerRadius - radiusLength;
+ }
+ updateElements(arcs, start, count, mode) {
+ const reset = mode === 'reset';
+ const chart = this.chart;
+ const dataset = this.getDataset();
+ const opts = chart.options;
+ const animationOpts = opts.animation;
+ const scale = this._cachedMeta.rScale;
+ const centerX = scale.xCenter;
+ const centerY = scale.yCenter;
+ const datasetStartAngle = scale.getIndexAngle(0) - 0.5 * PI;
+ let angle = datasetStartAngle;
+ let i;
+ const defaultAngle = 360 / this.countVisibleElements();
+ for (i = 0; i < start; ++i) {
+ angle += this._computeAngle(i, mode, defaultAngle);
+ }
+ for (i = start; i < start + count; i++) {
+ const arc = arcs[i];
+ let startAngle = angle;
+ let endAngle = angle + this._computeAngle(i, mode, defaultAngle);
+ let outerRadius = chart.getDataVisibility(i) ? scale.getDistanceFromCenterForValue(dataset.data[i]) : 0;
+ angle = endAngle;
+ if (reset) {
+ if (animationOpts.animateScale) {
+ outerRadius = 0;
+ }
+ if (animationOpts.animateRotate) {
+ startAngle = endAngle = datasetStartAngle;
+ }
+ }
+ const properties = {
+ x: centerX,
+ y: centerY,
+ innerRadius: 0,
+ outerRadius,
+ startAngle,
+ endAngle,
+ options: this.resolveDataElementOptions(i, arc.active ? 'active' : mode)
+ };
+ this.updateElement(arc, i, properties, mode);
+ }
+ }
+ countVisibleElements() {
+ const dataset = this.getDataset();
+ const meta = this._cachedMeta;
+ let count = 0;
+ meta.data.forEach((element, index) => {
+ if (!isNaN(dataset.data[index]) && this.chart.getDataVisibility(index)) {
+ count++;
+ }
+ });
+ return count;
+ }
+ _computeAngle(index, mode, defaultAngle) {
+ return this.chart.getDataVisibility(index)
+ ? toRadians(this.resolveDataElementOptions(index, mode).angle || defaultAngle)
+ : 0;
+ }
+}
+PolarAreaController.id = 'polarArea';
+PolarAreaController.defaults = {
+ dataElementType: 'arc',
+ animation: {
+ animateRotate: true,
+ animateScale: true
+ },
+ animations: {
+ numbers: {
+ type: 'number',
+ properties: ['x', 'y', 'startAngle', 'endAngle', 'innerRadius', 'outerRadius']
+ },
+ },
+ indexAxis: 'r',
+ startAngle: 0,
+};
+PolarAreaController.overrides = {
+ aspectRatio: 1,
+ plugins: {
+ legend: {
+ labels: {
+ generateLabels(chart) {
+ const data = chart.data;
+ if (data.labels.length && data.datasets.length) {
+ const {labels: {pointStyle}} = chart.legend.options;
+ return data.labels.map((label, i) => {
+ const meta = chart.getDatasetMeta(0);
+ const style = meta.controller.getStyle(i);
+ return {
+ text: label,
+ fillStyle: style.backgroundColor,
+ strokeStyle: style.borderColor,
+ lineWidth: style.borderWidth,
+ pointStyle: pointStyle,
+ hidden: !chart.getDataVisibility(i),
+ index: i
+ };
+ });
+ }
+ return [];
+ }
+ },
+ onClick(e, legendItem, legend) {
+ legend.chart.toggleDataVisibility(legendItem.index);
+ legend.chart.update();
+ }
+ },
+ tooltip: {
+ callbacks: {
+ title() {
+ return '';
+ },
+ label(context) {
+ return context.chart.data.labels[context.dataIndex] + ': ' + context.formattedValue;
+ }
+ }
+ }
+ },
+ scales: {
+ r: {
+ type: 'radialLinear',
+ angleLines: {
+ display: false
+ },
+ beginAtZero: true,
+ grid: {
+ circular: true
+ },
+ pointLabels: {
+ display: false
+ },
+ startAngle: 0
+ }
+ }
+};
+
+class PieController extends DoughnutController {
+}
+PieController.id = 'pie';
+PieController.defaults = {
+ cutout: 0,
+ rotation: 0,
+ circumference: 360,
+ radius: '100%'
+};
+
+class RadarController extends DatasetController {
+ getLabelAndValue(index) {
+ const vScale = this._cachedMeta.vScale;
+ const parsed = this.getParsed(index);
+ return {
+ label: vScale.getLabels()[index],
+ value: '' + vScale.getLabelForValue(parsed[vScale.axis])
+ };
+ }
+ update(mode) {
+ const meta = this._cachedMeta;
+ const line = meta.dataset;
+ const points = meta.data || [];
+ const labels = meta.iScale.getLabels();
+ line.points = points;
+ if (mode !== 'resize') {
+ const options = this.resolveDatasetElementOptions(mode);
+ if (!this.options.showLine) {
+ options.borderWidth = 0;
+ }
+ const properties = {
+ _loop: true,
+ _fullLoop: labels.length === points.length,
+ options
+ };
+ this.updateElement(line, undefined, properties, mode);
+ }
+ this.updateElements(points, 0, points.length, mode);
+ }
+ updateElements(points, start, count, mode) {
+ const dataset = this.getDataset();
+ const scale = this._cachedMeta.rScale;
+ const reset = mode === 'reset';
+ for (let i = start; i < start + count; i++) {
+ const point = points[i];
+ const options = this.resolveDataElementOptions(i, point.active ? 'active' : mode);
+ const pointPosition = scale.getPointPositionForValue(i, dataset.data[i]);
+ const x = reset ? scale.xCenter : pointPosition.x;
+ const y = reset ? scale.yCenter : pointPosition.y;
+ const properties = {
+ x,
+ y,
+ angle: pointPosition.angle,
+ skip: isNaN(x) || isNaN(y),
+ options
+ };
+ this.updateElement(point, i, properties, mode);
+ }
+ }
+}
+RadarController.id = 'radar';
+RadarController.defaults = {
+ datasetElementType: 'line',
+ dataElementType: 'point',
+ indexAxis: 'r',
+ showLine: true,
+ elements: {
+ line: {
+ fill: 'start'
+ }
+ },
+};
+RadarController.overrides = {
+ aspectRatio: 1,
+ scales: {
+ r: {
+ type: 'radialLinear',
+ }
+ }
+};
+
+class ScatterController extends LineController {
+}
+ScatterController.id = 'scatter';
+ScatterController.defaults = {
+ showLine: false,
+ fill: false
+};
+ScatterController.overrides = {
+ interaction: {
+ mode: 'point'
+ },
+ plugins: {
+ tooltip: {
+ callbacks: {
+ title() {
+ return '';
+ },
+ label(item) {
+ return '(' + item.label + ', ' + item.formattedValue + ')';
+ }
+ }
+ }
+ },
+ scales: {
+ x: {
+ type: 'linear'
+ },
+ y: {
+ type: 'linear'
+ }
+ }
+};
+
+var controllers = /*#__PURE__*/Object.freeze({
+__proto__: null,
+BarController: BarController,
+BubbleController: BubbleController,
+DoughnutController: DoughnutController,
+LineController: LineController,
+PolarAreaController: PolarAreaController,
+PieController: PieController,
+RadarController: RadarController,
+ScatterController: ScatterController
+});
+
+function clipArc(ctx, element, endAngle) {
+ const {startAngle, pixelMargin, x, y, outerRadius, innerRadius} = element;
+ let angleMargin = pixelMargin / outerRadius;
+ ctx.beginPath();
+ ctx.arc(x, y, outerRadius, startAngle - angleMargin, endAngle + angleMargin);
+ if (innerRadius > pixelMargin) {
+ angleMargin = pixelMargin / innerRadius;
+ ctx.arc(x, y, innerRadius, endAngle + angleMargin, startAngle - angleMargin, true);
+ } else {
+ ctx.arc(x, y, pixelMargin, endAngle + HALF_PI, startAngle - HALF_PI);
+ }
+ ctx.closePath();
+ ctx.clip();
+}
+function toRadiusCorners(value) {
+ return _readValueToProps(value, ['outerStart', 'outerEnd', 'innerStart', 'innerEnd']);
+}
+function parseBorderRadius$1(arc, innerRadius, outerRadius, angleDelta) {
+ const o = toRadiusCorners(arc.options.borderRadius);
+ const halfThickness = (outerRadius - innerRadius) / 2;
+ const innerLimit = Math.min(halfThickness, angleDelta * innerRadius / 2);
+ const computeOuterLimit = (val) => {
+ const outerArcLimit = (outerRadius - Math.min(halfThickness, val)) * angleDelta / 2;
+ return _limitValue(val, 0, Math.min(halfThickness, outerArcLimit));
+ };
+ return {
+ outerStart: computeOuterLimit(o.outerStart),
+ outerEnd: computeOuterLimit(o.outerEnd),
+ innerStart: _limitValue(o.innerStart, 0, innerLimit),
+ innerEnd: _limitValue(o.innerEnd, 0, innerLimit),
+ };
+}
+function rThetaToXY(r, theta, x, y) {
+ return {
+ x: x + r * Math.cos(theta),
+ y: y + r * Math.sin(theta),
+ };
+}
+function pathArc(ctx, element, offset, spacing, end) {
+ const {x, y, startAngle: start, pixelMargin, innerRadius: innerR} = element;
+ const outerRadius = Math.max(element.outerRadius + spacing + offset - pixelMargin, 0);
+ const innerRadius = innerR > 0 ? innerR + spacing + offset + pixelMargin : 0;
+ let spacingOffset = 0;
+ const alpha = end - start;
+ if (spacing) {
+ const noSpacingInnerRadius = innerR > 0 ? innerR - spacing : 0;
+ const noSpacingOuterRadius = outerRadius > 0 ? outerRadius - spacing : 0;
+ const avNogSpacingRadius = (noSpacingInnerRadius + noSpacingOuterRadius) / 2;
+ const adjustedAngle = avNogSpacingRadius !== 0 ? (alpha * avNogSpacingRadius) / (avNogSpacingRadius + spacing) : alpha;
+ spacingOffset = (alpha - adjustedAngle) / 2;
+ }
+ const beta = Math.max(0.001, alpha * outerRadius - offset / PI) / outerRadius;
+ const angleOffset = (alpha - beta) / 2;
+ const startAngle = start + angleOffset + spacingOffset;
+ const endAngle = end - angleOffset - spacingOffset;
+ const {outerStart, outerEnd, innerStart, innerEnd} = parseBorderRadius$1(element, innerRadius, outerRadius, endAngle - startAngle);
+ const outerStartAdjustedRadius = outerRadius - outerStart;
+ const outerEndAdjustedRadius = outerRadius - outerEnd;
+ const outerStartAdjustedAngle = startAngle + outerStart / outerStartAdjustedRadius;
+ const outerEndAdjustedAngle = endAngle - outerEnd / outerEndAdjustedRadius;
+ const innerStartAdjustedRadius = innerRadius + innerStart;
+ const innerEndAdjustedRadius = innerRadius + innerEnd;
+ const innerStartAdjustedAngle = startAngle + innerStart / innerStartAdjustedRadius;
+ const innerEndAdjustedAngle = endAngle - innerEnd / innerEndAdjustedRadius;
+ ctx.beginPath();
+ ctx.arc(x, y, outerRadius, outerStartAdjustedAngle, outerEndAdjustedAngle);
+ if (outerEnd > 0) {
+ const pCenter = rThetaToXY(outerEndAdjustedRadius, outerEndAdjustedAngle, x, y);
+ ctx.arc(pCenter.x, pCenter.y, outerEnd, outerEndAdjustedAngle, endAngle + HALF_PI);
+ }
+ const p4 = rThetaToXY(innerEndAdjustedRadius, endAngle, x, y);
+ ctx.lineTo(p4.x, p4.y);
+ if (innerEnd > 0) {
+ const pCenter = rThetaToXY(innerEndAdjustedRadius, innerEndAdjustedAngle, x, y);
+ ctx.arc(pCenter.x, pCenter.y, innerEnd, endAngle + HALF_PI, innerEndAdjustedAngle + Math.PI);
+ }
+ ctx.arc(x, y, innerRadius, endAngle - (innerEnd / innerRadius), startAngle + (innerStart / innerRadius), true);
+ if (innerStart > 0) {
+ const pCenter = rThetaToXY(innerStartAdjustedRadius, innerStartAdjustedAngle, x, y);
+ ctx.arc(pCenter.x, pCenter.y, innerStart, innerStartAdjustedAngle + Math.PI, startAngle - HALF_PI);
+ }
+ const p8 = rThetaToXY(outerStartAdjustedRadius, startAngle, x, y);
+ ctx.lineTo(p8.x, p8.y);
+ if (outerStart > 0) {
+ const pCenter = rThetaToXY(outerStartAdjustedRadius, outerStartAdjustedAngle, x, y);
+ ctx.arc(pCenter.x, pCenter.y, outerStart, startAngle - HALF_PI, outerStartAdjustedAngle);
+ }
+ ctx.closePath();
+}
+function drawArc(ctx, element, offset, spacing) {
+ const {fullCircles, startAngle, circumference} = element;
+ let endAngle = element.endAngle;
+ if (fullCircles) {
+ pathArc(ctx, element, offset, spacing, startAngle + TAU);
+ for (let i = 0; i < fullCircles; ++i) {
+ ctx.fill();
+ }
+ if (!isNaN(circumference)) {
+ endAngle = startAngle + circumference % TAU;
+ if (circumference % TAU === 0) {
+ endAngle += TAU;
+ }
+ }
+ }
+ pathArc(ctx, element, offset, spacing, endAngle);
+ ctx.fill();
+ return endAngle;
+}
+function drawFullCircleBorders(ctx, element, inner) {
+ const {x, y, startAngle, pixelMargin, fullCircles} = element;
+ const outerRadius = Math.max(element.outerRadius - pixelMargin, 0);
+ const innerRadius = element.innerRadius + pixelMargin;
+ let i;
+ if (inner) {
+ clipArc(ctx, element, startAngle + TAU);
+ }
+ ctx.beginPath();
+ ctx.arc(x, y, innerRadius, startAngle + TAU, startAngle, true);
+ for (i = 0; i < fullCircles; ++i) {
+ ctx.stroke();
+ }
+ ctx.beginPath();
+ ctx.arc(x, y, outerRadius, startAngle, startAngle + TAU);
+ for (i = 0; i < fullCircles; ++i) {
+ ctx.stroke();
+ }
+}
+function drawBorder(ctx, element, offset, spacing, endAngle) {
+ const {options} = element;
+ const inner = options.borderAlign === 'inner';
+ if (!options.borderWidth) {
+ return;
+ }
+ if (inner) {
+ ctx.lineWidth = options.borderWidth * 2;
+ ctx.lineJoin = 'round';
+ } else {
+ ctx.lineWidth = options.borderWidth;
+ ctx.lineJoin = 'bevel';
+ }
+ if (element.fullCircles) {
+ drawFullCircleBorders(ctx, element, inner);
+ }
+ if (inner) {
+ clipArc(ctx, element, endAngle);
+ }
+ pathArc(ctx, element, offset, spacing, endAngle);
+ ctx.stroke();
+}
+class ArcElement extends Element {
+ constructor(cfg) {
+ super();
+ this.options = undefined;
+ this.circumference = undefined;
+ this.startAngle = undefined;
+ this.endAngle = undefined;
+ this.innerRadius = undefined;
+ this.outerRadius = undefined;
+ this.pixelMargin = 0;
+ this.fullCircles = 0;
+ if (cfg) {
+ Object.assign(this, cfg);
+ }
+ }
+ inRange(chartX, chartY, useFinalPosition) {
+ const point = this.getProps(['x', 'y'], useFinalPosition);
+ const {angle, distance} = getAngleFromPoint(point, {x: chartX, y: chartY});
+ const {startAngle, endAngle, innerRadius, outerRadius, circumference} = this.getProps([
+ 'startAngle',
+ 'endAngle',
+ 'innerRadius',
+ 'outerRadius',
+ 'circumference'
+ ], useFinalPosition);
+ const rAdjust = this.options.spacing / 2;
+ const betweenAngles = circumference >= TAU || _angleBetween(angle, startAngle, endAngle);
+ const withinRadius = (distance >= innerRadius + rAdjust && distance <= outerRadius + rAdjust);
+ return (betweenAngles && withinRadius);
+ }
+ getCenterPoint(useFinalPosition) {
+ const {x, y, startAngle, endAngle, innerRadius, outerRadius} = this.getProps([
+ 'x',
+ 'y',
+ 'startAngle',
+ 'endAngle',
+ 'innerRadius',
+ 'outerRadius',
+ 'circumference',
+ ], useFinalPosition);
+ const {offset, spacing} = this.options;
+ const halfAngle = (startAngle + endAngle) / 2;
+ const halfRadius = (innerRadius + outerRadius + spacing + offset) / 2;
+ return {
+ x: x + Math.cos(halfAngle) * halfRadius,
+ y: y + Math.sin(halfAngle) * halfRadius
+ };
+ }
+ tooltipPosition(useFinalPosition) {
+ return this.getCenterPoint(useFinalPosition);
+ }
+ draw(ctx) {
+ const {options, circumference} = this;
+ const offset = (options.offset || 0) / 2;
+ const spacing = (options.spacing || 0) / 2;
+ this.pixelMargin = (options.borderAlign === 'inner') ? 0.33 : 0;
+ this.fullCircles = circumference > TAU ? Math.floor(circumference / TAU) : 0;
+ if (circumference === 0 || this.innerRadius < 0 || this.outerRadius < 0) {
+ return;
+ }
+ ctx.save();
+ let radiusOffset = 0;
+ if (offset) {
+ radiusOffset = offset / 2;
+ const halfAngle = (this.startAngle + this.endAngle) / 2;
+ ctx.translate(Math.cos(halfAngle) * radiusOffset, Math.sin(halfAngle) * radiusOffset);
+ if (this.circumference >= PI) {
+ radiusOffset = offset;
+ }
+ }
+ ctx.fillStyle = options.backgroundColor;
+ ctx.strokeStyle = options.borderColor;
+ const endAngle = drawArc(ctx, this, radiusOffset, spacing);
+ drawBorder(ctx, this, radiusOffset, spacing, endAngle);
+ ctx.restore();
+ }
+}
+ArcElement.id = 'arc';
+ArcElement.defaults = {
+ borderAlign: 'center',
+ borderColor: '#fff',
+ borderRadius: 0,
+ borderWidth: 2,
+ offset: 0,
+ spacing: 0,
+ angle: undefined,
+};
+ArcElement.defaultRoutes = {
+ backgroundColor: 'backgroundColor'
+};
+
+function setStyle(ctx, options, style = options) {
+ ctx.lineCap = valueOrDefault(style.borderCapStyle, options.borderCapStyle);
+ ctx.setLineDash(valueOrDefault(style.borderDash, options.borderDash));
+ ctx.lineDashOffset = valueOrDefault(style.borderDashOffset, options.borderDashOffset);
+ ctx.lineJoin = valueOrDefault(style.borderJoinStyle, options.borderJoinStyle);
+ ctx.lineWidth = valueOrDefault(style.borderWidth, options.borderWidth);
+ ctx.strokeStyle = valueOrDefault(style.borderColor, options.borderColor);
+}
+function lineTo(ctx, previous, target) {
+ ctx.lineTo(target.x, target.y);
+}
+function getLineMethod(options) {
+ if (options.stepped) {
+ return _steppedLineTo;
+ }
+ if (options.tension || options.cubicInterpolationMode === 'monotone') {
+ return _bezierCurveTo;
+ }
+ return lineTo;
+}
+function pathVars(points, segment, params = {}) {
+ const count = points.length;
+ const {start: paramsStart = 0, end: paramsEnd = count - 1} = params;
+ const {start: segmentStart, end: segmentEnd} = segment;
+ const start = Math.max(paramsStart, segmentStart);
+ const end = Math.min(paramsEnd, segmentEnd);
+ const outside = paramsStart < segmentStart && paramsEnd < segmentStart || paramsStart > segmentEnd && paramsEnd > segmentEnd;
+ return {
+ count,
+ start,
+ loop: segment.loop,
+ ilen: end < start && !outside ? count + end - start : end - start
+ };
+}
+function pathSegment(ctx, line, segment, params) {
+ const {points, options} = line;
+ const {count, start, loop, ilen} = pathVars(points, segment, params);
+ const lineMethod = getLineMethod(options);
+ let {move = true, reverse} = params || {};
+ let i, point, prev;
+ for (i = 0; i <= ilen; ++i) {
+ point = points[(start + (reverse ? ilen - i : i)) % count];
+ if (point.skip) {
+ continue;
+ } else if (move) {
+ ctx.moveTo(point.x, point.y);
+ move = false;
+ } else {
+ lineMethod(ctx, prev, point, reverse, options.stepped);
+ }
+ prev = point;
+ }
+ if (loop) {
+ point = points[(start + (reverse ? ilen : 0)) % count];
+ lineMethod(ctx, prev, point, reverse, options.stepped);
+ }
+ return !!loop;
+}
+function fastPathSegment(ctx, line, segment, params) {
+ const points = line.points;
+ const {count, start, ilen} = pathVars(points, segment, params);
+ const {move = true, reverse} = params || {};
+ let avgX = 0;
+ let countX = 0;
+ let i, point, prevX, minY, maxY, lastY;
+ const pointIndex = (index) => (start + (reverse ? ilen - index : index)) % count;
+ const drawX = () => {
+ if (minY !== maxY) {
+ ctx.lineTo(avgX, maxY);
+ ctx.lineTo(avgX, minY);
+ ctx.lineTo(avgX, lastY);
+ }
+ };
+ if (move) {
+ point = points[pointIndex(0)];
+ ctx.moveTo(point.x, point.y);
+ }
+ for (i = 0; i <= ilen; ++i) {
+ point = points[pointIndex(i)];
+ if (point.skip) {
+ continue;
+ }
+ const x = point.x;
+ const y = point.y;
+ const truncX = x | 0;
+ if (truncX === prevX) {
+ if (y < minY) {
+ minY = y;
+ } else if (y > maxY) {
+ maxY = y;
+ }
+ avgX = (countX * avgX + x) / ++countX;
+ } else {
+ drawX();
+ ctx.lineTo(x, y);
+ prevX = truncX;
+ countX = 0;
+ minY = maxY = y;
+ }
+ lastY = y;
+ }
+ drawX();
+}
+function _getSegmentMethod(line) {
+ const opts = line.options;
+ const borderDash = opts.borderDash && opts.borderDash.length;
+ const useFastPath = !line._decimated && !line._loop && !opts.tension && opts.cubicInterpolationMode !== 'monotone' && !opts.stepped && !borderDash;
+ return useFastPath ? fastPathSegment : pathSegment;
+}
+function _getInterpolationMethod(options) {
+ if (options.stepped) {
+ return _steppedInterpolation;
+ }
+ if (options.tension || options.cubicInterpolationMode === 'monotone') {
+ return _bezierInterpolation;
+ }
+ return _pointInLine;
+}
+function strokePathWithCache(ctx, line, start, count) {
+ let path = line._path;
+ if (!path) {
+ path = line._path = new Path2D();
+ if (line.path(path, start, count)) {
+ path.closePath();
+ }
+ }
+ setStyle(ctx, line.options);
+ ctx.stroke(path);
+}
+function strokePathDirect(ctx, line, start, count) {
+ const {segments, options} = line;
+ const segmentMethod = _getSegmentMethod(line);
+ for (const segment of segments) {
+ setStyle(ctx, options, segment.style);
+ ctx.beginPath();
+ if (segmentMethod(ctx, line, segment, {start, end: start + count - 1})) {
+ ctx.closePath();
+ }
+ ctx.stroke();
+ }
+}
+const usePath2D = typeof Path2D === 'function';
+function draw(ctx, line, start, count) {
+ if (usePath2D && !line.options.segment) {
+ strokePathWithCache(ctx, line, start, count);
+ } else {
+ strokePathDirect(ctx, line, start, count);
+ }
+}
+class LineElement extends Element {
+ constructor(cfg) {
+ super();
+ this.animated = true;
+ this.options = undefined;
+ this._chart = undefined;
+ this._loop = undefined;
+ this._fullLoop = undefined;
+ this._path = undefined;
+ this._points = undefined;
+ this._segments = undefined;
+ this._decimated = false;
+ this._pointsUpdated = false;
+ this._datasetIndex = undefined;
+ if (cfg) {
+ Object.assign(this, cfg);
+ }
+ }
+ updateControlPoints(chartArea, indexAxis) {
+ const options = this.options;
+ if ((options.tension || options.cubicInterpolationMode === 'monotone') && !options.stepped && !this._pointsUpdated) {
+ const loop = options.spanGaps ? this._loop : this._fullLoop;
+ _updateBezierControlPoints(this._points, options, chartArea, loop, indexAxis);
+ this._pointsUpdated = true;
+ }
+ }
+ set points(points) {
+ this._points = points;
+ delete this._segments;
+ delete this._path;
+ this._pointsUpdated = false;
+ }
+ get points() {
+ return this._points;
+ }
+ get segments() {
+ return this._segments || (this._segments = _computeSegments(this, this.options.segment));
+ }
+ first() {
+ const segments = this.segments;
+ const points = this.points;
+ return segments.length && points[segments[0].start];
+ }
+ last() {
+ const segments = this.segments;
+ const points = this.points;
+ const count = segments.length;
+ return count && points[segments[count - 1].end];
+ }
+ interpolate(point, property) {
+ const options = this.options;
+ const value = point[property];
+ const points = this.points;
+ const segments = _boundSegments(this, {property, start: value, end: value});
+ if (!segments.length) {
+ return;
+ }
+ const result = [];
+ const _interpolate = _getInterpolationMethod(options);
+ let i, ilen;
+ for (i = 0, ilen = segments.length; i < ilen; ++i) {
+ const {start, end} = segments[i];
+ const p1 = points[start];
+ const p2 = points[end];
+ if (p1 === p2) {
+ result.push(p1);
+ continue;
+ }
+ const t = Math.abs((value - p1[property]) / (p2[property] - p1[property]));
+ const interpolated = _interpolate(p1, p2, t, options.stepped);
+ interpolated[property] = point[property];
+ result.push(interpolated);
+ }
+ return result.length === 1 ? result[0] : result;
+ }
+ pathSegment(ctx, segment, params) {
+ const segmentMethod = _getSegmentMethod(this);
+ return segmentMethod(ctx, this, segment, params);
+ }
+ path(ctx, start, count) {
+ const segments = this.segments;
+ const segmentMethod = _getSegmentMethod(this);
+ let loop = this._loop;
+ start = start || 0;
+ count = count || (this.points.length - start);
+ for (const segment of segments) {
+ loop &= segmentMethod(ctx, this, segment, {start, end: start + count - 1});
+ }
+ return !!loop;
+ }
+ draw(ctx, chartArea, start, count) {
+ const options = this.options || {};
+ const points = this.points || [];
+ if (points.length && options.borderWidth) {
+ ctx.save();
+ draw(ctx, this, start, count);
+ ctx.restore();
+ }
+ if (this.animated) {
+ this._pointsUpdated = false;
+ this._path = undefined;
+ }
+ }
+}
+LineElement.id = 'line';
+LineElement.defaults = {
+ borderCapStyle: 'butt',
+ borderDash: [],
+ borderDashOffset: 0,
+ borderJoinStyle: 'miter',
+ borderWidth: 3,
+ capBezierPoints: true,
+ cubicInterpolationMode: 'default',
+ fill: false,
+ spanGaps: false,
+ stepped: false,
+ tension: 0,
+};
+LineElement.defaultRoutes = {
+ backgroundColor: 'backgroundColor',
+ borderColor: 'borderColor'
+};
+LineElement.descriptors = {
+ _scriptable: true,
+ _indexable: (name) => name !== 'borderDash' && name !== 'fill',
+};
+
+function inRange$1(el, pos, axis, useFinalPosition) {
+ const options = el.options;
+ const {[axis]: value} = el.getProps([axis], useFinalPosition);
+ return (Math.abs(pos - value) < options.radius + options.hitRadius);
+}
+class PointElement extends Element {
+ constructor(cfg) {
+ super();
+ this.options = undefined;
+ this.parsed = undefined;
+ this.skip = undefined;
+ this.stop = undefined;
+ if (cfg) {
+ Object.assign(this, cfg);
+ }
+ }
+ inRange(mouseX, mouseY, useFinalPosition) {
+ const options = this.options;
+ const {x, y} = this.getProps(['x', 'y'], useFinalPosition);
+ return ((Math.pow(mouseX - x, 2) + Math.pow(mouseY - y, 2)) < Math.pow(options.hitRadius + options.radius, 2));
+ }
+ inXRange(mouseX, useFinalPosition) {
+ return inRange$1(this, mouseX, 'x', useFinalPosition);
+ }
+ inYRange(mouseY, useFinalPosition) {
+ return inRange$1(this, mouseY, 'y', useFinalPosition);
+ }
+ getCenterPoint(useFinalPosition) {
+ const {x, y} = this.getProps(['x', 'y'], useFinalPosition);
+ return {x, y};
+ }
+ size(options) {
+ options = options || this.options || {};
+ let radius = options.radius || 0;
+ radius = Math.max(radius, radius && options.hoverRadius || 0);
+ const borderWidth = radius && options.borderWidth || 0;
+ return (radius + borderWidth) * 2;
+ }
+ draw(ctx, area) {
+ const options = this.options;
+ if (this.skip || options.radius < 0.1 || !_isPointInArea(this, area, this.size(options) / 2)) {
+ return;
+ }
+ ctx.strokeStyle = options.borderColor;
+ ctx.lineWidth = options.borderWidth;
+ ctx.fillStyle = options.backgroundColor;
+ drawPoint(ctx, options, this.x, this.y);
+ }
+ getRange() {
+ const options = this.options || {};
+ return options.radius + options.hitRadius;
+ }
+}
+PointElement.id = 'point';
+PointElement.defaults = {
+ borderWidth: 1,
+ hitRadius: 1,
+ hoverBorderWidth: 1,
+ hoverRadius: 4,
+ pointStyle: 'circle',
+ radius: 3,
+ rotation: 0
+};
+PointElement.defaultRoutes = {
+ backgroundColor: 'backgroundColor',
+ borderColor: 'borderColor'
+};
+
+function getBarBounds(bar, useFinalPosition) {
+ const {x, y, base, width, height} = bar.getProps(['x', 'y', 'base', 'width', 'height'], useFinalPosition);
+ let left, right, top, bottom, half;
+ if (bar.horizontal) {
+ half = height / 2;
+ left = Math.min(x, base);
+ right = Math.max(x, base);
+ top = y - half;
+ bottom = y + half;
+ } else {
+ half = width / 2;
+ left = x - half;
+ right = x + half;
+ top = Math.min(y, base);
+ bottom = Math.max(y, base);
+ }
+ return {left, top, right, bottom};
+}
+function skipOrLimit(skip, value, min, max) {
+ return skip ? 0 : _limitValue(value, min, max);
+}
+function parseBorderWidth(bar, maxW, maxH) {
+ const value = bar.options.borderWidth;
+ const skip = bar.borderSkipped;
+ const o = toTRBL(value);
+ return {
+ t: skipOrLimit(skip.top, o.top, 0, maxH),
+ r: skipOrLimit(skip.right, o.right, 0, maxW),
+ b: skipOrLimit(skip.bottom, o.bottom, 0, maxH),
+ l: skipOrLimit(skip.left, o.left, 0, maxW)
+ };
+}
+function parseBorderRadius(bar, maxW, maxH) {
+ const {enableBorderRadius} = bar.getProps(['enableBorderRadius']);
+ const value = bar.options.borderRadius;
+ const o = toTRBLCorners(value);
+ const maxR = Math.min(maxW, maxH);
+ const skip = bar.borderSkipped;
+ const enableBorder = enableBorderRadius || isObject(value);
+ return {
+ topLeft: skipOrLimit(!enableBorder || skip.top || skip.left, o.topLeft, 0, maxR),
+ topRight: skipOrLimit(!enableBorder || skip.top || skip.right, o.topRight, 0, maxR),
+ bottomLeft: skipOrLimit(!enableBorder || skip.bottom || skip.left, o.bottomLeft, 0, maxR),
+ bottomRight: skipOrLimit(!enableBorder || skip.bottom || skip.right, o.bottomRight, 0, maxR)
+ };
+}
+function boundingRects(bar) {
+ const bounds = getBarBounds(bar);
+ const width = bounds.right - bounds.left;
+ const height = bounds.bottom - bounds.top;
+ const border = parseBorderWidth(bar, width / 2, height / 2);
+ const radius = parseBorderRadius(bar, width / 2, height / 2);
+ return {
+ outer: {
+ x: bounds.left,
+ y: bounds.top,
+ w: width,
+ h: height,
+ radius
+ },
+ inner: {
+ x: bounds.left + border.l,
+ y: bounds.top + border.t,
+ w: width - border.l - border.r,
+ h: height - border.t - border.b,
+ radius: {
+ topLeft: Math.max(0, radius.topLeft - Math.max(border.t, border.l)),
+ topRight: Math.max(0, radius.topRight - Math.max(border.t, border.r)),
+ bottomLeft: Math.max(0, radius.bottomLeft - Math.max(border.b, border.l)),
+ bottomRight: Math.max(0, radius.bottomRight - Math.max(border.b, border.r)),
+ }
+ }
+ };
+}
+function inRange(bar, x, y, useFinalPosition) {
+ const skipX = x === null;
+ const skipY = y === null;
+ const skipBoth = skipX && skipY;
+ const bounds = bar && !skipBoth && getBarBounds(bar, useFinalPosition);
+ return bounds
+ && (skipX || x >= bounds.left && x <= bounds.right)
+ && (skipY || y >= bounds.top && y <= bounds.bottom);
+}
+function hasRadius(radius) {
+ return radius.topLeft || radius.topRight || radius.bottomLeft || radius.bottomRight;
+}
+function addNormalRectPath(ctx, rect) {
+ ctx.rect(rect.x, rect.y, rect.w, rect.h);
+}
+function inflateRect(rect, amount, refRect = {}) {
+ const x = rect.x !== refRect.x ? -amount : 0;
+ const y = rect.y !== refRect.y ? -amount : 0;
+ const w = (rect.x + rect.w !== refRect.x + refRect.w ? amount : 0) - x;
+ const h = (rect.y + rect.h !== refRect.y + refRect.h ? amount : 0) - y;
+ return {
+ x: rect.x + x,
+ y: rect.y + y,
+ w: rect.w + w,
+ h: rect.h + h,
+ radius: rect.radius
+ };
+}
+class BarElement extends Element {
+ constructor(cfg) {
+ super();
+ this.options = undefined;
+ this.horizontal = undefined;
+ this.base = undefined;
+ this.width = undefined;
+ this.height = undefined;
+ this.inflateAmount = undefined;
+ if (cfg) {
+ Object.assign(this, cfg);
+ }
+ }
+ draw(ctx) {
+ const {inflateAmount, options: {borderColor, backgroundColor}} = this;
+ const {inner, outer} = boundingRects(this);
+ const addRectPath = hasRadius(outer.radius) ? addRoundedRectPath : addNormalRectPath;
+ ctx.save();
+ if (outer.w !== inner.w || outer.h !== inner.h) {
+ ctx.beginPath();
+ addRectPath(ctx, inflateRect(outer, inflateAmount, inner));
+ ctx.clip();
+ addRectPath(ctx, inflateRect(inner, -inflateAmount, outer));
+ ctx.fillStyle = borderColor;
+ ctx.fill('evenodd');
+ }
+ ctx.beginPath();
+ addRectPath(ctx, inflateRect(inner, inflateAmount));
+ ctx.fillStyle = backgroundColor;
+ ctx.fill();
+ ctx.restore();
+ }
+ inRange(mouseX, mouseY, useFinalPosition) {
+ return inRange(this, mouseX, mouseY, useFinalPosition);
+ }
+ inXRange(mouseX, useFinalPosition) {
+ return inRange(this, mouseX, null, useFinalPosition);
+ }
+ inYRange(mouseY, useFinalPosition) {
+ return inRange(this, null, mouseY, useFinalPosition);
+ }
+ getCenterPoint(useFinalPosition) {
+ const {x, y, base, horizontal} = this.getProps(['x', 'y', 'base', 'horizontal'], useFinalPosition);
+ return {
+ x: horizontal ? (x + base) / 2 : x,
+ y: horizontal ? y : (y + base) / 2
+ };
+ }
+ getRange(axis) {
+ return axis === 'x' ? this.width / 2 : this.height / 2;
+ }
+}
+BarElement.id = 'bar';
+BarElement.defaults = {
+ borderSkipped: 'start',
+ borderWidth: 0,
+ borderRadius: 0,
+ inflateAmount: 'auto',
+ pointStyle: undefined
+};
+BarElement.defaultRoutes = {
+ backgroundColor: 'backgroundColor',
+ borderColor: 'borderColor'
+};
+
+var elements = /*#__PURE__*/Object.freeze({
+__proto__: null,
+ArcElement: ArcElement,
+LineElement: LineElement,
+PointElement: PointElement,
+BarElement: BarElement
+});
+
+function lttbDecimation(data, start, count, availableWidth, options) {
+ const samples = options.samples || availableWidth;
+ if (samples >= count) {
+ return data.slice(start, start + count);
+ }
+ const decimated = [];
+ const bucketWidth = (count - 2) / (samples - 2);
+ let sampledIndex = 0;
+ const endIndex = start + count - 1;
+ let a = start;
+ let i, maxAreaPoint, maxArea, area, nextA;
+ decimated[sampledIndex++] = data[a];
+ for (i = 0; i < samples - 2; i++) {
+ let avgX = 0;
+ let avgY = 0;
+ let j;
+ const avgRangeStart = Math.floor((i + 1) * bucketWidth) + 1 + start;
+ const avgRangeEnd = Math.min(Math.floor((i + 2) * bucketWidth) + 1, count) + start;
+ const avgRangeLength = avgRangeEnd - avgRangeStart;
+ for (j = avgRangeStart; j < avgRangeEnd; j++) {
+ avgX += data[j].x;
+ avgY += data[j].y;
+ }
+ avgX /= avgRangeLength;
+ avgY /= avgRangeLength;
+ const rangeOffs = Math.floor(i * bucketWidth) + 1 + start;
+ const rangeTo = Math.min(Math.floor((i + 1) * bucketWidth) + 1, count) + start;
+ const {x: pointAx, y: pointAy} = data[a];
+ maxArea = area = -1;
+ for (j = rangeOffs; j < rangeTo; j++) {
+ area = 0.5 * Math.abs(
+ (pointAx - avgX) * (data[j].y - pointAy) -
+ (pointAx - data[j].x) * (avgY - pointAy)
+ );
+ if (area > maxArea) {
+ maxArea = area;
+ maxAreaPoint = data[j];
+ nextA = j;
+ }
+ }
+ decimated[sampledIndex++] = maxAreaPoint;
+ a = nextA;
+ }
+ decimated[sampledIndex++] = data[endIndex];
+ return decimated;
+}
+function minMaxDecimation(data, start, count, availableWidth) {
+ let avgX = 0;
+ let countX = 0;
+ let i, point, x, y, prevX, minIndex, maxIndex, startIndex, minY, maxY;
+ const decimated = [];
+ const endIndex = start + count - 1;
+ const xMin = data[start].x;
+ const xMax = data[endIndex].x;
+ const dx = xMax - xMin;
+ for (i = start; i < start + count; ++i) {
+ point = data[i];
+ x = (point.x - xMin) / dx * availableWidth;
+ y = point.y;
+ const truncX = x | 0;
+ if (truncX === prevX) {
+ if (y < minY) {
+ minY = y;
+ minIndex = i;
+ } else if (y > maxY) {
+ maxY = y;
+ maxIndex = i;
+ }
+ avgX = (countX * avgX + point.x) / ++countX;
+ } else {
+ const lastIndex = i - 1;
+ if (!isNullOrUndef(minIndex) && !isNullOrUndef(maxIndex)) {
+ const intermediateIndex1 = Math.min(minIndex, maxIndex);
+ const intermediateIndex2 = Math.max(minIndex, maxIndex);
+ if (intermediateIndex1 !== startIndex && intermediateIndex1 !== lastIndex) {
+ decimated.push({
+ ...data[intermediateIndex1],
+ x: avgX,
+ });
+ }
+ if (intermediateIndex2 !== startIndex && intermediateIndex2 !== lastIndex) {
+ decimated.push({
+ ...data[intermediateIndex2],
+ x: avgX
+ });
+ }
+ }
+ if (i > 0 && lastIndex !== startIndex) {
+ decimated.push(data[lastIndex]);
+ }
+ decimated.push(point);
+ prevX = truncX;
+ countX = 0;
+ minY = maxY = y;
+ minIndex = maxIndex = startIndex = i;
+ }
+ }
+ return decimated;
+}
+function cleanDecimatedDataset(dataset) {
+ if (dataset._decimated) {
+ const data = dataset._data;
+ delete dataset._decimated;
+ delete dataset._data;
+ Object.defineProperty(dataset, 'data', {value: data});
+ }
+}
+function cleanDecimatedData(chart) {
+ chart.data.datasets.forEach((dataset) => {
+ cleanDecimatedDataset(dataset);
+ });
+}
+function getStartAndCountOfVisiblePointsSimplified(meta, points) {
+ const pointCount = points.length;
+ let start = 0;
+ let count;
+ const {iScale} = meta;
+ const {min, max, minDefined, maxDefined} = iScale.getUserBounds();
+ if (minDefined) {
+ start = _limitValue(_lookupByKey(points, iScale.axis, min).lo, 0, pointCount - 1);
+ }
+ if (maxDefined) {
+ count = _limitValue(_lookupByKey(points, iScale.axis, max).hi + 1, start, pointCount) - start;
+ } else {
+ count = pointCount - start;
+ }
+ return {start, count};
+}
+var plugin_decimation = {
+ id: 'decimation',
+ defaults: {
+ algorithm: 'min-max',
+ enabled: false,
+ },
+ beforeElementsUpdate: (chart, args, options) => {
+ if (!options.enabled) {
+ cleanDecimatedData(chart);
+ return;
+ }
+ const availableWidth = chart.width;
+ chart.data.datasets.forEach((dataset, datasetIndex) => {
+ const {_data, indexAxis} = dataset;
+ const meta = chart.getDatasetMeta(datasetIndex);
+ const data = _data || dataset.data;
+ if (resolve([indexAxis, chart.options.indexAxis]) === 'y') {
+ return;
+ }
+ if (meta.type !== 'line') {
+ return;
+ }
+ const xAxis = chart.scales[meta.xAxisID];
+ if (xAxis.type !== 'linear' && xAxis.type !== 'time') {
+ return;
+ }
+ if (chart.options.parsing) {
+ return;
+ }
+ let {start, count} = getStartAndCountOfVisiblePointsSimplified(meta, data);
+ const threshold = options.threshold || 4 * availableWidth;
+ if (count <= threshold) {
+ cleanDecimatedDataset(dataset);
+ return;
+ }
+ if (isNullOrUndef(_data)) {
+ dataset._data = data;
+ delete dataset.data;
+ Object.defineProperty(dataset, 'data', {
+ configurable: true,
+ enumerable: true,
+ get: function() {
+ return this._decimated;
+ },
+ set: function(d) {
+ this._data = d;
+ }
+ });
+ }
+ let decimated;
+ switch (options.algorithm) {
+ case 'lttb':
+ decimated = lttbDecimation(data, start, count, availableWidth, options);
+ break;
+ case 'min-max':
+ decimated = minMaxDecimation(data, start, count, availableWidth);
+ break;
+ default:
+ throw new Error(`Unsupported decimation algorithm '${options.algorithm}'`);
+ }
+ dataset._decimated = decimated;
+ });
+ },
+ destroy(chart) {
+ cleanDecimatedData(chart);
+ }
+};
+
+function getLineByIndex(chart, index) {
+ const meta = chart.getDatasetMeta(index);
+ const visible = meta && chart.isDatasetVisible(index);
+ return visible ? meta.dataset : null;
+}
+function parseFillOption(line) {
+ const options = line.options;
+ const fillOption = options.fill;
+ let fill = valueOrDefault(fillOption && fillOption.target, fillOption);
+ if (fill === undefined) {
+ fill = !!options.backgroundColor;
+ }
+ if (fill === false || fill === null) {
+ return false;
+ }
+ if (fill === true) {
+ return 'origin';
+ }
+ return fill;
+}
+function decodeFill(line, index, count) {
+ const fill = parseFillOption(line);
+ if (isObject(fill)) {
+ return isNaN(fill.value) ? false : fill;
+ }
+ let target = parseFloat(fill);
+ if (isNumberFinite(target) && Math.floor(target) === target) {
+ if (fill[0] === '-' || fill[0] === '+') {
+ target = index + target;
+ }
+ if (target === index || target < 0 || target >= count) {
+ return false;
+ }
+ return target;
+ }
+ return ['origin', 'start', 'end', 'stack', 'shape'].indexOf(fill) >= 0 && fill;
+}
+function computeLinearBoundary(source) {
+ const {scale = {}, fill} = source;
+ let target = null;
+ let horizontal;
+ if (fill === 'start') {
+ target = scale.bottom;
+ } else if (fill === 'end') {
+ target = scale.top;
+ } else if (isObject(fill)) {
+ target = scale.getPixelForValue(fill.value);
+ } else if (scale.getBasePixel) {
+ target = scale.getBasePixel();
+ }
+ if (isNumberFinite(target)) {
+ horizontal = scale.isHorizontal();
+ return {
+ x: horizontal ? target : null,
+ y: horizontal ? null : target
+ };
+ }
+ return null;
+}
+class simpleArc {
+ constructor(opts) {
+ this.x = opts.x;
+ this.y = opts.y;
+ this.radius = opts.radius;
+ }
+ pathSegment(ctx, bounds, opts) {
+ const {x, y, radius} = this;
+ bounds = bounds || {start: 0, end: TAU};
+ ctx.arc(x, y, radius, bounds.end, bounds.start, true);
+ return !opts.bounds;
+ }
+ interpolate(point) {
+ const {x, y, radius} = this;
+ const angle = point.angle;
+ return {
+ x: x + Math.cos(angle) * radius,
+ y: y + Math.sin(angle) * radius,
+ angle
+ };
+ }
+}
+function computeCircularBoundary(source) {
+ const {scale, fill} = source;
+ const options = scale.options;
+ const length = scale.getLabels().length;
+ const target = [];
+ const start = options.reverse ? scale.max : scale.min;
+ const end = options.reverse ? scale.min : scale.max;
+ let i, center, value;
+ if (fill === 'start') {
+ value = start;
+ } else if (fill === 'end') {
+ value = end;
+ } else if (isObject(fill)) {
+ value = fill.value;
+ } else {
+ value = scale.getBaseValue();
+ }
+ if (options.grid.circular) {
+ center = scale.getPointPositionForValue(0, start);
+ return new simpleArc({
+ x: center.x,
+ y: center.y,
+ radius: scale.getDistanceFromCenterForValue(value)
+ });
+ }
+ for (i = 0; i < length; ++i) {
+ target.push(scale.getPointPositionForValue(i, value));
+ }
+ return target;
+}
+function computeBoundary(source) {
+ const scale = source.scale || {};
+ if (scale.getPointPositionForValue) {
+ return computeCircularBoundary(source);
+ }
+ return computeLinearBoundary(source);
+}
+function findSegmentEnd(start, end, points) {
+ for (;end > start; end--) {
+ const point = points[end];
+ if (!isNaN(point.x) && !isNaN(point.y)) {
+ break;
+ }
+ }
+ return end;
+}
+function pointsFromSegments(boundary, line) {
+ const {x = null, y = null} = boundary || {};
+ const linePoints = line.points;
+ const points = [];
+ line.segments.forEach(({start, end}) => {
+ end = findSegmentEnd(start, end, linePoints);
+ const first = linePoints[start];
+ const last = linePoints[end];
+ if (y !== null) {
+ points.push({x: first.x, y});
+ points.push({x: last.x, y});
+ } else if (x !== null) {
+ points.push({x, y: first.y});
+ points.push({x, y: last.y});
+ }
+ });
+ return points;
+}
+function buildStackLine(source) {
+ const {scale, index, line} = source;
+ const points = [];
+ const segments = line.segments;
+ const sourcePoints = line.points;
+ const linesBelow = getLinesBelow(scale, index);
+ linesBelow.push(createBoundaryLine({x: null, y: scale.bottom}, line));
+ for (let i = 0; i < segments.length; i++) {
+ const segment = segments[i];
+ for (let j = segment.start; j <= segment.end; j++) {
+ addPointsBelow(points, sourcePoints[j], linesBelow);
+ }
+ }
+ return new LineElement({points, options: {}});
+}
+function getLinesBelow(scale, index) {
+ const below = [];
+ const metas = scale.getMatchingVisibleMetas('line');
+ for (let i = 0; i < metas.length; i++) {
+ const meta = metas[i];
+ if (meta.index === index) {
+ break;
+ }
+ if (!meta.hidden) {
+ below.unshift(meta.dataset);
+ }
+ }
+ return below;
+}
+function addPointsBelow(points, sourcePoint, linesBelow) {
+ const postponed = [];
+ for (let j = 0; j < linesBelow.length; j++) {
+ const line = linesBelow[j];
+ const {first, last, point} = findPoint(line, sourcePoint, 'x');
+ if (!point || (first && last)) {
+ continue;
+ }
+ if (first) {
+ postponed.unshift(point);
+ } else {
+ points.push(point);
+ if (!last) {
+ break;
+ }
+ }
+ }
+ points.push(...postponed);
+}
+function findPoint(line, sourcePoint, property) {
+ const point = line.interpolate(sourcePoint, property);
+ if (!point) {
+ return {};
+ }
+ const pointValue = point[property];
+ const segments = line.segments;
+ const linePoints = line.points;
+ let first = false;
+ let last = false;
+ for (let i = 0; i < segments.length; i++) {
+ const segment = segments[i];
+ const firstValue = linePoints[segment.start][property];
+ const lastValue = linePoints[segment.end][property];
+ if (pointValue >= firstValue && pointValue <= lastValue) {
+ first = pointValue === firstValue;
+ last = pointValue === lastValue;
+ break;
+ }
+ }
+ return {first, last, point};
+}
+function getTarget(source) {
+ const {chart, fill, line} = source;
+ if (isNumberFinite(fill)) {
+ return getLineByIndex(chart, fill);
+ }
+ if (fill === 'stack') {
+ return buildStackLine(source);
+ }
+ if (fill === 'shape') {
+ return true;
+ }
+ const boundary = computeBoundary(source);
+ if (boundary instanceof simpleArc) {
+ return boundary;
+ }
+ return createBoundaryLine(boundary, line);
+}
+function createBoundaryLine(boundary, line) {
+ let points = [];
+ let _loop = false;
+ if (isArray(boundary)) {
+ _loop = true;
+ points = boundary;
+ } else {
+ points = pointsFromSegments(boundary, line);
+ }
+ return points.length ? new LineElement({
+ points,
+ options: {tension: 0},
+ _loop,
+ _fullLoop: _loop
+ }) : null;
+}
+function resolveTarget(sources, index, propagate) {
+ const source = sources[index];
+ let fill = source.fill;
+ const visited = [index];
+ let target;
+ if (!propagate) {
+ return fill;
+ }
+ while (fill !== false && visited.indexOf(fill) === -1) {
+ if (!isNumberFinite(fill)) {
+ return fill;
+ }
+ target = sources[fill];
+ if (!target) {
+ return false;
+ }
+ if (target.visible) {
+ return fill;
+ }
+ visited.push(fill);
+ fill = target.fill;
+ }
+ return false;
+}
+function _clip(ctx, target, clipY) {
+ ctx.beginPath();
+ target.path(ctx);
+ ctx.lineTo(target.last().x, clipY);
+ ctx.lineTo(target.first().x, clipY);
+ ctx.closePath();
+ ctx.clip();
+}
+function getBounds(property, first, last, loop) {
+ if (loop) {
+ return;
+ }
+ let start = first[property];
+ let end = last[property];
+ if (property === 'angle') {
+ start = _normalizeAngle(start);
+ end = _normalizeAngle(end);
+ }
+ return {property, start, end};
+}
+function _getEdge(a, b, prop, fn) {
+ if (a && b) {
+ return fn(a[prop], b[prop]);
+ }
+ return a ? a[prop] : b ? b[prop] : 0;
+}
+function _segments(line, target, property) {
+ const segments = line.segments;
+ const points = line.points;
+ const tpoints = target.points;
+ const parts = [];
+ for (const segment of segments) {
+ let {start, end} = segment;
+ end = findSegmentEnd(start, end, points);
+ const bounds = getBounds(property, points[start], points[end], segment.loop);
+ if (!target.segments) {
+ parts.push({
+ source: segment,
+ target: bounds,
+ start: points[start],
+ end: points[end]
+ });
+ continue;
+ }
+ const targetSegments = _boundSegments(target, bounds);
+ for (const tgt of targetSegments) {
+ const subBounds = getBounds(property, tpoints[tgt.start], tpoints[tgt.end], tgt.loop);
+ const fillSources = _boundSegment(segment, points, subBounds);
+ for (const fillSource of fillSources) {
+ parts.push({
+ source: fillSource,
+ target: tgt,
+ start: {
+ [property]: _getEdge(bounds, subBounds, 'start', Math.max)
+ },
+ end: {
+ [property]: _getEdge(bounds, subBounds, 'end', Math.min)
+ }
+ });
+ }
+ }
+ }
+ return parts;
+}
+function clipBounds(ctx, scale, bounds) {
+ const {top, bottom} = scale.chart.chartArea;
+ const {property, start, end} = bounds || {};
+ if (property === 'x') {
+ ctx.beginPath();
+ ctx.rect(start, top, end - start, bottom - top);
+ ctx.clip();
+ }
+}
+function interpolatedLineTo(ctx, target, point, property) {
+ const interpolatedPoint = target.interpolate(point, property);
+ if (interpolatedPoint) {
+ ctx.lineTo(interpolatedPoint.x, interpolatedPoint.y);
+ }
+}
+function _fill(ctx, cfg) {
+ const {line, target, property, color, scale} = cfg;
+ const segments = _segments(line, target, property);
+ for (const {source: src, target: tgt, start, end} of segments) {
+ const {style: {backgroundColor = color} = {}} = src;
+ const notShape = target !== true;
+ ctx.save();
+ ctx.fillStyle = backgroundColor;
+ clipBounds(ctx, scale, notShape && getBounds(property, start, end));
+ ctx.beginPath();
+ const lineLoop = !!line.pathSegment(ctx, src);
+ let loop;
+ if (notShape) {
+ if (lineLoop) {
+ ctx.closePath();
+ } else {
+ interpolatedLineTo(ctx, target, end, property);
+ }
+ const targetLoop = !!target.pathSegment(ctx, tgt, {move: lineLoop, reverse: true});
+ loop = lineLoop && targetLoop;
+ if (!loop) {
+ interpolatedLineTo(ctx, target, start, property);
+ }
+ }
+ ctx.closePath();
+ ctx.fill(loop ? 'evenodd' : 'nonzero');
+ ctx.restore();
+ }
+}
+function doFill(ctx, cfg) {
+ const {line, target, above, below, area, scale} = cfg;
+ const property = line._loop ? 'angle' : cfg.axis;
+ ctx.save();
+ if (property === 'x' && below !== above) {
+ _clip(ctx, target, area.top);
+ _fill(ctx, {line, target, color: above, scale, property});
+ ctx.restore();
+ ctx.save();
+ _clip(ctx, target, area.bottom);
+ }
+ _fill(ctx, {line, target, color: below, scale, property});
+ ctx.restore();
+}
+function drawfill(ctx, source, area) {
+ const target = getTarget(source);
+ const {line, scale, axis} = source;
+ const lineOpts = line.options;
+ const fillOption = lineOpts.fill;
+ const color = lineOpts.backgroundColor;
+ const {above = color, below = color} = fillOption || {};
+ if (target && line.points.length) {
+ clipArea(ctx, area);
+ doFill(ctx, {line, target, above, below, area, scale, axis});
+ unclipArea(ctx);
+ }
+}
+var plugin_filler = {
+ id: 'filler',
+ afterDatasetsUpdate(chart, _args, options) {
+ const count = (chart.data.datasets || []).length;
+ const sources = [];
+ let meta, i, line, source;
+ for (i = 0; i < count; ++i) {
+ meta = chart.getDatasetMeta(i);
+ line = meta.dataset;
+ source = null;
+ if (line && line.options && line instanceof LineElement) {
+ source = {
+ visible: chart.isDatasetVisible(i),
+ index: i,
+ fill: decodeFill(line, i, count),
+ chart,
+ axis: meta.controller.options.indexAxis,
+ scale: meta.vScale,
+ line,
+ };
+ }
+ meta.$filler = source;
+ sources.push(source);
+ }
+ for (i = 0; i < count; ++i) {
+ source = sources[i];
+ if (!source || source.fill === false) {
+ continue;
+ }
+ source.fill = resolveTarget(sources, i, options.propagate);
+ }
+ },
+ beforeDraw(chart, _args, options) {
+ const draw = options.drawTime === 'beforeDraw';
+ const metasets = chart.getSortedVisibleDatasetMetas();
+ const area = chart.chartArea;
+ for (let i = metasets.length - 1; i >= 0; --i) {
+ const source = metasets[i].$filler;
+ if (!source) {
+ continue;
+ }
+ source.line.updateControlPoints(area, source.axis);
+ if (draw) {
+ drawfill(chart.ctx, source, area);
+ }
+ }
+ },
+ beforeDatasetsDraw(chart, _args, options) {
+ if (options.drawTime !== 'beforeDatasetsDraw') {
+ return;
+ }
+ const metasets = chart.getSortedVisibleDatasetMetas();
+ for (let i = metasets.length - 1; i >= 0; --i) {
+ const source = metasets[i].$filler;
+ if (source) {
+ drawfill(chart.ctx, source, chart.chartArea);
+ }
+ }
+ },
+ beforeDatasetDraw(chart, args, options) {
+ const source = args.meta.$filler;
+ if (!source || source.fill === false || options.drawTime !== 'beforeDatasetDraw') {
+ return;
+ }
+ drawfill(chart.ctx, source, chart.chartArea);
+ },
+ defaults: {
+ propagate: true,
+ drawTime: 'beforeDatasetDraw'
+ }
+};
+
+const getBoxSize = (labelOpts, fontSize) => {
+ let {boxHeight = fontSize, boxWidth = fontSize} = labelOpts;
+ if (labelOpts.usePointStyle) {
+ boxHeight = Math.min(boxHeight, fontSize);
+ boxWidth = Math.min(boxWidth, fontSize);
+ }
+ return {
+ boxWidth,
+ boxHeight,
+ itemHeight: Math.max(fontSize, boxHeight)
+ };
+};
+const itemsEqual = (a, b) => a !== null && b !== null && a.datasetIndex === b.datasetIndex && a.index === b.index;
+class Legend extends Element {
+ constructor(config) {
+ super();
+ this._added = false;
+ this.legendHitBoxes = [];
+ this._hoveredItem = null;
+ this.doughnutMode = false;
+ this.chart = config.chart;
+ this.options = config.options;
+ this.ctx = config.ctx;
+ this.legendItems = undefined;
+ this.columnSizes = undefined;
+ this.lineWidths = undefined;
+ this.maxHeight = undefined;
+ this.maxWidth = undefined;
+ this.top = undefined;
+ this.bottom = undefined;
+ this.left = undefined;
+ this.right = undefined;
+ this.height = undefined;
+ this.width = undefined;
+ this._margins = undefined;
+ this.position = undefined;
+ this.weight = undefined;
+ this.fullSize = undefined;
+ }
+ update(maxWidth, maxHeight, margins) {
+ this.maxWidth = maxWidth;
+ this.maxHeight = maxHeight;
+ this._margins = margins;
+ this.setDimensions();
+ this.buildLabels();
+ this.fit();
+ }
+ setDimensions() {
+ if (this.isHorizontal()) {
+ this.width = this.maxWidth;
+ this.left = this._margins.left;
+ this.right = this.width;
+ } else {
+ this.height = this.maxHeight;
+ this.top = this._margins.top;
+ this.bottom = this.height;
+ }
+ }
+ buildLabels() {
+ const labelOpts = this.options.labels || {};
+ let legendItems = callback(labelOpts.generateLabels, [this.chart], this) || [];
+ if (labelOpts.filter) {
+ legendItems = legendItems.filter((item) => labelOpts.filter(item, this.chart.data));
+ }
+ if (labelOpts.sort) {
+ legendItems = legendItems.sort((a, b) => labelOpts.sort(a, b, this.chart.data));
+ }
+ if (this.options.reverse) {
+ legendItems.reverse();
+ }
+ this.legendItems = legendItems;
+ }
+ fit() {
+ const {options, ctx} = this;
+ if (!options.display) {
+ this.width = this.height = 0;
+ return;
+ }
+ const labelOpts = options.labels;
+ const labelFont = toFont(labelOpts.font);
+ const fontSize = labelFont.size;
+ const titleHeight = this._computeTitleHeight();
+ const {boxWidth, itemHeight} = getBoxSize(labelOpts, fontSize);
+ let width, height;
+ ctx.font = labelFont.string;
+ if (this.isHorizontal()) {
+ width = this.maxWidth;
+ height = this._fitRows(titleHeight, fontSize, boxWidth, itemHeight) + 10;
+ } else {
+ height = this.maxHeight;
+ width = this._fitCols(titleHeight, fontSize, boxWidth, itemHeight) + 10;
+ }
+ this.width = Math.min(width, options.maxWidth || this.maxWidth);
+ this.height = Math.min(height, options.maxHeight || this.maxHeight);
+ }
+ _fitRows(titleHeight, fontSize, boxWidth, itemHeight) {
+ const {ctx, maxWidth, options: {labels: {padding}}} = this;
+ const hitboxes = this.legendHitBoxes = [];
+ const lineWidths = this.lineWidths = [0];
+ const lineHeight = itemHeight + padding;
+ let totalHeight = titleHeight;
+ ctx.textAlign = 'left';
+ ctx.textBaseline = 'middle';
+ let row = -1;
+ let top = -lineHeight;
+ this.legendItems.forEach((legendItem, i) => {
+ const itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
+ if (i === 0 || lineWidths[lineWidths.length - 1] + itemWidth + 2 * padding > maxWidth) {
+ totalHeight += lineHeight;
+ lineWidths[lineWidths.length - (i > 0 ? 0 : 1)] = 0;
+ top += lineHeight;
+ row++;
+ }
+ hitboxes[i] = {left: 0, top, row, width: itemWidth, height: itemHeight};
+ lineWidths[lineWidths.length - 1] += itemWidth + padding;
+ });
+ return totalHeight;
+ }
+ _fitCols(titleHeight, fontSize, boxWidth, itemHeight) {
+ const {ctx, maxHeight, options: {labels: {padding}}} = this;
+ const hitboxes = this.legendHitBoxes = [];
+ const columnSizes = this.columnSizes = [];
+ const heightLimit = maxHeight - titleHeight;
+ let totalWidth = padding;
+ let currentColWidth = 0;
+ let currentColHeight = 0;
+ let left = 0;
+ let col = 0;
+ this.legendItems.forEach((legendItem, i) => {
+ const itemWidth = boxWidth + (fontSize / 2) + ctx.measureText(legendItem.text).width;
+ if (i > 0 && currentColHeight + itemHeight + 2 * padding > heightLimit) {
+ totalWidth += currentColWidth + padding;
+ columnSizes.push({width: currentColWidth, height: currentColHeight});
+ left += currentColWidth + padding;
+ col++;
+ currentColWidth = currentColHeight = 0;
+ }
+ hitboxes[i] = {left, top: currentColHeight, col, width: itemWidth, height: itemHeight};
+ currentColWidth = Math.max(currentColWidth, itemWidth);
+ currentColHeight += itemHeight + padding;
+ });
+ totalWidth += currentColWidth;
+ columnSizes.push({width: currentColWidth, height: currentColHeight});
+ return totalWidth;
+ }
+ adjustHitBoxes() {
+ if (!this.options.display) {
+ return;
+ }
+ const titleHeight = this._computeTitleHeight();
+ const {legendHitBoxes: hitboxes, options: {align, labels: {padding}, rtl}} = this;
+ const rtlHelper = getRtlAdapter(rtl, this.left, this.width);
+ if (this.isHorizontal()) {
+ let row = 0;
+ let left = _alignStartEnd(align, this.left + padding, this.right - this.lineWidths[row]);
+ for (const hitbox of hitboxes) {
+ if (row !== hitbox.row) {
+ row = hitbox.row;
+ left = _alignStartEnd(align, this.left + padding, this.right - this.lineWidths[row]);
+ }
+ hitbox.top += this.top + titleHeight + padding;
+ hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(left), hitbox.width);
+ left += hitbox.width + padding;
+ }
+ } else {
+ let col = 0;
+ let top = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);
+ for (const hitbox of hitboxes) {
+ if (hitbox.col !== col) {
+ col = hitbox.col;
+ top = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - this.columnSizes[col].height);
+ }
+ hitbox.top = top;
+ hitbox.left += this.left + padding;
+ hitbox.left = rtlHelper.leftForLtr(rtlHelper.x(hitbox.left), hitbox.width);
+ top += hitbox.height + padding;
+ }
+ }
+ }
+ isHorizontal() {
+ return this.options.position === 'top' || this.options.position === 'bottom';
+ }
+ draw() {
+ if (this.options.display) {
+ const ctx = this.ctx;
+ clipArea(ctx, this);
+ this._draw();
+ unclipArea(ctx);
+ }
+ }
+ _draw() {
+ const {options: opts, columnSizes, lineWidths, ctx} = this;
+ const {align, labels: labelOpts} = opts;
+ const defaultColor = defaults.color;
+ const rtlHelper = getRtlAdapter(opts.rtl, this.left, this.width);
+ const labelFont = toFont(labelOpts.font);
+ const {color: fontColor, padding} = labelOpts;
+ const fontSize = labelFont.size;
+ const halfFontSize = fontSize / 2;
+ let cursor;
+ this.drawTitle();
+ ctx.textAlign = rtlHelper.textAlign('left');
+ ctx.textBaseline = 'middle';
+ ctx.lineWidth = 0.5;
+ ctx.font = labelFont.string;
+ const {boxWidth, boxHeight, itemHeight} = getBoxSize(labelOpts, fontSize);
+ const drawLegendBox = function(x, y, legendItem) {
+ if (isNaN(boxWidth) || boxWidth <= 0 || isNaN(boxHeight) || boxHeight < 0) {
+ return;
+ }
+ ctx.save();
+ const lineWidth = valueOrDefault(legendItem.lineWidth, 1);
+ ctx.fillStyle = valueOrDefault(legendItem.fillStyle, defaultColor);
+ ctx.lineCap = valueOrDefault(legendItem.lineCap, 'butt');
+ ctx.lineDashOffset = valueOrDefault(legendItem.lineDashOffset, 0);
+ ctx.lineJoin = valueOrDefault(legendItem.lineJoin, 'miter');
+ ctx.lineWidth = lineWidth;
+ ctx.strokeStyle = valueOrDefault(legendItem.strokeStyle, defaultColor);
+ ctx.setLineDash(valueOrDefault(legendItem.lineDash, []));
+ if (labelOpts.usePointStyle) {
+ const drawOptions = {
+ radius: boxWidth * Math.SQRT2 / 2,
+ pointStyle: legendItem.pointStyle,
+ rotation: legendItem.rotation,
+ borderWidth: lineWidth
+ };
+ const centerX = rtlHelper.xPlus(x, boxWidth / 2);
+ const centerY = y + halfFontSize;
+ drawPoint(ctx, drawOptions, centerX, centerY);
+ } else {
+ const yBoxTop = y + Math.max((fontSize - boxHeight) / 2, 0);
+ const xBoxLeft = rtlHelper.leftForLtr(x, boxWidth);
+ const borderRadius = toTRBLCorners(legendItem.borderRadius);
+ ctx.beginPath();
+ if (Object.values(borderRadius).some(v => v !== 0)) {
+ addRoundedRectPath(ctx, {
+ x: xBoxLeft,
+ y: yBoxTop,
+ w: boxWidth,
+ h: boxHeight,
+ radius: borderRadius,
+ });
+ } else {
+ ctx.rect(xBoxLeft, yBoxTop, boxWidth, boxHeight);
+ }
+ ctx.fill();
+ if (lineWidth !== 0) {
+ ctx.stroke();
+ }
+ }
+ ctx.restore();
+ };
+ const fillText = function(x, y, legendItem) {
+ renderText(ctx, legendItem.text, x, y + (itemHeight / 2), labelFont, {
+ strikethrough: legendItem.hidden,
+ textAlign: rtlHelper.textAlign(legendItem.textAlign)
+ });
+ };
+ const isHorizontal = this.isHorizontal();
+ const titleHeight = this._computeTitleHeight();
+ if (isHorizontal) {
+ cursor = {
+ x: _alignStartEnd(align, this.left + padding, this.right - lineWidths[0]),
+ y: this.top + padding + titleHeight,
+ line: 0
+ };
+ } else {
+ cursor = {
+ x: this.left + padding,
+ y: _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - columnSizes[0].height),
+ line: 0
+ };
+ }
+ overrideTextDirection(this.ctx, opts.textDirection);
+ const lineHeight = itemHeight + padding;
+ this.legendItems.forEach((legendItem, i) => {
+ ctx.strokeStyle = legendItem.fontColor || fontColor;
+ ctx.fillStyle = legendItem.fontColor || fontColor;
+ const textWidth = ctx.measureText(legendItem.text).width;
+ const textAlign = rtlHelper.textAlign(legendItem.textAlign || (legendItem.textAlign = labelOpts.textAlign));
+ const width = boxWidth + halfFontSize + textWidth;
+ let x = cursor.x;
+ let y = cursor.y;
+ rtlHelper.setWidth(this.width);
+ if (isHorizontal) {
+ if (i > 0 && x + width + padding > this.right) {
+ y = cursor.y += lineHeight;
+ cursor.line++;
+ x = cursor.x = _alignStartEnd(align, this.left + padding, this.right - lineWidths[cursor.line]);
+ }
+ } else if (i > 0 && y + lineHeight > this.bottom) {
+ x = cursor.x = x + columnSizes[cursor.line].width + padding;
+ cursor.line++;
+ y = cursor.y = _alignStartEnd(align, this.top + titleHeight + padding, this.bottom - columnSizes[cursor.line].height);
+ }
+ const realX = rtlHelper.x(x);
+ drawLegendBox(realX, y, legendItem);
+ x = _textX(textAlign, x + boxWidth + halfFontSize, isHorizontal ? x + width : this.right, opts.rtl);
+ fillText(rtlHelper.x(x), y, legendItem);
+ if (isHorizontal) {
+ cursor.x += width + padding;
+ } else {
+ cursor.y += lineHeight;
+ }
+ });
+ restoreTextDirection(this.ctx, opts.textDirection);
+ }
+ drawTitle() {
+ const opts = this.options;
+ const titleOpts = opts.title;
+ const titleFont = toFont(titleOpts.font);
+ const titlePadding = toPadding(titleOpts.padding);
+ if (!titleOpts.display) {
+ return;
+ }
+ const rtlHelper = getRtlAdapter(opts.rtl, this.left, this.width);
+ const ctx = this.ctx;
+ const position = titleOpts.position;
+ const halfFontSize = titleFont.size / 2;
+ const topPaddingPlusHalfFontSize = titlePadding.top + halfFontSize;
+ let y;
+ let left = this.left;
+ let maxWidth = this.width;
+ if (this.isHorizontal()) {
+ maxWidth = Math.max(...this.lineWidths);
+ y = this.top + topPaddingPlusHalfFontSize;
+ left = _alignStartEnd(opts.align, left, this.right - maxWidth);
+ } else {
+ const maxHeight = this.columnSizes.reduce((acc, size) => Math.max(acc, size.height), 0);
+ y = topPaddingPlusHalfFontSize + _alignStartEnd(opts.align, this.top, this.bottom - maxHeight - opts.labels.padding - this._computeTitleHeight());
+ }
+ const x = _alignStartEnd(position, left, left + maxWidth);
+ ctx.textAlign = rtlHelper.textAlign(_toLeftRightCenter(position));
+ ctx.textBaseline = 'middle';
+ ctx.strokeStyle = titleOpts.color;
+ ctx.fillStyle = titleOpts.color;
+ ctx.font = titleFont.string;
+ renderText(ctx, titleOpts.text, x, y, titleFont);
+ }
+ _computeTitleHeight() {
+ const titleOpts = this.options.title;
+ const titleFont = toFont(titleOpts.font);
+ const titlePadding = toPadding(titleOpts.padding);
+ return titleOpts.display ? titleFont.lineHeight + titlePadding.height : 0;
+ }
+ _getLegendItemAt(x, y) {
+ let i, hitBox, lh;
+ if (x >= this.left && x <= this.right && y >= this.top && y <= this.bottom) {
+ lh = this.legendHitBoxes;
+ for (i = 0; i < lh.length; ++i) {
+ hitBox = lh[i];
+ if (x >= hitBox.left && x <= hitBox.left + hitBox.width && y >= hitBox.top && y <= hitBox.top + hitBox.height) {
+ return this.legendItems[i];
+ }
+ }
+ }
+ return null;
+ }
+ handleEvent(e) {
+ const opts = this.options;
+ if (!isListened(e.type, opts)) {
+ return;
+ }
+ const hoveredItem = this._getLegendItemAt(e.x, e.y);
+ if (e.type === 'mousemove') {
+ const previous = this._hoveredItem;
+ const sameItem = itemsEqual(previous, hoveredItem);
+ if (previous && !sameItem) {
+ callback(opts.onLeave, [e, previous, this], this);
+ }
+ this._hoveredItem = hoveredItem;
+ if (hoveredItem && !sameItem) {
+ callback(opts.onHover, [e, hoveredItem, this], this);
+ }
+ } else if (hoveredItem) {
+ callback(opts.onClick, [e, hoveredItem, this], this);
+ }
+ }
+}
+function isListened(type, opts) {
+ if (type === 'mousemove' && (opts.onHover || opts.onLeave)) {
+ return true;
+ }
+ if (opts.onClick && (type === 'click' || type === 'mouseup')) {
+ return true;
+ }
+ return false;
+}
+var plugin_legend = {
+ id: 'legend',
+ _element: Legend,
+ start(chart, _args, options) {
+ const legend = chart.legend = new Legend({ctx: chart.ctx, options, chart});
+ layouts.configure(chart, legend, options);
+ layouts.addBox(chart, legend);
+ },
+ stop(chart) {
+ layouts.removeBox(chart, chart.legend);
+ delete chart.legend;
+ },
+ beforeUpdate(chart, _args, options) {
+ const legend = chart.legend;
+ layouts.configure(chart, legend, options);
+ legend.options = options;
+ },
+ afterUpdate(chart) {
+ const legend = chart.legend;
+ legend.buildLabels();
+ legend.adjustHitBoxes();
+ },
+ afterEvent(chart, args) {
+ if (!args.replay) {
+ chart.legend.handleEvent(args.event);
+ }
+ },
+ defaults: {
+ display: true,
+ position: 'top',
+ align: 'center',
+ fullSize: true,
+ reverse: false,
+ weight: 1000,
+ onClick(e, legendItem, legend) {
+ const index = legendItem.datasetIndex;
+ const ci = legend.chart;
+ if (ci.isDatasetVisible(index)) {
+ ci.hide(index);
+ legendItem.hidden = true;
+ } else {
+ ci.show(index);
+ legendItem.hidden = false;
+ }
+ },
+ onHover: null,
+ onLeave: null,
+ labels: {
+ color: (ctx) => ctx.chart.options.color,
+ boxWidth: 40,
+ padding: 10,
+ generateLabels(chart) {
+ const datasets = chart.data.datasets;
+ const {labels: {usePointStyle, pointStyle, textAlign, color}} = chart.legend.options;
+ return chart._getSortedDatasetMetas().map((meta) => {
+ const style = meta.controller.getStyle(usePointStyle ? 0 : undefined);
+ const borderWidth = toPadding(style.borderWidth);
+ return {
+ text: datasets[meta.index].label,
+ fillStyle: style.backgroundColor,
+ fontColor: color,
+ hidden: !meta.visible,
+ lineCap: style.borderCapStyle,
+ lineDash: style.borderDash,
+ lineDashOffset: style.borderDashOffset,
+ lineJoin: style.borderJoinStyle,
+ lineWidth: (borderWidth.width + borderWidth.height) / 4,
+ strokeStyle: style.borderColor,
+ pointStyle: pointStyle || style.pointStyle,
+ rotation: style.rotation,
+ textAlign: textAlign || style.textAlign,
+ borderRadius: 0,
+ datasetIndex: meta.index
+ };
+ }, this);
+ }
+ },
+ title: {
+ color: (ctx) => ctx.chart.options.color,
+ display: false,
+ position: 'center',
+ text: '',
+ }
+ },
+ descriptors: {
+ _scriptable: (name) => !name.startsWith('on'),
+ labels: {
+ _scriptable: (name) => !['generateLabels', 'filter', 'sort'].includes(name),
+ }
+ },
+};
+
+class Title extends Element {
+ constructor(config) {
+ super();
+ this.chart = config.chart;
+ this.options = config.options;
+ this.ctx = config.ctx;
+ this._padding = undefined;
+ this.top = undefined;
+ this.bottom = undefined;
+ this.left = undefined;
+ this.right = undefined;
+ this.width = undefined;
+ this.height = undefined;
+ this.position = undefined;
+ this.weight = undefined;
+ this.fullSize = undefined;
+ }
+ update(maxWidth, maxHeight) {
+ const opts = this.options;
+ this.left = 0;
+ this.top = 0;
+ if (!opts.display) {
+ this.width = this.height = this.right = this.bottom = 0;
+ return;
+ }
+ this.width = this.right = maxWidth;
+ this.height = this.bottom = maxHeight;
+ const lineCount = isArray(opts.text) ? opts.text.length : 1;
+ this._padding = toPadding(opts.padding);
+ const textSize = lineCount * toFont(opts.font).lineHeight + this._padding.height;
+ if (this.isHorizontal()) {
+ this.height = textSize;
+ } else {
+ this.width = textSize;
+ }
+ }
+ isHorizontal() {
+ const pos = this.options.position;
+ return pos === 'top' || pos === 'bottom';
+ }
+ _drawArgs(offset) {
+ const {top, left, bottom, right, options} = this;
+ const align = options.align;
+ let rotation = 0;
+ let maxWidth, titleX, titleY;
+ if (this.isHorizontal()) {
+ titleX = _alignStartEnd(align, left, right);
+ titleY = top + offset;
+ maxWidth = right - left;
+ } else {
+ if (options.position === 'left') {
+ titleX = left + offset;
+ titleY = _alignStartEnd(align, bottom, top);
+ rotation = PI * -0.5;
+ } else {
+ titleX = right - offset;
+ titleY = _alignStartEnd(align, top, bottom);
+ rotation = PI * 0.5;
+ }
+ maxWidth = bottom - top;
+ }
+ return {titleX, titleY, maxWidth, rotation};
+ }
+ draw() {
+ const ctx = this.ctx;
+ const opts = this.options;
+ if (!opts.display) {
+ return;
+ }
+ const fontOpts = toFont(opts.font);
+ const lineHeight = fontOpts.lineHeight;
+ const offset = lineHeight / 2 + this._padding.top;
+ const {titleX, titleY, maxWidth, rotation} = this._drawArgs(offset);
+ renderText(ctx, opts.text, 0, 0, fontOpts, {
+ color: opts.color,
+ maxWidth,
+ rotation,
+ textAlign: _toLeftRightCenter(opts.align),
+ textBaseline: 'middle',
+ translation: [titleX, titleY],
+ });
+ }
+}
+function createTitle(chart, titleOpts) {
+ const title = new Title({
+ ctx: chart.ctx,
+ options: titleOpts,
+ chart
+ });
+ layouts.configure(chart, title, titleOpts);
+ layouts.addBox(chart, title);
+ chart.titleBlock = title;
+}
+var plugin_title = {
+ id: 'title',
+ _element: Title,
+ start(chart, _args, options) {
+ createTitle(chart, options);
+ },
+ stop(chart) {
+ const titleBlock = chart.titleBlock;
+ layouts.removeBox(chart, titleBlock);
+ delete chart.titleBlock;
+ },
+ beforeUpdate(chart, _args, options) {
+ const title = chart.titleBlock;
+ layouts.configure(chart, title, options);
+ title.options = options;
+ },
+ defaults: {
+ align: 'center',
+ display: false,
+ font: {
+ weight: 'bold',
+ },
+ fullSize: true,
+ padding: 10,
+ position: 'top',
+ text: '',
+ weight: 2000
+ },
+ defaultRoutes: {
+ color: 'color'
+ },
+ descriptors: {
+ _scriptable: true,
+ _indexable: false,
+ },
+};
+
+const map = new WeakMap();
+var plugin_subtitle = {
+ id: 'subtitle',
+ start(chart, _args, options) {
+ const title = new Title({
+ ctx: chart.ctx,
+ options,
+ chart
+ });
+ layouts.configure(chart, title, options);
+ layouts.addBox(chart, title);
+ map.set(chart, title);
+ },
+ stop(chart) {
+ layouts.removeBox(chart, map.get(chart));
+ map.delete(chart);
+ },
+ beforeUpdate(chart, _args, options) {
+ const title = map.get(chart);
+ layouts.configure(chart, title, options);
+ title.options = options;
+ },
+ defaults: {
+ align: 'center',
+ display: false,
+ font: {
+ weight: 'normal',
+ },
+ fullSize: true,
+ padding: 0,
+ position: 'top',
+ text: '',
+ weight: 1500
+ },
+ defaultRoutes: {
+ color: 'color'
+ },
+ descriptors: {
+ _scriptable: true,
+ _indexable: false,
+ },
+};
+
+const positioners = {
+ average(items) {
+ if (!items.length) {
+ return false;
+ }
+ let i, len;
+ let x = 0;
+ let y = 0;
+ let count = 0;
+ for (i = 0, len = items.length; i < len; ++i) {
+ const el = items[i].element;
+ if (el && el.hasValue()) {
+ const pos = el.tooltipPosition();
+ x += pos.x;
+ y += pos.y;
+ ++count;
+ }
+ }
+ return {
+ x: x / count,
+ y: y / count
+ };
+ },
+ nearest(items, eventPosition) {
+ if (!items.length) {
+ return false;
+ }
+ let x = eventPosition.x;
+ let y = eventPosition.y;
+ let minDistance = Number.POSITIVE_INFINITY;
+ let i, len, nearestElement;
+ for (i = 0, len = items.length; i < len; ++i) {
+ const el = items[i].element;
+ if (el && el.hasValue()) {
+ const center = el.getCenterPoint();
+ const d = distanceBetweenPoints(eventPosition, center);
+ if (d < minDistance) {
+ minDistance = d;
+ nearestElement = el;
+ }
+ }
+ }
+ if (nearestElement) {
+ const tp = nearestElement.tooltipPosition();
+ x = tp.x;
+ y = tp.y;
+ }
+ return {
+ x,
+ y
+ };
+ }
+};
+function pushOrConcat(base, toPush) {
+ if (toPush) {
+ if (isArray(toPush)) {
+ Array.prototype.push.apply(base, toPush);
+ } else {
+ base.push(toPush);
+ }
+ }
+ return base;
+}
+function splitNewlines(str) {
+ if ((typeof str === 'string' || str instanceof String) && str.indexOf('\n') > -1) {
+ return str.split('\n');
+ }
+ return str;
+}
+function createTooltipItem(chart, item) {
+ const {element, datasetIndex, index} = item;
+ const controller = chart.getDatasetMeta(datasetIndex).controller;
+ const {label, value} = controller.getLabelAndValue(index);
+ return {
+ chart,
+ label,
+ parsed: controller.getParsed(index),
+ raw: chart.data.datasets[datasetIndex].data[index],
+ formattedValue: value,
+ dataset: controller.getDataset(),
+ dataIndex: index,
+ datasetIndex,
+ element
+ };
+}
+function getTooltipSize(tooltip, options) {
+ const ctx = tooltip._chart.ctx;
+ const {body, footer, title} = tooltip;
+ const {boxWidth, boxHeight} = options;
+ const bodyFont = toFont(options.bodyFont);
+ const titleFont = toFont(options.titleFont);
+ const footerFont = toFont(options.footerFont);
+ const titleLineCount = title.length;
+ const footerLineCount = footer.length;
+ const bodyLineItemCount = body.length;
+ const padding = toPadding(options.padding);
+ let height = padding.height;
+ let width = 0;
+ let combinedBodyLength = body.reduce((count, bodyItem) => count + bodyItem.before.length + bodyItem.lines.length + bodyItem.after.length, 0);
+ combinedBodyLength += tooltip.beforeBody.length + tooltip.afterBody.length;
+ if (titleLineCount) {
+ height += titleLineCount * titleFont.lineHeight
+ + (titleLineCount - 1) * options.titleSpacing
+ + options.titleMarginBottom;
+ }
+ if (combinedBodyLength) {
+ const bodyLineHeight = options.displayColors ? Math.max(boxHeight, bodyFont.lineHeight) : bodyFont.lineHeight;
+ height += bodyLineItemCount * bodyLineHeight
+ + (combinedBodyLength - bodyLineItemCount) * bodyFont.lineHeight
+ + (combinedBodyLength - 1) * options.bodySpacing;
+ }
+ if (footerLineCount) {
+ height += options.footerMarginTop
+ + footerLineCount * footerFont.lineHeight
+ + (footerLineCount - 1) * options.footerSpacing;
+ }
+ let widthPadding = 0;
+ const maxLineWidth = function(line) {
+ width = Math.max(width, ctx.measureText(line).width + widthPadding);
+ };
+ ctx.save();
+ ctx.font = titleFont.string;
+ each(tooltip.title, maxLineWidth);
+ ctx.font = bodyFont.string;
+ each(tooltip.beforeBody.concat(tooltip.afterBody), maxLineWidth);
+ widthPadding = options.displayColors ? (boxWidth + 2 + options.boxPadding) : 0;
+ each(body, (bodyItem) => {
+ each(bodyItem.before, maxLineWidth);
+ each(bodyItem.lines, maxLineWidth);
+ each(bodyItem.after, maxLineWidth);
+ });
+ widthPadding = 0;
+ ctx.font = footerFont.string;
+ each(tooltip.footer, maxLineWidth);
+ ctx.restore();
+ width += padding.width;
+ return {width, height};
+}
+function determineYAlign(chart, size) {
+ const {y, height} = size;
+ if (y < height / 2) {
+ return 'top';
+ } else if (y > (chart.height - height / 2)) {
+ return 'bottom';
+ }
+ return 'center';
+}
+function doesNotFitWithAlign(xAlign, chart, options, size) {
+ const {x, width} = size;
+ const caret = options.caretSize + options.caretPadding;
+ if (xAlign === 'left' && x + width + caret > chart.width) {
+ return true;
+ }
+ if (xAlign === 'right' && x - width - caret < 0) {
+ return true;
+ }
+}
+function determineXAlign(chart, options, size, yAlign) {
+ const {x, width} = size;
+ const {width: chartWidth, chartArea: {left, right}} = chart;
+ let xAlign = 'center';
+ if (yAlign === 'center') {
+ xAlign = x <= (left + right) / 2 ? 'left' : 'right';
+ } else if (x <= width / 2) {
+ xAlign = 'left';
+ } else if (x >= chartWidth - width / 2) {
+ xAlign = 'right';
+ }
+ if (doesNotFitWithAlign(xAlign, chart, options, size)) {
+ xAlign = 'center';
+ }
+ return xAlign;
+}
+function determineAlignment(chart, options, size) {
+ const yAlign = options.yAlign || determineYAlign(chart, size);
+ return {
+ xAlign: options.xAlign || determineXAlign(chart, options, size, yAlign),
+ yAlign
+ };
+}
+function alignX(size, xAlign) {
+ let {x, width} = size;
+ if (xAlign === 'right') {
+ x -= width;
+ } else if (xAlign === 'center') {
+ x -= (width / 2);
+ }
+ return x;
+}
+function alignY(size, yAlign, paddingAndSize) {
+ let {y, height} = size;
+ if (yAlign === 'top') {
+ y += paddingAndSize;
+ } else if (yAlign === 'bottom') {
+ y -= height + paddingAndSize;
+ } else {
+ y -= (height / 2);
+ }
+ return y;
+}
+function getBackgroundPoint(options, size, alignment, chart) {
+ const {caretSize, caretPadding, cornerRadius} = options;
+ const {xAlign, yAlign} = alignment;
+ const paddingAndSize = caretSize + caretPadding;
+ const {topLeft, topRight, bottomLeft, bottomRight} = toTRBLCorners(cornerRadius);
+ let x = alignX(size, xAlign);
+ const y = alignY(size, yAlign, paddingAndSize);
+ if (yAlign === 'center') {
+ if (xAlign === 'left') {
+ x += paddingAndSize;
+ } else if (xAlign === 'right') {
+ x -= paddingAndSize;
+ }
+ } else if (xAlign === 'left') {
+ x -= Math.max(topLeft, bottomLeft) + caretPadding;
+ } else if (xAlign === 'right') {
+ x += Math.max(topRight, bottomRight) + caretPadding;
+ }
+ return {
+ x: _limitValue(x, 0, chart.width - size.width),
+ y: _limitValue(y, 0, chart.height - size.height)
+ };
+}
+function getAlignedX(tooltip, align, options) {
+ const padding = toPadding(options.padding);
+ return align === 'center'
+ ? tooltip.x + tooltip.width / 2
+ : align === 'right'
+ ? tooltip.x + tooltip.width - padding.right
+ : tooltip.x + padding.left;
+}
+function getBeforeAfterBodyLines(callback) {
+ return pushOrConcat([], splitNewlines(callback));
+}
+function createTooltipContext(parent, tooltip, tooltipItems) {
+ return createContext(parent, {
+ tooltip,
+ tooltipItems,
+ type: 'tooltip'
+ });
+}
+function overrideCallbacks(callbacks, context) {
+ const override = context && context.dataset && context.dataset.tooltip && context.dataset.tooltip.callbacks;
+ return override ? callbacks.override(override) : callbacks;
+}
+class Tooltip extends Element {
+ constructor(config) {
+ super();
+ this.opacity = 0;
+ this._active = [];
+ this._chart = config._chart;
+ this._eventPosition = undefined;
+ this._size = undefined;
+ this._cachedAnimations = undefined;
+ this._tooltipItems = [];
+ this.$animations = undefined;
+ this.$context = undefined;
+ this.options = config.options;
+ this.dataPoints = undefined;
+ this.title = undefined;
+ this.beforeBody = undefined;
+ this.body = undefined;
+ this.afterBody = undefined;
+ this.footer = undefined;
+ this.xAlign = undefined;
+ this.yAlign = undefined;
+ this.x = undefined;
+ this.y = undefined;
+ this.height = undefined;
+ this.width = undefined;
+ this.caretX = undefined;
+ this.caretY = undefined;
+ this.labelColors = undefined;
+ this.labelPointStyles = undefined;
+ this.labelTextColors = undefined;
+ }
+ initialize(options) {
+ this.options = options;
+ this._cachedAnimations = undefined;
+ this.$context = undefined;
+ }
+ _resolveAnimations() {
+ const cached = this._cachedAnimations;
+ if (cached) {
+ return cached;
+ }
+ const chart = this._chart;
+ const options = this.options.setContext(this.getContext());
+ const opts = options.enabled && chart.options.animation && options.animations;
+ const animations = new Animations(this._chart, opts);
+ if (opts._cacheable) {
+ this._cachedAnimations = Object.freeze(animations);
+ }
+ return animations;
+ }
+ getContext() {
+ return this.$context ||
+ (this.$context = createTooltipContext(this._chart.getContext(), this, this._tooltipItems));
+ }
+ getTitle(context, options) {
+ const {callbacks} = options;
+ const beforeTitle = callbacks.beforeTitle.apply(this, [context]);
+ const title = callbacks.title.apply(this, [context]);
+ const afterTitle = callbacks.afterTitle.apply(this, [context]);
+ let lines = [];
+ lines = pushOrConcat(lines, splitNewlines(beforeTitle));
+ lines = pushOrConcat(lines, splitNewlines(title));
+ lines = pushOrConcat(lines, splitNewlines(afterTitle));
+ return lines;
+ }
+ getBeforeBody(tooltipItems, options) {
+ return getBeforeAfterBodyLines(options.callbacks.beforeBody.apply(this, [tooltipItems]));
+ }
+ getBody(tooltipItems, options) {
+ const {callbacks} = options;
+ const bodyItems = [];
+ each(tooltipItems, (context) => {
+ const bodyItem = {
+ before: [],
+ lines: [],
+ after: []
+ };
+ const scoped = overrideCallbacks(callbacks, context);
+ pushOrConcat(bodyItem.before, splitNewlines(scoped.beforeLabel.call(this, context)));
+ pushOrConcat(bodyItem.lines, scoped.label.call(this, context));
+ pushOrConcat(bodyItem.after, splitNewlines(scoped.afterLabel.call(this, context)));
+ bodyItems.push(bodyItem);
+ });
+ return bodyItems;
+ }
+ getAfterBody(tooltipItems, options) {
+ return getBeforeAfterBodyLines(options.callbacks.afterBody.apply(this, [tooltipItems]));
+ }
+ getFooter(tooltipItems, options) {
+ const {callbacks} = options;
+ const beforeFooter = callbacks.beforeFooter.apply(this, [tooltipItems]);
+ const footer = callbacks.footer.apply(this, [tooltipItems]);
+ const afterFooter = callbacks.afterFooter.apply(this, [tooltipItems]);
+ let lines = [];
+ lines = pushOrConcat(lines, splitNewlines(beforeFooter));
+ lines = pushOrConcat(lines, splitNewlines(footer));
+ lines = pushOrConcat(lines, splitNewlines(afterFooter));
+ return lines;
+ }
+ _createItems(options) {
+ const active = this._active;
+ const data = this._chart.data;
+ const labelColors = [];
+ const labelPointStyles = [];
+ const labelTextColors = [];
+ let tooltipItems = [];
+ let i, len;
+ for (i = 0, len = active.length; i < len; ++i) {
+ tooltipItems.push(createTooltipItem(this._chart, active[i]));
+ }
+ if (options.filter) {
+ tooltipItems = tooltipItems.filter((element, index, array) => options.filter(element, index, array, data));
+ }
+ if (options.itemSort) {
+ tooltipItems = tooltipItems.sort((a, b) => options.itemSort(a, b, data));
+ }
+ each(tooltipItems, (context) => {
+ const scoped = overrideCallbacks(options.callbacks, context);
+ labelColors.push(scoped.labelColor.call(this, context));
+ labelPointStyles.push(scoped.labelPointStyle.call(this, context));
+ labelTextColors.push(scoped.labelTextColor.call(this, context));
+ });
+ this.labelColors = labelColors;
+ this.labelPointStyles = labelPointStyles;
+ this.labelTextColors = labelTextColors;
+ this.dataPoints = tooltipItems;
+ return tooltipItems;
+ }
+ update(changed, replay) {
+ const options = this.options.setContext(this.getContext());
+ const active = this._active;
+ let properties;
+ let tooltipItems = [];
+ if (!active.length) {
+ if (this.opacity !== 0) {
+ properties = {
+ opacity: 0
+ };
+ }
+ } else {
+ const position = positioners[options.position].call(this, active, this._eventPosition);
+ tooltipItems = this._createItems(options);
+ this.title = this.getTitle(tooltipItems, options);
+ this.beforeBody = this.getBeforeBody(tooltipItems, options);
+ this.body = this.getBody(tooltipItems, options);
+ this.afterBody = this.getAfterBody(tooltipItems, options);
+ this.footer = this.getFooter(tooltipItems, options);
+ const size = this._size = getTooltipSize(this, options);
+ const positionAndSize = Object.assign({}, position, size);
+ const alignment = determineAlignment(this._chart, options, positionAndSize);
+ const backgroundPoint = getBackgroundPoint(options, positionAndSize, alignment, this._chart);
+ this.xAlign = alignment.xAlign;
+ this.yAlign = alignment.yAlign;
+ properties = {
+ opacity: 1,
+ x: backgroundPoint.x,
+ y: backgroundPoint.y,
+ width: size.width,
+ height: size.height,
+ caretX: position.x,
+ caretY: position.y
+ };
+ }
+ this._tooltipItems = tooltipItems;
+ this.$context = undefined;
+ if (properties) {
+ this._resolveAnimations().update(this, properties);
+ }
+ if (changed && options.external) {
+ options.external.call(this, {chart: this._chart, tooltip: this, replay});
+ }
+ }
+ drawCaret(tooltipPoint, ctx, size, options) {
+ const caretPosition = this.getCaretPosition(tooltipPoint, size, options);
+ ctx.lineTo(caretPosition.x1, caretPosition.y1);
+ ctx.lineTo(caretPosition.x2, caretPosition.y2);
+ ctx.lineTo(caretPosition.x3, caretPosition.y3);
+ }
+ getCaretPosition(tooltipPoint, size, options) {
+ const {xAlign, yAlign} = this;
+ const {caretSize, cornerRadius} = options;
+ const {topLeft, topRight, bottomLeft, bottomRight} = toTRBLCorners(cornerRadius);
+ const {x: ptX, y: ptY} = tooltipPoint;
+ const {width, height} = size;
+ let x1, x2, x3, y1, y2, y3;
+ if (yAlign === 'center') {
+ y2 = ptY + (height / 2);
+ if (xAlign === 'left') {
+ x1 = ptX;
+ x2 = x1 - caretSize;
+ y1 = y2 + caretSize;
+ y3 = y2 - caretSize;
+ } else {
+ x1 = ptX + width;
+ x2 = x1 + caretSize;
+ y1 = y2 - caretSize;
+ y3 = y2 + caretSize;
+ }
+ x3 = x1;
+ } else {
+ if (xAlign === 'left') {
+ x2 = ptX + Math.max(topLeft, bottomLeft) + (caretSize);
+ } else if (xAlign === 'right') {
+ x2 = ptX + width - Math.max(topRight, bottomRight) - caretSize;
+ } else {
+ x2 = this.caretX;
+ }
+ if (yAlign === 'top') {
+ y1 = ptY;
+ y2 = y1 - caretSize;
+ x1 = x2 - caretSize;
+ x3 = x2 + caretSize;
+ } else {
+ y1 = ptY + height;
+ y2 = y1 + caretSize;
+ x1 = x2 + caretSize;
+ x3 = x2 - caretSize;
+ }
+ y3 = y1;
+ }
+ return {x1, x2, x3, y1, y2, y3};
+ }
+ drawTitle(pt, ctx, options) {
+ const title = this.title;
+ const length = title.length;
+ let titleFont, titleSpacing, i;
+ if (length) {
+ const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
+ pt.x = getAlignedX(this, options.titleAlign, options);
+ ctx.textAlign = rtlHelper.textAlign(options.titleAlign);
+ ctx.textBaseline = 'middle';
+ titleFont = toFont(options.titleFont);
+ titleSpacing = options.titleSpacing;
+ ctx.fillStyle = options.titleColor;
+ ctx.font = titleFont.string;
+ for (i = 0; i < length; ++i) {
+ ctx.fillText(title[i], rtlHelper.x(pt.x), pt.y + titleFont.lineHeight / 2);
+ pt.y += titleFont.lineHeight + titleSpacing;
+ if (i + 1 === length) {
+ pt.y += options.titleMarginBottom - titleSpacing;
+ }
+ }
+ }
+ }
+ _drawColorBox(ctx, pt, i, rtlHelper, options) {
+ const labelColors = this.labelColors[i];
+ const labelPointStyle = this.labelPointStyles[i];
+ const {boxHeight, boxWidth, boxPadding} = options;
+ const bodyFont = toFont(options.bodyFont);
+ const colorX = getAlignedX(this, 'left', options);
+ const rtlColorX = rtlHelper.x(colorX);
+ const yOffSet = boxHeight < bodyFont.lineHeight ? (bodyFont.lineHeight - boxHeight) / 2 : 0;
+ const colorY = pt.y + yOffSet;
+ if (options.usePointStyle) {
+ const drawOptions = {
+ radius: Math.min(boxWidth, boxHeight) / 2,
+ pointStyle: labelPointStyle.pointStyle,
+ rotation: labelPointStyle.rotation,
+ borderWidth: 1
+ };
+ const centerX = rtlHelper.leftForLtr(rtlColorX, boxWidth) + boxWidth / 2;
+ const centerY = colorY + boxHeight / 2;
+ ctx.strokeStyle = options.multiKeyBackground;
+ ctx.fillStyle = options.multiKeyBackground;
+ drawPoint(ctx, drawOptions, centerX, centerY);
+ ctx.strokeStyle = labelColors.borderColor;
+ ctx.fillStyle = labelColors.backgroundColor;
+ drawPoint(ctx, drawOptions, centerX, centerY);
+ } else {
+ ctx.lineWidth = labelColors.borderWidth || 1;
+ ctx.strokeStyle = labelColors.borderColor;
+ ctx.setLineDash(labelColors.borderDash || []);
+ ctx.lineDashOffset = labelColors.borderDashOffset || 0;
+ const outerX = rtlHelper.leftForLtr(rtlColorX, boxWidth - boxPadding);
+ const innerX = rtlHelper.leftForLtr(rtlHelper.xPlus(rtlColorX, 1), boxWidth - boxPadding - 2);
+ const borderRadius = toTRBLCorners(labelColors.borderRadius);
+ if (Object.values(borderRadius).some(v => v !== 0)) {
+ ctx.beginPath();
+ ctx.fillStyle = options.multiKeyBackground;
+ addRoundedRectPath(ctx, {
+ x: outerX,
+ y: colorY,
+ w: boxWidth,
+ h: boxHeight,
+ radius: borderRadius,
+ });
+ ctx.fill();
+ ctx.stroke();
+ ctx.fillStyle = labelColors.backgroundColor;
+ ctx.beginPath();
+ addRoundedRectPath(ctx, {
+ x: innerX,
+ y: colorY + 1,
+ w: boxWidth - 2,
+ h: boxHeight - 2,
+ radius: borderRadius,
+ });
+ ctx.fill();
+ } else {
+ ctx.fillStyle = options.multiKeyBackground;
+ ctx.fillRect(outerX, colorY, boxWidth, boxHeight);
+ ctx.strokeRect(outerX, colorY, boxWidth, boxHeight);
+ ctx.fillStyle = labelColors.backgroundColor;
+ ctx.fillRect(innerX, colorY + 1, boxWidth - 2, boxHeight - 2);
+ }
+ }
+ ctx.fillStyle = this.labelTextColors[i];
+ }
+ drawBody(pt, ctx, options) {
+ const {body} = this;
+ const {bodySpacing, bodyAlign, displayColors, boxHeight, boxWidth, boxPadding} = options;
+ const bodyFont = toFont(options.bodyFont);
+ let bodyLineHeight = bodyFont.lineHeight;
+ let xLinePadding = 0;
+ const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
+ const fillLineOfText = function(line) {
+ ctx.fillText(line, rtlHelper.x(pt.x + xLinePadding), pt.y + bodyLineHeight / 2);
+ pt.y += bodyLineHeight + bodySpacing;
+ };
+ const bodyAlignForCalculation = rtlHelper.textAlign(bodyAlign);
+ let bodyItem, textColor, lines, i, j, ilen, jlen;
+ ctx.textAlign = bodyAlign;
+ ctx.textBaseline = 'middle';
+ ctx.font = bodyFont.string;
+ pt.x = getAlignedX(this, bodyAlignForCalculation, options);
+ ctx.fillStyle = options.bodyColor;
+ each(this.beforeBody, fillLineOfText);
+ xLinePadding = displayColors && bodyAlignForCalculation !== 'right'
+ ? bodyAlign === 'center' ? (boxWidth / 2 + boxPadding) : (boxWidth + 2 + boxPadding)
+ : 0;
+ for (i = 0, ilen = body.length; i < ilen; ++i) {
+ bodyItem = body[i];
+ textColor = this.labelTextColors[i];
+ ctx.fillStyle = textColor;
+ each(bodyItem.before, fillLineOfText);
+ lines = bodyItem.lines;
+ if (displayColors && lines.length) {
+ this._drawColorBox(ctx, pt, i, rtlHelper, options);
+ bodyLineHeight = Math.max(bodyFont.lineHeight, boxHeight);
+ }
+ for (j = 0, jlen = lines.length; j < jlen; ++j) {
+ fillLineOfText(lines[j]);
+ bodyLineHeight = bodyFont.lineHeight;
+ }
+ each(bodyItem.after, fillLineOfText);
+ }
+ xLinePadding = 0;
+ bodyLineHeight = bodyFont.lineHeight;
+ each(this.afterBody, fillLineOfText);
+ pt.y -= bodySpacing;
+ }
+ drawFooter(pt, ctx, options) {
+ const footer = this.footer;
+ const length = footer.length;
+ let footerFont, i;
+ if (length) {
+ const rtlHelper = getRtlAdapter(options.rtl, this.x, this.width);
+ pt.x = getAlignedX(this, options.footerAlign, options);
+ pt.y += options.footerMarginTop;
+ ctx.textAlign = rtlHelper.textAlign(options.footerAlign);
+ ctx.textBaseline = 'middle';
+ footerFont = toFont(options.footerFont);
+ ctx.fillStyle = options.footerColor;
+ ctx.font = footerFont.string;
+ for (i = 0; i < length; ++i) {
+ ctx.fillText(footer[i], rtlHelper.x(pt.x), pt.y + footerFont.lineHeight / 2);
+ pt.y += footerFont.lineHeight + options.footerSpacing;
+ }
+ }
+ }
+ drawBackground(pt, ctx, tooltipSize, options) {
+ const {xAlign, yAlign} = this;
+ const {x, y} = pt;
+ const {width, height} = tooltipSize;
+ const {topLeft, topRight, bottomLeft, bottomRight} = toTRBLCorners(options.cornerRadius);
+ ctx.fillStyle = options.backgroundColor;
+ ctx.strokeStyle = options.borderColor;
+ ctx.lineWidth = options.borderWidth;
+ ctx.beginPath();
+ ctx.moveTo(x + topLeft, y);
+ if (yAlign === 'top') {
+ this.drawCaret(pt, ctx, tooltipSize, options);
+ }
+ ctx.lineTo(x + width - topRight, y);
+ ctx.quadraticCurveTo(x + width, y, x + width, y + topRight);
+ if (yAlign === 'center' && xAlign === 'right') {
+ this.drawCaret(pt, ctx, tooltipSize, options);
+ }
+ ctx.lineTo(x + width, y + height - bottomRight);
+ ctx.quadraticCurveTo(x + width, y + height, x + width - bottomRight, y + height);
+ if (yAlign === 'bottom') {
+ this.drawCaret(pt, ctx, tooltipSize, options);
+ }
+ ctx.lineTo(x + bottomLeft, y + height);
+ ctx.quadraticCurveTo(x, y + height, x, y + height - bottomLeft);
+ if (yAlign === 'center' && xAlign === 'left') {
+ this.drawCaret(pt, ctx, tooltipSize, options);
+ }
+ ctx.lineTo(x, y + topLeft);
+ ctx.quadraticCurveTo(x, y, x + topLeft, y);
+ ctx.closePath();
+ ctx.fill();
+ if (options.borderWidth > 0) {
+ ctx.stroke();
+ }
+ }
+ _updateAnimationTarget(options) {
+ const chart = this._chart;
+ const anims = this.$animations;
+ const animX = anims && anims.x;
+ const animY = anims && anims.y;
+ if (animX || animY) {
+ const position = positioners[options.position].call(this, this._active, this._eventPosition);
+ if (!position) {
+ return;
+ }
+ const size = this._size = getTooltipSize(this, options);
+ const positionAndSize = Object.assign({}, position, this._size);
+ const alignment = determineAlignment(chart, options, positionAndSize);
+ const point = getBackgroundPoint(options, positionAndSize, alignment, chart);
+ if (animX._to !== point.x || animY._to !== point.y) {
+ this.xAlign = alignment.xAlign;
+ this.yAlign = alignment.yAlign;
+ this.width = size.width;
+ this.height = size.height;
+ this.caretX = position.x;
+ this.caretY = position.y;
+ this._resolveAnimations().update(this, point);
+ }
+ }
+ }
+ draw(ctx) {
+ const options = this.options.setContext(this.getContext());
+ let opacity = this.opacity;
+ if (!opacity) {
+ return;
+ }
+ this._updateAnimationTarget(options);
+ const tooltipSize = {
+ width: this.width,
+ height: this.height
+ };
+ const pt = {
+ x: this.x,
+ y: this.y
+ };
+ opacity = Math.abs(opacity) < 1e-3 ? 0 : opacity;
+ const padding = toPadding(options.padding);
+ const hasTooltipContent = this.title.length || this.beforeBody.length || this.body.length || this.afterBody.length || this.footer.length;
+ if (options.enabled && hasTooltipContent) {
+ ctx.save();
+ ctx.globalAlpha = opacity;
+ this.drawBackground(pt, ctx, tooltipSize, options);
+ overrideTextDirection(ctx, options.textDirection);
+ pt.y += padding.top;
+ this.drawTitle(pt, ctx, options);
+ this.drawBody(pt, ctx, options);
+ this.drawFooter(pt, ctx, options);
+ restoreTextDirection(ctx, options.textDirection);
+ ctx.restore();
+ }
+ }
+ getActiveElements() {
+ return this._active || [];
+ }
+ setActiveElements(activeElements, eventPosition) {
+ const lastActive = this._active;
+ const active = activeElements.map(({datasetIndex, index}) => {
+ const meta = this._chart.getDatasetMeta(datasetIndex);
+ if (!meta) {
+ throw new Error('Cannot find a dataset at index ' + datasetIndex);
+ }
+ return {
+ datasetIndex,
+ element: meta.data[index],
+ index,
+ };
+ });
+ const changed = !_elementsEqual(lastActive, active);
+ const positionChanged = this._positionChanged(active, eventPosition);
+ if (changed || positionChanged) {
+ this._active = active;
+ this._eventPosition = eventPosition;
+ this.update(true);
+ }
+ }
+ handleEvent(e, replay) {
+ const options = this.options;
+ const lastActive = this._active || [];
+ let changed = false;
+ let active = [];
+ if (e.type !== 'mouseout') {
+ active = this._chart.getElementsAtEventForMode(e, options.mode, options, replay);
+ if (options.reverse) {
+ active.reverse();
+ }
+ }
+ const positionChanged = this._positionChanged(active, e);
+ changed = replay || !_elementsEqual(active, lastActive) || positionChanged;
+ if (changed) {
+ this._active = active;
+ if (options.enabled || options.external) {
+ this._eventPosition = {
+ x: e.x,
+ y: e.y
+ };
+ this.update(true, replay);
+ }
+ }
+ return changed;
+ }
+ _positionChanged(active, e) {
+ const {caretX, caretY, options} = this;
+ const position = positioners[options.position].call(this, active, e);
+ return position !== false && (caretX !== position.x || caretY !== position.y);
+ }
+}
+Tooltip.positioners = positioners;
+var plugin_tooltip = {
+ id: 'tooltip',
+ _element: Tooltip,
+ positioners,
+ afterInit(chart, _args, options) {
+ if (options) {
+ chart.tooltip = new Tooltip({_chart: chart, options});
+ }
+ },
+ beforeUpdate(chart, _args, options) {
+ if (chart.tooltip) {
+ chart.tooltip.initialize(options);
+ }
+ },
+ reset(chart, _args, options) {
+ if (chart.tooltip) {
+ chart.tooltip.initialize(options);
+ }
+ },
+ afterDraw(chart) {
+ const tooltip = chart.tooltip;
+ const args = {
+ tooltip
+ };
+ if (chart.notifyPlugins('beforeTooltipDraw', args) === false) {
+ return;
+ }
+ if (tooltip) {
+ tooltip.draw(chart.ctx);
+ }
+ chart.notifyPlugins('afterTooltipDraw', args);
+ },
+ afterEvent(chart, args) {
+ if (chart.tooltip) {
+ const useFinalPosition = args.replay;
+ if (chart.tooltip.handleEvent(args.event, useFinalPosition)) {
+ args.changed = true;
+ }
+ }
+ },
+ defaults: {
+ enabled: true,
+ external: null,
+ position: 'average',
+ backgroundColor: 'rgba(0,0,0,0.8)',
+ titleColor: '#fff',
+ titleFont: {
+ weight: 'bold',
+ },
+ titleSpacing: 2,
+ titleMarginBottom: 6,
+ titleAlign: 'left',
+ bodyColor: '#fff',
+ bodySpacing: 2,
+ bodyFont: {
+ },
+ bodyAlign: 'left',
+ footerColor: '#fff',
+ footerSpacing: 2,
+ footerMarginTop: 6,
+ footerFont: {
+ weight: 'bold',
+ },
+ footerAlign: 'left',
+ padding: 6,
+ caretPadding: 2,
+ caretSize: 5,
+ cornerRadius: 6,
+ boxHeight: (ctx, opts) => opts.bodyFont.size,
+ boxWidth: (ctx, opts) => opts.bodyFont.size,
+ multiKeyBackground: '#fff',
+ displayColors: true,
+ boxPadding: 0,
+ borderColor: 'rgba(0,0,0,0)',
+ borderWidth: 0,
+ animation: {
+ duration: 400,
+ easing: 'easeOutQuart',
+ },
+ animations: {
+ numbers: {
+ type: 'number',
+ properties: ['x', 'y', 'width', 'height', 'caretX', 'caretY'],
+ },
+ opacity: {
+ easing: 'linear',
+ duration: 200
+ }
+ },
+ callbacks: {
+ beforeTitle: noop,
+ title(tooltipItems) {
+ if (tooltipItems.length > 0) {
+ const item = tooltipItems[0];
+ const labels = item.chart.data.labels;
+ const labelCount = labels ? labels.length : 0;
+ if (this && this.options && this.options.mode === 'dataset') {
+ return item.dataset.label || '';
+ } else if (item.label) {
+ return item.label;
+ } else if (labelCount > 0 && item.dataIndex < labelCount) {
+ return labels[item.dataIndex];
+ }
+ }
+ return '';
+ },
+ afterTitle: noop,
+ beforeBody: noop,
+ beforeLabel: noop,
+ label(tooltipItem) {
+ if (this && this.options && this.options.mode === 'dataset') {
+ return tooltipItem.label + ': ' + tooltipItem.formattedValue || tooltipItem.formattedValue;
+ }
+ let label = tooltipItem.dataset.label || '';
+ if (label) {
+ label += ': ';
+ }
+ const value = tooltipItem.formattedValue;
+ if (!isNullOrUndef(value)) {
+ label += value;
+ }
+ return label;
+ },
+ labelColor(tooltipItem) {
+ const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);
+ const options = meta.controller.getStyle(tooltipItem.dataIndex);
+ return {
+ borderColor: options.borderColor,
+ backgroundColor: options.backgroundColor,
+ borderWidth: options.borderWidth,
+ borderDash: options.borderDash,
+ borderDashOffset: options.borderDashOffset,
+ borderRadius: 0,
+ };
+ },
+ labelTextColor() {
+ return this.options.bodyColor;
+ },
+ labelPointStyle(tooltipItem) {
+ const meta = tooltipItem.chart.getDatasetMeta(tooltipItem.datasetIndex);
+ const options = meta.controller.getStyle(tooltipItem.dataIndex);
+ return {
+ pointStyle: options.pointStyle,
+ rotation: options.rotation,
+ };
+ },
+ afterLabel: noop,
+ afterBody: noop,
+ beforeFooter: noop,
+ footer: noop,
+ afterFooter: noop
+ }
+ },
+ defaultRoutes: {
+ bodyFont: 'font',
+ footerFont: 'font',
+ titleFont: 'font'
+ },
+ descriptors: {
+ _scriptable: (name) => name !== 'filter' && name !== 'itemSort' && name !== 'external',
+ _indexable: false,
+ callbacks: {
+ _scriptable: false,
+ _indexable: false,
+ },
+ animation: {
+ _fallback: false
+ },
+ animations: {
+ _fallback: 'animation'
+ }
+ },
+ additionalOptionScopes: ['interaction']
+};
+
+var plugins = /*#__PURE__*/Object.freeze({
+__proto__: null,
+Decimation: plugin_decimation,
+Filler: plugin_filler,
+Legend: plugin_legend,
+SubTitle: plugin_subtitle,
+Title: plugin_title,
+Tooltip: plugin_tooltip
+});
+
+const addIfString = (labels, raw, index) => typeof raw === 'string'
+ ? labels.push(raw) - 1
+ : isNaN(raw) ? null : index;
+function findOrAddLabel(labels, raw, index) {
+ const first = labels.indexOf(raw);
+ if (first === -1) {
+ return addIfString(labels, raw, index);
+ }
+ const last = labels.lastIndexOf(raw);
+ return first !== last ? index : first;
+}
+const validIndex = (index, max) => index === null ? null : _limitValue(Math.round(index), 0, max);
+class CategoryScale extends Scale {
+ constructor(cfg) {
+ super(cfg);
+ this._startValue = undefined;
+ this._valueRange = 0;
+ }
+ parse(raw, index) {
+ if (isNullOrUndef(raw)) {
+ return null;
+ }
+ const labels = this.getLabels();
+ index = isFinite(index) && labels[index] === raw ? index
+ : findOrAddLabel(labels, raw, valueOrDefault(index, raw));
+ return validIndex(index, labels.length - 1);
+ }
+ determineDataLimits() {
+ const {minDefined, maxDefined} = this.getUserBounds();
+ let {min, max} = this.getMinMax(true);
+ if (this.options.bounds === 'ticks') {
+ if (!minDefined) {
+ min = 0;
+ }
+ if (!maxDefined) {
+ max = this.getLabels().length - 1;
+ }
+ }
+ this.min = min;
+ this.max = max;
+ }
+ buildTicks() {
+ const min = this.min;
+ const max = this.max;
+ const offset = this.options.offset;
+ const ticks = [];
+ let labels = this.getLabels();
+ labels = (min === 0 && max === labels.length - 1) ? labels : labels.slice(min, max + 1);
+ this._valueRange = Math.max(labels.length - (offset ? 0 : 1), 1);
+ this._startValue = this.min - (offset ? 0.5 : 0);
+ for (let value = min; value <= max; value++) {
+ ticks.push({value});
+ }
+ return ticks;
+ }
+ getLabelForValue(value) {
+ const labels = this.getLabels();
+ if (value >= 0 && value < labels.length) {
+ return labels[value];
+ }
+ return value;
+ }
+ configure() {
+ super.configure();
+ if (!this.isHorizontal()) {
+ this._reversePixels = !this._reversePixels;
+ }
+ }
+ getPixelForValue(value) {
+ if (typeof value !== 'number') {
+ value = this.parse(value);
+ }
+ return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);
+ }
+ getPixelForTick(index) {
+ const ticks = this.ticks;
+ if (index < 0 || index > ticks.length - 1) {
+ return null;
+ }
+ return this.getPixelForValue(ticks[index].value);
+ }
+ getValueForPixel(pixel) {
+ return Math.round(this._startValue + this.getDecimalForPixel(pixel) * this._valueRange);
+ }
+ getBasePixel() {
+ return this.bottom;
+ }
+}
+CategoryScale.id = 'category';
+CategoryScale.defaults = {
+ ticks: {
+ callback: CategoryScale.prototype.getLabelForValue
+ }
+};
+
+function generateTicks$1(generationOptions, dataRange) {
+ const ticks = [];
+ const MIN_SPACING = 1e-14;
+ const {bounds, step, min, max, precision, count, maxTicks, maxDigits, includeBounds} = generationOptions;
+ const unit = step || 1;
+ const maxSpaces = maxTicks - 1;
+ const {min: rmin, max: rmax} = dataRange;
+ const minDefined = !isNullOrUndef(min);
+ const maxDefined = !isNullOrUndef(max);
+ const countDefined = !isNullOrUndef(count);
+ const minSpacing = (rmax - rmin) / (maxDigits + 1);
+ let spacing = niceNum((rmax - rmin) / maxSpaces / unit) * unit;
+ let factor, niceMin, niceMax, numSpaces;
+ if (spacing < MIN_SPACING && !minDefined && !maxDefined) {
+ return [{value: rmin}, {value: rmax}];
+ }
+ numSpaces = Math.ceil(rmax / spacing) - Math.floor(rmin / spacing);
+ if (numSpaces > maxSpaces) {
+ spacing = niceNum(numSpaces * spacing / maxSpaces / unit) * unit;
+ }
+ if (!isNullOrUndef(precision)) {
+ factor = Math.pow(10, precision);
+ spacing = Math.ceil(spacing * factor) / factor;
+ }
+ if (bounds === 'ticks') {
+ niceMin = Math.floor(rmin / spacing) * spacing;
+ niceMax = Math.ceil(rmax / spacing) * spacing;
+ } else {
+ niceMin = rmin;
+ niceMax = rmax;
+ }
+ if (minDefined && maxDefined && step && almostWhole((max - min) / step, spacing / 1000)) {
+ numSpaces = Math.round(Math.min((max - min) / spacing, maxTicks));
+ spacing = (max - min) / numSpaces;
+ niceMin = min;
+ niceMax = max;
+ } else if (countDefined) {
+ niceMin = minDefined ? min : niceMin;
+ niceMax = maxDefined ? max : niceMax;
+ numSpaces = count - 1;
+ spacing = (niceMax - niceMin) / numSpaces;
+ } else {
+ numSpaces = (niceMax - niceMin) / spacing;
+ if (almostEquals(numSpaces, Math.round(numSpaces), spacing / 1000)) {
+ numSpaces = Math.round(numSpaces);
+ } else {
+ numSpaces = Math.ceil(numSpaces);
+ }
+ }
+ const decimalPlaces = Math.max(
+ _decimalPlaces(spacing),
+ _decimalPlaces(niceMin)
+ );
+ factor = Math.pow(10, isNullOrUndef(precision) ? decimalPlaces : precision);
+ niceMin = Math.round(niceMin * factor) / factor;
+ niceMax = Math.round(niceMax * factor) / factor;
+ let j = 0;
+ if (minDefined) {
+ if (includeBounds && niceMin !== min) {
+ ticks.push({value: min});
+ if (niceMin < min) {
+ j++;
+ }
+ if (almostEquals(Math.round((niceMin + j * spacing) * factor) / factor, min, relativeLabelSize(min, minSpacing, generationOptions))) {
+ j++;
+ }
+ } else if (niceMin < min) {
+ j++;
+ }
+ }
+ for (; j < numSpaces; ++j) {
+ ticks.push({value: Math.round((niceMin + j * spacing) * factor) / factor});
+ }
+ if (maxDefined && includeBounds && niceMax !== max) {
+ if (ticks.length && almostEquals(ticks[ticks.length - 1].value, max, relativeLabelSize(max, minSpacing, generationOptions))) {
+ ticks[ticks.length - 1].value = max;
+ } else {
+ ticks.push({value: max});
+ }
+ } else if (!maxDefined || niceMax === max) {
+ ticks.push({value: niceMax});
+ }
+ return ticks;
+}
+function relativeLabelSize(value, minSpacing, {horizontal, minRotation}) {
+ const rad = toRadians(minRotation);
+ const ratio = (horizontal ? Math.sin(rad) : Math.cos(rad)) || 0.001;
+ const length = 0.75 * minSpacing * ('' + value).length;
+ return Math.min(minSpacing / ratio, length);
+}
+class LinearScaleBase extends Scale {
+ constructor(cfg) {
+ super(cfg);
+ this.start = undefined;
+ this.end = undefined;
+ this._startValue = undefined;
+ this._endValue = undefined;
+ this._valueRange = 0;
+ }
+ parse(raw, index) {
+ if (isNullOrUndef(raw)) {
+ return null;
+ }
+ if ((typeof raw === 'number' || raw instanceof Number) && !isFinite(+raw)) {
+ return null;
+ }
+ return +raw;
+ }
+ handleTickRangeOptions() {
+ const {beginAtZero} = this.options;
+ const {minDefined, maxDefined} = this.getUserBounds();
+ let {min, max} = this;
+ const setMin = v => (min = minDefined ? min : v);
+ const setMax = v => (max = maxDefined ? max : v);
+ if (beginAtZero) {
+ const minSign = sign(min);
+ const maxSign = sign(max);
+ if (minSign < 0 && maxSign < 0) {
+ setMax(0);
+ } else if (minSign > 0 && maxSign > 0) {
+ setMin(0);
+ }
+ }
+ if (min === max) {
+ let offset = 1;
+ if (max >= Number.MAX_SAFE_INTEGER || min <= Number.MIN_SAFE_INTEGER) {
+ offset = Math.abs(max * 0.05);
+ }
+ setMax(max + offset);
+ if (!beginAtZero) {
+ setMin(min - offset);
+ }
+ }
+ this.min = min;
+ this.max = max;
+ }
+ getTickLimit() {
+ const tickOpts = this.options.ticks;
+ let {maxTicksLimit, stepSize} = tickOpts;
+ let maxTicks;
+ if (stepSize) {
+ maxTicks = Math.ceil(this.max / stepSize) - Math.floor(this.min / stepSize) + 1;
+ if (maxTicks > 1000) {
+ console.warn(`scales.${this.id}.ticks.stepSize: ${stepSize} would result generating up to ${maxTicks} ticks. Limiting to 1000.`);
+ maxTicks = 1000;
+ }
+ } else {
+ maxTicks = this.computeTickLimit();
+ maxTicksLimit = maxTicksLimit || 11;
+ }
+ if (maxTicksLimit) {
+ maxTicks = Math.min(maxTicksLimit, maxTicks);
+ }
+ return maxTicks;
+ }
+ computeTickLimit() {
+ return Number.POSITIVE_INFINITY;
+ }
+ buildTicks() {
+ const opts = this.options;
+ const tickOpts = opts.ticks;
+ let maxTicks = this.getTickLimit();
+ maxTicks = Math.max(2, maxTicks);
+ const numericGeneratorOptions = {
+ maxTicks,
+ bounds: opts.bounds,
+ min: opts.min,
+ max: opts.max,
+ precision: tickOpts.precision,
+ step: tickOpts.stepSize,
+ count: tickOpts.count,
+ maxDigits: this._maxDigits(),
+ horizontal: this.isHorizontal(),
+ minRotation: tickOpts.minRotation || 0,
+ includeBounds: tickOpts.includeBounds !== false
+ };
+ const dataRange = this._range || this;
+ const ticks = generateTicks$1(numericGeneratorOptions, dataRange);
+ if (opts.bounds === 'ticks') {
+ _setMinAndMaxByKey(ticks, this, 'value');
+ }
+ if (opts.reverse) {
+ ticks.reverse();
+ this.start = this.max;
+ this.end = this.min;
+ } else {
+ this.start = this.min;
+ this.end = this.max;
+ }
+ return ticks;
+ }
+ configure() {
+ const ticks = this.ticks;
+ let start = this.min;
+ let end = this.max;
+ super.configure();
+ if (this.options.offset && ticks.length) {
+ const offset = (end - start) / Math.max(ticks.length - 1, 1) / 2;
+ start -= offset;
+ end += offset;
+ }
+ this._startValue = start;
+ this._endValue = end;
+ this._valueRange = end - start;
+ }
+ getLabelForValue(value) {
+ return formatNumber(value, this.chart.options.locale);
+ }
+}
+
+class LinearScale extends LinearScaleBase {
+ determineDataLimits() {
+ const {min, max} = this.getMinMax(true);
+ this.min = isNumberFinite(min) ? min : 0;
+ this.max = isNumberFinite(max) ? max : 1;
+ this.handleTickRangeOptions();
+ }
+ computeTickLimit() {
+ const horizontal = this.isHorizontal();
+ const length = horizontal ? this.width : this.height;
+ const minRotation = toRadians(this.options.ticks.minRotation);
+ const ratio = (horizontal ? Math.sin(minRotation) : Math.cos(minRotation)) || 0.001;
+ const tickFont = this._resolveTickFontOptions(0);
+ return Math.ceil(length / Math.min(40, tickFont.lineHeight / ratio));
+ }
+ getPixelForValue(value) {
+ return value === null ? NaN : this.getPixelForDecimal((value - this._startValue) / this._valueRange);
+ }
+ getValueForPixel(pixel) {
+ return this._startValue + this.getDecimalForPixel(pixel) * this._valueRange;
+ }
+}
+LinearScale.id = 'linear';
+LinearScale.defaults = {
+ ticks: {
+ callback: Ticks.formatters.numeric
+ }
+};
+
+function isMajor(tickVal) {
+ const remain = tickVal / (Math.pow(10, Math.floor(log10(tickVal))));
+ return remain === 1;
+}
+function generateTicks(generationOptions, dataRange) {
+ const endExp = Math.floor(log10(dataRange.max));
+ const endSignificand = Math.ceil(dataRange.max / Math.pow(10, endExp));
+ const ticks = [];
+ let tickVal = finiteOrDefault(generationOptions.min, Math.pow(10, Math.floor(log10(dataRange.min))));
+ let exp = Math.floor(log10(tickVal));
+ let significand = Math.floor(tickVal / Math.pow(10, exp));
+ let precision = exp < 0 ? Math.pow(10, Math.abs(exp)) : 1;
+ do {
+ ticks.push({value: tickVal, major: isMajor(tickVal)});
+ ++significand;
+ if (significand === 10) {
+ significand = 1;
+ ++exp;
+ precision = exp >= 0 ? 1 : precision;
+ }
+ tickVal = Math.round(significand * Math.pow(10, exp) * precision) / precision;
+ } while (exp < endExp || (exp === endExp && significand < endSignificand));
+ const lastTick = finiteOrDefault(generationOptions.max, tickVal);
+ ticks.push({value: lastTick, major: isMajor(tickVal)});
+ return ticks;
+}
+class LogarithmicScale extends Scale {
+ constructor(cfg) {
+ super(cfg);
+ this.start = undefined;
+ this.end = undefined;
+ this._startValue = undefined;
+ this._valueRange = 0;
+ }
+ parse(raw, index) {
+ const value = LinearScaleBase.prototype.parse.apply(this, [raw, index]);
+ if (value === 0) {
+ this._zero = true;
+ return undefined;
+ }
+ return isNumberFinite(value) && value > 0 ? value : null;
+ }
+ determineDataLimits() {
+ const {min, max} = this.getMinMax(true);
+ this.min = isNumberFinite(min) ? Math.max(0, min) : null;
+ this.max = isNumberFinite(max) ? Math.max(0, max) : null;
+ if (this.options.beginAtZero) {
+ this._zero = true;
+ }
+ this.handleTickRangeOptions();
+ }
+ handleTickRangeOptions() {
+ const {minDefined, maxDefined} = this.getUserBounds();
+ let min = this.min;
+ let max = this.max;
+ const setMin = v => (min = minDefined ? min : v);
+ const setMax = v => (max = maxDefined ? max : v);
+ const exp = (v, m) => Math.pow(10, Math.floor(log10(v)) + m);
+ if (min === max) {
+ if (min <= 0) {
+ setMin(1);
+ setMax(10);
+ } else {
+ setMin(exp(min, -1));
+ setMax(exp(max, +1));
+ }
+ }
+ if (min <= 0) {
+ setMin(exp(max, -1));
+ }
+ if (max <= 0) {
+ setMax(exp(min, +1));
+ }
+ if (this._zero && this.min !== this._suggestedMin && min === exp(this.min, 0)) {
+ setMin(exp(min, -1));
+ }
+ this.min = min;
+ this.max = max;
+ }
+ buildTicks() {
+ const opts = this.options;
+ const generationOptions = {
+ min: this._userMin,
+ max: this._userMax
+ };
+ const ticks = generateTicks(generationOptions, this);
+ if (opts.bounds === 'ticks') {
+ _setMinAndMaxByKey(ticks, this, 'value');
+ }
+ if (opts.reverse) {
+ ticks.reverse();
+ this.start = this.max;
+ this.end = this.min;
+ } else {
+ this.start = this.min;
+ this.end = this.max;
+ }
+ return ticks;
+ }
+ getLabelForValue(value) {
+ return value === undefined ? '0' : formatNumber(value, this.chart.options.locale);
+ }
+ configure() {
+ const start = this.min;
+ super.configure();
+ this._startValue = log10(start);
+ this._valueRange = log10(this.max) - log10(start);
+ }
+ getPixelForValue(value) {
+ if (value === undefined || value === 0) {
+ value = this.min;
+ }
+ if (value === null || isNaN(value)) {
+ return NaN;
+ }
+ return this.getPixelForDecimal(value === this.min
+ ? 0
+ : (log10(value) - this._startValue) / this._valueRange);
+ }
+ getValueForPixel(pixel) {
+ const decimal = this.getDecimalForPixel(pixel);
+ return Math.pow(10, this._startValue + decimal * this._valueRange);
+ }
+}
+LogarithmicScale.id = 'logarithmic';
+LogarithmicScale.defaults = {
+ ticks: {
+ callback: Ticks.formatters.logarithmic,
+ major: {
+ enabled: true
+ }
+ }
+};
+
+function getTickBackdropHeight(opts) {
+ const tickOpts = opts.ticks;
+ if (tickOpts.display && opts.display) {
+ const padding = toPadding(tickOpts.backdropPadding);
+ return valueOrDefault(tickOpts.font && tickOpts.font.size, defaults.font.size) + padding.height;
+ }
+ return 0;
+}
+function measureLabelSize(ctx, font, label) {
+ label = isArray(label) ? label : [label];
+ return {
+ w: _longestText(ctx, font.string, label),
+ h: label.length * font.lineHeight
+ };
+}
+function determineLimits(angle, pos, size, min, max) {
+ if (angle === min || angle === max) {
+ return {
+ start: pos - (size / 2),
+ end: pos + (size / 2)
+ };
+ } else if (angle < min || angle > max) {
+ return {
+ start: pos - size,
+ end: pos
+ };
+ }
+ return {
+ start: pos,
+ end: pos + size
+ };
+}
+function fitWithPointLabels(scale) {
+ const furthestLimits = {
+ l: 0,
+ r: scale.width,
+ t: 0,
+ b: scale.height - scale.paddingTop
+ };
+ const furthestAngles = {};
+ const labelSizes = [];
+ const padding = [];
+ const valueCount = scale.getLabels().length;
+ for (let i = 0; i < valueCount; i++) {
+ const opts = scale.options.pointLabels.setContext(scale.getPointLabelContext(i));
+ padding[i] = opts.padding;
+ const pointPosition = scale.getPointPosition(i, scale.drawingArea + padding[i]);
+ const plFont = toFont(opts.font);
+ const textSize = measureLabelSize(scale.ctx, plFont, scale._pointLabels[i]);
+ labelSizes[i] = textSize;
+ const angleRadians = scale.getIndexAngle(i);
+ const angle = toDegrees(angleRadians);
+ const hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180);
+ const vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270);
+ if (hLimits.start < furthestLimits.l) {
+ furthestLimits.l = hLimits.start;
+ furthestAngles.l = angleRadians;
+ }
+ if (hLimits.end > furthestLimits.r) {
+ furthestLimits.r = hLimits.end;
+ furthestAngles.r = angleRadians;
+ }
+ if (vLimits.start < furthestLimits.t) {
+ furthestLimits.t = vLimits.start;
+ furthestAngles.t = angleRadians;
+ }
+ if (vLimits.end > furthestLimits.b) {
+ furthestLimits.b = vLimits.end;
+ furthestAngles.b = angleRadians;
+ }
+ }
+ scale._setReductions(scale.drawingArea, furthestLimits, furthestAngles);
+ scale._pointLabelItems = buildPointLabelItems(scale, labelSizes, padding);
+}
+function buildPointLabelItems(scale, labelSizes, padding) {
+ const items = [];
+ const valueCount = scale.getLabels().length;
+ const opts = scale.options;
+ const tickBackdropHeight = getTickBackdropHeight(opts);
+ const outerDistance = scale.getDistanceFromCenterForValue(opts.ticks.reverse ? scale.min : scale.max);
+ for (let i = 0; i < valueCount; i++) {
+ const extra = (i === 0 ? tickBackdropHeight / 2 : 0);
+ const pointLabelPosition = scale.getPointPosition(i, outerDistance + extra + padding[i]);
+ const angle = toDegrees(scale.getIndexAngle(i));
+ const size = labelSizes[i];
+ const y = yForAngle(pointLabelPosition.y, size.h, angle);
+ const textAlign = getTextAlignForAngle(angle);
+ const left = leftForTextAlign(pointLabelPosition.x, size.w, textAlign);
+ items.push({
+ x: pointLabelPosition.x,
+ y,
+ textAlign,
+ left,
+ top: y,
+ right: left + size.w,
+ bottom: y + size.h
+ });
+ }
+ return items;
+}
+function getTextAlignForAngle(angle) {
+ if (angle === 0 || angle === 180) {
+ return 'center';
+ } else if (angle < 180) {
+ return 'left';
+ }
+ return 'right';
+}
+function leftForTextAlign(x, w, align) {
+ if (align === 'right') {
+ x -= w;
+ } else if (align === 'center') {
+ x -= (w / 2);
+ }
+ return x;
+}
+function yForAngle(y, h, angle) {
+ if (angle === 90 || angle === 270) {
+ y -= (h / 2);
+ } else if (angle > 270 || angle < 90) {
+ y -= h;
+ }
+ return y;
+}
+function drawPointLabels(scale, labelCount) {
+ const {ctx, options: {pointLabels}} = scale;
+ for (let i = labelCount - 1; i >= 0; i--) {
+ const optsAtIndex = pointLabels.setContext(scale.getPointLabelContext(i));
+ const plFont = toFont(optsAtIndex.font);
+ const {x, y, textAlign, left, top, right, bottom} = scale._pointLabelItems[i];
+ const {backdropColor} = optsAtIndex;
+ if (!isNullOrUndef(backdropColor)) {
+ const padding = toPadding(optsAtIndex.backdropPadding);
+ ctx.fillStyle = backdropColor;
+ ctx.fillRect(left - padding.left, top - padding.top, right - left + padding.width, bottom - top + padding.height);
+ }
+ renderText(
+ ctx,
+ scale._pointLabels[i],
+ x,
+ y + (plFont.lineHeight / 2),
+ plFont,
+ {
+ color: optsAtIndex.color,
+ textAlign: textAlign,
+ textBaseline: 'middle'
+ }
+ );
+ }
+}
+function pathRadiusLine(scale, radius, circular, labelCount) {
+ const {ctx} = scale;
+ if (circular) {
+ ctx.arc(scale.xCenter, scale.yCenter, radius, 0, TAU);
+ } else {
+ let pointPosition = scale.getPointPosition(0, radius);
+ ctx.moveTo(pointPosition.x, pointPosition.y);
+ for (let i = 1; i < labelCount; i++) {
+ pointPosition = scale.getPointPosition(i, radius);
+ ctx.lineTo(pointPosition.x, pointPosition.y);
+ }
+ }
+}
+function drawRadiusLine(scale, gridLineOpts, radius, labelCount) {
+ const ctx = scale.ctx;
+ const circular = gridLineOpts.circular;
+ const {color, lineWidth} = gridLineOpts;
+ if ((!circular && !labelCount) || !color || !lineWidth || radius < 0) {
+ return;
+ }
+ ctx.save();
+ ctx.strokeStyle = color;
+ ctx.lineWidth = lineWidth;
+ ctx.setLineDash(gridLineOpts.borderDash);
+ ctx.lineDashOffset = gridLineOpts.borderDashOffset;
+ ctx.beginPath();
+ pathRadiusLine(scale, radius, circular, labelCount);
+ ctx.closePath();
+ ctx.stroke();
+ ctx.restore();
+}
+function numberOrZero(param) {
+ return isNumber(param) ? param : 0;
+}
+function createPointLabelContext(parent, index, label) {
+ return createContext(parent, {
+ label,
+ index,
+ type: 'pointLabel'
+ });
+}
+class RadialLinearScale extends LinearScaleBase {
+ constructor(cfg) {
+ super(cfg);
+ this.xCenter = undefined;
+ this.yCenter = undefined;
+ this.drawingArea = undefined;
+ this._pointLabels = [];
+ this._pointLabelItems = [];
+ }
+ setDimensions() {
+ this.width = this.maxWidth;
+ this.height = this.maxHeight;
+ this.paddingTop = getTickBackdropHeight(this.options) / 2;
+ this.xCenter = Math.floor(this.width / 2);
+ this.yCenter = Math.floor((this.height - this.paddingTop) / 2);
+ this.drawingArea = Math.min(this.height - this.paddingTop, this.width) / 2;
+ }
+ determineDataLimits() {
+ const {min, max} = this.getMinMax(false);
+ this.min = isNumberFinite(min) && !isNaN(min) ? min : 0;
+ this.max = isNumberFinite(max) && !isNaN(max) ? max : 0;
+ this.handleTickRangeOptions();
+ }
+ computeTickLimit() {
+ return Math.ceil(this.drawingArea / getTickBackdropHeight(this.options));
+ }
+ generateTickLabels(ticks) {
+ LinearScaleBase.prototype.generateTickLabels.call(this, ticks);
+ this._pointLabels = this.getLabels().map((value, index) => {
+ const label = callback(this.options.pointLabels.callback, [value, index], this);
+ return label || label === 0 ? label : '';
+ });
+ }
+ fit() {
+ const opts = this.options;
+ if (opts.display && opts.pointLabels.display) {
+ fitWithPointLabels(this);
+ } else {
+ this.setCenterPoint(0, 0, 0, 0);
+ }
+ }
+ _setReductions(largestPossibleRadius, furthestLimits, furthestAngles) {
+ let radiusReductionLeft = furthestLimits.l / Math.sin(furthestAngles.l);
+ let radiusReductionRight = Math.max(furthestLimits.r - this.width, 0) / Math.sin(furthestAngles.r);
+ let radiusReductionTop = -furthestLimits.t / Math.cos(furthestAngles.t);
+ let radiusReductionBottom = -Math.max(furthestLimits.b - (this.height - this.paddingTop), 0) / Math.cos(furthestAngles.b);
+ radiusReductionLeft = numberOrZero(radiusReductionLeft);
+ radiusReductionRight = numberOrZero(radiusReductionRight);
+ radiusReductionTop = numberOrZero(radiusReductionTop);
+ radiusReductionBottom = numberOrZero(radiusReductionBottom);
+ this.drawingArea = Math.max(largestPossibleRadius / 2, Math.min(
+ Math.floor(largestPossibleRadius - (radiusReductionLeft + radiusReductionRight) / 2),
+ Math.floor(largestPossibleRadius - (radiusReductionTop + radiusReductionBottom) / 2)));
+ this.setCenterPoint(radiusReductionLeft, radiusReductionRight, radiusReductionTop, radiusReductionBottom);
+ }
+ setCenterPoint(leftMovement, rightMovement, topMovement, bottomMovement) {
+ const maxRight = this.width - rightMovement - this.drawingArea;
+ const maxLeft = leftMovement + this.drawingArea;
+ const maxTop = topMovement + this.drawingArea;
+ const maxBottom = (this.height - this.paddingTop) - bottomMovement - this.drawingArea;
+ this.xCenter = Math.floor(((maxLeft + maxRight) / 2) + this.left);
+ this.yCenter = Math.floor(((maxTop + maxBottom) / 2) + this.top + this.paddingTop);
+ }
+ getIndexAngle(index) {
+ const angleMultiplier = TAU / this.getLabels().length;
+ const startAngle = this.options.startAngle || 0;
+ return _normalizeAngle(index * angleMultiplier + toRadians(startAngle));
+ }
+ getDistanceFromCenterForValue(value) {
+ if (isNullOrUndef(value)) {
+ return NaN;
+ }
+ const scalingFactor = this.drawingArea / (this.max - this.min);
+ if (this.options.reverse) {
+ return (this.max - value) * scalingFactor;
+ }
+ return (value - this.min) * scalingFactor;
+ }
+ getValueForDistanceFromCenter(distance) {
+ if (isNullOrUndef(distance)) {
+ return NaN;
+ }
+ const scaledDistance = distance / (this.drawingArea / (this.max - this.min));
+ return this.options.reverse ? this.max - scaledDistance : this.min + scaledDistance;
+ }
+ getPointLabelContext(index) {
+ const pointLabels = this._pointLabels || [];
+ if (index >= 0 && index < pointLabels.length) {
+ const pointLabel = pointLabels[index];
+ return createPointLabelContext(this.getContext(), index, pointLabel);
+ }
+ }
+ getPointPosition(index, distanceFromCenter) {
+ const angle = this.getIndexAngle(index) - HALF_PI;
+ return {
+ x: Math.cos(angle) * distanceFromCenter + this.xCenter,
+ y: Math.sin(angle) * distanceFromCenter + this.yCenter,
+ angle
+ };
+ }
+ getPointPositionForValue(index, value) {
+ return this.getPointPosition(index, this.getDistanceFromCenterForValue(value));
+ }
+ getBasePosition(index) {
+ return this.getPointPositionForValue(index || 0, this.getBaseValue());
+ }
+ getPointLabelPosition(index) {
+ const {left, top, right, bottom} = this._pointLabelItems[index];
+ return {
+ left,
+ top,
+ right,
+ bottom,
+ };
+ }
+ drawBackground() {
+ const {backgroundColor, grid: {circular}} = this.options;
+ if (backgroundColor) {
+ const ctx = this.ctx;
+ ctx.save();
+ ctx.beginPath();
+ pathRadiusLine(this, this.getDistanceFromCenterForValue(this._endValue), circular, this.getLabels().length);
+ ctx.closePath();
+ ctx.fillStyle = backgroundColor;
+ ctx.fill();
+ ctx.restore();
+ }
+ }
+ drawGrid() {
+ const ctx = this.ctx;
+ const opts = this.options;
+ const {angleLines, grid} = opts;
+ const labelCount = this.getLabels().length;
+ let i, offset, position;
+ if (opts.pointLabels.display) {
+ drawPointLabels(this, labelCount);
+ }
+ if (grid.display) {
+ this.ticks.forEach((tick, index) => {
+ if (index !== 0) {
+ offset = this.getDistanceFromCenterForValue(tick.value);
+ const optsAtIndex = grid.setContext(this.getContext(index - 1));
+ drawRadiusLine(this, optsAtIndex, offset, labelCount);
+ }
+ });
+ }
+ if (angleLines.display) {
+ ctx.save();
+ for (i = this.getLabels().length - 1; i >= 0; i--) {
+ const optsAtIndex = angleLines.setContext(this.getPointLabelContext(i));
+ const {color, lineWidth} = optsAtIndex;
+ if (!lineWidth || !color) {
+ continue;
+ }
+ ctx.lineWidth = lineWidth;
+ ctx.strokeStyle = color;
+ ctx.setLineDash(optsAtIndex.borderDash);
+ ctx.lineDashOffset = optsAtIndex.borderDashOffset;
+ offset = this.getDistanceFromCenterForValue(opts.ticks.reverse ? this.min : this.max);
+ position = this.getPointPosition(i, offset);
+ ctx.beginPath();
+ ctx.moveTo(this.xCenter, this.yCenter);
+ ctx.lineTo(position.x, position.y);
+ ctx.stroke();
+ }
+ ctx.restore();
+ }
+ }
+ drawBorder() {}
+ drawLabels() {
+ const ctx = this.ctx;
+ const opts = this.options;
+ const tickOpts = opts.ticks;
+ if (!tickOpts.display) {
+ return;
+ }
+ const startAngle = this.getIndexAngle(0);
+ let offset, width;
+ ctx.save();
+ ctx.translate(this.xCenter, this.yCenter);
+ ctx.rotate(startAngle);
+ ctx.textAlign = 'center';
+ ctx.textBaseline = 'middle';
+ this.ticks.forEach((tick, index) => {
+ if (index === 0 && !opts.reverse) {
+ return;
+ }
+ const optsAtIndex = tickOpts.setContext(this.getContext(index));
+ const tickFont = toFont(optsAtIndex.font);
+ offset = this.getDistanceFromCenterForValue(this.ticks[index].value);
+ if (optsAtIndex.showLabelBackdrop) {
+ ctx.font = tickFont.string;
+ width = ctx.measureText(tick.label).width;
+ ctx.fillStyle = optsAtIndex.backdropColor;
+ const padding = toPadding(optsAtIndex.backdropPadding);
+ ctx.fillRect(
+ -width / 2 - padding.left,
+ -offset - tickFont.size / 2 - padding.top,
+ width + padding.width,
+ tickFont.size + padding.height
+ );
+ }
+ renderText(ctx, tick.label, 0, -offset, tickFont, {
+ color: optsAtIndex.color,
+ });
+ });
+ ctx.restore();
+ }
+ drawTitle() {}
+}
+RadialLinearScale.id = 'radialLinear';
+RadialLinearScale.defaults = {
+ display: true,
+ animate: true,
+ position: 'chartArea',
+ angleLines: {
+ display: true,
+ lineWidth: 1,
+ borderDash: [],
+ borderDashOffset: 0.0
+ },
+ grid: {
+ circular: false
+ },
+ startAngle: 0,
+ ticks: {
+ showLabelBackdrop: true,
+ callback: Ticks.formatters.numeric
+ },
+ pointLabels: {
+ backdropColor: undefined,
+ backdropPadding: 2,
+ display: true,
+ font: {
+ size: 10
+ },
+ callback(label) {
+ return label;
+ },
+ padding: 5
+ }
+};
+RadialLinearScale.defaultRoutes = {
+ 'angleLines.color': 'borderColor',
+ 'pointLabels.color': 'color',
+ 'ticks.color': 'color'
+};
+RadialLinearScale.descriptors = {
+ angleLines: {
+ _fallback: 'grid'
+ }
+};
+
+const INTERVALS = {
+ millisecond: {common: true, size: 1, steps: 1000},
+ second: {common: true, size: 1000, steps: 60},
+ minute: {common: true, size: 60000, steps: 60},
+ hour: {common: true, size: 3600000, steps: 24},
+ day: {common: true, size: 86400000, steps: 30},
+ week: {common: false, size: 604800000, steps: 4},
+ month: {common: true, size: 2.628e9, steps: 12},
+ quarter: {common: false, size: 7.884e9, steps: 4},
+ year: {common: true, size: 3.154e10}
+};
+const UNITS = (Object.keys(INTERVALS));
+function sorter(a, b) {
+ return a - b;
+}
+function parse(scale, input) {
+ if (isNullOrUndef(input)) {
+ return null;
+ }
+ const adapter = scale._adapter;
+ const {parser, round, isoWeekday} = scale._parseOpts;
+ let value = input;
+ if (typeof parser === 'function') {
+ value = parser(value);
+ }
+ if (!isNumberFinite(value)) {
+ value = typeof parser === 'string'
+ ? adapter.parse(value, parser)
+ : adapter.parse(value);
+ }
+ if (value === null) {
+ return null;
+ }
+ if (round) {
+ value = round === 'week' && (isNumber(isoWeekday) || isoWeekday === true)
+ ? adapter.startOf(value, 'isoWeek', isoWeekday)
+ : adapter.startOf(value, round);
+ }
+ return +value;
+}
+function determineUnitForAutoTicks(minUnit, min, max, capacity) {
+ const ilen = UNITS.length;
+ for (let i = UNITS.indexOf(minUnit); i < ilen - 1; ++i) {
+ const interval = INTERVALS[UNITS[i]];
+ const factor = interval.steps ? interval.steps : Number.MAX_SAFE_INTEGER;
+ if (interval.common && Math.ceil((max - min) / (factor * interval.size)) <= capacity) {
+ return UNITS[i];
+ }
+ }
+ return UNITS[ilen - 1];
+}
+function determineUnitForFormatting(scale, numTicks, minUnit, min, max) {
+ for (let i = UNITS.length - 1; i >= UNITS.indexOf(minUnit); i--) {
+ const unit = UNITS[i];
+ if (INTERVALS[unit].common && scale._adapter.diff(max, min, unit) >= numTicks - 1) {
+ return unit;
+ }
+ }
+ return UNITS[minUnit ? UNITS.indexOf(minUnit) : 0];
+}
+function determineMajorUnit(unit) {
+ for (let i = UNITS.indexOf(unit) + 1, ilen = UNITS.length; i < ilen; ++i) {
+ if (INTERVALS[UNITS[i]].common) {
+ return UNITS[i];
+ }
+ }
+}
+function addTick(ticks, time, timestamps) {
+ if (!timestamps) {
+ ticks[time] = true;
+ } else if (timestamps.length) {
+ const {lo, hi} = _lookup(timestamps, time);
+ const timestamp = timestamps[lo] >= time ? timestamps[lo] : timestamps[hi];
+ ticks[timestamp] = true;
+ }
+}
+function setMajorTicks(scale, ticks, map, majorUnit) {
+ const adapter = scale._adapter;
+ const first = +adapter.startOf(ticks[0].value, majorUnit);
+ const last = ticks[ticks.length - 1].value;
+ let major, index;
+ for (major = first; major <= last; major = +adapter.add(major, 1, majorUnit)) {
+ index = map[major];
+ if (index >= 0) {
+ ticks[index].major = true;
+ }
+ }
+ return ticks;
+}
+function ticksFromTimestamps(scale, values, majorUnit) {
+ const ticks = [];
+ const map = {};
+ const ilen = values.length;
+ let i, value;
+ for (i = 0; i < ilen; ++i) {
+ value = values[i];
+ map[value] = i;
+ ticks.push({
+ value,
+ major: false
+ });
+ }
+ return (ilen === 0 || !majorUnit) ? ticks : setMajorTicks(scale, ticks, map, majorUnit);
+}
+class TimeScale extends Scale {
+ constructor(props) {
+ super(props);
+ this._cache = {
+ data: [],
+ labels: [],
+ all: []
+ };
+ this._unit = 'day';
+ this._majorUnit = undefined;
+ this._offsets = {};
+ this._normalized = false;
+ this._parseOpts = undefined;
+ }
+ init(scaleOpts, opts) {
+ const time = scaleOpts.time || (scaleOpts.time = {});
+ const adapter = this._adapter = new _adapters._date(scaleOpts.adapters.date);
+ mergeIf(time.displayFormats, adapter.formats());
+ this._parseOpts = {
+ parser: time.parser,
+ round: time.round,
+ isoWeekday: time.isoWeekday
+ };
+ super.init(scaleOpts);
+ this._normalized = opts.normalized;
+ }
+ parse(raw, index) {
+ if (raw === undefined) {
+ return null;
+ }
+ return parse(this, raw);
+ }
+ beforeLayout() {
+ super.beforeLayout();
+ this._cache = {
+ data: [],
+ labels: [],
+ all: []
+ };
+ }
+ determineDataLimits() {
+ const options = this.options;
+ const adapter = this._adapter;
+ const unit = options.time.unit || 'day';
+ let {min, max, minDefined, maxDefined} = this.getUserBounds();
+ function _applyBounds(bounds) {
+ if (!minDefined && !isNaN(bounds.min)) {
+ min = Math.min(min, bounds.min);
+ }
+ if (!maxDefined && !isNaN(bounds.max)) {
+ max = Math.max(max, bounds.max);
+ }
+ }
+ if (!minDefined || !maxDefined) {
+ _applyBounds(this._getLabelBounds());
+ if (options.bounds !== 'ticks' || options.ticks.source !== 'labels') {
+ _applyBounds(this.getMinMax(false));
+ }
+ }
+ min = isNumberFinite(min) && !isNaN(min) ? min : +adapter.startOf(Date.now(), unit);
+ max = isNumberFinite(max) && !isNaN(max) ? max : +adapter.endOf(Date.now(), unit) + 1;
+ this.min = Math.min(min, max - 1);
+ this.max = Math.max(min + 1, max);
+ }
+ _getLabelBounds() {
+ const arr = this.getLabelTimestamps();
+ let min = Number.POSITIVE_INFINITY;
+ let max = Number.NEGATIVE_INFINITY;
+ if (arr.length) {
+ min = arr[0];
+ max = arr[arr.length - 1];
+ }
+ return {min, max};
+ }
+ buildTicks() {
+ const options = this.options;
+ const timeOpts = options.time;
+ const tickOpts = options.ticks;
+ const timestamps = tickOpts.source === 'labels' ? this.getLabelTimestamps() : this._generate();
+ if (options.bounds === 'ticks' && timestamps.length) {
+ this.min = this._userMin || timestamps[0];
+ this.max = this._userMax || timestamps[timestamps.length - 1];
+ }
+ const min = this.min;
+ const max = this.max;
+ const ticks = _filterBetween(timestamps, min, max);
+ this._unit = timeOpts.unit || (tickOpts.autoSkip
+ ? determineUnitForAutoTicks(timeOpts.minUnit, this.min, this.max, this._getLabelCapacity(min))
+ : determineUnitForFormatting(this, ticks.length, timeOpts.minUnit, this.min, this.max));
+ this._majorUnit = !tickOpts.major.enabled || this._unit === 'year' ? undefined
+ : determineMajorUnit(this._unit);
+ this.initOffsets(timestamps);
+ if (options.reverse) {
+ ticks.reverse();
+ }
+ return ticksFromTimestamps(this, ticks, this._majorUnit);
+ }
+ initOffsets(timestamps) {
+ let start = 0;
+ let end = 0;
+ let first, last;
+ if (this.options.offset && timestamps.length) {
+ first = this.getDecimalForValue(timestamps[0]);
+ if (timestamps.length === 1) {
+ start = 1 - first;
+ } else {
+ start = (this.getDecimalForValue(timestamps[1]) - first) / 2;
+ }
+ last = this.getDecimalForValue(timestamps[timestamps.length - 1]);
+ if (timestamps.length === 1) {
+ end = last;
+ } else {
+ end = (last - this.getDecimalForValue(timestamps[timestamps.length - 2])) / 2;
+ }
+ }
+ const limit = timestamps.length < 3 ? 0.5 : 0.25;
+ start = _limitValue(start, 0, limit);
+ end = _limitValue(end, 0, limit);
+ this._offsets = {start, end, factor: 1 / (start + 1 + end)};
+ }
+ _generate() {
+ const adapter = this._adapter;
+ const min = this.min;
+ const max = this.max;
+ const options = this.options;
+ const timeOpts = options.time;
+ const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, this._getLabelCapacity(min));
+ const stepSize = valueOrDefault(timeOpts.stepSize, 1);
+ const weekday = minor === 'week' ? timeOpts.isoWeekday : false;
+ const hasWeekday = isNumber(weekday) || weekday === true;
+ const ticks = {};
+ let first = min;
+ let time, count;
+ if (hasWeekday) {
+ first = +adapter.startOf(first, 'isoWeek', weekday);
+ }
+ first = +adapter.startOf(first, hasWeekday ? 'day' : minor);
+ if (adapter.diff(max, min, minor) > 100000 * stepSize) {
+ throw new Error(min + ' and ' + max + ' are too far apart with stepSize of ' + stepSize + ' ' + minor);
+ }
+ const timestamps = options.ticks.source === 'data' && this.getDataTimestamps();
+ for (time = first, count = 0; time < max; time = +adapter.add(time, stepSize, minor), count++) {
+ addTick(ticks, time, timestamps);
+ }
+ if (time === max || options.bounds === 'ticks' || count === 1) {
+ addTick(ticks, time, timestamps);
+ }
+ return Object.keys(ticks).sort((a, b) => a - b).map(x => +x);
+ }
+ getLabelForValue(value) {
+ const adapter = this._adapter;
+ const timeOpts = this.options.time;
+ if (timeOpts.tooltipFormat) {
+ return adapter.format(value, timeOpts.tooltipFormat);
+ }
+ return adapter.format(value, timeOpts.displayFormats.datetime);
+ }
+ _tickFormatFunction(time, index, ticks, format) {
+ const options = this.options;
+ const formats = options.time.displayFormats;
+ const unit = this._unit;
+ const majorUnit = this._majorUnit;
+ const minorFormat = unit && formats[unit];
+ const majorFormat = majorUnit && formats[majorUnit];
+ const tick = ticks[index];
+ const major = majorUnit && majorFormat && tick && tick.major;
+ const label = this._adapter.format(time, format || (major ? majorFormat : minorFormat));
+ const formatter = options.ticks.callback;
+ return formatter ? callback(formatter, [label, index, ticks], this) : label;
+ }
+ generateTickLabels(ticks) {
+ let i, ilen, tick;
+ for (i = 0, ilen = ticks.length; i < ilen; ++i) {
+ tick = ticks[i];
+ tick.label = this._tickFormatFunction(tick.value, i, ticks);
+ }
+ }
+ getDecimalForValue(value) {
+ return value === null ? NaN : (value - this.min) / (this.max - this.min);
+ }
+ getPixelForValue(value) {
+ const offsets = this._offsets;
+ const pos = this.getDecimalForValue(value);
+ return this.getPixelForDecimal((offsets.start + pos) * offsets.factor);
+ }
+ getValueForPixel(pixel) {
+ const offsets = this._offsets;
+ const pos = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
+ return this.min + pos * (this.max - this.min);
+ }
+ _getLabelSize(label) {
+ const ticksOpts = this.options.ticks;
+ const tickLabelWidth = this.ctx.measureText(label).width;
+ const angle = toRadians(this.isHorizontal() ? ticksOpts.maxRotation : ticksOpts.minRotation);
+ const cosRotation = Math.cos(angle);
+ const sinRotation = Math.sin(angle);
+ const tickFontSize = this._resolveTickFontOptions(0).size;
+ return {
+ w: (tickLabelWidth * cosRotation) + (tickFontSize * sinRotation),
+ h: (tickLabelWidth * sinRotation) + (tickFontSize * cosRotation)
+ };
+ }
+ _getLabelCapacity(exampleTime) {
+ const timeOpts = this.options.time;
+ const displayFormats = timeOpts.displayFormats;
+ const format = displayFormats[timeOpts.unit] || displayFormats.millisecond;
+ const exampleLabel = this._tickFormatFunction(exampleTime, 0, ticksFromTimestamps(this, [exampleTime], this._majorUnit), format);
+ const size = this._getLabelSize(exampleLabel);
+ const capacity = Math.floor(this.isHorizontal() ? this.width / size.w : this.height / size.h) - 1;
+ return capacity > 0 ? capacity : 1;
+ }
+ getDataTimestamps() {
+ let timestamps = this._cache.data || [];
+ let i, ilen;
+ if (timestamps.length) {
+ return timestamps;
+ }
+ const metas = this.getMatchingVisibleMetas();
+ if (this._normalized && metas.length) {
+ return (this._cache.data = metas[0].controller.getAllParsedValues(this));
+ }
+ for (i = 0, ilen = metas.length; i < ilen; ++i) {
+ timestamps = timestamps.concat(metas[i].controller.getAllParsedValues(this));
+ }
+ return (this._cache.data = this.normalize(timestamps));
+ }
+ getLabelTimestamps() {
+ const timestamps = this._cache.labels || [];
+ let i, ilen;
+ if (timestamps.length) {
+ return timestamps;
+ }
+ const labels = this.getLabels();
+ for (i = 0, ilen = labels.length; i < ilen; ++i) {
+ timestamps.push(parse(this, labels[i]));
+ }
+ return (this._cache.labels = this._normalized ? timestamps : this.normalize(timestamps));
+ }
+ normalize(values) {
+ return _arrayUnique(values.sort(sorter));
+ }
+}
+TimeScale.id = 'time';
+TimeScale.defaults = {
+ bounds: 'data',
+ adapters: {},
+ time: {
+ parser: false,
+ unit: false,
+ round: false,
+ isoWeekday: false,
+ minUnit: 'millisecond',
+ displayFormats: {}
+ },
+ ticks: {
+ source: 'auto',
+ major: {
+ enabled: false
+ }
+ }
+};
+
+function interpolate(table, val, reverse) {
+ let lo = 0;
+ let hi = table.length - 1;
+ let prevSource, nextSource, prevTarget, nextTarget;
+ if (reverse) {
+ if (val >= table[lo].pos && val <= table[hi].pos) {
+ ({lo, hi} = _lookupByKey(table, 'pos', val));
+ }
+ ({pos: prevSource, time: prevTarget} = table[lo]);
+ ({pos: nextSource, time: nextTarget} = table[hi]);
+ } else {
+ if (val >= table[lo].time && val <= table[hi].time) {
+ ({lo, hi} = _lookupByKey(table, 'time', val));
+ }
+ ({time: prevSource, pos: prevTarget} = table[lo]);
+ ({time: nextSource, pos: nextTarget} = table[hi]);
+ }
+ const span = nextSource - prevSource;
+ return span ? prevTarget + (nextTarget - prevTarget) * (val - prevSource) / span : prevTarget;
+}
+class TimeSeriesScale extends TimeScale {
+ constructor(props) {
+ super(props);
+ this._table = [];
+ this._minPos = undefined;
+ this._tableRange = undefined;
+ }
+ initOffsets() {
+ const timestamps = this._getTimestampsForTable();
+ const table = this._table = this.buildLookupTable(timestamps);
+ this._minPos = interpolate(table, this.min);
+ this._tableRange = interpolate(table, this.max) - this._minPos;
+ super.initOffsets(timestamps);
+ }
+ buildLookupTable(timestamps) {
+ const {min, max} = this;
+ const items = [];
+ const table = [];
+ let i, ilen, prev, curr, next;
+ for (i = 0, ilen = timestamps.length; i < ilen; ++i) {
+ curr = timestamps[i];
+ if (curr >= min && curr <= max) {
+ items.push(curr);
+ }
+ }
+ if (items.length < 2) {
+ return [
+ {time: min, pos: 0},
+ {time: max, pos: 1}
+ ];
+ }
+ for (i = 0, ilen = items.length; i < ilen; ++i) {
+ next = items[i + 1];
+ prev = items[i - 1];
+ curr = items[i];
+ if (Math.round((next + prev) / 2) !== curr) {
+ table.push({time: curr, pos: i / (ilen - 1)});
+ }
+ }
+ return table;
+ }
+ _getTimestampsForTable() {
+ let timestamps = this._cache.all || [];
+ if (timestamps.length) {
+ return timestamps;
+ }
+ const data = this.getDataTimestamps();
+ const label = this.getLabelTimestamps();
+ if (data.length && label.length) {
+ timestamps = this.normalize(data.concat(label));
+ } else {
+ timestamps = data.length ? data : label;
+ }
+ timestamps = this._cache.all = timestamps;
+ return timestamps;
+ }
+ getDecimalForValue(value) {
+ return (interpolate(this._table, value) - this._minPos) / this._tableRange;
+ }
+ getValueForPixel(pixel) {
+ const offsets = this._offsets;
+ const decimal = this.getDecimalForPixel(pixel) / offsets.factor - offsets.end;
+ return interpolate(this._table, decimal * this._tableRange + this._minPos, true);
+ }
+}
+TimeSeriesScale.id = 'timeseries';
+TimeSeriesScale.defaults = TimeScale.defaults;
+
+var scales = /*#__PURE__*/Object.freeze({
+__proto__: null,
+CategoryScale: CategoryScale,
+LinearScale: LinearScale,
+LogarithmicScale: LogarithmicScale,
+RadialLinearScale: RadialLinearScale,
+TimeScale: TimeScale,
+TimeSeriesScale: TimeSeriesScale
+});
+
+Chart.register(controllers, scales, elements, plugins);
+Chart.helpers = {...helpers};
+Chart._adapters = _adapters;
+Chart.Animation = Animation;
+Chart.Animations = Animations;
+Chart.animator = animator;
+Chart.controllers = registry.controllers.items;
+Chart.DatasetController = DatasetController;
+Chart.Element = Element;
+Chart.elements = elements;
+Chart.Interaction = Interaction;
+Chart.layouts = layouts;
+Chart.platforms = platforms;
+Chart.Scale = Scale;
+Chart.Ticks = Ticks;
+Object.assign(Chart, controllers, scales, elements, plugins, platforms);
+Chart.Chart = Chart;
+if (typeof window !== 'undefined') {
+ window.Chart = Chart;
+}
+
+return Chart;
+
+})));
diff --git a/static/chart.min.js b/static/chart.min.js
@@ -0,0 +1,13 @@
+/*!
+ * Chart.js v3.6.0
+ * https://www.chartjs.org
+ * (c) 2021 Chart.js Contributors
+ * Released under the MIT License
+ */
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Chart=e()}(this,(function(){"use strict";const t="undefined"==typeof window?function(t){return t()}:window.requestAnimationFrame;function e(e,i,s){const n=s||(t=>Array.prototype.slice.call(t));let o=!1,a=[];return function(...s){a=n(s),o||(o=!0,t.call(window,(()=>{o=!1,e.apply(i,a)})))}}function i(t,e){let i;return function(...s){return e?(clearTimeout(i),i=setTimeout(t,e,s)):t.apply(this,s),e}}const s=t=>"start"===t?"left":"end"===t?"right":"center",n=(t,e,i)=>"start"===t?e:"end"===t?i:(e+i)/2,o=(t,e,i,s)=>t===(s?"left":"right")?i:"center"===t?(e+i)/2:e;var a=new class{constructor(){this._request=null,this._charts=new Map,this._running=!1,this._lastDate=void 0}_notify(t,e,i,s){const n=e.listeners[s],o=e.duration;n.forEach((s=>s({chart:t,initial:e.initial,numSteps:o,currentStep:Math.min(i-e.start,o)})))}_refresh(){this._request||(this._running=!0,this._request=t.call(window,(()=>{this._update(),this._request=null,this._running&&this._refresh()})))}_update(t=Date.now()){let e=0;this._charts.forEach(((i,s)=>{if(!i.running||!i.items.length)return;const n=i.items;let o,a=n.length-1,r=!1;for(;a>=0;--a)o=n[a],o._active?(o._total>i.duration&&(i.duration=o._total),o.tick(t),r=!0):(n[a]=n[n.length-1],n.pop());r&&(s.draw(),this._notify(s,i,t,"progress")),n.length||(i.running=!1,this._notify(s,i,t,"complete"),i.initial=!1),e+=n.length})),this._lastDate=t,0===e&&(this._running=!1)}_getAnims(t){const e=this._charts;let i=e.get(t);return i||(i={running:!1,initial:!0,items:[],listeners:{complete:[],progress:[]}},e.set(t,i)),i}listen(t,e,i){this._getAnims(t).listeners[e].push(i)}add(t,e){e&&e.length&&this._getAnims(t).items.push(...e)}has(t){return this._getAnims(t).items.length>0}start(t){const e=this._charts.get(t);e&&(e.running=!0,e.start=Date.now(),e.duration=e.items.reduce(((t,e)=>Math.max(t,e._duration)),0),this._refresh())}running(t){if(!this._running)return!1;const e=this._charts.get(t);return!!(e&&e.running&&e.items.length)}stop(t){const e=this._charts.get(t);if(!e||!e.items.length)return;const i=e.items;let s=i.length-1;for(;s>=0;--s)i[s].cancel();e.items=[],this._notify(t,e,Date.now(),"complete")}remove(t){return this._charts.delete(t)}};
+/*!
+ * @kurkle/color v0.1.9
+ * https://github.com/kurkle/color#readme
+ * (c) 2020 Jukka Kurkela
+ * Released under the MIT License
+ */const r={0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,A:10,B:11,C:12,D:13,E:14,F:15,a:10,b:11,c:12,d:13,e:14,f:15},l="0123456789ABCDEF",h=t=>l[15&t],c=t=>l[(240&t)>>4]+l[15&t],d=t=>(240&t)>>4==(15&t);function u(t){var e=function(t){return d(t.r)&&d(t.g)&&d(t.b)&&d(t.a)}(t)?h:c;return t?"#"+e(t.r)+e(t.g)+e(t.b)+(t.a<255?e(t.a):""):t}function f(t){return t+.5|0}const g=(t,e,i)=>Math.max(Math.min(t,i),e);function p(t){return g(f(2.55*t),0,255)}function m(t){return g(f(255*t),0,255)}function x(t){return g(f(t/2.55)/100,0,1)}function b(t){return g(f(100*t),0,100)}const _=/^rgba?\(\s*([-+.\d]+)(%)?[\s,]+([-+.e\d]+)(%)?[\s,]+([-+.e\d]+)(%)?(?:[\s,/]+([-+.e\d]+)(%)?)?\s*\)$/;const y=/^(hsla?|hwb|hsv)\(\s*([-+.e\d]+)(?:deg)?[\s,]+([-+.e\d]+)%[\s,]+([-+.e\d]+)%(?:[\s,]+([-+.e\d]+)(%)?)?\s*\)$/;function v(t,e,i){const s=e*Math.min(i,1-i),n=(e,n=(e+t/30)%12)=>i-s*Math.max(Math.min(n-3,9-n,1),-1);return[n(0),n(8),n(4)]}function w(t,e,i){const s=(s,n=(s+t/60)%6)=>i-i*e*Math.max(Math.min(n,4-n,1),0);return[s(5),s(3),s(1)]}function M(t,e,i){const s=v(t,1,.5);let n;for(e+i>1&&(n=1/(e+i),e*=n,i*=n),n=0;n<3;n++)s[n]*=1-e-i,s[n]+=e;return s}function k(t){const e=t.r/255,i=t.g/255,s=t.b/255,n=Math.max(e,i,s),o=Math.min(e,i,s),a=(n+o)/2;let r,l,h;return n!==o&&(h=n-o,l=a>.5?h/(2-n-o):h/(n+o),r=n===e?(i-s)/h+(i<s?6:0):n===i?(s-e)/h+2:(e-i)/h+4,r=60*r+.5),[0|r,l||0,a]}function S(t,e,i,s){return(Array.isArray(e)?t(e[0],e[1],e[2]):t(e,i,s)).map(m)}function P(t,e,i){return S(v,t,e,i)}function D(t){return(t%360+360)%360}function C(t){const e=y.exec(t);let i,s=255;if(!e)return;e[5]!==i&&(s=e[6]?p(+e[5]):m(+e[5]));const n=D(+e[2]),o=+e[3]/100,a=+e[4]/100;return i="hwb"===e[1]?function(t,e,i){return S(M,t,e,i)}(n,o,a):"hsv"===e[1]?function(t,e,i){return S(w,t,e,i)}(n,o,a):P(n,o,a),{r:i[0],g:i[1],b:i[2],a:s}}const O={x:"dark",Z:"light",Y:"re",X:"blu",W:"gr",V:"medium",U:"slate",A:"ee",T:"ol",S:"or",B:"ra",C:"lateg",D:"ights",R:"in",Q:"turquois",E:"hi",P:"ro",O:"al",N:"le",M:"de",L:"yello",F:"en",K:"ch",G:"arks",H:"ea",I:"ightg",J:"wh"},A={OiceXe:"f0f8ff",antiquewEte:"faebd7",aqua:"ffff",aquamarRe:"7fffd4",azuY:"f0ffff",beige:"f5f5dc",bisque:"ffe4c4",black:"0",blanKedOmond:"ffebcd",Xe:"ff",XeviTet:"8a2be2",bPwn:"a52a2a",burlywood:"deb887",caMtXe:"5f9ea0",KartYuse:"7fff00",KocTate:"d2691e",cSO:"ff7f50",cSnflowerXe:"6495ed",cSnsilk:"fff8dc",crimson:"dc143c",cyan:"ffff",xXe:"8b",xcyan:"8b8b",xgTMnPd:"b8860b",xWay:"a9a9a9",xgYF:"6400",xgYy:"a9a9a9",xkhaki:"bdb76b",xmagFta:"8b008b",xTivegYF:"556b2f",xSange:"ff8c00",xScEd:"9932cc",xYd:"8b0000",xsOmon:"e9967a",xsHgYF:"8fbc8f",xUXe:"483d8b",xUWay:"2f4f4f",xUgYy:"2f4f4f",xQe:"ced1",xviTet:"9400d3",dAppRk:"ff1493",dApskyXe:"bfff",dimWay:"696969",dimgYy:"696969",dodgerXe:"1e90ff",fiYbrick:"b22222",flSOwEte:"fffaf0",foYstWAn:"228b22",fuKsia:"ff00ff",gaRsbSo:"dcdcdc",ghostwEte:"f8f8ff",gTd:"ffd700",gTMnPd:"daa520",Way:"808080",gYF:"8000",gYFLw:"adff2f",gYy:"808080",honeyMw:"f0fff0",hotpRk:"ff69b4",RdianYd:"cd5c5c",Rdigo:"4b0082",ivSy:"fffff0",khaki:"f0e68c",lavFMr:"e6e6fa",lavFMrXsh:"fff0f5",lawngYF:"7cfc00",NmoncEffon:"fffacd",ZXe:"add8e6",ZcSO:"f08080",Zcyan:"e0ffff",ZgTMnPdLw:"fafad2",ZWay:"d3d3d3",ZgYF:"90ee90",ZgYy:"d3d3d3",ZpRk:"ffb6c1",ZsOmon:"ffa07a",ZsHgYF:"20b2aa",ZskyXe:"87cefa",ZUWay:"778899",ZUgYy:"778899",ZstAlXe:"b0c4de",ZLw:"ffffe0",lime:"ff00",limegYF:"32cd32",lRF:"faf0e6",magFta:"ff00ff",maPon:"800000",VaquamarRe:"66cdaa",VXe:"cd",VScEd:"ba55d3",VpurpN:"9370db",VsHgYF:"3cb371",VUXe:"7b68ee",VsprRggYF:"fa9a",VQe:"48d1cc",VviTetYd:"c71585",midnightXe:"191970",mRtcYam:"f5fffa",mistyPse:"ffe4e1",moccasR:"ffe4b5",navajowEte:"ffdead",navy:"80",Tdlace:"fdf5e6",Tive:"808000",TivedBb:"6b8e23",Sange:"ffa500",SangeYd:"ff4500",ScEd:"da70d6",pOegTMnPd:"eee8aa",pOegYF:"98fb98",pOeQe:"afeeee",pOeviTetYd:"db7093",papayawEp:"ffefd5",pHKpuff:"ffdab9",peru:"cd853f",pRk:"ffc0cb",plum:"dda0dd",powMrXe:"b0e0e6",purpN:"800080",YbeccapurpN:"663399",Yd:"ff0000",Psybrown:"bc8f8f",PyOXe:"4169e1",saddNbPwn:"8b4513",sOmon:"fa8072",sandybPwn:"f4a460",sHgYF:"2e8b57",sHshell:"fff5ee",siFna:"a0522d",silver:"c0c0c0",skyXe:"87ceeb",UXe:"6a5acd",UWay:"708090",UgYy:"708090",snow:"fffafa",sprRggYF:"ff7f",stAlXe:"4682b4",tan:"d2b48c",teO:"8080",tEstN:"d8bfd8",tomato:"ff6347",Qe:"40e0d0",viTet:"ee82ee",JHt:"f5deb3",wEte:"ffffff",wEtesmoke:"f5f5f5",Lw:"ffff00",LwgYF:"9acd32"};let T;function L(t){T||(T=function(){const t={},e=Object.keys(A),i=Object.keys(O);let s,n,o,a,r;for(s=0;s<e.length;s++){for(a=r=e[s],n=0;n<i.length;n++)o=i[n],r=r.replace(o,O[o]);o=parseInt(A[a],16),t[r]=[o>>16&255,o>>8&255,255&o]}return t}(),T.transparent=[0,0,0,0]);const e=T[t.toLowerCase()];return e&&{r:e[0],g:e[1],b:e[2],a:4===e.length?e[3]:255}}function R(t,e,i){if(t){let s=k(t);s[e]=Math.max(0,Math.min(s[e]+s[e]*i,0===e?360:1)),s=P(s),t.r=s[0],t.g=s[1],t.b=s[2]}}function E(t,e){return t?Object.assign(e||{},t):t}function I(t){var e={r:0,g:0,b:0,a:255};return Array.isArray(t)?t.length>=3&&(e={r:t[0],g:t[1],b:t[2],a:255},t.length>3&&(e.a=m(t[3]))):(e=E(t,{r:0,g:0,b:0,a:1})).a=m(e.a),e}function z(t){return"r"===t.charAt(0)?function(t){const e=_.exec(t);let i,s,n,o=255;if(e){if(e[7]!==i){const t=+e[7];o=255&(e[8]?p(t):255*t)}return i=+e[1],s=+e[3],n=+e[5],i=255&(e[2]?p(i):i),s=255&(e[4]?p(s):s),n=255&(e[6]?p(n):n),{r:i,g:s,b:n,a:o}}}(t):C(t)}class F{constructor(t){if(t instanceof F)return t;const e=typeof t;let i;var s,n,o;"object"===e?i=I(t):"string"===e&&(o=(s=t).length,"#"===s[0]&&(4===o||5===o?n={r:255&17*r[s[1]],g:255&17*r[s[2]],b:255&17*r[s[3]],a:5===o?17*r[s[4]]:255}:7!==o&&9!==o||(n={r:r[s[1]]<<4|r[s[2]],g:r[s[3]]<<4|r[s[4]],b:r[s[5]]<<4|r[s[6]],a:9===o?r[s[7]]<<4|r[s[8]]:255})),i=n||L(t)||z(t)),this._rgb=i,this._valid=!!i}get valid(){return this._valid}get rgb(){var t=E(this._rgb);return t&&(t.a=x(t.a)),t}set rgb(t){this._rgb=I(t)}rgbString(){return this._valid?(t=this._rgb)&&(t.a<255?`rgba(${t.r}, ${t.g}, ${t.b}, ${x(t.a)})`:`rgb(${t.r}, ${t.g}, ${t.b})`):this._rgb;var t}hexString(){return this._valid?u(this._rgb):this._rgb}hslString(){return this._valid?function(t){if(!t)return;const e=k(t),i=e[0],s=b(e[1]),n=b(e[2]);return t.a<255?`hsla(${i}, ${s}%, ${n}%, ${x(t.a)})`:`hsl(${i}, ${s}%, ${n}%)`}(this._rgb):this._rgb}mix(t,e){const i=this;if(t){const s=i.rgb,n=t.rgb;let o;const a=e===o?.5:e,r=2*a-1,l=s.a-n.a,h=((r*l==-1?r:(r+l)/(1+r*l))+1)/2;o=1-h,s.r=255&h*s.r+o*n.r+.5,s.g=255&h*s.g+o*n.g+.5,s.b=255&h*s.b+o*n.b+.5,s.a=a*s.a+(1-a)*n.a,i.rgb=s}return i}clone(){return new F(this.rgb)}alpha(t){return this._rgb.a=m(t),this}clearer(t){return this._rgb.a*=1-t,this}greyscale(){const t=this._rgb,e=f(.3*t.r+.59*t.g+.11*t.b);return t.r=t.g=t.b=e,this}opaquer(t){return this._rgb.a*=1+t,this}negate(){const t=this._rgb;return t.r=255-t.r,t.g=255-t.g,t.b=255-t.b,this}lighten(t){return R(this._rgb,2,t),this}darken(t){return R(this._rgb,2,-t),this}saturate(t){return R(this._rgb,1,t),this}desaturate(t){return R(this._rgb,1,-t),this}rotate(t){return function(t,e){var i=k(t);i[0]=D(i[0]+e),i=P(i),t.r=i[0],t.g=i[1],t.b=i[2]}(this._rgb,t),this}}function B(t){return new F(t)}const V=t=>t instanceof CanvasGradient||t instanceof CanvasPattern;function W(t){return V(t)?t:B(t)}function N(t){return V(t)?t:B(t).saturate(.5).darken(.1).hexString()}function H(){}const j=function(){let t=0;return function(){return t++}}();function $(t){return null==t}function Y(t){if(Array.isArray&&Array.isArray(t))return!0;const e=Object.prototype.toString.call(t);return"[object"===e.substr(0,7)&&"Array]"===e.substr(-6)}function U(t){return null!==t&&"[object Object]"===Object.prototype.toString.call(t)}const X=t=>("number"==typeof t||t instanceof Number)&&isFinite(+t);function q(t,e){return X(t)?t:e}function K(t,e){return void 0===t?e:t}const G=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100:t/e,Z=(t,e)=>"string"==typeof t&&t.endsWith("%")?parseFloat(t)/100*e:+t;function Q(t,e,i){if(t&&"function"==typeof t.call)return t.apply(i,e)}function J(t,e,i,s){let n,o,a;if(Y(t))if(o=t.length,s)for(n=o-1;n>=0;n--)e.call(i,t[n],n);else for(n=0;n<o;n++)e.call(i,t[n],n);else if(U(t))for(a=Object.keys(t),o=a.length,n=0;n<o;n++)e.call(i,t[a[n]],a[n])}function tt(t,e){let i,s,n,o;if(!t||!e||t.length!==e.length)return!1;for(i=0,s=t.length;i<s;++i)if(n=t[i],o=e[i],n.datasetIndex!==o.datasetIndex||n.index!==o.index)return!1;return!0}function et(t){if(Y(t))return t.map(et);if(U(t)){const e=Object.create(null),i=Object.keys(t),s=i.length;let n=0;for(;n<s;++n)e[i[n]]=et(t[i[n]]);return e}return t}function it(t){return-1===["__proto__","prototype","constructor"].indexOf(t)}function st(t,e,i,s){if(!it(t))return;const n=e[t],o=i[t];U(n)&&U(o)?nt(n,o,s):e[t]=et(o)}function nt(t,e,i){const s=Y(e)?e:[e],n=s.length;if(!U(t))return t;const o=(i=i||{}).merger||st;for(let a=0;a<n;++a){if(!U(e=s[a]))continue;const n=Object.keys(e);for(let s=0,a=n.length;s<a;++s)o(n[s],t,e,i)}return t}function ot(t,e){return nt(t,e,{merger:at})}function at(t,e,i){if(!it(t))return;const s=e[t],n=i[t];U(s)&&U(n)?ot(s,n):Object.prototype.hasOwnProperty.call(e,t)||(e[t]=et(n))}function rt(t,e){const i=t.indexOf(".",e);return-1===i?t.length:i}function lt(t,e){if(""===e)return t;let i=0,s=rt(e,i);for(;t&&s>i;)t=t[e.substr(i,s-i)],i=s+1,s=rt(e,i);return t}function ht(t){return t.charAt(0).toUpperCase()+t.slice(1)}const ct=t=>void 0!==t,dt=t=>"function"==typeof t,ut=(t,e)=>{if(t.size!==e.size)return!1;for(const i of t)if(!e.has(i))return!1;return!0},ft=Object.create(null),gt=Object.create(null);function pt(t,e){if(!e)return t;const i=e.split(".");for(let e=0,s=i.length;e<s;++e){const s=i[e];t=t[s]||(t[s]=Object.create(null))}return t}function mt(t,e,i){return"string"==typeof e?nt(pt(t,e),i):nt(pt(t,""),e)}var xt=new class{constructor(t){this.animation=void 0,this.backgroundColor="rgba(0,0,0,0.1)",this.borderColor="rgba(0,0,0,0.1)",this.color="#666",this.datasets={},this.devicePixelRatio=t=>t.chart.platform.getDevicePixelRatio(),this.elements={},this.events=["mousemove","mouseout","click","touchstart","touchmove"],this.font={family:"'Helvetica Neue', 'Helvetica', 'Arial', sans-serif",size:12,style:"normal",lineHeight:1.2,weight:null},this.hover={},this.hoverBackgroundColor=(t,e)=>N(e.backgroundColor),this.hoverBorderColor=(t,e)=>N(e.borderColor),this.hoverColor=(t,e)=>N(e.color),this.indexAxis="x",this.interaction={mode:"nearest",intersect:!0},this.maintainAspectRatio=!0,this.onHover=null,this.onClick=null,this.parsing=!0,this.plugins={},this.responsive=!0,this.scale=void 0,this.scales={},this.showLine=!0,this.describe(t)}set(t,e){return mt(this,t,e)}get(t){return pt(this,t)}describe(t,e){return mt(gt,t,e)}override(t,e){return mt(ft,t,e)}route(t,e,i,s){const n=pt(this,t),o=pt(this,i),a="_"+e;Object.defineProperties(n,{[a]:{value:n[e],writable:!0},[e]:{enumerable:!0,get(){const t=this[a],e=o[s];return U(t)?Object.assign({},e,t):K(t,e)},set(t){this[a]=t}}})}}({_scriptable:t=>!t.startsWith("on"),_indexable:t=>"events"!==t,hover:{_fallback:"interaction"},interaction:{_scriptable:!1,_indexable:!1}});const bt=Math.PI,_t=2*bt,yt=_t+bt,vt=Number.POSITIVE_INFINITY,wt=bt/180,Mt=bt/2,kt=bt/4,St=2*bt/3,Pt=Math.log10,Dt=Math.sign;function Ct(t){const e=Math.round(t);t=Tt(t,e,t/1e3)?e:t;const i=Math.pow(10,Math.floor(Pt(t))),s=t/i;return(s<=1?1:s<=2?2:s<=5?5:10)*i}function Ot(t){const e=[],i=Math.sqrt(t);let s;for(s=1;s<i;s++)t%s==0&&(e.push(s),e.push(t/s));return i===(0|i)&&e.push(i),e.sort(((t,e)=>t-e)).pop(),e}function At(t){return!isNaN(parseFloat(t))&&isFinite(t)}function Tt(t,e,i){return Math.abs(t-e)<i}function Lt(t,e){const i=Math.round(t);return i-e<=t&&i+e>=t}function Rt(t,e,i){let s,n,o;for(s=0,n=t.length;s<n;s++)o=t[s][i],isNaN(o)||(e.min=Math.min(e.min,o),e.max=Math.max(e.max,o))}function Et(t){return t*(bt/180)}function It(t){return t*(180/bt)}function zt(t){if(!X(t))return;let e=1,i=0;for(;Math.round(t*e)/e!==t;)e*=10,i++;return i}function Ft(t,e){const i=e.x-t.x,s=e.y-t.y,n=Math.sqrt(i*i+s*s);let o=Math.atan2(s,i);return o<-.5*bt&&(o+=_t),{angle:o,distance:n}}function Bt(t,e){return Math.sqrt(Math.pow(e.x-t.x,2)+Math.pow(e.y-t.y,2))}function Vt(t,e){return(t-e+yt)%_t-bt}function Wt(t){return(t%_t+_t)%_t}function Nt(t,e,i,s){const n=Wt(t),o=Wt(e),a=Wt(i),r=Wt(o-n),l=Wt(a-n),h=Wt(n-o),c=Wt(n-a);return n===o||n===a||s&&o===a||r>l&&h<c}function Ht(t,e,i){return Math.max(e,Math.min(i,t))}function jt(t){return Ht(t,-32768,32767)}function $t(t){return!t||$(t.size)||$(t.family)?null:(t.style?t.style+" ":"")+(t.weight?t.weight+" ":"")+t.size+"px "+t.family}function Yt(t,e,i,s,n){let o=e[n];return o||(o=e[n]=t.measureText(n).width,i.push(n)),o>s&&(s=o),s}function Ut(t,e,i,s){let n=(s=s||{}).data=s.data||{},o=s.garbageCollect=s.garbageCollect||[];s.font!==e&&(n=s.data={},o=s.garbageCollect=[],s.font=e),t.save(),t.font=e;let a=0;const r=i.length;let l,h,c,d,u;for(l=0;l<r;l++)if(d=i[l],null!=d&&!0!==Y(d))a=Yt(t,n,o,a,d);else if(Y(d))for(h=0,c=d.length;h<c;h++)u=d[h],null==u||Y(u)||(a=Yt(t,n,o,a,u));t.restore();const f=o.length/2;if(f>i.length){for(l=0;l<f;l++)delete n[o[l]];o.splice(0,f)}return a}function Xt(t,e,i){const s=t.currentDevicePixelRatio,n=0!==i?Math.max(i/2,.5):0;return Math.round((e-n)*s)/s+n}function qt(t,e){(e=e||t.getContext("2d")).save(),e.resetTransform(),e.clearRect(0,0,t.width,t.height),e.restore()}function Kt(t,e,i,s){let n,o,a,r,l;const h=e.pointStyle,c=e.rotation,d=e.radius;let u=(c||0)*wt;if(h&&"object"==typeof h&&(n=h.toString(),"[object HTMLImageElement]"===n||"[object HTMLCanvasElement]"===n))return t.save(),t.translate(i,s),t.rotate(u),t.drawImage(h,-h.width/2,-h.height/2,h.width,h.height),void t.restore();if(!(isNaN(d)||d<=0)){switch(t.beginPath(),h){default:t.arc(i,s,d,0,_t),t.closePath();break;case"triangle":t.moveTo(i+Math.sin(u)*d,s-Math.cos(u)*d),u+=St,t.lineTo(i+Math.sin(u)*d,s-Math.cos(u)*d),u+=St,t.lineTo(i+Math.sin(u)*d,s-Math.cos(u)*d),t.closePath();break;case"rectRounded":l=.516*d,r=d-l,o=Math.cos(u+kt)*r,a=Math.sin(u+kt)*r,t.arc(i-o,s-a,l,u-bt,u-Mt),t.arc(i+a,s-o,l,u-Mt,u),t.arc(i+o,s+a,l,u,u+Mt),t.arc(i-a,s+o,l,u+Mt,u+bt),t.closePath();break;case"rect":if(!c){r=Math.SQRT1_2*d,t.rect(i-r,s-r,2*r,2*r);break}u+=kt;case"rectRot":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+a,s-o),t.lineTo(i+o,s+a),t.lineTo(i-a,s+o),t.closePath();break;case"crossRot":u+=kt;case"cross":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a),t.moveTo(i+a,s-o),t.lineTo(i-a,s+o);break;case"star":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a),t.moveTo(i+a,s-o),t.lineTo(i-a,s+o),u+=kt,o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a),t.moveTo(i+a,s-o),t.lineTo(i-a,s+o);break;case"line":o=Math.cos(u)*d,a=Math.sin(u)*d,t.moveTo(i-o,s-a),t.lineTo(i+o,s+a);break;case"dash":t.moveTo(i,s),t.lineTo(i+Math.cos(u)*d,s+Math.sin(u)*d)}t.fill(),e.borderWidth>0&&t.stroke()}}function Gt(t,e,i){return i=i||.5,!e||t&&t.x>e.left-i&&t.x<e.right+i&&t.y>e.top-i&&t.y<e.bottom+i}function Zt(t,e){t.save(),t.beginPath(),t.rect(e.left,e.top,e.right-e.left,e.bottom-e.top),t.clip()}function Qt(t){t.restore()}function Jt(t,e,i,s,n){if(!e)return t.lineTo(i.x,i.y);if("middle"===n){const s=(e.x+i.x)/2;t.lineTo(s,e.y),t.lineTo(s,i.y)}else"after"===n!=!!s?t.lineTo(e.x,i.y):t.lineTo(i.x,e.y);t.lineTo(i.x,i.y)}function te(t,e,i,s){if(!e)return t.lineTo(i.x,i.y);t.bezierCurveTo(s?e.cp1x:e.cp2x,s?e.cp1y:e.cp2y,s?i.cp2x:i.cp1x,s?i.cp2y:i.cp1y,i.x,i.y)}function ee(t,e,i,s,n,o={}){const a=Y(e)?e:[e],r=o.strokeWidth>0&&""!==o.strokeColor;let l,h;for(t.save(),t.font=n.string,function(t,e){e.translation&&t.translate(e.translation[0],e.translation[1]);$(e.rotation)||t.rotate(e.rotation);e.color&&(t.fillStyle=e.color);e.textAlign&&(t.textAlign=e.textAlign);e.textBaseline&&(t.textBaseline=e.textBaseline)}(t,o),l=0;l<a.length;++l)h=a[l],r&&(o.strokeColor&&(t.strokeStyle=o.strokeColor),$(o.strokeWidth)||(t.lineWidth=o.strokeWidth),t.strokeText(h,i,s,o.maxWidth)),t.fillText(h,i,s,o.maxWidth),ie(t,i,s,h,o),s+=n.lineHeight;t.restore()}function ie(t,e,i,s,n){if(n.strikethrough||n.underline){const o=t.measureText(s),a=e-o.actualBoundingBoxLeft,r=e+o.actualBoundingBoxRight,l=i-o.actualBoundingBoxAscent,h=i+o.actualBoundingBoxDescent,c=n.strikethrough?(l+h)/2:h;t.strokeStyle=t.fillStyle,t.beginPath(),t.lineWidth=n.decorationWidth||2,t.moveTo(a,c),t.lineTo(r,c),t.stroke()}}function se(t,e){const{x:i,y:s,w:n,h:o,radius:a}=e;t.arc(i+a.topLeft,s+a.topLeft,a.topLeft,-Mt,bt,!0),t.lineTo(i,s+o-a.bottomLeft),t.arc(i+a.bottomLeft,s+o-a.bottomLeft,a.bottomLeft,bt,Mt,!0),t.lineTo(i+n-a.bottomRight,s+o),t.arc(i+n-a.bottomRight,s+o-a.bottomRight,a.bottomRight,Mt,0,!0),t.lineTo(i+n,s+a.topRight),t.arc(i+n-a.topRight,s+a.topRight,a.topRight,0,-Mt,!0),t.lineTo(i+a.topLeft,s)}function ne(t,e,i){i=i||(i=>t[i]<e);let s,n=t.length-1,o=0;for(;n-o>1;)s=o+n>>1,i(s)?o=s:n=s;return{lo:o,hi:n}}const oe=(t,e,i)=>ne(t,i,(s=>t[s][e]<i)),ae=(t,e,i)=>ne(t,i,(s=>t[s][e]>=i));function re(t,e,i){let s=0,n=t.length;for(;s<n&&t[s]<e;)s++;for(;n>s&&t[n-1]>i;)n--;return s>0||n<t.length?t.slice(s,n):t}const le=["push","pop","shift","splice","unshift"];function he(t,e){t._chartjs?t._chartjs.listeners.push(e):(Object.defineProperty(t,"_chartjs",{configurable:!0,enumerable:!1,value:{listeners:[e]}}),le.forEach((e=>{const i="_onData"+ht(e),s=t[e];Object.defineProperty(t,e,{configurable:!0,enumerable:!1,value(...e){const n=s.apply(this,e);return t._chartjs.listeners.forEach((t=>{"function"==typeof t[i]&&t[i](...e)})),n}})})))}function ce(t,e){const i=t._chartjs;if(!i)return;const s=i.listeners,n=s.indexOf(e);-1!==n&&s.splice(n,1),s.length>0||(le.forEach((e=>{delete t[e]})),delete t._chartjs)}function de(t){const e=new Set;let i,s;for(i=0,s=t.length;i<s;++i)e.add(t[i]);return e.size===s?t:Array.from(e)}function ue(){return"undefined"!=typeof window&&"undefined"!=typeof document}function fe(t){let e=t.parentNode;return e&&"[object ShadowRoot]"===e.toString()&&(e=e.host),e}function ge(t,e,i){let s;return"string"==typeof t?(s=parseInt(t,10),-1!==t.indexOf("%")&&(s=s/100*e.parentNode[i])):s=t,s}const pe=t=>window.getComputedStyle(t,null);function me(t,e){return pe(t).getPropertyValue(e)}const xe=["top","right","bottom","left"];function be(t,e,i){const s={};i=i?"-"+i:"";for(let n=0;n<4;n++){const o=xe[n];s[o]=parseFloat(t[e+"-"+o+i])||0}return s.width=s.left+s.right,s.height=s.top+s.bottom,s}function _e(t,e){const{canvas:i,currentDevicePixelRatio:s}=e,n=pe(i),o="border-box"===n.boxSizing,a=be(n,"padding"),r=be(n,"border","width"),{x:l,y:h,box:c}=function(t,e){const i=t.native||t,s=i.touches,n=s&&s.length?s[0]:i,{offsetX:o,offsetY:a}=n;let r,l,h=!1;if(((t,e,i)=>(t>0||e>0)&&(!i||!i.shadowRoot))(o,a,i.target))r=o,l=a;else{const t=e.getBoundingClientRect();r=n.clientX-t.left,l=n.clientY-t.top,h=!0}return{x:r,y:l,box:h}}(t,i),d=a.left+(c&&r.left),u=a.top+(c&&r.top);let{width:f,height:g}=e;return o&&(f-=a.width+r.width,g-=a.height+r.height),{x:Math.round((l-d)/f*i.width/s),y:Math.round((h-u)/g*i.height/s)}}const ye=t=>Math.round(10*t)/10;function ve(t,e,i,s){const n=pe(t),o=be(n,"margin"),a=ge(n.maxWidth,t,"clientWidth")||vt,r=ge(n.maxHeight,t,"clientHeight")||vt,l=function(t,e,i){let s,n;if(void 0===e||void 0===i){const o=fe(t);if(o){const t=o.getBoundingClientRect(),a=pe(o),r=be(a,"border","width"),l=be(a,"padding");e=t.width-l.width-r.width,i=t.height-l.height-r.height,s=ge(a.maxWidth,o,"clientWidth"),n=ge(a.maxHeight,o,"clientHeight")}else e=t.clientWidth,i=t.clientHeight}return{width:e,height:i,maxWidth:s||vt,maxHeight:n||vt}}(t,e,i);let{width:h,height:c}=l;if("content-box"===n.boxSizing){const t=be(n,"border","width"),e=be(n,"padding");h-=e.width+t.width,c-=e.height+t.height}return h=Math.max(0,h-o.width),c=Math.max(0,s?Math.floor(h/s):c-o.height),h=ye(Math.min(h,a,l.maxWidth)),c=ye(Math.min(c,r,l.maxHeight)),h&&!c&&(c=ye(h/2)),{width:h,height:c}}function we(t,e,i){const s=e||1,n=Math.floor(t.height*s),o=Math.floor(t.width*s);t.height=n/s,t.width=o/s;const a=t.canvas;return a.style&&(i||!a.style.height&&!a.style.width)&&(a.style.height=`${t.height}px`,a.style.width=`${t.width}px`),(t.currentDevicePixelRatio!==s||a.height!==n||a.width!==o)&&(t.currentDevicePixelRatio=s,a.height=n,a.width=o,t.ctx.setTransform(s,0,0,s,0,0),!0)}const Me=function(){let t=!1;try{const e={get passive(){return t=!0,!1}};window.addEventListener("test",null,e),window.removeEventListener("test",null,e)}catch(t){}return t}();function ke(t,e){const i=me(t,e),s=i&&i.match(/^(\d+)(\.\d+)?px$/);return s?+s[1]:void 0}function Se(t,e){return"native"in t?{x:t.x,y:t.y}:_e(t,e)}function Pe(t,e,i,s){const{controller:n,data:o,_sorted:a}=t,r=n._cachedMeta.iScale;if(r&&e===r.axis&&a&&o.length){const t=r._reversePixels?ae:oe;if(!s)return t(o,e,i);if(n._sharedOptions){const s=o[0],n="function"==typeof s.getRange&&s.getRange(e);if(n){const s=t(o,e,i-n),a=t(o,e,i+n);return{lo:s.lo,hi:a.hi}}}}return{lo:0,hi:o.length-1}}function De(t,e,i,s,n){const o=t.getSortedVisibleDatasetMetas(),a=i[e];for(let t=0,i=o.length;t<i;++t){const{index:i,data:r}=o[t],{lo:l,hi:h}=Pe(o[t],e,a,n);for(let t=l;t<=h;++t){const e=r[t];e.skip||s(e,i,t)}}}function Ce(t,e,i,s){const n=[];if(!Gt(e,t.chartArea,t._minPadding))return n;return De(t,i,e,(function(t,i,o){t.inRange(e.x,e.y,s)&&n.push({element:t,datasetIndex:i,index:o})}),!0),n}function Oe(t,e,i,s,n){const o=function(t){const e=-1!==t.indexOf("x"),i=-1!==t.indexOf("y");return function(t,s){const n=e?Math.abs(t.x-s.x):0,o=i?Math.abs(t.y-s.y):0;return Math.sqrt(Math.pow(n,2)+Math.pow(o,2))}}(i);let a=Number.POSITIVE_INFINITY,r=[];if(!Gt(e,t.chartArea,t._minPadding))return r;return De(t,i,e,(function(i,l,h){if(s&&!i.inRange(e.x,e.y,n))return;const c=i.getCenterPoint(n);if(!Gt(c,t.chartArea,t._minPadding)&&!i.inRange(e.x,e.y,n))return;const d=o(e,c);d<a?(r=[{element:i,datasetIndex:l,index:h}],a=d):d===a&&r.push({element:i,datasetIndex:l,index:h})})),r}function Ae(t,e,i,s){const n=Se(e,t),o=[],a=i.axis,r="x"===a?"inXRange":"inYRange";let l=!1;return function(t,e){const i=t.getSortedVisibleDatasetMetas();let s,n,o;for(let t=0,a=i.length;t<a;++t){({index:s,data:n}=i[t]);for(let t=0,i=n.length;t<i;++t)o=n[t],o.skip||e(o,s,t)}}(t,((t,e,i)=>{t[r](n[a],s)&&o.push({element:t,datasetIndex:e,index:i}),t.inRange(n.x,n.y,s)&&(l=!0)})),i.intersect&&!l?[]:o}var Te={modes:{index(t,e,i,s){const n=Se(e,t),o=i.axis||"x",a=i.intersect?Ce(t,n,o,s):Oe(t,n,o,!1,s),r=[];return a.length?(t.getSortedVisibleDatasetMetas().forEach((t=>{const e=a[0].index,i=t.data[e];i&&!i.skip&&r.push({element:i,datasetIndex:t.index,index:e})})),r):[]},dataset(t,e,i,s){const n=Se(e,t),o=i.axis||"xy";let a=i.intersect?Ce(t,n,o,s):Oe(t,n,o,!1,s);if(a.length>0){const e=a[0].datasetIndex,i=t.getDatasetMeta(e).data;a=[];for(let t=0;t<i.length;++t)a.push({element:i[t],datasetIndex:e,index:t})}return a},point:(t,e,i,s)=>Ce(t,Se(e,t),i.axis||"xy",s),nearest:(t,e,i,s)=>Oe(t,Se(e,t),i.axis||"xy",i.intersect,s),x:(t,e,i,s)=>(i.axis="x",Ae(t,e,i,s)),y:(t,e,i,s)=>(i.axis="y",Ae(t,e,i,s))}};const Le=new RegExp(/^(normal|(\d+(?:\.\d+)?)(px|em|%)?)$/),Re=new RegExp(/^(normal|italic|initial|inherit|unset|(oblique( -?[0-9]?[0-9]deg)?))$/);function Ee(t,e){const i=(""+t).match(Le);if(!i||"normal"===i[1])return 1.2*e;switch(t=+i[2],i[3]){case"px":return t;case"%":t/=100}return e*t}function Ie(t,e){const i={},s=U(e),n=s?Object.keys(e):e,o=U(t)?s?i=>K(t[i],t[e[i]]):e=>t[e]:()=>t;for(const t of n)i[t]=+o(t)||0;return i}function ze(t){return Ie(t,{top:"y",right:"x",bottom:"y",left:"x"})}function Fe(t){return Ie(t,["topLeft","topRight","bottomLeft","bottomRight"])}function Be(t){const e=ze(t);return e.width=e.left+e.right,e.height=e.top+e.bottom,e}function Ve(t,e){t=t||{},e=e||xt.font;let i=K(t.size,e.size);"string"==typeof i&&(i=parseInt(i,10));let s=K(t.style,e.style);s&&!(""+s).match(Re)&&(console.warn('Invalid font style specified: "'+s+'"'),s="");const n={family:K(t.family,e.family),lineHeight:Ee(K(t.lineHeight,e.lineHeight),i),size:i,style:s,weight:K(t.weight,e.weight),string:""};return n.string=$t(n),n}function We(t,e,i,s){let n,o,a,r=!0;for(n=0,o=t.length;n<o;++n)if(a=t[n],void 0!==a&&(void 0!==e&&"function"==typeof a&&(a=a(e),r=!1),void 0!==i&&Y(a)&&(a=a[i%a.length],r=!1),void 0!==a))return s&&!r&&(s.cacheable=!1),a}function Ne(t,e,i){const{min:s,max:n}=t,o=Z(e,(n-s)/2),a=(t,e)=>i&&0===t?0:t+e;return{min:a(s,-Math.abs(o)),max:a(n,o)}}function He(t,e){return Object.assign(Object.create(t),e)}const je=["left","top","right","bottom"];function $e(t,e){return t.filter((t=>t.pos===e))}function Ye(t,e){return t.filter((t=>-1===je.indexOf(t.pos)&&t.box.axis===e))}function Ue(t,e){return t.sort(((t,i)=>{const s=e?i:t,n=e?t:i;return s.weight===n.weight?s.index-n.index:s.weight-n.weight}))}function Xe(t,e){const i=function(t){const e={};for(const i of t){const{stack:t,pos:s,stackWeight:n}=i;if(!t||!je.includes(s))continue;const o=e[t]||(e[t]={count:0,placed:0,weight:0,size:0});o.count++,o.weight+=n}return e}(t),{vBoxMaxWidth:s,hBoxMaxHeight:n}=e;let o,a,r;for(o=0,a=t.length;o<a;++o){r=t[o];const{fullSize:a}=r.box,l=i[r.stack],h=l&&r.stackWeight/l.weight;r.horizontal?(r.width=h?h*s:a&&e.availableWidth,r.height=n):(r.width=s,r.height=h?h*n:a&&e.availableHeight)}return i}function qe(t,e,i,s){return Math.max(t[i],e[i])+Math.max(t[s],e[s])}function Ke(t,e){t.top=Math.max(t.top,e.top),t.left=Math.max(t.left,e.left),t.bottom=Math.max(t.bottom,e.bottom),t.right=Math.max(t.right,e.right)}function Ge(t,e,i,s){const{pos:n,box:o}=i,a=t.maxPadding;if(!U(n)){i.size&&(t[n]-=i.size);const e=s[i.stack]||{size:0,count:1};e.size=Math.max(e.size,i.horizontal?o.height:o.width),i.size=e.size/e.count,t[n]+=i.size}o.getPadding&&Ke(a,o.getPadding());const r=Math.max(0,e.outerWidth-qe(a,t,"left","right")),l=Math.max(0,e.outerHeight-qe(a,t,"top","bottom")),h=r!==t.w,c=l!==t.h;return t.w=r,t.h=l,i.horizontal?{same:h,other:c}:{same:c,other:h}}function Ze(t,e){const i=e.maxPadding;function s(t){const s={left:0,top:0,right:0,bottom:0};return t.forEach((t=>{s[t]=Math.max(e[t],i[t])})),s}return s(t?["left","right"]:["top","bottom"])}function Qe(t,e,i,s){const n=[];let o,a,r,l,h,c;for(o=0,a=t.length,h=0;o<a;++o){r=t[o],l=r.box,l.update(r.width||e.w,r.height||e.h,Ze(r.horizontal,e));const{same:a,other:d}=Ge(e,i,r,s);h|=a&&n.length,c=c||d,l.fullSize||n.push(r)}return h&&Qe(n,e,i,s)||c}function Je(t,e,i,s,n){t.top=i,t.left=e,t.right=e+s,t.bottom=i+n,t.width=s,t.height=n}function ti(t,e,i,s){const n=i.padding;let{x:o,y:a}=e;for(const r of t){const t=r.box,l=s[r.stack]||{count:1,placed:0,weight:1},h=r.stackWeight/l.weight||1;if(r.horizontal){const s=e.w*h,o=l.size||t.height;ct(l.start)&&(a=l.start),t.fullSize?Je(t,n.left,a,i.outerWidth-n.right-n.left,o):Je(t,e.left+l.placed,a,s,o),l.start=a,l.placed+=s,a=t.bottom}else{const s=e.h*h,a=l.size||t.width;ct(l.start)&&(o=l.start),t.fullSize?Je(t,o,n.top,a,i.outerHeight-n.bottom-n.top):Je(t,o,e.top+l.placed,a,s),l.start=o,l.placed+=s,o=t.right}}e.x=o,e.y=a}xt.set("layout",{autoPadding:!0,padding:{top:0,right:0,bottom:0,left:0}});var ei={addBox(t,e){t.boxes||(t.boxes=[]),e.fullSize=e.fullSize||!1,e.position=e.position||"top",e.weight=e.weight||0,e._layers=e._layers||function(){return[{z:0,draw(t){e.draw(t)}}]},t.boxes.push(e)},removeBox(t,e){const i=t.boxes?t.boxes.indexOf(e):-1;-1!==i&&t.boxes.splice(i,1)},configure(t,e,i){e.fullSize=i.fullSize,e.position=i.position,e.weight=i.weight},update(t,e,i,s){if(!t)return;const n=Be(t.options.layout.padding),o=Math.max(e-n.width,0),a=Math.max(i-n.height,0),r=function(t){const e=function(t){const e=[];let i,s,n,o,a,r;for(i=0,s=(t||[]).length;i<s;++i)n=t[i],({position:o,options:{stack:a,stackWeight:r=1}}=n),e.push({index:i,box:n,pos:o,horizontal:n.isHorizontal(),weight:n.weight,stack:a&&o+a,stackWeight:r});return e}(t),i=Ue(e.filter((t=>t.box.fullSize)),!0),s=Ue($e(e,"left"),!0),n=Ue($e(e,"right")),o=Ue($e(e,"top"),!0),a=Ue($e(e,"bottom")),r=Ye(e,"x"),l=Ye(e,"y");return{fullSize:i,leftAndTop:s.concat(o),rightAndBottom:n.concat(l).concat(a).concat(r),chartArea:$e(e,"chartArea"),vertical:s.concat(n).concat(l),horizontal:o.concat(a).concat(r)}}(t.boxes),l=r.vertical,h=r.horizontal;J(t.boxes,(t=>{"function"==typeof t.beforeLayout&&t.beforeLayout()}));const c=l.reduce(((t,e)=>e.box.options&&!1===e.box.options.display?t:t+1),0)||1,d=Object.freeze({outerWidth:e,outerHeight:i,padding:n,availableWidth:o,availableHeight:a,vBoxMaxWidth:o/2/c,hBoxMaxHeight:a/2}),u=Object.assign({},n);Ke(u,Be(s));const f=Object.assign({maxPadding:u,w:o,h:a,x:n.left,y:n.top},n),g=Xe(l.concat(h),d);Qe(r.fullSize,f,d,g),Qe(l,f,d,g),Qe(h,f,d,g)&&Qe(l,f,d,g),function(t){const e=t.maxPadding;function i(i){const s=Math.max(e[i]-t[i],0);return t[i]+=s,s}t.y+=i("top"),t.x+=i("left"),i("right"),i("bottom")}(f),ti(r.leftAndTop,f,d,g),f.x+=f.w,f.y+=f.h,ti(r.rightAndBottom,f,d,g),t.chartArea={left:f.left,top:f.top,right:f.left+f.w,bottom:f.top+f.h,height:f.h,width:f.w},J(r.chartArea,(e=>{const i=e.box;Object.assign(i,t.chartArea),i.update(f.w,f.h)}))}};function ii(t,e=[""],i=t,s,n=(()=>t[0])){ct(s)||(s=fi("_fallback",t));const o={[Symbol.toStringTag]:"Object",_cacheable:!0,_scopes:t,_rootScopes:i,_fallback:s,_getTarget:n,override:n=>ii([n,...t],e,i,s)};return new Proxy(o,{deleteProperty:(e,i)=>(delete e[i],delete e._keys,delete t[0][i],!0),get:(i,s)=>ri(i,s,(()=>function(t,e,i,s){let n;for(const o of e)if(n=fi(oi(o,t),i),ct(n))return ai(t,n)?di(i,s,t,n):n}(s,e,t,i))),getOwnPropertyDescriptor:(t,e)=>Reflect.getOwnPropertyDescriptor(t._scopes[0],e),getPrototypeOf:()=>Reflect.getPrototypeOf(t[0]),has:(t,e)=>gi(t).includes(e),ownKeys:t=>gi(t),set:(t,e,i)=>((t._storage||(t._storage=n()))[e]=i,delete t[e],delete t._keys,!0)})}function si(t,e,i,s){const n={_cacheable:!1,_proxy:t,_context:e,_subProxy:i,_stack:new Set,_descriptors:ni(t,s),setContext:e=>si(t,e,i,s),override:n=>si(t.override(n),e,i,s)};return new Proxy(n,{deleteProperty:(e,i)=>(delete e[i],delete t[i],!0),get:(t,e,i)=>ri(t,e,(()=>function(t,e,i){const{_proxy:s,_context:n,_subProxy:o,_descriptors:a}=t;let r=s[e];dt(r)&&a.isScriptable(e)&&(r=function(t,e,i,s){const{_proxy:n,_context:o,_subProxy:a,_stack:r}=i;if(r.has(t))throw new Error("Recursion detected: "+Array.from(r).join("->")+"->"+t);r.add(t),e=e(o,a||s),r.delete(t),U(e)&&(e=di(n._scopes,n,t,e));return e}(e,r,t,i));Y(r)&&r.length&&(r=function(t,e,i,s){const{_proxy:n,_context:o,_subProxy:a,_descriptors:r}=i;if(ct(o.index)&&s(t))e=e[o.index%e.length];else if(U(e[0])){const i=e,s=n._scopes.filter((t=>t!==i));e=[];for(const l of i){const i=di(s,n,t,l);e.push(si(i,o,a&&a[t],r))}}return e}(e,r,t,a.isIndexable));ai(e,r)&&(r=si(r,n,o&&o[e],a));return r}(t,e,i))),getOwnPropertyDescriptor:(e,i)=>e._descriptors.allKeys?Reflect.has(t,i)?{enumerable:!0,configurable:!0}:void 0:Reflect.getOwnPropertyDescriptor(t,i),getPrototypeOf:()=>Reflect.getPrototypeOf(t),has:(e,i)=>Reflect.has(t,i),ownKeys:()=>Reflect.ownKeys(t),set:(e,i,s)=>(t[i]=s,delete e[i],!0)})}function ni(t,e={scriptable:!0,indexable:!0}){const{_scriptable:i=e.scriptable,_indexable:s=e.indexable,_allKeys:n=e.allKeys}=t;return{allKeys:n,scriptable:i,indexable:s,isScriptable:dt(i)?i:()=>i,isIndexable:dt(s)?s:()=>s}}const oi=(t,e)=>t?t+ht(e):e,ai=(t,e)=>U(e)&&"adapters"!==t;function ri(t,e,i){if(Object.prototype.hasOwnProperty.call(t,e))return t[e];const s=i();return t[e]=s,s}function li(t,e,i){return dt(t)?t(e,i):t}const hi=(t,e)=>!0===t?e:"string"==typeof t?lt(e,t):void 0;function ci(t,e,i,s){for(const n of e){const e=hi(i,n);if(e){t.add(e);const n=li(e._fallback,i,e);if(ct(n)&&n!==i&&n!==s)return n}else if(!1===e&&ct(s)&&i!==s)return null}return!1}function di(t,e,i,s){const n=e._rootScopes,o=li(e._fallback,i,s),a=[...t,...n],r=new Set;r.add(s);let l=ui(r,a,i,o||i);return null!==l&&((!ct(o)||o===i||(l=ui(r,a,o,l),null!==l))&&ii(Array.from(r),[""],n,o,(()=>function(t,e,i){const s=t._getTarget();e in s||(s[e]={});const n=s[e];if(Y(n)&&U(i))return i;return n}(e,i,s))))}function ui(t,e,i,s){for(;i;)i=ci(t,e,i,s);return i}function fi(t,e){for(const i of e){if(!i)continue;const e=i[t];if(ct(e))return e}}function gi(t){let e=t._keys;return e||(e=t._keys=function(t){const e=new Set;for(const i of t)for(const t of Object.keys(i).filter((t=>!t.startsWith("_"))))e.add(t);return Array.from(e)}(t._scopes)),e}const pi=Number.EPSILON||1e-14,mi=(t,e)=>e<t.length&&!t[e].skip&&t[e],xi=t=>"x"===t?"y":"x";function bi(t,e,i,s){const n=t.skip?e:t,o=e,a=i.skip?e:i,r=Bt(o,n),l=Bt(a,o);let h=r/(r+l),c=l/(r+l);h=isNaN(h)?0:h,c=isNaN(c)?0:c;const d=s*h,u=s*c;return{previous:{x:o.x-d*(a.x-n.x),y:o.y-d*(a.y-n.y)},next:{x:o.x+u*(a.x-n.x),y:o.y+u*(a.y-n.y)}}}function _i(t,e="x"){const i=xi(e),s=t.length,n=Array(s).fill(0),o=Array(s);let a,r,l,h=mi(t,0);for(a=0;a<s;++a)if(r=l,l=h,h=mi(t,a+1),l){if(h){const t=h[e]-l[e];n[a]=0!==t?(h[i]-l[i])/t:0}o[a]=r?h?Dt(n[a-1])!==Dt(n[a])?0:(n[a-1]+n[a])/2:n[a-1]:n[a]}!function(t,e,i){const s=t.length;let n,o,a,r,l,h=mi(t,0);for(let c=0;c<s-1;++c)l=h,h=mi(t,c+1),l&&h&&(Tt(e[c],0,pi)?i[c]=i[c+1]=0:(n=i[c]/e[c],o=i[c+1]/e[c],r=Math.pow(n,2)+Math.pow(o,2),r<=9||(a=3/Math.sqrt(r),i[c]=n*a*e[c],i[c+1]=o*a*e[c])))}(t,n,o),function(t,e,i="x"){const s=xi(i),n=t.length;let o,a,r,l=mi(t,0);for(let h=0;h<n;++h){if(a=r,r=l,l=mi(t,h+1),!r)continue;const n=r[i],c=r[s];a&&(o=(n-a[i])/3,r[`cp1${i}`]=n-o,r[`cp1${s}`]=c-o*e[h]),l&&(o=(l[i]-n)/3,r[`cp2${i}`]=n+o,r[`cp2${s}`]=c+o*e[h])}}(t,o,e)}function yi(t,e,i){return Math.max(Math.min(t,i),e)}function vi(t,e,i,s,n){let o,a,r,l;if(e.spanGaps&&(t=t.filter((t=>!t.skip))),"monotone"===e.cubicInterpolationMode)_i(t,n);else{let i=s?t[t.length-1]:t[0];for(o=0,a=t.length;o<a;++o)r=t[o],l=bi(i,r,t[Math.min(o+1,a-(s?0:1))%a],e.tension),r.cp1x=l.previous.x,r.cp1y=l.previous.y,r.cp2x=l.next.x,r.cp2y=l.next.y,i=r}e.capBezierPoints&&function(t,e){let i,s,n,o,a,r=Gt(t[0],e);for(i=0,s=t.length;i<s;++i)a=o,o=r,r=i<s-1&&Gt(t[i+1],e),o&&(n=t[i],a&&(n.cp1x=yi(n.cp1x,e.left,e.right),n.cp1y=yi(n.cp1y,e.top,e.bottom)),r&&(n.cp2x=yi(n.cp2x,e.left,e.right),n.cp2y=yi(n.cp2y,e.top,e.bottom)))}(t,i)}const wi=t=>0===t||1===t,Mi=(t,e,i)=>-Math.pow(2,10*(t-=1))*Math.sin((t-e)*_t/i),ki=(t,e,i)=>Math.pow(2,-10*t)*Math.sin((t-e)*_t/i)+1,Si={linear:t=>t,easeInQuad:t=>t*t,easeOutQuad:t=>-t*(t-2),easeInOutQuad:t=>(t/=.5)<1?.5*t*t:-.5*(--t*(t-2)-1),easeInCubic:t=>t*t*t,easeOutCubic:t=>(t-=1)*t*t+1,easeInOutCubic:t=>(t/=.5)<1?.5*t*t*t:.5*((t-=2)*t*t+2),easeInQuart:t=>t*t*t*t,easeOutQuart:t=>-((t-=1)*t*t*t-1),easeInOutQuart:t=>(t/=.5)<1?.5*t*t*t*t:-.5*((t-=2)*t*t*t-2),easeInQuint:t=>t*t*t*t*t,easeOutQuint:t=>(t-=1)*t*t*t*t+1,easeInOutQuint:t=>(t/=.5)<1?.5*t*t*t*t*t:.5*((t-=2)*t*t*t*t+2),easeInSine:t=>1-Math.cos(t*Mt),easeOutSine:t=>Math.sin(t*Mt),easeInOutSine:t=>-.5*(Math.cos(bt*t)-1),easeInExpo:t=>0===t?0:Math.pow(2,10*(t-1)),easeOutExpo:t=>1===t?1:1-Math.pow(2,-10*t),easeInOutExpo:t=>wi(t)?t:t<.5?.5*Math.pow(2,10*(2*t-1)):.5*(2-Math.pow(2,-10*(2*t-1))),easeInCirc:t=>t>=1?t:-(Math.sqrt(1-t*t)-1),easeOutCirc:t=>Math.sqrt(1-(t-=1)*t),easeInOutCirc:t=>(t/=.5)<1?-.5*(Math.sqrt(1-t*t)-1):.5*(Math.sqrt(1-(t-=2)*t)+1),easeInElastic:t=>wi(t)?t:Mi(t,.075,.3),easeOutElastic:t=>wi(t)?t:ki(t,.075,.3),easeInOutElastic(t){const e=.1125;return wi(t)?t:t<.5?.5*Mi(2*t,e,.45):.5+.5*ki(2*t-1,e,.45)},easeInBack(t){const e=1.70158;return t*t*((e+1)*t-e)},easeOutBack(t){const e=1.70158;return(t-=1)*t*((e+1)*t+e)+1},easeInOutBack(t){let e=1.70158;return(t/=.5)<1?t*t*((1+(e*=1.525))*t-e)*.5:.5*((t-=2)*t*((1+(e*=1.525))*t+e)+2)},easeInBounce:t=>1-Si.easeOutBounce(1-t),easeOutBounce(t){const e=7.5625,i=2.75;return t<1/i?e*t*t:t<2/i?e*(t-=1.5/i)*t+.75:t<2.5/i?e*(t-=2.25/i)*t+.9375:e*(t-=2.625/i)*t+.984375},easeInOutBounce:t=>t<.5?.5*Si.easeInBounce(2*t):.5*Si.easeOutBounce(2*t-1)+.5};function Pi(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:t.y+i*(e.y-t.y)}}function Di(t,e,i,s){return{x:t.x+i*(e.x-t.x),y:"middle"===s?i<.5?t.y:e.y:"after"===s?i<1?t.y:e.y:i>0?e.y:t.y}}function Ci(t,e,i,s){const n={x:t.cp2x,y:t.cp2y},o={x:e.cp1x,y:e.cp1y},a=Pi(t,n,i),r=Pi(n,o,i),l=Pi(o,e,i),h=Pi(a,r,i),c=Pi(r,l,i);return Pi(h,c,i)}const Oi=new Map;function Ai(t,e,i){return function(t,e){e=e||{};const i=t+JSON.stringify(e);let s=Oi.get(i);return s||(s=new Intl.NumberFormat(t,e),Oi.set(i,s)),s}(e,i).format(t)}function Ti(t,e,i){return t?function(t,e){return{x:i=>t+t+e-i,setWidth(t){e=t},textAlign:t=>"center"===t?t:"right"===t?"left":"right",xPlus:(t,e)=>t-e,leftForLtr:(t,e)=>t-e}}(e,i):{x:t=>t,setWidth(t){},textAlign:t=>t,xPlus:(t,e)=>t+e,leftForLtr:(t,e)=>t}}function Li(t,e){let i,s;"ltr"!==e&&"rtl"!==e||(i=t.canvas.style,s=[i.getPropertyValue("direction"),i.getPropertyPriority("direction")],i.setProperty("direction",e,"important"),t.prevTextDirection=s)}function Ri(t,e){void 0!==e&&(delete t.prevTextDirection,t.canvas.style.setProperty("direction",e[0],e[1]))}function Ei(t){return"angle"===t?{between:Nt,compare:Vt,normalize:Wt}:{between:(t,e,i)=>t>=Math.min(e,i)&&t<=Math.max(i,e),compare:(t,e)=>t-e,normalize:t=>t}}function Ii({start:t,end:e,count:i,loop:s,style:n}){return{start:t%i,end:e%i,loop:s&&(e-t+1)%i==0,style:n}}function zi(t,e,i){if(!i)return[t];const{property:s,start:n,end:o}=i,a=e.length,{compare:r,between:l,normalize:h}=Ei(s),{start:c,end:d,loop:u,style:f}=function(t,e,i){const{property:s,start:n,end:o}=i,{between:a,normalize:r}=Ei(s),l=e.length;let h,c,{start:d,end:u,loop:f}=t;if(f){for(d+=l,u+=l,h=0,c=l;h<c&&a(r(e[d%l][s]),n,o);++h)d--,u--;d%=l,u%=l}return u<d&&(u+=l),{start:d,end:u,loop:f,style:t.style}}(t,e,i),g=[];let p,m,x,b=!1,_=null;const y=()=>b||l(n,x,p)&&0!==r(n,x),v=()=>!b||0===r(o,p)||l(o,x,p);for(let t=c,i=c;t<=d;++t)m=e[t%a],m.skip||(p=h(m[s]),p!==x&&(b=l(p,n,o),null===_&&y()&&(_=0===r(p,n)?t:i),null!==_&&v()&&(g.push(Ii({start:_,end:t,loop:u,count:a,style:f})),_=null),i=t,x=p));return null!==_&&g.push(Ii({start:_,end:d,loop:u,count:a,style:f})),g}function Fi(t,e){const i=[],s=t.segments;for(let n=0;n<s.length;n++){const o=zi(s[n],t.points,e);o.length&&i.push(...o)}return i}function Bi(t,e){const i=t.points,s=t.options.spanGaps,n=i.length;if(!n)return[];const o=!!t._loop,{start:a,end:r}=function(t,e,i,s){let n=0,o=e-1;if(i&&!s)for(;n<e&&!t[n].skip;)n++;for(;n<e&&t[n].skip;)n++;for(n%=e,i&&(o+=n);o>n&&t[o%e].skip;)o--;return o%=e,{start:n,end:o}}(i,n,o,s);if(!0===s)return Vi(t,[{start:a,end:r,loop:o}],i,e);return Vi(t,function(t,e,i,s){const n=t.length,o=[];let a,r=e,l=t[e];for(a=e+1;a<=i;++a){const i=t[a%n];i.skip||i.stop?l.skip||(s=!1,o.push({start:e%n,end:(a-1)%n,loop:s}),e=r=i.stop?a:null):(r=a,l.skip&&(e=a)),l=i}return null!==r&&o.push({start:e%n,end:r%n,loop:s}),o}(i,a,r<a?r+n:r,!!t._fullLoop&&0===a&&r===n-1),i,e)}function Vi(t,e,i,s){return s&&s.setContext&&i?function(t,e,i,s){const n=t._chart.getContext(),o=Wi(t.options),{_datasetIndex:a,options:{spanGaps:r}}=t,l=i.length,h=[];let c=o,d=e[0].start,u=d;function f(t,e,s,n){const o=r?-1:1;if(t!==e){for(t+=l;i[t%l].skip;)t-=o;for(;i[e%l].skip;)e+=o;t%l!=e%l&&(h.push({start:t%l,end:e%l,loop:s,style:n}),c=n,d=e%l)}}for(const t of e){d=r?d:t.start;let e,o=i[d%l];for(u=d+1;u<=t.end;u++){const r=i[u%l];e=Wi(s.setContext(He(n,{type:"segment",p0:o,p1:r,p0DataIndex:(u-1)%l,p1DataIndex:u%l,datasetIndex:a}))),Ni(e,c)&&f(d,u-1,t.loop,c),o=r,c=e}d<u-1&&f(d,u-1,t.loop,c)}return h}(t,e,i,s):e}function Wi(t){return{backgroundColor:t.backgroundColor,borderCapStyle:t.borderCapStyle,borderDash:t.borderDash,borderDashOffset:t.borderDashOffset,borderJoinStyle:t.borderJoinStyle,borderWidth:t.borderWidth,borderColor:t.borderColor}}function Ni(t,e){return e&&JSON.stringify(t)!==JSON.stringify(e)}var Hi=Object.freeze({__proto__:null,easingEffects:Si,color:W,getHoverColor:N,noop:H,uid:j,isNullOrUndef:$,isArray:Y,isObject:U,isFinite:X,finiteOrDefault:q,valueOrDefault:K,toPercentage:G,toDimension:Z,callback:Q,each:J,_elementsEqual:tt,clone:et,_merger:st,merge:nt,mergeIf:ot,_mergerIf:at,_deprecated:function(t,e,i,s){void 0!==e&&console.warn(t+': "'+i+'" is deprecated. Please use "'+s+'" instead')},resolveObjectKey:lt,_capitalize:ht,defined:ct,isFunction:dt,setsEqual:ut,toFontString:$t,_measureText:Yt,_longestText:Ut,_alignPixel:Xt,clearCanvas:qt,drawPoint:Kt,_isPointInArea:Gt,clipArea:Zt,unclipArea:Qt,_steppedLineTo:Jt,_bezierCurveTo:te,renderText:ee,addRoundedRectPath:se,_lookup:ne,_lookupByKey:oe,_rlookupByKey:ae,_filterBetween:re,listenArrayEvents:he,unlistenArrayEvents:ce,_arrayUnique:de,_createResolver:ii,_attachContext:si,_descriptors:ni,splineCurve:bi,splineCurveMonotone:_i,_updateBezierControlPoints:vi,_isDomSupported:ue,_getParentNode:fe,getStyle:me,getRelativePosition:_e,getMaximumSize:ve,retinaScale:we,supportsEventListenerOptions:Me,readUsedSize:ke,fontString:function(t,e,i){return e+" "+t+"px "+i},requestAnimFrame:t,throttled:e,debounce:i,_toLeftRightCenter:s,_alignStartEnd:n,_textX:o,_pointInLine:Pi,_steppedInterpolation:Di,_bezierInterpolation:Ci,formatNumber:Ai,toLineHeight:Ee,_readValueToProps:Ie,toTRBL:ze,toTRBLCorners:Fe,toPadding:Be,toFont:Ve,resolve:We,_addGrace:Ne,createContext:He,PI:bt,TAU:_t,PITAU:yt,INFINITY:vt,RAD_PER_DEG:wt,HALF_PI:Mt,QUARTER_PI:kt,TWO_THIRDS_PI:St,log10:Pt,sign:Dt,niceNum:Ct,_factorize:Ot,isNumber:At,almostEquals:Tt,almostWhole:Lt,_setMinAndMaxByKey:Rt,toRadians:Et,toDegrees:It,_decimalPlaces:zt,getAngleFromPoint:Ft,distanceBetweenPoints:Bt,_angleDiff:Vt,_normalizeAngle:Wt,_angleBetween:Nt,_limitValue:Ht,_int16Range:jt,getRtlAdapter:Ti,overrideTextDirection:Li,restoreTextDirection:Ri,_boundSegment:zi,_boundSegments:Fi,_computeSegments:Bi});class ji{acquireContext(t,e){}releaseContext(t){return!1}addEventListener(t,e,i){}removeEventListener(t,e,i){}getDevicePixelRatio(){return 1}getMaximumSize(t,e,i,s){return e=Math.max(0,e||t.width),i=i||t.height,{width:e,height:Math.max(0,s?Math.floor(e/s):i)}}isAttached(t){return!0}updateConfig(t){}}class $i extends ji{acquireContext(t){return t&&t.getContext&&t.getContext("2d")||null}updateConfig(t){t.options.animation=!1}}const Yi={touchstart:"mousedown",touchmove:"mousemove",touchend:"mouseup",pointerenter:"mouseenter",pointerdown:"mousedown",pointermove:"mousemove",pointerup:"mouseup",pointerleave:"mouseout",pointerout:"mouseout"},Ui=t=>null===t||""===t;const Xi=!!Me&&{passive:!0};function qi(t,e,i){t.canvas.removeEventListener(e,i,Xi)}function Ki(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{for(const e of t)for(const t of e.addedNodes)if(t===s||t.contains(s))return i()}));return n.observe(document,{childList:!0,subtree:!0}),n}function Gi(t,e,i){const s=t.canvas,n=new MutationObserver((t=>{for(const e of t)for(const t of e.removedNodes)if(t===s||t.contains(s))return i()}));return n.observe(document,{childList:!0,subtree:!0}),n}const Zi=new Map;let Qi=0;function Ji(){const t=window.devicePixelRatio;t!==Qi&&(Qi=t,Zi.forEach(((e,i)=>{i.currentDevicePixelRatio!==t&&e()})))}function ts(t,i,s){const n=t.canvas,o=n&&fe(n);if(!o)return;const a=e(((t,e)=>{const i=o.clientWidth;s(t,e),i<o.clientWidth&&s()}),window),r=new ResizeObserver((t=>{const e=t[0],i=e.contentRect.width,s=e.contentRect.height;0===i&&0===s||a(i,s)}));return r.observe(o),function(t,e){Zi.size||window.addEventListener("resize",Ji),Zi.set(t,e)}(t,a),r}function es(t,e,i){i&&i.disconnect(),"resize"===e&&function(t){Zi.delete(t),Zi.size||window.removeEventListener("resize",Ji)}(t)}function is(t,i,s){const n=t.canvas,o=e((e=>{null!==t.ctx&&s(function(t,e){const i=Yi[t.type]||t.type,{x:s,y:n}=_e(t,e);return{type:i,chart:e,native:t,x:void 0!==s?s:null,y:void 0!==n?n:null}}(e,t))}),t,(t=>{const e=t[0];return[e,e.offsetX,e.offsetY]}));return function(t,e,i){t.addEventListener(e,i,Xi)}(n,i,o),o}class ss extends ji{acquireContext(t,e){const i=t&&t.getContext&&t.getContext("2d");return i&&i.canvas===t?(function(t,e){const i=t.style,s=t.getAttribute("height"),n=t.getAttribute("width");if(t.$chartjs={initial:{height:s,width:n,style:{display:i.display,height:i.height,width:i.width}}},i.display=i.display||"block",i.boxSizing=i.boxSizing||"border-box",Ui(n)){const e=ke(t,"width");void 0!==e&&(t.width=e)}if(Ui(s))if(""===t.style.height)t.height=t.width/(e||2);else{const e=ke(t,"height");void 0!==e&&(t.height=e)}}(t,e),i):null}releaseContext(t){const e=t.canvas;if(!e.$chartjs)return!1;const i=e.$chartjs.initial;["height","width"].forEach((t=>{const s=i[t];$(s)?e.removeAttribute(t):e.setAttribute(t,s)}));const s=i.style||{};return Object.keys(s).forEach((t=>{e.style[t]=s[t]})),e.width=e.width,delete e.$chartjs,!0}addEventListener(t,e,i){this.removeEventListener(t,e);const s=t.$proxies||(t.$proxies={}),n={attach:Ki,detach:Gi,resize:ts}[e]||is;s[e]=n(t,e,i)}removeEventListener(t,e){const i=t.$proxies||(t.$proxies={}),s=i[e];if(!s)return;({attach:es,detach:es,resize:es}[e]||qi)(t,e,s),i[e]=void 0}getDevicePixelRatio(){return window.devicePixelRatio}getMaximumSize(t,e,i,s){return ve(t,e,i,s)}isAttached(t){const e=fe(t);return!(!e||!e.isConnected)}}function ns(t){return!ue()||"undefined"!=typeof OffscreenCanvas&&t instanceof OffscreenCanvas?$i:ss}var os=Object.freeze({__proto__:null,_detectPlatform:ns,BasePlatform:ji,BasicPlatform:$i,DomPlatform:ss});const as="transparent",rs={boolean:(t,e,i)=>i>.5?e:t,color(t,e,i){const s=W(t||as),n=s.valid&&W(e||as);return n&&n.valid?n.mix(s,i).hexString():e},number:(t,e,i)=>t+(e-t)*i};class ls{constructor(t,e,i,s){const n=e[i];s=We([t.to,s,n,t.from]);const o=We([t.from,n,s]);this._active=!0,this._fn=t.fn||rs[t.type||typeof o],this._easing=Si[t.easing]||Si.linear,this._start=Math.floor(Date.now()+(t.delay||0)),this._duration=this._total=Math.floor(t.duration),this._loop=!!t.loop,this._target=e,this._prop=i,this._from=o,this._to=s,this._promises=void 0}active(){return this._active}update(t,e,i){if(this._active){this._notify(!1);const s=this._target[this._prop],n=i-this._start,o=this._duration-n;this._start=i,this._duration=Math.floor(Math.max(o,t.duration)),this._total+=n,this._loop=!!t.loop,this._to=We([t.to,e,s,t.from]),this._from=We([t.from,s,e])}}cancel(){this._active&&(this.tick(Date.now()),this._active=!1,this._notify(!1))}tick(t){const e=t-this._start,i=this._duration,s=this._prop,n=this._from,o=this._loop,a=this._to;let r;if(this._active=n!==a&&(o||e<i),!this._active)return this._target[s]=a,void this._notify(!0);e<0?this._target[s]=n:(r=e/i%2,r=o&&r>1?2-r:r,r=this._easing(Math.min(1,Math.max(0,r))),this._target[s]=this._fn(n,a,r))}wait(){const t=this._promises||(this._promises=[]);return new Promise(((e,i)=>{t.push({res:e,rej:i})}))}_notify(t){const e=t?"res":"rej",i=this._promises||[];for(let t=0;t<i.length;t++)i[t][e]()}}xt.set("animation",{delay:void 0,duration:1e3,easing:"easeOutQuart",fn:void 0,from:void 0,loop:void 0,to:void 0,type:void 0});const hs=Object.keys(xt.animation);xt.describe("animation",{_fallback:!1,_indexable:!1,_scriptable:t=>"onProgress"!==t&&"onComplete"!==t&&"fn"!==t}),xt.set("animations",{colors:{type:"color",properties:["color","borderColor","backgroundColor"]},numbers:{type:"number",properties:["x","y","borderWidth","radius","tension"]}}),xt.describe("animations",{_fallback:"animation"}),xt.set("transitions",{active:{animation:{duration:400}},resize:{animation:{duration:0}},show:{animations:{colors:{from:"transparent"},visible:{type:"boolean",duration:0}}},hide:{animations:{colors:{to:"transparent"},visible:{type:"boolean",easing:"linear",fn:t=>0|t}}}});class cs{constructor(t,e){this._chart=t,this._properties=new Map,this.configure(e)}configure(t){if(!U(t))return;const e=this._properties;Object.getOwnPropertyNames(t).forEach((i=>{const s=t[i];if(!U(s))return;const n={};for(const t of hs)n[t]=s[t];(Y(s.properties)&&s.properties||[i]).forEach((t=>{t!==i&&e.has(t)||e.set(t,n)}))}))}_animateOptions(t,e){const i=e.options,s=function(t,e){if(!e)return;let i=t.options;if(!i)return void(t.options=e);i.$shared&&(t.options=i=Object.assign({},i,{$shared:!1,$animations:{}}));return i}(t,i);if(!s)return[];const n=this._createAnimations(s,i);return i.$shared&&function(t,e){const i=[],s=Object.keys(e);for(let e=0;e<s.length;e++){const n=t[s[e]];n&&n.active()&&i.push(n.wait())}return Promise.all(i)}(t.options.$animations,i).then((()=>{t.options=i}),(()=>{})),n}_createAnimations(t,e){const i=this._properties,s=[],n=t.$animations||(t.$animations={}),o=Object.keys(e),a=Date.now();let r;for(r=o.length-1;r>=0;--r){const l=o[r];if("$"===l.charAt(0))continue;if("options"===l){s.push(...this._animateOptions(t,e));continue}const h=e[l];let c=n[l];const d=i.get(l);if(c){if(d&&c.active()){c.update(d,h,a);continue}c.cancel()}d&&d.duration?(n[l]=c=new ls(d,t,l,h),s.push(c)):t[l]=h}return s}update(t,e){if(0===this._properties.size)return void Object.assign(t,e);const i=this._createAnimations(t,e);return i.length?(a.add(this._chart,i),!0):void 0}}function ds(t,e){const i=t&&t.options||{},s=i.reverse,n=void 0===i.min?e:0,o=void 0===i.max?e:0;return{start:s?o:n,end:s?n:o}}function us(t,e){const i=[],s=t._getSortedDatasetMetas(e);let n,o;for(n=0,o=s.length;n<o;++n)i.push(s[n].index);return i}function fs(t,e,i,s={}){const n=t.keys,o="single"===s.mode;let a,r,l,h;if(null!==e){for(a=0,r=n.length;a<r;++a){if(l=+n[a],l===i){if(s.all)continue;break}h=t.values[l],X(h)&&(o||0===e||Dt(e)===Dt(h))&&(e+=h)}return e}}function gs(t,e){const i=t&&t.options.stacked;return i||void 0===i&&void 0!==e.stack}function ps(t,e,i){const s=t[e]||(t[e]={});return s[i]||(s[i]={})}function ms(t,e,i,s){for(const n of e.getMatchingVisibleMetas(s).reverse()){const e=t[n.index];if(i&&e>0||!i&&e<0)return n.index}return null}function xs(t,e){const{chart:i,_cachedMeta:s}=t,n=i._stacks||(i._stacks={}),{iScale:o,vScale:a,index:r}=s,l=o.axis,h=a.axis,c=function(t,e,i){return`${t.id}.${e.id}.${i.stack||i.type}`}(o,a,s),d=e.length;let u;for(let t=0;t<d;++t){const i=e[t],{[l]:o,[h]:d}=i;u=(i._stacks||(i._stacks={}))[h]=ps(n,c,o),u[r]=d,u._top=ms(u,a,!0,s.type),u._bottom=ms(u,a,!1,s.type)}}function bs(t,e){const i=t.scales;return Object.keys(i).filter((t=>i[t].axis===e)).shift()}function _s(t,e){const i=t.controller.index,s=t.vScale&&t.vScale.axis;if(s){e=e||t._parsed;for(const t of e){const e=t._stacks;if(!e||void 0===e[s]||void 0===e[s][i])return;delete e[s][i]}}}const ys=t=>"reset"===t||"none"===t,vs=(t,e)=>e?t:Object.assign({},t);class ws{constructor(t,e){this.chart=t,this._ctx=t.ctx,this.index=e,this._cachedDataOpts={},this._cachedMeta=this.getMeta(),this._type=this._cachedMeta.type,this.options=void 0,this._parsing=!1,this._data=void 0,this._objectData=void 0,this._sharedOptions=void 0,this._drawStart=void 0,this._drawCount=void 0,this.enableOptionSharing=!1,this.$context=void 0,this._syncList=[],this.initialize()}initialize(){const t=this._cachedMeta;this.configure(),this.linkScales(),t._stacked=gs(t.vScale,t),this.addElements()}updateIndex(t){this.index!==t&&_s(this._cachedMeta),this.index=t}linkScales(){const t=this.chart,e=this._cachedMeta,i=this.getDataset(),s=(t,e,i,s)=>"x"===t?e:"r"===t?s:i,n=e.xAxisID=K(i.xAxisID,bs(t,"x")),o=e.yAxisID=K(i.yAxisID,bs(t,"y")),a=e.rAxisID=K(i.rAxisID,bs(t,"r")),r=e.indexAxis,l=e.iAxisID=s(r,n,o,a),h=e.vAxisID=s(r,o,n,a);e.xScale=this.getScaleForId(n),e.yScale=this.getScaleForId(o),e.rScale=this.getScaleForId(a),e.iScale=this.getScaleForId(l),e.vScale=this.getScaleForId(h)}getDataset(){return this.chart.data.datasets[this.index]}getMeta(){return this.chart.getDatasetMeta(this.index)}getScaleForId(t){return this.chart.scales[t]}_getOtherScale(t){const e=this._cachedMeta;return t===e.iScale?e.vScale:e.iScale}reset(){this._update("reset")}_destroy(){const t=this._cachedMeta;this._data&&ce(this._data,this),t._stacked&&_s(t)}_dataCheck(){const t=this.getDataset(),e=t.data||(t.data=[]),i=this._data;if(U(e))this._data=function(t){const e=Object.keys(t),i=new Array(e.length);let s,n,o;for(s=0,n=e.length;s<n;++s)o=e[s],i[s]={x:o,y:t[o]};return i}(e);else if(i!==e){if(i){ce(i,this);const t=this._cachedMeta;_s(t),t._parsed=[]}e&&Object.isExtensible(e)&&he(e,this),this._syncList=[],this._data=e}}addElements(){const t=this._cachedMeta;this._dataCheck(),this.datasetElementType&&(t.dataset=new this.datasetElementType)}buildOrUpdateElements(t){const e=this._cachedMeta,i=this.getDataset();let s=!1;this._dataCheck();const n=e._stacked;e._stacked=gs(e.vScale,e),e.stack!==i.stack&&(s=!0,_s(e),e.stack=i.stack),this._resyncElements(t),(s||n!==e._stacked)&&xs(this,e._parsed)}configure(){const t=this.chart.config,e=t.datasetScopeKeys(this._type),i=t.getOptionScopes(this.getDataset(),e,!0);this.options=t.createResolver(i,this.getContext()),this._parsing=this.options.parsing}parse(t,e){const{_cachedMeta:i,_data:s}=this,{iScale:n,_stacked:o}=i,a=n.axis;let r,l,h,c=0===t&&e===s.length||i._sorted,d=t>0&&i._parsed[t-1];if(!1===this._parsing)i._parsed=s,i._sorted=!0,h=s;else{h=Y(s[t])?this.parseArrayData(i,s,t,e):U(s[t])?this.parseObjectData(i,s,t,e):this.parsePrimitiveData(i,s,t,e);const n=()=>null===l[a]||d&&l[a]<d[a];for(r=0;r<e;++r)i._parsed[r+t]=l=h[r],c&&(n()&&(c=!1),d=l);i._sorted=c}o&&xs(this,h)}parsePrimitiveData(t,e,i,s){const{iScale:n,vScale:o}=t,a=n.axis,r=o.axis,l=n.getLabels(),h=n===o,c=new Array(s);let d,u,f;for(d=0,u=s;d<u;++d)f=d+i,c[d]={[a]:h||n.parse(l[f],f),[r]:o.parse(e[f],f)};return c}parseArrayData(t,e,i,s){const{xScale:n,yScale:o}=t,a=new Array(s);let r,l,h,c;for(r=0,l=s;r<l;++r)h=r+i,c=e[h],a[r]={x:n.parse(c[0],h),y:o.parse(c[1],h)};return a}parseObjectData(t,e,i,s){const{xScale:n,yScale:o}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l=new Array(s);let h,c,d,u;for(h=0,c=s;h<c;++h)d=h+i,u=e[d],l[h]={x:n.parse(lt(u,a),d),y:o.parse(lt(u,r),d)};return l}getParsed(t){return this._cachedMeta._parsed[t]}getDataElement(t){return this._cachedMeta.data[t]}applyStack(t,e,i){const s=this.chart,n=this._cachedMeta,o=e[t.axis];return fs({keys:us(s,!0),values:e._stacks[t.axis]},o,n.index,{mode:i})}updateRangeFromParsed(t,e,i,s){const n=i[e.axis];let o=null===n?NaN:n;const a=s&&i._stacks[e.axis];s&&a&&(s.values=a,o=fs(s,n,this._cachedMeta.index)),t.min=Math.min(t.min,o),t.max=Math.max(t.max,o)}getMinMax(t,e){const i=this._cachedMeta,s=i._parsed,n=i._sorted&&t===i.iScale,o=s.length,a=this._getOtherScale(t),r=((t,e,i)=>t&&!e.hidden&&e._stacked&&{keys:us(i,!0),values:null})(e,i,this.chart),l={min:Number.POSITIVE_INFINITY,max:Number.NEGATIVE_INFINITY},{min:h,max:c}=function(t){const{min:e,max:i,minDefined:s,maxDefined:n}=t.getUserBounds();return{min:s?e:Number.NEGATIVE_INFINITY,max:n?i:Number.POSITIVE_INFINITY}}(a);let d,u;function f(){u=s[d];const e=u[a.axis];return!X(u[t.axis])||h>e||c<e}for(d=0;d<o&&(f()||(this.updateRangeFromParsed(l,t,u,r),!n));++d);if(n)for(d=o-1;d>=0;--d)if(!f()){this.updateRangeFromParsed(l,t,u,r);break}return l}getAllParsedValues(t){const e=this._cachedMeta._parsed,i=[];let s,n,o;for(s=0,n=e.length;s<n;++s)o=e[s][t.axis],X(o)&&i.push(o);return i}getMaxOverflow(){return!1}getLabelAndValue(t){const e=this._cachedMeta,i=e.iScale,s=e.vScale,n=this.getParsed(t);return{label:i?""+i.getLabelForValue(n[i.axis]):"",value:s?""+s.getLabelForValue(n[s.axis]):""}}_update(t){const e=this._cachedMeta;this.configure(),this._cachedDataOpts={},this.update(t||"default"),e._clip=function(t){let e,i,s,n;return U(t)?(e=t.top,i=t.right,s=t.bottom,n=t.left):e=i=s=n=t,{top:e,right:i,bottom:s,left:n,disabled:!1===t}}(K(this.options.clip,function(t,e,i){if(!1===i)return!1;const s=ds(t,i),n=ds(e,i);return{top:n.end,right:s.end,bottom:n.start,left:s.start}}(e.xScale,e.yScale,this.getMaxOverflow())))}update(t){}draw(){const t=this._ctx,e=this.chart,i=this._cachedMeta,s=i.data||[],n=e.chartArea,o=[],a=this._drawStart||0,r=this._drawCount||s.length-a;let l;for(i.dataset&&i.dataset.draw(t,n,a,r),l=a;l<a+r;++l){const e=s[l];e.hidden||(e.active?o.push(e):e.draw(t,n))}for(l=0;l<o.length;++l)o[l].draw(t,n)}getStyle(t,e){const i=e?"active":"default";return void 0===t&&this._cachedMeta.dataset?this.resolveDatasetElementOptions(i):this.resolveDataElementOptions(t||0,i)}getContext(t,e,i){const s=this.getDataset();let n;if(t>=0&&t<this._cachedMeta.data.length){const e=this._cachedMeta.data[t];n=e.$context||(e.$context=function(t,e,i){return He(t,{active:!1,dataIndex:e,parsed:void 0,raw:void 0,element:i,index:e,mode:"default",type:"data"})}(this.getContext(),t,e)),n.parsed=this.getParsed(t),n.raw=s.data[t],n.index=n.dataIndex=t}else n=this.$context||(this.$context=function(t,e){return He(t,{active:!1,dataset:void 0,datasetIndex:e,index:e,mode:"default",type:"dataset"})}(this.chart.getContext(),this.index)),n.dataset=s,n.index=n.datasetIndex=this.index;return n.active=!!e,n.mode=i,n}resolveDatasetElementOptions(t){return this._resolveElementOptions(this.datasetElementType.id,t)}resolveDataElementOptions(t,e){return this._resolveElementOptions(this.dataElementType.id,e,t)}_resolveElementOptions(t,e="default",i){const s="active"===e,n=this._cachedDataOpts,o=t+"-"+e,a=n[o],r=this.enableOptionSharing&&ct(i);if(a)return vs(a,r);const l=this.chart.config,h=l.datasetElementScopeKeys(this._type,t),c=s?[`${t}Hover`,"hover",t,""]:[t,""],d=l.getOptionScopes(this.getDataset(),h),u=Object.keys(xt.elements[t]),f=l.resolveNamedOptions(d,u,(()=>this.getContext(i,s)),c);return f.$shared&&(f.$shared=r,n[o]=Object.freeze(vs(f,r))),f}_resolveAnimations(t,e,i){const s=this.chart,n=this._cachedDataOpts,o=`animation-${e}`,a=n[o];if(a)return a;let r;if(!1!==s.options.animation){const s=this.chart.config,n=s.datasetAnimationScopeKeys(this._type,e),o=s.getOptionScopes(this.getDataset(),n);r=s.createResolver(o,this.getContext(t,i,e))}const l=new cs(s,r&&r.animations);return r&&r._cacheable&&(n[o]=Object.freeze(l)),l}getSharedOptions(t){if(t.$shared)return this._sharedOptions||(this._sharedOptions=Object.assign({},t))}includeOptions(t,e){return!e||ys(t)||this.chart._animationsDisabled}updateElement(t,e,i,s){ys(s)?Object.assign(t,i):this._resolveAnimations(e,s).update(t,i)}updateSharedOptions(t,e,i){t&&!ys(e)&&this._resolveAnimations(void 0,e).update(t,i)}_setStyle(t,e,i,s){t.active=s;const n=this.getStyle(e,s);this._resolveAnimations(e,i,s).update(t,{options:!s&&this.getSharedOptions(n)||n})}removeHoverStyle(t,e,i){this._setStyle(t,i,"active",!1)}setHoverStyle(t,e,i){this._setStyle(t,i,"active",!0)}_removeDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!1)}_setDatasetHoverStyle(){const t=this._cachedMeta.dataset;t&&this._setStyle(t,void 0,"active",!0)}_resyncElements(t){const e=this._data,i=this._cachedMeta.data;for(const[t,e,i]of this._syncList)this[t](e,i);this._syncList=[];const s=i.length,n=e.length,o=Math.min(n,s);o&&this.parse(0,o),n>s?this._insertElements(s,n-s,t):n<s&&this._removeElements(n,s-n)}_insertElements(t,e,i=!0){const s=this._cachedMeta,n=s.data,o=t+e;let a;const r=t=>{for(t.length+=e,a=t.length-1;a>=o;a--)t[a]=t[a-e]};for(r(n),a=t;a<o;++a)n[a]=new this.dataElementType;this._parsing&&r(s._parsed),this.parse(t,e),i&&this.updateElements(n,t,e,"reset")}updateElements(t,e,i,s){}_removeElements(t,e){const i=this._cachedMeta;if(this._parsing){const s=i._parsed.splice(t,e);i._stacked&&_s(i,s)}i.data.splice(t,e)}_sync(t){if(this._parsing)this._syncList.push(t);else{const[e,i,s]=t;this[e](i,s)}}_onDataPush(){const t=arguments.length;this._sync(["_insertElements",this.getDataset().data.length-t,t])}_onDataPop(){this._sync(["_removeElements",this._cachedMeta.data.length-1,1])}_onDataShift(){this._sync(["_removeElements",0,1])}_onDataSplice(t,e){this._sync(["_removeElements",t,e]),this._sync(["_insertElements",t,arguments.length-2])}_onDataUnshift(){this._sync(["_insertElements",0,arguments.length])}}ws.defaults={},ws.prototype.datasetElementType=null,ws.prototype.dataElementType=null;class Ms{constructor(){this.x=void 0,this.y=void 0,this.active=!1,this.options=void 0,this.$animations=void 0}tooltipPosition(t){const{x:e,y:i}=this.getProps(["x","y"],t);return{x:e,y:i}}hasValue(){return At(this.x)&&At(this.y)}getProps(t,e){const i=this.$animations;if(!e||!i)return this;const s={};return t.forEach((t=>{s[t]=i[t]&&i[t].active()?i[t]._to:this[t]})),s}}Ms.defaults={},Ms.defaultRoutes=void 0;const ks={values:t=>Y(t)?t:""+t,numeric(t,e,i){if(0===t)return"0";const s=this.chart.options.locale;let n,o=t;if(i.length>1){const e=Math.max(Math.abs(i[0].value),Math.abs(i[i.length-1].value));(e<1e-4||e>1e15)&&(n="scientific"),o=function(t,e){let i=e.length>3?e[2].value-e[1].value:e[1].value-e[0].value;Math.abs(i)>=1&&t!==Math.floor(t)&&(i=t-Math.floor(t));return i}(t,i)}const a=Pt(Math.abs(o)),r=Math.max(Math.min(-1*Math.floor(a),20),0),l={notation:n,minimumFractionDigits:r,maximumFractionDigits:r};return Object.assign(l,this.options.ticks.format),Ai(t,s,l)},logarithmic(t,e,i){if(0===t)return"0";const s=t/Math.pow(10,Math.floor(Pt(t)));return 1===s||2===s||5===s?ks.numeric.call(this,t,e,i):""}};var Ss={formatters:ks};function Ps(t,e){const i=t.options.ticks,s=i.maxTicksLimit||function(t){const e=t.options.offset,i=t._tickSize(),s=t._length/i+(e?0:1),n=t._maxLength/i;return Math.floor(Math.min(s,n))}(t),n=i.major.enabled?function(t){const e=[];let i,s;for(i=0,s=t.length;i<s;i++)t[i].major&&e.push(i);return e}(e):[],o=n.length,a=n[0],r=n[o-1],l=[];if(o>s)return function(t,e,i,s){let n,o=0,a=i[0];for(s=Math.ceil(s),n=0;n<t.length;n++)n===a&&(e.push(t[n]),o++,a=i[o*s])}(e,l,n,o/s),l;const h=function(t,e,i){const s=function(t){const e=t.length;let i,s;if(e<2)return!1;for(s=t[0],i=1;i<e;++i)if(t[i]-t[i-1]!==s)return!1;return s}(t),n=e.length/i;if(!s)return Math.max(n,1);const o=Ot(s);for(let t=0,e=o.length-1;t<e;t++){const e=o[t];if(e>n)return e}return Math.max(n,1)}(n,e,s);if(o>0){let t,i;const s=o>1?Math.round((r-a)/(o-1)):null;for(Ds(e,l,h,$(s)?0:a-s,a),t=0,i=o-1;t<i;t++)Ds(e,l,h,n[t],n[t+1]);return Ds(e,l,h,r,$(s)?e.length:r+s),l}return Ds(e,l,h),l}function Ds(t,e,i,s,n){const o=K(s,0),a=Math.min(K(n,t.length),t.length);let r,l,h,c=0;for(i=Math.ceil(i),n&&(r=n-s,i=r/Math.floor(r/i)),h=o;h<0;)c++,h=Math.round(o+c*i);for(l=Math.max(o,0);l<a;l++)l===h&&(e.push(t[l]),c++,h=Math.round(o+c*i))}xt.set("scale",{display:!0,offset:!1,reverse:!1,beginAtZero:!1,bounds:"ticks",grace:0,grid:{display:!0,lineWidth:1,drawBorder:!0,drawOnChartArea:!0,drawTicks:!0,tickLength:8,tickWidth:(t,e)=>e.lineWidth,tickColor:(t,e)=>e.color,offset:!1,borderDash:[],borderDashOffset:0,borderWidth:1},title:{display:!1,text:"",padding:{top:4,bottom:4}},ticks:{minRotation:0,maxRotation:50,mirror:!1,textStrokeWidth:0,textStrokeColor:"",padding:3,display:!0,autoSkip:!0,autoSkipPadding:3,labelOffset:0,callback:Ss.formatters.values,minor:{},major:{},align:"center",crossAlign:"near",showLabelBackdrop:!1,backdropColor:"rgba(255, 255, 255, 0.75)",backdropPadding:2}}),xt.route("scale.ticks","color","","color"),xt.route("scale.grid","color","","borderColor"),xt.route("scale.grid","borderColor","","borderColor"),xt.route("scale.title","color","","color"),xt.describe("scale",{_fallback:!1,_scriptable:t=>!t.startsWith("before")&&!t.startsWith("after")&&"callback"!==t&&"parser"!==t,_indexable:t=>"borderDash"!==t&&"tickBorderDash"!==t}),xt.describe("scales",{_fallback:"scale"}),xt.describe("scale.ticks",{_scriptable:t=>"backdropPadding"!==t&&"callback"!==t,_indexable:t=>"backdropPadding"!==t});const Cs=(t,e,i)=>"top"===e||"left"===e?t[e]+i:t[e]-i;function Os(t,e){const i=[],s=t.length/e,n=t.length;let o=0;for(;o<n;o+=s)i.push(t[Math.floor(o)]);return i}function As(t,e,i){const s=t.ticks.length,n=Math.min(e,s-1),o=t._startPixel,a=t._endPixel,r=1e-6;let l,h=t.getPixelForTick(n);if(!(i&&(l=1===s?Math.max(h-o,a-h):0===e?(t.getPixelForTick(1)-h)/2:(h-t.getPixelForTick(n-1))/2,h+=n<e?l:-l,h<o-r||h>a+r)))return h}function Ts(t){return t.drawTicks?t.tickLength:0}function Ls(t,e){if(!t.display)return 0;const i=Ve(t.font,e),s=Be(t.padding);return(Y(t.text)?t.text.length:1)*i.lineHeight+s.height}function Rs(t,e,i){let n=s(t);return(i&&"right"!==e||!i&&"right"===e)&&(n=(t=>"left"===t?"right":"right"===t?"left":t)(n)),n}class Es extends Ms{constructor(t){super(),this.id=t.id,this.type=t.type,this.options=void 0,this.ctx=t.ctx,this.chart=t.chart,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this._margins={left:0,right:0,top:0,bottom:0},this.maxWidth=void 0,this.maxHeight=void 0,this.paddingTop=void 0,this.paddingBottom=void 0,this.paddingLeft=void 0,this.paddingRight=void 0,this.axis=void 0,this.labelRotation=void 0,this.min=void 0,this.max=void 0,this._range=void 0,this.ticks=[],this._gridLineItems=null,this._labelItems=null,this._labelSizes=null,this._length=0,this._maxLength=0,this._longestTextCache={},this._startPixel=void 0,this._endPixel=void 0,this._reversePixels=!1,this._userMax=void 0,this._userMin=void 0,this._suggestedMax=void 0,this._suggestedMin=void 0,this._ticksLength=0,this._borderValue=0,this._cache={},this._dataLimitsCached=!1,this.$context=void 0}init(t){this.options=t.setContext(this.getContext()),this.axis=t.axis,this._userMin=this.parse(t.min),this._userMax=this.parse(t.max),this._suggestedMin=this.parse(t.suggestedMin),this._suggestedMax=this.parse(t.suggestedMax)}parse(t,e){return t}getUserBounds(){let{_userMin:t,_userMax:e,_suggestedMin:i,_suggestedMax:s}=this;return t=q(t,Number.POSITIVE_INFINITY),e=q(e,Number.NEGATIVE_INFINITY),i=q(i,Number.POSITIVE_INFINITY),s=q(s,Number.NEGATIVE_INFINITY),{min:q(t,i),max:q(e,s),minDefined:X(t),maxDefined:X(e)}}getMinMax(t){let e,{min:i,max:s,minDefined:n,maxDefined:o}=this.getUserBounds();if(n&&o)return{min:i,max:s};const a=this.getMatchingVisibleMetas();for(let r=0,l=a.length;r<l;++r)e=a[r].controller.getMinMax(this,t),n||(i=Math.min(i,e.min)),o||(s=Math.max(s,e.max));return i=o&&i>s?s:i,s=n&&i>s?i:s,{min:q(i,q(s,i)),max:q(s,q(i,s))}}getPadding(){return{left:this.paddingLeft||0,top:this.paddingTop||0,right:this.paddingRight||0,bottom:this.paddingBottom||0}}getTicks(){return this.ticks}getLabels(){const t=this.chart.data;return this.options.labels||(this.isHorizontal()?t.xLabels:t.yLabels)||t.labels||[]}beforeLayout(){this._cache={},this._dataLimitsCached=!1}beforeUpdate(){Q(this.options.beforeUpdate,[this])}update(t,e,i){const{beginAtZero:s,grace:n,ticks:o}=this.options,a=o.sampleSize;this.beforeUpdate(),this.maxWidth=t,this.maxHeight=e,this._margins=i=Object.assign({left:0,right:0,top:0,bottom:0},i),this.ticks=null,this._labelSizes=null,this._gridLineItems=null,this._labelItems=null,this.beforeSetDimensions(),this.setDimensions(),this.afterSetDimensions(),this._maxLength=this.isHorizontal()?this.width+i.left+i.right:this.height+i.top+i.bottom,this._dataLimitsCached||(this.beforeDataLimits(),this.determineDataLimits(),this.afterDataLimits(),this._range=Ne(this,n,s),this._dataLimitsCached=!0),this.beforeBuildTicks(),this.ticks=this.buildTicks()||[],this.afterBuildTicks();const r=a<this.ticks.length;this._convertTicksToLabels(r?Os(this.ticks,a):this.ticks),this.configure(),this.beforeCalculateLabelRotation(),this.calculateLabelRotation(),this.afterCalculateLabelRotation(),o.display&&(o.autoSkip||"auto"===o.source)&&(this.ticks=Ps(this,this.ticks),this._labelSizes=null),r&&this._convertTicksToLabels(this.ticks),this.beforeFit(),this.fit(),this.afterFit(),this.afterUpdate()}configure(){let t,e,i=this.options.reverse;this.isHorizontal()?(t=this.left,e=this.right):(t=this.top,e=this.bottom,i=!i),this._startPixel=t,this._endPixel=e,this._reversePixels=i,this._length=e-t,this._alignToPixels=this.options.alignToPixels}afterUpdate(){Q(this.options.afterUpdate,[this])}beforeSetDimensions(){Q(this.options.beforeSetDimensions,[this])}setDimensions(){this.isHorizontal()?(this.width=this.maxWidth,this.left=0,this.right=this.width):(this.height=this.maxHeight,this.top=0,this.bottom=this.height),this.paddingLeft=0,this.paddingTop=0,this.paddingRight=0,this.paddingBottom=0}afterSetDimensions(){Q(this.options.afterSetDimensions,[this])}_callHooks(t){this.chart.notifyPlugins(t,this.getContext()),Q(this.options[t],[this])}beforeDataLimits(){this._callHooks("beforeDataLimits")}determineDataLimits(){}afterDataLimits(){this._callHooks("afterDataLimits")}beforeBuildTicks(){this._callHooks("beforeBuildTicks")}buildTicks(){return[]}afterBuildTicks(){this._callHooks("afterBuildTicks")}beforeTickToLabelConversion(){Q(this.options.beforeTickToLabelConversion,[this])}generateTickLabels(t){const e=this.options.ticks;let i,s,n;for(i=0,s=t.length;i<s;i++)n=t[i],n.label=Q(e.callback,[n.value,i,t],this)}afterTickToLabelConversion(){Q(this.options.afterTickToLabelConversion,[this])}beforeCalculateLabelRotation(){Q(this.options.beforeCalculateLabelRotation,[this])}calculateLabelRotation(){const t=this.options,e=t.ticks,i=this.ticks.length,s=e.minRotation||0,n=e.maxRotation;let o,a,r,l=s;if(!this._isVisible()||!e.display||s>=n||i<=1||!this.isHorizontal())return void(this.labelRotation=s);const h=this._getLabelSizes(),c=h.widest.width,d=h.highest.height,u=Ht(this.chart.width-c,0,this.maxWidth);o=t.offset?this.maxWidth/i:u/(i-1),c+6>o&&(o=u/(i-(t.offset?.5:1)),a=this.maxHeight-Ts(t.grid)-e.padding-Ls(t.title,this.chart.options.font),r=Math.sqrt(c*c+d*d),l=It(Math.min(Math.asin(Ht((h.highest.height+6)/o,-1,1)),Math.asin(Ht(a/r,-1,1))-Math.asin(Ht(d/r,-1,1)))),l=Math.max(s,Math.min(n,l))),this.labelRotation=l}afterCalculateLabelRotation(){Q(this.options.afterCalculateLabelRotation,[this])}beforeFit(){Q(this.options.beforeFit,[this])}fit(){const t={width:0,height:0},{chart:e,options:{ticks:i,title:s,grid:n}}=this,o=this._isVisible(),a=this.isHorizontal();if(o){const o=Ls(s,e.options.font);if(a?(t.width=this.maxWidth,t.height=Ts(n)+o):(t.height=this.maxHeight,t.width=Ts(n)+o),i.display&&this.ticks.length){const{first:e,last:s,widest:n,highest:o}=this._getLabelSizes(),r=2*i.padding,l=Et(this.labelRotation),h=Math.cos(l),c=Math.sin(l);if(a){const e=i.mirror?0:c*n.width+h*o.height;t.height=Math.min(this.maxHeight,t.height+e+r)}else{const e=i.mirror?0:h*n.width+c*o.height;t.width=Math.min(this.maxWidth,t.width+e+r)}this._calculatePadding(e,s,c,h)}}this._handleMargins(),a?(this.width=this._length=e.width-this._margins.left-this._margins.right,this.height=t.height):(this.width=t.width,this.height=this._length=e.height-this._margins.top-this._margins.bottom)}_calculatePadding(t,e,i,s){const{ticks:{align:n,padding:o},position:a}=this.options,r=0!==this.labelRotation,l="top"!==a&&"x"===this.axis;if(this.isHorizontal()){const a=this.getPixelForTick(0)-this.left,h=this.right-this.getPixelForTick(this.ticks.length-1);let c=0,d=0;r?l?(c=s*t.width,d=i*e.height):(c=i*t.height,d=s*e.width):"start"===n?d=e.width:"end"===n?c=t.width:(c=t.width/2,d=e.width/2),this.paddingLeft=Math.max((c-a+o)*this.width/(this.width-a),0),this.paddingRight=Math.max((d-h+o)*this.width/(this.width-h),0)}else{let i=e.height/2,s=t.height/2;"start"===n?(i=0,s=t.height):"end"===n&&(i=e.height,s=0),this.paddingTop=i+o,this.paddingBottom=s+o}}_handleMargins(){this._margins&&(this._margins.left=Math.max(this.paddingLeft,this._margins.left),this._margins.top=Math.max(this.paddingTop,this._margins.top),this._margins.right=Math.max(this.paddingRight,this._margins.right),this._margins.bottom=Math.max(this.paddingBottom,this._margins.bottom))}afterFit(){Q(this.options.afterFit,[this])}isHorizontal(){const{axis:t,position:e}=this.options;return"top"===e||"bottom"===e||"x"===t}isFullSize(){return this.options.fullSize}_convertTicksToLabels(t){let e,i;for(this.beforeTickToLabelConversion(),this.generateTickLabels(t),e=0,i=t.length;e<i;e++)$(t[e].label)&&(t.splice(e,1),i--,e--);this.afterTickToLabelConversion()}_getLabelSizes(){let t=this._labelSizes;if(!t){const e=this.options.ticks.sampleSize;let i=this.ticks;e<i.length&&(i=Os(i,e)),this._labelSizes=t=this._computeLabelSizes(i,i.length)}return t}_computeLabelSizes(t,e){const{ctx:i,_longestTextCache:s}=this,n=[],o=[];let a,r,l,h,c,d,u,f,g,p,m,x=0,b=0;for(a=0;a<e;++a){if(h=t[a].label,c=this._resolveTickFontOptions(a),i.font=d=c.string,u=s[d]=s[d]||{data:{},gc:[]},f=c.lineHeight,g=p=0,$(h)||Y(h)){if(Y(h))for(r=0,l=h.length;r<l;++r)m=h[r],$(m)||Y(m)||(g=Yt(i,u.data,u.gc,g,m),p+=f)}else g=Yt(i,u.data,u.gc,g,h),p=f;n.push(g),o.push(p),x=Math.max(g,x),b=Math.max(p,b)}!function(t,e){J(t,(t=>{const i=t.gc,s=i.length/2;let n;if(s>e){for(n=0;n<s;++n)delete t.data[i[n]];i.splice(0,s)}}))}(s,e);const _=n.indexOf(x),y=o.indexOf(b),v=t=>({width:n[t]||0,height:o[t]||0});return{first:v(0),last:v(e-1),widest:v(_),highest:v(y),widths:n,heights:o}}getLabelForValue(t){return t}getPixelForValue(t,e){return NaN}getValueForPixel(t){}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getPixelForDecimal(t){this._reversePixels&&(t=1-t);const e=this._startPixel+t*this._length;return jt(this._alignToPixels?Xt(this.chart,e,0):e)}getDecimalForPixel(t){const e=(t-this._startPixel)/this._length;return this._reversePixels?1-e:e}getBasePixel(){return this.getPixelForValue(this.getBaseValue())}getBaseValue(){const{min:t,max:e}=this;return t<0&&e<0?e:t>0&&e>0?t:0}getContext(t){const e=this.ticks||[];if(t>=0&&t<e.length){const i=e[t];return i.$context||(i.$context=function(t,e,i){return He(t,{tick:i,index:e,type:"tick"})}(this.getContext(),t,i))}return this.$context||(this.$context=He(this.chart.getContext(),{scale:this,type:"scale"}))}_tickSize(){const t=this.options.ticks,e=Et(this.labelRotation),i=Math.abs(Math.cos(e)),s=Math.abs(Math.sin(e)),n=this._getLabelSizes(),o=t.autoSkipPadding||0,a=n?n.widest.width+o:0,r=n?n.highest.height+o:0;return this.isHorizontal()?r*i>a*s?a/i:r/s:r*s<a*i?r/i:a/s}_isVisible(){const t=this.options.display;return"auto"!==t?!!t:this.getMatchingVisibleMetas().length>0}_computeGridLineItems(t){const e=this.axis,i=this.chart,s=this.options,{grid:n,position:o}=s,a=n.offset,r=this.isHorizontal(),l=this.ticks.length+(a?1:0),h=Ts(n),c=[],d=n.setContext(this.getContext()),u=d.drawBorder?d.borderWidth:0,f=u/2,g=function(t){return Xt(i,t,u)};let p,m,x,b,_,y,v,w,M,k,S,P;if("top"===o)p=g(this.bottom),y=this.bottom-h,w=p-f,k=g(t.top)+f,P=t.bottom;else if("bottom"===o)p=g(this.top),k=t.top,P=g(t.bottom)-f,y=p+f,w=this.top+h;else if("left"===o)p=g(this.right),_=this.right-h,v=p-f,M=g(t.left)+f,S=t.right;else if("right"===o)p=g(this.left),M=t.left,S=g(t.right)-f,_=p+f,v=this.left+h;else if("x"===e){if("center"===o)p=g((t.top+t.bottom)/2+.5);else if(U(o)){const t=Object.keys(o)[0],e=o[t];p=g(this.chart.scales[t].getPixelForValue(e))}k=t.top,P=t.bottom,y=p+f,w=y+h}else if("y"===e){if("center"===o)p=g((t.left+t.right)/2);else if(U(o)){const t=Object.keys(o)[0],e=o[t];p=g(this.chart.scales[t].getPixelForValue(e))}_=p-f,v=_-h,M=t.left,S=t.right}const D=K(s.ticks.maxTicksLimit,l),C=Math.max(1,Math.ceil(l/D));for(m=0;m<l;m+=C){const t=n.setContext(this.getContext(m)),e=t.lineWidth,s=t.color,o=n.borderDash||[],l=t.borderDashOffset,h=t.tickWidth,d=t.tickColor,u=t.tickBorderDash||[],f=t.tickBorderDashOffset;x=As(this,m,a),void 0!==x&&(b=Xt(i,x,e),r?_=v=M=S=b:y=w=k=P=b,c.push({tx1:_,ty1:y,tx2:v,ty2:w,x1:M,y1:k,x2:S,y2:P,width:e,color:s,borderDash:o,borderDashOffset:l,tickWidth:h,tickColor:d,tickBorderDash:u,tickBorderDashOffset:f}))}return this._ticksLength=l,this._borderValue=p,c}_computeLabelItems(t){const e=this.axis,i=this.options,{position:s,ticks:n}=i,o=this.isHorizontal(),a=this.ticks,{align:r,crossAlign:l,padding:h,mirror:c}=n,d=Ts(i.grid),u=d+h,f=c?-h:u,g=-Et(this.labelRotation),p=[];let m,x,b,_,y,v,w,M,k,S,P,D,C="middle";if("top"===s)v=this.bottom-f,w=this._getXAxisLabelAlignment();else if("bottom"===s)v=this.top+f,w=this._getXAxisLabelAlignment();else if("left"===s){const t=this._getYAxisLabelAlignment(d);w=t.textAlign,y=t.x}else if("right"===s){const t=this._getYAxisLabelAlignment(d);w=t.textAlign,y=t.x}else if("x"===e){if("center"===s)v=(t.top+t.bottom)/2+u;else if(U(s)){const t=Object.keys(s)[0],e=s[t];v=this.chart.scales[t].getPixelForValue(e)+u}w=this._getXAxisLabelAlignment()}else if("y"===e){if("center"===s)y=(t.left+t.right)/2-u;else if(U(s)){const t=Object.keys(s)[0],e=s[t];y=this.chart.scales[t].getPixelForValue(e)}w=this._getYAxisLabelAlignment(d).textAlign}"y"===e&&("start"===r?C="top":"end"===r&&(C="bottom"));const O=this._getLabelSizes();for(m=0,x=a.length;m<x;++m){b=a[m],_=b.label;const t=n.setContext(this.getContext(m));M=this.getPixelForTick(m)+n.labelOffset,k=this._resolveTickFontOptions(m),S=k.lineHeight,P=Y(_)?_.length:1;const e=P/2,i=t.color,r=t.textStrokeColor,h=t.textStrokeWidth;let d;if(o?(y=M,D="top"===s?"near"===l||0!==g?-P*S+S/2:"center"===l?-O.highest.height/2-e*S+S:-O.highest.height+S/2:"near"===l||0!==g?S/2:"center"===l?O.highest.height/2-e*S:O.highest.height-P*S,c&&(D*=-1)):(v=M,D=(1-P)*S/2),t.showLabelBackdrop){const e=Be(t.backdropPadding),i=O.heights[m],s=O.widths[m];let n=v+D-e.top,o=y-e.left;switch(C){case"middle":n-=i/2;break;case"bottom":n-=i}switch(w){case"center":o-=s/2;break;case"right":o-=s}d={left:o,top:n,width:s+e.width,height:i+e.height,color:t.backdropColor}}p.push({rotation:g,label:_,font:k,color:i,strokeColor:r,strokeWidth:h,textOffset:D,textAlign:w,textBaseline:C,translation:[y,v],backdrop:d})}return p}_getXAxisLabelAlignment(){const{position:t,ticks:e}=this.options;if(-Et(this.labelRotation))return"top"===t?"left":"right";let i="center";return"start"===e.align?i="left":"end"===e.align&&(i="right"),i}_getYAxisLabelAlignment(t){const{position:e,ticks:{crossAlign:i,mirror:s,padding:n}}=this.options,o=t+n,a=this._getLabelSizes().widest.width;let r,l;return"left"===e?s?(l=this.right+n,"near"===i?r="left":"center"===i?(r="center",l+=a/2):(r="right",l+=a)):(l=this.right-o,"near"===i?r="right":"center"===i?(r="center",l-=a/2):(r="left",l=this.left)):"right"===e?s?(l=this.left+n,"near"===i?r="right":"center"===i?(r="center",l-=a/2):(r="left",l-=a)):(l=this.left+o,"near"===i?r="left":"center"===i?(r="center",l+=a/2):(r="right",l=this.right)):r="right",{textAlign:r,x:l}}_computeLabelArea(){if(this.options.ticks.mirror)return;const t=this.chart,e=this.options.position;return"left"===e||"right"===e?{top:0,left:this.left,bottom:t.height,right:this.right}:"top"===e||"bottom"===e?{top:this.top,left:0,bottom:this.bottom,right:t.width}:void 0}drawBackground(){const{ctx:t,options:{backgroundColor:e},left:i,top:s,width:n,height:o}=this;e&&(t.save(),t.fillStyle=e,t.fillRect(i,s,n,o),t.restore())}getLineWidthForValue(t){const e=this.options.grid;if(!this._isVisible()||!e.display)return 0;const i=this.ticks.findIndex((e=>e.value===t));if(i>=0){return e.setContext(this.getContext(i)).lineWidth}return 0}drawGrid(t){const e=this.options.grid,i=this.ctx,s=this._gridLineItems||(this._gridLineItems=this._computeGridLineItems(t));let n,o;const a=(t,e,s)=>{s.width&&s.color&&(i.save(),i.lineWidth=s.width,i.strokeStyle=s.color,i.setLineDash(s.borderDash||[]),i.lineDashOffset=s.borderDashOffset,i.beginPath(),i.moveTo(t.x,t.y),i.lineTo(e.x,e.y),i.stroke(),i.restore())};if(e.display)for(n=0,o=s.length;n<o;++n){const t=s[n];e.drawOnChartArea&&a({x:t.x1,y:t.y1},{x:t.x2,y:t.y2},t),e.drawTicks&&a({x:t.tx1,y:t.ty1},{x:t.tx2,y:t.ty2},{color:t.tickColor,width:t.tickWidth,borderDash:t.tickBorderDash,borderDashOffset:t.tickBorderDashOffset})}}drawBorder(){const{chart:t,ctx:e,options:{grid:i}}=this,s=i.setContext(this.getContext()),n=i.drawBorder?s.borderWidth:0;if(!n)return;const o=i.setContext(this.getContext(0)).lineWidth,a=this._borderValue;let r,l,h,c;this.isHorizontal()?(r=Xt(t,this.left,n)-n/2,l=Xt(t,this.right,o)+o/2,h=c=a):(h=Xt(t,this.top,n)-n/2,c=Xt(t,this.bottom,o)+o/2,r=l=a),e.save(),e.lineWidth=s.borderWidth,e.strokeStyle=s.borderColor,e.beginPath(),e.moveTo(r,h),e.lineTo(l,c),e.stroke(),e.restore()}drawLabels(t){if(!this.options.ticks.display)return;const e=this.ctx,i=this._computeLabelArea();i&&Zt(e,i);const s=this._labelItems||(this._labelItems=this._computeLabelItems(t));let n,o;for(n=0,o=s.length;n<o;++n){const t=s[n],i=t.font,o=t.label;t.backdrop&&(e.fillStyle=t.backdrop.color,e.fillRect(t.backdrop.left,t.backdrop.top,t.backdrop.width,t.backdrop.height)),ee(e,o,0,t.textOffset,i,t)}i&&Qt(e)}drawTitle(){const{ctx:t,options:{position:e,title:i,reverse:s}}=this;if(!i.display)return;const o=Ve(i.font),a=Be(i.padding),r=i.align;let l=o.lineHeight/2;"bottom"===e||"center"===e||U(e)?(l+=a.bottom,Y(i.text)&&(l+=o.lineHeight*(i.text.length-1))):l+=a.top;const{titleX:h,titleY:c,maxWidth:d,rotation:u}=function(t,e,i,s){const{top:o,left:a,bottom:r,right:l,chart:h}=t,{chartArea:c,scales:d}=h;let u,f,g,p=0;const m=r-o,x=l-a;if(t.isHorizontal()){if(f=n(s,a,l),U(i)){const t=Object.keys(i)[0],s=i[t];g=d[t].getPixelForValue(s)+m-e}else g="center"===i?(c.bottom+c.top)/2+m-e:Cs(t,i,e);u=l-a}else{if(U(i)){const t=Object.keys(i)[0],s=i[t];f=d[t].getPixelForValue(s)-x+e}else f="center"===i?(c.left+c.right)/2-x+e:Cs(t,i,e);g=n(s,r,o),p="left"===i?-Mt:Mt}return{titleX:f,titleY:g,maxWidth:u,rotation:p}}(this,l,e,r);ee(t,i.text,0,0,o,{color:i.color,maxWidth:d,rotation:u,textAlign:Rs(r,e,s),textBaseline:"middle",translation:[h,c]})}draw(t){this._isVisible()&&(this.drawBackground(),this.drawGrid(t),this.drawBorder(),this.drawTitle(),this.drawLabels(t))}_layers(){const t=this.options,e=t.ticks&&t.ticks.z||0,i=K(t.grid&&t.grid.z,-1);return this._isVisible()&&this.draw===Es.prototype.draw?[{z:i,draw:t=>{this.drawBackground(),this.drawGrid(t),this.drawTitle()}},{z:i+1,draw:()=>{this.drawBorder()}},{z:e,draw:t=>{this.drawLabels(t)}}]:[{z:e,draw:t=>{this.draw(t)}}]}getMatchingVisibleMetas(t){const e=this.chart.getSortedVisibleDatasetMetas(),i=this.axis+"AxisID",s=[];let n,o;for(n=0,o=e.length;n<o;++n){const o=e[n];o[i]!==this.id||t&&o.type!==t||s.push(o)}return s}_resolveTickFontOptions(t){return Ve(this.options.ticks.setContext(this.getContext(t)).font)}_maxDigits(){const t=this._resolveTickFontOptions(0).lineHeight;return(this.isHorizontal()?this.width:this.height)/t}}class Is{constructor(t,e,i){this.type=t,this.scope=e,this.override=i,this.items=Object.create(null)}isForType(t){return Object.prototype.isPrototypeOf.call(this.type.prototype,t.prototype)}register(t){const e=Object.getPrototypeOf(t);let i;(function(t){return"id"in t&&"defaults"in t})(e)&&(i=this.register(e));const s=this.items,n=t.id,o=this.scope+"."+n;if(!n)throw new Error("class does not have id: "+t);return n in s||(s[n]=t,function(t,e,i){const s=nt(Object.create(null),[i?xt.get(i):{},xt.get(e),t.defaults]);xt.set(e,s),t.defaultRoutes&&function(t,e){Object.keys(e).forEach((i=>{const s=i.split("."),n=s.pop(),o=[t].concat(s).join("."),a=e[i].split("."),r=a.pop(),l=a.join(".");xt.route(o,n,l,r)}))}(e,t.defaultRoutes);t.descriptors&&xt.describe(e,t.descriptors)}(t,o,i),this.override&&xt.override(t.id,t.overrides)),o}get(t){return this.items[t]}unregister(t){const e=this.items,i=t.id,s=this.scope;i in e&&delete e[i],s&&i in xt[s]&&(delete xt[s][i],this.override&&delete ft[i])}}var zs=new class{constructor(){this.controllers=new Is(ws,"datasets",!0),this.elements=new Is(Ms,"elements"),this.plugins=new Is(Object,"plugins"),this.scales=new Is(Es,"scales"),this._typedRegistries=[this.controllers,this.scales,this.elements]}add(...t){this._each("register",t)}remove(...t){this._each("unregister",t)}addControllers(...t){this._each("register",t,this.controllers)}addElements(...t){this._each("register",t,this.elements)}addPlugins(...t){this._each("register",t,this.plugins)}addScales(...t){this._each("register",t,this.scales)}getController(t){return this._get(t,this.controllers,"controller")}getElement(t){return this._get(t,this.elements,"element")}getPlugin(t){return this._get(t,this.plugins,"plugin")}getScale(t){return this._get(t,this.scales,"scale")}removeControllers(...t){this._each("unregister",t,this.controllers)}removeElements(...t){this._each("unregister",t,this.elements)}removePlugins(...t){this._each("unregister",t,this.plugins)}removeScales(...t){this._each("unregister",t,this.scales)}_each(t,e,i){[...e].forEach((e=>{const s=i||this._getRegistryForType(e);i||s.isForType(e)||s===this.plugins&&e.id?this._exec(t,s,e):J(e,(e=>{const s=i||this._getRegistryForType(e);this._exec(t,s,e)}))}))}_exec(t,e,i){const s=ht(t);Q(i["before"+s],[],i),e[t](i),Q(i["after"+s],[],i)}_getRegistryForType(t){for(let e=0;e<this._typedRegistries.length;e++){const i=this._typedRegistries[e];if(i.isForType(t))return i}return this.plugins}_get(t,e,i){const s=e.get(t);if(void 0===s)throw new Error('"'+t+'" is not a registered '+i+".");return s}};class Fs{constructor(){this._init=[]}notify(t,e,i,s){"beforeInit"===e&&(this._init=this._createDescriptors(t,!0),this._notify(this._init,t,"install"));const n=s?this._descriptors(t).filter(s):this._descriptors(t),o=this._notify(n,t,e,i);return"destroy"===e&&(this._notify(n,t,"stop"),this._notify(this._init,t,"uninstall")),o}_notify(t,e,i,s){s=s||{};for(const n of t){const t=n.plugin;if(!1===Q(t[i],[e,s,n.options],t)&&s.cancelable)return!1}return!0}invalidate(){$(this._cache)||(this._oldCache=this._cache,this._cache=void 0)}_descriptors(t){if(this._cache)return this._cache;const e=this._cache=this._createDescriptors(t);return this._notifyStateChanges(t),e}_createDescriptors(t,e){const i=t&&t.config,s=K(i.options&&i.options.plugins,{}),n=function(t){const e=[],i=Object.keys(zs.plugins.items);for(let t=0;t<i.length;t++)e.push(zs.getPlugin(i[t]));const s=t.plugins||[];for(let t=0;t<s.length;t++){const i=s[t];-1===e.indexOf(i)&&e.push(i)}return e}(i);return!1!==s||e?function(t,e,i,s){const n=[],o=t.getContext();for(let a=0;a<e.length;a++){const r=e[a],l=Bs(i[r.id],s);null!==l&&n.push({plugin:r,options:Vs(t.config,r,l,o)})}return n}(t,n,s,e):[]}_notifyStateChanges(t){const e=this._oldCache||[],i=this._cache,s=(t,e)=>t.filter((t=>!e.some((e=>t.plugin.id===e.plugin.id))));this._notify(s(e,i),t,"stop"),this._notify(s(i,e),t,"start")}}function Bs(t,e){return e||!1!==t?!0===t?{}:t:null}function Vs(t,e,i,s){const n=t.pluginScopeKeys(e),o=t.getOptionScopes(i,n);return t.createResolver(o,s,[""],{scriptable:!1,indexable:!1,allKeys:!0})}function Ws(t,e){const i=xt.datasets[t]||{};return((e.datasets||{})[t]||{}).indexAxis||e.indexAxis||i.indexAxis||"x"}function Ns(t,e){return"x"===t||"y"===t?t:e.axis||("top"===(i=e.position)||"bottom"===i?"x":"left"===i||"right"===i?"y":void 0)||t.charAt(0).toLowerCase();var i}function Hs(t){const e=t.options||(t.options={});e.plugins=K(e.plugins,{}),e.scales=function(t,e){const i=ft[t.type]||{scales:{}},s=e.scales||{},n=Ws(t.type,e),o=Object.create(null),a=Object.create(null);return Object.keys(s).forEach((t=>{const e=s[t];if(!U(e))return console.error(`Invalid scale configuration for scale: ${t}`);if(e._proxy)return console.warn(`Ignoring resolver passed as options for scale: ${t}`);const r=Ns(t,e),l=function(t,e){return t===e?"_index_":"_value_"}(r,n),h=i.scales||{};o[r]=o[r]||t,a[t]=ot(Object.create(null),[{axis:r},e,h[r],h[l]])})),t.data.datasets.forEach((i=>{const n=i.type||t.type,r=i.indexAxis||Ws(n,e),l=(ft[n]||{}).scales||{};Object.keys(l).forEach((t=>{const e=function(t,e){let i=t;return"_index_"===t?i=e:"_value_"===t&&(i="x"===e?"y":"x"),i}(t,r),n=i[e+"AxisID"]||o[e]||e;a[n]=a[n]||Object.create(null),ot(a[n],[{axis:e},s[n],l[t]])}))})),Object.keys(a).forEach((t=>{const e=a[t];ot(e,[xt.scales[e.type],xt.scale])})),a}(t,e)}function js(t){return(t=t||{}).datasets=t.datasets||[],t.labels=t.labels||[],t}const $s=new Map,Ys=new Set;function Us(t,e){let i=$s.get(t);return i||(i=e(),$s.set(t,i),Ys.add(i)),i}const Xs=(t,e,i)=>{const s=lt(e,i);void 0!==s&&t.add(s)};class qs{constructor(t){this._config=function(t){return(t=t||{}).data=js(t.data),Hs(t),t}(t),this._scopeCache=new Map,this._resolverCache=new Map}get platform(){return this._config.platform}get type(){return this._config.type}set type(t){this._config.type=t}get data(){return this._config.data}set data(t){this._config.data=js(t)}get options(){return this._config.options}set options(t){this._config.options=t}get plugins(){return this._config.plugins}update(){const t=this._config;this.clearCache(),Hs(t)}clearCache(){this._scopeCache.clear(),this._resolverCache.clear()}datasetScopeKeys(t){return Us(t,(()=>[[`datasets.${t}`,""]]))}datasetAnimationScopeKeys(t,e){return Us(`${t}.transition.${e}`,(()=>[[`datasets.${t}.transitions.${e}`,`transitions.${e}`],[`datasets.${t}`,""]]))}datasetElementScopeKeys(t,e){return Us(`${t}-${e}`,(()=>[[`datasets.${t}.elements.${e}`,`datasets.${t}`,`elements.${e}`,""]]))}pluginScopeKeys(t){const e=t.id;return Us(`${this.type}-plugin-${e}`,(()=>[[`plugins.${e}`,...t.additionalOptionScopes||[]]]))}_cachedScopes(t,e){const i=this._scopeCache;let s=i.get(t);return s&&!e||(s=new Map,i.set(t,s)),s}getOptionScopes(t,e,i){const{options:s,type:n}=this,o=this._cachedScopes(t,i),a=o.get(e);if(a)return a;const r=new Set;e.forEach((e=>{t&&(r.add(t),e.forEach((e=>Xs(r,t,e)))),e.forEach((t=>Xs(r,s,t))),e.forEach((t=>Xs(r,ft[n]||{},t))),e.forEach((t=>Xs(r,xt,t))),e.forEach((t=>Xs(r,gt,t)))}));const l=Array.from(r);return 0===l.length&&l.push(Object.create(null)),Ys.has(e)&&o.set(e,l),l}chartOptionScopes(){const{options:t,type:e}=this;return[t,ft[e]||{},xt.datasets[e]||{},{type:e},xt,gt]}resolveNamedOptions(t,e,i,s=[""]){const n={$shared:!0},{resolver:o,subPrefixes:a}=Ks(this._resolverCache,t,s);let r=o;if(function(t,e){const{isScriptable:i,isIndexable:s}=ni(t);for(const n of e){const e=i(n),o=s(n),a=(o||e)&&t[n];if(e&&(dt(a)||Gs(a))||o&&Y(a))return!0}return!1}(o,e)){n.$shared=!1;r=si(o,i=dt(i)?i():i,this.createResolver(t,i,a))}for(const t of e)n[t]=r[t];return n}createResolver(t,e,i=[""],s){const{resolver:n}=Ks(this._resolverCache,t,i);return U(e)?si(n,e,void 0,s):n}}function Ks(t,e,i){let s=t.get(e);s||(s=new Map,t.set(e,s));const n=i.join();let o=s.get(n);if(!o){o={resolver:ii(e,i),subPrefixes:i.filter((t=>!t.toLowerCase().includes("hover")))},s.set(n,o)}return o}const Gs=t=>U(t)&&Object.getOwnPropertyNames(t).reduce(((e,i)=>e||dt(t[i])),!1);const Zs=["top","bottom","left","right","chartArea"];function Qs(t,e){return"top"===t||"bottom"===t||-1===Zs.indexOf(t)&&"x"===e}function Js(t,e){return function(i,s){return i[t]===s[t]?i[e]-s[e]:i[t]-s[t]}}function tn(t){const e=t.chart,i=e.options.animation;e.notifyPlugins("afterRender"),Q(i&&i.onComplete,[t],e)}function en(t){const e=t.chart,i=e.options.animation;Q(i&&i.onProgress,[t],e)}function sn(t){return ue()&&"string"==typeof t?t=document.getElementById(t):t&&t.length&&(t=t[0]),t&&t.canvas&&(t=t.canvas),t}const nn={},on=t=>{const e=sn(t);return Object.values(nn).filter((t=>t.canvas===e)).pop()};class an{constructor(t,e){const s=this.config=new qs(e),n=sn(t),o=on(n);if(o)throw new Error("Canvas is already in use. Chart with ID '"+o.id+"' must be destroyed before the canvas can be reused.");const r=s.createResolver(s.chartOptionScopes(),this.getContext());this.platform=new(s.platform||ns(n)),this.platform.updateConfig(s);const l=this.platform.acquireContext(n,r.aspectRatio),h=l&&l.canvas,c=h&&h.height,d=h&&h.width;this.id=j(),this.ctx=l,this.canvas=h,this.width=d,this.height=c,this._options=r,this._aspectRatio=this.aspectRatio,this._layers=[],this._metasets=[],this._stacks=void 0,this.boxes=[],this.currentDevicePixelRatio=void 0,this.chartArea=void 0,this._active=[],this._lastEvent=void 0,this._listeners={},this._responsiveListeners=void 0,this._sortedMetasets=[],this.scales={},this._plugins=new Fs,this.$proxies={},this._hiddenIndices={},this.attached=!1,this._animationsDisabled=void 0,this.$context=void 0,this._doResize=i((t=>this.update(t)),r.resizeDelay||0),nn[this.id]=this,l&&h?(a.listen(this,"complete",tn),a.listen(this,"progress",en),this._initialize(),this.attached&&this.update()):console.error("Failed to create chart: can't acquire context from the given item")}get aspectRatio(){const{options:{aspectRatio:t,maintainAspectRatio:e},width:i,height:s,_aspectRatio:n}=this;return $(t)?e&&n?n:s?i/s:null:t}get data(){return this.config.data}set data(t){this.config.data=t}get options(){return this._options}set options(t){this.config.options=t}_initialize(){return this.notifyPlugins("beforeInit"),this.options.responsive?this.resize():we(this,this.options.devicePixelRatio),this.bindEvents(),this.notifyPlugins("afterInit"),this}clear(){return qt(this.canvas,this.ctx),this}stop(){return a.stop(this),this}resize(t,e){a.running(this)?this._resizeBeforeDraw={width:t,height:e}:this._resize(t,e)}_resize(t,e){const i=this.options,s=this.canvas,n=i.maintainAspectRatio&&this.aspectRatio,o=this.platform.getMaximumSize(s,t,e,n),a=i.devicePixelRatio||this.platform.getDevicePixelRatio(),r=this.width?"resize":"attach";this.width=o.width,this.height=o.height,this._aspectRatio=this.aspectRatio,we(this,a,!0)&&(this.notifyPlugins("resize",{size:o}),Q(i.onResize,[this,o],this),this.attached&&this._doResize(r)&&this.render())}ensureScalesHaveIDs(){J(this.options.scales||{},((t,e)=>{t.id=e}))}buildOrUpdateScales(){const t=this.options,e=t.scales,i=this.scales,s=Object.keys(i).reduce(((t,e)=>(t[e]=!1,t)),{});let n=[];e&&(n=n.concat(Object.keys(e).map((t=>{const i=e[t],s=Ns(t,i),n="r"===s,o="x"===s;return{options:i,dposition:n?"chartArea":o?"bottom":"left",dtype:n?"radialLinear":o?"category":"linear"}})))),J(n,(e=>{const n=e.options,o=n.id,a=Ns(o,n),r=K(n.type,e.dtype);void 0!==n.position&&Qs(n.position,a)===Qs(e.dposition)||(n.position=e.dposition),s[o]=!0;let l=null;if(o in i&&i[o].type===r)l=i[o];else{l=new(zs.getScale(r))({id:o,type:r,ctx:this.ctx,chart:this}),i[l.id]=l}l.init(n,t)})),J(s,((t,e)=>{t||delete i[e]})),J(i,(t=>{ei.configure(this,t,t.options),ei.addBox(this,t)}))}_updateMetasets(){const t=this._metasets,e=this.data.datasets.length,i=t.length;if(t.sort(((t,e)=>t.index-e.index)),i>e){for(let t=e;t<i;++t)this._destroyDatasetMeta(t);t.splice(e,i-e)}this._sortedMetasets=t.slice(0).sort(Js("order","index"))}_removeUnreferencedMetasets(){const{_metasets:t,data:{datasets:e}}=this;t.length>e.length&&delete this._stacks,t.forEach(((t,i)=>{0===e.filter((e=>e===t._dataset)).length&&this._destroyDatasetMeta(i)}))}buildOrUpdateControllers(){const t=[],e=this.data.datasets;let i,s;for(this._removeUnreferencedMetasets(),i=0,s=e.length;i<s;i++){const s=e[i];let n=this.getDatasetMeta(i);const o=s.type||this.config.type;if(n.type&&n.type!==o&&(this._destroyDatasetMeta(i),n=this.getDatasetMeta(i)),n.type=o,n.indexAxis=s.indexAxis||Ws(o,this.options),n.order=s.order||0,n.index=i,n.label=""+s.label,n.visible=this.isDatasetVisible(i),n.controller)n.controller.updateIndex(i),n.controller.linkScales();else{const e=zs.getController(o),{datasetElementType:s,dataElementType:a}=xt.datasets[o];Object.assign(e.prototype,{dataElementType:zs.getElement(a),datasetElementType:s&&zs.getElement(s)}),n.controller=new e(this,i),t.push(n.controller)}}return this._updateMetasets(),t}_resetElements(){J(this.data.datasets,((t,e)=>{this.getDatasetMeta(e).controller.reset()}),this)}reset(){this._resetElements(),this.notifyPlugins("reset")}update(t){const e=this.config;e.update();const i=this._options=e.createResolver(e.chartOptionScopes(),this.getContext());J(this.scales,(t=>{ei.removeBox(this,t)}));const s=this._animationsDisabled=!i.animation;this.ensureScalesHaveIDs(),this.buildOrUpdateScales();const n=new Set(Object.keys(this._listeners)),o=new Set(i.events);if(ut(n,o)&&!!this._responsiveListeners===i.responsive||(this.unbindEvents(),this.bindEvents()),this._plugins.invalidate(),!1===this.notifyPlugins("beforeUpdate",{mode:t,cancelable:!0}))return;const a=this.buildOrUpdateControllers();this.notifyPlugins("beforeElementsUpdate");let r=0;for(let t=0,e=this.data.datasets.length;t<e;t++){const{controller:e}=this.getDatasetMeta(t),i=!s&&-1===a.indexOf(e);e.buildOrUpdateElements(i),r=Math.max(+e.getMaxOverflow(),r)}r=this._minPadding=i.layout.autoPadding?r:0,this._updateLayout(r),s||J(a,(t=>{t.reset()})),this._updateDatasets(t),this.notifyPlugins("afterUpdate",{mode:t}),this._layers.sort(Js("z","_idx")),this._lastEvent&&this._eventHandler(this._lastEvent,!0),this.render()}_updateLayout(t){if(!1===this.notifyPlugins("beforeLayout",{cancelable:!0}))return;ei.update(this,this.width,this.height,t);const e=this.chartArea,i=e.width<=0||e.height<=0;this._layers=[],J(this.boxes,(t=>{i&&"chartArea"===t.position||(t.configure&&t.configure(),this._layers.push(...t._layers()))}),this),this._layers.forEach(((t,e)=>{t._idx=e})),this.notifyPlugins("afterLayout")}_updateDatasets(t){if(!1!==this.notifyPlugins("beforeDatasetsUpdate",{mode:t,cancelable:!0})){for(let e=0,i=this.data.datasets.length;e<i;++e)this._updateDataset(e,dt(t)?t({datasetIndex:e}):t);this.notifyPlugins("afterDatasetsUpdate",{mode:t})}}_updateDataset(t,e){const i=this.getDatasetMeta(t),s={meta:i,index:t,mode:e,cancelable:!0};!1!==this.notifyPlugins("beforeDatasetUpdate",s)&&(i.controller._update(e),s.cancelable=!1,this.notifyPlugins("afterDatasetUpdate",s))}render(){!1!==this.notifyPlugins("beforeRender",{cancelable:!0})&&(a.has(this)?this.attached&&!a.running(this)&&a.start(this):(this.draw(),tn({chart:this})))}draw(){let t;if(this._resizeBeforeDraw){const{width:t,height:e}=this._resizeBeforeDraw;this._resize(t,e),this._resizeBeforeDraw=null}if(this.clear(),this.width<=0||this.height<=0)return;if(!1===this.notifyPlugins("beforeDraw",{cancelable:!0}))return;const e=this._layers;for(t=0;t<e.length&&e[t].z<=0;++t)e[t].draw(this.chartArea);for(this._drawDatasets();t<e.length;++t)e[t].draw(this.chartArea);this.notifyPlugins("afterDraw")}_getSortedDatasetMetas(t){const e=this._sortedMetasets,i=[];let s,n;for(s=0,n=e.length;s<n;++s){const n=e[s];t&&!n.visible||i.push(n)}return i}getSortedVisibleDatasetMetas(){return this._getSortedDatasetMetas(!0)}_drawDatasets(){if(!1===this.notifyPlugins("beforeDatasetsDraw",{cancelable:!0}))return;const t=this.getSortedVisibleDatasetMetas();for(let e=t.length-1;e>=0;--e)this._drawDataset(t[e]);this.notifyPlugins("afterDatasetsDraw")}_drawDataset(t){const e=this.ctx,i=t._clip,s=!i.disabled,n=this.chartArea,o={meta:t,index:t.index,cancelable:!0};!1!==this.notifyPlugins("beforeDatasetDraw",o)&&(s&&Zt(e,{left:!1===i.left?0:n.left-i.left,right:!1===i.right?this.width:n.right+i.right,top:!1===i.top?0:n.top-i.top,bottom:!1===i.bottom?this.height:n.bottom+i.bottom}),t.controller.draw(),s&&Qt(e),o.cancelable=!1,this.notifyPlugins("afterDatasetDraw",o))}getElementsAtEventForMode(t,e,i,s){const n=Te.modes[e];return"function"==typeof n?n(this,t,i,s):[]}getDatasetMeta(t){const e=this.data.datasets[t],i=this._metasets;let s=i.filter((t=>t&&t._dataset===e)).pop();return s||(s={type:null,data:[],dataset:null,controller:null,hidden:null,xAxisID:null,yAxisID:null,order:e&&e.order||0,index:t,_dataset:e,_parsed:[],_sorted:!1},i.push(s)),s}getContext(){return this.$context||(this.$context=He(null,{chart:this,type:"chart"}))}getVisibleDatasetCount(){return this.getSortedVisibleDatasetMetas().length}isDatasetVisible(t){const e=this.data.datasets[t];if(!e)return!1;const i=this.getDatasetMeta(t);return"boolean"==typeof i.hidden?!i.hidden:!e.hidden}setDatasetVisibility(t,e){this.getDatasetMeta(t).hidden=!e}toggleDataVisibility(t){this._hiddenIndices[t]=!this._hiddenIndices[t]}getDataVisibility(t){return!this._hiddenIndices[t]}_updateVisibility(t,e,i){const s=i?"show":"hide",n=this.getDatasetMeta(t),o=n.controller._resolveAnimations(void 0,s);ct(e)?(n.data[e].hidden=!i,this.update()):(this.setDatasetVisibility(t,i),o.update(n,{visible:i}),this.update((e=>e.datasetIndex===t?s:void 0)))}hide(t,e){this._updateVisibility(t,e,!1)}show(t,e){this._updateVisibility(t,e,!0)}_destroyDatasetMeta(t){const e=this._metasets[t];e&&e.controller&&e.controller._destroy(),delete this._metasets[t]}_stop(){let t,e;for(this.stop(),a.remove(this),t=0,e=this.data.datasets.length;t<e;++t)this._destroyDatasetMeta(t)}destroy(){const{canvas:t,ctx:e}=this;this._stop(),this.config.clearCache(),t&&(this.unbindEvents(),qt(t,e),this.platform.releaseContext(e),this.canvas=null,this.ctx=null),this.notifyPlugins("destroy"),delete nn[this.id]}toBase64Image(...t){return this.canvas.toDataURL(...t)}bindEvents(){this.bindUserEvents(),this.options.responsive?this.bindResponsiveEvents():this.attached=!0}bindUserEvents(){const t=this._listeners,e=this.platform,i=(i,s)=>{e.addEventListener(this,i,s),t[i]=s},s=(t,e,i)=>{t.offsetX=e,t.offsetY=i,this._eventHandler(t)};J(this.options.events,(t=>i(t,s)))}bindResponsiveEvents(){this._responsiveListeners||(this._responsiveListeners={});const t=this._responsiveListeners,e=this.platform,i=(i,s)=>{e.addEventListener(this,i,s),t[i]=s},s=(i,s)=>{t[i]&&(e.removeEventListener(this,i,s),delete t[i])},n=(t,e)=>{this.canvas&&this.resize(t,e)};let o;const a=()=>{s("attach",a),this.attached=!0,this.resize(),i("resize",n),i("detach",o)};o=()=>{this.attached=!1,s("resize",n),this._stop(),this._resize(0,0),i("attach",a)},e.isAttached(this.canvas)?a():o()}unbindEvents(){J(this._listeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._listeners={},J(this._responsiveListeners,((t,e)=>{this.platform.removeEventListener(this,e,t)})),this._responsiveListeners=void 0}updateHoverStyle(t,e,i){const s=i?"set":"remove";let n,o,a,r;for("dataset"===e&&(n=this.getDatasetMeta(t[0].datasetIndex),n.controller["_"+s+"DatasetHoverStyle"]()),a=0,r=t.length;a<r;++a){o=t[a];const e=o&&this.getDatasetMeta(o.datasetIndex).controller;e&&e[s+"HoverStyle"](o.element,o.datasetIndex,o.index)}}getActiveElements(){return this._active||[]}setActiveElements(t){const e=this._active||[],i=t.map((({datasetIndex:t,index:e})=>{const i=this.getDatasetMeta(t);if(!i)throw new Error("No dataset found at index "+t);return{datasetIndex:t,element:i.data[e],index:e}}));!tt(i,e)&&(this._active=i,this._updateHoverStyles(i,e))}notifyPlugins(t,e,i){return this._plugins.notify(this,t,e,i)}_updateHoverStyles(t,e,i){const s=this.options.hover,n=(t,e)=>t.filter((t=>!e.some((e=>t.datasetIndex===e.datasetIndex&&t.index===e.index)))),o=n(e,t),a=i?t:n(t,e);o.length&&this.updateHoverStyle(o,s.mode,!1),a.length&&s.mode&&this.updateHoverStyle(a,s.mode,!0)}_eventHandler(t,e){const i={event:t,replay:e,cancelable:!0},s=e=>(e.options.events||this.options.events).includes(t.native.type);if(!1===this.notifyPlugins("beforeEvent",i,s))return;const n=this._handleEvent(t,e);return i.cancelable=!1,this.notifyPlugins("afterEvent",i,s),(n||i.changed)&&this.render(),this}_handleEvent(t,e){const{_active:i=[],options:s}=this,n=s.hover,o=e;let a=[],r=!1,l=null;return"mouseout"!==t.type&&(a=this.getElementsAtEventForMode(t,n.mode,n,o),l="click"===t.type?this._lastEvent:t),this._lastEvent=null,Gt(t,this.chartArea,this._minPadding)&&(Q(s.onHover,[t,a,this],this),"mouseup"!==t.type&&"click"!==t.type&&"contextmenu"!==t.type||Q(s.onClick,[t,a,this],this)),r=!tt(a,i),(r||e)&&(this._active=a,this._updateHoverStyles(a,i,e)),this._lastEvent=l,r}}const rn=()=>J(an.instances,(t=>t._plugins.invalidate())),ln=!0;function hn(){throw new Error("This method is not implemented: Check that a complete date adapter is provided.")}Object.defineProperties(an,{defaults:{enumerable:ln,value:xt},instances:{enumerable:ln,value:nn},overrides:{enumerable:ln,value:ft},registry:{enumerable:ln,value:zs},version:{enumerable:ln,value:"3.6.0"},getChart:{enumerable:ln,value:on},register:{enumerable:ln,value:(...t)=>{zs.add(...t),rn()}},unregister:{enumerable:ln,value:(...t)=>{zs.remove(...t),rn()}}});class cn{constructor(t){this.options=t||{}}formats(){return hn()}parse(t,e){return hn()}format(t,e){return hn()}add(t,e,i){return hn()}diff(t,e,i){return hn()}startOf(t,e,i){return hn()}endOf(t,e){return hn()}}cn.override=function(t){Object.assign(cn.prototype,t)};var dn={_date:cn};function un(t){const e=t.iScale,i=function(t,e){if(!t._cache.$bar){const i=t.getMatchingVisibleMetas(e);let s=[];for(let e=0,n=i.length;e<n;e++)s=s.concat(i[e].controller.getAllParsedValues(t));t._cache.$bar=de(s.sort(((t,e)=>t-e)))}return t._cache.$bar}(e,t.type);let s,n,o,a,r=e._length;const l=()=>{32767!==o&&-32768!==o&&(ct(a)&&(r=Math.min(r,Math.abs(o-a)||r)),a=o)};for(s=0,n=i.length;s<n;++s)o=e.getPixelForValue(i[s]),l();for(a=void 0,s=0,n=e.ticks.length;s<n;++s)o=e.getPixelForTick(s),l();return r}function fn(t,e,i,s){return Y(t)?function(t,e,i,s){const n=i.parse(t[0],s),o=i.parse(t[1],s),a=Math.min(n,o),r=Math.max(n,o);let l=a,h=r;Math.abs(a)>Math.abs(r)&&(l=r,h=a),e[i.axis]=h,e._custom={barStart:l,barEnd:h,start:n,end:o,min:a,max:r}}(t,e,i,s):e[i.axis]=i.parse(t,s),e}function gn(t,e,i,s){const n=t.iScale,o=t.vScale,a=n.getLabels(),r=n===o,l=[];let h,c,d,u;for(h=i,c=i+s;h<c;++h)u=e[h],d={},d[n.axis]=r||n.parse(a[h],h),l.push(fn(u,d,o,h));return l}function pn(t){return t&&void 0!==t.barStart&&void 0!==t.barEnd}function mn(t,e,i,s){let n=e.borderSkipped;const o={};if(!n)return void(t.borderSkipped=o);const{start:a,end:r,reverse:l,top:h,bottom:c}=function(t){let e,i,s,n,o;return t.horizontal?(e=t.base>t.x,i="left",s="right"):(e=t.base<t.y,i="bottom",s="top"),e?(n="end",o="start"):(n="start",o="end"),{start:i,end:s,reverse:e,top:n,bottom:o}}(t);"middle"===n&&i&&(t.enableBorderRadius=!0,(i._top||0)===s?n=h:(i._bottom||0)===s?n=c:(o[xn(c,a,r,l)]=!0,n=h)),o[xn(n,a,r,l)]=!0,t.borderSkipped=o}function xn(t,e,i,s){var n,o,a;return s?(a=i,t=bn(t=(n=t)===(o=e)?a:n===a?o:n,i,e)):t=bn(t,e,i),t}function bn(t,e,i){return"start"===t?e:"end"===t?i:t}function _n(t,{inflateAmount:e},i){t.inflateAmount="auto"===e?1===i?.33:0:e}class yn extends ws{parsePrimitiveData(t,e,i,s){return gn(t,e,i,s)}parseArrayData(t,e,i,s){return gn(t,e,i,s)}parseObjectData(t,e,i,s){const{iScale:n,vScale:o}=t,{xAxisKey:a="x",yAxisKey:r="y"}=this._parsing,l="x"===n.axis?a:r,h="x"===o.axis?a:r,c=[];let d,u,f,g;for(d=i,u=i+s;d<u;++d)g=e[d],f={},f[n.axis]=n.parse(lt(g,l),d),c.push(fn(lt(g,h),f,o,d));return c}updateRangeFromParsed(t,e,i,s){super.updateRangeFromParsed(t,e,i,s);const n=i._custom;n&&e===this._cachedMeta.vScale&&(t.min=Math.min(t.min,n.min),t.max=Math.max(t.max,n.max))}getMaxOverflow(){return 0}getLabelAndValue(t){const e=this._cachedMeta,{iScale:i,vScale:s}=e,n=this.getParsed(t),o=n._custom,a=pn(o)?"["+o.start+", "+o.end+"]":""+s.getLabelForValue(n[s.axis]);return{label:""+i.getLabelForValue(n[i.axis]),value:a}}initialize(){this.enableOptionSharing=!0,super.initialize();this._cachedMeta.stack=this.getDataset().stack}update(t){const e=this._cachedMeta;this.updateElements(e.data,0,e.data.length,t)}updateElements(t,e,i,s){const n="reset"===s,{index:o,_cachedMeta:{vScale:a}}=this,r=a.getBasePixel(),l=a.isHorizontal(),h=this._getRuler(),c=this.resolveDataElementOptions(e,s),d=this.getSharedOptions(c),u=this.includeOptions(s,d);this.updateSharedOptions(d,s,c);for(let c=e;c<e+i;c++){const e=this.getParsed(c),i=n||$(e[a.axis])?{base:r,head:r}:this._calculateBarValuePixels(c),f=this._calculateBarIndexPixels(c,h),g=(e._stacks||{})[a.axis],p={horizontal:l,base:i.base,enableBorderRadius:!g||pn(e._custom)||o===g._top||o===g._bottom,x:l?i.head:f.center,y:l?f.center:i.head,height:l?f.size:Math.abs(i.size),width:l?Math.abs(i.size):f.size};u&&(p.options=d||this.resolveDataElementOptions(c,t[c].active?"active":s));const m=p.options||t[c].options;mn(p,m,g,o),_n(p,m,h.ratio),this.updateElement(t[c],c,p,s)}}_getStacks(t,e){const i=this._cachedMeta.iScale,s=i.getMatchingVisibleMetas(this._type),n=i.options.stacked,o=s.length,a=[];let r,l;for(r=0;r<o;++r)if(l=s[r],l.controller.options.grouped){if(void 0!==e){const t=l.controller.getParsed(e)[l.controller._cachedMeta.vScale.axis];if($(t)||isNaN(t))continue}if((!1===n||-1===a.indexOf(l.stack)||void 0===n&&void 0===l.stack)&&a.push(l.stack),l.index===t)break}return a.length||a.push(void 0),a}_getStackCount(t){return this._getStacks(void 0,t).length}_getStackIndex(t,e,i){const s=this._getStacks(t,i),n=void 0!==e?s.indexOf(e):-1;return-1===n?s.length-1:n}_getRuler(){const t=this.options,e=this._cachedMeta,i=e.iScale,s=[];let n,o;for(n=0,o=e.data.length;n<o;++n)s.push(i.getPixelForValue(this.getParsed(n)[i.axis],n));const a=t.barThickness;return{min:a||un(e),pixels:s,start:i._startPixel,end:i._endPixel,stackCount:this._getStackCount(),scale:i,grouped:t.grouped,ratio:a?1:t.categoryPercentage*t.barPercentage}}_calculateBarValuePixels(t){const{_cachedMeta:{vScale:e,_stacked:i},options:{base:s,minBarLength:n}}=this,o=s||0,a=this.getParsed(t),r=a._custom,l=pn(r);let h,c,d=a[e.axis],u=0,f=i?this.applyStack(e,a,i):d;f!==d&&(u=f-d,f=d),l&&(d=r.barStart,f=r.barEnd-r.barStart,0!==d&&Dt(d)!==Dt(r.barEnd)&&(u=0),u+=d);const g=$(s)||l?u:s;let p=e.getPixelForValue(g);if(h=this.chart.getDataVisibility(t)?e.getPixelForValue(u+f):p,c=h-p,Math.abs(c)<n&&(c=function(t,e,i){return 0!==t?Dt(t):(e.isHorizontal()?1:-1)*(e.min>=i?1:-1)}(c,e,o)*n,d===o&&(p-=c/2),h=p+c),p===e.getPixelForValue(o)){const t=Dt(c)*e.getLineWidthForValue(o)/2;p+=t,c-=t}return{size:c,base:p,head:h,center:h+c/2}}_calculateBarIndexPixels(t,e){const i=e.scale,s=this.options,n=s.skipNull,o=K(s.maxBarThickness,1/0);let a,r;if(e.grouped){const i=n?this._getStackCount(t):e.stackCount,l="flex"===s.barThickness?function(t,e,i,s){const n=e.pixels,o=n[t];let a=t>0?n[t-1]:null,r=t<n.length-1?n[t+1]:null;const l=i.categoryPercentage;null===a&&(a=o-(null===r?e.end-e.start:r-o)),null===r&&(r=o+o-a);const h=o-(o-Math.min(a,r))/2*l;return{chunk:Math.abs(r-a)/2*l/s,ratio:i.barPercentage,start:h}}(t,e,s,i):function(t,e,i,s){const n=i.barThickness;let o,a;return $(n)?(o=e.min*i.categoryPercentage,a=i.barPercentage):(o=n*s,a=1),{chunk:o/s,ratio:a,start:e.pixels[t]-o/2}}(t,e,s,i),h=this._getStackIndex(this.index,this._cachedMeta.stack,n?t:void 0);a=l.start+l.chunk*h+l.chunk/2,r=Math.min(o,l.chunk*l.ratio)}else a=i.getPixelForValue(this.getParsed(t)[i.axis],t),r=Math.min(o,e.min*e.ratio);return{base:a-r/2,head:a+r/2,center:a,size:r}}draw(){const t=this._cachedMeta,e=t.vScale,i=t.data,s=i.length;let n=0;for(;n<s;++n)null!==this.getParsed(n)[e.axis]&&i[n].draw(this._ctx)}}yn.id="bar",yn.defaults={datasetElementType:!1,dataElementType:"bar",categoryPercentage:.8,barPercentage:.9,grouped:!0,animations:{numbers:{type:"number",properties:["x","y","base","width","height"]}}},yn.overrides={scales:{_index_:{type:"category",offset:!0,grid:{offset:!0}},_value_:{type:"linear",beginAtZero:!0}}};class vn extends ws{initialize(){this.enableOptionSharing=!0,super.initialize()}parsePrimitiveData(t,e,i,s){const n=super.parsePrimitiveData(t,e,i,s);for(let t=0;t<n.length;t++)n[t]._custom=this.resolveDataElementOptions(t+i).radius;return n}parseArrayData(t,e,i,s){const n=super.parseArrayData(t,e,i,s);for(let t=0;t<n.length;t++){const s=e[i+t];n[t]._custom=K(s[2],this.resolveDataElementOptions(t+i).radius)}return n}parseObjectData(t,e,i,s){const n=super.parseObjectData(t,e,i,s);for(let t=0;t<n.length;t++){const s=e[i+t];n[t]._custom=K(s&&s.r&&+s.r,this.resolveDataElementOptions(t+i).radius)}return n}getMaxOverflow(){const t=this._cachedMeta.data;let e=0;for(let i=t.length-1;i>=0;--i)e=Math.max(e,t[i].size(this.resolveDataElementOptions(i))/2);return e>0&&e}getLabelAndValue(t){const e=this._cachedMeta,{xScale:i,yScale:s}=e,n=this.getParsed(t),o=i.getLabelForValue(n.x),a=s.getLabelForValue(n.y),r=n._custom;return{label:e.label,value:"("+o+", "+a+(r?", "+r:"")+")"}}update(t){const e=this._cachedMeta.data;this.updateElements(e,0,e.length,t)}updateElements(t,e,i,s){const n="reset"===s,{iScale:o,vScale:a}=this._cachedMeta,r=this.resolveDataElementOptions(e,s),l=this.getSharedOptions(r),h=this.includeOptions(s,l),c=o.axis,d=a.axis;for(let r=e;r<e+i;r++){const e=t[r],i=!n&&this.getParsed(r),l={},u=l[c]=n?o.getPixelForDecimal(.5):o.getPixelForValue(i[c]),f=l[d]=n?a.getBasePixel():a.getPixelForValue(i[d]);l.skip=isNaN(u)||isNaN(f),h&&(l.options=this.resolveDataElementOptions(r,e.active?"active":s),n&&(l.options.radius=0)),this.updateElement(e,r,l,s)}this.updateSharedOptions(l,s,r)}resolveDataElementOptions(t,e){const i=this.getParsed(t);let s=super.resolveDataElementOptions(t,e);s.$shared&&(s=Object.assign({},s,{$shared:!1}));const n=s.radius;return"active"!==e&&(s.radius=0),s.radius+=K(i&&i._custom,n),s}}vn.id="bubble",vn.defaults={datasetElementType:!1,dataElementType:"point",animations:{numbers:{type:"number",properties:["x","y","borderWidth","radius"]}}},vn.overrides={scales:{x:{type:"linear"},y:{type:"linear"}},plugins:{tooltip:{callbacks:{title:()=>""}}}};class wn extends ws{constructor(t,e){super(t,e),this.enableOptionSharing=!0,this.innerRadius=void 0,this.outerRadius=void 0,this.offsetX=void 0,this.offsetY=void 0}linkScales(){}parse(t,e){const i=this.getDataset().data,s=this._cachedMeta;if(!1===this._parsing)s._parsed=i;else{let n,o,a=t=>+i[t];if(U(i[t])){const{key:t="value"}=this._parsing;a=e=>+lt(i[e],t)}for(n=t,o=t+e;n<o;++n)s._parsed[n]=a(n)}}_getRotation(){return Et(this.options.rotation-90)}_getCircumference(){return Et(this.options.circumference)}_getRotationExtents(){let t=_t,e=-_t;for(let i=0;i<this.chart.data.datasets.length;++i)if(this.chart.isDatasetVisible(i)){const s=this.chart.getDatasetMeta(i).controller,n=s._getRotation(),o=s._getCircumference();t=Math.min(t,n),e=Math.max(e,n+o)}return{rotation:t,circumference:e-t}}update(t){const e=this.chart,{chartArea:i}=e,s=this._cachedMeta,n=s.data,o=this.getMaxBorderWidth()+this.getMaxOffset(n)+this.options.spacing,a=Math.max((Math.min(i.width,i.height)-o)/2,0),r=Math.min(G(this.options.cutout,a),1),l=this._getRingWeight(this.index),{circumference:h,rotation:c}=this._getRotationExtents(),{ratioX:d,ratioY:u,offsetX:f,offsetY:g}=function(t,e,i){let s=1,n=1,o=0,a=0;if(e<_t){const r=t,l=r+e,h=Math.cos(r),c=Math.sin(r),d=Math.cos(l),u=Math.sin(l),f=(t,e,s)=>Nt(t,r,l,!0)?1:Math.max(e,e*i,s,s*i),g=(t,e,s)=>Nt(t,r,l,!0)?-1:Math.min(e,e*i,s,s*i),p=f(0,h,d),m=f(Mt,c,u),x=g(bt,h,d),b=g(bt+Mt,c,u);s=(p-x)/2,n=(m-b)/2,o=-(p+x)/2,a=-(m+b)/2}return{ratioX:s,ratioY:n,offsetX:o,offsetY:a}}(c,h,r),p=(i.width-o)/d,m=(i.height-o)/u,x=Math.max(Math.min(p,m)/2,0),b=Z(this.options.radius,x),_=(b-Math.max(b*r,0))/this._getVisibleDatasetWeightTotal();this.offsetX=f*b,this.offsetY=g*b,s.total=this.calculateTotal(),this.outerRadius=b-_*this._getRingWeightOffset(this.index),this.innerRadius=Math.max(this.outerRadius-_*l,0),this.updateElements(n,0,n.length,t)}_circumference(t,e){const i=this.options,s=this._cachedMeta,n=this._getCircumference();return e&&i.animation.animateRotate||!this.chart.getDataVisibility(t)||null===s._parsed[t]||s.data[t].hidden?0:this.calculateCircumference(s._parsed[t]*n/_t)}updateElements(t,e,i,s){const n="reset"===s,o=this.chart,a=o.chartArea,r=o.options.animation,l=(a.left+a.right)/2,h=(a.top+a.bottom)/2,c=n&&r.animateScale,d=c?0:this.innerRadius,u=c?0:this.outerRadius,f=this.resolveDataElementOptions(e,s),g=this.getSharedOptions(f),p=this.includeOptions(s,g);let m,x=this._getRotation();for(m=0;m<e;++m)x+=this._circumference(m,n);for(m=e;m<e+i;++m){const e=this._circumference(m,n),i=t[m],o={x:l+this.offsetX,y:h+this.offsetY,startAngle:x,endAngle:x+e,circumference:e,outerRadius:u,innerRadius:d};p&&(o.options=g||this.resolveDataElementOptions(m,i.active?"active":s)),x+=e,this.updateElement(i,m,o,s)}this.updateSharedOptions(g,s,f)}calculateTotal(){const t=this._cachedMeta,e=t.data;let i,s=0;for(i=0;i<e.length;i++){const n=t._parsed[i];null===n||isNaN(n)||!this.chart.getDataVisibility(i)||e[i].hidden||(s+=Math.abs(n))}return s}calculateCircumference(t){const e=this._cachedMeta.total;return e>0&&!isNaN(t)?_t*(Math.abs(t)/e):0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=Ai(e._parsed[t],i.options.locale);return{label:s[t]||"",value:n}}getMaxBorderWidth(t){let e=0;const i=this.chart;let s,n,o,a,r;if(!t)for(s=0,n=i.data.datasets.length;s<n;++s)if(i.isDatasetVisible(s)){o=i.getDatasetMeta(s),t=o.data,a=o.controller,a!==this&&a.configure();break}if(!t)return 0;for(s=0,n=t.length;s<n;++s)r=a.resolveDataElementOptions(s),"inner"!==r.borderAlign&&(e=Math.max(e,r.borderWidth||0,r.hoverBorderWidth||0));return e}getMaxOffset(t){let e=0;for(let i=0,s=t.length;i<s;++i){const t=this.resolveDataElementOptions(i);e=Math.max(e,t.offset||0,t.hoverOffset||0)}return e}_getRingWeightOffset(t){let e=0;for(let i=0;i<t;++i)this.chart.isDatasetVisible(i)&&(e+=this._getRingWeight(i));return e}_getRingWeight(t){return Math.max(K(this.chart.data.datasets[t].weight,1),0)}_getVisibleDatasetWeightTotal(){return this._getRingWeightOffset(this.chart.data.datasets.length)||1}}wn.id="doughnut",wn.defaults={datasetElementType:!1,dataElementType:"arc",animation:{animateRotate:!0,animateScale:!1},animations:{numbers:{type:"number",properties:["circumference","endAngle","innerRadius","outerRadius","startAngle","x","y","offset","borderWidth","spacing"]}},cutout:"50%",rotation:0,circumference:360,radius:"100%",spacing:0,indexAxis:"r"},wn.descriptors={_scriptable:t=>"spacing"!==t,_indexable:t=>"spacing"!==t},wn.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,s)=>{const n=t.getDatasetMeta(0).controller.getStyle(s);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(s),index:s}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label(t){let e=t.label;const i=": "+t.formattedValue;return Y(e)?(e=e.slice(),e[0]+=i):e+=i,e}}}}};class Mn extends ws{initialize(){this.enableOptionSharing=!0,super.initialize()}update(t){const e=this._cachedMeta,{dataset:i,data:s=[],_dataset:n}=e,o=this.chart._animationsDisabled;let{start:a,count:r}=function(t,e,i){const s=e.length;let n=0,o=s;if(t._sorted){const{iScale:a,_parsed:r}=t,l=a.axis,{min:h,max:c,minDefined:d,maxDefined:u}=a.getUserBounds();d&&(n=Ht(Math.min(oe(r,a.axis,h).lo,i?s:oe(e,l,a.getPixelForValue(h)).lo),0,s-1)),o=u?Ht(Math.max(oe(r,a.axis,c).hi+1,i?0:oe(e,l,a.getPixelForValue(c)).hi+1),n,s)-n:s-n}return{start:n,count:o}}(e,s,o);this._drawStart=a,this._drawCount=r,function(t){const{xScale:e,yScale:i,_scaleRanges:s}=t,n={xmin:e.min,xmax:e.max,ymin:i.min,ymax:i.max};if(!s)return t._scaleRanges=n,!0;const o=s.xmin!==e.min||s.xmax!==e.max||s.ymin!==i.min||s.ymax!==i.max;return Object.assign(s,n),o}(e)&&(a=0,r=s.length),i._chart=this.chart,i._datasetIndex=this.index,i._decimated=!!n._decimated,i.points=s;const l=this.resolveDatasetElementOptions(t);this.options.showLine||(l.borderWidth=0),l.segment=this.options.segment,this.updateElement(i,void 0,{animated:!o,options:l},t),this.updateElements(s,a,r,t)}updateElements(t,e,i,s){const n="reset"===s,{iScale:o,vScale:a,_stacked:r,_dataset:l}=this._cachedMeta,h=this.resolveDataElementOptions(e,s),c=this.getSharedOptions(h),d=this.includeOptions(s,c),u=o.axis,f=a.axis,{spanGaps:g,segment:p}=this.options,m=At(g)?g:Number.POSITIVE_INFINITY,x=this.chart._animationsDisabled||n||"none"===s;let b=e>0&&this.getParsed(e-1);for(let h=e;h<e+i;++h){const e=t[h],i=this.getParsed(h),g=x?e:{},_=$(i[f]),y=g[u]=o.getPixelForValue(i[u],h),v=g[f]=n||_?a.getBasePixel():a.getPixelForValue(r?this.applyStack(a,i,r):i[f],h);g.skip=isNaN(y)||isNaN(v)||_,g.stop=h>0&&i[u]-b[u]>m,p&&(g.parsed=i,g.raw=l.data[h]),d&&(g.options=c||this.resolveDataElementOptions(h,e.active?"active":s)),x||this.updateElement(e,h,g,s),b=i}this.updateSharedOptions(c,s,h)}getMaxOverflow(){const t=this._cachedMeta,e=t.dataset,i=e.options&&e.options.borderWidth||0,s=t.data||[];if(!s.length)return i;const n=s[0].size(this.resolveDataElementOptions(0)),o=s[s.length-1].size(this.resolveDataElementOptions(s.length-1));return Math.max(i,n,o)/2}draw(){const t=this._cachedMeta;t.dataset.updateControlPoints(this.chart.chartArea,t.iScale.axis),super.draw()}}Mn.id="line",Mn.defaults={datasetElementType:"line",dataElementType:"point",showLine:!0,spanGaps:!1},Mn.overrides={scales:{_index_:{type:"category"},_value_:{type:"linear"}}};class kn extends ws{constructor(t,e){super(t,e),this.innerRadius=void 0,this.outerRadius=void 0}getLabelAndValue(t){const e=this._cachedMeta,i=this.chart,s=i.data.labels||[],n=Ai(e._parsed[t].r,i.options.locale);return{label:s[t]||"",value:n}}update(t){const e=this._cachedMeta.data;this._updateRadius(),this.updateElements(e,0,e.length,t)}_updateRadius(){const t=this.chart,e=t.chartArea,i=t.options,s=Math.min(e.right-e.left,e.bottom-e.top),n=Math.max(s/2,0),o=(n-Math.max(i.cutoutPercentage?n/100*i.cutoutPercentage:1,0))/t.getVisibleDatasetCount();this.outerRadius=n-o*this.index,this.innerRadius=this.outerRadius-o}updateElements(t,e,i,s){const n="reset"===s,o=this.chart,a=this.getDataset(),r=o.options.animation,l=this._cachedMeta.rScale,h=l.xCenter,c=l.yCenter,d=l.getIndexAngle(0)-.5*bt;let u,f=d;const g=360/this.countVisibleElements();for(u=0;u<e;++u)f+=this._computeAngle(u,s,g);for(u=e;u<e+i;u++){const e=t[u];let i=f,p=f+this._computeAngle(u,s,g),m=o.getDataVisibility(u)?l.getDistanceFromCenterForValue(a.data[u]):0;f=p,n&&(r.animateScale&&(m=0),r.animateRotate&&(i=p=d));const x={x:h,y:c,innerRadius:0,outerRadius:m,startAngle:i,endAngle:p,options:this.resolveDataElementOptions(u,e.active?"active":s)};this.updateElement(e,u,x,s)}}countVisibleElements(){const t=this.getDataset(),e=this._cachedMeta;let i=0;return e.data.forEach(((e,s)=>{!isNaN(t.data[s])&&this.chart.getDataVisibility(s)&&i++})),i}_computeAngle(t,e,i){return this.chart.getDataVisibility(t)?Et(this.resolveDataElementOptions(t,e).angle||i):0}}kn.id="polarArea",kn.defaults={dataElementType:"arc",animation:{animateRotate:!0,animateScale:!0},animations:{numbers:{type:"number",properties:["x","y","startAngle","endAngle","innerRadius","outerRadius"]}},indexAxis:"r",startAngle:0},kn.overrides={aspectRatio:1,plugins:{legend:{labels:{generateLabels(t){const e=t.data;if(e.labels.length&&e.datasets.length){const{labels:{pointStyle:i}}=t.legend.options;return e.labels.map(((e,s)=>{const n=t.getDatasetMeta(0).controller.getStyle(s);return{text:e,fillStyle:n.backgroundColor,strokeStyle:n.borderColor,lineWidth:n.borderWidth,pointStyle:i,hidden:!t.getDataVisibility(s),index:s}}))}return[]}},onClick(t,e,i){i.chart.toggleDataVisibility(e.index),i.chart.update()}},tooltip:{callbacks:{title:()=>"",label:t=>t.chart.data.labels[t.dataIndex]+": "+t.formattedValue}}},scales:{r:{type:"radialLinear",angleLines:{display:!1},beginAtZero:!0,grid:{circular:!0},pointLabels:{display:!1},startAngle:0}}};class Sn extends wn{}Sn.id="pie",Sn.defaults={cutout:0,rotation:0,circumference:360,radius:"100%"};class Pn extends ws{getLabelAndValue(t){const e=this._cachedMeta.vScale,i=this.getParsed(t);return{label:e.getLabels()[t],value:""+e.getLabelForValue(i[e.axis])}}update(t){const e=this._cachedMeta,i=e.dataset,s=e.data||[],n=e.iScale.getLabels();if(i.points=s,"resize"!==t){const e=this.resolveDatasetElementOptions(t);this.options.showLine||(e.borderWidth=0);const o={_loop:!0,_fullLoop:n.length===s.length,options:e};this.updateElement(i,void 0,o,t)}this.updateElements(s,0,s.length,t)}updateElements(t,e,i,s){const n=this.getDataset(),o=this._cachedMeta.rScale,a="reset"===s;for(let r=e;r<e+i;r++){const e=t[r],i=this.resolveDataElementOptions(r,e.active?"active":s),l=o.getPointPositionForValue(r,n.data[r]),h=a?o.xCenter:l.x,c=a?o.yCenter:l.y,d={x:h,y:c,angle:l.angle,skip:isNaN(h)||isNaN(c),options:i};this.updateElement(e,r,d,s)}}}Pn.id="radar",Pn.defaults={datasetElementType:"line",dataElementType:"point",indexAxis:"r",showLine:!0,elements:{line:{fill:"start"}}},Pn.overrides={aspectRatio:1,scales:{r:{type:"radialLinear"}}};class Dn extends Mn{}Dn.id="scatter",Dn.defaults={showLine:!1,fill:!1},Dn.overrides={interaction:{mode:"point"},plugins:{tooltip:{callbacks:{title:()=>"",label:t=>"("+t.label+", "+t.formattedValue+")"}}},scales:{x:{type:"linear"},y:{type:"linear"}}};var Cn=Object.freeze({__proto__:null,BarController:yn,BubbleController:vn,DoughnutController:wn,LineController:Mn,PolarAreaController:kn,PieController:Sn,RadarController:Pn,ScatterController:Dn});function On(t,e,i){const{startAngle:s,pixelMargin:n,x:o,y:a,outerRadius:r,innerRadius:l}=e;let h=n/r;t.beginPath(),t.arc(o,a,r,s-h,i+h),l>n?(h=n/l,t.arc(o,a,l,i+h,s-h,!0)):t.arc(o,a,n,i+Mt,s-Mt),t.closePath(),t.clip()}function An(t,e,i,s){const n=Ie(t.options.borderRadius,["outerStart","outerEnd","innerStart","innerEnd"]);const o=(i-e)/2,a=Math.min(o,s*e/2),r=t=>{const e=(i-Math.min(o,t))*s/2;return Ht(t,0,Math.min(o,e))};return{outerStart:r(n.outerStart),outerEnd:r(n.outerEnd),innerStart:Ht(n.innerStart,0,a),innerEnd:Ht(n.innerEnd,0,a)}}function Tn(t,e,i,s){return{x:i+t*Math.cos(e),y:s+t*Math.sin(e)}}function Ln(t,e,i,s,n){const{x:o,y:a,startAngle:r,pixelMargin:l,innerRadius:h}=e,c=Math.max(e.outerRadius+s+i-l,0),d=h>0?h+s+i+l:0;let u=0;const f=n-r;if(s){const t=((h>0?h-s:0)+(c>0?c-s:0))/2;u=(f-(0!==t?f*t/(t+s):f))/2}const g=(f-Math.max(.001,f*c-i/bt)/c)/2,p=r+g+u,m=n-g-u,{outerStart:x,outerEnd:b,innerStart:_,innerEnd:y}=An(e,d,c,m-p),v=c-x,w=c-b,M=p+x/v,k=m-b/w,S=d+_,P=d+y,D=p+_/S,C=m-y/P;if(t.beginPath(),t.arc(o,a,c,M,k),b>0){const e=Tn(w,k,o,a);t.arc(e.x,e.y,b,k,m+Mt)}const O=Tn(P,m,o,a);if(t.lineTo(O.x,O.y),y>0){const e=Tn(P,C,o,a);t.arc(e.x,e.y,y,m+Mt,C+Math.PI)}if(t.arc(o,a,d,m-y/d,p+_/d,!0),_>0){const e=Tn(S,D,o,a);t.arc(e.x,e.y,_,D+Math.PI,p-Mt)}const A=Tn(v,p,o,a);if(t.lineTo(A.x,A.y),x>0){const e=Tn(v,M,o,a);t.arc(e.x,e.y,x,p-Mt,M)}t.closePath()}function Rn(t,e,i,s,n){const{options:o}=e,a="inner"===o.borderAlign;o.borderWidth&&(a?(t.lineWidth=2*o.borderWidth,t.lineJoin="round"):(t.lineWidth=o.borderWidth,t.lineJoin="bevel"),e.fullCircles&&function(t,e,i){const{x:s,y:n,startAngle:o,pixelMargin:a,fullCircles:r}=e,l=Math.max(e.outerRadius-a,0),h=e.innerRadius+a;let c;for(i&&On(t,e,o+_t),t.beginPath(),t.arc(s,n,h,o+_t,o,!0),c=0;c<r;++c)t.stroke();for(t.beginPath(),t.arc(s,n,l,o,o+_t),c=0;c<r;++c)t.stroke()}(t,e,a),a&&On(t,e,n),Ln(t,e,i,s,n),t.stroke())}class En extends Ms{constructor(t){super(),this.options=void 0,this.circumference=void 0,this.startAngle=void 0,this.endAngle=void 0,this.innerRadius=void 0,this.outerRadius=void 0,this.pixelMargin=0,this.fullCircles=0,t&&Object.assign(this,t)}inRange(t,e,i){const s=this.getProps(["x","y"],i),{angle:n,distance:o}=Ft(s,{x:t,y:e}),{startAngle:a,endAngle:r,innerRadius:l,outerRadius:h,circumference:c}=this.getProps(["startAngle","endAngle","innerRadius","outerRadius","circumference"],i),d=this.options.spacing/2;return(c>=_t||Nt(n,a,r))&&(o>=l+d&&o<=h+d)}getCenterPoint(t){const{x:e,y:i,startAngle:s,endAngle:n,innerRadius:o,outerRadius:a}=this.getProps(["x","y","startAngle","endAngle","innerRadius","outerRadius","circumference"],t),{offset:r,spacing:l}=this.options,h=(s+n)/2,c=(o+a+l+r)/2;return{x:e+Math.cos(h)*c,y:i+Math.sin(h)*c}}tooltipPosition(t){return this.getCenterPoint(t)}draw(t){const{options:e,circumference:i}=this,s=(e.offset||0)/2,n=(e.spacing||0)/2;if(this.pixelMargin="inner"===e.borderAlign?.33:0,this.fullCircles=i>_t?Math.floor(i/_t):0,0===i||this.innerRadius<0||this.outerRadius<0)return;t.save();let o=0;if(s){o=s/2;const e=(this.startAngle+this.endAngle)/2;t.translate(Math.cos(e)*o,Math.sin(e)*o),this.circumference>=bt&&(o=s)}t.fillStyle=e.backgroundColor,t.strokeStyle=e.borderColor;const a=function(t,e,i,s){const{fullCircles:n,startAngle:o,circumference:a}=e;let r=e.endAngle;if(n){Ln(t,e,i,s,o+_t);for(let e=0;e<n;++e)t.fill();isNaN(a)||(r=o+a%_t,a%_t==0&&(r+=_t))}return Ln(t,e,i,s,r),t.fill(),r}(t,this,o,n);Rn(t,this,o,n,a),t.restore()}}function In(t,e,i=e){t.lineCap=K(i.borderCapStyle,e.borderCapStyle),t.setLineDash(K(i.borderDash,e.borderDash)),t.lineDashOffset=K(i.borderDashOffset,e.borderDashOffset),t.lineJoin=K(i.borderJoinStyle,e.borderJoinStyle),t.lineWidth=K(i.borderWidth,e.borderWidth),t.strokeStyle=K(i.borderColor,e.borderColor)}function zn(t,e,i){t.lineTo(i.x,i.y)}function Fn(t,e,i={}){const s=t.length,{start:n=0,end:o=s-1}=i,{start:a,end:r}=e,l=Math.max(n,a),h=Math.min(o,r),c=n<a&&o<a||n>r&&o>r;return{count:s,start:l,loop:e.loop,ilen:h<l&&!c?s+h-l:h-l}}function Bn(t,e,i,s){const{points:n,options:o}=e,{count:a,start:r,loop:l,ilen:h}=Fn(n,i,s),c=function(t){return t.stepped?Jt:t.tension||"monotone"===t.cubicInterpolationMode?te:zn}(o);let d,u,f,{move:g=!0,reverse:p}=s||{};for(d=0;d<=h;++d)u=n[(r+(p?h-d:d))%a],u.skip||(g?(t.moveTo(u.x,u.y),g=!1):c(t,f,u,p,o.stepped),f=u);return l&&(u=n[(r+(p?h:0))%a],c(t,f,u,p,o.stepped)),!!l}function Vn(t,e,i,s){const n=e.points,{count:o,start:a,ilen:r}=Fn(n,i,s),{move:l=!0,reverse:h}=s||{};let c,d,u,f,g,p,m=0,x=0;const b=t=>(a+(h?r-t:t))%o,_=()=>{f!==g&&(t.lineTo(m,g),t.lineTo(m,f),t.lineTo(m,p))};for(l&&(d=n[b(0)],t.moveTo(d.x,d.y)),c=0;c<=r;++c){if(d=n[b(c)],d.skip)continue;const e=d.x,i=d.y,s=0|e;s===u?(i<f?f=i:i>g&&(g=i),m=(x*m+e)/++x):(_(),t.lineTo(e,i),u=s,x=0,f=g=i),p=i}_()}function Wn(t){const e=t.options,i=e.borderDash&&e.borderDash.length;return!(t._decimated||t._loop||e.tension||"monotone"===e.cubicInterpolationMode||e.stepped||i)?Vn:Bn}En.id="arc",En.defaults={borderAlign:"center",borderColor:"#fff",borderRadius:0,borderWidth:2,offset:0,spacing:0,angle:void 0},En.defaultRoutes={backgroundColor:"backgroundColor"};const Nn="function"==typeof Path2D;function Hn(t,e,i,s){Nn&&!e.options.segment?function(t,e,i,s){let n=e._path;n||(n=e._path=new Path2D,e.path(n,i,s)&&n.closePath()),In(t,e.options),t.stroke(n)}(t,e,i,s):function(t,e,i,s){const{segments:n,options:o}=e,a=Wn(e);for(const r of n)In(t,o,r.style),t.beginPath(),a(t,e,r,{start:i,end:i+s-1})&&t.closePath(),t.stroke()}(t,e,i,s)}class jn extends Ms{constructor(t){super(),this.animated=!0,this.options=void 0,this._chart=void 0,this._loop=void 0,this._fullLoop=void 0,this._path=void 0,this._points=void 0,this._segments=void 0,this._decimated=!1,this._pointsUpdated=!1,this._datasetIndex=void 0,t&&Object.assign(this,t)}updateControlPoints(t,e){const i=this.options;if((i.tension||"monotone"===i.cubicInterpolationMode)&&!i.stepped&&!this._pointsUpdated){const s=i.spanGaps?this._loop:this._fullLoop;vi(this._points,i,t,s,e),this._pointsUpdated=!0}}set points(t){this._points=t,delete this._segments,delete this._path,this._pointsUpdated=!1}get points(){return this._points}get segments(){return this._segments||(this._segments=Bi(this,this.options.segment))}first(){const t=this.segments,e=this.points;return t.length&&e[t[0].start]}last(){const t=this.segments,e=this.points,i=t.length;return i&&e[t[i-1].end]}interpolate(t,e){const i=this.options,s=t[e],n=this.points,o=Fi(this,{property:e,start:s,end:s});if(!o.length)return;const a=[],r=function(t){return t.stepped?Di:t.tension||"monotone"===t.cubicInterpolationMode?Ci:Pi}(i);let l,h;for(l=0,h=o.length;l<h;++l){const{start:h,end:c}=o[l],d=n[h],u=n[c];if(d===u){a.push(d);continue}const f=r(d,u,Math.abs((s-d[e])/(u[e]-d[e])),i.stepped);f[e]=t[e],a.push(f)}return 1===a.length?a[0]:a}pathSegment(t,e,i){return Wn(this)(t,this,e,i)}path(t,e,i){const s=this.segments,n=Wn(this);let o=this._loop;e=e||0,i=i||this.points.length-e;for(const a of s)o&=n(t,this,a,{start:e,end:e+i-1});return!!o}draw(t,e,i,s){const n=this.options||{};(this.points||[]).length&&n.borderWidth&&(t.save(),Hn(t,this,i,s),t.restore()),this.animated&&(this._pointsUpdated=!1,this._path=void 0)}}function $n(t,e,i,s){const n=t.options,{[i]:o}=t.getProps([i],s);return Math.abs(e-o)<n.radius+n.hitRadius}jn.id="line",jn.defaults={borderCapStyle:"butt",borderDash:[],borderDashOffset:0,borderJoinStyle:"miter",borderWidth:3,capBezierPoints:!0,cubicInterpolationMode:"default",fill:!1,spanGaps:!1,stepped:!1,tension:0},jn.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"},jn.descriptors={_scriptable:!0,_indexable:t=>"borderDash"!==t&&"fill"!==t};class Yn extends Ms{constructor(t){super(),this.options=void 0,this.parsed=void 0,this.skip=void 0,this.stop=void 0,t&&Object.assign(this,t)}inRange(t,e,i){const s=this.options,{x:n,y:o}=this.getProps(["x","y"],i);return Math.pow(t-n,2)+Math.pow(e-o,2)<Math.pow(s.hitRadius+s.radius,2)}inXRange(t,e){return $n(this,t,"x",e)}inYRange(t,e){return $n(this,t,"y",e)}getCenterPoint(t){const{x:e,y:i}=this.getProps(["x","y"],t);return{x:e,y:i}}size(t){let e=(t=t||this.options||{}).radius||0;e=Math.max(e,e&&t.hoverRadius||0);return 2*(e+(e&&t.borderWidth||0))}draw(t,e){const i=this.options;this.skip||i.radius<.1||!Gt(this,e,this.size(i)/2)||(t.strokeStyle=i.borderColor,t.lineWidth=i.borderWidth,t.fillStyle=i.backgroundColor,Kt(t,i,this.x,this.y))}getRange(){const t=this.options||{};return t.radius+t.hitRadius}}function Un(t,e){const{x:i,y:s,base:n,width:o,height:a}=t.getProps(["x","y","base","width","height"],e);let r,l,h,c,d;return t.horizontal?(d=a/2,r=Math.min(i,n),l=Math.max(i,n),h=s-d,c=s+d):(d=o/2,r=i-d,l=i+d,h=Math.min(s,n),c=Math.max(s,n)),{left:r,top:h,right:l,bottom:c}}function Xn(t,e,i,s){return t?0:Ht(e,i,s)}function qn(t){const e=Un(t),i=e.right-e.left,s=e.bottom-e.top,n=function(t,e,i){const s=t.options.borderWidth,n=t.borderSkipped,o=ze(s);return{t:Xn(n.top,o.top,0,i),r:Xn(n.right,o.right,0,e),b:Xn(n.bottom,o.bottom,0,i),l:Xn(n.left,o.left,0,e)}}(t,i/2,s/2),o=function(t,e,i){const{enableBorderRadius:s}=t.getProps(["enableBorderRadius"]),n=t.options.borderRadius,o=Fe(n),a=Math.min(e,i),r=t.borderSkipped,l=s||U(n);return{topLeft:Xn(!l||r.top||r.left,o.topLeft,0,a),topRight:Xn(!l||r.top||r.right,o.topRight,0,a),bottomLeft:Xn(!l||r.bottom||r.left,o.bottomLeft,0,a),bottomRight:Xn(!l||r.bottom||r.right,o.bottomRight,0,a)}}(t,i/2,s/2);return{outer:{x:e.left,y:e.top,w:i,h:s,radius:o},inner:{x:e.left+n.l,y:e.top+n.t,w:i-n.l-n.r,h:s-n.t-n.b,radius:{topLeft:Math.max(0,o.topLeft-Math.max(n.t,n.l)),topRight:Math.max(0,o.topRight-Math.max(n.t,n.r)),bottomLeft:Math.max(0,o.bottomLeft-Math.max(n.b,n.l)),bottomRight:Math.max(0,o.bottomRight-Math.max(n.b,n.r))}}}}function Kn(t,e,i,s){const n=null===e,o=null===i,a=t&&!(n&&o)&&Un(t,s);return a&&(n||e>=a.left&&e<=a.right)&&(o||i>=a.top&&i<=a.bottom)}function Gn(t,e){t.rect(e.x,e.y,e.w,e.h)}function Zn(t,e,i={}){const s=t.x!==i.x?-e:0,n=t.y!==i.y?-e:0,o=(t.x+t.w!==i.x+i.w?e:0)-s,a=(t.y+t.h!==i.y+i.h?e:0)-n;return{x:t.x+s,y:t.y+n,w:t.w+o,h:t.h+a,radius:t.radius}}Yn.id="point",Yn.defaults={borderWidth:1,hitRadius:1,hoverBorderWidth:1,hoverRadius:4,pointStyle:"circle",radius:3,rotation:0},Yn.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};class Qn extends Ms{constructor(t){super(),this.options=void 0,this.horizontal=void 0,this.base=void 0,this.width=void 0,this.height=void 0,this.inflateAmount=void 0,t&&Object.assign(this,t)}draw(t){const{inflateAmount:e,options:{borderColor:i,backgroundColor:s}}=this,{inner:n,outer:o}=qn(this),a=(r=o.radius).topLeft||r.topRight||r.bottomLeft||r.bottomRight?se:Gn;var r;t.save(),o.w===n.w&&o.h===n.h||(t.beginPath(),a(t,Zn(o,e,n)),t.clip(),a(t,Zn(n,-e,o)),t.fillStyle=i,t.fill("evenodd")),t.beginPath(),a(t,Zn(n,e)),t.fillStyle=s,t.fill(),t.restore()}inRange(t,e,i){return Kn(this,t,e,i)}inXRange(t,e){return Kn(this,t,null,e)}inYRange(t,e){return Kn(this,null,t,e)}getCenterPoint(t){const{x:e,y:i,base:s,horizontal:n}=this.getProps(["x","y","base","horizontal"],t);return{x:n?(e+s)/2:e,y:n?i:(i+s)/2}}getRange(t){return"x"===t?this.width/2:this.height/2}}Qn.id="bar",Qn.defaults={borderSkipped:"start",borderWidth:0,borderRadius:0,inflateAmount:"auto",pointStyle:void 0},Qn.defaultRoutes={backgroundColor:"backgroundColor",borderColor:"borderColor"};var Jn=Object.freeze({__proto__:null,ArcElement:En,LineElement:jn,PointElement:Yn,BarElement:Qn});function to(t){if(t._decimated){const e=t._data;delete t._decimated,delete t._data,Object.defineProperty(t,"data",{value:e})}}function eo(t){t.data.datasets.forEach((t=>{to(t)}))}var io={id:"decimation",defaults:{algorithm:"min-max",enabled:!1},beforeElementsUpdate:(t,e,i)=>{if(!i.enabled)return void eo(t);const s=t.width;t.data.datasets.forEach(((e,n)=>{const{_data:o,indexAxis:a}=e,r=t.getDatasetMeta(n),l=o||e.data;if("y"===We([a,t.options.indexAxis]))return;if("line"!==r.type)return;const h=t.scales[r.xAxisID];if("linear"!==h.type&&"time"!==h.type)return;if(t.options.parsing)return;let{start:c,count:d}=function(t,e){const i=e.length;let s,n=0;const{iScale:o}=t,{min:a,max:r,minDefined:l,maxDefined:h}=o.getUserBounds();return l&&(n=Ht(oe(e,o.axis,a).lo,0,i-1)),s=h?Ht(oe(e,o.axis,r).hi+1,n,i)-n:i-n,{start:n,count:s}}(r,l);if(d<=(i.threshold||4*s))return void to(e);let u;switch($(o)&&(e._data=l,delete e.data,Object.defineProperty(e,"data",{configurable:!0,enumerable:!0,get:function(){return this._decimated},set:function(t){this._data=t}})),i.algorithm){case"lttb":u=function(t,e,i,s,n){const o=n.samples||s;if(o>=i)return t.slice(e,e+i);const a=[],r=(i-2)/(o-2);let l=0;const h=e+i-1;let c,d,u,f,g,p=e;for(a[l++]=t[p],c=0;c<o-2;c++){let s,n=0,o=0;const h=Math.floor((c+1)*r)+1+e,m=Math.min(Math.floor((c+2)*r)+1,i)+e,x=m-h;for(s=h;s<m;s++)n+=t[s].x,o+=t[s].y;n/=x,o/=x;const b=Math.floor(c*r)+1+e,_=Math.min(Math.floor((c+1)*r)+1,i)+e,{x:y,y:v}=t[p];for(u=f=-1,s=b;s<_;s++)f=.5*Math.abs((y-n)*(t[s].y-v)-(y-t[s].x)*(o-v)),f>u&&(u=f,d=t[s],g=s);a[l++]=d,p=g}return a[l++]=t[h],a}(l,c,d,s,i);break;case"min-max":u=function(t,e,i,s){let n,o,a,r,l,h,c,d,u,f,g=0,p=0;const m=[],x=e+i-1,b=t[e].x,_=t[x].x-b;for(n=e;n<e+i;++n){o=t[n],a=(o.x-b)/_*s,r=o.y;const e=0|a;if(e===l)r<u?(u=r,h=n):r>f&&(f=r,c=n),g=(p*g+o.x)/++p;else{const i=n-1;if(!$(h)&&!$(c)){const e=Math.min(h,c),s=Math.max(h,c);e!==d&&e!==i&&m.push({...t[e],x:g}),s!==d&&s!==i&&m.push({...t[s],x:g})}n>0&&i!==d&&m.push(t[i]),m.push(o),l=e,p=0,u=f=r,h=c=d=n}}return m}(l,c,d,s);break;default:throw new Error(`Unsupported decimation algorithm '${i.algorithm}'`)}e._decimated=u}))},destroy(t){eo(t)}};function so(t,e,i){const s=function(t){const e=t.options,i=e.fill;let s=K(i&&i.target,i);return void 0===s&&(s=!!e.backgroundColor),!1!==s&&null!==s&&(!0===s?"origin":s)}(t);if(U(s))return!isNaN(s.value)&&s;let n=parseFloat(s);return X(n)&&Math.floor(n)===n?("-"!==s[0]&&"+"!==s[0]||(n=e+n),!(n===e||n<0||n>=i)&&n):["origin","start","end","stack","shape"].indexOf(s)>=0&&s}class no{constructor(t){this.x=t.x,this.y=t.y,this.radius=t.radius}pathSegment(t,e,i){const{x:s,y:n,radius:o}=this;return e=e||{start:0,end:_t},t.arc(s,n,o,e.end,e.start,!0),!i.bounds}interpolate(t){const{x:e,y:i,radius:s}=this,n=t.angle;return{x:e+Math.cos(n)*s,y:i+Math.sin(n)*s,angle:n}}}function oo(t){return(t.scale||{}).getPointPositionForValue?function(t){const{scale:e,fill:i}=t,s=e.options,n=e.getLabels().length,o=[],a=s.reverse?e.max:e.min,r=s.reverse?e.min:e.max;let l,h,c;if(c="start"===i?a:"end"===i?r:U(i)?i.value:e.getBaseValue(),s.grid.circular)return h=e.getPointPositionForValue(0,a),new no({x:h.x,y:h.y,radius:e.getDistanceFromCenterForValue(c)});for(l=0;l<n;++l)o.push(e.getPointPositionForValue(l,c));return o}(t):function(t){const{scale:e={},fill:i}=t;let s,n=null;return"start"===i?n=e.bottom:"end"===i?n=e.top:U(i)?n=e.getPixelForValue(i.value):e.getBasePixel&&(n=e.getBasePixel()),X(n)?(s=e.isHorizontal(),{x:s?n:null,y:s?null:n}):null}(t)}function ao(t,e,i){for(;e>t;e--){const t=i[e];if(!isNaN(t.x)&&!isNaN(t.y))break}return e}function ro(t,e,i){const s=[];for(let n=0;n<i.length;n++){const o=i[n],{first:a,last:r,point:l}=lo(o,e,"x");if(!(!l||a&&r))if(a)s.unshift(l);else if(t.push(l),!r)break}t.push(...s)}function lo(t,e,i){const s=t.interpolate(e,i);if(!s)return{};const n=s[i],o=t.segments,a=t.points;let r=!1,l=!1;for(let t=0;t<o.length;t++){const e=o[t],s=a[e.start][i],h=a[e.end][i];if(n>=s&&n<=h){r=n===s,l=n===h;break}}return{first:r,last:l,point:s}}function ho(t){const{chart:e,fill:i,line:s}=t;if(X(i))return function(t,e){const i=t.getDatasetMeta(e);return i&&t.isDatasetVisible(e)?i.dataset:null}(e,i);if("stack"===i)return function(t){const{scale:e,index:i,line:s}=t,n=[],o=s.segments,a=s.points,r=function(t,e){const i=[],s=t.getMatchingVisibleMetas("line");for(let t=0;t<s.length;t++){const n=s[t];if(n.index===e)break;n.hidden||i.unshift(n.dataset)}return i}(e,i);r.push(co({x:null,y:e.bottom},s));for(let t=0;t<o.length;t++){const e=o[t];for(let t=e.start;t<=e.end;t++)ro(n,a[t],r)}return new jn({points:n,options:{}})}(t);if("shape"===i)return!0;const n=oo(t);return n instanceof no?n:co(n,s)}function co(t,e){let i=[],s=!1;return Y(t)?(s=!0,i=t):i=function(t,e){const{x:i=null,y:s=null}=t||{},n=e.points,o=[];return e.segments.forEach((({start:t,end:e})=>{e=ao(t,e,n);const a=n[t],r=n[e];null!==s?(o.push({x:a.x,y:s}),o.push({x:r.x,y:s})):null!==i&&(o.push({x:i,y:a.y}),o.push({x:i,y:r.y}))})),o}(t,e),i.length?new jn({points:i,options:{tension:0},_loop:s,_fullLoop:s}):null}function uo(t,e,i){let s=t[e].fill;const n=[e];let o;if(!i)return s;for(;!1!==s&&-1===n.indexOf(s);){if(!X(s))return s;if(o=t[s],!o)return!1;if(o.visible)return s;n.push(s),s=o.fill}return!1}function fo(t,e,i){t.beginPath(),e.path(t),t.lineTo(e.last().x,i),t.lineTo(e.first().x,i),t.closePath(),t.clip()}function go(t,e,i,s){if(s)return;let n=e[t],o=i[t];return"angle"===t&&(n=Wt(n),o=Wt(o)),{property:t,start:n,end:o}}function po(t,e,i,s){return t&&e?s(t[i],e[i]):t?t[i]:e?e[i]:0}function mo(t,e,i){const{top:s,bottom:n}=e.chart.chartArea,{property:o,start:a,end:r}=i||{};"x"===o&&(t.beginPath(),t.rect(a,s,r-a,n-s),t.clip())}function xo(t,e,i,s){const n=e.interpolate(i,s);n&&t.lineTo(n.x,n.y)}function bo(t,e){const{line:i,target:s,property:n,color:o,scale:a}=e,r=function(t,e,i){const s=t.segments,n=t.points,o=e.points,a=[];for(const t of s){let{start:s,end:r}=t;r=ao(s,r,n);const l=go(i,n[s],n[r],t.loop);if(!e.segments){a.push({source:t,target:l,start:n[s],end:n[r]});continue}const h=Fi(e,l);for(const e of h){const s=go(i,o[e.start],o[e.end],e.loop),r=zi(t,n,s);for(const t of r)a.push({source:t,target:e,start:{[i]:po(l,s,"start",Math.max)},end:{[i]:po(l,s,"end",Math.min)}})}}return a}(i,s,n);for(const{source:e,target:l,start:h,end:c}of r){const{style:{backgroundColor:r=o}={}}=e,d=!0!==s;t.save(),t.fillStyle=r,mo(t,a,d&&go(n,h,c)),t.beginPath();const u=!!i.pathSegment(t,e);let f;if(d){u?t.closePath():xo(t,s,c,n);const e=!!s.pathSegment(t,l,{move:u,reverse:!0});f=u&&e,f||xo(t,s,h,n)}t.closePath(),t.fill(f?"evenodd":"nonzero"),t.restore()}}function _o(t,e,i){const s=ho(e),{line:n,scale:o,axis:a}=e,r=n.options,l=r.fill,h=r.backgroundColor,{above:c=h,below:d=h}=l||{};s&&n.points.length&&(Zt(t,i),function(t,e){const{line:i,target:s,above:n,below:o,area:a,scale:r}=e,l=i._loop?"angle":e.axis;t.save(),"x"===l&&o!==n&&(fo(t,s,a.top),bo(t,{line:i,target:s,color:n,scale:r,property:l}),t.restore(),t.save(),fo(t,s,a.bottom)),bo(t,{line:i,target:s,color:o,scale:r,property:l}),t.restore()}(t,{line:n,target:s,above:c,below:d,area:i,scale:o,axis:a}),Qt(t))}var yo={id:"filler",afterDatasetsUpdate(t,e,i){const s=(t.data.datasets||[]).length,n=[];let o,a,r,l;for(a=0;a<s;++a)o=t.getDatasetMeta(a),r=o.dataset,l=null,r&&r.options&&r instanceof jn&&(l={visible:t.isDatasetVisible(a),index:a,fill:so(r,a,s),chart:t,axis:o.controller.options.indexAxis,scale:o.vScale,line:r}),o.$filler=l,n.push(l);for(a=0;a<s;++a)l=n[a],l&&!1!==l.fill&&(l.fill=uo(n,a,i.propagate))},beforeDraw(t,e,i){const s="beforeDraw"===i.drawTime,n=t.getSortedVisibleDatasetMetas(),o=t.chartArea;for(let e=n.length-1;e>=0;--e){const i=n[e].$filler;i&&(i.line.updateControlPoints(o,i.axis),s&&_o(t.ctx,i,o))}},beforeDatasetsDraw(t,e,i){if("beforeDatasetsDraw"!==i.drawTime)return;const s=t.getSortedVisibleDatasetMetas();for(let e=s.length-1;e>=0;--e){const i=s[e].$filler;i&&_o(t.ctx,i,t.chartArea)}},beforeDatasetDraw(t,e,i){const s=e.meta.$filler;s&&!1!==s.fill&&"beforeDatasetDraw"===i.drawTime&&_o(t.ctx,s,t.chartArea)},defaults:{propagate:!0,drawTime:"beforeDatasetDraw"}};const vo=(t,e)=>{let{boxHeight:i=e,boxWidth:s=e}=t;return t.usePointStyle&&(i=Math.min(i,e),s=Math.min(s,e)),{boxWidth:s,boxHeight:i,itemHeight:Math.max(e,i)}};class wo extends Ms{constructor(t){super(),this._added=!1,this.legendHitBoxes=[],this._hoveredItem=null,this.doughnutMode=!1,this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this.legendItems=void 0,this.columnSizes=void 0,this.lineWidths=void 0,this.maxHeight=void 0,this.maxWidth=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.height=void 0,this.width=void 0,this._margins=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e,i){this.maxWidth=t,this.maxHeight=e,this._margins=i,this.setDimensions(),this.buildLabels(),this.fit()}setDimensions(){this.isHorizontal()?(this.width=this.maxWidth,this.left=this._margins.left,this.right=this.width):(this.height=this.maxHeight,this.top=this._margins.top,this.bottom=this.height)}buildLabels(){const t=this.options.labels||{};let e=Q(t.generateLabels,[this.chart],this)||[];t.filter&&(e=e.filter((e=>t.filter(e,this.chart.data)))),t.sort&&(e=e.sort(((e,i)=>t.sort(e,i,this.chart.data)))),this.options.reverse&&e.reverse(),this.legendItems=e}fit(){const{options:t,ctx:e}=this;if(!t.display)return void(this.width=this.height=0);const i=t.labels,s=Ve(i.font),n=s.size,o=this._computeTitleHeight(),{boxWidth:a,itemHeight:r}=vo(i,n);let l,h;e.font=s.string,this.isHorizontal()?(l=this.maxWidth,h=this._fitRows(o,n,a,r)+10):(h=this.maxHeight,l=this._fitCols(o,n,a,r)+10),this.width=Math.min(l,t.maxWidth||this.maxWidth),this.height=Math.min(h,t.maxHeight||this.maxHeight)}_fitRows(t,e,i,s){const{ctx:n,maxWidth:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.lineWidths=[0],h=s+a;let c=t;n.textAlign="left",n.textBaseline="middle";let d=-1,u=-h;return this.legendItems.forEach(((t,f)=>{const g=i+e/2+n.measureText(t.text).width;(0===f||l[l.length-1]+g+2*a>o)&&(c+=h,l[l.length-(f>0?0:1)]=0,u+=h,d++),r[f]={left:0,top:u,row:d,width:g,height:s},l[l.length-1]+=g+a})),c}_fitCols(t,e,i,s){const{ctx:n,maxHeight:o,options:{labels:{padding:a}}}=this,r=this.legendHitBoxes=[],l=this.columnSizes=[],h=o-t;let c=a,d=0,u=0,f=0,g=0;return this.legendItems.forEach(((t,o)=>{const p=i+e/2+n.measureText(t.text).width;o>0&&u+s+2*a>h&&(c+=d+a,l.push({width:d,height:u}),f+=d+a,g++,d=u=0),r[o]={left:f,top:u,col:g,width:p,height:s},d=Math.max(d,p),u+=s+a})),c+=d,l.push({width:d,height:u}),c}adjustHitBoxes(){if(!this.options.display)return;const t=this._computeTitleHeight(),{legendHitBoxes:e,options:{align:i,labels:{padding:s},rtl:o}}=this,a=Ti(o,this.left,this.width);if(this.isHorizontal()){let o=0,r=n(i,this.left+s,this.right-this.lineWidths[o]);for(const l of e)o!==l.row&&(o=l.row,r=n(i,this.left+s,this.right-this.lineWidths[o])),l.top+=this.top+t+s,l.left=a.leftForLtr(a.x(r),l.width),r+=l.width+s}else{let o=0,r=n(i,this.top+t+s,this.bottom-this.columnSizes[o].height);for(const l of e)l.col!==o&&(o=l.col,r=n(i,this.top+t+s,this.bottom-this.columnSizes[o].height)),l.top=r,l.left+=this.left+s,l.left=a.leftForLtr(a.x(l.left),l.width),r+=l.height+s}}isHorizontal(){return"top"===this.options.position||"bottom"===this.options.position}draw(){if(this.options.display){const t=this.ctx;Zt(t,this),this._draw(),Qt(t)}}_draw(){const{options:t,columnSizes:e,lineWidths:i,ctx:s}=this,{align:a,labels:r}=t,l=xt.color,h=Ti(t.rtl,this.left,this.width),c=Ve(r.font),{color:d,padding:u}=r,f=c.size,g=f/2;let p;this.drawTitle(),s.textAlign=h.textAlign("left"),s.textBaseline="middle",s.lineWidth=.5,s.font=c.string;const{boxWidth:m,boxHeight:x,itemHeight:b}=vo(r,f),_=this.isHorizontal(),y=this._computeTitleHeight();p=_?{x:n(a,this.left+u,this.right-i[0]),y:this.top+u+y,line:0}:{x:this.left+u,y:n(a,this.top+y+u,this.bottom-e[0].height),line:0},Li(this.ctx,t.textDirection);const v=b+u;this.legendItems.forEach(((w,M)=>{s.strokeStyle=w.fontColor||d,s.fillStyle=w.fontColor||d;const k=s.measureText(w.text).width,S=h.textAlign(w.textAlign||(w.textAlign=r.textAlign)),P=m+g+k;let D=p.x,C=p.y;h.setWidth(this.width),_?M>0&&D+P+u>this.right&&(C=p.y+=v,p.line++,D=p.x=n(a,this.left+u,this.right-i[p.line])):M>0&&C+v>this.bottom&&(D=p.x=D+e[p.line].width+u,p.line++,C=p.y=n(a,this.top+y+u,this.bottom-e[p.line].height));!function(t,e,i){if(isNaN(m)||m<=0||isNaN(x)||x<0)return;s.save();const n=K(i.lineWidth,1);if(s.fillStyle=K(i.fillStyle,l),s.lineCap=K(i.lineCap,"butt"),s.lineDashOffset=K(i.lineDashOffset,0),s.lineJoin=K(i.lineJoin,"miter"),s.lineWidth=n,s.strokeStyle=K(i.strokeStyle,l),s.setLineDash(K(i.lineDash,[])),r.usePointStyle){const o={radius:m*Math.SQRT2/2,pointStyle:i.pointStyle,rotation:i.rotation,borderWidth:n},a=h.xPlus(t,m/2);Kt(s,o,a,e+g)}else{const o=e+Math.max((f-x)/2,0),a=h.leftForLtr(t,m),r=Fe(i.borderRadius);s.beginPath(),Object.values(r).some((t=>0!==t))?se(s,{x:a,y:o,w:m,h:x,radius:r}):s.rect(a,o,m,x),s.fill(),0!==n&&s.stroke()}s.restore()}(h.x(D),C,w),D=o(S,D+m+g,_?D+P:this.right,t.rtl),function(t,e,i){ee(s,i.text,t,e+b/2,c,{strikethrough:i.hidden,textAlign:h.textAlign(i.textAlign)})}(h.x(D),C,w),_?p.x+=P+u:p.y+=v})),Ri(this.ctx,t.textDirection)}drawTitle(){const t=this.options,e=t.title,i=Ve(e.font),o=Be(e.padding);if(!e.display)return;const a=Ti(t.rtl,this.left,this.width),r=this.ctx,l=e.position,h=i.size/2,c=o.top+h;let d,u=this.left,f=this.width;if(this.isHorizontal())f=Math.max(...this.lineWidths),d=this.top+c,u=n(t.align,u,this.right-f);else{const e=this.columnSizes.reduce(((t,e)=>Math.max(t,e.height)),0);d=c+n(t.align,this.top,this.bottom-e-t.labels.padding-this._computeTitleHeight())}const g=n(l,u,u+f);r.textAlign=a.textAlign(s(l)),r.textBaseline="middle",r.strokeStyle=e.color,r.fillStyle=e.color,r.font=i.string,ee(r,e.text,g,d,i)}_computeTitleHeight(){const t=this.options.title,e=Ve(t.font),i=Be(t.padding);return t.display?e.lineHeight+i.height:0}_getLegendItemAt(t,e){let i,s,n;if(t>=this.left&&t<=this.right&&e>=this.top&&e<=this.bottom)for(n=this.legendHitBoxes,i=0;i<n.length;++i)if(s=n[i],t>=s.left&&t<=s.left+s.width&&e>=s.top&&e<=s.top+s.height)return this.legendItems[i];return null}handleEvent(t){const e=this.options;if(!function(t,e){if("mousemove"===t&&(e.onHover||e.onLeave))return!0;if(e.onClick&&("click"===t||"mouseup"===t))return!0;return!1}(t.type,e))return;const i=this._getLegendItemAt(t.x,t.y);if("mousemove"===t.type){const o=this._hoveredItem,a=(n=i,null!==(s=o)&&null!==n&&s.datasetIndex===n.datasetIndex&&s.index===n.index);o&&!a&&Q(e.onLeave,[t,o,this],this),this._hoveredItem=i,i&&!a&&Q(e.onHover,[t,i,this],this)}else i&&Q(e.onClick,[t,i,this],this);var s,n}}var Mo={id:"legend",_element:wo,start(t,e,i){const s=t.legend=new wo({ctx:t.ctx,options:i,chart:t});ei.configure(t,s,i),ei.addBox(t,s)},stop(t){ei.removeBox(t,t.legend),delete t.legend},beforeUpdate(t,e,i){const s=t.legend;ei.configure(t,s,i),s.options=i},afterUpdate(t){const e=t.legend;e.buildLabels(),e.adjustHitBoxes()},afterEvent(t,e){e.replay||t.legend.handleEvent(e.event)},defaults:{display:!0,position:"top",align:"center",fullSize:!0,reverse:!1,weight:1e3,onClick(t,e,i){const s=e.datasetIndex,n=i.chart;n.isDatasetVisible(s)?(n.hide(s),e.hidden=!0):(n.show(s),e.hidden=!1)},onHover:null,onLeave:null,labels:{color:t=>t.chart.options.color,boxWidth:40,padding:10,generateLabels(t){const e=t.data.datasets,{labels:{usePointStyle:i,pointStyle:s,textAlign:n,color:o}}=t.legend.options;return t._getSortedDatasetMetas().map((t=>{const a=t.controller.getStyle(i?0:void 0),r=Be(a.borderWidth);return{text:e[t.index].label,fillStyle:a.backgroundColor,fontColor:o,hidden:!t.visible,lineCap:a.borderCapStyle,lineDash:a.borderDash,lineDashOffset:a.borderDashOffset,lineJoin:a.borderJoinStyle,lineWidth:(r.width+r.height)/4,strokeStyle:a.borderColor,pointStyle:s||a.pointStyle,rotation:a.rotation,textAlign:n||a.textAlign,borderRadius:0,datasetIndex:t.index}}),this)}},title:{color:t=>t.chart.options.color,display:!1,position:"center",text:""}},descriptors:{_scriptable:t=>!t.startsWith("on"),labels:{_scriptable:t=>!["generateLabels","filter","sort"].includes(t)}}};class ko extends Ms{constructor(t){super(),this.chart=t.chart,this.options=t.options,this.ctx=t.ctx,this._padding=void 0,this.top=void 0,this.bottom=void 0,this.left=void 0,this.right=void 0,this.width=void 0,this.height=void 0,this.position=void 0,this.weight=void 0,this.fullSize=void 0}update(t,e){const i=this.options;if(this.left=0,this.top=0,!i.display)return void(this.width=this.height=this.right=this.bottom=0);this.width=this.right=t,this.height=this.bottom=e;const s=Y(i.text)?i.text.length:1;this._padding=Be(i.padding);const n=s*Ve(i.font).lineHeight+this._padding.height;this.isHorizontal()?this.height=n:this.width=n}isHorizontal(){const t=this.options.position;return"top"===t||"bottom"===t}_drawArgs(t){const{top:e,left:i,bottom:s,right:o,options:a}=this,r=a.align;let l,h,c,d=0;return this.isHorizontal()?(h=n(r,i,o),c=e+t,l=o-i):("left"===a.position?(h=i+t,c=n(r,s,e),d=-.5*bt):(h=o-t,c=n(r,e,s),d=.5*bt),l=s-e),{titleX:h,titleY:c,maxWidth:l,rotation:d}}draw(){const t=this.ctx,e=this.options;if(!e.display)return;const i=Ve(e.font),n=i.lineHeight/2+this._padding.top,{titleX:o,titleY:a,maxWidth:r,rotation:l}=this._drawArgs(n);ee(t,e.text,0,0,i,{color:e.color,maxWidth:r,rotation:l,textAlign:s(e.align),textBaseline:"middle",translation:[o,a]})}}var So={id:"title",_element:ko,start(t,e,i){!function(t,e){const i=new ko({ctx:t.ctx,options:e,chart:t});ei.configure(t,i,e),ei.addBox(t,i),t.titleBlock=i}(t,i)},stop(t){const e=t.titleBlock;ei.removeBox(t,e),delete t.titleBlock},beforeUpdate(t,e,i){const s=t.titleBlock;ei.configure(t,s,i),s.options=i},defaults:{align:"center",display:!1,font:{weight:"bold"},fullSize:!0,padding:10,position:"top",text:"",weight:2e3},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const Po=new WeakMap;var Do={id:"subtitle",start(t,e,i){const s=new ko({ctx:t.ctx,options:i,chart:t});ei.configure(t,s,i),ei.addBox(t,s),Po.set(t,s)},stop(t){ei.removeBox(t,Po.get(t)),Po.delete(t)},beforeUpdate(t,e,i){const s=Po.get(t);ei.configure(t,s,i),s.options=i},defaults:{align:"center",display:!1,font:{weight:"normal"},fullSize:!0,padding:0,position:"top",text:"",weight:1500},defaultRoutes:{color:"color"},descriptors:{_scriptable:!0,_indexable:!1}};const Co={average(t){if(!t.length)return!1;let e,i,s=0,n=0,o=0;for(e=0,i=t.length;e<i;++e){const i=t[e].element;if(i&&i.hasValue()){const t=i.tooltipPosition();s+=t.x,n+=t.y,++o}}return{x:s/o,y:n/o}},nearest(t,e){if(!t.length)return!1;let i,s,n,o=e.x,a=e.y,r=Number.POSITIVE_INFINITY;for(i=0,s=t.length;i<s;++i){const s=t[i].element;if(s&&s.hasValue()){const t=Bt(e,s.getCenterPoint());t<r&&(r=t,n=s)}}if(n){const t=n.tooltipPosition();o=t.x,a=t.y}return{x:o,y:a}}};function Oo(t,e){return e&&(Y(e)?Array.prototype.push.apply(t,e):t.push(e)),t}function Ao(t){return("string"==typeof t||t instanceof String)&&t.indexOf("\n")>-1?t.split("\n"):t}function To(t,e){const{element:i,datasetIndex:s,index:n}=e,o=t.getDatasetMeta(s).controller,{label:a,value:r}=o.getLabelAndValue(n);return{chart:t,label:a,parsed:o.getParsed(n),raw:t.data.datasets[s].data[n],formattedValue:r,dataset:o.getDataset(),dataIndex:n,datasetIndex:s,element:i}}function Lo(t,e){const i=t._chart.ctx,{body:s,footer:n,title:o}=t,{boxWidth:a,boxHeight:r}=e,l=Ve(e.bodyFont),h=Ve(e.titleFont),c=Ve(e.footerFont),d=o.length,u=n.length,f=s.length,g=Be(e.padding);let p=g.height,m=0,x=s.reduce(((t,e)=>t+e.before.length+e.lines.length+e.after.length),0);if(x+=t.beforeBody.length+t.afterBody.length,d&&(p+=d*h.lineHeight+(d-1)*e.titleSpacing+e.titleMarginBottom),x){p+=f*(e.displayColors?Math.max(r,l.lineHeight):l.lineHeight)+(x-f)*l.lineHeight+(x-1)*e.bodySpacing}u&&(p+=e.footerMarginTop+u*c.lineHeight+(u-1)*e.footerSpacing);let b=0;const _=function(t){m=Math.max(m,i.measureText(t).width+b)};return i.save(),i.font=h.string,J(t.title,_),i.font=l.string,J(t.beforeBody.concat(t.afterBody),_),b=e.displayColors?a+2+e.boxPadding:0,J(s,(t=>{J(t.before,_),J(t.lines,_),J(t.after,_)})),b=0,i.font=c.string,J(t.footer,_),i.restore(),m+=g.width,{width:m,height:p}}function Ro(t,e,i,s){const{x:n,width:o}=i,{width:a,chartArea:{left:r,right:l}}=t;let h="center";return"center"===s?h=n<=(r+l)/2?"left":"right":n<=o/2?h="left":n>=a-o/2&&(h="right"),function(t,e,i,s){const{x:n,width:o}=s,a=i.caretSize+i.caretPadding;return"left"===t&&n+o+a>e.width||"right"===t&&n-o-a<0||void 0}(h,t,e,i)&&(h="center"),h}function Eo(t,e,i){const s=e.yAlign||function(t,e){const{y:i,height:s}=e;return i<s/2?"top":i>t.height-s/2?"bottom":"center"}(t,i);return{xAlign:e.xAlign||Ro(t,e,i,s),yAlign:s}}function Io(t,e,i,s){const{caretSize:n,caretPadding:o,cornerRadius:a}=t,{xAlign:r,yAlign:l}=i,h=n+o,{topLeft:c,topRight:d,bottomLeft:u,bottomRight:f}=Fe(a);let g=function(t,e){let{x:i,width:s}=t;return"right"===e?i-=s:"center"===e&&(i-=s/2),i}(e,r);const p=function(t,e,i){let{y:s,height:n}=t;return"top"===e?s+=i:s-="bottom"===e?n+i:n/2,s}(e,l,h);return"center"===l?"left"===r?g+=h:"right"===r&&(g-=h):"left"===r?g-=Math.max(c,u)+o:"right"===r&&(g+=Math.max(d,f)+o),{x:Ht(g,0,s.width-e.width),y:Ht(p,0,s.height-e.height)}}function zo(t,e,i){const s=Be(i.padding);return"center"===e?t.x+t.width/2:"right"===e?t.x+t.width-s.right:t.x+s.left}function Fo(t){return Oo([],Ao(t))}function Bo(t,e){const i=e&&e.dataset&&e.dataset.tooltip&&e.dataset.tooltip.callbacks;return i?t.override(i):t}class Vo extends Ms{constructor(t){super(),this.opacity=0,this._active=[],this._chart=t._chart,this._eventPosition=void 0,this._size=void 0,this._cachedAnimations=void 0,this._tooltipItems=[],this.$animations=void 0,this.$context=void 0,this.options=t.options,this.dataPoints=void 0,this.title=void 0,this.beforeBody=void 0,this.body=void 0,this.afterBody=void 0,this.footer=void 0,this.xAlign=void 0,this.yAlign=void 0,this.x=void 0,this.y=void 0,this.height=void 0,this.width=void 0,this.caretX=void 0,this.caretY=void 0,this.labelColors=void 0,this.labelPointStyles=void 0,this.labelTextColors=void 0}initialize(t){this.options=t,this._cachedAnimations=void 0,this.$context=void 0}_resolveAnimations(){const t=this._cachedAnimations;if(t)return t;const e=this._chart,i=this.options.setContext(this.getContext()),s=i.enabled&&e.options.animation&&i.animations,n=new cs(this._chart,s);return s._cacheable&&(this._cachedAnimations=Object.freeze(n)),n}getContext(){return this.$context||(this.$context=(t=this._chart.getContext(),e=this,i=this._tooltipItems,He(t,{tooltip:e,tooltipItems:i,type:"tooltip"})));var t,e,i}getTitle(t,e){const{callbacks:i}=e,s=i.beforeTitle.apply(this,[t]),n=i.title.apply(this,[t]),o=i.afterTitle.apply(this,[t]);let a=[];return a=Oo(a,Ao(s)),a=Oo(a,Ao(n)),a=Oo(a,Ao(o)),a}getBeforeBody(t,e){return Fo(e.callbacks.beforeBody.apply(this,[t]))}getBody(t,e){const{callbacks:i}=e,s=[];return J(t,(t=>{const e={before:[],lines:[],after:[]},n=Bo(i,t);Oo(e.before,Ao(n.beforeLabel.call(this,t))),Oo(e.lines,n.label.call(this,t)),Oo(e.after,Ao(n.afterLabel.call(this,t))),s.push(e)})),s}getAfterBody(t,e){return Fo(e.callbacks.afterBody.apply(this,[t]))}getFooter(t,e){const{callbacks:i}=e,s=i.beforeFooter.apply(this,[t]),n=i.footer.apply(this,[t]),o=i.afterFooter.apply(this,[t]);let a=[];return a=Oo(a,Ao(s)),a=Oo(a,Ao(n)),a=Oo(a,Ao(o)),a}_createItems(t){const e=this._active,i=this._chart.data,s=[],n=[],o=[];let a,r,l=[];for(a=0,r=e.length;a<r;++a)l.push(To(this._chart,e[a]));return t.filter&&(l=l.filter(((e,s,n)=>t.filter(e,s,n,i)))),t.itemSort&&(l=l.sort(((e,s)=>t.itemSort(e,s,i)))),J(l,(e=>{const i=Bo(t.callbacks,e);s.push(i.labelColor.call(this,e)),n.push(i.labelPointStyle.call(this,e)),o.push(i.labelTextColor.call(this,e))})),this.labelColors=s,this.labelPointStyles=n,this.labelTextColors=o,this.dataPoints=l,l}update(t,e){const i=this.options.setContext(this.getContext()),s=this._active;let n,o=[];if(s.length){const t=Co[i.position].call(this,s,this._eventPosition);o=this._createItems(i),this.title=this.getTitle(o,i),this.beforeBody=this.getBeforeBody(o,i),this.body=this.getBody(o,i),this.afterBody=this.getAfterBody(o,i),this.footer=this.getFooter(o,i);const e=this._size=Lo(this,i),a=Object.assign({},t,e),r=Eo(this._chart,i,a),l=Io(i,a,r,this._chart);this.xAlign=r.xAlign,this.yAlign=r.yAlign,n={opacity:1,x:l.x,y:l.y,width:e.width,height:e.height,caretX:t.x,caretY:t.y}}else 0!==this.opacity&&(n={opacity:0});this._tooltipItems=o,this.$context=void 0,n&&this._resolveAnimations().update(this,n),t&&i.external&&i.external.call(this,{chart:this._chart,tooltip:this,replay:e})}drawCaret(t,e,i,s){const n=this.getCaretPosition(t,i,s);e.lineTo(n.x1,n.y1),e.lineTo(n.x2,n.y2),e.lineTo(n.x3,n.y3)}getCaretPosition(t,e,i){const{xAlign:s,yAlign:n}=this,{caretSize:o,cornerRadius:a}=i,{topLeft:r,topRight:l,bottomLeft:h,bottomRight:c}=Fe(a),{x:d,y:u}=t,{width:f,height:g}=e;let p,m,x,b,_,y;return"center"===n?(_=u+g/2,"left"===s?(p=d,m=p-o,b=_+o,y=_-o):(p=d+f,m=p+o,b=_-o,y=_+o),x=p):(m="left"===s?d+Math.max(r,h)+o:"right"===s?d+f-Math.max(l,c)-o:this.caretX,"top"===n?(b=u,_=b-o,p=m-o,x=m+o):(b=u+g,_=b+o,p=m+o,x=m-o),y=b),{x1:p,x2:m,x3:x,y1:b,y2:_,y3:y}}drawTitle(t,e,i){const s=this.title,n=s.length;let o,a,r;if(n){const l=Ti(i.rtl,this.x,this.width);for(t.x=zo(this,i.titleAlign,i),e.textAlign=l.textAlign(i.titleAlign),e.textBaseline="middle",o=Ve(i.titleFont),a=i.titleSpacing,e.fillStyle=i.titleColor,e.font=o.string,r=0;r<n;++r)e.fillText(s[r],l.x(t.x),t.y+o.lineHeight/2),t.y+=o.lineHeight+a,r+1===n&&(t.y+=i.titleMarginBottom-a)}}_drawColorBox(t,e,i,s,n){const o=this.labelColors[i],a=this.labelPointStyles[i],{boxHeight:r,boxWidth:l,boxPadding:h}=n,c=Ve(n.bodyFont),d=zo(this,"left",n),u=s.x(d),f=r<c.lineHeight?(c.lineHeight-r)/2:0,g=e.y+f;if(n.usePointStyle){const e={radius:Math.min(l,r)/2,pointStyle:a.pointStyle,rotation:a.rotation,borderWidth:1},i=s.leftForLtr(u,l)+l/2,h=g+r/2;t.strokeStyle=n.multiKeyBackground,t.fillStyle=n.multiKeyBackground,Kt(t,e,i,h),t.strokeStyle=o.borderColor,t.fillStyle=o.backgroundColor,Kt(t,e,i,h)}else{t.lineWidth=o.borderWidth||1,t.strokeStyle=o.borderColor,t.setLineDash(o.borderDash||[]),t.lineDashOffset=o.borderDashOffset||0;const e=s.leftForLtr(u,l-h),i=s.leftForLtr(s.xPlus(u,1),l-h-2),a=Fe(o.borderRadius);Object.values(a).some((t=>0!==t))?(t.beginPath(),t.fillStyle=n.multiKeyBackground,se(t,{x:e,y:g,w:l,h:r,radius:a}),t.fill(),t.stroke(),t.fillStyle=o.backgroundColor,t.beginPath(),se(t,{x:i,y:g+1,w:l-2,h:r-2,radius:a}),t.fill()):(t.fillStyle=n.multiKeyBackground,t.fillRect(e,g,l,r),t.strokeRect(e,g,l,r),t.fillStyle=o.backgroundColor,t.fillRect(i,g+1,l-2,r-2))}t.fillStyle=this.labelTextColors[i]}drawBody(t,e,i){const{body:s}=this,{bodySpacing:n,bodyAlign:o,displayColors:a,boxHeight:r,boxWidth:l,boxPadding:h}=i,c=Ve(i.bodyFont);let d=c.lineHeight,u=0;const f=Ti(i.rtl,this.x,this.width),g=function(i){e.fillText(i,f.x(t.x+u),t.y+d/2),t.y+=d+n},p=f.textAlign(o);let m,x,b,_,y,v,w;for(e.textAlign=o,e.textBaseline="middle",e.font=c.string,t.x=zo(this,p,i),e.fillStyle=i.bodyColor,J(this.beforeBody,g),u=a&&"right"!==p?"center"===o?l/2+h:l+2+h:0,_=0,v=s.length;_<v;++_){for(m=s[_],x=this.labelTextColors[_],e.fillStyle=x,J(m.before,g),b=m.lines,a&&b.length&&(this._drawColorBox(e,t,_,f,i),d=Math.max(c.lineHeight,r)),y=0,w=b.length;y<w;++y)g(b[y]),d=c.lineHeight;J(m.after,g)}u=0,d=c.lineHeight,J(this.afterBody,g),t.y-=n}drawFooter(t,e,i){const s=this.footer,n=s.length;let o,a;if(n){const r=Ti(i.rtl,this.x,this.width);for(t.x=zo(this,i.footerAlign,i),t.y+=i.footerMarginTop,e.textAlign=r.textAlign(i.footerAlign),e.textBaseline="middle",o=Ve(i.footerFont),e.fillStyle=i.footerColor,e.font=o.string,a=0;a<n;++a)e.fillText(s[a],r.x(t.x),t.y+o.lineHeight/2),t.y+=o.lineHeight+i.footerSpacing}}drawBackground(t,e,i,s){const{xAlign:n,yAlign:o}=this,{x:a,y:r}=t,{width:l,height:h}=i,{topLeft:c,topRight:d,bottomLeft:u,bottomRight:f}=Fe(s.cornerRadius);e.fillStyle=s.backgroundColor,e.strokeStyle=s.borderColor,e.lineWidth=s.borderWidth,e.beginPath(),e.moveTo(a+c,r),"top"===o&&this.drawCaret(t,e,i,s),e.lineTo(a+l-d,r),e.quadraticCurveTo(a+l,r,a+l,r+d),"center"===o&&"right"===n&&this.drawCaret(t,e,i,s),e.lineTo(a+l,r+h-f),e.quadraticCurveTo(a+l,r+h,a+l-f,r+h),"bottom"===o&&this.drawCaret(t,e,i,s),e.lineTo(a+u,r+h),e.quadraticCurveTo(a,r+h,a,r+h-u),"center"===o&&"left"===n&&this.drawCaret(t,e,i,s),e.lineTo(a,r+c),e.quadraticCurveTo(a,r,a+c,r),e.closePath(),e.fill(),s.borderWidth>0&&e.stroke()}_updateAnimationTarget(t){const e=this._chart,i=this.$animations,s=i&&i.x,n=i&&i.y;if(s||n){const i=Co[t.position].call(this,this._active,this._eventPosition);if(!i)return;const o=this._size=Lo(this,t),a=Object.assign({},i,this._size),r=Eo(e,t,a),l=Io(t,a,r,e);s._to===l.x&&n._to===l.y||(this.xAlign=r.xAlign,this.yAlign=r.yAlign,this.width=o.width,this.height=o.height,this.caretX=i.x,this.caretY=i.y,this._resolveAnimations().update(this,l))}}draw(t){const e=this.options.setContext(this.getContext());let i=this.opacity;if(!i)return;this._updateAnimationTarget(e);const s={width:this.width,height:this.height},n={x:this.x,y:this.y};i=Math.abs(i)<.001?0:i;const o=Be(e.padding),a=this.title.length||this.beforeBody.length||this.body.length||this.afterBody.length||this.footer.length;e.enabled&&a&&(t.save(),t.globalAlpha=i,this.drawBackground(n,t,s,e),Li(t,e.textDirection),n.y+=o.top,this.drawTitle(n,t,e),this.drawBody(n,t,e),this.drawFooter(n,t,e),Ri(t,e.textDirection),t.restore())}getActiveElements(){return this._active||[]}setActiveElements(t,e){const i=this._active,s=t.map((({datasetIndex:t,index:e})=>{const i=this._chart.getDatasetMeta(t);if(!i)throw new Error("Cannot find a dataset at index "+t);return{datasetIndex:t,element:i.data[e],index:e}})),n=!tt(i,s),o=this._positionChanged(s,e);(n||o)&&(this._active=s,this._eventPosition=e,this.update(!0))}handleEvent(t,e){const i=this.options,s=this._active||[];let n=!1,o=[];"mouseout"!==t.type&&(o=this._chart.getElementsAtEventForMode(t,i.mode,i,e),i.reverse&&o.reverse());const a=this._positionChanged(o,t);return n=e||!tt(o,s)||a,n&&(this._active=o,(i.enabled||i.external)&&(this._eventPosition={x:t.x,y:t.y},this.update(!0,e))),n}_positionChanged(t,e){const{caretX:i,caretY:s,options:n}=this,o=Co[n.position].call(this,t,e);return!1!==o&&(i!==o.x||s!==o.y)}}Vo.positioners=Co;var Wo={id:"tooltip",_element:Vo,positioners:Co,afterInit(t,e,i){i&&(t.tooltip=new Vo({_chart:t,options:i}))},beforeUpdate(t,e,i){t.tooltip&&t.tooltip.initialize(i)},reset(t,e,i){t.tooltip&&t.tooltip.initialize(i)},afterDraw(t){const e=t.tooltip,i={tooltip:e};!1!==t.notifyPlugins("beforeTooltipDraw",i)&&(e&&e.draw(t.ctx),t.notifyPlugins("afterTooltipDraw",i))},afterEvent(t,e){if(t.tooltip){const i=e.replay;t.tooltip.handleEvent(e.event,i)&&(e.changed=!0)}},defaults:{enabled:!0,external:null,position:"average",backgroundColor:"rgba(0,0,0,0.8)",titleColor:"#fff",titleFont:{weight:"bold"},titleSpacing:2,titleMarginBottom:6,titleAlign:"left",bodyColor:"#fff",bodySpacing:2,bodyFont:{},bodyAlign:"left",footerColor:"#fff",footerSpacing:2,footerMarginTop:6,footerFont:{weight:"bold"},footerAlign:"left",padding:6,caretPadding:2,caretSize:5,cornerRadius:6,boxHeight:(t,e)=>e.bodyFont.size,boxWidth:(t,e)=>e.bodyFont.size,multiKeyBackground:"#fff",displayColors:!0,boxPadding:0,borderColor:"rgba(0,0,0,0)",borderWidth:0,animation:{duration:400,easing:"easeOutQuart"},animations:{numbers:{type:"number",properties:["x","y","width","height","caretX","caretY"]},opacity:{easing:"linear",duration:200}},callbacks:{beforeTitle:H,title(t){if(t.length>0){const e=t[0],i=e.chart.data.labels,s=i?i.length:0;if(this&&this.options&&"dataset"===this.options.mode)return e.dataset.label||"";if(e.label)return e.label;if(s>0&&e.dataIndex<s)return i[e.dataIndex]}return""},afterTitle:H,beforeBody:H,beforeLabel:H,label(t){if(this&&this.options&&"dataset"===this.options.mode)return t.label+": "+t.formattedValue||t.formattedValue;let e=t.dataset.label||"";e&&(e+=": ");const i=t.formattedValue;return $(i)||(e+=i),e},labelColor(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{borderColor:e.borderColor,backgroundColor:e.backgroundColor,borderWidth:e.borderWidth,borderDash:e.borderDash,borderDashOffset:e.borderDashOffset,borderRadius:0}},labelTextColor(){return this.options.bodyColor},labelPointStyle(t){const e=t.chart.getDatasetMeta(t.datasetIndex).controller.getStyle(t.dataIndex);return{pointStyle:e.pointStyle,rotation:e.rotation}},afterLabel:H,afterBody:H,beforeFooter:H,footer:H,afterFooter:H}},defaultRoutes:{bodyFont:"font",footerFont:"font",titleFont:"font"},descriptors:{_scriptable:t=>"filter"!==t&&"itemSort"!==t&&"external"!==t,_indexable:!1,callbacks:{_scriptable:!1,_indexable:!1},animation:{_fallback:!1},animations:{_fallback:"animation"}},additionalOptionScopes:["interaction"]},No=Object.freeze({__proto__:null,Decimation:io,Filler:yo,Legend:Mo,SubTitle:Do,Title:So,Tooltip:Wo});function Ho(t,e,i){const s=t.indexOf(e);if(-1===s)return((t,e,i)=>"string"==typeof e?t.push(e)-1:isNaN(e)?null:i)(t,e,i);return s!==t.lastIndexOf(e)?i:s}class jo extends Es{constructor(t){super(t),this._startValue=void 0,this._valueRange=0}parse(t,e){if($(t))return null;const i=this.getLabels();return((t,e)=>null===t?null:Ht(Math.round(t),0,e))(e=isFinite(e)&&i[e]===t?e:Ho(i,t,K(e,t)),i.length-1)}determineDataLimits(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let{min:i,max:s}=this.getMinMax(!0);"ticks"===this.options.bounds&&(t||(i=0),e||(s=this.getLabels().length-1)),this.min=i,this.max=s}buildTicks(){const t=this.min,e=this.max,i=this.options.offset,s=[];let n=this.getLabels();n=0===t&&e===n.length-1?n:n.slice(t,e+1),this._valueRange=Math.max(n.length-(i?0:1),1),this._startValue=this.min-(i?.5:0);for(let i=t;i<=e;i++)s.push({value:i});return s}getLabelForValue(t){const e=this.getLabels();return t>=0&&t<e.length?e[t]:t}configure(){super.configure(),this.isHorizontal()||(this._reversePixels=!this._reversePixels)}getPixelForValue(t){return"number"!=typeof t&&(t=this.parse(t)),null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getPixelForTick(t){const e=this.ticks;return t<0||t>e.length-1?null:this.getPixelForValue(e[t].value)}getValueForPixel(t){return Math.round(this._startValue+this.getDecimalForPixel(t)*this._valueRange)}getBasePixel(){return this.bottom}}function $o(t,e,{horizontal:i,minRotation:s}){const n=Et(s),o=(i?Math.sin(n):Math.cos(n))||.001,a=.75*e*(""+t).length;return Math.min(e/o,a)}jo.id="category",jo.defaults={ticks:{callback:jo.prototype.getLabelForValue}};class Yo extends Es{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._endValue=void 0,this._valueRange=0}parse(t,e){return $(t)||("number"==typeof t||t instanceof Number)&&!isFinite(+t)?null:+t}handleTickRangeOptions(){const{beginAtZero:t}=this.options,{minDefined:e,maxDefined:i}=this.getUserBounds();let{min:s,max:n}=this;const o=t=>s=e?s:t,a=t=>n=i?n:t;if(t){const t=Dt(s),e=Dt(n);t<0&&e<0?a(0):t>0&&e>0&&o(0)}if(s===n){let e=1;(n>=Number.MAX_SAFE_INTEGER||s<=Number.MIN_SAFE_INTEGER)&&(e=Math.abs(.05*n)),a(n+e),t||o(s-e)}this.min=s,this.max=n}getTickLimit(){const t=this.options.ticks;let e,{maxTicksLimit:i,stepSize:s}=t;return s?(e=Math.ceil(this.max/s)-Math.floor(this.min/s)+1,e>1e3&&(console.warn(`scales.${this.id}.ticks.stepSize: ${s} would result generating up to ${e} ticks. Limiting to 1000.`),e=1e3)):(e=this.computeTickLimit(),i=i||11),i&&(e=Math.min(i,e)),e}computeTickLimit(){return Number.POSITIVE_INFINITY}buildTicks(){const t=this.options,e=t.ticks;let i=this.getTickLimit();i=Math.max(2,i);const s=function(t,e){const i=[],{bounds:s,step:n,min:o,max:a,precision:r,count:l,maxTicks:h,maxDigits:c,includeBounds:d}=t,u=n||1,f=h-1,{min:g,max:p}=e,m=!$(o),x=!$(a),b=!$(l),_=(p-g)/(c+1);let y,v,w,M,k=Ct((p-g)/f/u)*u;if(k<1e-14&&!m&&!x)return[{value:g},{value:p}];M=Math.ceil(p/k)-Math.floor(g/k),M>f&&(k=Ct(M*k/f/u)*u),$(r)||(y=Math.pow(10,r),k=Math.ceil(k*y)/y),"ticks"===s?(v=Math.floor(g/k)*k,w=Math.ceil(p/k)*k):(v=g,w=p),m&&x&&n&&Lt((a-o)/n,k/1e3)?(M=Math.round(Math.min((a-o)/k,h)),k=(a-o)/M,v=o,w=a):b?(v=m?o:v,w=x?a:w,M=l-1,k=(w-v)/M):(M=(w-v)/k,M=Tt(M,Math.round(M),k/1e3)?Math.round(M):Math.ceil(M));const S=Math.max(zt(k),zt(v));y=Math.pow(10,$(r)?S:r),v=Math.round(v*y)/y,w=Math.round(w*y)/y;let P=0;for(m&&(d&&v!==o?(i.push({value:o}),v<o&&P++,Tt(Math.round((v+P*k)*y)/y,o,$o(o,_,t))&&P++):v<o&&P++);P<M;++P)i.push({value:Math.round((v+P*k)*y)/y});return x&&d&&w!==a?i.length&&Tt(i[i.length-1].value,a,$o(a,_,t))?i[i.length-1].value=a:i.push({value:a}):x&&w!==a||i.push({value:w}),i}({maxTicks:i,bounds:t.bounds,min:t.min,max:t.max,precision:e.precision,step:e.stepSize,count:e.count,maxDigits:this._maxDigits(),horizontal:this.isHorizontal(),minRotation:e.minRotation||0,includeBounds:!1!==e.includeBounds},this._range||this);return"ticks"===t.bounds&&Rt(s,this,"value"),t.reverse?(s.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),s}configure(){const t=this.ticks;let e=this.min,i=this.max;if(super.configure(),this.options.offset&&t.length){const s=(i-e)/Math.max(t.length-1,1)/2;e-=s,i+=s}this._startValue=e,this._endValue=i,this._valueRange=i-e}getLabelForValue(t){return Ai(t,this.chart.options.locale)}}class Uo extends Yo{determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=X(t)?t:0,this.max=X(e)?e:1,this.handleTickRangeOptions()}computeTickLimit(){const t=this.isHorizontal(),e=t?this.width:this.height,i=Et(this.options.ticks.minRotation),s=(t?Math.sin(i):Math.cos(i))||.001,n=this._resolveTickFontOptions(0);return Math.ceil(e/Math.min(40,n.lineHeight/s))}getPixelForValue(t){return null===t?NaN:this.getPixelForDecimal((t-this._startValue)/this._valueRange)}getValueForPixel(t){return this._startValue+this.getDecimalForPixel(t)*this._valueRange}}function Xo(t){return 1===t/Math.pow(10,Math.floor(Pt(t)))}Uo.id="linear",Uo.defaults={ticks:{callback:Ss.formatters.numeric}};class qo extends Es{constructor(t){super(t),this.start=void 0,this.end=void 0,this._startValue=void 0,this._valueRange=0}parse(t,e){const i=Yo.prototype.parse.apply(this,[t,e]);if(0!==i)return X(i)&&i>0?i:null;this._zero=!0}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!0);this.min=X(t)?Math.max(0,t):null,this.max=X(e)?Math.max(0,e):null,this.options.beginAtZero&&(this._zero=!0),this.handleTickRangeOptions()}handleTickRangeOptions(){const{minDefined:t,maxDefined:e}=this.getUserBounds();let i=this.min,s=this.max;const n=e=>i=t?i:e,o=t=>s=e?s:t,a=(t,e)=>Math.pow(10,Math.floor(Pt(t))+e);i===s&&(i<=0?(n(1),o(10)):(n(a(i,-1)),o(a(s,1)))),i<=0&&n(a(s,-1)),s<=0&&o(a(i,1)),this._zero&&this.min!==this._suggestedMin&&i===a(this.min,0)&&n(a(i,-1)),this.min=i,this.max=s}buildTicks(){const t=this.options,e=function(t,e){const i=Math.floor(Pt(e.max)),s=Math.ceil(e.max/Math.pow(10,i)),n=[];let o=q(t.min,Math.pow(10,Math.floor(Pt(e.min)))),a=Math.floor(Pt(o)),r=Math.floor(o/Math.pow(10,a)),l=a<0?Math.pow(10,Math.abs(a)):1;do{n.push({value:o,major:Xo(o)}),++r,10===r&&(r=1,++a,l=a>=0?1:l),o=Math.round(r*Math.pow(10,a)*l)/l}while(a<i||a===i&&r<s);const h=q(t.max,o);return n.push({value:h,major:Xo(o)}),n}({min:this._userMin,max:this._userMax},this);return"ticks"===t.bounds&&Rt(e,this,"value"),t.reverse?(e.reverse(),this.start=this.max,this.end=this.min):(this.start=this.min,this.end=this.max),e}getLabelForValue(t){return void 0===t?"0":Ai(t,this.chart.options.locale)}configure(){const t=this.min;super.configure(),this._startValue=Pt(t),this._valueRange=Pt(this.max)-Pt(t)}getPixelForValue(t){return void 0!==t&&0!==t||(t=this.min),null===t||isNaN(t)?NaN:this.getPixelForDecimal(t===this.min?0:(Pt(t)-this._startValue)/this._valueRange)}getValueForPixel(t){const e=this.getDecimalForPixel(t);return Math.pow(10,this._startValue+e*this._valueRange)}}function Ko(t){const e=t.ticks;if(e.display&&t.display){const t=Be(e.backdropPadding);return K(e.font&&e.font.size,xt.font.size)+t.height}return 0}function Go(t,e,i,s,n){return t===s||t===n?{start:e-i/2,end:e+i/2}:t<s||t>n?{start:e-i,end:e}:{start:e,end:e+i}}function Zo(t){const e={l:0,r:t.width,t:0,b:t.height-t.paddingTop},i={},s=[],n=[],o=t.getLabels().length;for(let h=0;h<o;h++){const o=t.options.pointLabels.setContext(t.getPointLabelContext(h));n[h]=o.padding;const c=t.getPointPosition(h,t.drawingArea+n[h]),d=Ve(o.font),u=(a=t.ctx,r=d,l=Y(l=t._pointLabels[h])?l:[l],{w:Ut(a,r.string,l),h:l.length*r.lineHeight});s[h]=u;const f=t.getIndexAngle(h),g=It(f),p=Go(g,c.x,u.w,0,180),m=Go(g,c.y,u.h,90,270);p.start<e.l&&(e.l=p.start,i.l=f),p.end>e.r&&(e.r=p.end,i.r=f),m.start<e.t&&(e.t=m.start,i.t=f),m.end>e.b&&(e.b=m.end,i.b=f)}var a,r,l;t._setReductions(t.drawingArea,e,i),t._pointLabelItems=function(t,e,i){const s=[],n=t.getLabels().length,o=t.options,a=Ko(o),r=t.getDistanceFromCenterForValue(o.ticks.reverse?t.min:t.max);for(let o=0;o<n;o++){const n=0===o?a/2:0,l=t.getPointPosition(o,r+n+i[o]),h=It(t.getIndexAngle(o)),c=e[o],d=ta(l.y,c.h,h),u=Qo(h),f=Jo(l.x,c.w,u);s.push({x:l.x,y:d,textAlign:u,left:f,top:d,right:f+c.w,bottom:d+c.h})}return s}(t,s,n)}function Qo(t){return 0===t||180===t?"center":t<180?"left":"right"}function Jo(t,e,i){return"right"===i?t-=e:"center"===i&&(t-=e/2),t}function ta(t,e,i){return 90===i||270===i?t-=e/2:(i>270||i<90)&&(t-=e),t}function ea(t,e,i,s){const{ctx:n}=t;if(i)n.arc(t.xCenter,t.yCenter,e,0,_t);else{let i=t.getPointPosition(0,e);n.moveTo(i.x,i.y);for(let o=1;o<s;o++)i=t.getPointPosition(o,e),n.lineTo(i.x,i.y)}}function ia(t){return At(t)?t:0}qo.id="logarithmic",qo.defaults={ticks:{callback:Ss.formatters.logarithmic,major:{enabled:!0}}};class sa extends Yo{constructor(t){super(t),this.xCenter=void 0,this.yCenter=void 0,this.drawingArea=void 0,this._pointLabels=[],this._pointLabelItems=[]}setDimensions(){this.width=this.maxWidth,this.height=this.maxHeight,this.paddingTop=Ko(this.options)/2,this.xCenter=Math.floor(this.width/2),this.yCenter=Math.floor((this.height-this.paddingTop)/2),this.drawingArea=Math.min(this.height-this.paddingTop,this.width)/2}determineDataLimits(){const{min:t,max:e}=this.getMinMax(!1);this.min=X(t)&&!isNaN(t)?t:0,this.max=X(e)&&!isNaN(e)?e:0,this.handleTickRangeOptions()}computeTickLimit(){return Math.ceil(this.drawingArea/Ko(this.options))}generateTickLabels(t){Yo.prototype.generateTickLabels.call(this,t),this._pointLabels=this.getLabels().map(((t,e)=>{const i=Q(this.options.pointLabels.callback,[t,e],this);return i||0===i?i:""}))}fit(){const t=this.options;t.display&&t.pointLabels.display?Zo(this):this.setCenterPoint(0,0,0,0)}_setReductions(t,e,i){let s=e.l/Math.sin(i.l),n=Math.max(e.r-this.width,0)/Math.sin(i.r),o=-e.t/Math.cos(i.t),a=-Math.max(e.b-(this.height-this.paddingTop),0)/Math.cos(i.b);s=ia(s),n=ia(n),o=ia(o),a=ia(a),this.drawingArea=Math.max(t/2,Math.min(Math.floor(t-(s+n)/2),Math.floor(t-(o+a)/2))),this.setCenterPoint(s,n,o,a)}setCenterPoint(t,e,i,s){const n=this.width-e-this.drawingArea,o=t+this.drawingArea,a=i+this.drawingArea,r=this.height-this.paddingTop-s-this.drawingArea;this.xCenter=Math.floor((o+n)/2+this.left),this.yCenter=Math.floor((a+r)/2+this.top+this.paddingTop)}getIndexAngle(t){return Wt(t*(_t/this.getLabels().length)+Et(this.options.startAngle||0))}getDistanceFromCenterForValue(t){if($(t))return NaN;const e=this.drawingArea/(this.max-this.min);return this.options.reverse?(this.max-t)*e:(t-this.min)*e}getValueForDistanceFromCenter(t){if($(t))return NaN;const e=t/(this.drawingArea/(this.max-this.min));return this.options.reverse?this.max-e:this.min+e}getPointLabelContext(t){const e=this._pointLabels||[];if(t>=0&&t<e.length){const i=e[t];return function(t,e,i){return He(t,{label:i,index:e,type:"pointLabel"})}(this.getContext(),t,i)}}getPointPosition(t,e){const i=this.getIndexAngle(t)-Mt;return{x:Math.cos(i)*e+this.xCenter,y:Math.sin(i)*e+this.yCenter,angle:i}}getPointPositionForValue(t,e){return this.getPointPosition(t,this.getDistanceFromCenterForValue(e))}getBasePosition(t){return this.getPointPositionForValue(t||0,this.getBaseValue())}getPointLabelPosition(t){const{left:e,top:i,right:s,bottom:n}=this._pointLabelItems[t];return{left:e,top:i,right:s,bottom:n}}drawBackground(){const{backgroundColor:t,grid:{circular:e}}=this.options;if(t){const i=this.ctx;i.save(),i.beginPath(),ea(this,this.getDistanceFromCenterForValue(this._endValue),e,this.getLabels().length),i.closePath(),i.fillStyle=t,i.fill(),i.restore()}}drawGrid(){const t=this.ctx,e=this.options,{angleLines:i,grid:s}=e,n=this.getLabels().length;let o,a,r;if(e.pointLabels.display&&function(t,e){const{ctx:i,options:{pointLabels:s}}=t;for(let n=e-1;n>=0;n--){const e=s.setContext(t.getPointLabelContext(n)),o=Ve(e.font),{x:a,y:r,textAlign:l,left:h,top:c,right:d,bottom:u}=t._pointLabelItems[n],{backdropColor:f}=e;if(!$(f)){const t=Be(e.backdropPadding);i.fillStyle=f,i.fillRect(h-t.left,c-t.top,d-h+t.width,u-c+t.height)}ee(i,t._pointLabels[n],a,r+o.lineHeight/2,o,{color:e.color,textAlign:l,textBaseline:"middle"})}}(this,n),s.display&&this.ticks.forEach(((t,e)=>{if(0!==e){a=this.getDistanceFromCenterForValue(t.value);!function(t,e,i,s){const n=t.ctx,o=e.circular,{color:a,lineWidth:r}=e;!o&&!s||!a||!r||i<0||(n.save(),n.strokeStyle=a,n.lineWidth=r,n.setLineDash(e.borderDash),n.lineDashOffset=e.borderDashOffset,n.beginPath(),ea(t,i,o,s),n.closePath(),n.stroke(),n.restore())}(this,s.setContext(this.getContext(e-1)),a,n)}})),i.display){for(t.save(),o=this.getLabels().length-1;o>=0;o--){const s=i.setContext(this.getPointLabelContext(o)),{color:n,lineWidth:l}=s;l&&n&&(t.lineWidth=l,t.strokeStyle=n,t.setLineDash(s.borderDash),t.lineDashOffset=s.borderDashOffset,a=this.getDistanceFromCenterForValue(e.ticks.reverse?this.min:this.max),r=this.getPointPosition(o,a),t.beginPath(),t.moveTo(this.xCenter,this.yCenter),t.lineTo(r.x,r.y),t.stroke())}t.restore()}}drawBorder(){}drawLabels(){const t=this.ctx,e=this.options,i=e.ticks;if(!i.display)return;const s=this.getIndexAngle(0);let n,o;t.save(),t.translate(this.xCenter,this.yCenter),t.rotate(s),t.textAlign="center",t.textBaseline="middle",this.ticks.forEach(((s,a)=>{if(0===a&&!e.reverse)return;const r=i.setContext(this.getContext(a)),l=Ve(r.font);if(n=this.getDistanceFromCenterForValue(this.ticks[a].value),r.showLabelBackdrop){t.font=l.string,o=t.measureText(s.label).width,t.fillStyle=r.backdropColor;const e=Be(r.backdropPadding);t.fillRect(-o/2-e.left,-n-l.size/2-e.top,o+e.width,l.size+e.height)}ee(t,s.label,0,-n,l,{color:r.color})})),t.restore()}drawTitle(){}}sa.id="radialLinear",sa.defaults={display:!0,animate:!0,position:"chartArea",angleLines:{display:!0,lineWidth:1,borderDash:[],borderDashOffset:0},grid:{circular:!1},startAngle:0,ticks:{showLabelBackdrop:!0,callback:Ss.formatters.numeric},pointLabels:{backdropColor:void 0,backdropPadding:2,display:!0,font:{size:10},callback:t=>t,padding:5}},sa.defaultRoutes={"angleLines.color":"borderColor","pointLabels.color":"color","ticks.color":"color"},sa.descriptors={angleLines:{_fallback:"grid"}};const na={millisecond:{common:!0,size:1,steps:1e3},second:{common:!0,size:1e3,steps:60},minute:{common:!0,size:6e4,steps:60},hour:{common:!0,size:36e5,steps:24},day:{common:!0,size:864e5,steps:30},week:{common:!1,size:6048e5,steps:4},month:{common:!0,size:2628e6,steps:12},quarter:{common:!1,size:7884e6,steps:4},year:{common:!0,size:3154e7}},oa=Object.keys(na);function aa(t,e){return t-e}function ra(t,e){if($(e))return null;const i=t._adapter,{parser:s,round:n,isoWeekday:o}=t._parseOpts;let a=e;return"function"==typeof s&&(a=s(a)),X(a)||(a="string"==typeof s?i.parse(a,s):i.parse(a)),null===a?null:(n&&(a="week"!==n||!At(o)&&!0!==o?i.startOf(a,n):i.startOf(a,"isoWeek",o)),+a)}function la(t,e,i,s){const n=oa.length;for(let o=oa.indexOf(t);o<n-1;++o){const t=na[oa[o]],n=t.steps?t.steps:Number.MAX_SAFE_INTEGER;if(t.common&&Math.ceil((i-e)/(n*t.size))<=s)return oa[o]}return oa[n-1]}function ha(t,e,i){if(i){if(i.length){const{lo:s,hi:n}=ne(i,e);t[i[s]>=e?i[s]:i[n]]=!0}}else t[e]=!0}function ca(t,e,i){const s=[],n={},o=e.length;let a,r;for(a=0;a<o;++a)r=e[a],n[r]=a,s.push({value:r,major:!1});return 0!==o&&i?function(t,e,i,s){const n=t._adapter,o=+n.startOf(e[0].value,s),a=e[e.length-1].value;let r,l;for(r=o;r<=a;r=+n.add(r,1,s))l=i[r],l>=0&&(e[l].major=!0);return e}(t,s,n,i):s}class da extends Es{constructor(t){super(t),this._cache={data:[],labels:[],all:[]},this._unit="day",this._majorUnit=void 0,this._offsets={},this._normalized=!1,this._parseOpts=void 0}init(t,e){const i=t.time||(t.time={}),s=this._adapter=new dn._date(t.adapters.date);ot(i.displayFormats,s.formats()),this._parseOpts={parser:i.parser,round:i.round,isoWeekday:i.isoWeekday},super.init(t),this._normalized=e.normalized}parse(t,e){return void 0===t?null:ra(this,t)}beforeLayout(){super.beforeLayout(),this._cache={data:[],labels:[],all:[]}}determineDataLimits(){const t=this.options,e=this._adapter,i=t.time.unit||"day";let{min:s,max:n,minDefined:o,maxDefined:a}=this.getUserBounds();function r(t){o||isNaN(t.min)||(s=Math.min(s,t.min)),a||isNaN(t.max)||(n=Math.max(n,t.max))}o&&a||(r(this._getLabelBounds()),"ticks"===t.bounds&&"labels"===t.ticks.source||r(this.getMinMax(!1))),s=X(s)&&!isNaN(s)?s:+e.startOf(Date.now(),i),n=X(n)&&!isNaN(n)?n:+e.endOf(Date.now(),i)+1,this.min=Math.min(s,n-1),this.max=Math.max(s+1,n)}_getLabelBounds(){const t=this.getLabelTimestamps();let e=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY;return t.length&&(e=t[0],i=t[t.length-1]),{min:e,max:i}}buildTicks(){const t=this.options,e=t.time,i=t.ticks,s="labels"===i.source?this.getLabelTimestamps():this._generate();"ticks"===t.bounds&&s.length&&(this.min=this._userMin||s[0],this.max=this._userMax||s[s.length-1]);const n=this.min,o=re(s,n,this.max);return this._unit=e.unit||(i.autoSkip?la(e.minUnit,this.min,this.max,this._getLabelCapacity(n)):function(t,e,i,s,n){for(let o=oa.length-1;o>=oa.indexOf(i);o--){const i=oa[o];if(na[i].common&&t._adapter.diff(n,s,i)>=e-1)return i}return oa[i?oa.indexOf(i):0]}(this,o.length,e.minUnit,this.min,this.max)),this._majorUnit=i.major.enabled&&"year"!==this._unit?function(t){for(let e=oa.indexOf(t)+1,i=oa.length;e<i;++e)if(na[oa[e]].common)return oa[e]}(this._unit):void 0,this.initOffsets(s),t.reverse&&o.reverse(),ca(this,o,this._majorUnit)}initOffsets(t){let e,i,s=0,n=0;this.options.offset&&t.length&&(e=this.getDecimalForValue(t[0]),s=1===t.length?1-e:(this.getDecimalForValue(t[1])-e)/2,i=this.getDecimalForValue(t[t.length-1]),n=1===t.length?i:(i-this.getDecimalForValue(t[t.length-2]))/2);const o=t.length<3?.5:.25;s=Ht(s,0,o),n=Ht(n,0,o),this._offsets={start:s,end:n,factor:1/(s+1+n)}}_generate(){const t=this._adapter,e=this.min,i=this.max,s=this.options,n=s.time,o=n.unit||la(n.minUnit,e,i,this._getLabelCapacity(e)),a=K(n.stepSize,1),r="week"===o&&n.isoWeekday,l=At(r)||!0===r,h={};let c,d,u=e;if(l&&(u=+t.startOf(u,"isoWeek",r)),u=+t.startOf(u,l?"day":o),t.diff(i,e,o)>1e5*a)throw new Error(e+" and "+i+" are too far apart with stepSize of "+a+" "+o);const f="data"===s.ticks.source&&this.getDataTimestamps();for(c=u,d=0;c<i;c=+t.add(c,a,o),d++)ha(h,c,f);return c!==i&&"ticks"!==s.bounds&&1!==d||ha(h,c,f),Object.keys(h).sort(((t,e)=>t-e)).map((t=>+t))}getLabelForValue(t){const e=this._adapter,i=this.options.time;return i.tooltipFormat?e.format(t,i.tooltipFormat):e.format(t,i.displayFormats.datetime)}_tickFormatFunction(t,e,i,s){const n=this.options,o=n.time.displayFormats,a=this._unit,r=this._majorUnit,l=a&&o[a],h=r&&o[r],c=i[e],d=r&&h&&c&&c.major,u=this._adapter.format(t,s||(d?h:l)),f=n.ticks.callback;return f?Q(f,[u,e,i],this):u}generateTickLabels(t){let e,i,s;for(e=0,i=t.length;e<i;++e)s=t[e],s.label=this._tickFormatFunction(s.value,e,t)}getDecimalForValue(t){return null===t?NaN:(t-this.min)/(this.max-this.min)}getPixelForValue(t){const e=this._offsets,i=this.getDecimalForValue(t);return this.getPixelForDecimal((e.start+i)*e.factor)}getValueForPixel(t){const e=this._offsets,i=this.getDecimalForPixel(t)/e.factor-e.end;return this.min+i*(this.max-this.min)}_getLabelSize(t){const e=this.options.ticks,i=this.ctx.measureText(t).width,s=Et(this.isHorizontal()?e.maxRotation:e.minRotation),n=Math.cos(s),o=Math.sin(s),a=this._resolveTickFontOptions(0).size;return{w:i*n+a*o,h:i*o+a*n}}_getLabelCapacity(t){const e=this.options.time,i=e.displayFormats,s=i[e.unit]||i.millisecond,n=this._tickFormatFunction(t,0,ca(this,[t],this._majorUnit),s),o=this._getLabelSize(n),a=Math.floor(this.isHorizontal()?this.width/o.w:this.height/o.h)-1;return a>0?a:1}getDataTimestamps(){let t,e,i=this._cache.data||[];if(i.length)return i;const s=this.getMatchingVisibleMetas();if(this._normalized&&s.length)return this._cache.data=s[0].controller.getAllParsedValues(this);for(t=0,e=s.length;t<e;++t)i=i.concat(s[t].controller.getAllParsedValues(this));return this._cache.data=this.normalize(i)}getLabelTimestamps(){const t=this._cache.labels||[];let e,i;if(t.length)return t;const s=this.getLabels();for(e=0,i=s.length;e<i;++e)t.push(ra(this,s[e]));return this._cache.labels=this._normalized?t:this.normalize(t)}normalize(t){return de(t.sort(aa))}}function ua(t,e,i){let s,n,o,a,r=0,l=t.length-1;i?(e>=t[r].pos&&e<=t[l].pos&&({lo:r,hi:l}=oe(t,"pos",e)),({pos:s,time:o}=t[r]),({pos:n,time:a}=t[l])):(e>=t[r].time&&e<=t[l].time&&({lo:r,hi:l}=oe(t,"time",e)),({time:s,pos:o}=t[r]),({time:n,pos:a}=t[l]));const h=n-s;return h?o+(a-o)*(e-s)/h:o}da.id="time",da.defaults={bounds:"data",adapters:{},time:{parser:!1,unit:!1,round:!1,isoWeekday:!1,minUnit:"millisecond",displayFormats:{}},ticks:{source:"auto",major:{enabled:!1}}};class fa extends da{constructor(t){super(t),this._table=[],this._minPos=void 0,this._tableRange=void 0}initOffsets(){const t=this._getTimestampsForTable(),e=this._table=this.buildLookupTable(t);this._minPos=ua(e,this.min),this._tableRange=ua(e,this.max)-this._minPos,super.initOffsets(t)}buildLookupTable(t){const{min:e,max:i}=this,s=[],n=[];let o,a,r,l,h;for(o=0,a=t.length;o<a;++o)l=t[o],l>=e&&l<=i&&s.push(l);if(s.length<2)return[{time:e,pos:0},{time:i,pos:1}];for(o=0,a=s.length;o<a;++o)h=s[o+1],r=s[o-1],l=s[o],Math.round((h+r)/2)!==l&&n.push({time:l,pos:o/(a-1)});return n}_getTimestampsForTable(){let t=this._cache.all||[];if(t.length)return t;const e=this.getDataTimestamps(),i=this.getLabelTimestamps();return t=e.length&&i.length?this.normalize(e.concat(i)):e.length?e:i,t=this._cache.all=t,t}getDecimalForValue(t){return(ua(this._table,t)-this._minPos)/this._tableRange}getValueForPixel(t){const e=this._offsets,i=this.getDecimalForPixel(t)/e.factor-e.end;return ua(this._table,i*this._tableRange+this._minPos,!0)}}fa.id="timeseries",fa.defaults=da.defaults;var ga=Object.freeze({__proto__:null,CategoryScale:jo,LinearScale:Uo,LogarithmicScale:qo,RadialLinearScale:sa,TimeScale:da,TimeSeriesScale:fa});return an.register(Cn,ga,Jn,No),an.helpers={...Hi},an._adapters=dn,an.Animation=ls,an.Animations=cs,an.animator=a,an.controllers=zs.controllers.items,an.DatasetController=ws,an.Element=Ms,an.elements=Jn,an.Interaction=Te,an.layouts=ei,an.platforms=os,an.Scale=Es,an.Ticks=Ss,Object.assign(an,Cn,ga,Jn,No,os),an.Chart=an,"undefined"!=typeof window&&(window.Chart=an),an}));
diff --git a/static/chartjs-adapter-moment.js b/static/chartjs-adapter-moment.js
@@ -0,0 +1,72 @@
+/*!
+ * chartjs-adapter-moment v1.0.0
+ * https://www.chartjs.org
+ * (c) 2021 chartjs-adapter-moment Contributors
+ * Released under the MIT license
+ */
+(function (global, factory) {
+typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('moment'), require('chart.js')) :
+typeof define === 'function' && define.amd ? define(['moment', 'chart.js'], factory) :
+(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.moment, global.Chart));
+}(this, (function (moment, chart_js) { 'use strict';
+
+function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
+
+var moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);
+
+const FORMATS = {
+ datetime: 'MMM D, YYYY, h:mm:ss a',
+ millisecond: 'h:mm:ss.SSS a',
+ second: 'h:mm:ss a',
+ minute: 'h:mm a',
+ hour: 'hA',
+ day: 'MMM D',
+ week: 'll',
+ month: 'MMM YYYY',
+ quarter: '[Q]Q - YYYY',
+ year: 'YYYY'
+};
+
+chart_js._adapters._date.override(typeof moment__default['default'] === 'function' ? {
+ _id: 'moment', // DEBUG ONLY
+
+ formats: function() {
+ return FORMATS;
+ },
+
+ parse: function(value, format) {
+ if (typeof value === 'string' && typeof format === 'string') {
+ value = moment__default['default'](value, format);
+ } else if (!(value instanceof moment__default['default'])) {
+ value = moment__default['default'](value);
+ }
+ return value.isValid() ? value.valueOf() : null;
+ },
+
+ format: function(time, format) {
+ return moment__default['default'](time).format(format);
+ },
+
+ add: function(time, amount, unit) {
+ return moment__default['default'](time).add(amount, unit).valueOf();
+ },
+
+ diff: function(max, min, unit) {
+ return moment__default['default'](max).diff(moment__default['default'](min), unit);
+ },
+
+ startOf: function(time, unit, weekday) {
+ time = moment__default['default'](time);
+ if (unit === 'isoWeek') {
+ weekday = Math.trunc(Math.min(Math.max(0, weekday), 6));
+ return time.isoWeekday(weekday).startOf('day').valueOf();
+ }
+ return time.startOf(unit).valueOf();
+ },
+
+ endOf: function(time, unit) {
+ return moment__default['default'](time).endOf(unit).valueOf();
+ }
+} : {});
+
+})));
diff --git a/static/chartjs-adapter-moment.min.js b/static/chartjs-adapter-moment.min.js
@@ -0,0 +1,8 @@
+/*!
+ * chartjs-adapter-moment v1.0.0
+ * https://www.chartjs.org
+ * (c) 2021 chartjs-adapter-moment Contributors
+ * Released under the MIT license
+ */
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(require("moment"),require("chart.js")):"function"==typeof define&&define.amd?define(["moment","chart.js"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).moment,e.Chart)}(this,(function(e,t){"use strict";function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var f=n(e);const a={datetime:"MMM D, YYYY, h:mm:ss a",millisecond:"h:mm:ss.SSS a",second:"h:mm:ss a",minute:"h:mm a",hour:"hA",day:"MMM D",week:"ll",month:"MMM YYYY",quarter:"[Q]Q - YYYY",year:"YYYY"};t._adapters._date.override("function"==typeof f.default?{_id:"moment",formats:function(){return a},parse:function(e,t){return"string"==typeof e&&"string"==typeof t?e=f.default(e,t):e instanceof f.default||(e=f.default(e)),e.isValid()?e.valueOf():null},format:function(e,t){return f.default(e).format(t)},add:function(e,t,n){return f.default(e).add(t,n).valueOf()},diff:function(e,t,n){return f.default(e).diff(f.default(t),n)},startOf:function(e,t,n){return e=f.default(e),"isoWeek"===t?(n=Math.trunc(Math.min(Math.max(0,n),6)),e.isoWeekday(n).startOf("day").valueOf()):e.startOf(t).valueOf()},endOf:function(e,t){return f.default(e).endOf(t).valueOf()}}:{})}));
+//# sourceMappingURL=chartjs-adapter-moment.min.js.map
diff --git a/static/dashboard.html b/static/dashboard.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html lang="en">
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<title>Sensor Data</title>
+</head>
+
+<body>
+<canvas id="chart-temperature"></canvas>
+<canvas id="chart-humidity"></canvas>
+<canvas id="chart-pressure"></canvas>
+</body>
+
+<!-- Load chart scripts -->
+<script src="/static/chart.min.js"></script>
+<script src="/static/moment.min.js"></script>
+<script src="/static/chartjs-adapter-moment.js"></script>
+<script src="/static/tempestas.js"></script>
+</html>
diff --git a/static/moment.js b/static/moment.js
@@ -0,0 +1,5670 @@
+//! moment.js
+//! version : 2.29.1
+//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
+//! license : MIT
+//! momentjs.com
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ global.moment = factory()
+}(this, (function () { 'use strict';
+
+ var hookCallback;
+
+ function hooks() {
+ return hookCallback.apply(null, arguments);
+ }
+
+ // This is done to register the method called with moment()
+ // without creating circular dependencies.
+ function setHookCallback(callback) {
+ hookCallback = callback;
+ }
+
+ function isArray(input) {
+ return (
+ input instanceof Array ||
+ Object.prototype.toString.call(input) === '[object Array]'
+ );
+ }
+
+ function isObject(input) {
+ // IE8 will treat undefined and null as object if it wasn't for
+ // input != null
+ return (
+ input != null &&
+ Object.prototype.toString.call(input) === '[object Object]'
+ );
+ }
+
+ function hasOwnProp(a, b) {
+ return Object.prototype.hasOwnProperty.call(a, b);
+ }
+
+ function isObjectEmpty(obj) {
+ if (Object.getOwnPropertyNames) {
+ return Object.getOwnPropertyNames(obj).length === 0;
+ } else {
+ var k;
+ for (k in obj) {
+ if (hasOwnProp(obj, k)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ function isUndefined(input) {
+ return input === void 0;
+ }
+
+ function isNumber(input) {
+ return (
+ typeof input === 'number' ||
+ Object.prototype.toString.call(input) === '[object Number]'
+ );
+ }
+
+ function isDate(input) {
+ return (
+ input instanceof Date ||
+ Object.prototype.toString.call(input) === '[object Date]'
+ );
+ }
+
+ function map(arr, fn) {
+ var res = [],
+ i;
+ for (i = 0; i < arr.length; ++i) {
+ res.push(fn(arr[i], i));
+ }
+ return res;
+ }
+
+ function extend(a, b) {
+ for (var i in b) {
+ if (hasOwnProp(b, i)) {
+ a[i] = b[i];
+ }
+ }
+
+ if (hasOwnProp(b, 'toString')) {
+ a.toString = b.toString;
+ }
+
+ if (hasOwnProp(b, 'valueOf')) {
+ a.valueOf = b.valueOf;
+ }
+
+ return a;
+ }
+
+ function createUTC(input, format, locale, strict) {
+ return createLocalOrUTC(input, format, locale, strict, true).utc();
+ }
+
+ function defaultParsingFlags() {
+ // We need to deep clone this object.
+ return {
+ empty: false,
+ unusedTokens: [],
+ unusedInput: [],
+ overflow: -2,
+ charsLeftOver: 0,
+ nullInput: false,
+ invalidEra: null,
+ invalidMonth: null,
+ invalidFormat: false,
+ userInvalidated: false,
+ iso: false,
+ parsedDateParts: [],
+ era: null,
+ meridiem: null,
+ rfc2822: false,
+ weekdayMismatch: false,
+ };
+ }
+
+ function getParsingFlags(m) {
+ if (m._pf == null) {
+ m._pf = defaultParsingFlags();
+ }
+ return m._pf;
+ }
+
+ var some;
+ if (Array.prototype.some) {
+ some = Array.prototype.some;
+ } else {
+ some = function (fun) {
+ var t = Object(this),
+ len = t.length >>> 0,
+ i;
+
+ for (i = 0; i < len; i++) {
+ if (i in t && fun.call(this, t[i], i, t)) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+ }
+
+ function isValid(m) {
+ if (m._isValid == null) {
+ var flags = getParsingFlags(m),
+ parsedParts = some.call(flags.parsedDateParts, function (i) {
+ return i != null;
+ }),
+ isNowValid =
+ !isNaN(m._d.getTime()) &&
+ flags.overflow < 0 &&
+ !flags.empty &&
+ !flags.invalidEra &&
+ !flags.invalidMonth &&
+ !flags.invalidWeekday &&
+ !flags.weekdayMismatch &&
+ !flags.nullInput &&
+ !flags.invalidFormat &&
+ !flags.userInvalidated &&
+ (!flags.meridiem || (flags.meridiem && parsedParts));
+
+ if (m._strict) {
+ isNowValid =
+ isNowValid &&
+ flags.charsLeftOver === 0 &&
+ flags.unusedTokens.length === 0 &&
+ flags.bigHour === undefined;
+ }
+
+ if (Object.isFrozen == null || !Object.isFrozen(m)) {
+ m._isValid = isNowValid;
+ } else {
+ return isNowValid;
+ }
+ }
+ return m._isValid;
+ }
+
+ function createInvalid(flags) {
+ var m = createUTC(NaN);
+ if (flags != null) {
+ extend(getParsingFlags(m), flags);
+ } else {
+ getParsingFlags(m).userInvalidated = true;
+ }
+
+ return m;
+ }
+
+ // Plugins that add properties should also add the key here (null value),
+ // so we can properly clone ourselves.
+ var momentProperties = (hooks.momentProperties = []),
+ updateInProgress = false;
+
+ function copyConfig(to, from) {
+ var i, prop, val;
+
+ if (!isUndefined(from._isAMomentObject)) {
+ to._isAMomentObject = from._isAMomentObject;
+ }
+ if (!isUndefined(from._i)) {
+ to._i = from._i;
+ }
+ if (!isUndefined(from._f)) {
+ to._f = from._f;
+ }
+ if (!isUndefined(from._l)) {
+ to._l = from._l;
+ }
+ if (!isUndefined(from._strict)) {
+ to._strict = from._strict;
+ }
+ if (!isUndefined(from._tzm)) {
+ to._tzm = from._tzm;
+ }
+ if (!isUndefined(from._isUTC)) {
+ to._isUTC = from._isUTC;
+ }
+ if (!isUndefined(from._offset)) {
+ to._offset = from._offset;
+ }
+ if (!isUndefined(from._pf)) {
+ to._pf = getParsingFlags(from);
+ }
+ if (!isUndefined(from._locale)) {
+ to._locale = from._locale;
+ }
+
+ if (momentProperties.length > 0) {
+ for (i = 0; i < momentProperties.length; i++) {
+ prop = momentProperties[i];
+ val = from[prop];
+ if (!isUndefined(val)) {
+ to[prop] = val;
+ }
+ }
+ }
+
+ return to;
+ }
+
+ // Moment prototype object
+ function Moment(config) {
+ copyConfig(this, config);
+ this._d = new Date(config._d != null ? config._d.getTime() : NaN);
+ if (!this.isValid()) {
+ this._d = new Date(NaN);
+ }
+ // Prevent infinite loop in case updateOffset creates new moment
+ // objects.
+ if (updateInProgress === false) {
+ updateInProgress = true;
+ hooks.updateOffset(this);
+ updateInProgress = false;
+ }
+ }
+
+ function isMoment(obj) {
+ return (
+ obj instanceof Moment || (obj != null && obj._isAMomentObject != null)
+ );
+ }
+
+ function warn(msg) {
+ if (
+ hooks.suppressDeprecationWarnings === false &&
+ typeof console !== 'undefined' &&
+ console.warn
+ ) {
+ console.warn('Deprecation warning: ' + msg);
+ }
+ }
+
+ function deprecate(msg, fn) {
+ var firstTime = true;
+
+ return extend(function () {
+ if (hooks.deprecationHandler != null) {
+ hooks.deprecationHandler(null, msg);
+ }
+ if (firstTime) {
+ var args = [],
+ arg,
+ i,
+ key;
+ for (i = 0; i < arguments.length; i++) {
+ arg = '';
+ if (typeof arguments[i] === 'object') {
+ arg += '\n[' + i + '] ';
+ for (key in arguments[0]) {
+ if (hasOwnProp(arguments[0], key)) {
+ arg += key + ': ' + arguments[0][key] + ', ';
+ }
+ }
+ arg = arg.slice(0, -2); // Remove trailing comma and space
+ } else {
+ arg = arguments[i];
+ }
+ args.push(arg);
+ }
+ warn(
+ msg +
+ '\nArguments: ' +
+ Array.prototype.slice.call(args).join('') +
+ '\n' +
+ new Error().stack
+ );
+ firstTime = false;
+ }
+ return fn.apply(this, arguments);
+ }, fn);
+ }
+
+ var deprecations = {};
+
+ function deprecateSimple(name, msg) {
+ if (hooks.deprecationHandler != null) {
+ hooks.deprecationHandler(name, msg);
+ }
+ if (!deprecations[name]) {
+ warn(msg);
+ deprecations[name] = true;
+ }
+ }
+
+ hooks.suppressDeprecationWarnings = false;
+ hooks.deprecationHandler = null;
+
+ function isFunction(input) {
+ return (
+ (typeof Function !== 'undefined' && input instanceof Function) ||
+ Object.prototype.toString.call(input) === '[object Function]'
+ );
+ }
+
+ function set(config) {
+ var prop, i;
+ for (i in config) {
+ if (hasOwnProp(config, i)) {
+ prop = config[i];
+ if (isFunction(prop)) {
+ this[i] = prop;
+ } else {
+ this['_' + i] = prop;
+ }
+ }
+ }
+ this._config = config;
+ // Lenient ordinal parsing accepts just a number in addition to
+ // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
+ // TODO: Remove "ordinalParse" fallback in next major release.
+ this._dayOfMonthOrdinalParseLenient = new RegExp(
+ (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
+ '|' +
+ /\d{1,2}/.source
+ );
+ }
+
+ function mergeConfigs(parentConfig, childConfig) {
+ var res = extend({}, parentConfig),
+ prop;
+ for (prop in childConfig) {
+ if (hasOwnProp(childConfig, prop)) {
+ if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
+ res[prop] = {};
+ extend(res[prop], parentConfig[prop]);
+ extend(res[prop], childConfig[prop]);
+ } else if (childConfig[prop] != null) {
+ res[prop] = childConfig[prop];
+ } else {
+ delete res[prop];
+ }
+ }
+ }
+ for (prop in parentConfig) {
+ if (
+ hasOwnProp(parentConfig, prop) &&
+ !hasOwnProp(childConfig, prop) &&
+ isObject(parentConfig[prop])
+ ) {
+ // make sure changes to properties don't modify parent config
+ res[prop] = extend({}, res[prop]);
+ }
+ }
+ return res;
+ }
+
+ function Locale(config) {
+ if (config != null) {
+ this.set(config);
+ }
+ }
+
+ var keys;
+
+ if (Object.keys) {
+ keys = Object.keys;
+ } else {
+ keys = function (obj) {
+ var i,
+ res = [];
+ for (i in obj) {
+ if (hasOwnProp(obj, i)) {
+ res.push(i);
+ }
+ }
+ return res;
+ };
+ }
+
+ var defaultCalendar = {
+ sameDay: '[Today at] LT',
+ nextDay: '[Tomorrow at] LT',
+ nextWeek: 'dddd [at] LT',
+ lastDay: '[Yesterday at] LT',
+ lastWeek: '[Last] dddd [at] LT',
+ sameElse: 'L',
+ };
+
+ function calendar(key, mom, now) {
+ var output = this._calendar[key] || this._calendar['sameElse'];
+ return isFunction(output) ? output.call(mom, now) : output;
+ }
+
+ function zeroFill(number, targetLength, forceSign) {
+ var absNumber = '' + Math.abs(number),
+ zerosToFill = targetLength - absNumber.length,
+ sign = number >= 0;
+ return (
+ (sign ? (forceSign ? '+' : '') : '-') +
+ Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) +
+ absNumber
+ );
+ }
+
+ var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,
+ localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
+ formatFunctions = {},
+ formatTokenFunctions = {};
+
+ // token: 'M'
+ // padded: ['MM', 2]
+ // ordinal: 'Mo'
+ // callback: function () { this.month() + 1 }
+ function addFormatToken(token, padded, ordinal, callback) {
+ var func = callback;
+ if (typeof callback === 'string') {
+ func = function () {
+ return this[callback]();
+ };
+ }
+ if (token) {
+ formatTokenFunctions[token] = func;
+ }
+ if (padded) {
+ formatTokenFunctions[padded[0]] = function () {
+ return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
+ };
+ }
+ if (ordinal) {
+ formatTokenFunctions[ordinal] = function () {
+ return this.localeData().ordinal(
+ func.apply(this, arguments),
+ token
+ );
+ };
+ }
+ }
+
+ function removeFormattingTokens(input) {
+ if (input.match(/\[[\s\S]/)) {
+ return input.replace(/^\[|\]$/g, '');
+ }
+ return input.replace(/\\/g, '');
+ }
+
+ function makeFormatFunction(format) {
+ var array = format.match(formattingTokens),
+ i,
+ length;
+
+ for (i = 0, length = array.length; i < length; i++) {
+ if (formatTokenFunctions[array[i]]) {
+ array[i] = formatTokenFunctions[array[i]];
+ } else {
+ array[i] = removeFormattingTokens(array[i]);
+ }
+ }
+
+ return function (mom) {
+ var output = '',
+ i;
+ for (i = 0; i < length; i++) {
+ output += isFunction(array[i])
+ ? array[i].call(mom, format)
+ : array[i];
+ }
+ return output;
+ };
+ }
+
+ // format date using native date object
+ function formatMoment(m, format) {
+ if (!m.isValid()) {
+ return m.localeData().invalidDate();
+ }
+
+ format = expandFormat(format, m.localeData());
+ formatFunctions[format] =
+ formatFunctions[format] || makeFormatFunction(format);
+
+ return formatFunctions[format](m);
+ }
+
+ function expandFormat(format, locale) {
+ var i = 5;
+
+ function replaceLongDateFormatTokens(input) {
+ return locale.longDateFormat(input) || input;
+ }
+
+ localFormattingTokens.lastIndex = 0;
+ while (i >= 0 && localFormattingTokens.test(format)) {
+ format = format.replace(
+ localFormattingTokens,
+ replaceLongDateFormatTokens
+ );
+ localFormattingTokens.lastIndex = 0;
+ i -= 1;
+ }
+
+ return format;
+ }
+
+ var defaultLongDateFormat = {
+ 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',
+ };
+
+ function longDateFormat(key) {
+ var format = this._longDateFormat[key],
+ formatUpper = this._longDateFormat[key.toUpperCase()];
+
+ if (format || !formatUpper) {
+ return format;
+ }
+
+ this._longDateFormat[key] = formatUpper
+ .match(formattingTokens)
+ .map(function (tok) {
+ if (
+ tok === 'MMMM' ||
+ tok === 'MM' ||
+ tok === 'DD' ||
+ tok === 'dddd'
+ ) {
+ return tok.slice(1);
+ }
+ return tok;
+ })
+ .join('');
+
+ return this._longDateFormat[key];
+ }
+
+ var defaultInvalidDate = 'Invalid date';
+
+ function invalidDate() {
+ return this._invalidDate;
+ }
+
+ var defaultOrdinal = '%d',
+ defaultDayOfMonthOrdinalParse = /\d{1,2}/;
+
+ function ordinal(number) {
+ return this._ordinal.replace('%d', number);
+ }
+
+ var defaultRelativeTime = {
+ future: 'in %s',
+ past: '%s ago',
+ s: 'a few seconds',
+ ss: '%d seconds',
+ m: 'a minute',
+ mm: '%d minutes',
+ h: 'an hour',
+ hh: '%d hours',
+ d: 'a day',
+ dd: '%d days',
+ w: 'a week',
+ ww: '%d weeks',
+ M: 'a month',
+ MM: '%d months',
+ y: 'a year',
+ yy: '%d years',
+ };
+
+ function relativeTime(number, withoutSuffix, string, isFuture) {
+ var output = this._relativeTime[string];
+ return isFunction(output)
+ ? output(number, withoutSuffix, string, isFuture)
+ : output.replace(/%d/i, number);
+ }
+
+ function pastFuture(diff, output) {
+ var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
+ return isFunction(format) ? format(output) : format.replace(/%s/i, output);
+ }
+
+ var aliases = {};
+
+ function addUnitAlias(unit, shorthand) {
+ var lowerCase = unit.toLowerCase();
+ aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
+ }
+
+ function normalizeUnits(units) {
+ return typeof units === 'string'
+ ? aliases[units] || aliases[units.toLowerCase()]
+ : undefined;
+ }
+
+ function normalizeObjectUnits(inputObject) {
+ var normalizedInput = {},
+ normalizedProp,
+ prop;
+
+ for (prop in inputObject) {
+ if (hasOwnProp(inputObject, prop)) {
+ normalizedProp = normalizeUnits(prop);
+ if (normalizedProp) {
+ normalizedInput[normalizedProp] = inputObject[prop];
+ }
+ }
+ }
+
+ return normalizedInput;
+ }
+
+ var priorities = {};
+
+ function addUnitPriority(unit, priority) {
+ priorities[unit] = priority;
+ }
+
+ function getPrioritizedUnits(unitsObj) {
+ var units = [],
+ u;
+ for (u in unitsObj) {
+ if (hasOwnProp(unitsObj, u)) {
+ units.push({ unit: u, priority: priorities[u] });
+ }
+ }
+ units.sort(function (a, b) {
+ return a.priority - b.priority;
+ });
+ return units;
+ }
+
+ function isLeapYear(year) {
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+ }
+
+ function absFloor(number) {
+ if (number < 0) {
+ // -0 -> 0
+ return Math.ceil(number) || 0;
+ } else {
+ return Math.floor(number);
+ }
+ }
+
+ function toInt(argumentForCoercion) {
+ var coercedNumber = +argumentForCoercion,
+ value = 0;
+
+ if (coercedNumber !== 0 && isFinite(coercedNumber)) {
+ value = absFloor(coercedNumber);
+ }
+
+ return value;
+ }
+
+ function makeGetSet(unit, keepTime) {
+ return function (value) {
+ if (value != null) {
+ set$1(this, unit, value);
+ hooks.updateOffset(this, keepTime);
+ return this;
+ } else {
+ return get(this, unit);
+ }
+ };
+ }
+
+ function get(mom, unit) {
+ return mom.isValid()
+ ? mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]()
+ : NaN;
+ }
+
+ function set$1(mom, unit, value) {
+ if (mom.isValid() && !isNaN(value)) {
+ if (
+ unit === 'FullYear' &&
+ isLeapYear(mom.year()) &&
+ mom.month() === 1 &&
+ mom.date() === 29
+ ) {
+ value = toInt(value);
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](
+ value,
+ mom.month(),
+ daysInMonth(value, mom.month())
+ );
+ } else {
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
+ }
+ }
+ }
+
+ // MOMENTS
+
+ function stringGet(units) {
+ units = normalizeUnits(units);
+ if (isFunction(this[units])) {
+ return this[units]();
+ }
+ return this;
+ }
+
+ function stringSet(units, value) {
+ if (typeof units === 'object') {
+ units = normalizeObjectUnits(units);
+ var prioritized = getPrioritizedUnits(units),
+ i;
+ for (i = 0; i < prioritized.length; i++) {
+ this[prioritized[i].unit](units[prioritized[i].unit]);
+ }
+ } else {
+ units = normalizeUnits(units);
+ if (isFunction(this[units])) {
+ return this[units](value);
+ }
+ }
+ return this;
+ }
+
+ var match1 = /\d/, // 0 - 9
+ match2 = /\d\d/, // 00 - 99
+ match3 = /\d{3}/, // 000 - 999
+ match4 = /\d{4}/, // 0000 - 9999
+ match6 = /[+-]?\d{6}/, // -999999 - 999999
+ match1to2 = /\d\d?/, // 0 - 99
+ match3to4 = /\d\d\d\d?/, // 999 - 9999
+ match5to6 = /\d\d\d\d\d\d?/, // 99999 - 999999
+ match1to3 = /\d{1,3}/, // 0 - 999
+ match1to4 = /\d{1,4}/, // 0 - 9999
+ match1to6 = /[+-]?\d{1,6}/, // -999999 - 999999
+ matchUnsigned = /\d+/, // 0 - inf
+ matchSigned = /[+-]?\d+/, // -inf - inf
+ matchOffset = /Z|[+-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
+ matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi, // +00 -00 +00:00 -00:00 +0000 -0000 or Z
+ matchTimestamp = /[+-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
+ // any word (or two) characters or numbers including two/three word month in arabic.
+ // includes scottish gaelic two word and hyphenated months
+ matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i,
+ regexes;
+
+ regexes = {};
+
+ function addRegexToken(token, regex, strictRegex) {
+ regexes[token] = isFunction(regex)
+ ? regex
+ : function (isStrict, localeData) {
+ return isStrict && strictRegex ? strictRegex : regex;
+ };
+ }
+
+ function getParseRegexForToken(token, config) {
+ if (!hasOwnProp(regexes, token)) {
+ return new RegExp(unescapeFormat(token));
+ }
+
+ return regexes[token](config._strict, config._locale);
+ }
+
+ // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+ function unescapeFormat(s) {
+ return regexEscape(
+ s
+ .replace('\\', '')
+ .replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (
+ matched,
+ p1,
+ p2,
+ p3,
+ p4
+ ) {
+ return p1 || p2 || p3 || p4;
+ })
+ );
+ }
+
+ function regexEscape(s) {
+ return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+ }
+
+ var tokens = {};
+
+ function addParseToken(token, callback) {
+ var i,
+ func = callback;
+ if (typeof token === 'string') {
+ token = [token];
+ }
+ if (isNumber(callback)) {
+ func = function (input, array) {
+ array[callback] = toInt(input);
+ };
+ }
+ for (i = 0; i < token.length; i++) {
+ tokens[token[i]] = func;
+ }
+ }
+
+ function addWeekParseToken(token, callback) {
+ addParseToken(token, function (input, array, config, token) {
+ config._w = config._w || {};
+ callback(input, config._w, config, token);
+ });
+ }
+
+ function addTimeToArrayFromToken(token, input, config) {
+ if (input != null && hasOwnProp(tokens, token)) {
+ tokens[token](input, config._a, config, token);
+ }
+ }
+
+ var YEAR = 0,
+ MONTH = 1,
+ DATE = 2,
+ HOUR = 3,
+ MINUTE = 4,
+ SECOND = 5,
+ MILLISECOND = 6,
+ WEEK = 7,
+ WEEKDAY = 8;
+
+ function mod(n, x) {
+ return ((n % x) + x) % x;
+ }
+
+ var indexOf;
+
+ if (Array.prototype.indexOf) {
+ indexOf = Array.prototype.indexOf;
+ } else {
+ indexOf = function (o) {
+ // I know
+ var i;
+ for (i = 0; i < this.length; ++i) {
+ if (this[i] === o) {
+ return i;
+ }
+ }
+ return -1;
+ };
+ }
+
+ function daysInMonth(year, month) {
+ if (isNaN(year) || isNaN(month)) {
+ return NaN;
+ }
+ var modMonth = mod(month, 12);
+ year += (month - modMonth) / 12;
+ return modMonth === 1
+ ? isLeapYear(year)
+ ? 29
+ : 28
+ : 31 - ((modMonth % 7) % 2);
+ }
+
+ // FORMATTING
+
+ addFormatToken('M', ['MM', 2], 'Mo', function () {
+ return this.month() + 1;
+ });
+
+ addFormatToken('MMM', 0, 0, function (format) {
+ return this.localeData().monthsShort(this, format);
+ });
+
+ addFormatToken('MMMM', 0, 0, function (format) {
+ return this.localeData().months(this, format);
+ });
+
+ // ALIASES
+
+ addUnitAlias('month', 'M');
+
+ // PRIORITY
+
+ addUnitPriority('month', 8);
+
+ // PARSING
+
+ addRegexToken('M', match1to2);
+ addRegexToken('MM', match1to2, match2);
+ addRegexToken('MMM', function (isStrict, locale) {
+ return locale.monthsShortRegex(isStrict);
+ });
+ addRegexToken('MMMM', function (isStrict, locale) {
+ return locale.monthsRegex(isStrict);
+ });
+
+ addParseToken(['M', 'MM'], function (input, array) {
+ array[MONTH] = toInt(input) - 1;
+ });
+
+ addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
+ var month = config._locale.monthsParse(input, token, config._strict);
+ // if we didn't find a month name, mark the date as invalid.
+ if (month != null) {
+ array[MONTH] = month;
+ } else {
+ getParsingFlags(config).invalidMonth = input;
+ }
+ });
+
+ // LOCALES
+
+ var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
+ '_'
+ ),
+ defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split(
+ '_'
+ ),
+ MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,
+ defaultMonthsShortRegex = matchWord,
+ defaultMonthsRegex = matchWord;
+
+ function localeMonths(m, format) {
+ if (!m) {
+ return isArray(this._months)
+ ? this._months
+ : this._months['standalone'];
+ }
+ return isArray(this._months)
+ ? this._months[m.month()]
+ : this._months[
+ (this._months.isFormat || MONTHS_IN_FORMAT).test(format)
+ ? 'format'
+ : 'standalone'
+ ][m.month()];
+ }
+
+ function localeMonthsShort(m, format) {
+ if (!m) {
+ return isArray(this._monthsShort)
+ ? this._monthsShort
+ : this._monthsShort['standalone'];
+ }
+ return isArray(this._monthsShort)
+ ? this._monthsShort[m.month()]
+ : this._monthsShort[
+ MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'
+ ][m.month()];
+ }
+
+ function handleStrictParse(monthName, format, strict) {
+ var i,
+ ii,
+ mom,
+ llc = monthName.toLocaleLowerCase();
+ if (!this._monthsParse) {
+ // this is not used
+ this._monthsParse = [];
+ this._longMonthsParse = [];
+ this._shortMonthsParse = [];
+ for (i = 0; i < 12; ++i) {
+ mom = createUTC([2000, i]);
+ this._shortMonthsParse[i] = this.monthsShort(
+ mom,
+ ''
+ ).toLocaleLowerCase();
+ this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
+ }
+ }
+
+ if (strict) {
+ if (format === 'MMM') {
+ ii = indexOf.call(this._shortMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._longMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ } else {
+ if (format === 'MMM') {
+ ii = indexOf.call(this._shortMonthsParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._longMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._longMonthsParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._shortMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ }
+ }
+
+ function localeMonthsParse(monthName, format, strict) {
+ var i, mom, regex;
+
+ if (this._monthsParseExact) {
+ return handleStrictParse.call(this, monthName, format, strict);
+ }
+
+ if (!this._monthsParse) {
+ this._monthsParse = [];
+ this._longMonthsParse = [];
+ this._shortMonthsParse = [];
+ }
+
+ // TODO: add sorting
+ // Sorting makes sure if one month (or abbr) is a prefix of another
+ // see sorting in computeMonthsParse
+ for (i = 0; i < 12; i++) {
+ // make the regex if we don't have it already
+ mom = createUTC([2000, i]);
+ if (strict && !this._longMonthsParse[i]) {
+ this._longMonthsParse[i] = new RegExp(
+ '^' + this.months(mom, '').replace('.', '') + '$',
+ 'i'
+ );
+ this._shortMonthsParse[i] = new RegExp(
+ '^' + this.monthsShort(mom, '').replace('.', '') + '$',
+ 'i'
+ );
+ }
+ if (!strict && !this._monthsParse[i]) {
+ regex =
+ '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
+ this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
+ }
+ // test the regex
+ if (
+ strict &&
+ format === 'MMMM' &&
+ this._longMonthsParse[i].test(monthName)
+ ) {
+ return i;
+ } else if (
+ strict &&
+ format === 'MMM' &&
+ this._shortMonthsParse[i].test(monthName)
+ ) {
+ return i;
+ } else if (!strict && this._monthsParse[i].test(monthName)) {
+ return i;
+ }
+ }
+ }
+
+ // MOMENTS
+
+ function setMonth(mom, value) {
+ var dayOfMonth;
+
+ if (!mom.isValid()) {
+ // No op
+ return mom;
+ }
+
+ if (typeof value === 'string') {
+ if (/^\d+$/.test(value)) {
+ value = toInt(value);
+ } else {
+ value = mom.localeData().monthsParse(value);
+ // TODO: Another silent failure?
+ if (!isNumber(value)) {
+ return mom;
+ }
+ }
+ }
+
+ dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
+ return mom;
+ }
+
+ function getSetMonth(value) {
+ if (value != null) {
+ setMonth(this, value);
+ hooks.updateOffset(this, true);
+ return this;
+ } else {
+ return get(this, 'Month');
+ }
+ }
+
+ function getDaysInMonth() {
+ return daysInMonth(this.year(), this.month());
+ }
+
+ function monthsShortRegex(isStrict) {
+ if (this._monthsParseExact) {
+ if (!hasOwnProp(this, '_monthsRegex')) {
+ computeMonthsParse.call(this);
+ }
+ if (isStrict) {
+ return this._monthsShortStrictRegex;
+ } else {
+ return this._monthsShortRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_monthsShortRegex')) {
+ this._monthsShortRegex = defaultMonthsShortRegex;
+ }
+ return this._monthsShortStrictRegex && isStrict
+ ? this._monthsShortStrictRegex
+ : this._monthsShortRegex;
+ }
+ }
+
+ function monthsRegex(isStrict) {
+ if (this._monthsParseExact) {
+ if (!hasOwnProp(this, '_monthsRegex')) {
+ computeMonthsParse.call(this);
+ }
+ if (isStrict) {
+ return this._monthsStrictRegex;
+ } else {
+ return this._monthsRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_monthsRegex')) {
+ this._monthsRegex = defaultMonthsRegex;
+ }
+ return this._monthsStrictRegex && isStrict
+ ? this._monthsStrictRegex
+ : this._monthsRegex;
+ }
+ }
+
+ function computeMonthsParse() {
+ function cmpLenRev(a, b) {
+ return b.length - a.length;
+ }
+
+ var shortPieces = [],
+ longPieces = [],
+ mixedPieces = [],
+ i,
+ mom;
+ for (i = 0; i < 12; i++) {
+ // make the regex if we don't have it already
+ mom = createUTC([2000, i]);
+ shortPieces.push(this.monthsShort(mom, ''));
+ longPieces.push(this.months(mom, ''));
+ mixedPieces.push(this.months(mom, ''));
+ mixedPieces.push(this.monthsShort(mom, ''));
+ }
+ // Sorting makes sure if one month (or abbr) is a prefix of another it
+ // will match the longer piece.
+ shortPieces.sort(cmpLenRev);
+ longPieces.sort(cmpLenRev);
+ mixedPieces.sort(cmpLenRev);
+ for (i = 0; i < 12; i++) {
+ shortPieces[i] = regexEscape(shortPieces[i]);
+ longPieces[i] = regexEscape(longPieces[i]);
+ }
+ for (i = 0; i < 24; i++) {
+ mixedPieces[i] = regexEscape(mixedPieces[i]);
+ }
+
+ this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
+ this._monthsShortRegex = this._monthsRegex;
+ this._monthsStrictRegex = new RegExp(
+ '^(' + longPieces.join('|') + ')',
+ 'i'
+ );
+ this._monthsShortStrictRegex = new RegExp(
+ '^(' + shortPieces.join('|') + ')',
+ 'i'
+ );
+ }
+
+ // FORMATTING
+
+ addFormatToken('Y', 0, 0, function () {
+ var y = this.year();
+ return y <= 9999 ? zeroFill(y, 4) : '+' + y;
+ });
+
+ addFormatToken(0, ['YY', 2], 0, function () {
+ return this.year() % 100;
+ });
+
+ addFormatToken(0, ['YYYY', 4], 0, 'year');
+ addFormatToken(0, ['YYYYY', 5], 0, 'year');
+ addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
+
+ // ALIASES
+
+ addUnitAlias('year', 'y');
+
+ // PRIORITIES
+
+ addUnitPriority('year', 1);
+
+ // PARSING
+
+ addRegexToken('Y', matchSigned);
+ addRegexToken('YY', match1to2, match2);
+ addRegexToken('YYYY', match1to4, match4);
+ addRegexToken('YYYYY', match1to6, match6);
+ addRegexToken('YYYYYY', match1to6, match6);
+
+ addParseToken(['YYYYY', 'YYYYYY'], YEAR);
+ addParseToken('YYYY', function (input, array) {
+ array[YEAR] =
+ input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
+ });
+ addParseToken('YY', function (input, array) {
+ array[YEAR] = hooks.parseTwoDigitYear(input);
+ });
+ addParseToken('Y', function (input, array) {
+ array[YEAR] = parseInt(input, 10);
+ });
+
+ // HELPERS
+
+ function daysInYear(year) {
+ return isLeapYear(year) ? 366 : 365;
+ }
+
+ // HOOKS
+
+ hooks.parseTwoDigitYear = function (input) {
+ return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
+ };
+
+ // MOMENTS
+
+ var getSetYear = makeGetSet('FullYear', true);
+
+ function getIsLeapYear() {
+ return isLeapYear(this.year());
+ }
+
+ function createDate(y, m, d, h, M, s, ms) {
+ // can't just apply() to create a date:
+ // https://stackoverflow.com/q/181348
+ var date;
+ // the date constructor remaps years 0-99 to 1900-1999
+ if (y < 100 && y >= 0) {
+ // preserve leap years using a full 400 year cycle, then reset
+ date = new Date(y + 400, m, d, h, M, s, ms);
+ if (isFinite(date.getFullYear())) {
+ date.setFullYear(y);
+ }
+ } else {
+ date = new Date(y, m, d, h, M, s, ms);
+ }
+
+ return date;
+ }
+
+ function createUTCDate(y) {
+ var date, args;
+ // the Date.UTC function remaps years 0-99 to 1900-1999
+ if (y < 100 && y >= 0) {
+ args = Array.prototype.slice.call(arguments);
+ // preserve leap years using a full 400 year cycle, then reset
+ args[0] = y + 400;
+ date = new Date(Date.UTC.apply(null, args));
+ if (isFinite(date.getUTCFullYear())) {
+ date.setUTCFullYear(y);
+ }
+ } else {
+ date = new Date(Date.UTC.apply(null, arguments));
+ }
+
+ return date;
+ }
+
+ // start-of-first-week - start-of-year
+ function firstWeekOffset(year, dow, doy) {
+ var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
+ fwd = 7 + dow - doy,
+ // first-week day local weekday -- which local weekday is fwd
+ fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
+
+ return -fwdlw + fwd - 1;
+ }
+
+ // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
+ function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
+ var localWeekday = (7 + weekday - dow) % 7,
+ weekOffset = firstWeekOffset(year, dow, doy),
+ dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
+ resYear,
+ resDayOfYear;
+
+ if (dayOfYear <= 0) {
+ resYear = year - 1;
+ resDayOfYear = daysInYear(resYear) + dayOfYear;
+ } else if (dayOfYear > daysInYear(year)) {
+ resYear = year + 1;
+ resDayOfYear = dayOfYear - daysInYear(year);
+ } else {
+ resYear = year;
+ resDayOfYear = dayOfYear;
+ }
+
+ return {
+ year: resYear,
+ dayOfYear: resDayOfYear,
+ };
+ }
+
+ function weekOfYear(mom, dow, doy) {
+ var weekOffset = firstWeekOffset(mom.year(), dow, doy),
+ week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
+ resWeek,
+ resYear;
+
+ if (week < 1) {
+ resYear = mom.year() - 1;
+ resWeek = week + weeksInYear(resYear, dow, doy);
+ } else if (week > weeksInYear(mom.year(), dow, doy)) {
+ resWeek = week - weeksInYear(mom.year(), dow, doy);
+ resYear = mom.year() + 1;
+ } else {
+ resYear = mom.year();
+ resWeek = week;
+ }
+
+ return {
+ week: resWeek,
+ year: resYear,
+ };
+ }
+
+ function weeksInYear(year, dow, doy) {
+ var weekOffset = firstWeekOffset(year, dow, doy),
+ weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
+ return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
+ }
+
+ // FORMATTING
+
+ addFormatToken('w', ['ww', 2], 'wo', 'week');
+ addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
+
+ // ALIASES
+
+ addUnitAlias('week', 'w');
+ addUnitAlias('isoWeek', 'W');
+
+ // PRIORITIES
+
+ addUnitPriority('week', 5);
+ addUnitPriority('isoWeek', 5);
+
+ // PARSING
+
+ addRegexToken('w', match1to2);
+ addRegexToken('ww', match1to2, match2);
+ addRegexToken('W', match1to2);
+ addRegexToken('WW', match1to2, match2);
+
+ addWeekParseToken(['w', 'ww', 'W', 'WW'], function (
+ input,
+ week,
+ config,
+ token
+ ) {
+ week[token.substr(0, 1)] = toInt(input);
+ });
+
+ // HELPERS
+
+ // LOCALES
+
+ function localeWeek(mom) {
+ return weekOfYear(mom, this._week.dow, this._week.doy).week;
+ }
+
+ var defaultLocaleWeek = {
+ dow: 0, // Sunday is the first day of the week.
+ doy: 6, // The week that contains Jan 6th is the first week of the year.
+ };
+
+ function localeFirstDayOfWeek() {
+ return this._week.dow;
+ }
+
+ function localeFirstDayOfYear() {
+ return this._week.doy;
+ }
+
+ // MOMENTS
+
+ function getSetWeek(input) {
+ var week = this.localeData().week(this);
+ return input == null ? week : this.add((input - week) * 7, 'd');
+ }
+
+ function getSetISOWeek(input) {
+ var week = weekOfYear(this, 1, 4).week;
+ return input == null ? week : this.add((input - week) * 7, 'd');
+ }
+
+ // FORMATTING
+
+ addFormatToken('d', 0, 'do', 'day');
+
+ addFormatToken('dd', 0, 0, function (format) {
+ return this.localeData().weekdaysMin(this, format);
+ });
+
+ addFormatToken('ddd', 0, 0, function (format) {
+ return this.localeData().weekdaysShort(this, format);
+ });
+
+ addFormatToken('dddd', 0, 0, function (format) {
+ return this.localeData().weekdays(this, format);
+ });
+
+ addFormatToken('e', 0, 0, 'weekday');
+ addFormatToken('E', 0, 0, 'isoWeekday');
+
+ // ALIASES
+
+ addUnitAlias('day', 'd');
+ addUnitAlias('weekday', 'e');
+ addUnitAlias('isoWeekday', 'E');
+
+ // PRIORITY
+ addUnitPriority('day', 11);
+ addUnitPriority('weekday', 11);
+ addUnitPriority('isoWeekday', 11);
+
+ // PARSING
+
+ addRegexToken('d', match1to2);
+ addRegexToken('e', match1to2);
+ addRegexToken('E', match1to2);
+ addRegexToken('dd', function (isStrict, locale) {
+ return locale.weekdaysMinRegex(isStrict);
+ });
+ addRegexToken('ddd', function (isStrict, locale) {
+ return locale.weekdaysShortRegex(isStrict);
+ });
+ addRegexToken('dddd', function (isStrict, locale) {
+ return locale.weekdaysRegex(isStrict);
+ });
+
+ addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
+ var weekday = config._locale.weekdaysParse(input, token, config._strict);
+ // if we didn't get a weekday name, mark the date as invalid
+ if (weekday != null) {
+ week.d = weekday;
+ } else {
+ getParsingFlags(config).invalidWeekday = input;
+ }
+ });
+
+ addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
+ week[token] = toInt(input);
+ });
+
+ // HELPERS
+
+ function parseWeekday(input, locale) {
+ if (typeof input !== 'string') {
+ return input;
+ }
+
+ if (!isNaN(input)) {
+ return parseInt(input, 10);
+ }
+
+ input = locale.weekdaysParse(input);
+ if (typeof input === 'number') {
+ return input;
+ }
+
+ return null;
+ }
+
+ function parseIsoWeekday(input, locale) {
+ if (typeof input === 'string') {
+ return locale.weekdaysParse(input) % 7 || 7;
+ }
+ return isNaN(input) ? null : input;
+ }
+
+ // LOCALES
+ function shiftWeekdays(ws, n) {
+ return ws.slice(n, 7).concat(ws.slice(0, n));
+ }
+
+ var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
+ '_'
+ ),
+ defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+ defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+ defaultWeekdaysRegex = matchWord,
+ defaultWeekdaysShortRegex = matchWord,
+ defaultWeekdaysMinRegex = matchWord;
+
+ function localeWeekdays(m, format) {
+ var weekdays = isArray(this._weekdays)
+ ? this._weekdays
+ : this._weekdays[
+ m && m !== true && this._weekdays.isFormat.test(format)
+ ? 'format'
+ : 'standalone'
+ ];
+ return m === true
+ ? shiftWeekdays(weekdays, this._week.dow)
+ : m
+ ? weekdays[m.day()]
+ : weekdays;
+ }
+
+ function localeWeekdaysShort(m) {
+ return m === true
+ ? shiftWeekdays(this._weekdaysShort, this._week.dow)
+ : m
+ ? this._weekdaysShort[m.day()]
+ : this._weekdaysShort;
+ }
+
+ function localeWeekdaysMin(m) {
+ return m === true
+ ? shiftWeekdays(this._weekdaysMin, this._week.dow)
+ : m
+ ? this._weekdaysMin[m.day()]
+ : this._weekdaysMin;
+ }
+
+ function handleStrictParse$1(weekdayName, format, strict) {
+ var i,
+ ii,
+ mom,
+ llc = weekdayName.toLocaleLowerCase();
+ if (!this._weekdaysParse) {
+ this._weekdaysParse = [];
+ this._shortWeekdaysParse = [];
+ this._minWeekdaysParse = [];
+
+ for (i = 0; i < 7; ++i) {
+ mom = createUTC([2000, 1]).day(i);
+ this._minWeekdaysParse[i] = this.weekdaysMin(
+ mom,
+ ''
+ ).toLocaleLowerCase();
+ this._shortWeekdaysParse[i] = this.weekdaysShort(
+ mom,
+ ''
+ ).toLocaleLowerCase();
+ this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
+ }
+ }
+
+ if (strict) {
+ if (format === 'dddd') {
+ ii = indexOf.call(this._weekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else if (format === 'ddd') {
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ } else {
+ if (format === 'dddd') {
+ ii = indexOf.call(this._weekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else if (format === 'ddd') {
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._weekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._weekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ }
+ }
+
+ function localeWeekdaysParse(weekdayName, format, strict) {
+ var i, mom, regex;
+
+ if (this._weekdaysParseExact) {
+ return handleStrictParse$1.call(this, weekdayName, format, strict);
+ }
+
+ if (!this._weekdaysParse) {
+ this._weekdaysParse = [];
+ this._minWeekdaysParse = [];
+ this._shortWeekdaysParse = [];
+ this._fullWeekdaysParse = [];
+ }
+
+ for (i = 0; i < 7; i++) {
+ // make the regex if we don't have it already
+
+ mom = createUTC([2000, 1]).day(i);
+ if (strict && !this._fullWeekdaysParse[i]) {
+ this._fullWeekdaysParse[i] = new RegExp(
+ '^' + this.weekdays(mom, '').replace('.', '\\.?') + '$',
+ 'i'
+ );
+ this._shortWeekdaysParse[i] = new RegExp(
+ '^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$',
+ 'i'
+ );
+ this._minWeekdaysParse[i] = new RegExp(
+ '^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$',
+ 'i'
+ );
+ }
+ if (!this._weekdaysParse[i]) {
+ regex =
+ '^' +
+ this.weekdays(mom, '') +
+ '|^' +
+ this.weekdaysShort(mom, '') +
+ '|^' +
+ this.weekdaysMin(mom, '');
+ this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
+ }
+ // test the regex
+ if (
+ strict &&
+ format === 'dddd' &&
+ this._fullWeekdaysParse[i].test(weekdayName)
+ ) {
+ return i;
+ } else if (
+ strict &&
+ format === 'ddd' &&
+ this._shortWeekdaysParse[i].test(weekdayName)
+ ) {
+ return i;
+ } else if (
+ strict &&
+ format === 'dd' &&
+ this._minWeekdaysParse[i].test(weekdayName)
+ ) {
+ return i;
+ } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
+ return i;
+ }
+ }
+ }
+
+ // MOMENTS
+
+ function getSetDayOfWeek(input) {
+ if (!this.isValid()) {
+ return input != null ? this : NaN;
+ }
+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
+ if (input != null) {
+ input = parseWeekday(input, this.localeData());
+ return this.add(input - day, 'd');
+ } else {
+ return day;
+ }
+ }
+
+ function getSetLocaleDayOfWeek(input) {
+ if (!this.isValid()) {
+ return input != null ? this : NaN;
+ }
+ var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
+ return input == null ? weekday : this.add(input - weekday, 'd');
+ }
+
+ function getSetISODayOfWeek(input) {
+ if (!this.isValid()) {
+ return input != null ? 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 (input != null) {
+ var weekday = parseIsoWeekday(input, this.localeData());
+ return this.day(this.day() % 7 ? weekday : weekday - 7);
+ } else {
+ return this.day() || 7;
+ }
+ }
+
+ function weekdaysRegex(isStrict) {
+ if (this._weekdaysParseExact) {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ computeWeekdaysParse.call(this);
+ }
+ if (isStrict) {
+ return this._weekdaysStrictRegex;
+ } else {
+ return this._weekdaysRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ this._weekdaysRegex = defaultWeekdaysRegex;
+ }
+ return this._weekdaysStrictRegex && isStrict
+ ? this._weekdaysStrictRegex
+ : this._weekdaysRegex;
+ }
+ }
+
+ function weekdaysShortRegex(isStrict) {
+ if (this._weekdaysParseExact) {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ computeWeekdaysParse.call(this);
+ }
+ if (isStrict) {
+ return this._weekdaysShortStrictRegex;
+ } else {
+ return this._weekdaysShortRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_weekdaysShortRegex')) {
+ this._weekdaysShortRegex = defaultWeekdaysShortRegex;
+ }
+ return this._weekdaysShortStrictRegex && isStrict
+ ? this._weekdaysShortStrictRegex
+ : this._weekdaysShortRegex;
+ }
+ }
+
+ function weekdaysMinRegex(isStrict) {
+ if (this._weekdaysParseExact) {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ computeWeekdaysParse.call(this);
+ }
+ if (isStrict) {
+ return this._weekdaysMinStrictRegex;
+ } else {
+ return this._weekdaysMinRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_weekdaysMinRegex')) {
+ this._weekdaysMinRegex = defaultWeekdaysMinRegex;
+ }
+ return this._weekdaysMinStrictRegex && isStrict
+ ? this._weekdaysMinStrictRegex
+ : this._weekdaysMinRegex;
+ }
+ }
+
+ function computeWeekdaysParse() {
+ function cmpLenRev(a, b) {
+ return b.length - a.length;
+ }
+
+ var minPieces = [],
+ shortPieces = [],
+ longPieces = [],
+ mixedPieces = [],
+ i,
+ mom,
+ minp,
+ shortp,
+ longp;
+ for (i = 0; i < 7; i++) {
+ // make the regex if we don't have it already
+ mom = createUTC([2000, 1]).day(i);
+ minp = regexEscape(this.weekdaysMin(mom, ''));
+ shortp = regexEscape(this.weekdaysShort(mom, ''));
+ longp = regexEscape(this.weekdays(mom, ''));
+ minPieces.push(minp);
+ shortPieces.push(shortp);
+ longPieces.push(longp);
+ mixedPieces.push(minp);
+ mixedPieces.push(shortp);
+ mixedPieces.push(longp);
+ }
+ // Sorting makes sure if one weekday (or abbr) is a prefix of another it
+ // will match the longer piece.
+ minPieces.sort(cmpLenRev);
+ shortPieces.sort(cmpLenRev);
+ longPieces.sort(cmpLenRev);
+ mixedPieces.sort(cmpLenRev);
+
+ this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
+ this._weekdaysShortRegex = this._weekdaysRegex;
+ this._weekdaysMinRegex = this._weekdaysRegex;
+
+ this._weekdaysStrictRegex = new RegExp(
+ '^(' + longPieces.join('|') + ')',
+ 'i'
+ );
+ this._weekdaysShortStrictRegex = new RegExp(
+ '^(' + shortPieces.join('|') + ')',
+ 'i'
+ );
+ this._weekdaysMinStrictRegex = new RegExp(
+ '^(' + minPieces.join('|') + ')',
+ 'i'
+ );
+ }
+
+ // FORMATTING
+
+ function hFormat() {
+ return this.hours() % 12 || 12;
+ }
+
+ function kFormat() {
+ return this.hours() || 24;
+ }
+
+ addFormatToken('H', ['HH', 2], 0, 'hour');
+ addFormatToken('h', ['hh', 2], 0, hFormat);
+ addFormatToken('k', ['kk', 2], 0, kFormat);
+
+ addFormatToken('hmm', 0, 0, function () {
+ return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
+ });
+
+ addFormatToken('hmmss', 0, 0, function () {
+ return (
+ '' +
+ hFormat.apply(this) +
+ zeroFill(this.minutes(), 2) +
+ zeroFill(this.seconds(), 2)
+ );
+ });
+
+ addFormatToken('Hmm', 0, 0, function () {
+ return '' + this.hours() + zeroFill(this.minutes(), 2);
+ });
+
+ addFormatToken('Hmmss', 0, 0, function () {
+ return (
+ '' +
+ this.hours() +
+ zeroFill(this.minutes(), 2) +
+ zeroFill(this.seconds(), 2)
+ );
+ });
+
+ function meridiem(token, lowercase) {
+ addFormatToken(token, 0, 0, function () {
+ return this.localeData().meridiem(
+ this.hours(),
+ this.minutes(),
+ lowercase
+ );
+ });
+ }
+
+ meridiem('a', true);
+ meridiem('A', false);
+
+ // ALIASES
+
+ addUnitAlias('hour', 'h');
+
+ // PRIORITY
+ addUnitPriority('hour', 13);
+
+ // PARSING
+
+ function matchMeridiem(isStrict, locale) {
+ return locale._meridiemParse;
+ }
+
+ addRegexToken('a', matchMeridiem);
+ addRegexToken('A', matchMeridiem);
+ addRegexToken('H', match1to2);
+ addRegexToken('h', match1to2);
+ addRegexToken('k', match1to2);
+ addRegexToken('HH', match1to2, match2);
+ addRegexToken('hh', match1to2, match2);
+ addRegexToken('kk', match1to2, match2);
+
+ addRegexToken('hmm', match3to4);
+ addRegexToken('hmmss', match5to6);
+ addRegexToken('Hmm', match3to4);
+ addRegexToken('Hmmss', match5to6);
+
+ addParseToken(['H', 'HH'], HOUR);
+ addParseToken(['k', 'kk'], function (input, array, config) {
+ var kInput = toInt(input);
+ array[HOUR] = kInput === 24 ? 0 : kInput;
+ });
+ addParseToken(['a', 'A'], function (input, array, config) {
+ config._isPm = config._locale.isPM(input);
+ config._meridiem = input;
+ });
+ addParseToken(['h', 'hh'], function (input, array, config) {
+ array[HOUR] = toInt(input);
+ getParsingFlags(config).bigHour = true;
+ });
+ addParseToken('hmm', function (input, array, config) {
+ var pos = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos));
+ array[MINUTE] = toInt(input.substr(pos));
+ getParsingFlags(config).bigHour = true;
+ });
+ addParseToken('hmmss', function (input, array, config) {
+ var pos1 = input.length - 4,
+ pos2 = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos1));
+ array[MINUTE] = toInt(input.substr(pos1, 2));
+ array[SECOND] = toInt(input.substr(pos2));
+ getParsingFlags(config).bigHour = true;
+ });
+ addParseToken('Hmm', function (input, array, config) {
+ var pos = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos));
+ array[MINUTE] = toInt(input.substr(pos));
+ });
+ addParseToken('Hmmss', function (input, array, config) {
+ var pos1 = input.length - 4,
+ pos2 = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos1));
+ array[MINUTE] = toInt(input.substr(pos1, 2));
+ array[SECOND] = toInt(input.substr(pos2));
+ });
+
+ // LOCALES
+
+ function localeIsPM(input) {
+ // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
+ // Using charAt should be more compatible.
+ return (input + '').toLowerCase().charAt(0) === 'p';
+ }
+
+ var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i,
+ // Setting the hour should keep the time, because the user explicitly
+ // specified which hour they want. So trying to maintain the same hour (in
+ // a new timezone) makes sense. Adding/subtracting hours does not follow
+ // this rule.
+ getSetHour = makeGetSet('Hours', true);
+
+ function localeMeridiem(hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'pm' : 'PM';
+ } else {
+ return isLower ? 'am' : 'AM';
+ }
+ }
+
+ var baseConfig = {
+ calendar: defaultCalendar,
+ longDateFormat: defaultLongDateFormat,
+ invalidDate: defaultInvalidDate,
+ ordinal: defaultOrdinal,
+ dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
+ relativeTime: defaultRelativeTime,
+
+ months: defaultLocaleMonths,
+ monthsShort: defaultLocaleMonthsShort,
+
+ week: defaultLocaleWeek,
+
+ weekdays: defaultLocaleWeekdays,
+ weekdaysMin: defaultLocaleWeekdaysMin,
+ weekdaysShort: defaultLocaleWeekdaysShort,
+
+ meridiemParse: defaultLocaleMeridiemParse,
+ };
+
+ // internal storage for locale config files
+ var locales = {},
+ localeFamilies = {},
+ globalLocale;
+
+ function commonPrefix(arr1, arr2) {
+ var i,
+ minl = Math.min(arr1.length, arr2.length);
+ for (i = 0; i < minl; i += 1) {
+ if (arr1[i] !== arr2[i]) {
+ return i;
+ }
+ }
+ return minl;
+ }
+
+ function normalizeLocale(key) {
+ return key ? key.toLowerCase().replace('_', '-') : key;
+ }
+
+ // 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 chooseLocale(names) {
+ var i = 0,
+ j,
+ next,
+ locale,
+ split;
+
+ while (i < names.length) {
+ split = normalizeLocale(names[i]).split('-');
+ j = split.length;
+ next = normalizeLocale(names[i + 1]);
+ next = next ? next.split('-') : null;
+ while (j > 0) {
+ locale = loadLocale(split.slice(0, j).join('-'));
+ if (locale) {
+ return locale;
+ }
+ if (
+ next &&
+ next.length >= j &&
+ commonPrefix(split, next) >= j - 1
+ ) {
+ //the next array item is better than a shallower substring of this one
+ break;
+ }
+ j--;
+ }
+ i++;
+ }
+ return globalLocale;
+ }
+
+ function loadLocale(name) {
+ var oldLocale = null,
+ aliasedRequire;
+ // TODO: Find a better way to register and load all the locales in Node
+ if (
+ locales[name] === undefined &&
+ typeof module !== 'undefined' &&
+ module &&
+ module.exports
+ ) {
+ try {
+ oldLocale = globalLocale._abbr;
+ aliasedRequire = require;
+ aliasedRequire('./locale/' + name);
+ getSetGlobalLocale(oldLocale);
+ } catch (e) {
+ // mark as not found to avoid repeating expensive file require call causing high CPU
+ // when trying to find en-US, en_US, en-us for every format call
+ locales[name] = null; // null means not found
+ }
+ }
+ return locales[name];
+ }
+
+ // 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 getSetGlobalLocale(key, values) {
+ var data;
+ if (key) {
+ if (isUndefined(values)) {
+ data = getLocale(key);
+ } else {
+ data = defineLocale(key, values);
+ }
+
+ if (data) {
+ // moment.duration._locale = moment._locale = data;
+ globalLocale = data;
+ } else {
+ if (typeof console !== 'undefined' && console.warn) {
+ //warn user if arguments are passed but the locale could not be set
+ console.warn(
+ 'Locale ' + key + ' not found. Did you forget to load it?'
+ );
+ }
+ }
+ }
+
+ return globalLocale._abbr;
+ }
+
+ function defineLocale(name, config) {
+ if (config !== null) {
+ var locale,
+ parentConfig = baseConfig;
+ config.abbr = name;
+ if (locales[name] != null) {
+ deprecateSimple(
+ '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.'
+ );
+ parentConfig = locales[name]._config;
+ } else if (config.parentLocale != null) {
+ if (locales[config.parentLocale] != null) {
+ parentConfig = locales[config.parentLocale]._config;
+ } else {
+ locale = loadLocale(config.parentLocale);
+ if (locale != null) {
+ parentConfig = locale._config;
+ } else {
+ if (!localeFamilies[config.parentLocale]) {
+ localeFamilies[config.parentLocale] = [];
+ }
+ localeFamilies[config.parentLocale].push({
+ name: name,
+ config: config,
+ });
+ return null;
+ }
+ }
+ }
+ locales[name] = new Locale(mergeConfigs(parentConfig, config));
+
+ if (localeFamilies[name]) {
+ localeFamilies[name].forEach(function (x) {
+ defineLocale(x.name, x.config);
+ });
+ }
+
+ // backwards compat for now: also set the locale
+ // make sure we set the locale AFTER all child locales have been
+ // created, so we won't end up with the child locale set.
+ getSetGlobalLocale(name);
+
+ return locales[name];
+ } else {
+ // useful for testing
+ delete locales[name];
+ return null;
+ }
+ }
+
+ function updateLocale(name, config) {
+ if (config != null) {
+ var locale,
+ tmpLocale,
+ parentConfig = baseConfig;
+
+ if (locales[name] != null && locales[name].parentLocale != null) {
+ // Update existing child locale in-place to avoid memory-leaks
+ locales[name].set(mergeConfigs(locales[name]._config, config));
+ } else {
+ // MERGE
+ tmpLocale = loadLocale(name);
+ if (tmpLocale != null) {
+ parentConfig = tmpLocale._config;
+ }
+ config = mergeConfigs(parentConfig, config);
+ if (tmpLocale == null) {
+ // updateLocale is called for creating a new locale
+ // Set abbr so it will have a name (getters return
+ // undefined otherwise).
+ config.abbr = name;
+ }
+ locale = new Locale(config);
+ locale.parentLocale = locales[name];
+ locales[name] = locale;
+ }
+
+ // backwards compat for now: also set the locale
+ getSetGlobalLocale(name);
+ } else {
+ // pass null for config to unupdate, useful for tests
+ if (locales[name] != null) {
+ if (locales[name].parentLocale != null) {
+ locales[name] = locales[name].parentLocale;
+ if (name === getSetGlobalLocale()) {
+ getSetGlobalLocale(name);
+ }
+ } else if (locales[name] != null) {
+ delete locales[name];
+ }
+ }
+ }
+ return locales[name];
+ }
+
+ // returns locale data
+ function getLocale(key) {
+ var locale;
+
+ if (key && key._locale && key._locale._abbr) {
+ key = key._locale._abbr;
+ }
+
+ if (!key) {
+ return globalLocale;
+ }
+
+ if (!isArray(key)) {
+ //short-circuit everything else
+ locale = loadLocale(key);
+ if (locale) {
+ return locale;
+ }
+ key = [key];
+ }
+
+ return chooseLocale(key);
+ }
+
+ function listLocales() {
+ return keys(locales);
+ }
+
+ function checkOverflow(m) {
+ var overflow,
+ a = m._a;
+
+ if (a && getParsingFlags(m).overflow === -2) {
+ overflow =
+ a[MONTH] < 0 || a[MONTH] > 11
+ ? MONTH
+ : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH])
+ ? DATE
+ : a[HOUR] < 0 ||
+ a[HOUR] > 24 ||
+ (a[HOUR] === 24 &&
+ (a[MINUTE] !== 0 ||
+ a[SECOND] !== 0 ||
+ a[MILLISECOND] !== 0))
+ ? HOUR
+ : a[MINUTE] < 0 || a[MINUTE] > 59
+ ? MINUTE
+ : a[SECOND] < 0 || a[SECOND] > 59
+ ? SECOND
+ : a[MILLISECOND] < 0 || a[MILLISECOND] > 999
+ ? MILLISECOND
+ : -1;
+
+ if (
+ getParsingFlags(m)._overflowDayOfYear &&
+ (overflow < YEAR || overflow > DATE)
+ ) {
+ overflow = DATE;
+ }
+ if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
+ overflow = WEEK;
+ }
+ if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
+ overflow = WEEKDAY;
+ }
+
+ getParsingFlags(m).overflow = overflow;
+ }
+
+ return m;
+ }
+
+ // iso 8601 regex
+ // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
+ var extendedIsoRegex = /^\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)?)?$/,
+ basicIsoRegex = /^\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)?)?$/,
+ tzRegex = /Z|[+-]\d\d(?::?\d\d)?/,
+ isoDates = [
+ ['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/, false],
+ ['YYYY-DDD', /\d{4}-\d{3}/],
+ ['YYYY-MM', /\d{4}-\d\d/, false],
+ ['YYYYYYMMDD', /[+-]\d{10}/],
+ ['YYYYMMDD', /\d{8}/],
+ ['GGGG[W]WWE', /\d{4}W\d{3}/],
+ ['GGGG[W]WW', /\d{4}W\d{2}/, false],
+ ['YYYYDDD', /\d{7}/],
+ ['YYYYMM', /\d{6}/, false],
+ ['YYYY', /\d{4}/, false],
+ ],
+ // iso time formats and regexes
+ isoTimes = [
+ ['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/],
+ ],
+ aspNetJsonRegex = /^\/?Date\((-?\d+)/i,
+ // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
+ rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,
+ obsOffsets = {
+ UT: 0,
+ GMT: 0,
+ EDT: -4 * 60,
+ EST: -5 * 60,
+ CDT: -5 * 60,
+ CST: -6 * 60,
+ MDT: -6 * 60,
+ MST: -7 * 60,
+ PDT: -7 * 60,
+ PST: -8 * 60,
+ };
+
+ // date from iso format
+ function configFromISO(config) {
+ var i,
+ l,
+ string = config._i,
+ match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
+ allowTime,
+ dateFormat,
+ timeFormat,
+ tzFormat;
+
+ if (match) {
+ getParsingFlags(config).iso = true;
+
+ for (i = 0, l = isoDates.length; i < l; i++) {
+ if (isoDates[i][1].exec(match[1])) {
+ dateFormat = isoDates[i][0];
+ allowTime = isoDates[i][2] !== false;
+ break;
+ }
+ }
+ if (dateFormat == null) {
+ config._isValid = false;
+ return;
+ }
+ if (match[3]) {
+ for (i = 0, l = isoTimes.length; i < l; i++) {
+ if (isoTimes[i][1].exec(match[3])) {
+ // match[2] should be 'T' or space
+ timeFormat = (match[2] || ' ') + isoTimes[i][0];
+ break;
+ }
+ }
+ if (timeFormat == null) {
+ config._isValid = false;
+ return;
+ }
+ }
+ if (!allowTime && timeFormat != null) {
+ config._isValid = false;
+ return;
+ }
+ if (match[4]) {
+ if (tzRegex.exec(match[4])) {
+ tzFormat = 'Z';
+ } else {
+ config._isValid = false;
+ return;
+ }
+ }
+ config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
+ configFromStringAndFormat(config);
+ } else {
+ config._isValid = false;
+ }
+ }
+
+ function extractFromRFC2822Strings(
+ yearStr,
+ monthStr,
+ dayStr,
+ hourStr,
+ minuteStr,
+ secondStr
+ ) {
+ var result = [
+ untruncateYear(yearStr),
+ defaultLocaleMonthsShort.indexOf(monthStr),
+ parseInt(dayStr, 10),
+ parseInt(hourStr, 10),
+ parseInt(minuteStr, 10),
+ ];
+
+ if (secondStr) {
+ result.push(parseInt(secondStr, 10));
+ }
+
+ return result;
+ }
+
+ function untruncateYear(yearStr) {
+ var year = parseInt(yearStr, 10);
+ if (year <= 49) {
+ return 2000 + year;
+ } else if (year <= 999) {
+ return 1900 + year;
+ }
+ return year;
+ }
+
+ function preprocessRFC2822(s) {
+ // Remove comments and folding whitespace and replace multiple-spaces with a single space
+ return s
+ .replace(/\([^)]*\)|[\n\t]/g, ' ')
+ .replace(/(\s\s+)/g, ' ')
+ .replace(/^\s\s*/, '')
+ .replace(/\s\s*$/, '');
+ }
+
+ function checkWeekday(weekdayStr, parsedInput, config) {
+ if (weekdayStr) {
+ // TODO: Replace the vanilla JS Date object with an independent day-of-week check.
+ var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
+ weekdayActual = new Date(
+ parsedInput[0],
+ parsedInput[1],
+ parsedInput[2]
+ ).getDay();
+ if (weekdayProvided !== weekdayActual) {
+ getParsingFlags(config).weekdayMismatch = true;
+ config._isValid = false;
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function calculateOffset(obsOffset, militaryOffset, numOffset) {
+ if (obsOffset) {
+ return obsOffsets[obsOffset];
+ } else if (militaryOffset) {
+ // the only allowed military tz is Z
+ return 0;
+ } else {
+ var hm = parseInt(numOffset, 10),
+ m = hm % 100,
+ h = (hm - m) / 100;
+ return h * 60 + m;
+ }
+ }
+
+ // date and time from ref 2822 format
+ function configFromRFC2822(config) {
+ var match = rfc2822.exec(preprocessRFC2822(config._i)),
+ parsedArray;
+ if (match) {
+ parsedArray = extractFromRFC2822Strings(
+ match[4],
+ match[3],
+ match[2],
+ match[5],
+ match[6],
+ match[7]
+ );
+ if (!checkWeekday(match[1], parsedArray, config)) {
+ return;
+ }
+
+ config._a = parsedArray;
+ config._tzm = calculateOffset(match[8], match[9], match[10]);
+
+ config._d = createUTCDate.apply(null, config._a);
+ config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
+
+ getParsingFlags(config).rfc2822 = true;
+ } else {
+ config._isValid = false;
+ }
+ }
+
+ // date from 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict
+ function configFromString(config) {
+ var matched = aspNetJsonRegex.exec(config._i);
+ if (matched !== null) {
+ config._d = new Date(+matched[1]);
+ return;
+ }
+
+ configFromISO(config);
+ if (config._isValid === false) {
+ delete config._isValid;
+ } else {
+ return;
+ }
+
+ configFromRFC2822(config);
+ if (config._isValid === false) {
+ delete config._isValid;
+ } else {
+ return;
+ }
+
+ if (config._strict) {
+ config._isValid = false;
+ } else {
+ // Final attempt, use Input Fallback
+ hooks.createFromInputFallback(config);
+ }
+ }
+
+ hooks.createFromInputFallback = deprecate(
+ 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
+ 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
+ 'discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.',
+ function (config) {
+ config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
+ }
+ );
+
+ // Pick the first defined of two or three arguments.
+ function defaults(a, b, c) {
+ if (a != null) {
+ return a;
+ }
+ if (b != null) {
+ return b;
+ }
+ return c;
+ }
+
+ function currentDateArray(config) {
+ // hooks is actually the exported moment object
+ var nowValue = new Date(hooks.now());
+ if (config._useUTC) {
+ return [
+ nowValue.getUTCFullYear(),
+ nowValue.getUTCMonth(),
+ nowValue.getUTCDate(),
+ ];
+ }
+ return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.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 configFromArray(config) {
+ var i,
+ date,
+ input = [],
+ currentDate,
+ expectedWeekday,
+ yearToUse;
+
+ if (config._d) {
+ return;
+ }
+
+ currentDate = currentDateArray(config);
+
+ //compute day of the year from weeks and weekdays
+ if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
+ dayOfYearFromWeekInfo(config);
+ }
+
+ //if the day of the year is set, figure out what it is
+ if (config._dayOfYear != null) {
+ yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
+
+ if (
+ config._dayOfYear > daysInYear(yearToUse) ||
+ config._dayOfYear === 0
+ ) {
+ getParsingFlags(config)._overflowDayOfYear = true;
+ }
+
+ date = createUTCDate(yearToUse, 0, config._dayOfYear);
+ config._a[MONTH] = date.getUTCMonth();
+ config._a[DATE] = date.getUTCDate();
+ }
+
+ // 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 (i = 0; i < 3 && config._a[i] == null; ++i) {
+ config._a[i] = input[i] = currentDate[i];
+ }
+
+ // Zero out whatever was not defaulted, including time
+ for (; i < 7; i++) {
+ config._a[i] = input[i] =
+ config._a[i] == null ? (i === 2 ? 1 : 0) : config._a[i];
+ }
+
+ // Check for 24:00:00.000
+ if (
+ config._a[HOUR] === 24 &&
+ config._a[MINUTE] === 0 &&
+ config._a[SECOND] === 0 &&
+ config._a[MILLISECOND] === 0
+ ) {
+ config._nextDay = true;
+ config._a[HOUR] = 0;
+ }
+
+ config._d = (config._useUTC ? createUTCDate : createDate).apply(
+ null,
+ input
+ );
+ expectedWeekday = config._useUTC
+ ? config._d.getUTCDay()
+ : config._d.getDay();
+
+ // Apply timezone offset from input. The actual utcOffset can be changed
+ // with parseZone.
+ if (config._tzm != null) {
+ config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
+ }
+
+ if (config._nextDay) {
+ config._a[HOUR] = 24;
+ }
+
+ // check for mismatching day of week
+ if (
+ config._w &&
+ typeof config._w.d !== 'undefined' &&
+ config._w.d !== expectedWeekday
+ ) {
+ getParsingFlags(config).weekdayMismatch = true;
+ }
+ }
+
+ function dayOfYearFromWeekInfo(config) {
+ var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow, curWeek;
+
+ w = config._w;
+ if (w.GG != null || w.W != null || w.E != null) {
+ dow = 1;
+ doy = 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).
+ weekYear = defaults(
+ w.GG,
+ config._a[YEAR],
+ weekOfYear(createLocal(), 1, 4).year
+ );
+ week = defaults(w.W, 1);
+ weekday = defaults(w.E, 1);
+ if (weekday < 1 || weekday > 7) {
+ weekdayOverflow = true;
+ }
+ } else {
+ dow = config._locale._week.dow;
+ doy = config._locale._week.doy;
+
+ curWeek = weekOfYear(createLocal(), dow, doy);
+
+ weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
+
+ // Default to current week.
+ week = defaults(w.w, curWeek.week);
+
+ if (w.d != null) {
+ // weekday -- low day numbers are considered next week
+ weekday = w.d;
+ if (weekday < 0 || weekday > 6) {
+ weekdayOverflow = true;
+ }
+ } else if (w.e != null) {
+ // local weekday -- counting starts from beginning of week
+ weekday = w.e + dow;
+ if (w.e < 0 || w.e > 6) {
+ weekdayOverflow = true;
+ }
+ } else {
+ // default to beginning of week
+ weekday = dow;
+ }
+ }
+ if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
+ getParsingFlags(config)._overflowWeeks = true;
+ } else if (weekdayOverflow != null) {
+ getParsingFlags(config)._overflowWeekday = true;
+ } else {
+ temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
+ config._a[YEAR] = temp.year;
+ config._dayOfYear = temp.dayOfYear;
+ }
+ }
+
+ // constant that refers to the ISO standard
+ hooks.ISO_8601 = function () {};
+
+ // constant that refers to the RFC 2822 form
+ hooks.RFC_2822 = function () {};
+
+ // date from string and format string
+ function configFromStringAndFormat(config) {
+ // TODO: Move this to another part of the creation flow to prevent circular deps
+ if (config._f === hooks.ISO_8601) {
+ configFromISO(config);
+ return;
+ }
+ if (config._f === hooks.RFC_2822) {
+ configFromRFC2822(config);
+ return;
+ }
+ config._a = [];
+ getParsingFlags(config).empty = true;
+
+ // This array is used to make a Date, either with `new Date` or `Date.UTC`
+ var string = '' + config._i,
+ i,
+ parsedInput,
+ tokens,
+ token,
+ skipped,
+ stringLength = string.length,
+ totalParsedInputLength = 0,
+ era;
+
+ tokens =
+ expandFormat(config._f, config._locale).match(formattingTokens) || [];
+
+ for (i = 0; i < tokens.length; i++) {
+ token = tokens[i];
+ parsedInput = (string.match(getParseRegexForToken(token, config)) ||
+ [])[0];
+ if (parsedInput) {
+ skipped = string.substr(0, string.indexOf(parsedInput));
+ if (skipped.length > 0) {
+ getParsingFlags(config).unusedInput.push(skipped);
+ }
+ string = string.slice(
+ string.indexOf(parsedInput) + parsedInput.length
+ );
+ totalParsedInputLength += parsedInput.length;
+ }
+ // don't parse if it's not a known token
+ if (formatTokenFunctions[token]) {
+ if (parsedInput) {
+ getParsingFlags(config).empty = false;
+ } else {
+ getParsingFlags(config).unusedTokens.push(token);
+ }
+ addTimeToArrayFromToken(token, parsedInput, config);
+ } else if (config._strict && !parsedInput) {
+ getParsingFlags(config).unusedTokens.push(token);
+ }
+ }
+
+ // add remaining unparsed input length to the string
+ getParsingFlags(config).charsLeftOver =
+ stringLength - totalParsedInputLength;
+ if (string.length > 0) {
+ getParsingFlags(config).unusedInput.push(string);
+ }
+
+ // clear _12h flag if hour is <= 12
+ if (
+ config._a[HOUR] <= 12 &&
+ getParsingFlags(config).bigHour === true &&
+ config._a[HOUR] > 0
+ ) {
+ getParsingFlags(config).bigHour = undefined;
+ }
+
+ getParsingFlags(config).parsedDateParts = config._a.slice(0);
+ getParsingFlags(config).meridiem = config._meridiem;
+ // handle meridiem
+ config._a[HOUR] = meridiemFixWrap(
+ config._locale,
+ config._a[HOUR],
+ config._meridiem
+ );
+
+ // handle era
+ era = getParsingFlags(config).era;
+ if (era !== null) {
+ config._a[YEAR] = config._locale.erasConvertYear(era, config._a[YEAR]);
+ }
+
+ configFromArray(config);
+ checkOverflow(config);
+ }
+
+ function meridiemFixWrap(locale, hour, meridiem) {
+ var isPm;
+
+ if (meridiem == null) {
+ // nothing to do
+ return hour;
+ }
+ if (locale.meridiemHour != null) {
+ return locale.meridiemHour(hour, meridiem);
+ } else if (locale.isPM != null) {
+ // Fallback
+ isPm = locale.isPM(meridiem);
+ if (isPm && hour < 12) {
+ hour += 12;
+ }
+ if (!isPm && hour === 12) {
+ hour = 0;
+ }
+ return hour;
+ } else {
+ // this is not supposed to happen
+ return hour;
+ }
+ }
+
+ // date from string and array of format strings
+ function configFromStringAndArray(config) {
+ var tempConfig,
+ bestMoment,
+ scoreToBeat,
+ i,
+ currentScore,
+ validFormatFound,
+ bestFormatIsValid = false;
+
+ if (config._f.length === 0) {
+ getParsingFlags(config).invalidFormat = true;
+ config._d = new Date(NaN);
+ return;
+ }
+
+ for (i = 0; i < config._f.length; i++) {
+ currentScore = 0;
+ validFormatFound = false;
+ tempConfig = copyConfig({}, config);
+ if (config._useUTC != null) {
+ tempConfig._useUTC = config._useUTC;
+ }
+ tempConfig._f = config._f[i];
+ configFromStringAndFormat(tempConfig);
+
+ if (isValid(tempConfig)) {
+ validFormatFound = true;
+ }
+
+ // if there is any input that was not parsed add a penalty for that format
+ currentScore += getParsingFlags(tempConfig).charsLeftOver;
+
+ //or tokens
+ currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
+
+ getParsingFlags(tempConfig).score = currentScore;
+
+ if (!bestFormatIsValid) {
+ if (
+ scoreToBeat == null ||
+ currentScore < scoreToBeat ||
+ validFormatFound
+ ) {
+ scoreToBeat = currentScore;
+ bestMoment = tempConfig;
+ if (validFormatFound) {
+ bestFormatIsValid = true;
+ }
+ }
+ } else {
+ if (currentScore < scoreToBeat) {
+ scoreToBeat = currentScore;
+ bestMoment = tempConfig;
+ }
+ }
+ }
+
+ extend(config, bestMoment || tempConfig);
+ }
+
+ function configFromObject(config) {
+ if (config._d) {
+ return;
+ }
+
+ var i = normalizeObjectUnits(config._i),
+ dayOrDate = i.day === undefined ? i.date : i.day;
+ config._a = map(
+ [i.year, i.month, dayOrDate, i.hour, i.minute, i.second, i.millisecond],
+ function (obj) {
+ return obj && parseInt(obj, 10);
+ }
+ );
+
+ configFromArray(config);
+ }
+
+ function createFromConfig(config) {
+ var res = new Moment(checkOverflow(prepareConfig(config)));
+ if (res._nextDay) {
+ // Adding is smart enough around DST
+ res.add(1, 'd');
+ res._nextDay = undefined;
+ }
+
+ return res;
+ }
+
+ function prepareConfig(config) {
+ var input = config._i,
+ format = config._f;
+
+ config._locale = config._locale || getLocale(config._l);
+
+ if (input === null || (format === undefined && input === '')) {
+ return createInvalid({ nullInput: true });
+ }
+
+ if (typeof input === 'string') {
+ config._i = input = config._locale.preparse(input);
+ }
+
+ if (isMoment(input)) {
+ return new Moment(checkOverflow(input));
+ } else if (isDate(input)) {
+ config._d = input;
+ } else if (isArray(format)) {
+ configFromStringAndArray(config);
+ } else if (format) {
+ configFromStringAndFormat(config);
+ } else {
+ configFromInput(config);
+ }
+
+ if (!isValid(config)) {
+ config._d = null;
+ }
+
+ return config;
+ }
+
+ function configFromInput(config) {
+ var input = config._i;
+ if (isUndefined(input)) {
+ config._d = new Date(hooks.now());
+ } else if (isDate(input)) {
+ config._d = new Date(input.valueOf());
+ } else if (typeof input === 'string') {
+ configFromString(config);
+ } else if (isArray(input)) {
+ config._a = map(input.slice(0), function (obj) {
+ return parseInt(obj, 10);
+ });
+ configFromArray(config);
+ } else if (isObject(input)) {
+ configFromObject(config);
+ } else if (isNumber(input)) {
+ // from milliseconds
+ config._d = new Date(input);
+ } else {
+ hooks.createFromInputFallback(config);
+ }
+ }
+
+ function createLocalOrUTC(input, format, locale, strict, isUTC) {
+ var c = {};
+
+ if (format === true || format === false) {
+ strict = format;
+ format = undefined;
+ }
+
+ if (locale === true || locale === false) {
+ strict = locale;
+ locale = undefined;
+ }
+
+ if (
+ (isObject(input) && isObjectEmpty(input)) ||
+ (isArray(input) && input.length === 0)
+ ) {
+ input = undefined;
+ }
+ // object construction must be done this way.
+ // https://github.com/moment/moment/issues/1423
+ c._isAMomentObject = true;
+ c._useUTC = c._isUTC = isUTC;
+ c._l = locale;
+ c._i = input;
+ c._f = format;
+ c._strict = strict;
+
+ return createFromConfig(c);
+ }
+
+ function createLocal(input, format, locale, strict) {
+ return createLocalOrUTC(input, format, locale, strict, false);
+ }
+
+ var prototypeMin = deprecate(
+ 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
+ function () {
+ var other = createLocal.apply(null, arguments);
+ if (this.isValid() && other.isValid()) {
+ return other < this ? this : other;
+ } else {
+ return createInvalid();
+ }
+ }
+ ),
+ prototypeMax = deprecate(
+ 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
+ function () {
+ var other = createLocal.apply(null, arguments);
+ if (this.isValid() && other.isValid()) {
+ return other > this ? this : other;
+ } else {
+ return createInvalid();
+ }
+ }
+ );
+
+ // 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 pickBy(fn, moments) {
+ var res, i;
+ if (moments.length === 1 && isArray(moments[0])) {
+ moments = moments[0];
+ }
+ if (!moments.length) {
+ return createLocal();
+ }
+ res = moments[0];
+ for (i = 1; i < moments.length; ++i) {
+ if (!moments[i].isValid() || moments[i][fn](res)) {
+ res = moments[i];
+ }
+ }
+ return res;
+ }
+
+ // TODO: Use [].sort instead?
+ function min() {
+ var args = [].slice.call(arguments, 0);
+
+ return pickBy('isBefore', args);
+ }
+
+ function max() {
+ var args = [].slice.call(arguments, 0);
+
+ return pickBy('isAfter', args);
+ }
+
+ var now = function () {
+ return Date.now ? Date.now() : +new Date();
+ };
+
+ var ordering = [
+ 'year',
+ 'quarter',
+ 'month',
+ 'week',
+ 'day',
+ 'hour',
+ 'minute',
+ 'second',
+ 'millisecond',
+ ];
+
+ function isDurationValid(m) {
+ var key,
+ unitHasDecimal = false,
+ i;
+ for (key in m) {
+ if (
+ hasOwnProp(m, key) &&
+ !(
+ indexOf.call(ordering, key) !== -1 &&
+ (m[key] == null || !isNaN(m[key]))
+ )
+ ) {
+ return false;
+ }
+ }
+
+ for (i = 0; i < ordering.length; ++i) {
+ if (m[ordering[i]]) {
+ if (unitHasDecimal) {
+ return false; // only allow non-integers for smallest unit
+ }
+ if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
+ unitHasDecimal = true;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ function isValid$1() {
+ return this._isValid;
+ }
+
+ function createInvalid$1() {
+ return createDuration(NaN);
+ }
+
+ function Duration(duration) {
+ var normalizedInput = normalizeObjectUnits(duration),
+ years = normalizedInput.year || 0,
+ quarters = normalizedInput.quarter || 0,
+ months = normalizedInput.month || 0,
+ weeks = normalizedInput.week || normalizedInput.isoWeek || 0,
+ days = normalizedInput.day || 0,
+ hours = normalizedInput.hour || 0,
+ minutes = normalizedInput.minute || 0,
+ seconds = normalizedInput.second || 0,
+ milliseconds = normalizedInput.millisecond || 0;
+
+ this._isValid = isDurationValid(normalizedInput);
+
+ // representation for dateAddRemove
+ this._milliseconds =
+ +milliseconds +
+ seconds * 1e3 + // 1000
+ minutes * 6e4 + // 1000 * 60
+ hours * 1000 * 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 = +days + weeks * 7;
+ // It is impossible to translate months into days without knowing
+ // which months you are are talking about, so we have to store
+ // it separately.
+ this._months = +months + quarters * 3 + years * 12;
+
+ this._data = {};
+
+ this._locale = getLocale();
+
+ this._bubble();
+ }
+
+ function isDuration(obj) {
+ return obj instanceof Duration;
+ }
+
+ function absRound(number) {
+ if (number < 0) {
+ return Math.round(-1 * number) * -1;
+ } else {
+ return Math.round(number);
+ }
+ }
+
+ // compare two arrays, return the number of differences
+ function compareArrays(array1, array2, dontConvert) {
+ var len = Math.min(array1.length, array2.length),
+ lengthDiff = Math.abs(array1.length - array2.length),
+ diffs = 0,
+ i;
+ for (i = 0; i < len; i++) {
+ if (
+ (dontConvert && array1[i] !== array2[i]) ||
+ (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))
+ ) {
+ diffs++;
+ }
+ }
+ return diffs + lengthDiff;
+ }
+
+ // FORMATTING
+
+ function offset(token, separator) {
+ addFormatToken(token, 0, 0, function () {
+ var offset = this.utcOffset(),
+ sign = '+';
+ if (offset < 0) {
+ offset = -offset;
+ sign = '-';
+ }
+ return (
+ sign +
+ zeroFill(~~(offset / 60), 2) +
+ separator +
+ zeroFill(~~offset % 60, 2)
+ );
+ });
+ }
+
+ offset('Z', ':');
+ offset('ZZ', '');
+
+ // PARSING
+
+ addRegexToken('Z', matchShortOffset);
+ addRegexToken('ZZ', matchShortOffset);
+ addParseToken(['Z', 'ZZ'], function (input, array, config) {
+ config._useUTC = true;
+ config._tzm = offsetFromString(matchShortOffset, input);
+ });
+
+ // HELPERS
+
+ // timezone chunker
+ // '+10:00' > ['10', '00']
+ // '-1530' > ['-15', '30']
+ var chunkOffset = /([\+\-]|\d\d)/gi;
+
+ function offsetFromString(matcher, string) {
+ var matches = (string || '').match(matcher),
+ chunk,
+ parts,
+ minutes;
+
+ if (matches === null) {
+ return null;
+ }
+
+ chunk = matches[matches.length - 1] || [];
+ parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
+ minutes = +(parts[1] * 60) + toInt(parts[2]);
+
+ return minutes === 0 ? 0 : parts[0] === '+' ? minutes : -minutes;
+ }
+
+ // Return a moment from input, that is local/utc/zone equivalent to model.
+ function cloneWithOffset(input, model) {
+ var res, diff;
+ if (model._isUTC) {
+ res = model.clone();
+ diff =
+ (isMoment(input) || isDate(input)
+ ? input.valueOf()
+ : createLocal(input).valueOf()) - res.valueOf();
+ // Use low-level api, because this fn is low-level api.
+ res._d.setTime(res._d.valueOf() + diff);
+ hooks.updateOffset(res, false);
+ return res;
+ } else {
+ return createLocal(input).local();
+ }
+ }
+
+ function getDateOffset(m) {
+ // On Firefox.24 Date#getTimezoneOffset returns a floating point.
+ // https://github.com/moment/moment/pull/1871
+ return -Math.round(m._d.getTimezoneOffset());
+ }
+
+ // HOOKS
+
+ // This function will be called whenever a moment is mutated.
+ // It is intended to keep the offset in sync with the timezone.
+ hooks.updateOffset = function () {};
+
+ // 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 getSetOffset(input, keepLocalTime, keepMinutes) {
+ var offset = this._offset || 0,
+ localAdjust;
+ if (!this.isValid()) {
+ return input != null ? this : NaN;
+ }
+ if (input != null) {
+ if (typeof input === 'string') {
+ input = offsetFromString(matchShortOffset, input);
+ if (input === null) {
+ return this;
+ }
+ } else if (Math.abs(input) < 16 && !keepMinutes) {
+ input = input * 60;
+ }
+ if (!this._isUTC && keepLocalTime) {
+ localAdjust = getDateOffset(this);
+ }
+ this._offset = input;
+ this._isUTC = true;
+ if (localAdjust != null) {
+ this.add(localAdjust, 'm');
+ }
+ if (offset !== input) {
+ if (!keepLocalTime || this._changeInProgress) {
+ addSubtract(
+ this,
+ createDuration(input - offset, 'm'),
+ 1,
+ false
+ );
+ } else if (!this._changeInProgress) {
+ this._changeInProgress = true;
+ hooks.updateOffset(this, true);
+ this._changeInProgress = null;
+ }
+ }
+ return this;
+ } else {
+ return this._isUTC ? offset : getDateOffset(this);
+ }
+ }
+
+ function getSetZone(input, keepLocalTime) {
+ if (input != null) {
+ if (typeof input !== 'string') {
+ input = -input;
+ }
+
+ this.utcOffset(input, keepLocalTime);
+
+ return this;
+ } else {
+ return -this.utcOffset();
+ }
+ }
+
+ function setOffsetToUTC(keepLocalTime) {
+ return this.utcOffset(0, keepLocalTime);
+ }
+
+ function setOffsetToLocal(keepLocalTime) {
+ if (this._isUTC) {
+ this.utcOffset(0, keepLocalTime);
+ this._isUTC = false;
+
+ if (keepLocalTime) {
+ this.subtract(getDateOffset(this), 'm');
+ }
+ }
+ return this;
+ }
+
+ function setOffsetToParsedOffset() {
+ if (this._tzm != null) {
+ this.utcOffset(this._tzm, false, true);
+ } else if (typeof this._i === 'string') {
+ var tZone = offsetFromString(matchOffset, this._i);
+ if (tZone != null) {
+ this.utcOffset(tZone);
+ } else {
+ this.utcOffset(0, true);
+ }
+ }
+ return this;
+ }
+
+ function hasAlignedHourOffset(input) {
+ if (!this.isValid()) {
+ return false;
+ }
+ input = input ? createLocal(input).utcOffset() : 0;
+
+ return (this.utcOffset() - input) % 60 === 0;
+ }
+
+ function isDaylightSavingTime() {
+ return (
+ this.utcOffset() > this.clone().month(0).utcOffset() ||
+ this.utcOffset() > this.clone().month(5).utcOffset()
+ );
+ }
+
+ function isDaylightSavingTimeShifted() {
+ if (!isUndefined(this._isDSTShifted)) {
+ return this._isDSTShifted;
+ }
+
+ var c = {},
+ other;
+
+ copyConfig(c, this);
+ c = prepareConfig(c);
+
+ if (c._a) {
+ other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
+ this._isDSTShifted =
+ this.isValid() && compareArrays(c._a, other.toArray()) > 0;
+ } else {
+ this._isDSTShifted = false;
+ }
+
+ return this._isDSTShifted;
+ }
+
+ function isLocal() {
+ return this.isValid() ? !this._isUTC : false;
+ }
+
+ function isUtcOffset() {
+ return this.isValid() ? this._isUTC : false;
+ }
+
+ function isUtc() {
+ return this.isValid() ? this._isUTC && this._offset === 0 : false;
+ }
+
+ // ASP.NET json date format regex
+ var aspNetRegex = /^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,
+ // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
+ // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
+ // and further modified to allow for strings containing both week and day
+ isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
+
+ function createDuration(input, key) {
+ var duration = input,
+ // matching against regexp is expensive, do it on demand
+ match = null,
+ sign,
+ ret,
+ diffRes;
+
+ if (isDuration(input)) {
+ duration = {
+ ms: input._milliseconds,
+ d: input._days,
+ M: input._months,
+ };
+ } else if (isNumber(input) || !isNaN(+input)) {
+ duration = {};
+ if (key) {
+ duration[key] = +input;
+ } else {
+ duration.milliseconds = +input;
+ }
+ } else if ((match = aspNetRegex.exec(input))) {
+ sign = match[1] === '-' ? -1 : 1;
+ duration = {
+ y: 0,
+ d: toInt(match[DATE]) * sign,
+ h: toInt(match[HOUR]) * sign,
+ m: toInt(match[MINUTE]) * sign,
+ s: toInt(match[SECOND]) * sign,
+ ms: toInt(absRound(match[MILLISECOND] * 1000)) * sign, // the millisecond decimal point is included in the match
+ };
+ } else if ((match = isoRegex.exec(input))) {
+ sign = match[1] === '-' ? -1 : 1;
+ duration = {
+ y: parseIso(match[2], sign),
+ M: parseIso(match[3], sign),
+ w: parseIso(match[4], sign),
+ d: parseIso(match[5], sign),
+ h: parseIso(match[6], sign),
+ m: parseIso(match[7], sign),
+ s: parseIso(match[8], sign),
+ };
+ } else if (duration == null) {
+ // checks for null or undefined
+ duration = {};
+ } else if (
+ typeof duration === 'object' &&
+ ('from' in duration || 'to' in duration)
+ ) {
+ diffRes = momentsDifference(
+ createLocal(duration.from),
+ createLocal(duration.to)
+ );
+
+ duration = {};
+ duration.ms = diffRes.milliseconds;
+ duration.M = diffRes.months;
+ }
+
+ ret = new Duration(duration);
+
+ if (isDuration(input) && hasOwnProp(input, '_locale')) {
+ ret._locale = input._locale;
+ }
+
+ if (isDuration(input) && hasOwnProp(input, '_isValid')) {
+ ret._isValid = input._isValid;
+ }
+
+ return ret;
+ }
+
+ createDuration.fn = Duration.prototype;
+ createDuration.invalid = createInvalid$1;
+
+ function parseIso(inp, sign) {
+ // 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 res = inp && parseFloat(inp.replace(',', '.'));
+ // apply sign while we're at it
+ return (isNaN(res) ? 0 : res) * sign;
+ }
+
+ function positiveMomentsDifference(base, other) {
+ var res = {};
+
+ res.months =
+ other.month() - base.month() + (other.year() - base.year()) * 12;
+ if (base.clone().add(res.months, 'M').isAfter(other)) {
+ --res.months;
+ }
+
+ res.milliseconds = +other - +base.clone().add(res.months, 'M');
+
+ return res;
+ }
+
+ function momentsDifference(base, other) {
+ var res;
+ if (!(base.isValid() && other.isValid())) {
+ return { milliseconds: 0, months: 0 };
+ }
+
+ other = cloneWithOffset(other, base);
+ if (base.isBefore(other)) {
+ res = positiveMomentsDifference(base, other);
+ } else {
+ res = positiveMomentsDifference(other, base);
+ res.milliseconds = -res.milliseconds;
+ res.months = -res.months;
+ }
+
+ return res;
+ }
+
+ // TODO: remove 'name' arg after deprecation is removed
+ function createAdder(direction, name) {
+ return function (val, period) {
+ var dur, tmp;
+ //invert the arguments, but complain about it
+ if (period !== null && !isNaN(+period)) {
+ deprecateSimple(
+ name,
+ 'moment().' +
+ name +
+ '(period, number) is deprecated. Please use moment().' +
+ name +
+ '(number, period). ' +
+ 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'
+ );
+ tmp = val;
+ val = period;
+ period = tmp;
+ }
+
+ dur = createDuration(val, period);
+ addSubtract(this, dur, direction);
+ return this;
+ };
+ }
+
+ function addSubtract(mom, duration, isAdding, updateOffset) {
+ var milliseconds = duration._milliseconds,
+ days = absRound(duration._days),
+ months = absRound(duration._months);
+
+ if (!mom.isValid()) {
+ // No op
+ return;
+ }
+
+ updateOffset = updateOffset == null ? true : updateOffset;
+
+ if (months) {
+ setMonth(mom, get(mom, 'Month') + months * isAdding);
+ }
+ if (days) {
+ set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
+ }
+ if (milliseconds) {
+ mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
+ }
+ if (updateOffset) {
+ hooks.updateOffset(mom, days || months);
+ }
+ }
+
+ var add = createAdder(1, 'add'),
+ subtract = createAdder(-1, 'subtract');
+
+ function isString(input) {
+ return typeof input === 'string' || input instanceof String;
+ }
+
+ // type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | void; // null | undefined
+ function isMomentInput(input) {
+ return (
+ isMoment(input) ||
+ isDate(input) ||
+ isString(input) ||
+ isNumber(input) ||
+ isNumberOrStringArray(input) ||
+ isMomentInputObject(input) ||
+ input === null ||
+ input === undefined
+ );
+ }
+
+ function isMomentInputObject(input) {
+ var objectTest = isObject(input) && !isObjectEmpty(input),
+ propertyTest = false,
+ properties = [
+ 'years',
+ 'year',
+ 'y',
+ 'months',
+ 'month',
+ 'M',
+ 'days',
+ 'day',
+ 'd',
+ 'dates',
+ 'date',
+ 'D',
+ 'hours',
+ 'hour',
+ 'h',
+ 'minutes',
+ 'minute',
+ 'm',
+ 'seconds',
+ 'second',
+ 's',
+ 'milliseconds',
+ 'millisecond',
+ 'ms',
+ ],
+ i,
+ property;
+
+ for (i = 0; i < properties.length; i += 1) {
+ property = properties[i];
+ propertyTest = propertyTest || hasOwnProp(input, property);
+ }
+
+ return objectTest && propertyTest;
+ }
+
+ function isNumberOrStringArray(input) {
+ var arrayTest = isArray(input),
+ dataTypeTest = false;
+ if (arrayTest) {
+ dataTypeTest =
+ input.filter(function (item) {
+ return !isNumber(item) && isString(input);
+ }).length === 0;
+ }
+ return arrayTest && dataTypeTest;
+ }
+
+ function isCalendarSpec(input) {
+ var objectTest = isObject(input) && !isObjectEmpty(input),
+ propertyTest = false,
+ properties = [
+ 'sameDay',
+ 'nextDay',
+ 'lastDay',
+ 'nextWeek',
+ 'lastWeek',
+ 'sameElse',
+ ],
+ i,
+ property;
+
+ for (i = 0; i < properties.length; i += 1) {
+ property = properties[i];
+ propertyTest = propertyTest || hasOwnProp(input, property);
+ }
+
+ return objectTest && propertyTest;
+ }
+
+ function getCalendarFormat(myMoment, now) {
+ var diff = myMoment.diff(now, 'days', true);
+ return diff < -6
+ ? 'sameElse'
+ : diff < -1
+ ? 'lastWeek'
+ : diff < 0
+ ? 'lastDay'
+ : diff < 1
+ ? 'sameDay'
+ : diff < 2
+ ? 'nextDay'
+ : diff < 7
+ ? 'nextWeek'
+ : 'sameElse';
+ }
+
+ function calendar$1(time, formats) {
+ // Support for single parameter, formats only overload to the calendar function
+ if (arguments.length === 1) {
+ if (!arguments[0]) {
+ time = undefined;
+ formats = undefined;
+ } else if (isMomentInput(arguments[0])) {
+ time = arguments[0];
+ formats = undefined;
+ } else if (isCalendarSpec(arguments[0])) {
+ formats = arguments[0];
+ time = undefined;
+ }
+ }
+ // 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 now = time || createLocal(),
+ sod = cloneWithOffset(now, this).startOf('day'),
+ format = hooks.calendarFormat(this, sod) || 'sameElse',
+ output =
+ formats &&
+ (isFunction(formats[format])
+ ? formats[format].call(this, now)
+ : formats[format]);
+
+ return this.format(
+ output || this.localeData().calendar(format, this, createLocal(now))
+ );
+ }
+
+ function clone() {
+ return new Moment(this);
+ }
+
+ function isAfter(input, units) {
+ var localInput = isMoment(input) ? input : createLocal(input);
+ if (!(this.isValid() && localInput.isValid())) {
+ return false;
+ }
+ units = normalizeUnits(units) || 'millisecond';
+ if (units === 'millisecond') {
+ return this.valueOf() > localInput.valueOf();
+ } else {
+ return localInput.valueOf() < this.clone().startOf(units).valueOf();
+ }
+ }
+
+ function isBefore(input, units) {
+ var localInput = isMoment(input) ? input : createLocal(input);
+ if (!(this.isValid() && localInput.isValid())) {
+ return false;
+ }
+ units = normalizeUnits(units) || 'millisecond';
+ if (units === 'millisecond') {
+ return this.valueOf() < localInput.valueOf();
+ } else {
+ return this.clone().endOf(units).valueOf() < localInput.valueOf();
+ }
+ }
+
+ function isBetween(from, to, units, inclusivity) {
+ var localFrom = isMoment(from) ? from : createLocal(from),
+ localTo = isMoment(to) ? to : createLocal(to);
+ if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
+ return false;
+ }
+ inclusivity = inclusivity || '()';
+ return (
+ (inclusivity[0] === '('
+ ? this.isAfter(localFrom, units)
+ : !this.isBefore(localFrom, units)) &&
+ (inclusivity[1] === ')'
+ ? this.isBefore(localTo, units)
+ : !this.isAfter(localTo, units))
+ );
+ }
+
+ function isSame(input, units) {
+ var localInput = isMoment(input) ? input : createLocal(input),
+ inputMs;
+ if (!(this.isValid() && localInput.isValid())) {
+ return false;
+ }
+ units = normalizeUnits(units) || 'millisecond';
+ if (units === 'millisecond') {
+ return this.valueOf() === localInput.valueOf();
+ } else {
+ inputMs = localInput.valueOf();
+ return (
+ this.clone().startOf(units).valueOf() <= inputMs &&
+ inputMs <= this.clone().endOf(units).valueOf()
+ );
+ }
+ }
+
+ function isSameOrAfter(input, units) {
+ return this.isSame(input, units) || this.isAfter(input, units);
+ }
+
+ function isSameOrBefore(input, units) {
+ return this.isSame(input, units) || this.isBefore(input, units);
+ }
+
+ function diff(input, units, asFloat) {
+ var that, zoneDelta, output;
+
+ if (!this.isValid()) {
+ return NaN;
+ }
+
+ that = cloneWithOffset(input, this);
+
+ if (!that.isValid()) {
+ return NaN;
+ }
+
+ zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
+
+ units = normalizeUnits(units);
+
+ switch (units) {
+ case 'year':
+ output = monthDiff(this, that) / 12;
+ break;
+ case 'month':
+ output = monthDiff(this, that);
+ break;
+ case 'quarter':
+ output = monthDiff(this, that) / 3;
+ break;
+ case 'second':
+ output = (this - that) / 1e3;
+ break; // 1000
+ case 'minute':
+ output = (this - that) / 6e4;
+ break; // 1000 * 60
+ case 'hour':
+ output = (this - that) / 36e5;
+ break; // 1000 * 60 * 60
+ case 'day':
+ output = (this - that - zoneDelta) / 864e5;
+ break; // 1000 * 60 * 60 * 24, negate dst
+ case 'week':
+ output = (this - that - zoneDelta) / 6048e5;
+ break; // 1000 * 60 * 60 * 24 * 7, negate dst
+ default:
+ output = this - that;
+ }
+
+ return asFloat ? output : absFloor(output);
+ }
+
+ function monthDiff(a, b) {
+ if (a.date() < b.date()) {
+ // end-of-month calculations work correct when the start month has more
+ // days than the end month.
+ return -monthDiff(b, a);
+ }
+ // difference in months
+ var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()),
+ // b is in (anchor - 1 month, anchor + 1 month)
+ anchor = a.clone().add(wholeMonthDiff, 'months'),
+ anchor2,
+ adjust;
+
+ if (b - anchor < 0) {
+ anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
+ // linear across the month
+ adjust = (b - anchor) / (anchor - anchor2);
+ } else {
+ anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
+ // linear across the month
+ adjust = (b - anchor) / (anchor2 - anchor);
+ }
+
+ //check for negative zero, return zero if negative zero
+ return -(wholeMonthDiff + adjust) || 0;
+ }
+
+ hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
+ hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
+
+ function toString() {
+ return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
+ }
+
+ function toISOString(keepOffset) {
+ if (!this.isValid()) {
+ return null;
+ }
+ var utc = keepOffset !== true,
+ m = utc ? this.clone().utc() : this;
+ if (m.year() < 0 || m.year() > 9999) {
+ return formatMoment(
+ m,
+ utc
+ ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'
+ : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ'
+ );
+ }
+ if (isFunction(Date.prototype.toISOString)) {
+ // native implementation is ~50x faster, use it when we can
+ if (utc) {
+ return this.toDate().toISOString();
+ } else {
+ return new Date(this.valueOf() + this.utcOffset() * 60 * 1000)
+ .toISOString()
+ .replace('Z', formatMoment(m, 'Z'));
+ }
+ }
+ return formatMoment(
+ m,
+ utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ'
+ );
+ }
+
+ /**
+ * Return a human readable representation of a moment that can
+ * also be evaluated to get a new moment which is the same
+ *
+ * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
+ */
+ function inspect() {
+ if (!this.isValid()) {
+ return 'moment.invalid(/* ' + this._i + ' */)';
+ }
+ var func = 'moment',
+ zone = '',
+ prefix,
+ year,
+ datetime,
+ suffix;
+ if (!this.isLocal()) {
+ func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
+ zone = 'Z';
+ }
+ prefix = '[' + func + '("]';
+ year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY';
+ datetime = '-MM-DD[T]HH:mm:ss.SSS';
+ suffix = zone + '[")]';
+
+ return this.format(prefix + year + datetime + suffix);
+ }
+
+ function format(inputString) {
+ if (!inputString) {
+ inputString = this.isUtc()
+ ? hooks.defaultFormatUtc
+ : hooks.defaultFormat;
+ }
+ var output = formatMoment(this, inputString);
+ return this.localeData().postformat(output);
+ }
+
+ function from(time, withoutSuffix) {
+ if (
+ this.isValid() &&
+ ((isMoment(time) && time.isValid()) || createLocal(time).isValid())
+ ) {
+ return createDuration({ to: this, from: time })
+ .locale(this.locale())
+ .humanize(!withoutSuffix);
+ } else {
+ return this.localeData().invalidDate();
+ }
+ }
+
+ function fromNow(withoutSuffix) {
+ return this.from(createLocal(), withoutSuffix);
+ }
+
+ function to(time, withoutSuffix) {
+ if (
+ this.isValid() &&
+ ((isMoment(time) && time.isValid()) || createLocal(time).isValid())
+ ) {
+ return createDuration({ from: this, to: time })
+ .locale(this.locale())
+ .humanize(!withoutSuffix);
+ } else {
+ return this.localeData().invalidDate();
+ }
+ }
+
+ function toNow(withoutSuffix) {
+ return this.to(createLocal(), withoutSuffix);
+ }
+
+ // 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 locale(key) {
+ var newLocaleData;
+
+ if (key === undefined) {
+ return this._locale._abbr;
+ } else {
+ newLocaleData = getLocale(key);
+ if (newLocaleData != null) {
+ this._locale = newLocaleData;
+ }
+ return this;
+ }
+ }
+
+ var lang = deprecate(
+ 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
+ function (key) {
+ if (key === undefined) {
+ return this.localeData();
+ } else {
+ return this.locale(key);
+ }
+ }
+ );
+
+ function localeData() {
+ return this._locale;
+ }
+
+ var MS_PER_SECOND = 1000,
+ MS_PER_MINUTE = 60 * MS_PER_SECOND,
+ MS_PER_HOUR = 60 * MS_PER_MINUTE,
+ MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;
+
+ // actual modulo - handles negative numbers (for dates before 1970):
+ function mod$1(dividend, divisor) {
+ return ((dividend % divisor) + divisor) % divisor;
+ }
+
+ function localStartOfDate(y, m, d) {
+ // the date constructor remaps years 0-99 to 1900-1999
+ if (y < 100 && y >= 0) {
+ // preserve leap years using a full 400 year cycle, then reset
+ return new Date(y + 400, m, d) - MS_PER_400_YEARS;
+ } else {
+ return new Date(y, m, d).valueOf();
+ }
+ }
+
+ function utcStartOfDate(y, m, d) {
+ // Date.UTC remaps years 0-99 to 1900-1999
+ if (y < 100 && y >= 0) {
+ // preserve leap years using a full 400 year cycle, then reset
+ return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
+ } else {
+ return Date.UTC(y, m, d);
+ }
+ }
+
+ function startOf(units) {
+ var time, startOfDate;
+ units = normalizeUnits(units);
+ if (units === undefined || units === 'millisecond' || !this.isValid()) {
+ return this;
+ }
+
+ startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
+
+ switch (units) {
+ case 'year':
+ time = startOfDate(this.year(), 0, 1);
+ break;
+ case 'quarter':
+ time = startOfDate(
+ this.year(),
+ this.month() - (this.month() % 3),
+ 1
+ );
+ break;
+ case 'month':
+ time = startOfDate(this.year(), this.month(), 1);
+ break;
+ case 'week':
+ time = startOfDate(
+ this.year(),
+ this.month(),
+ this.date() - this.weekday()
+ );
+ break;
+ case 'isoWeek':
+ time = startOfDate(
+ this.year(),
+ this.month(),
+ this.date() - (this.isoWeekday() - 1)
+ );
+ break;
+ case 'day':
+ case 'date':
+ time = startOfDate(this.year(), this.month(), this.date());
+ break;
+ case 'hour':
+ time = this._d.valueOf();
+ time -= mod$1(
+ time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
+ MS_PER_HOUR
+ );
+ break;
+ case 'minute':
+ time = this._d.valueOf();
+ time -= mod$1(time, MS_PER_MINUTE);
+ break;
+ case 'second':
+ time = this._d.valueOf();
+ time -= mod$1(time, MS_PER_SECOND);
+ break;
+ }
+
+ this._d.setTime(time);
+ hooks.updateOffset(this, true);
+ return this;
+ }
+
+ function endOf(units) {
+ var time, startOfDate;
+ units = normalizeUnits(units);
+ if (units === undefined || units === 'millisecond' || !this.isValid()) {
+ return this;
+ }
+
+ startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
+
+ switch (units) {
+ case 'year':
+ time = startOfDate(this.year() + 1, 0, 1) - 1;
+ break;
+ case 'quarter':
+ time =
+ startOfDate(
+ this.year(),
+ this.month() - (this.month() % 3) + 3,
+ 1
+ ) - 1;
+ break;
+ case 'month':
+ time = startOfDate(this.year(), this.month() + 1, 1) - 1;
+ break;
+ case 'week':
+ time =
+ startOfDate(
+ this.year(),
+ this.month(),
+ this.date() - this.weekday() + 7
+ ) - 1;
+ break;
+ case 'isoWeek':
+ time =
+ startOfDate(
+ this.year(),
+ this.month(),
+ this.date() - (this.isoWeekday() - 1) + 7
+ ) - 1;
+ break;
+ case 'day':
+ case 'date':
+ time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
+ break;
+ case 'hour':
+ time = this._d.valueOf();
+ time +=
+ MS_PER_HOUR -
+ mod$1(
+ time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
+ MS_PER_HOUR
+ ) -
+ 1;
+ break;
+ case 'minute':
+ time = this._d.valueOf();
+ time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
+ break;
+ case 'second':
+ time = this._d.valueOf();
+ time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
+ break;
+ }
+
+ this._d.setTime(time);
+ hooks.updateOffset(this, true);
+ return this;
+ }
+
+ function valueOf() {
+ return this._d.valueOf() - (this._offset || 0) * 60000;
+ }
+
+ function unix() {
+ return Math.floor(this.valueOf() / 1000);
+ }
+
+ function toDate() {
+ return new Date(this.valueOf());
+ }
+
+ function toArray() {
+ var m = this;
+ return [
+ m.year(),
+ m.month(),
+ m.date(),
+ m.hour(),
+ m.minute(),
+ m.second(),
+ m.millisecond(),
+ ];
+ }
+
+ function toObject() {
+ var m = this;
+ return {
+ years: m.year(),
+ months: m.month(),
+ date: m.date(),
+ hours: m.hours(),
+ minutes: m.minutes(),
+ seconds: m.seconds(),
+ milliseconds: m.milliseconds(),
+ };
+ }
+
+ function toJSON() {
+ // new Date(NaN).toJSON() === null
+ return this.isValid() ? this.toISOString() : null;
+ }
+
+ function isValid$2() {
+ return isValid(this);
+ }
+
+ function parsingFlags() {
+ return extend({}, getParsingFlags(this));
+ }
+
+ function invalidAt() {
+ return getParsingFlags(this).overflow;
+ }
+
+ function creationData() {
+ return {
+ input: this._i,
+ format: this._f,
+ locale: this._locale,
+ isUTC: this._isUTC,
+ strict: this._strict,
+ };
+ }
+
+ addFormatToken('N', 0, 0, 'eraAbbr');
+ addFormatToken('NN', 0, 0, 'eraAbbr');
+ addFormatToken('NNN', 0, 0, 'eraAbbr');
+ addFormatToken('NNNN', 0, 0, 'eraName');
+ addFormatToken('NNNNN', 0, 0, 'eraNarrow');
+
+ addFormatToken('y', ['y', 1], 'yo', 'eraYear');
+ addFormatToken('y', ['yy', 2], 0, 'eraYear');
+ addFormatToken('y', ['yyy', 3], 0, 'eraYear');
+ addFormatToken('y', ['yyyy', 4], 0, 'eraYear');
+
+ addRegexToken('N', matchEraAbbr);
+ addRegexToken('NN', matchEraAbbr);
+ addRegexToken('NNN', matchEraAbbr);
+ addRegexToken('NNNN', matchEraName);
+ addRegexToken('NNNNN', matchEraNarrow);
+
+ addParseToken(['N', 'NN', 'NNN', 'NNNN', 'NNNNN'], function (
+ input,
+ array,
+ config,
+ token
+ ) {
+ var era = config._locale.erasParse(input, token, config._strict);
+ if (era) {
+ getParsingFlags(config).era = era;
+ } else {
+ getParsingFlags(config).invalidEra = input;
+ }
+ });
+
+ addRegexToken('y', matchUnsigned);
+ addRegexToken('yy', matchUnsigned);
+ addRegexToken('yyy', matchUnsigned);
+ addRegexToken('yyyy', matchUnsigned);
+ addRegexToken('yo', matchEraYearOrdinal);
+
+ addParseToken(['y', 'yy', 'yyy', 'yyyy'], YEAR);
+ addParseToken(['yo'], function (input, array, config, token) {
+ var match;
+ if (config._locale._eraYearOrdinalRegex) {
+ match = input.match(config._locale._eraYearOrdinalRegex);
+ }
+
+ if (config._locale.eraYearOrdinalParse) {
+ array[YEAR] = config._locale.eraYearOrdinalParse(input, match);
+ } else {
+ array[YEAR] = parseInt(input, 10);
+ }
+ });
+
+ function localeEras(m, format) {
+ var i,
+ l,
+ date,
+ eras = this._eras || getLocale('en')._eras;
+ for (i = 0, l = eras.length; i < l; ++i) {
+ switch (typeof eras[i].since) {
+ case 'string':
+ // truncate time
+ date = hooks(eras[i].since).startOf('day');
+ eras[i].since = date.valueOf();
+ break;
+ }
+
+ switch (typeof eras[i].until) {
+ case 'undefined':
+ eras[i].until = +Infinity;
+ break;
+ case 'string':
+ // truncate time
+ date = hooks(eras[i].until).startOf('day').valueOf();
+ eras[i].until = date.valueOf();
+ break;
+ }
+ }
+ return eras;
+ }
+
+ function localeErasParse(eraName, format, strict) {
+ var i,
+ l,
+ eras = this.eras(),
+ name,
+ abbr,
+ narrow;
+ eraName = eraName.toUpperCase();
+
+ for (i = 0, l = eras.length; i < l; ++i) {
+ name = eras[i].name.toUpperCase();
+ abbr = eras[i].abbr.toUpperCase();
+ narrow = eras[i].narrow.toUpperCase();
+
+ if (strict) {
+ switch (format) {
+ case 'N':
+ case 'NN':
+ case 'NNN':
+ if (abbr === eraName) {
+ return eras[i];
+ }
+ break;
+
+ case 'NNNN':
+ if (name === eraName) {
+ return eras[i];
+ }
+ break;
+
+ case 'NNNNN':
+ if (narrow === eraName) {
+ return eras[i];
+ }
+ break;
+ }
+ } else if ([name, abbr, narrow].indexOf(eraName) >= 0) {
+ return eras[i];
+ }
+ }
+ }
+
+ function localeErasConvertYear(era, year) {
+ var dir = era.since <= era.until ? +1 : -1;
+ if (year === undefined) {
+ return hooks(era.since).year();
+ } else {
+ return hooks(era.since).year() + (year - era.offset) * dir;
+ }
+ }
+
+ function getEraName() {
+ var i,
+ l,
+ val,
+ eras = this.localeData().eras();
+ for (i = 0, l = eras.length; i < l; ++i) {
+ // truncate time
+ val = this.clone().startOf('day').valueOf();
+
+ if (eras[i].since <= val && val <= eras[i].until) {
+ return eras[i].name;
+ }
+ if (eras[i].until <= val && val <= eras[i].since) {
+ return eras[i].name;
+ }
+ }
+
+ return '';
+ }
+
+ function getEraNarrow() {
+ var i,
+ l,
+ val,
+ eras = this.localeData().eras();
+ for (i = 0, l = eras.length; i < l; ++i) {
+ // truncate time
+ val = this.clone().startOf('day').valueOf();
+
+ if (eras[i].since <= val && val <= eras[i].until) {
+ return eras[i].narrow;
+ }
+ if (eras[i].until <= val && val <= eras[i].since) {
+ return eras[i].narrow;
+ }
+ }
+
+ return '';
+ }
+
+ function getEraAbbr() {
+ var i,
+ l,
+ val,
+ eras = this.localeData().eras();
+ for (i = 0, l = eras.length; i < l; ++i) {
+ // truncate time
+ val = this.clone().startOf('day').valueOf();
+
+ if (eras[i].since <= val && val <= eras[i].until) {
+ return eras[i].abbr;
+ }
+ if (eras[i].until <= val && val <= eras[i].since) {
+ return eras[i].abbr;
+ }
+ }
+
+ return '';
+ }
+
+ function getEraYear() {
+ var i,
+ l,
+ dir,
+ val,
+ eras = this.localeData().eras();
+ for (i = 0, l = eras.length; i < l; ++i) {
+ dir = eras[i].since <= eras[i].until ? +1 : -1;
+
+ // truncate time
+ val = this.clone().startOf('day').valueOf();
+
+ if (
+ (eras[i].since <= val && val <= eras[i].until) ||
+ (eras[i].until <= val && val <= eras[i].since)
+ ) {
+ return (
+ (this.year() - hooks(eras[i].since).year()) * dir +
+ eras[i].offset
+ );
+ }
+ }
+
+ return this.year();
+ }
+
+ function erasNameRegex(isStrict) {
+ if (!hasOwnProp(this, '_erasNameRegex')) {
+ computeErasParse.call(this);
+ }
+ return isStrict ? this._erasNameRegex : this._erasRegex;
+ }
+
+ function erasAbbrRegex(isStrict) {
+ if (!hasOwnProp(this, '_erasAbbrRegex')) {
+ computeErasParse.call(this);
+ }
+ return isStrict ? this._erasAbbrRegex : this._erasRegex;
+ }
+
+ function erasNarrowRegex(isStrict) {
+ if (!hasOwnProp(this, '_erasNarrowRegex')) {
+ computeErasParse.call(this);
+ }
+ return isStrict ? this._erasNarrowRegex : this._erasRegex;
+ }
+
+ function matchEraAbbr(isStrict, locale) {
+ return locale.erasAbbrRegex(isStrict);
+ }
+
+ function matchEraName(isStrict, locale) {
+ return locale.erasNameRegex(isStrict);
+ }
+
+ function matchEraNarrow(isStrict, locale) {
+ return locale.erasNarrowRegex(isStrict);
+ }
+
+ function matchEraYearOrdinal(isStrict, locale) {
+ return locale._eraYearOrdinalRegex || matchUnsigned;
+ }
+
+ function computeErasParse() {
+ var abbrPieces = [],
+ namePieces = [],
+ narrowPieces = [],
+ mixedPieces = [],
+ i,
+ l,
+ eras = this.eras();
+
+ for (i = 0, l = eras.length; i < l; ++i) {
+ namePieces.push(regexEscape(eras[i].name));
+ abbrPieces.push(regexEscape(eras[i].abbr));
+ narrowPieces.push(regexEscape(eras[i].narrow));
+
+ mixedPieces.push(regexEscape(eras[i].name));
+ mixedPieces.push(regexEscape(eras[i].abbr));
+ mixedPieces.push(regexEscape(eras[i].narrow));
+ }
+
+ this._erasRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
+ this._erasNameRegex = new RegExp('^(' + namePieces.join('|') + ')', 'i');
+ this._erasAbbrRegex = new RegExp('^(' + abbrPieces.join('|') + ')', 'i');
+ this._erasNarrowRegex = new RegExp(
+ '^(' + narrowPieces.join('|') + ')',
+ 'i'
+ );
+ }
+
+ // FORMATTING
+
+ addFormatToken(0, ['gg', 2], 0, function () {
+ return this.weekYear() % 100;
+ });
+
+ addFormatToken(0, ['GG', 2], 0, function () {
+ return this.isoWeekYear() % 100;
+ });
+
+ function addWeekYearFormatToken(token, getter) {
+ addFormatToken(0, [token, token.length], 0, getter);
+ }
+
+ addWeekYearFormatToken('gggg', 'weekYear');
+ addWeekYearFormatToken('ggggg', 'weekYear');
+ addWeekYearFormatToken('GGGG', 'isoWeekYear');
+ addWeekYearFormatToken('GGGGG', 'isoWeekYear');
+
+ // ALIASES
+
+ addUnitAlias('weekYear', 'gg');
+ addUnitAlias('isoWeekYear', 'GG');
+
+ // PRIORITY
+
+ addUnitPriority('weekYear', 1);
+ addUnitPriority('isoWeekYear', 1);
+
+ // PARSING
+
+ addRegexToken('G', matchSigned);
+ addRegexToken('g', matchSigned);
+ addRegexToken('GG', match1to2, match2);
+ addRegexToken('gg', match1to2, match2);
+ addRegexToken('GGGG', match1to4, match4);
+ addRegexToken('gggg', match1to4, match4);
+ addRegexToken('GGGGG', match1to6, match6);
+ addRegexToken('ggggg', match1to6, match6);
+
+ addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (
+ input,
+ week,
+ config,
+ token
+ ) {
+ week[token.substr(0, 2)] = toInt(input);
+ });
+
+ addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
+ week[token] = hooks.parseTwoDigitYear(input);
+ });
+
+ // MOMENTS
+
+ function getSetWeekYear(input) {
+ return getSetWeekYearHelper.call(
+ this,
+ input,
+ this.week(),
+ this.weekday(),
+ this.localeData()._week.dow,
+ this.localeData()._week.doy
+ );
+ }
+
+ function getSetISOWeekYear(input) {
+ return getSetWeekYearHelper.call(
+ this,
+ input,
+ this.isoWeek(),
+ this.isoWeekday(),
+ 1,
+ 4
+ );
+ }
+
+ function getISOWeeksInYear() {
+ return weeksInYear(this.year(), 1, 4);
+ }
+
+ function getISOWeeksInISOWeekYear() {
+ return weeksInYear(this.isoWeekYear(), 1, 4);
+ }
+
+ function getWeeksInYear() {
+ var weekInfo = this.localeData()._week;
+ return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
+ }
+
+ function getWeeksInWeekYear() {
+ var weekInfo = this.localeData()._week;
+ return weeksInYear(this.weekYear(), weekInfo.dow, weekInfo.doy);
+ }
+
+ function getSetWeekYearHelper(input, week, weekday, dow, doy) {
+ var weeksTarget;
+ if (input == null) {
+ return weekOfYear(this, dow, doy).year;
+ } else {
+ weeksTarget = weeksInYear(input, dow, doy);
+ if (week > weeksTarget) {
+ week = weeksTarget;
+ }
+ return setWeekAll.call(this, input, week, weekday, dow, doy);
+ }
+ }
+
+ function setWeekAll(weekYear, week, weekday, dow, doy) {
+ var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
+ date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
+
+ this.year(date.getUTCFullYear());
+ this.month(date.getUTCMonth());
+ this.date(date.getUTCDate());
+ return this;
+ }
+
+ // FORMATTING
+
+ addFormatToken('Q', 0, 'Qo', 'quarter');
+
+ // ALIASES
+
+ addUnitAlias('quarter', 'Q');
+
+ // PRIORITY
+
+ addUnitPriority('quarter', 7);
+
+ // PARSING
+
+ addRegexToken('Q', match1);
+ addParseToken('Q', function (input, array) {
+ array[MONTH] = (toInt(input) - 1) * 3;
+ });
+
+ // MOMENTS
+
+ function getSetQuarter(input) {
+ return input == null
+ ? Math.ceil((this.month() + 1) / 3)
+ : this.month((input - 1) * 3 + (this.month() % 3));
+ }
+
+ // FORMATTING
+
+ addFormatToken('D', ['DD', 2], 'Do', 'date');
+
+ // ALIASES
+
+ addUnitAlias('date', 'D');
+
+ // PRIORITY
+ addUnitPriority('date', 9);
+
+ // PARSING
+
+ addRegexToken('D', match1to2);
+ addRegexToken('DD', match1to2, match2);
+ addRegexToken('Do', function (isStrict, locale) {
+ // TODO: Remove "ordinalParse" fallback in next major release.
+ return isStrict
+ ? locale._dayOfMonthOrdinalParse || locale._ordinalParse
+ : locale._dayOfMonthOrdinalParseLenient;
+ });
+
+ addParseToken(['D', 'DD'], DATE);
+ addParseToken('Do', function (input, array) {
+ array[DATE] = toInt(input.match(match1to2)[0]);
+ });
+
+ // MOMENTS
+
+ var getSetDayOfMonth = makeGetSet('Date', true);
+
+ // FORMATTING
+
+ addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
+
+ // ALIASES
+
+ addUnitAlias('dayOfYear', 'DDD');
+
+ // PRIORITY
+ addUnitPriority('dayOfYear', 4);
+
+ // PARSING
+
+ addRegexToken('DDD', match1to3);
+ addRegexToken('DDDD', match3);
+ addParseToken(['DDD', 'DDDD'], function (input, array, config) {
+ config._dayOfYear = toInt(input);
+ });
+
+ // HELPERS
+
+ // MOMENTS
+
+ function getSetDayOfYear(input) {
+ var dayOfYear =
+ Math.round(
+ (this.clone().startOf('day') - this.clone().startOf('year')) / 864e5
+ ) + 1;
+ return input == null ? dayOfYear : this.add(input - dayOfYear, 'd');
+ }
+
+ // FORMATTING
+
+ addFormatToken('m', ['mm', 2], 0, 'minute');
+
+ // ALIASES
+
+ addUnitAlias('minute', 'm');
+
+ // PRIORITY
+
+ addUnitPriority('minute', 14);
+
+ // PARSING
+
+ addRegexToken('m', match1to2);
+ addRegexToken('mm', match1to2, match2);
+ addParseToken(['m', 'mm'], MINUTE);
+
+ // MOMENTS
+
+ var getSetMinute = makeGetSet('Minutes', false);
+
+ // FORMATTING
+
+ addFormatToken('s', ['ss', 2], 0, 'second');
+
+ // ALIASES
+
+ addUnitAlias('second', 's');
+
+ // PRIORITY
+
+ addUnitPriority('second', 15);
+
+ // PARSING
+
+ addRegexToken('s', match1to2);
+ addRegexToken('ss', match1to2, match2);
+ addParseToken(['s', 'ss'], SECOND);
+
+ // MOMENTS
+
+ var getSetSecond = makeGetSet('Seconds', false);
+
+ // FORMATTING
+
+ addFormatToken('S', 0, 0, function () {
+ return ~~(this.millisecond() / 100);
+ });
+
+ addFormatToken(0, ['SS', 2], 0, function () {
+ return ~~(this.millisecond() / 10);
+ });
+
+ addFormatToken(0, ['SSS', 3], 0, 'millisecond');
+ addFormatToken(0, ['SSSS', 4], 0, function () {
+ return this.millisecond() * 10;
+ });
+ addFormatToken(0, ['SSSSS', 5], 0, function () {
+ return this.millisecond() * 100;
+ });
+ addFormatToken(0, ['SSSSSS', 6], 0, function () {
+ return this.millisecond() * 1000;
+ });
+ addFormatToken(0, ['SSSSSSS', 7], 0, function () {
+ return this.millisecond() * 10000;
+ });
+ addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
+ return this.millisecond() * 100000;
+ });
+ addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
+ return this.millisecond() * 1000000;
+ });
+
+ // ALIASES
+
+ addUnitAlias('millisecond', 'ms');
+
+ // PRIORITY
+
+ addUnitPriority('millisecond', 16);
+
+ // PARSING
+
+ addRegexToken('S', match1to3, match1);
+ addRegexToken('SS', match1to3, match2);
+ addRegexToken('SSS', match1to3, match3);
+
+ var token, getSetMillisecond;
+ for (token = 'SSSS'; token.length <= 9; token += 'S') {
+ addRegexToken(token, matchUnsigned);
+ }
+
+ function parseMs(input, array) {
+ array[MILLISECOND] = toInt(('0.' + input) * 1000);
+ }
+
+ for (token = 'S'; token.length <= 9; token += 'S') {
+ addParseToken(token, parseMs);
+ }
+
+ getSetMillisecond = makeGetSet('Milliseconds', false);
+
+ // FORMATTING
+
+ addFormatToken('z', 0, 0, 'zoneAbbr');
+ addFormatToken('zz', 0, 0, 'zoneName');
+
+ // MOMENTS
+
+ function getZoneAbbr() {
+ return this._isUTC ? 'UTC' : '';
+ }
+
+ function getZoneName() {
+ return this._isUTC ? 'Coordinated Universal Time' : '';
+ }
+
+ var proto = Moment.prototype;
+
+ proto.add = add;
+ proto.calendar = calendar$1;
+ proto.clone = clone;
+ proto.diff = diff;
+ proto.endOf = endOf;
+ proto.format = format;
+ proto.from = from;
+ proto.fromNow = fromNow;
+ proto.to = to;
+ proto.toNow = toNow;
+ proto.get = stringGet;
+ proto.invalidAt = invalidAt;
+ proto.isAfter = isAfter;
+ proto.isBefore = isBefore;
+ proto.isBetween = isBetween;
+ proto.isSame = isSame;
+ proto.isSameOrAfter = isSameOrAfter;
+ proto.isSameOrBefore = isSameOrBefore;
+ proto.isValid = isValid$2;
+ proto.lang = lang;
+ proto.locale = locale;
+ proto.localeData = localeData;
+ proto.max = prototypeMax;
+ proto.min = prototypeMin;
+ proto.parsingFlags = parsingFlags;
+ proto.set = stringSet;
+ proto.startOf = startOf;
+ proto.subtract = subtract;
+ proto.toArray = toArray;
+ proto.toObject = toObject;
+ proto.toDate = toDate;
+ proto.toISOString = toISOString;
+ proto.inspect = inspect;
+ if (typeof Symbol !== 'undefined' && Symbol.for != null) {
+ proto[Symbol.for('nodejs.util.inspect.custom')] = function () {
+ return 'Moment<' + this.format() + '>';
+ };
+ }
+ proto.toJSON = toJSON;
+ proto.toString = toString;
+ proto.unix = unix;
+ proto.valueOf = valueOf;
+ proto.creationData = creationData;
+ proto.eraName = getEraName;
+ proto.eraNarrow = getEraNarrow;
+ proto.eraAbbr = getEraAbbr;
+ proto.eraYear = getEraYear;
+ proto.year = getSetYear;
+ proto.isLeapYear = getIsLeapYear;
+ proto.weekYear = getSetWeekYear;
+ proto.isoWeekYear = getSetISOWeekYear;
+ proto.quarter = proto.quarters = getSetQuarter;
+ proto.month = getSetMonth;
+ proto.daysInMonth = getDaysInMonth;
+ proto.week = proto.weeks = getSetWeek;
+ proto.isoWeek = proto.isoWeeks = getSetISOWeek;
+ proto.weeksInYear = getWeeksInYear;
+ proto.weeksInWeekYear = getWeeksInWeekYear;
+ proto.isoWeeksInYear = getISOWeeksInYear;
+ proto.isoWeeksInISOWeekYear = getISOWeeksInISOWeekYear;
+ proto.date = getSetDayOfMonth;
+ proto.day = proto.days = getSetDayOfWeek;
+ proto.weekday = getSetLocaleDayOfWeek;
+ proto.isoWeekday = getSetISODayOfWeek;
+ proto.dayOfYear = getSetDayOfYear;
+ proto.hour = proto.hours = getSetHour;
+ proto.minute = proto.minutes = getSetMinute;
+ proto.second = proto.seconds = getSetSecond;
+ proto.millisecond = proto.milliseconds = getSetMillisecond;
+ proto.utcOffset = getSetOffset;
+ proto.utc = setOffsetToUTC;
+ proto.local = setOffsetToLocal;
+ proto.parseZone = setOffsetToParsedOffset;
+ proto.hasAlignedHourOffset = hasAlignedHourOffset;
+ proto.isDST = isDaylightSavingTime;
+ proto.isLocal = isLocal;
+ proto.isUtcOffset = isUtcOffset;
+ proto.isUtc = isUtc;
+ proto.isUTC = isUtc;
+ proto.zoneAbbr = getZoneAbbr;
+ proto.zoneName = getZoneName;
+ proto.dates = deprecate(
+ 'dates accessor is deprecated. Use date instead.',
+ getSetDayOfMonth
+ );
+ proto.months = deprecate(
+ 'months accessor is deprecated. Use month instead',
+ getSetMonth
+ );
+ proto.years = deprecate(
+ 'years accessor is deprecated. Use year instead',
+ getSetYear
+ );
+ proto.zone = deprecate(
+ 'moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/',
+ getSetZone
+ );
+ proto.isDSTShifted = deprecate(
+ 'isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information',
+ isDaylightSavingTimeShifted
+ );
+
+ function createUnix(input) {
+ return createLocal(input * 1000);
+ }
+
+ function createInZone() {
+ return createLocal.apply(null, arguments).parseZone();
+ }
+
+ function preParsePostFormat(string) {
+ return string;
+ }
+
+ var proto$1 = Locale.prototype;
+
+ proto$1.calendar = calendar;
+ proto$1.longDateFormat = longDateFormat;
+ proto$1.invalidDate = invalidDate;
+ proto$1.ordinal = ordinal;
+ proto$1.preparse = preParsePostFormat;
+ proto$1.postformat = preParsePostFormat;
+ proto$1.relativeTime = relativeTime;
+ proto$1.pastFuture = pastFuture;
+ proto$1.set = set;
+ proto$1.eras = localeEras;
+ proto$1.erasParse = localeErasParse;
+ proto$1.erasConvertYear = localeErasConvertYear;
+ proto$1.erasAbbrRegex = erasAbbrRegex;
+ proto$1.erasNameRegex = erasNameRegex;
+ proto$1.erasNarrowRegex = erasNarrowRegex;
+
+ proto$1.months = localeMonths;
+ proto$1.monthsShort = localeMonthsShort;
+ proto$1.monthsParse = localeMonthsParse;
+ proto$1.monthsRegex = monthsRegex;
+ proto$1.monthsShortRegex = monthsShortRegex;
+ proto$1.week = localeWeek;
+ proto$1.firstDayOfYear = localeFirstDayOfYear;
+ proto$1.firstDayOfWeek = localeFirstDayOfWeek;
+
+ proto$1.weekdays = localeWeekdays;
+ proto$1.weekdaysMin = localeWeekdaysMin;
+ proto$1.weekdaysShort = localeWeekdaysShort;
+ proto$1.weekdaysParse = localeWeekdaysParse;
+
+ proto$1.weekdaysRegex = weekdaysRegex;
+ proto$1.weekdaysShortRegex = weekdaysShortRegex;
+ proto$1.weekdaysMinRegex = weekdaysMinRegex;
+
+ proto$1.isPM = localeIsPM;
+ proto$1.meridiem = localeMeridiem;
+
+ function get$1(format, index, field, setter) {
+ var locale = getLocale(),
+ utc = createUTC().set(setter, index);
+ return locale[field](utc, format);
+ }
+
+ function listMonthsImpl(format, index, field) {
+ if (isNumber(format)) {
+ index = format;
+ format = undefined;
+ }
+
+ format = format || '';
+
+ if (index != null) {
+ return get$1(format, index, field, 'month');
+ }
+
+ var i,
+ out = [];
+ for (i = 0; i < 12; i++) {
+ out[i] = get$1(format, i, field, 'month');
+ }
+ return out;
+ }
+
+ // ()
+ // (5)
+ // (fmt, 5)
+ // (fmt)
+ // (true)
+ // (true, 5)
+ // (true, fmt, 5)
+ // (true, fmt)
+ function listWeekdaysImpl(localeSorted, format, index, field) {
+ if (typeof localeSorted === 'boolean') {
+ if (isNumber(format)) {
+ index = format;
+ format = undefined;
+ }
+
+ format = format || '';
+ } else {
+ format = localeSorted;
+ index = format;
+ localeSorted = false;
+
+ if (isNumber(format)) {
+ index = format;
+ format = undefined;
+ }
+
+ format = format || '';
+ }
+
+ var locale = getLocale(),
+ shift = localeSorted ? locale._week.dow : 0,
+ i,
+ out = [];
+
+ if (index != null) {
+ return get$1(format, (index + shift) % 7, field, 'day');
+ }
+
+ for (i = 0; i < 7; i++) {
+ out[i] = get$1(format, (i + shift) % 7, field, 'day');
+ }
+ return out;
+ }
+
+ function listMonths(format, index) {
+ return listMonthsImpl(format, index, 'months');
+ }
+
+ function listMonthsShort(format, index) {
+ return listMonthsImpl(format, index, 'monthsShort');
+ }
+
+ function listWeekdays(localeSorted, format, index) {
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
+ }
+
+ function listWeekdaysShort(localeSorted, format, index) {
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
+ }
+
+ function listWeekdaysMin(localeSorted, format, index) {
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
+ }
+
+ getSetGlobalLocale('en', {
+ eras: [
+ {
+ since: '0001-01-01',
+ until: +Infinity,
+ offset: 1,
+ name: 'Anno Domini',
+ narrow: 'AD',
+ abbr: 'AD',
+ },
+ {
+ since: '0000-12-31',
+ until: -Infinity,
+ offset: 1,
+ name: 'Before Christ',
+ narrow: 'BC',
+ abbr: 'BC',
+ },
+ ],
+ dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
+ ordinal: function (number) {
+ var b = number % 10,
+ output =
+ toInt((number % 100) / 10) === 1
+ ? 'th'
+ : b === 1
+ ? 'st'
+ : b === 2
+ ? 'nd'
+ : b === 3
+ ? 'rd'
+ : 'th';
+ return number + output;
+ },
+ });
+
+ // Side effect imports
+
+ hooks.lang = deprecate(
+ 'moment.lang is deprecated. Use moment.locale instead.',
+ getSetGlobalLocale
+ );
+ hooks.langData = deprecate(
+ 'moment.langData is deprecated. Use moment.localeData instead.',
+ getLocale
+ );
+
+ var mathAbs = Math.abs;
+
+ function abs() {
+ var data = this._data;
+
+ this._milliseconds = mathAbs(this._milliseconds);
+ this._days = mathAbs(this._days);
+ this._months = mathAbs(this._months);
+
+ data.milliseconds = mathAbs(data.milliseconds);
+ data.seconds = mathAbs(data.seconds);
+ data.minutes = mathAbs(data.minutes);
+ data.hours = mathAbs(data.hours);
+ data.months = mathAbs(data.months);
+ data.years = mathAbs(data.years);
+
+ return this;
+ }
+
+ function addSubtract$1(duration, input, value, direction) {
+ var other = createDuration(input, value);
+
+ duration._milliseconds += direction * other._milliseconds;
+ duration._days += direction * other._days;
+ duration._months += direction * other._months;
+
+ return duration._bubble();
+ }
+
+ // supports only 2.0-style add(1, 's') or add(duration)
+ function add$1(input, value) {
+ return addSubtract$1(this, input, value, 1);
+ }
+
+ // supports only 2.0-style subtract(1, 's') or subtract(duration)
+ function subtract$1(input, value) {
+ return addSubtract$1(this, input, value, -1);
+ }
+
+ function absCeil(number) {
+ if (number < 0) {
+ return Math.floor(number);
+ } else {
+ return Math.ceil(number);
+ }
+ }
+
+ function bubble() {
+ var milliseconds = this._milliseconds,
+ days = this._days,
+ months = this._months,
+ data = this._data,
+ seconds,
+ minutes,
+ hours,
+ years,
+ monthsFromDays;
+
+ // if we have a mix of positive and negative values, bubble down first
+ // check: https://github.com/moment/moment/issues/2166
+ if (
+ !(
+ (milliseconds >= 0 && days >= 0 && months >= 0) ||
+ (milliseconds <= 0 && days <= 0 && months <= 0)
+ )
+ ) {
+ milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
+ days = 0;
+ months = 0;
+ }
+
+ // The following code bubbles up values, see the tests for
+ // examples of what that means.
+ data.milliseconds = milliseconds % 1000;
+
+ seconds = absFloor(milliseconds / 1000);
+ data.seconds = seconds % 60;
+
+ minutes = absFloor(seconds / 60);
+ data.minutes = minutes % 60;
+
+ hours = absFloor(minutes / 60);
+ data.hours = hours % 24;
+
+ days += absFloor(hours / 24);
+
+ // convert days to months
+ monthsFromDays = absFloor(daysToMonths(days));
+ months += monthsFromDays;
+ days -= absCeil(monthsToDays(monthsFromDays));
+
+ // 12 months -> 1 year
+ years = absFloor(months / 12);
+ months %= 12;
+
+ data.days = days;
+ data.months = months;
+ data.years = years;
+
+ return this;
+ }
+
+ function daysToMonths(days) {
+ // 400 years have 146097 days (taking into account leap year rules)
+ // 400 years have 12 months === 4800
+ return (days * 4800) / 146097;
+ }
+
+ function monthsToDays(months) {
+ // the reverse of daysToMonths
+ return (months * 146097) / 4800;
+ }
+
+ function as(units) {
+ if (!this.isValid()) {
+ return NaN;
+ }
+ var days,
+ months,
+ milliseconds = this._milliseconds;
+
+ units = normalizeUnits(units);
+
+ if (units === 'month' || units === 'quarter' || units === 'year') {
+ days = this._days + milliseconds / 864e5;
+ months = this._months + daysToMonths(days);
+ switch (units) {
+ case 'month':
+ return months;
+ case 'quarter':
+ return months / 3;
+ case 'year':
+ return months / 12;
+ }
+ } else {
+ // handle milliseconds separately because of floating point math errors (issue #1867)
+ days = this._days + Math.round(monthsToDays(this._months));
+ switch (units) {
+ case 'week':
+ return days / 7 + milliseconds / 6048e5;
+ case 'day':
+ return days + milliseconds / 864e5;
+ case 'hour':
+ return days * 24 + milliseconds / 36e5;
+ case 'minute':
+ return days * 1440 + milliseconds / 6e4;
+ case 'second':
+ return days * 86400 + milliseconds / 1000;
+ // Math.floor prevents floating point math errors here
+ case 'millisecond':
+ return Math.floor(days * 864e5) + milliseconds;
+ default:
+ throw new Error('Unknown unit ' + units);
+ }
+ }
+ }
+
+ // TODO: Use this.as('ms')?
+ function valueOf$1() {
+ if (!this.isValid()) {
+ return NaN;
+ }
+ return (
+ this._milliseconds +
+ this._days * 864e5 +
+ (this._months % 12) * 2592e6 +
+ toInt(this._months / 12) * 31536e6
+ );
+ }
+
+ function makeAs(alias) {
+ return function () {
+ return this.as(alias);
+ };
+ }
+
+ var asMilliseconds = makeAs('ms'),
+ asSeconds = makeAs('s'),
+ asMinutes = makeAs('m'),
+ asHours = makeAs('h'),
+ asDays = makeAs('d'),
+ asWeeks = makeAs('w'),
+ asMonths = makeAs('M'),
+ asQuarters = makeAs('Q'),
+ asYears = makeAs('y');
+
+ function clone$1() {
+ return createDuration(this);
+ }
+
+ function get$2(units) {
+ units = normalizeUnits(units);
+ return this.isValid() ? this[units + 's']() : NaN;
+ }
+
+ function makeGetter(name) {
+ return function () {
+ return this.isValid() ? this._data[name] : NaN;
+ };
+ }
+
+ var milliseconds = makeGetter('milliseconds'),
+ seconds = makeGetter('seconds'),
+ minutes = makeGetter('minutes'),
+ hours = makeGetter('hours'),
+ days = makeGetter('days'),
+ months = makeGetter('months'),
+ years = makeGetter('years');
+
+ function weeks() {
+ return absFloor(this.days() / 7);
+ }
+
+ var round = Math.round,
+ thresholds = {
+ ss: 44, // a few seconds to seconds
+ s: 45, // seconds to minute
+ m: 45, // minutes to hour
+ h: 22, // hours to day
+ d: 26, // days to month/week
+ w: null, // weeks to month
+ M: 11, // months to year
+ };
+
+ // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
+ function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
+ return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
+ }
+
+ function relativeTime$1(posNegDuration, withoutSuffix, thresholds, locale) {
+ var duration = createDuration(posNegDuration).abs(),
+ seconds = round(duration.as('s')),
+ minutes = round(duration.as('m')),
+ hours = round(duration.as('h')),
+ days = round(duration.as('d')),
+ months = round(duration.as('M')),
+ weeks = round(duration.as('w')),
+ years = round(duration.as('y')),
+ a =
+ (seconds <= thresholds.ss && ['s', seconds]) ||
+ (seconds < thresholds.s && ['ss', seconds]) ||
+ (minutes <= 1 && ['m']) ||
+ (minutes < thresholds.m && ['mm', minutes]) ||
+ (hours <= 1 && ['h']) ||
+ (hours < thresholds.h && ['hh', hours]) ||
+ (days <= 1 && ['d']) ||
+ (days < thresholds.d && ['dd', days]);
+
+ if (thresholds.w != null) {
+ a =
+ a ||
+ (weeks <= 1 && ['w']) ||
+ (weeks < thresholds.w && ['ww', weeks]);
+ }
+ a = a ||
+ (months <= 1 && ['M']) ||
+ (months < thresholds.M && ['MM', months]) ||
+ (years <= 1 && ['y']) || ['yy', years];
+
+ a[2] = withoutSuffix;
+ a[3] = +posNegDuration > 0;
+ a[4] = locale;
+ return substituteTimeAgo.apply(null, a);
+ }
+
+ // This function allows you to set the rounding function for relative time strings
+ function getSetRelativeTimeRounding(roundingFunction) {
+ if (roundingFunction === undefined) {
+ return round;
+ }
+ if (typeof roundingFunction === 'function') {
+ round = roundingFunction;
+ return true;
+ }
+ return false;
+ }
+
+ // This function allows you to set a threshold for relative time strings
+ function getSetRelativeTimeThreshold(threshold, limit) {
+ if (thresholds[threshold] === undefined) {
+ return false;
+ }
+ if (limit === undefined) {
+ return thresholds[threshold];
+ }
+ thresholds[threshold] = limit;
+ if (threshold === 's') {
+ thresholds.ss = limit - 1;
+ }
+ return true;
+ }
+
+ function humanize(argWithSuffix, argThresholds) {
+ if (!this.isValid()) {
+ return this.localeData().invalidDate();
+ }
+
+ var withSuffix = false,
+ th = thresholds,
+ locale,
+ output;
+
+ if (typeof argWithSuffix === 'object') {
+ argThresholds = argWithSuffix;
+ argWithSuffix = false;
+ }
+ if (typeof argWithSuffix === 'boolean') {
+ withSuffix = argWithSuffix;
+ }
+ if (typeof argThresholds === 'object') {
+ th = Object.assign({}, thresholds, argThresholds);
+ if (argThresholds.s != null && argThresholds.ss == null) {
+ th.ss = argThresholds.s - 1;
+ }
+ }
+
+ locale = this.localeData();
+ output = relativeTime$1(this, !withSuffix, th, locale);
+
+ if (withSuffix) {
+ output = locale.pastFuture(+this, output);
+ }
+
+ return locale.postformat(output);
+ }
+
+ var abs$1 = Math.abs;
+
+ function sign(x) {
+ return (x > 0) - (x < 0) || +x;
+ }
+
+ function toISOString$1() {
+ // 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)
+ if (!this.isValid()) {
+ return this.localeData().invalidDate();
+ }
+
+ var seconds = abs$1(this._milliseconds) / 1000,
+ days = abs$1(this._days),
+ months = abs$1(this._months),
+ minutes,
+ hours,
+ years,
+ s,
+ total = this.asSeconds(),
+ totalSign,
+ ymSign,
+ daysSign,
+ hmsSign;
+
+ if (!total) {
+ // this is the same as C#'s (Noda) and python (isodate)...
+ // but not other JS (goog.date)
+ return 'P0D';
+ }
+
+ // 3600 seconds -> 60 minutes -> 1 hour
+ minutes = absFloor(seconds / 60);
+ hours = absFloor(minutes / 60);
+ seconds %= 60;
+ minutes %= 60;
+
+ // 12 months -> 1 year
+ years = absFloor(months / 12);
+ months %= 12;
+
+ // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
+ s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
+
+ totalSign = total < 0 ? '-' : '';
+ ymSign = sign(this._months) !== sign(total) ? '-' : '';
+ daysSign = sign(this._days) !== sign(total) ? '-' : '';
+ hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
+
+ return (
+ totalSign +
+ 'P' +
+ (years ? ymSign + years + 'Y' : '') +
+ (months ? ymSign + months + 'M' : '') +
+ (days ? daysSign + days + 'D' : '') +
+ (hours || minutes || seconds ? 'T' : '') +
+ (hours ? hmsSign + hours + 'H' : '') +
+ (minutes ? hmsSign + minutes + 'M' : '') +
+ (seconds ? hmsSign + s + 'S' : '')
+ );
+ }
+
+ var proto$2 = Duration.prototype;
+
+ proto$2.isValid = isValid$1;
+ proto$2.abs = abs;
+ proto$2.add = add$1;
+ proto$2.subtract = subtract$1;
+ proto$2.as = as;
+ proto$2.asMilliseconds = asMilliseconds;
+ proto$2.asSeconds = asSeconds;
+ proto$2.asMinutes = asMinutes;
+ proto$2.asHours = asHours;
+ proto$2.asDays = asDays;
+ proto$2.asWeeks = asWeeks;
+ proto$2.asMonths = asMonths;
+ proto$2.asQuarters = asQuarters;
+ proto$2.asYears = asYears;
+ proto$2.valueOf = valueOf$1;
+ proto$2._bubble = bubble;
+ proto$2.clone = clone$1;
+ proto$2.get = get$2;
+ proto$2.milliseconds = milliseconds;
+ proto$2.seconds = seconds;
+ proto$2.minutes = minutes;
+ proto$2.hours = hours;
+ proto$2.days = days;
+ proto$2.weeks = weeks;
+ proto$2.months = months;
+ proto$2.years = years;
+ proto$2.humanize = humanize;
+ proto$2.toISOString = toISOString$1;
+ proto$2.toString = toISOString$1;
+ proto$2.toJSON = toISOString$1;
+ proto$2.locale = locale;
+ proto$2.localeData = localeData;
+
+ proto$2.toIsoString = deprecate(
+ 'toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)',
+ toISOString$1
+ );
+ proto$2.lang = lang;
+
+ // FORMATTING
+
+ addFormatToken('X', 0, 0, 'unix');
+ addFormatToken('x', 0, 0, 'valueOf');
+
+ // PARSING
+
+ addRegexToken('x', matchSigned);
+ addRegexToken('X', matchTimestamp);
+ addParseToken('X', function (input, array, config) {
+ config._d = new Date(parseFloat(input) * 1000);
+ });
+ addParseToken('x', function (input, array, config) {
+ config._d = new Date(toInt(input));
+ });
+
+ //! moment.js
+
+ hooks.version = '2.29.1';
+
+ setHookCallback(createLocal);
+
+ hooks.fn = proto;
+ hooks.min = min;
+ hooks.max = max;
+ hooks.now = now;
+ hooks.utc = createUTC;
+ hooks.unix = createUnix;
+ hooks.months = listMonths;
+ hooks.isDate = isDate;
+ hooks.locale = getSetGlobalLocale;
+ hooks.invalid = createInvalid;
+ hooks.duration = createDuration;
+ hooks.isMoment = isMoment;
+ hooks.weekdays = listWeekdays;
+ hooks.parseZone = createInZone;
+ hooks.localeData = getLocale;
+ hooks.isDuration = isDuration;
+ hooks.monthsShort = listMonthsShort;
+ hooks.weekdaysMin = listWeekdaysMin;
+ hooks.defineLocale = defineLocale;
+ hooks.updateLocale = updateLocale;
+ hooks.locales = listLocales;
+ hooks.weekdaysShort = listWeekdaysShort;
+ hooks.normalizeUnits = normalizeUnits;
+ hooks.relativeTimeRounding = getSetRelativeTimeRounding;
+ hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
+ hooks.calendarFormat = getCalendarFormat;
+ hooks.prototype = proto;
+
+ // currently HTML5 input type only supports 24-hour formats
+ hooks.HTML5_FMT = {
+ DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // <input type="datetime-local" />
+ DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // <input type="datetime-local" step="1" />
+ DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // <input type="datetime-local" step="0.001" />
+ DATE: 'YYYY-MM-DD', // <input type="date" />
+ TIME: 'HH:mm', // <input type="time" />
+ TIME_SECONDS: 'HH:mm:ss', // <input type="time" step="1" />
+ TIME_MS: 'HH:mm:ss.SSS', // <input type="time" step="0.001" />
+ WEEK: 'GGGG-[W]WW', // <input type="week" />
+ MONTH: 'YYYY-MM', // <input type="month" />
+ };
+
+ return hooks;
+
+})));
diff --git a/static/moment.min.js b/static/moment.min.js
@@ -0,0 +1,15 @@
+/**
+ * Minified by jsDelivr using Terser v5.3.0.
+ * Original file: /npm/moment@2.29.1/moment.js
+ *
+ * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
+ */
+//! moment.js
+//! version : 2.29.1
+//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
+//! license : MIT
+//! momentjs.com
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,(function(){"use strict";var e,t;function n(){return e.apply(null,arguments)}function s(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function i(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function r(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function a(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;var t;for(t in e)if(r(e,t))return!1;return!0}function o(e){return void 0===e}function u(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function l(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function h(e,t){var n,s=[];for(n=0;n<e.length;++n)s.push(t(e[n],n));return s}function d(e,t){for(var n in t)r(t,n)&&(e[n]=t[n]);return r(t,"toString")&&(e.toString=t.toString),r(t,"valueOf")&&(e.valueOf=t.valueOf),e}function c(e,t,n,s){return Dt(e,t,n,s,!0).utc()}function f(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidEra:null,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],era:null,meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function m(e){if(null==e._isValid){var n=f(e),s=t.call(n.parsedDateParts,(function(e){return null!=e})),i=!isNaN(e._d.getTime())&&n.overflow<0&&!n.empty&&!n.invalidEra&&!n.invalidMonth&&!n.invalidWeekday&&!n.weekdayMismatch&&!n.nullInput&&!n.invalidFormat&&!n.userInvalidated&&(!n.meridiem||n.meridiem&&s);if(e._strict&&(i=i&&0===n.charsLeftOver&&0===n.unusedTokens.length&&void 0===n.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return i;e._isValid=i}return e._isValid}function _(e){var t=c(NaN);return null!=e?d(f(t),e):f(t).userInvalidated=!0,t}t=Array.prototype.some?Array.prototype.some:function(e){var t,n=Object(this),s=n.length>>>0;for(t=0;t<s;t++)if(t in n&&e.call(this,n[t],t,n))return!0;return!1};var y=n.momentProperties=[],g=!1;function w(e,t){var n,s,i;if(o(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),o(t._i)||(e._i=t._i),o(t._f)||(e._f=t._f),o(t._l)||(e._l=t._l),o(t._strict)||(e._strict=t._strict),o(t._tzm)||(e._tzm=t._tzm),o(t._isUTC)||(e._isUTC=t._isUTC),o(t._offset)||(e._offset=t._offset),o(t._pf)||(e._pf=f(t)),o(t._locale)||(e._locale=t._locale),y.length>0)for(n=0;n<y.length;n++)o(i=t[s=y[n]])||(e[s]=i);return e}function p(e){w(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===g&&(g=!0,n.updateOffset(this),g=!1)}function v(e){return e instanceof p||null!=e&&null!=e._isAMomentObject}function k(e){!1===n.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+e)}function M(e,t){var s=!0;return d((function(){if(null!=n.deprecationHandler&&n.deprecationHandler(null,e),s){var i,a,o,u=[];for(a=0;a<arguments.length;a++){if(i="","object"==typeof arguments[a]){for(o in i+="\n["+a+"] ",arguments[0])r(arguments[0],o)&&(i+=o+": "+arguments[0][o]+", ");i=i.slice(0,-2)}else i=arguments[a];u.push(i)}k(e+"\nArguments: "+Array.prototype.slice.call(u).join("")+"\n"+(new Error).stack),s=!1}return t.apply(this,arguments)}),t)}var D,S={};function Y(e,t){null!=n.deprecationHandler&&n.deprecationHandler(e,t),S[e]||(k(t),S[e]=!0)}function O(e){return"undefined"!=typeof Function&&e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function b(e,t){var n,s=d({},e);for(n in t)r(t,n)&&(i(e[n])&&i(t[n])?(s[n]={},d(s[n],e[n]),d(s[n],t[n])):null!=t[n]?s[n]=t[n]:delete s[n]);for(n in e)r(e,n)&&!r(t,n)&&i(e[n])&&(s[n]=d({},s[n]));return s}function x(e){null!=e&&this.set(e)}n.suppressDeprecationWarnings=!1,n.deprecationHandler=null,D=Object.keys?Object.keys:function(e){var t,n=[];for(t in e)r(e,t)&&n.push(t);return n};function T(e,t,n){var s=""+Math.abs(e),i=t-s.length;return(e>=0?n?"+":"":"-")+Math.pow(10,Math.max(0,i)).toString().substr(1)+s}var N=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,P=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,R={},W={};function C(e,t,n,s){var i=s;"string"==typeof s&&(i=function(){return this[s]()}),e&&(W[e]=i),t&&(W[t[0]]=function(){return T(i.apply(this,arguments),t[1],t[2])}),n&&(W[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function H(e,t){return e.isValid()?(t=U(t,e.localeData()),R[t]=R[t]||function(e){var t,n,s,i=e.match(N);for(t=0,n=i.length;t<n;t++)W[i[t]]?i[t]=W[i[t]]:i[t]=(s=i[t]).match(/\[[\s\S]/)?s.replace(/^\[|\]$/g,""):s.replace(/\\/g,"");return function(t){var s,r="";for(s=0;s<n;s++)r+=O(i[s])?i[s].call(t,e):i[s];return r}}(t),R[t](e)):e.localeData().invalidDate()}function U(e,t){var n=5;function s(e){return t.longDateFormat(e)||e}for(P.lastIndex=0;n>=0&&P.test(e);)e=e.replace(P,s),P.lastIndex=0,n-=1;return e}var F={};function L(e,t){var n=e.toLowerCase();F[n]=F[n+"s"]=F[t]=e}function V(e){return"string"==typeof e?F[e]||F[e.toLowerCase()]:void 0}function G(e){var t,n,s={};for(n in e)r(e,n)&&(t=V(n))&&(s[t]=e[n]);return s}var E={};function A(e,t){E[e]=t}function j(e){return e%4==0&&e%100!=0||e%400==0}function I(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function Z(e){var t=+e,n=0;return 0!==t&&isFinite(t)&&(n=I(t)),n}function z(e,t){return function(s){return null!=s?(q(this,e,s),n.updateOffset(this,t),this):$(this,e)}}function $(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function q(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&j(e.year())&&1===e.month()&&29===e.date()?(n=Z(n),e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),ve(n,e.month()))):e._d["set"+(e._isUTC?"UTC":"")+t](n))}var B,J=/\d/,Q=/\d\d/,X=/\d{3}/,K=/\d{4}/,ee=/[+-]?\d{6}/,te=/\d\d?/,ne=/\d\d\d\d?/,se=/\d\d\d\d\d\d?/,ie=/\d{1,3}/,re=/\d{1,4}/,ae=/[+-]?\d{1,6}/,oe=/\d+/,ue=/[+-]?\d+/,le=/Z|[+-]\d\d:?\d\d/gi,he=/Z|[+-]\d\d(?::?\d\d)?/gi,de=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;function ce(e,t,n){B[e]=O(t)?t:function(e,s){return e&&n?n:t}}function fe(e,t){return r(B,e)?B[e](t._strict,t._locale):new RegExp(me(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,(function(e,t,n,s,i){return t||n||s||i}))))}function me(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}B={};var _e={};function ye(e,t){var n,s=t;for("string"==typeof e&&(e=[e]),u(t)&&(s=function(e,n){n[t]=Z(e)}),n=0;n<e.length;n++)_e[e[n]]=s}function ge(e,t){ye(e,(function(e,n,s,i){s._w=s._w||{},t(e,s._w,s,i)}))}function we(e,t,n){null!=t&&r(_e,e)&&_e[e](t,n._a,n,e)}var pe;function ve(e,t){if(isNaN(e)||isNaN(t))return NaN;var n,s=(t%(n=12)+n)%n;return e+=(t-s)/12,1===s?j(e)?29:28:31-s%7%2}pe=Array.prototype.indexOf?Array.prototype.indexOf:function(e){var t;for(t=0;t<this.length;++t)if(this[t]===e)return t;return-1},C("M",["MM",2],"Mo",(function(){return this.month()+1})),C("MMM",0,0,(function(e){return this.localeData().monthsShort(this,e)})),C("MMMM",0,0,(function(e){return this.localeData().months(this,e)})),L("month","M"),A("month",8),ce("M",te),ce("MM",te,Q),ce("MMM",(function(e,t){return t.monthsShortRegex(e)})),ce("MMMM",(function(e,t){return t.monthsRegex(e)})),ye(["M","MM"],(function(e,t){t[1]=Z(e)-1})),ye(["MMM","MMMM"],(function(e,t,n,s){var i=n._locale.monthsParse(e,s,n._strict);null!=i?t[1]=i:f(n).invalidMonth=e}));var ke="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Me="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),De=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Se=de,Ye=de;function Oe(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=c([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=pe.call(this._shortMonthsParse,a))?i:null:-1!==(i=pe.call(this._longMonthsParse,a))?i:null:"MMM"===t?-1!==(i=pe.call(this._shortMonthsParse,a))||-1!==(i=pe.call(this._longMonthsParse,a))?i:null:-1!==(i=pe.call(this._longMonthsParse,a))||-1!==(i=pe.call(this._shortMonthsParse,a))?i:null}function be(e,t){var n;if(!e.isValid())return e;if("string"==typeof t)if(/^\d+$/.test(t))t=Z(t);else if(!u(t=e.localeData().monthsParse(t)))return e;return n=Math.min(e.date(),ve(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n),e}function xe(e){return null!=e?(be(this,e),n.updateOffset(this,!0),this):$(this,"Month")}function Te(){function e(e,t){return t.length-e.length}var t,n,s=[],i=[],r=[];for(t=0;t<12;t++)n=c([2e3,t]),s.push(this.monthsShort(n,"")),i.push(this.months(n,"")),r.push(this.months(n,"")),r.push(this.monthsShort(n,""));for(s.sort(e),i.sort(e),r.sort(e),t=0;t<12;t++)s[t]=me(s[t]),i[t]=me(i[t]);for(t=0;t<24;t++)r[t]=me(r[t]);this._monthsRegex=new RegExp("^("+r.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+s.join("|")+")","i")}function Ne(e){return j(e)?366:365}C("Y",0,0,(function(){var e=this.year();return e<=9999?T(e,4):"+"+e})),C(0,["YY",2],0,(function(){return this.year()%100})),C(0,["YYYY",4],0,"year"),C(0,["YYYYY",5],0,"year"),C(0,["YYYYYY",6,!0],0,"year"),L("year","y"),A("year",1),ce("Y",ue),ce("YY",te,Q),ce("YYYY",re,K),ce("YYYYY",ae,ee),ce("YYYYYY",ae,ee),ye(["YYYYY","YYYYYY"],0),ye("YYYY",(function(e,t){t[0]=2===e.length?n.parseTwoDigitYear(e):Z(e)})),ye("YY",(function(e,t){t[0]=n.parseTwoDigitYear(e)})),ye("Y",(function(e,t){t[0]=parseInt(e,10)})),n.parseTwoDigitYear=function(e){return Z(e)+(Z(e)>68?1900:2e3)};var Pe=z("FullYear",!0);function Re(e,t,n,s,i,r,a){var o;return e<100&&e>=0?(o=new Date(e+400,t,n,s,i,r,a),isFinite(o.getFullYear())&&o.setFullYear(e)):o=new Date(e,t,n,s,i,r,a),o}function We(e){var t,n;return e<100&&e>=0?((n=Array.prototype.slice.call(arguments))[0]=e+400,t=new Date(Date.UTC.apply(null,n)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)):t=new Date(Date.UTC.apply(null,arguments)),t}function Ce(e,t,n){var s=7+t-n;return-((7+We(e,0,s).getUTCDay()-t)%7)+s-1}function He(e,t,n,s,i){var r,a,o=1+7*(t-1)+(7+n-s)%7+Ce(e,s,i);return o<=0?a=Ne(r=e-1)+o:o>Ne(e)?(r=e+1,a=o-Ne(e)):(r=e,a=o),{year:r,dayOfYear:a}}function Ue(e,t,n){var s,i,r=Ce(e.year(),t,n),a=Math.floor((e.dayOfYear()-r-1)/7)+1;return a<1?s=a+Fe(i=e.year()-1,t,n):a>Fe(e.year(),t,n)?(s=a-Fe(e.year(),t,n),i=e.year()+1):(i=e.year(),s=a),{week:s,year:i}}function Fe(e,t,n){var s=Ce(e,t,n),i=Ce(e+1,t,n);return(Ne(e)-s+i)/7}C("w",["ww",2],"wo","week"),C("W",["WW",2],"Wo","isoWeek"),L("week","w"),L("isoWeek","W"),A("week",5),A("isoWeek",5),ce("w",te),ce("ww",te,Q),ce("W",te),ce("WW",te,Q),ge(["w","ww","W","WW"],(function(e,t,n,s){t[s.substr(0,1)]=Z(e)}));function Le(e,t){return e.slice(t,7).concat(e.slice(0,t))}C("d",0,"do","day"),C("dd",0,0,(function(e){return this.localeData().weekdaysMin(this,e)})),C("ddd",0,0,(function(e){return this.localeData().weekdaysShort(this,e)})),C("dddd",0,0,(function(e){return this.localeData().weekdays(this,e)})),C("e",0,0,"weekday"),C("E",0,0,"isoWeekday"),L("day","d"),L("weekday","e"),L("isoWeekday","E"),A("day",11),A("weekday",11),A("isoWeekday",11),ce("d",te),ce("e",te),ce("E",te),ce("dd",(function(e,t){return t.weekdaysMinRegex(e)})),ce("ddd",(function(e,t){return t.weekdaysShortRegex(e)})),ce("dddd",(function(e,t){return t.weekdaysRegex(e)})),ge(["dd","ddd","dddd"],(function(e,t,n,s){var i=n._locale.weekdaysParse(e,s,n._strict);null!=i?t.d=i:f(n).invalidWeekday=e})),ge(["d","e","E"],(function(e,t,n,s){t[s]=Z(e)}));var Ve="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Ge="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Ee="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Ae=de,je=de,Ie=de;function Ze(e,t,n){var s,i,r,a=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=c([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=pe.call(this._weekdaysParse,a))?i:null:"ddd"===t?-1!==(i=pe.call(this._shortWeekdaysParse,a))?i:null:-1!==(i=pe.call(this._minWeekdaysParse,a))?i:null:"dddd"===t?-1!==(i=pe.call(this._weekdaysParse,a))||-1!==(i=pe.call(this._shortWeekdaysParse,a))||-1!==(i=pe.call(this._minWeekdaysParse,a))?i:null:"ddd"===t?-1!==(i=pe.call(this._shortWeekdaysParse,a))||-1!==(i=pe.call(this._weekdaysParse,a))||-1!==(i=pe.call(this._minWeekdaysParse,a))?i:null:-1!==(i=pe.call(this._minWeekdaysParse,a))||-1!==(i=pe.call(this._weekdaysParse,a))||-1!==(i=pe.call(this._shortWeekdaysParse,a))?i:null}function ze(){function e(e,t){return t.length-e.length}var t,n,s,i,r,a=[],o=[],u=[],l=[];for(t=0;t<7;t++)n=c([2e3,1]).day(t),s=me(this.weekdaysMin(n,"")),i=me(this.weekdaysShort(n,"")),r=me(this.weekdays(n,"")),a.push(s),o.push(i),u.push(r),l.push(s),l.push(i),l.push(r);a.sort(e),o.sort(e),u.sort(e),l.sort(e),this._weekdaysRegex=new RegExp("^("+l.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+u.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+a.join("|")+")","i")}function $e(){return this.hours()%12||12}function qe(e,t){C(e,0,0,(function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)}))}function Be(e,t){return t._meridiemParse}C("H",["HH",2],0,"hour"),C("h",["hh",2],0,$e),C("k",["kk",2],0,(function(){return this.hours()||24})),C("hmm",0,0,(function(){return""+$e.apply(this)+T(this.minutes(),2)})),C("hmmss",0,0,(function(){return""+$e.apply(this)+T(this.minutes(),2)+T(this.seconds(),2)})),C("Hmm",0,0,(function(){return""+this.hours()+T(this.minutes(),2)})),C("Hmmss",0,0,(function(){return""+this.hours()+T(this.minutes(),2)+T(this.seconds(),2)})),qe("a",!0),qe("A",!1),L("hour","h"),A("hour",13),ce("a",Be),ce("A",Be),ce("H",te),ce("h",te),ce("k",te),ce("HH",te,Q),ce("hh",te,Q),ce("kk",te,Q),ce("hmm",ne),ce("hmmss",se),ce("Hmm",ne),ce("Hmmss",se),ye(["H","HH"],3),ye(["k","kk"],(function(e,t,n){var s=Z(e);t[3]=24===s?0:s})),ye(["a","A"],(function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e})),ye(["h","hh"],(function(e,t,n){t[3]=Z(e),f(n).bigHour=!0})),ye("hmm",(function(e,t,n){var s=e.length-2;t[3]=Z(e.substr(0,s)),t[4]=Z(e.substr(s)),f(n).bigHour=!0})),ye("hmmss",(function(e,t,n){var s=e.length-4,i=e.length-2;t[3]=Z(e.substr(0,s)),t[4]=Z(e.substr(s,2)),t[5]=Z(e.substr(i)),f(n).bigHour=!0})),ye("Hmm",(function(e,t,n){var s=e.length-2;t[3]=Z(e.substr(0,s)),t[4]=Z(e.substr(s))})),ye("Hmmss",(function(e,t,n){var s=e.length-4,i=e.length-2;t[3]=Z(e.substr(0,s)),t[4]=Z(e.substr(s,2)),t[5]=Z(e.substr(i))}));var Je=z("Hours",!0);var Qe,Xe={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{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"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:ke,monthsShort:Me,week:{dow:0,doy:6},weekdays:Ve,weekdaysMin:Ee,weekdaysShort:Ge,meridiemParse:/[ap]\.?m?\.?/i},Ke={},et={};function tt(e,t){var n,s=Math.min(e.length,t.length);for(n=0;n<s;n+=1)if(e[n]!==t[n])return n;return s}function nt(e){return e?e.toLowerCase().replace("_","-"):e}function st(e){var t=null;if(void 0===Ke[e]&&"undefined"!=typeof module&&module&&module.exports)try{t=Qe._abbr,require("./locale/"+e),it(t)}catch(t){Ke[e]=null}return Ke[e]}function it(e,t){var n;return e&&((n=o(t)?at(e):rt(e,t))?Qe=n:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),Qe._abbr}function rt(e,t){if(null!==t){var n,s=Xe;if(t.abbr=e,null!=Ke[e])Y("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."),s=Ke[e]._config;else if(null!=t.parentLocale)if(null!=Ke[t.parentLocale])s=Ke[t.parentLocale]._config;else{if(null==(n=st(t.parentLocale)))return et[t.parentLocale]||(et[t.parentLocale]=[]),et[t.parentLocale].push({name:e,config:t}),null;s=n._config}return Ke[e]=new x(b(s,t)),et[e]&&et[e].forEach((function(e){rt(e.name,e.config)})),it(e),Ke[e]}return delete Ke[e],null}function at(e){var t;if(e&&e._locale&&e._locale._abbr&&(e=e._locale._abbr),!e)return Qe;if(!s(e)){if(t=st(e))return t;e=[e]}return function(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=nt(e[r]).split("-")).length,n=(n=nt(e[r+1]))?n.split("-"):null;t>0;){if(s=st(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&tt(i,n)>=t-1)break;t--}r++}return Qe}(e)}function ot(e){var t,n=e._a;return n&&-2===f(e).overflow&&(t=n[1]<0||n[1]>11?1:n[2]<1||n[2]>ve(n[0],n[1])?2:n[3]<0||n[3]>24||24===n[3]&&(0!==n[4]||0!==n[5]||0!==n[6])?3:n[4]<0||n[4]>59?4:n[5]<0||n[5]>59?5:n[6]<0||n[6]>999?6:-1,f(e)._overflowDayOfYear&&(t<0||t>2)&&(t=2),f(e)._overflowWeeks&&-1===t&&(t=7),f(e)._overflowWeekday&&-1===t&&(t=8),f(e).overflow=t),e}var ut=/^\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)?)?$/,lt=/^\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)?)?$/,ht=/Z|[+-]\d\d(?::?\d\d)?/,dt=[["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}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/],["YYYYMM",/\d{6}/,!1],["YYYY",/\d{4}/,!1]],ct=[["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/]],ft=/^\/?Date\((-?\d+)/i,mt=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,_t={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function yt(e){var t,n,s,i,r,a,o=e._i,u=ut.exec(o)||lt.exec(o);if(u){for(f(e).iso=!0,t=0,n=dt.length;t<n;t++)if(dt[t][1].exec(u[1])){i=dt[t][0],s=!1!==dt[t][2];break}if(null==i)return void(e._isValid=!1);if(u[3]){for(t=0,n=ct.length;t<n;t++)if(ct[t][1].exec(u[3])){r=(u[2]||" ")+ct[t][0];break}if(null==r)return void(e._isValid=!1)}if(!s&&null!=r)return void(e._isValid=!1);if(u[4]){if(!ht.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),kt(e)}else e._isValid=!1}function gt(e){var t=parseInt(e,10);return t<=49?2e3+t:t<=999?1900+t:t}function wt(e){var t,n,s,i,r,a,o,u,l=mt.exec(e._i.replace(/\([^)]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));if(l){if(n=l[4],s=l[3],i=l[2],r=l[5],a=l[6],o=l[7],u=[gt(n),Me.indexOf(s),parseInt(i,10),parseInt(r,10),parseInt(a,10)],o&&u.push(parseInt(o,10)),t=u,!function(e,t,n){return!e||Ge.indexOf(e)===new Date(t[0],t[1],t[2]).getDay()||(f(n).weekdayMismatch=!0,n._isValid=!1,!1)}(l[1],t,e))return;e._a=t,e._tzm=function(e,t,n){if(e)return _t[e];if(t)return 0;var s=parseInt(n,10),i=s%100;return(s-i)/100*60+i}(l[8],l[9],l[10]),e._d=We.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),f(e).rfc2822=!0}else e._isValid=!1}function pt(e,t,n){return null!=e?e:null!=t?t:n}function vt(e){var t,s,i,r,a,o=[];if(!e._d){for(i=function(e){var t=new Date(n.now());return e._useUTC?[t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate()]:[t.getFullYear(),t.getMonth(),t.getDate()]}(e),e._w&&null==e._a[2]&&null==e._a[1]&&function(e){var t,n,s,i,r,a,o,u,l;null!=(t=e._w).GG||null!=t.W||null!=t.E?(r=1,a=4,n=pt(t.GG,e._a[0],Ue(St(),1,4).year),s=pt(t.W,1),((i=pt(t.E,1))<1||i>7)&&(u=!0)):(r=e._locale._week.dow,a=e._locale._week.doy,l=Ue(St(),r,a),n=pt(t.gg,e._a[0],l.year),s=pt(t.w,l.week),null!=t.d?((i=t.d)<0||i>6)&&(u=!0):null!=t.e?(i=t.e+r,(t.e<0||t.e>6)&&(u=!0)):i=r);s<1||s>Fe(n,r,a)?f(e)._overflowWeeks=!0:null!=u?f(e)._overflowWeekday=!0:(o=He(n,s,i,r,a),e._a[0]=o.year,e._dayOfYear=o.dayOfYear)}(e),null!=e._dayOfYear&&(a=pt(e._a[0],i[0]),(e._dayOfYear>Ne(a)||0===e._dayOfYear)&&(f(e)._overflowDayOfYear=!0),s=We(a,0,e._dayOfYear),e._a[1]=s.getUTCMonth(),e._a[2]=s.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=o[t]=i[t];for(;t<7;t++)e._a[t]=o[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[3]&&0===e._a[4]&&0===e._a[5]&&0===e._a[6]&&(e._nextDay=!0,e._a[3]=0),e._d=(e._useUTC?We:Re).apply(null,o),r=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[3]=24),e._w&&void 0!==e._w.d&&e._w.d!==r&&(f(e).weekdayMismatch=!0)}}function kt(e){if(e._f!==n.ISO_8601)if(e._f!==n.RFC_2822){e._a=[],f(e).empty=!0;var t,s,i,r,a,o,u=""+e._i,l=u.length,h=0;for(i=U(e._f,e._locale).match(N)||[],t=0;t<i.length;t++)r=i[t],(s=(u.match(fe(r,e))||[])[0])&&((a=u.substr(0,u.indexOf(s))).length>0&&f(e).unusedInput.push(a),u=u.slice(u.indexOf(s)+s.length),h+=s.length),W[r]?(s?f(e).empty=!1:f(e).unusedTokens.push(r),we(r,s,e)):e._strict&&!s&&f(e).unusedTokens.push(r);f(e).charsLeftOver=l-h,u.length>0&&f(e).unusedInput.push(u),e._a[3]<=12&&!0===f(e).bigHour&&e._a[3]>0&&(f(e).bigHour=void 0),f(e).parsedDateParts=e._a.slice(0),f(e).meridiem=e._meridiem,e._a[3]=function(e,t,n){var s;if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):null!=e.isPM?((s=e.isPM(n))&&t<12&&(t+=12),s||12!==t||(t=0),t):t}(e._locale,e._a[3],e._meridiem),null!==(o=f(e).era)&&(e._a[0]=e._locale.erasConvertYear(o,e._a[0])),vt(e),ot(e)}else wt(e);else yt(e)}function Mt(e){var t=e._i,r=e._f;return e._locale=e._locale||at(e._l),null===t||void 0===r&&""===t?_({nullInput:!0}):("string"==typeof t&&(e._i=t=e._locale.preparse(t)),v(t)?new p(ot(t)):(l(t)?e._d=t:s(r)?function(e){var t,n,s,i,r,a,o=!1;if(0===e._f.length)return f(e).invalidFormat=!0,void(e._d=new Date(NaN));for(i=0;i<e._f.length;i++)r=0,a=!1,t=w({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],kt(t),m(t)&&(a=!0),r+=f(t).charsLeftOver,r+=10*f(t).unusedTokens.length,f(t).score=r,o?r<s&&(s=r,n=t):(null==s||r<s||a)&&(s=r,n=t,a&&(o=!0));d(e,n||t)}(e):r?kt(e):function(e){var t=e._i;o(t)?e._d=new Date(n.now()):l(t)?e._d=new Date(t.valueOf()):"string"==typeof t?function(e){var t=ft.exec(e._i);null===t?(yt(e),!1===e._isValid&&(delete e._isValid,wt(e),!1===e._isValid&&(delete e._isValid,e._strict?e._isValid=!1:n.createFromInputFallback(e)))):e._d=new Date(+t[1])}(e):s(t)?(e._a=h(t.slice(0),(function(e){return parseInt(e,10)})),vt(e)):i(t)?function(e){if(!e._d){var t=G(e._i),n=void 0===t.day?t.date:t.day;e._a=h([t.year,t.month,n,t.hour,t.minute,t.second,t.millisecond],(function(e){return e&&parseInt(e,10)})),vt(e)}}(e):u(t)?e._d=new Date(t):n.createFromInputFallback(e)}(e),m(e)||(e._d=null),e))}function Dt(e,t,n,r,o){var u,l={};return!0!==t&&!1!==t||(r=t,t=void 0),!0!==n&&!1!==n||(r=n,n=void 0),(i(e)&&a(e)||s(e)&&0===e.length)&&(e=void 0),l._isAMomentObject=!0,l._useUTC=l._isUTC=o,l._l=n,l._i=e,l._f=t,l._strict=r,(u=new p(ot(Mt(l))))._nextDay&&(u.add(1,"d"),u._nextDay=void 0),u}function St(e,t,n,s){return Dt(e,t,n,s,!1)}n.createFromInputFallback=M("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",(function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))})),n.ISO_8601=function(){},n.RFC_2822=function(){};var Yt=M("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",(function(){var e=St.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:_()})),Ot=M("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",(function(){var e=St.apply(null,arguments);return this.isValid()&&e.isValid()?e>this?this:e:_()}));function bt(e,t){var n,i;if(1===t.length&&s(t[0])&&(t=t[0]),!t.length)return St();for(n=t[0],i=1;i<t.length;++i)t[i].isValid()&&!t[i][e](n)||(n=t[i]);return n}var xt=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Tt(e){var t=G(e),n=t.year||0,s=t.quarter||0,i=t.month||0,a=t.week||t.isoWeek||0,o=t.day||0,u=t.hour||0,l=t.minute||0,h=t.second||0,d=t.millisecond||0;this._isValid=function(e){var t,n,s=!1;for(t in e)if(r(e,t)&&(-1===pe.call(xt,t)||null!=e[t]&&isNaN(e[t])))return!1;for(n=0;n<xt.length;++n)if(e[xt[n]]){if(s)return!1;parseFloat(e[xt[n]])!==Z(e[xt[n]])&&(s=!0)}return!0}(t),this._milliseconds=+d+1e3*h+6e4*l+1e3*u*60*60,this._days=+o+7*a,this._months=+i+3*s+12*n,this._data={},this._locale=at(),this._bubble()}function Nt(e){return e instanceof Tt}function Pt(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Rt(e,t){C(e,0,0,(function(){var e=this.utcOffset(),n="+";return e<0&&(e=-e,n="-"),n+T(~~(e/60),2)+t+T(~~e%60,2)}))}Rt("Z",":"),Rt("ZZ",""),ce("Z",he),ce("ZZ",he),ye(["Z","ZZ"],(function(e,t,n){n._useUTC=!0,n._tzm=Ct(he,e)}));var Wt=/([\+\-]|\d\d)/gi;function Ct(e,t){var n,s,i=(t||"").match(e);return null===i?null:0===(s=60*(n=((i[i.length-1]||[])+"").match(Wt)||["-",0,0])[1]+Z(n[2]))?0:"+"===n[0]?s:-s}function Ht(e,t){var s,i;return t._isUTC?(s=t.clone(),i=(v(e)||l(e)?e.valueOf():St(e).valueOf())-s.valueOf(),s._d.setTime(s._d.valueOf()+i),n.updateOffset(s,!1),s):St(e).local()}function Ut(e){return-Math.round(e._d.getTimezoneOffset())}function Ft(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}n.updateOffset=function(){};var Lt=/^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,Vt=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function Gt(e,t){var n,s,i,a=e,o=null;return Nt(e)?a={ms:e._milliseconds,d:e._days,M:e._months}:u(e)||!isNaN(+e)?(a={},t?a[t]=+e:a.milliseconds=+e):(o=Lt.exec(e))?(n="-"===o[1]?-1:1,a={y:0,d:Z(o[2])*n,h:Z(o[3])*n,m:Z(o[4])*n,s:Z(o[5])*n,ms:Z(Pt(1e3*o[6]))*n}):(o=Vt.exec(e))?(n="-"===o[1]?-1:1,a={y:Et(o[2],n),M:Et(o[3],n),w:Et(o[4],n),d:Et(o[5],n),h:Et(o[6],n),m:Et(o[7],n),s:Et(o[8],n)}):null==a?a={}:"object"==typeof a&&("from"in a||"to"in a)&&(i=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Ht(t,e),e.isBefore(t)?n=At(e,t):((n=At(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(St(a.from),St(a.to)),(a={}).ms=i.milliseconds,a.M=i.months),s=new Tt(a),Nt(e)&&r(e,"_locale")&&(s._locale=e._locale),Nt(e)&&r(e,"_isValid")&&(s._isValid=e._isValid),s}function Et(e,t){var n=e&&parseFloat(e.replace(",","."));return(isNaN(n)?0:n)*t}function At(e,t){var n={};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function jt(e,t){return function(n,s){var i;return null===s||isNaN(+s)||(Y(t,"moment()."+t+"(period, number) is deprecated. Please use moment()."+t+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),i=n,n=s,s=i),It(this,Gt(n,s),e),this}}function It(e,t,s,i){var r=t._milliseconds,a=Pt(t._days),o=Pt(t._months);e.isValid()&&(i=null==i||i,o&&be(e,$(e,"Month")+o*s),a&&q(e,"Date",$(e,"Date")+a*s),r&&e._d.setTime(e._d.valueOf()+r*s),i&&n.updateOffset(e,a||o))}Gt.fn=Tt.prototype,Gt.invalid=function(){return Gt(NaN)};var Zt=jt(1,"add"),zt=jt(-1,"subtract");function $t(e){return"string"==typeof e||e instanceof String}function qt(e){return v(e)||l(e)||$t(e)||u(e)||function(e){var t=s(e),n=!1;t&&(n=0===e.filter((function(t){return!u(t)&&$t(e)})).length);return t&&n}(e)||function(e){var t,n,s=i(e)&&!a(e),o=!1,u=["years","year","y","months","month","M","days","day","d","dates","date","D","hours","hour","h","minutes","minute","m","seconds","second","s","milliseconds","millisecond","ms"];for(t=0;t<u.length;t+=1)n=u[t],o=o||r(e,n);return s&&o}(e)||null==e}function Bt(e){var t,n=i(e)&&!a(e),s=!1,o=["sameDay","nextDay","lastDay","nextWeek","lastWeek","sameElse"];for(t=0;t<o.length;t+=1)s=s||r(e,o[t]);return n&&s}function Jt(e,t){if(e.date()<t.date())return-Jt(t,e);var n=12*(t.year()-e.year())+(t.month()-e.month()),s=e.clone().add(n,"months");return-(n+(t-s<0?(t-s)/(s-e.clone().add(n-1,"months")):(t-s)/(e.clone().add(n+1,"months")-s)))||0}function Qt(e){var t;return void 0===e?this._locale._abbr:(null!=(t=at(e))&&(this._locale=t),this)}n.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",n.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";var Xt=M("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",(function(e){return void 0===e?this.localeData():this.locale(e)}));function Kt(){return this._locale}var en=1e3,tn=6e4,nn=36e5,sn=126227808e5;function rn(e,t){return(e%t+t)%t}function an(e,t,n){return e<100&&e>=0?new Date(e+400,t,n)-sn:new Date(e,t,n).valueOf()}function on(e,t,n){return e<100&&e>=0?Date.UTC(e+400,t,n)-sn:Date.UTC(e,t,n)}function un(e,t){return t.erasAbbrRegex(e)}function ln(){var e,t,n=[],s=[],i=[],r=[],a=this.eras();for(e=0,t=a.length;e<t;++e)s.push(me(a[e].name)),n.push(me(a[e].abbr)),i.push(me(a[e].narrow)),r.push(me(a[e].name)),r.push(me(a[e].abbr)),r.push(me(a[e].narrow));this._erasRegex=new RegExp("^("+r.join("|")+")","i"),this._erasNameRegex=new RegExp("^("+s.join("|")+")","i"),this._erasAbbrRegex=new RegExp("^("+n.join("|")+")","i"),this._erasNarrowRegex=new RegExp("^("+i.join("|")+")","i")}function hn(e,t){C(0,[e,e.length],0,t)}function dn(e,t,n,s,i){var r;return null==e?Ue(this,s,i).year:(t>(r=Fe(e,s,i))&&(t=r),cn.call(this,e,t,n,s,i))}function cn(e,t,n,s,i){var r=He(e,t,n,s,i),a=We(r.year,0,r.dayOfYear);return this.year(a.getUTCFullYear()),this.month(a.getUTCMonth()),this.date(a.getUTCDate()),this}C("N",0,0,"eraAbbr"),C("NN",0,0,"eraAbbr"),C("NNN",0,0,"eraAbbr"),C("NNNN",0,0,"eraName"),C("NNNNN",0,0,"eraNarrow"),C("y",["y",1],"yo","eraYear"),C("y",["yy",2],0,"eraYear"),C("y",["yyy",3],0,"eraYear"),C("y",["yyyy",4],0,"eraYear"),ce("N",un),ce("NN",un),ce("NNN",un),ce("NNNN",(function(e,t){return t.erasNameRegex(e)})),ce("NNNNN",(function(e,t){return t.erasNarrowRegex(e)})),ye(["N","NN","NNN","NNNN","NNNNN"],(function(e,t,n,s){var i=n._locale.erasParse(e,s,n._strict);i?f(n).era=i:f(n).invalidEra=e})),ce("y",oe),ce("yy",oe),ce("yyy",oe),ce("yyyy",oe),ce("yo",(function(e,t){return t._eraYearOrdinalRegex||oe})),ye(["y","yy","yyy","yyyy"],0),ye(["yo"],(function(e,t,n,s){var i;n._locale._eraYearOrdinalRegex&&(i=e.match(n._locale._eraYearOrdinalRegex)),n._locale.eraYearOrdinalParse?t[0]=n._locale.eraYearOrdinalParse(e,i):t[0]=parseInt(e,10)})),C(0,["gg",2],0,(function(){return this.weekYear()%100})),C(0,["GG",2],0,(function(){return this.isoWeekYear()%100})),hn("gggg","weekYear"),hn("ggggg","weekYear"),hn("GGGG","isoWeekYear"),hn("GGGGG","isoWeekYear"),L("weekYear","gg"),L("isoWeekYear","GG"),A("weekYear",1),A("isoWeekYear",1),ce("G",ue),ce("g",ue),ce("GG",te,Q),ce("gg",te,Q),ce("GGGG",re,K),ce("gggg",re,K),ce("GGGGG",ae,ee),ce("ggggg",ae,ee),ge(["gggg","ggggg","GGGG","GGGGG"],(function(e,t,n,s){t[s.substr(0,2)]=Z(e)})),ge(["gg","GG"],(function(e,t,s,i){t[i]=n.parseTwoDigitYear(e)})),C("Q",0,"Qo","quarter"),L("quarter","Q"),A("quarter",7),ce("Q",J),ye("Q",(function(e,t){t[1]=3*(Z(e)-1)})),C("D",["DD",2],"Do","date"),L("date","D"),A("date",9),ce("D",te),ce("DD",te,Q),ce("Do",(function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient})),ye(["D","DD"],2),ye("Do",(function(e,t){t[2]=Z(e.match(te)[0])}));var fn=z("Date",!0);C("DDD",["DDDD",3],"DDDo","dayOfYear"),L("dayOfYear","DDD"),A("dayOfYear",4),ce("DDD",ie),ce("DDDD",X),ye(["DDD","DDDD"],(function(e,t,n){n._dayOfYear=Z(e)})),C("m",["mm",2],0,"minute"),L("minute","m"),A("minute",14),ce("m",te),ce("mm",te,Q),ye(["m","mm"],4);var mn=z("Minutes",!1);C("s",["ss",2],0,"second"),L("second","s"),A("second",15),ce("s",te),ce("ss",te,Q),ye(["s","ss"],5);var _n,yn,gn=z("Seconds",!1);for(C("S",0,0,(function(){return~~(this.millisecond()/100)})),C(0,["SS",2],0,(function(){return~~(this.millisecond()/10)})),C(0,["SSS",3],0,"millisecond"),C(0,["SSSS",4],0,(function(){return 10*this.millisecond()})),C(0,["SSSSS",5],0,(function(){return 100*this.millisecond()})),C(0,["SSSSSS",6],0,(function(){return 1e3*this.millisecond()})),C(0,["SSSSSSS",7],0,(function(){return 1e4*this.millisecond()})),C(0,["SSSSSSSS",8],0,(function(){return 1e5*this.millisecond()})),C(0,["SSSSSSSSS",9],0,(function(){return 1e6*this.millisecond()})),L("millisecond","ms"),A("millisecond",16),ce("S",ie,J),ce("SS",ie,Q),ce("SSS",ie,X),_n="SSSS";_n.length<=9;_n+="S")ce(_n,oe);function wn(e,t){t[6]=Z(1e3*("0."+e))}for(_n="S";_n.length<=9;_n+="S")ye(_n,wn);yn=z("Milliseconds",!1),C("z",0,0,"zoneAbbr"),C("zz",0,0,"zoneName");var pn=p.prototype;function vn(e){return e}pn.add=Zt,pn.calendar=function(e,t){1===arguments.length&&(arguments[0]?qt(arguments[0])?(e=arguments[0],t=void 0):Bt(arguments[0])&&(t=arguments[0],e=void 0):(e=void 0,t=void 0));var s=e||St(),i=Ht(s,this).startOf("day"),r=n.calendarFormat(this,i)||"sameElse",a=t&&(O(t[r])?t[r].call(this,s):t[r]);return this.format(a||this.localeData().calendar(r,this,St(s)))},pn.clone=function(){return new p(this)},pn.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Ht(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=V(t)){case"year":r=Jt(this,s)/12;break;case"month":r=Jt(this,s);break;case"quarter":r=Jt(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:I(r)},pn.endOf=function(e){var t,s;if(void 0===(e=V(e))||"millisecond"===e||!this.isValid())return this;switch(s=this._isUTC?on:an,e){case"year":t=s(this.year()+1,0,1)-1;break;case"quarter":t=s(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":t=s(this.year(),this.month()+1,1)-1;break;case"week":t=s(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":t=s(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":t=s(this.year(),this.month(),this.date()+1)-1;break;case"hour":t=this._d.valueOf(),t+=nn-rn(t+(this._isUTC?0:this.utcOffset()*tn),nn)-1;break;case"minute":t=this._d.valueOf(),t+=tn-rn(t,tn)-1;break;case"second":t=this._d.valueOf(),t+=en-rn(t,en)-1}return this._d.setTime(t),n.updateOffset(this,!0),this},pn.format=function(e){e||(e=this.isUtc()?n.defaultFormatUtc:n.defaultFormat);var t=H(this,e);return this.localeData().postformat(t)},pn.from=function(e,t){return this.isValid()&&(v(e)&&e.isValid()||St(e).isValid())?Gt({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},pn.fromNow=function(e){return this.from(St(),e)},pn.to=function(e,t){return this.isValid()&&(v(e)&&e.isValid()||St(e).isValid())?Gt({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},pn.toNow=function(e){return this.to(St(),e)},pn.get=function(e){return O(this[e=V(e)])?this[e]():this},pn.invalidAt=function(){return f(this).overflow},pn.isAfter=function(e,t){var n=v(e)?e:St(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=V(t)||"millisecond")?this.valueOf()>n.valueOf():n.valueOf()<this.clone().startOf(t).valueOf())},pn.isBefore=function(e,t){var n=v(e)?e:St(e);return!(!this.isValid()||!n.isValid())&&("millisecond"===(t=V(t)||"millisecond")?this.valueOf()<n.valueOf():this.clone().endOf(t).valueOf()<n.valueOf())},pn.isBetween=function(e,t,n,s){var i=v(e)?e:St(e),r=v(t)?t:St(t);return!!(this.isValid()&&i.isValid()&&r.isValid())&&(("("===(s=s||"()")[0]?this.isAfter(i,n):!this.isBefore(i,n))&&(")"===s[1]?this.isBefore(r,n):!this.isAfter(r,n)))},pn.isSame=function(e,t){var n,s=v(e)?e:St(e);return!(!this.isValid()||!s.isValid())&&("millisecond"===(t=V(t)||"millisecond")?this.valueOf()===s.valueOf():(n=s.valueOf(),this.clone().startOf(t).valueOf()<=n&&n<=this.clone().endOf(t).valueOf()))},pn.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},pn.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},pn.isValid=function(){return m(this)},pn.lang=Xt,pn.locale=Qt,pn.localeData=Kt,pn.max=Ot,pn.min=Yt,pn.parsingFlags=function(){return d({},f(this))},pn.set=function(e,t){if("object"==typeof e){var n,s=function(e){var t,n=[];for(t in e)r(e,t)&&n.push({unit:t,priority:E[t]});return n.sort((function(e,t){return e.priority-t.priority})),n}(e=G(e));for(n=0;n<s.length;n++)this[s[n].unit](e[s[n].unit])}else if(O(this[e=V(e)]))return this[e](t);return this},pn.startOf=function(e){var t,s;if(void 0===(e=V(e))||"millisecond"===e||!this.isValid())return this;switch(s=this._isUTC?on:an,e){case"year":t=s(this.year(),0,1);break;case"quarter":t=s(this.year(),this.month()-this.month()%3,1);break;case"month":t=s(this.year(),this.month(),1);break;case"week":t=s(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":t=s(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":t=s(this.year(),this.month(),this.date());break;case"hour":t=this._d.valueOf(),t-=rn(t+(this._isUTC?0:this.utcOffset()*tn),nn);break;case"minute":t=this._d.valueOf(),t-=rn(t,tn);break;case"second":t=this._d.valueOf(),t-=rn(t,en)}return this._d.setTime(t),n.updateOffset(this,!0),this},pn.subtract=zt,pn.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},pn.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},pn.toDate=function(){return new Date(this.valueOf())},pn.toISOString=function(e){if(!this.isValid())return null;var t=!0!==e,n=t?this.clone().utc():this;return n.year()<0||n.year()>9999?H(n,t?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):O(Date.prototype.toISOString)?t?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",H(n,"Z")):H(n,t?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},pn.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e,t,n,s="moment",i="";return this.isLocal()||(s=0===this.utcOffset()?"moment.utc":"moment.parseZone",i="Z"),e="["+s+'("]',t=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY","-MM-DD[T]HH:mm:ss.SSS",n=i+'[")]',this.format(e+t+"-MM-DD[T]HH:mm:ss.SSS"+n)},"undefined"!=typeof Symbol&&null!=Symbol.for&&(pn[Symbol.for("nodejs.util.inspect.custom")]=function(){return"Moment<"+this.format()+">"}),pn.toJSON=function(){return this.isValid()?this.toISOString():null},pn.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},pn.unix=function(){return Math.floor(this.valueOf()/1e3)},pn.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},pn.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},pn.eraName=function(){var e,t,n,s=this.localeData().eras();for(e=0,t=s.length;e<t;++e){if(n=this.clone().startOf("day").valueOf(),s[e].since<=n&&n<=s[e].until)return s[e].name;if(s[e].until<=n&&n<=s[e].since)return s[e].name}return""},pn.eraNarrow=function(){var e,t,n,s=this.localeData().eras();for(e=0,t=s.length;e<t;++e){if(n=this.clone().startOf("day").valueOf(),s[e].since<=n&&n<=s[e].until)return s[e].narrow;if(s[e].until<=n&&n<=s[e].since)return s[e].narrow}return""},pn.eraAbbr=function(){var e,t,n,s=this.localeData().eras();for(e=0,t=s.length;e<t;++e){if(n=this.clone().startOf("day").valueOf(),s[e].since<=n&&n<=s[e].until)return s[e].abbr;if(s[e].until<=n&&n<=s[e].since)return s[e].abbr}return""},pn.eraYear=function(){var e,t,s,i,r=this.localeData().eras();for(e=0,t=r.length;e<t;++e)if(s=r[e].since<=r[e].until?1:-1,i=this.clone().startOf("day").valueOf(),r[e].since<=i&&i<=r[e].until||r[e].until<=i&&i<=r[e].since)return(this.year()-n(r[e].since).year())*s+r[e].offset;return this.year()},pn.year=Pe,pn.isLeapYear=function(){return j(this.year())},pn.weekYear=function(e){return dn.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},pn.isoWeekYear=function(e){return dn.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},pn.quarter=pn.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},pn.month=xe,pn.daysInMonth=function(){return ve(this.year(),this.month())},pn.week=pn.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},pn.isoWeek=pn.isoWeeks=function(e){var t=Ue(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},pn.weeksInYear=function(){var e=this.localeData()._week;return Fe(this.year(),e.dow,e.doy)},pn.weeksInWeekYear=function(){var e=this.localeData()._week;return Fe(this.weekYear(),e.dow,e.doy)},pn.isoWeeksInYear=function(){return Fe(this.year(),1,4)},pn.isoWeeksInISOWeekYear=function(){return Fe(this.isoWeekYear(),1,4)},pn.date=fn,pn.day=pn.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(e=function(e,t){return"string"!=typeof e?e:isNaN(e)?"number"==typeof(e=t.weekdaysParse(e))?e:null:parseInt(e,10)}(e,this.localeData()),this.add(e-t,"d")):t},pn.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},pn.isoWeekday=function(e){if(!this.isValid())return null!=e?this:NaN;if(null!=e){var t=function(e,t){return"string"==typeof e?t.weekdaysParse(e)%7||7:isNaN(e)?null:e}(e,this.localeData());return this.day(this.day()%7?t:t-7)}return this.day()||7},pn.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},pn.hour=pn.hours=Je,pn.minute=pn.minutes=mn,pn.second=pn.seconds=gn,pn.millisecond=pn.milliseconds=yn,pn.utcOffset=function(e,t,s){var i,r=this._offset||0;if(!this.isValid())return null!=e?this:NaN;if(null!=e){if("string"==typeof e){if(null===(e=Ct(he,e)))return this}else Math.abs(e)<16&&!s&&(e*=60);return!this._isUTC&&t&&(i=Ut(this)),this._offset=e,this._isUTC=!0,null!=i&&this.add(i,"m"),r!==e&&(!t||this._changeInProgress?It(this,Gt(e-r,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,n.updateOffset(this,!0),this._changeInProgress=null)),this}return this._isUTC?r:Ut(this)},pn.utc=function(e){return this.utcOffset(0,e)},pn.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Ut(this),"m")),this},pn.parseZone=function(){if(null!=this._tzm)this.utcOffset(this._tzm,!1,!0);else if("string"==typeof this._i){var e=Ct(le,this._i);null!=e?this.utcOffset(e):this.utcOffset(0,!0)}return this},pn.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?St(e).utcOffset():0,(this.utcOffset()-e)%60==0)},pn.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},pn.isLocal=function(){return!!this.isValid()&&!this._isUTC},pn.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},pn.isUtc=Ft,pn.isUTC=Ft,pn.zoneAbbr=function(){return this._isUTC?"UTC":""},pn.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},pn.dates=M("dates accessor is deprecated. Use date instead.",fn),pn.months=M("months accessor is deprecated. Use month instead",xe),pn.years=M("years accessor is deprecated. Use year instead",Pe),pn.zone=M("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",(function(e,t){return null!=e?("string"!=typeof e&&(e=-e),this.utcOffset(e,t),this):-this.utcOffset()})),pn.isDSTShifted=M("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",(function(){if(!o(this._isDSTShifted))return this._isDSTShifted;var e,t={};return w(t,this),(t=Mt(t))._a?(e=t._isUTC?c(t._a):St(t._a),this._isDSTShifted=this.isValid()&&function(e,t,n){var s,i=Math.min(e.length,t.length),r=Math.abs(e.length-t.length),a=0;for(s=0;s<i;s++)(n&&e[s]!==t[s]||!n&&Z(e[s])!==Z(t[s]))&&a++;return a+r}(t._a,e.toArray())>0):this._isDSTShifted=!1,this._isDSTShifted}));var kn=x.prototype;function Mn(e,t,n,s){var i=at(),r=c().set(s,t);return i[n](r,e)}function Dn(e,t,n){if(u(e)&&(t=e,e=void 0),e=e||"",null!=t)return Mn(e,t,n,"month");var s,i=[];for(s=0;s<12;s++)i[s]=Mn(e,s,n,"month");return i}function Sn(e,t,n,s){"boolean"==typeof e?(u(t)&&(n=t,t=void 0),t=t||""):(n=t=e,e=!1,u(t)&&(n=t,t=void 0),t=t||"");var i,r=at(),a=e?r._week.dow:0,o=[];if(null!=n)return Mn(t,(n+a)%7,s,"day");for(i=0;i<7;i++)o[i]=Mn(t,(i+a)%7,s,"day");return o}kn.calendar=function(e,t,n){var s=this._calendar[e]||this._calendar.sameElse;return O(s)?s.call(t,n):s},kn.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.match(N).map((function(e){return"MMMM"===e||"MM"===e||"DD"===e||"dddd"===e?e.slice(1):e})).join(""),this._longDateFormat[e])},kn.invalidDate=function(){return this._invalidDate},kn.ordinal=function(e){return this._ordinal.replace("%d",e)},kn.preparse=vn,kn.postformat=vn,kn.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return O(i)?i(e,t,n,s):i.replace(/%d/i,e)},kn.pastFuture=function(e,t){var n=this._relativeTime[e>0?"future":"past"];return O(n)?n(t):n.replace(/%s/i,t)},kn.set=function(e){var t,n;for(n in e)r(e,n)&&(O(t=e[n])?this[n]=t:this["_"+n]=t);this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},kn.eras=function(e,t){var s,i,r,a=this._eras||at("en")._eras;for(s=0,i=a.length;s<i;++s){switch(typeof a[s].since){case"string":r=n(a[s].since).startOf("day"),a[s].since=r.valueOf()}switch(typeof a[s].until){case"undefined":a[s].until=1/0;break;case"string":r=n(a[s].until).startOf("day").valueOf(),a[s].until=r.valueOf()}}return a},kn.erasParse=function(e,t,n){var s,i,r,a,o,u=this.eras();for(e=e.toUpperCase(),s=0,i=u.length;s<i;++s)if(r=u[s].name.toUpperCase(),a=u[s].abbr.toUpperCase(),o=u[s].narrow.toUpperCase(),n)switch(t){case"N":case"NN":case"NNN":if(a===e)return u[s];break;case"NNNN":if(r===e)return u[s];break;case"NNNNN":if(o===e)return u[s]}else if([r,a,o].indexOf(e)>=0)return u[s]},kn.erasConvertYear=function(e,t){var s=e.since<=e.until?1:-1;return void 0===t?n(e.since).year():n(e.since).year()+(t-e.offset)*s},kn.erasAbbrRegex=function(e){return r(this,"_erasAbbrRegex")||ln.call(this),e?this._erasAbbrRegex:this._erasRegex},kn.erasNameRegex=function(e){return r(this,"_erasNameRegex")||ln.call(this),e?this._erasNameRegex:this._erasRegex},kn.erasNarrowRegex=function(e){return r(this,"_erasNarrowRegex")||ln.call(this),e?this._erasNarrowRegex:this._erasRegex},kn.months=function(e,t){return e?s(this._months)?this._months[e.month()]:this._months[(this._months.isFormat||De).test(t)?"format":"standalone"][e.month()]:s(this._months)?this._months:this._months.standalone},kn.monthsShort=function(e,t){return e?s(this._monthsShort)?this._monthsShort[e.month()]:this._monthsShort[De.test(t)?"format":"standalone"][e.month()]:s(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},kn.monthsParse=function(e,t,n){var s,i,r;if(this._monthsParseExact)return Oe.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=c([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(r="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(r.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},kn.monthsRegex=function(e){return this._monthsParseExact?(r(this,"_monthsRegex")||Te.call(this),e?this._monthsStrictRegex:this._monthsRegex):(r(this,"_monthsRegex")||(this._monthsRegex=Ye),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},kn.monthsShortRegex=function(e){return this._monthsParseExact?(r(this,"_monthsRegex")||Te.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(r(this,"_monthsShortRegex")||(this._monthsShortRegex=Se),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},kn.week=function(e){return Ue(e,this._week.dow,this._week.doy).week},kn.firstDayOfYear=function(){return this._week.doy},kn.firstDayOfWeek=function(){return this._week.dow},kn.weekdays=function(e,t){var n=s(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(t)?"format":"standalone"];return!0===e?Le(n,this._week.dow):e?n[e.day()]:n},kn.weekdaysMin=function(e){return!0===e?Le(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin},kn.weekdaysShort=function(e){return!0===e?Le(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort},kn.weekdaysParse=function(e,t,n){var s,i,r;if(this._weekdaysParseExact)return Ze.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=c([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[s]||(r="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(r.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},kn.weekdaysRegex=function(e){return this._weekdaysParseExact?(r(this,"_weekdaysRegex")||ze.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(r(this,"_weekdaysRegex")||(this._weekdaysRegex=Ae),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},kn.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(r(this,"_weekdaysRegex")||ze.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(r(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=je),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},kn.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(r(this,"_weekdaysRegex")||ze.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(r(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=Ie),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},kn.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},kn.meridiem=function(e,t,n){return e>11?n?"pm":"PM":n?"am":"AM"},it("en",{eras:[{since:"0001-01-01",until:1/0,offset:1,name:"Anno Domini",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"Before Christ",narrow:"BC",abbr:"BC"}],dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===Z(e%100/10)?"th":1===t?"st":2===t?"nd":3===t?"rd":"th")}}),n.lang=M("moment.lang is deprecated. Use moment.locale instead.",it),n.langData=M("moment.langData is deprecated. Use moment.localeData instead.",at);var Yn=Math.abs;function On(e,t,n,s){var i=Gt(t,n);return e._milliseconds+=s*i._milliseconds,e._days+=s*i._days,e._months+=s*i._months,e._bubble()}function bn(e){return e<0?Math.floor(e):Math.ceil(e)}function xn(e){return 4800*e/146097}function Tn(e){return 146097*e/4800}function Nn(e){return function(){return this.as(e)}}var Pn=Nn("ms"),Rn=Nn("s"),Wn=Nn("m"),Cn=Nn("h"),Hn=Nn("d"),Un=Nn("w"),Fn=Nn("M"),Ln=Nn("Q"),Vn=Nn("y");function Gn(e){return function(){return this.isValid()?this._data[e]:NaN}}var En=Gn("milliseconds"),An=Gn("seconds"),jn=Gn("minutes"),In=Gn("hours"),Zn=Gn("days"),zn=Gn("months"),$n=Gn("years");var qn=Math.round,Bn={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function Jn(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}var Qn=Math.abs;function Xn(e){return(e>0)-(e<0)||+e}function Kn(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n,s,i,r,a,o,u=Qn(this._milliseconds)/1e3,l=Qn(this._days),h=Qn(this._months),d=this.asSeconds();return d?(e=I(u/60),t=I(e/60),u%=60,e%=60,n=I(h/12),h%=12,s=u?u.toFixed(3).replace(/\.?0+$/,""):"",i=d<0?"-":"",r=Xn(this._months)!==Xn(d)?"-":"",a=Xn(this._days)!==Xn(d)?"-":"",o=Xn(this._milliseconds)!==Xn(d)?"-":"",i+"P"+(n?r+n+"Y":"")+(h?r+h+"M":"")+(l?a+l+"D":"")+(t||e||u?"T":"")+(t?o+t+"H":"")+(e?o+e+"M":"")+(u?o+s+"S":"")):"P0D"}var es=Tt.prototype;return es.isValid=function(){return this._isValid},es.abs=function(){var e=this._data;return this._milliseconds=Yn(this._milliseconds),this._days=Yn(this._days),this._months=Yn(this._months),e.milliseconds=Yn(e.milliseconds),e.seconds=Yn(e.seconds),e.minutes=Yn(e.minutes),e.hours=Yn(e.hours),e.months=Yn(e.months),e.years=Yn(e.years),this},es.add=function(e,t){return On(this,e,t,1)},es.subtract=function(e,t){return On(this,e,t,-1)},es.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=V(e))||"quarter"===e||"year"===e)switch(t=this._days+s/864e5,n=this._months+xn(t),e){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(t=this._days+Math.round(Tn(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},es.asMilliseconds=Pn,es.asSeconds=Rn,es.asMinutes=Wn,es.asHours=Cn,es.asDays=Hn,es.asWeeks=Un,es.asMonths=Fn,es.asQuarters=Ln,es.asYears=Vn,es.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*Z(this._months/12):NaN},es._bubble=function(){var e,t,n,s,i,r=this._milliseconds,a=this._days,o=this._months,u=this._data;return r>=0&&a>=0&&o>=0||r<=0&&a<=0&&o<=0||(r+=864e5*bn(Tn(o)+a),a=0,o=0),u.milliseconds=r%1e3,e=I(r/1e3),u.seconds=e%60,t=I(e/60),u.minutes=t%60,n=I(t/60),u.hours=n%24,a+=I(n/24),o+=i=I(xn(a)),a-=bn(Tn(i)),s=I(o/12),o%=12,u.days=a,u.months=o,u.years=s,this},es.clone=function(){return Gt(this)},es.get=function(e){return e=V(e),this.isValid()?this[e+"s"]():NaN},es.milliseconds=En,es.seconds=An,es.minutes=jn,es.hours=In,es.days=Zn,es.weeks=function(){return I(this.days()/7)},es.months=zn,es.years=$n,es.humanize=function(e,t){if(!this.isValid())return this.localeData().invalidDate();var n,s,i=!1,r=Bn;return"object"==typeof e&&(t=e,e=!1),"boolean"==typeof e&&(i=e),"object"==typeof t&&(r=Object.assign({},Bn,t),null!=t.s&&null==t.ss&&(r.ss=t.s-1)),s=function(e,t,n,s){var i=Gt(e).abs(),r=qn(i.as("s")),a=qn(i.as("m")),o=qn(i.as("h")),u=qn(i.as("d")),l=qn(i.as("M")),h=qn(i.as("w")),d=qn(i.as("y")),c=r<=n.ss&&["s",r]||r<n.s&&["ss",r]||a<=1&&["m"]||a<n.m&&["mm",a]||o<=1&&["h"]||o<n.h&&["hh",o]||u<=1&&["d"]||u<n.d&&["dd",u];return null!=n.w&&(c=c||h<=1&&["w"]||h<n.w&&["ww",h]),(c=c||l<=1&&["M"]||l<n.M&&["MM",l]||d<=1&&["y"]||["yy",d])[2]=t,c[3]=+e>0,c[4]=s,Jn.apply(null,c)}(this,!i,r,n=this.localeData()),i&&(s=n.pastFuture(+this,s)),n.postformat(s)},es.toISOString=Kn,es.toString=Kn,es.toJSON=Kn,es.locale=Qt,es.localeData=Kt,es.toIsoString=M("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Kn),es.lang=Xt,C("X",0,0,"unix"),C("x",0,0,"valueOf"),ce("x",ue),ce("X",/[+-]?\d+(\.\d{1,3})?/),ye("X",(function(e,t,n){n._d=new Date(1e3*parseFloat(e))})),ye("x",(function(e,t,n){n._d=new Date(Z(e))})),
+//! moment.js
+n.version="2.29.1",e=St,n.fn=pn,n.min=function(){var e=[].slice.call(arguments,0);return bt("isBefore",e)},n.max=function(){var e=[].slice.call(arguments,0);return bt("isAfter",e)},n.now=function(){return Date.now?Date.now():+new Date},n.utc=c,n.unix=function(e){return St(1e3*e)},n.months=function(e,t){return Dn(e,t,"months")},n.isDate=l,n.locale=it,n.invalid=_,n.duration=Gt,n.isMoment=v,n.weekdays=function(e,t,n){return Sn(e,t,n,"weekdays")},n.parseZone=function(){return St.apply(null,arguments).parseZone()},n.localeData=at,n.isDuration=Nt,n.monthsShort=function(e,t){return Dn(e,t,"monthsShort")},n.weekdaysMin=function(e,t,n){return Sn(e,t,n,"weekdaysMin")},n.defineLocale=rt,n.updateLocale=function(e,t){if(null!=t){var n,s,i=Xe;null!=Ke[e]&&null!=Ke[e].parentLocale?Ke[e].set(b(Ke[e]._config,t)):(null!=(s=st(e))&&(i=s._config),t=b(i,t),null==s&&(t.abbr=e),(n=new x(t)).parentLocale=Ke[e],Ke[e]=n),it(e)}else null!=Ke[e]&&(null!=Ke[e].parentLocale?(Ke[e]=Ke[e].parentLocale,e===it()&&it(e)):null!=Ke[e]&&delete Ke[e]);return Ke[e]},n.locales=function(){return D(Ke)},n.weekdaysShort=function(e,t,n){return Sn(e,t,n,"weekdaysShort")},n.normalizeUnits=V,n.relativeTimeRounding=function(e){return void 0===e?qn:"function"==typeof e&&(qn=e,!0)},n.relativeTimeThreshold=function(e,t){return void 0!==Bn[e]&&(void 0===t?Bn[e]:(Bn[e]=t,"s"===e&&(Bn.ss=t-1),!0))},n.calendarFormat=function(e,t){var n=e.diff(t,"days",!0);return n<-6?"sameElse":n<-1?"lastWeek":n<0?"lastDay":n<1?"sameDay":n<2?"nextDay":n<7?"nextWeek":"sameElse"},n.prototype=pn,n.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},n}));
+//# sourceMappingURL=/sm/ac6ca6e51d8435fbb492538442f7060550b81bb0c2505d4048856d957213e3a8.map
+\ No newline at end of file
diff --git a/static/tempestas.js b/static/tempestas.js
@@ -0,0 +1,86 @@
+/* Warning: I am not a web developer and have absolutely zero idea what I'm
+ doing. This is almost certainly composed entirely of Very Bad Ideas. */
+
+var sensors = [
+ {id: '8558074', name: 'Back yard', color: 'rgb(75, 192, 192)'},
+ {id: '10714323', name: 'Master bedroom', color: 'rgb(255, 99, 132)'},
+ {id: '6497060', name: 'Dining room', color: 'rgb(255, 159, 64)'},
+];
+var charts = [
+ {id: 'chart-temperature', title: 'Temperature (°C)', readingType: 'BME280_temperature'},
+ {id: 'chart-humidity', title: 'Humidity (%)', readingType: 'BME280_humidity'},
+ {id: 'chart-pressure', title: 'Pressure (Pa)', readingType: 'BME280_pressure'},
+];
+var sensorReadings = {};
+
+charts.forEach((chart, i) => sensorReadings[chart.id] = {});
+sensors.forEach((sensor, i) => fetchSensorData(sensor.id, charts[0]));
+sensors.forEach((sensor, i) => fetchSensorData(sensor.id, charts[1]));
+sensors.forEach((sensor, i) => fetchSensorData(sensor.id, charts[2]));
+
+function fetchSensorData(sensorId, chart) {
+ var xmlhttp = new XMLHttpRequest();
+ var url = '/sensor/reading/' + sensorId + '/' + chart.readingType;
+ xmlhttp.onreadystatechange = function() {
+ if (this.readyState == 4 && this.status == 200) {
+ var readings = JSON.parse(this.responseText);
+ if (readings.length > 0) {
+ sensorId = readings[0].sensor_id;
+ sensorReadings[chart.id][sensorId] = readings;
+ }
+ updateChart(chart);
+ }
+ };
+ xmlhttp.open("GET", url, true);
+ xmlhttp.send();
+}
+
+function updateChart(chart) {
+ for (let i = 0; i < sensors.length; i++) {
+ var sensorId = sensors[i].id;
+ if (sensorReadings[chart.id][sensorId] == null) {
+ return;
+ }
+ }
+
+ data = {
+ labels: sensorReadings[chart.id][sensors[0].id].map(e => Date.parse(e.time)),
+ datasets: [],
+ };
+ for (let i = 0; i < sensors.length; i++) {
+ var sensorId = sensors[i].id;
+ data.datasets.push({
+ data: sensorReadings[chart.id][sensorId].map(e => e.value),
+ label: sensors[i].name,
+ radius: 0,
+ borderWidth: 1,
+ borderColor: sensors[i].color,
+ fill: false,
+ });
+ }
+
+ var ctx = document.getElementById(chart.id).getContext('2d');
+ var chart = new Chart(ctx, {
+ type: 'line',
+ data: data,
+ options: {
+ plugins: {
+ title: {
+ display: true,
+ text: chart.title,
+ },
+ legend: {
+ position: 'bottom',
+ },
+ },
+ scales: {
+ x: {
+ type: 'time',
+ time: {
+ unit: 'hour',
+ },
+ },
+ },
+ },
+ });
+}