From a3e456c283d011539cb6c3c4e597f53275235320 Mon Sep 17 00:00:00 2001 From: AnHeuermann <38031952+AnHeuermann@users.noreply.github.com> Date: Tue, 24 Feb 2026 15:47:07 +0100 Subject: [PATCH] Implement full BaseModelicaLibraryTesting pipeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a complete four-phase pipeline for testing Modelica libraries via Base Modelica and Julia: 1. Export – instantiate models to .bmo via OMJulia (src/export.jl) 2. Parse – create ODEProblem via BaseModelica.jl (src/parse_bm.jl) 3. Simulate – solve with Rodas5P from DifferentialEquations.jl (src/simulate.jl) 4. Compare – validate against MAP-LIB reference CSVs with configurable rel/abs tolerances; generate interactive Dygraph diff pages (src/compare.jl) Top-level `main()` and `test_model()` orchestrate the full pipeline and produce an HTML summary report (src/pipeline.jl, src/report.jl). Also includes: - CI workflow: add OpenModelica setup, omc-version matrix, sanity check step against MSL ChuaCircuit, and artifact upload - Project.toml: add dependencies (BaseModelica, DifferentialEquations, ModelingToolkit, OMJulia, ZMQ, etc.) - assets/: bundle Dygraph JS/CSS and an HTML diff template - README: add usage docs and MSL v4.1.0 example - .gitignore: exclude generated logs, CSVs, HTMLs, and result directories Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/CI.yml | 25 +- .gitignore | 12 + Project.toml | 13 +- README.md | 58 ++++- assets/diff_template.html | 95 ++++++++ assets/dygraph.min.css | 87 +++++++ assets/dygraph.min.js | 3 + src/BaseModelicaLibraryTesting.jl | 41 +++- src/compare.jl | 393 ++++++++++++++++++++++++++++++ src/export.jl | 47 ++++ src/parse_bm.jl | 40 +++ src/pipeline.jl | 141 +++++++++++ src/report.jl | 118 +++++++++ src/simulate.jl | 68 ++++++ src/types.jl | 52 ++++ test/runtests.jl | 142 ++++++++++- 16 files changed, 1322 insertions(+), 13 deletions(-) create mode 100644 assets/diff_template.html create mode 100644 assets/dygraph.min.css create mode 100644 assets/dygraph.min.js create mode 100644 src/compare.jl create mode 100644 src/export.jl create mode 100644 src/parse_bm.jl create mode 100644 src/pipeline.jl create mode 100644 src/report.jl create mode 100644 src/simulate.jl create mode 100644 src/types.jl diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 250086ca3..9591105b2 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -22,6 +22,8 @@ jobs: strategy: fail-fast: false matrix: + omc-version: + - 'nightly' version: - '1.10' - '1.12' @@ -31,10 +33,31 @@ jobs: - x64 steps: - uses: actions/checkout@v6 - - uses: julia-actions/setup-julia@v2 + + - name: "Set up OpenModelica Compiler" + uses: OpenModelica/setup-openmodelica@v1.0 + with: + version: ${{ matrix.omc-version }} + packages: | + omc + libraries: | + 'Modelica 4.1.0' + + - name: "Setup Julia ${{ matrix.version }}-${{ matrix.arch }}" + uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - uses: julia-actions/cache@v2 - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 + + - name: Sanity check + run: | + julia --project='.' -e 'using BaseModelicaLibraryTesting; main(library = "Modelica", version = "4.1.0", filter = "Modelica.Electrical.Analog.Examples.ChuaCircuit", results_root = "main/Modelica/4.1.0/")' + + - name: Upload test results + uses: actions/upload-artifact@v6 + with: + name: test-results-${{ matrix.version }}-${{ matrix.os }}-${{ matrix.arch }} + path: main/ diff --git a/.gitignore b/.gitignore index 1c8b450d7..d7ddbf77f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,15 @@ # Julia files /Manifest*.toml + +# Python +.CondaPkg/ + +# Generated files and example results +*.log +*.html +!asserts/*.html +*.csv +*.bmo +MAP-LIB_ReferenceResults/ +main/ diff --git a/Project.toml b/Project.toml index f744705da..04752939a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,9 +1,20 @@ name = "BaseModelicaLibraryTesting" uuid = "e216686d-a052-4e92-9543-563498248f9c" -authors = ["Andreas Heuermann"] version = "0.1.0-DEV" +authors = ["AnHeuermann"] + +[deps] +BaseModelica = "a17d5099-185d-4ff5-b5d3-51aa4569e56d" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" +DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa" +ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78" +OMJulia = "0f4fe800-344e-11e9-2949-fb537ad918e1" +Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7" +Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +ZMQ = "c2297ded-f4af-51ae-bb23-16f91089e4e1" [compat] +OMJulia = "0.3.3" julia = "1.10.10, 1.12.5" [extras] diff --git a/README.md b/README.md index 74246b0e9..d4b36baa2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# BaseModelicaLibraryTesting +# BaseModelicaLibraryTesting.jl -[![Build Status](https://github.com/OpenModelica/BaseModelicaLibraryTesting.jl/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/OpenModelica/BaseModelicaLibraryTesting.jl/actions/workflows/CI.yml?query=branch%3Amain) +[![Build Status][build-badge-svg]][build-action-url] Experimental Base Modelica library testing based on Julia. @@ -15,16 +15,64 @@ For a given Modelica library test [DifferentialEquations.jl][diffeqjl-url]) 4. Validating simulation results +## Usage + +```julia +main( + library = "", + version = "", + filter = "", + omc_exe = "path/to/omc", + results_root = "results", + ref_root = "path/to/ReferenceResults" +) +``` + +If reference results are available provide the path via `ref_root`. + +### Example - Testing the Modelica Standard Library v4.1.0 + +For example, for the Modelica Standard Library v4.1.0 reference results can be obtained by cloning the [MAP-LIB_ReferenceResults][map-lib-ref-results-url] repository:` + +```bash +git clone --depth 1 -b v4.1.0 https://github.com/modelica/MAP-LIB_ReferenceResults +``` + +Run the library testing for the ChuaCircuit example of the Modelica Standard +Library v4.1.0 with: + +```julia +using BaseModelicaLibraryTesting + +main( + library = "Modelica", + version = "4.1.0", + filter = "Modelica.Electrical.Analog.Examples.ChuaCircuit", + omc_exe = "omc", + results_root = "main/Modelica/4.1.0/", + ref_root = "MAP-LIB_ReferenceResults" +) +``` + +Preview the generated HTML report at `main/Modelica/4.1.0/report.html`. + +```bash +python -m http.server -d main/Modelica/4.1.0/ +``` + ## License This package is available under the [OSMC-PL License][osmc-license-file] and the [AGPL-3.0 License][agpl-file]. See the [OSMC-License.txt][osmc-license-file] file for details. +[build-badge-svg]: https://github.com/OpenModelica/BaseModelicaLibraryTesting.jl/actions/workflows/CI.yml/badge.svg?branch=main +[build-action-url]: https://github.com/OpenModelica/BaseModelicaLibraryTesting.jl/actions/workflows/CI.yml?query=branch%3Amain [openmodelica-url]: https://openmodelica.org/ -[omjuliajl-url]: https://github.com/OpenModelica/OMJulia.jl -[osmc-license-file]: OSMC-License.txt -[agpl-file]: LICENSE [basemodelicajl-url]: https://github.com/SciML/BaseModelica.jl [modelingtoolkitjl-url]: https://github.com/SciML/ModelingToolkit.jl [diffeqjl-url]: https://github.com/SciML/DifferentialEquations.jl +[omjuliajl-url]: https://github.com/OpenModelica/OMJulia.jl +[map-lib-ref-results-url]: https://github.com/modelica/MAP-LIB_ReferenceResults/tree/v4.1.0 +[osmc-license-file]: OSMC-License.txt +[agpl-file]: LICENSE diff --git a/assets/diff_template.html b/assets/diff_template.html new file mode 100644 index 000000000..c333a831b --- /dev/null +++ b/assets/diff_template.html @@ -0,0 +1,95 @@ + + + + + Diff — {{TITLE}} + + + + + +

Diff — {{MODEL}}

+

+ {{N_FAIL}} signal(s) outside tolerance + (rel ≤ {{REL_TOL_PCT}}%,  abs ≤ {{ABS_TOL}}) +  ·  + Download CSV +

+
+ + + diff --git a/assets/dygraph.min.css b/assets/dygraph.min.css new file mode 100644 index 000000000..eaf0b349a --- /dev/null +++ b/assets/dygraph.min.css @@ -0,0 +1,87 @@ +.dygraph-legend { + position: absolute; + font-size: 14px; + z-index: 10; + width: 250px; + background: #fff; + line-height: normal; + text-align: left; + overflow: hidden +} + +.dygraph-legend[dir=rtl] { + text-align: right +} + +.dygraph-legend-line { + display: inline-block; + position: relative; + bottom: .5ex; + padding-left: 1em; + height: 1px; + border-bottom-width: 2px; + border-bottom-style: solid +} + +.dygraph-legend-dash { + display: inline-block; + position: relative; + bottom: .5ex; + height: 1px; + border-bottom-width: 2px; + border-bottom-style: solid +} + +.dygraph-roller { + position: absolute; + z-index: 10 +} + +.dygraph-annotation { + position: absolute; + z-index: 10; + overflow: hidden +} + +.dygraph-default-annotation { + border: 1px solid #000; + background-color: #fff; + text-align: center +} + +.dygraph-axis-label { + z-index: 10; + line-height: normal; + overflow: hidden; + color: #000 +} + +.dygraph-title { + font-weight: 700; + z-index: 10; + text-align: center +} + +.dygraph-xlabel { + text-align: center +} + +.dygraph-label-rotate-left { + text-align: center; + transform: rotate(90deg); + -webkit-transform: rotate(90deg); + -moz-transform: rotate(90deg); + -o-transform: rotate(90deg); + -ms-transform: rotate(90deg) +} + +.dygraph-label-rotate-right { + text-align: center; + transform: rotate(-90deg); + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -o-transform: rotate(-90deg); + -ms-transform: rotate(-90deg) +} + +/*# sourceMappingURL=dygraph.min.css.map */ diff --git a/assets/dygraph.min.js b/assets/dygraph.min.js new file mode 100644 index 000000000..fba7edbe9 --- /dev/null +++ b/assets/dygraph.min.js @@ -0,0 +1,3 @@ +/*! @license https://github.com/danvk/dygraphs/blob/v2.2.1/LICENSE.txt (MIT) */ +!function (t) { "object" == typeof exports && "undefined" != typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define([], t) : ("undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : this).Dygraph = t() }(function () { var t = function n(i, r, o) { function s(e, t) { if (!r[e]) { if (!i[e]) { var a = "function" == typeof require && require; if (!t && a) return a(e, !0); if (l) return l(e, !0); throw (t = new Error("Cannot find module '" + e + "'")).code = "MODULE_NOT_FOUND", t } a = r[e] = { exports: {} }, i[e][0].call(a.exports, function (t) { return s(i[e][1][t] || t) }, a, a.exports, n, i, r, o) } return r[e].exports } for (var l = "function" == typeof require && require, t = 0; t < o.length; t++)s(o[t]); return s }({ "dygraphs/src/datahandler/bars-custom.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; t = (t = t("./bars")) && t.__esModule ? t : { default: t }; function n() { } (n.prototype = new t.default).extractSeries = function (t, e, a) { for (var n, i, r, o = [], s = a.get("labels")[e], l = a.getForSeries("logscale", s), h = 0; h < t.length; h++)n = t[h][0], r = t[h][e], null !== (r = l && null !== r && (r[0] <= 0 || r[1] <= 0 || r[2] <= 0) ? null : r) ? null === (i = r[1]) || isNaN(i) ? o.push([n, i, [i, i]]) : o.push([n, i, [r[0], r[2]]]) : o.push([n, null, [null, null]]); return o }, n.prototype.rollingAverage = function (t, e, a, n) { e = Math.min(e, t.length); var i = [], r = 0, o = 0, s = 0, l = 0; for (n = 0; n < t.length; n++) { var h = t[n][1], d = t[n][2]; i[n] = t[n], null === h || isNaN(h) || (r += d[0], o += h, s += d[1], l += 1), 0 <= n - e && (null === (h = t[n - e])[1] || isNaN(h[1]) || (r -= h[2][0], o -= h[1], s -= h[2][1], --l)), i[n] = l ? [t[n][0], +o / l, [+r / l, +s / l]] : [t[n][0], null, [null, null]] } return i }, a.default = n, e.exports = a.default }, { "./bars": "dygraphs/src/datahandler/bars.js" }], "dygraphs/src/datahandler/bars-error.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; t = (t = t("./bars")) && t.__esModule ? t : { default: t }; function n() { } (n.prototype = new t.default).extractSeries = function (t, e, a) { for (var n, i, r, o, s = [], l = a.get("labels")[e], h = a.getForSeries("logscale", l), d = a.getForSeries("sigma", l), u = 0; u < t.length; u++)n = t[u][0], o = t[u][e], null !== (o = h && null !== o && (o[0] <= 0 || o[0] - d * o[1] <= 0) ? null : o) ? null === (i = o[0]) || isNaN(i) ? s.push([n, i, [i, i, i]]) : (r = d * o[1], s.push([n, i, [i - r, i + r, o[1]]])) : s.push([n, null, [null, null, null]]); return s }, n.prototype.rollingAverage = function (t, e, a, n) { e = Math.min(e, t.length); var i, r, o, s, l, h, d, u = [], c = a.get("labels")[n], p = a.getForSeries("sigma", c); for (n = 0; n < t.length; n++) { for (s = h = o = 0, i = Math.max(0, n - e + 1); i < n + 1; i++)null === (r = t[i][1]) || isNaN(r) || (s++, o += r, h += Math.pow(t[i][2][2], 2)); s ? (l = Math.sqrt(h) / s, u[n] = [t[n][0], d = o / s, [d - p * l, d + p * l]]) : (d = 1 == e ? t[n][1] : null, u[n] = [t[n][0], d, [d, d]]) } return u }, a.default = n, e.exports = a.default }, { "./bars": "dygraphs/src/datahandler/bars.js" }], "dygraphs/src/datahandler/bars-fractions.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; t = (t = t("./bars")) && t.__esModule ? t : { default: t }; function n() { } (n.prototype = new t.default).extractSeries = function (t, e, a) { for (var n, i, r, o, s, l = [], h = a.get("labels")[e], d = a.getForSeries("logscale", h), u = a.getForSeries("sigma", h), c = 0; c < t.length; c++)n = t[c][0], r = t[c][e], null !== (r = d && null !== r && (r[0] <= 0 || r[1] <= 0) ? null : r) ? (i = r[0], r = r[1], null === i || isNaN(i) ? l.push([n, i, [i, i, i, r]]) : (o = r ? i / r : 0, s = r ? u * Math.sqrt(o * (1 - o) / r) : 1, l.push([n, o = 100 * o, [o - (s = 100 * s), o + s, i, r]]))) : l.push([n, null, [null, null, null, null]]); return l }, n.prototype.rollingAverage = function (t, e, a, n) { e = Math.min(e, t.length); var i = [], r = a.get("labels")[n], o = a.getForSeries("sigma", r), s = a.getForSeries("wilsonInterval", r), l = 0, h = 0; for (n = 0; n < t.length; n++) { l += t[n][2][2], h += t[n][2][3], 0 <= n - e && (l -= t[n - e][2][2], h -= t[n - e][2][3]); var d, u, c, p = t[n][0], g = h ? l / h : 0; s ? h ? (d = g < 0 ? 0 : g, u = h, u = o * Math.sqrt(d * (1 - d) / u + o * o / (4 * u * u)), i[n] = [p, 100 * d, [100 * ((d + o * o / (2 * h) - u) / (c = 1 + o * o / h)), 100 * ((d + o * o / (2 * h) + u) / c)]]) : i[n] = [p, 0, [0, 0]] : (d = h ? o * Math.sqrt(g * (1 - g) / h) : 1, i[n] = [p, 100 * g, [100 * (g - d), 100 * (g + d)]]) } return i }, a.default = n, e.exports = a.default }, { "./bars": "dygraphs/src/datahandler/bars.js" }], "dygraphs/src/datahandler/bars.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var r = n(t("./datahandler")), o = n(t("../dygraph-layout")); function n(t) { return t && t.__esModule ? t : { default: t } } function i() { r.default.call(this) } (i.prototype = new r.default).extractSeries = function (t, e, a) { }, i.prototype.rollingAverage = function (t, e, a, n) { }, i.prototype.onPointsCreated_ = function (t, e) { for (var a = 0; a < t.length; ++a) { var n = t[a], i = e[a]; i.y_top = NaN, i.y_bottom = NaN, i.yval_minus = r.default.parseFloat(n[2][0]), i.yval_plus = r.default.parseFloat(n[2][1]) } }, i.prototype.getExtremeYValues = function (t, e, a) { for (var n, i, r, o = null, s = null, l = t.length - 1, h = 0; h <= l; h++)null !== (r = t[h][1]) && !isNaN(r) && (r < (n = t[h][2][0]) && (n = r), (i = t[h][2][1]) < r && (i = r), (null === s || s < i) && (s = i), null === o || n < o) && (o = n); return [o, s] }, i.prototype.onLineEvaluated = function (t, e, a) { for (var n, i = 0; i < t.length; i++)(n = t[i]).y_top = o.default.calcYNormal_(e, n.yval_minus, a), n.y_bottom = o.default.calcYNormal_(e, n.yval_plus, a) }, a.default = i, e.exports = a.default }, { "../dygraph-layout": "dygraphs/src/dygraph-layout.js", "./datahandler": "dygraphs/src/datahandler/datahandler.js" }], "dygraphs/src/datahandler/datahandler.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; function n() { } var s = n; s.X = 0, s.Y = 1, s.EXTRAS = 2, s.prototype.extractSeries = function (t, e, a) { }, s.prototype.seriesToPoints = function (t, e, a) { for (var n = [], i = 0; i < t.length; ++i) { var r = t[i], o = r[1], o = null === o ? null : s.parseFloat(o), r = { x: NaN, y: NaN, xval: s.parseFloat(r[0]), yval: o, name: e, idx: i + a, canvasx: NaN, canvasy: NaN }; n.push(r) } return this.onPointsCreated_(t, n), n }, s.prototype.onPointsCreated_ = function (t, e) { }, s.prototype.rollingAverage = function (t, e, a, n) { }, s.prototype.getExtremeYValues = function (t, e, a) { }, s.prototype.onLineEvaluated = function (t, e, a) { }, s.parseFloat = function (t) { return null === t ? NaN : t }, a.default = n, e.exports = a.default }, {}], "dygraphs/src/datahandler/default-fractions.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; n(t("./datahandler")); t = n(t("./default")); function n(t) { return t && t.__esModule ? t : { default: t } } function i() { } (i.prototype = new t.default).extractSeries = function (t, e, a) { for (var n, i, r, o = [], s = a.get("labels")[e], l = a.getForSeries("logscale", s), h = 0; h < t.length; h++)n = t[h][0], r = t[h][e], null !== (r = l && null !== r && (r[0] <= 0 || r[1] <= 0) ? null : r) ? (i = r[0], r = r[1], null === i || isNaN(i) ? o.push([n, i, [i, r]]) : o.push([n, 100 * (r ? i / r : 0), [i, r]])) : o.push([n, null, [null, null]]); return o }, i.prototype.rollingAverage = function (t, e, a, n) { e = Math.min(e, t.length); var i = [], r = 0, o = 0; for (n = 0; n < t.length; n++) { r += t[n][2][0], o += t[n][2][1], 0 <= n - e && (r -= t[n - e][2][0], o -= t[n - e][2][1]); var s = t[n][0]; i[n] = [s, 100 * (o ? r / o : 0)] } return i }, a.default = i, e.exports = a.default }, { "./datahandler": "dygraphs/src/datahandler/datahandler.js", "./default": "dygraphs/src/datahandler/default.js" }], "dygraphs/src/datahandler/default.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; t = (t = t("./datahandler")) && t.__esModule ? t : { default: t }; function n() { } (n.prototype = new t.default).extractSeries = function (t, e, a) { for (var n = [], i = a.get("labels")[e], r = a.getForSeries("logscale", i), o = 0; o < t.length; o++) { var s = t[o][0], l = t[o][e]; n.push([s, l = r && l <= 0 ? null : l]) } return n }, n.prototype.rollingAverage = function (t, e, a, n) { var i, r, o, s, l = []; if (1 == (e = Math.min(e, t.length))) return t; for (n = 0; n < t.length; n++) { for (s = o = 0, i = Math.max(0, n - e + 1); i < n + 1; i++)null === (r = t[i][1]) || isNaN(r) || (s++, o += t[i][1]); l[n] = s ? [t[n][0], o / s] : [t[n][0], null] } return l }, n.prototype.getExtremeYValues = function (t, e, a) { for (var n, i = null, r = null, o = t.length - 1, s = 0; s <= o; s++)null !== (n = t[s][1]) && !isNaN(n) && ((null === r || r < n) && (r = n), null === i || n < i) && (i = n); return [i, r] }, a.default = n, e.exports = a.default }, { "./datahandler": "dygraphs/src/datahandler/datahandler.js" }], "dygraphs/src/dygraph-canvas.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var T = function (t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = o(e); if (e && e.has(t)) return e.get(t); var a, n = {}, i = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) { var r; "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((r = i ? Object.getOwnPropertyDescriptor(t, a) : null) && (r.get || r.set) ? Object.defineProperty(n, a, r) : n[a] = t[a]) } n.default = t, e && e.set(t, n); return n }(t("./dygraph-utils")), D = (t = t("./dygraph")) && t.__esModule ? t : { default: t }; function o(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (o = function (t) { return t ? a : e })(t)) } function E(t, e, a, n) { if (this.dygraph_ = t, this.layout = n, this.element = e, this.elementContext = a, this.height = t.height_, this.width = t.width_, !T.isCanvasSupported(this.element)) throw "Canvas is not supported."; this.area = n.getPlotArea(), (e = this.dygraph_.canvas_ctx_).beginPath(), e.rect(this.area.x, this.area.y, this.area.w, this.area.h), e.clip(), (e = this.dygraph_.hidden_ctx_).beginPath(), e.rect(this.area.x, this.area.y, this.area.w, this.area.h), e.clip() } E.prototype.clear = function () { this.elementContext.clearRect(0, 0, this.width, this.height) }, E.prototype.render = function () { this._updatePoints(), this._renderLineChart() }, E._getIteratorPredicate = function (t) { return t ? E._predicateThatSkipsEmptyPoints : null }, E._predicateThatSkipsEmptyPoints = function (t, e) { return null !== t[e].yval }, E._drawStyledLine = function (t, e, a, n, i, r, o) { var s = t.dygraph, l = s.getBooleanOption("stepPlot", t.setName), h = (T.isArrayLike(n) || (n = null), s.getBooleanOption("drawGapEdgePoints", t.setName)), d = t.points, u = t.setName, d = T.createIterator(d, 0, d.length, E._getIteratorPredicate(s.getBooleanOption("connectSeparatedPoints", u))), s = n && 2 <= n.length, u = t.drawingContext, n = (u.save(), s && u.setLineDash && u.setLineDash(n), E._drawSeries(t, d, a, o, i, h, l, e)); E._drawPointsOnLine(t, n, r, e, o), s && u.setLineDash && u.setLineDash([]), u.restore() }, E._drawSeries = function (t, e, a, n, i, r, o, s) { for (var l, h, d, u = null, c = null, p = [], g = !0, f = t.drawingContext, _ = (f.beginPath(), f.strokeStyle = s, f.lineWidth = a, e.array_), y = e.end_, v = e.predicate_, x = e.start_; x < y; x++) { if (l = _[x], v) { for (; x < y && !v(_, x);)x++; if (x == y) break; l = _[x] } null === l.canvasy || l.canvasy != l.canvasy ? (o && null !== u && (f.moveTo(u, c), f.lineTo(l.canvasx, c)), u = c = null) : (d = !1, (r || null === u) && (e.nextIdx_ = x, e.next(), h = null === (h = e.hasNext ? e.peek.canvasy : null) || h != h, d = null === u && h, r) && (!g && null === u || e.hasNext && h) && (d = !0), null !== u ? a && (o && (f.moveTo(u, c), f.lineTo(l.canvasx, c)), f.lineTo(l.canvasx, l.canvasy)) : f.moveTo(l.canvasx, l.canvasy), (i || d) && p.push([l.canvasx, l.canvasy, l.idx]), u = l.canvasx, c = l.canvasy), g = !1 } return f.stroke(), p }, E._drawPointsOnLine = function (t, e, a, n, i) { for (var r = t.drawingContext, o = 0; o < e.length; o++) { var s = e[o]; r.save(), a.call(t.dygraph, t.dygraph, t.setName, r, s[0], s[1], n, i, s[2]), r.restore() } }, E.prototype._updatePoints = function () { for (var t = this.layout.points, e = t.length; e--;)for (var a = t[e], n = a.length; n--;) { var i = a[n]; i.canvasx = this.area.w * i.x + this.area.x, i.canvasy = this.area.h * i.y + this.area.y } }, E.prototype._renderLineChart = function (t, e) { for (var a = e || this.elementContext, n = this.layout.points, i = this.layout.setNames, r = (this.colors = this.dygraph_.colorsMap_, this.dygraph_.getOption("plotter")), o = r, s = (T.isArrayLike(o) || (o = [o]), {}), l = 0; l < i.length; l++) { var h = i[l], d = this.dygraph_.getOption("plotter", h); d != r && (s[h] = d) } for (l = 0; l < o.length; l++)for (var u = o[l], c = l == o.length - 1, p = 0; p < n.length; p++)if (h = i[p], !t || h == t) { var g = n[p], f = u; if (h in s) { if (!c) continue; f = s[h] } var _ = this.colors[h], y = this.dygraph_.getOption("strokeWidth", h); a.save(), a.strokeStyle = _, a.lineWidth = y, f({ points: g, setName: h, drawingContext: a, color: _, strokeWidth: y, dygraph: this.dygraph_, axis: this.dygraph_.axisPropertiesForSeries(h), plotArea: this.area, seriesIndex: p, seriesCount: n.length, singleSeriesName: t, allSeriesPoints: n }), a.restore() } }, E._Plotters = { linePlotter: function (t) { E._linePlotter(t) }, fillPlotter: function (t) { E._fillPlotter(t) }, errorPlotter: function (t) { E._errorPlotter(t) } }, E._linePlotter = function (t) { var e = t.dygraph, a = t.setName, n = t.strokeWidth, i = e.getNumericOption("strokeBorderWidth", a), r = e.getOption("drawPointCallback", a) || T.Circles.DEFAULT, o = e.getOption("strokePattern", a), s = e.getBooleanOption("drawPoints", a), l = e.getNumericOption("pointSize", a); i && n && E._drawStyledLine(t, e.getOption("strokeBorderColor", a), n + 2 * i, o, s, r, l), E._drawStyledLine(t, t.color, n, o, s, r, l) }, E._errorPlotter = function (t) { var e = t.dygraph, a = t.setName; if (e.getBooleanOption("errorBars") || e.getBooleanOption("customBars")) { e.getBooleanOption("fillGraph", a) && console.warn("Can't use fillGraph option with customBars or errorBars option"); for (var n, i = t.drawingContext, r = t.color, o = e.getNumericOption("fillAlpha", a), s = e.getBooleanOption("stepPlot", a), l = t.points, h = T.createIterator(l, 0, l.length, E._getIteratorPredicate(e.getBooleanOption("connectSeparatedPoints", a))), d = NaN, u = NaN, c = [-1, -1], l = T.toRGB_(r), e = "rgba(" + l.r + "," + l.g + "," + l.b + "," + o + ")", p = (i.fillStyle = e, i.beginPath(), function (t) { return null == t || isNaN(t) }); h.hasNext;) { var g = h.next(); !s && p(g.y) || s && !isNaN(u) && p(u) ? d = NaN : (n = [g.y_bottom, g.y_top], s && (u = g.y), isNaN(n[0]) && (n[0] = g.y), isNaN(n[1]) && (n[1] = g.y), n[0] = t.plotArea.h * n[0] + t.plotArea.y, n[1] = t.plotArea.h * n[1] + t.plotArea.y, isNaN(d) || (s ? (i.moveTo(d, c[0]), i.lineTo(g.canvasx, c[0]), i.lineTo(g.canvasx, c[1])) : (i.moveTo(d, c[0]), i.lineTo(g.canvasx, n[0]), i.lineTo(g.canvasx, n[1])), i.lineTo(d, c[1]), i.closePath()), c = n, d = g.canvasx) } i.fill() } }, E._fastCanvasProxy = function (i) { function r(t) { c(t); for (var e = 0, a = h.length; e < a; e++) { var n = h[e]; n[0] == d ? i.lineTo(n[1], n[2]) : n[0] == u && i.moveTo(n[1], n[2]) } h.length && (s = h[h.length - 1][1]), l += h.length, h = [] } function a(t, e, a) { var n = Math.round(e); null !== o && n == o || (r(1 < o - s || 1 < n - o), o = n), h.push([t, e, a]) } var h = [], o = null, s = null, d = 1, u = 2, l = 0, c = function (t) { if (!(h.length <= 1)) { for (var e, a = h.length - 1; 0 < a; a--)(n = h[a])[0] == u && (e = h[a - 1])[1] == n[1] && e[2] == n[2] && h.splice(a, 1); for (a = 0; a < h.length - 1;)(n = h[a])[0] == u && h[a + 1][0] == u ? h.splice(a, 1) : a++; if (2 < h.length && !t) { for (var n, i, t = 0, r = (h[0][0] == u && t++, null), o = null, a = t; a < h.length; a++)(n = h[a])[0] == d && (null === r && null === o ? o = r = a : (i = n[2]) < h[r][2] ? r = a : i > h[o][2] && (o = a)); var s = h[r], l = h[o]; h.splice(t, h.length - t), r < o ? (h.push(s), h.push(l)) : (o < r && h.push(l), h.push(s)) } } }; return { moveTo: function (t, e) { a(u, t, e) }, lineTo: function (t, e) { a(d, t, e) }, stroke: function () { r(!0), i.stroke() }, fill: function () { r(!0), i.fill() }, beginPath: function () { r(!0), i.beginPath() }, closePath: function () { r(!0), i.closePath() }, _count: function () { return l } } }, E._fillPlotter = function (t) { if (!t.singleSeriesName && 0 === t.seriesIndex) { for (var e = t.dygraph, a = e.getLabels().slice(1), n = a.length; 0 <= n; n--)e.visibility()[n] || a.splice(n, 1); if (function () { for (var t = 0; t < a.length; t++)if (e.getBooleanOption("fillGraph", a[t])) return !0; return !1 }()) for (var i, r = t.plotArea, o = t.allSeriesPoints, s = o.length, l = e.getBooleanOption("stackedGraph"), h = e.getColors(), d = {}, u = function (t, e, a, n) { if (t.lineTo(e, a), l) for (var i = n.length - 1; 0 <= i; i--) { var r = n[i]; t.lineTo(r[0], r[1]) } }, c = s - 1; 0 <= c; c--) { var p = t.drawingContext, g = a[c]; if (e.getBooleanOption("fillGraph", g)) { var f = e.getNumericOption("fillAlpha", g), _ = e.getBooleanOption("stepPlot", g), y = h[c], v = e.axisPropertiesForSeries(g), x = 1 + v.minyval * v.yscale, v = (x < 0 ? x = 0 : 1 < x && (x = 1), x = r.h * x + r.y, o[c]), m = T.createIterator(v, 0, v.length, E._getIteratorPredicate(e.getBooleanOption("connectSeparatedPoints", g))), b = NaN, w = [-1, -1], g = T.toRGB_(y), y = "rgba(" + g.r + "," + g.g + "," + g.b + "," + f + ")"; p.fillStyle = y, p.beginPath(); for (var O, A = !0, P = ((v.length > 2 * e.width_ || D.default.FORCE_FAST_PROXY) && (p = E._fastCanvasProxy(p)), []); m.hasNext;)if (O = m.next(), T.isOK(O.y) || _) { if (l) { if (!A && L == O.xval) continue; var S, A = !1, L = O.xval, M = void 0 === (S = d[O.canvasx]) ? x : i ? S[0] : S, C = [O.canvasy, M]; _ ? -1 === w[0] ? d[O.canvasx] = [O.canvasy, x] : d[O.canvasx] = [O.canvasy, w[0]] : d[O.canvasx] = O.canvasy } else C = isNaN(O.canvasy) && _ ? [r.y + r.h, x] : [O.canvasy, x]; isNaN(b) ? (p.moveTo(O.canvasx, C[1]), p.lineTo(O.canvasx, C[0])) : (_ && p.lineTo(O.canvasx, w[0]), p.lineTo(O.canvasx, C[0]), l && (P.push([b, w[1]]), i && S ? P.push([O.canvasx, S[1]]) : P.push([O.canvasx, C[1]]))), w = C, b = O.canvasx } else u(p, b, w[1], P), P = [], b = NaN, null === O.y_stacked || isNaN(O.y_stacked) || (d[O.canvasx] = r.h * O.y_stacked + r.y); i = _, C && O && (u(p, O.canvasx, C[1], P), P = []), p.fill() } } } }, a.default = E, e.exports = a.default }, { "./dygraph": "dygraphs/src/dygraph.js", "./dygraph-utils": "dygraphs/src/dygraph-utils.js" }], "dygraphs/src/dygraph-default-attrs.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var n = l(t("./dygraph-tickers")), i = o(t("./dygraph-interaction-model")), r = o(t("./dygraph-canvas")), t = l(t("./dygraph-utils")); function o(t) { return t && t.__esModule ? t : { default: t } } function s(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (s = function (t) { return t ? a : e })(t)) } function l(t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = s(e); if (e && e.has(t)) return e.get(t); var a, n, i = {}, r = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((n = r ? Object.getOwnPropertyDescriptor(t, a) : null) && (n.get || n.set) ? Object.defineProperty(i, a, n) : i[a] = t[a]); return i.default = t, e && e.set(t, i), i } i = { highlightCircleSize: 3, highlightSeriesOpts: null, highlightSeriesBackgroundAlpha: .5, highlightSeriesBackgroundColor: "rgb(255, 255, 255)", labelsSeparateLines: !1, labelsShowZeroValues: !0, labelsKMB: !1, labelsKMG2: !1, showLabelsOnHighlight: !0, digitsAfterDecimal: 2, maxNumberWidth: 6, sigFigs: null, strokeWidth: 1, strokeBorderWidth: 0, strokeBorderColor: "white", axisTickSize: 3, axisLabelFontSize: 14, rightGap: 5, showRoller: !1, xValueParser: void 0, delimiter: ",", sigma: 2, errorBars: !1, fractions: !1, wilsonInterval: !0, customBars: !1, fillGraph: !1, fillAlpha: .15, connectSeparatedPoints: !1, stackedGraph: !1, stackedGraphNaNFill: "all", hideOverlayOnMouseOut: !0, resizable: "no", legend: "onmouseover", legendFollowOffsetX: 50, legendFollowOffsetY: -50, stepPlot: !1, xRangePad: 0, yRangePad: null, drawAxesAtZero: !1, titleHeight: 28, xLabelHeight: 18, yLabelWidth: 18, axisLineColor: "black", axisLineWidth: .3, gridLineWidth: .3, axisLabelWidth: 50, gridLineColor: "rgb(128,128,128)", interactionModel: i.default.defaultModel, animatedZooms: !1, animateBackgroundFade: !0, showRangeSelector: !1, rangeSelectorHeight: 40, rangeSelectorPlotStrokeColor: "#808FAB", rangeSelectorPlotFillGradientColor: "white", rangeSelectorPlotFillColor: "#A7B1C4", rangeSelectorBackgroundStrokeColor: "gray", rangeSelectorBackgroundLineWidth: 1, rangeSelectorPlotLineWidth: 1.5, rangeSelectorForegroundStrokeColor: "black", rangeSelectorForegroundLineWidth: 1, rangeSelectorAlpha: .6, showInRangeSelector: null, plotter: [r.default._fillPlotter, r.default._errorPlotter, r.default._linePlotter], plugins: [], axes: { x: { pixelsPerLabel: 70, axisLabelWidth: 60, axisLabelFormatter: t.dateAxisLabelFormatter, valueFormatter: t.dateValueFormatter, drawGrid: !0, drawAxis: !0, independentTicks: !0, ticker: n.dateTicker }, y: { axisLabelWidth: 50, pixelsPerLabel: 30, valueFormatter: t.numberValueFormatter, axisLabelFormatter: t.numberAxisLabelFormatter, drawGrid: !0, drawAxis: !0, independentTicks: !0, ticker: n.numericTicks }, y2: { axisLabelWidth: 50, pixelsPerLabel: 30, valueFormatter: t.numberValueFormatter, axisLabelFormatter: t.numberAxisLabelFormatter, drawAxis: !0, drawGrid: !1, independentTicks: !1, ticker: n.numericTicks } } }; a.default = i, e.exports = a.default }, { "./dygraph-canvas": "dygraphs/src/dygraph-canvas.js", "./dygraph-interaction-model": "dygraphs/src/dygraph-interaction-model.js", "./dygraph-tickers": "dygraphs/src/dygraph-tickers.js", "./dygraph-utils": "dygraphs/src/dygraph-utils.js" }], "dygraphs/src/dygraph-gviz.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var n = (t = t("./dygraph")) && t.__esModule ? t : { default: t }; function i(t) { this.container = t } i.prototype.draw = function (t, e) { this.container.innerHTML = "", void 0 !== this.date_graph && this.date_graph.destroy(), this.date_graph = new n.default(this.container, t, e) }, i.prototype.setSelection = function (t) { var e = !1; t.length && (e = t[0].row), this.date_graph.setSelection(e) }, i.prototype.getSelection = function () { var t = [], e = this.date_graph.getSelection(); if (!(e < 0)) for (var a = this.date_graph.layout_.points, n = 0; n < a.length; ++n)t.push({ row: e, column: n + 1 }); return t }, a.default = i, e.exports = a.default }, { "./dygraph": "dygraphs/src/dygraph.js" }], "dygraphs/src/dygraph-interaction-model.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var g = function (t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = o(e); if (e && e.has(t)) return e.get(t); var a, n = {}, i = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) { var r; "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((r = i ? Object.getOwnPropertyDescriptor(t, a) : null) && (r.get || r.set) ? Object.defineProperty(n, a, r) : n[a] = t[a]) } n.default = t, e && e.set(t, n); return n }(t("./dygraph-utils")); function o(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (o = function (t) { return t ? a : e })(t)) } var s = { maybeTreatMouseOpAsClick: function (t, e, a) { a.dragEndX = g.dragGetX_(t, a), a.dragEndY = g.dragGetY_(t, a); var n = Math.abs(a.dragEndX - a.dragStartX), i = Math.abs(a.dragEndY - a.dragStartY); n < 2 && i < 2 && void 0 !== e.lastx_ && null !== e.lastx_ && s.treatMouseOpAsClick(e, t, a), a.regionWidth = n, a.regionHeight = i }, startPan: function (t, e, a) { a.isPanning = !0; var n = e.xAxisRange(); if (e.getOptionForAxis("logscale", "x") ? (a.initialLeftmostDate = g.log10(n[0]), a.dateRange = g.log10(n[1]) - g.log10(n[0])) : (a.initialLeftmostDate = n[0], a.dateRange = n[1] - n[0]), a.xUnitsPerPixel = a.dateRange / (e.plotter_.area.w - 1), e.getNumericOption("panEdgeFraction")) { for (var n = e.width_ * e.getNumericOption("panEdgeFraction"), i = e.xAxisExtremes(), r = e.toDomXCoord(i[0]) - n, i = e.toDomXCoord(i[1]) + n, n = e.toDataXCoord(r), r = e.toDataXCoord(i), o = (a.boundedDates = [n, r], []), s = e.height_ * e.getNumericOption("panEdgeFraction"), l = 0; l < e.axes_.length; l++) { var h, d = (h = e.axes_[l]).extremeRange, u = e.toDomYCoord(d[0], l) + s, d = e.toDomYCoord(d[1], l) - s, u = e.toDataYCoord(u, l), d = e.toDataYCoord(d, l); o[l] = [u, d] } a.boundedValues = o } else a.boundedDates = null, a.boundedValues = null; for (a.is2DPan = !1, a.axes = [], l = 0; l < e.axes_.length; l++) { h = e.axes_[l]; var c = {}, p = e.yAxisRange(l); e.attributes_.getForAxis("logscale", l) ? (c.initialTopValue = g.log10(p[1]), c.dragValueRange = g.log10(p[1]) - g.log10(p[0])) : (c.initialTopValue = p[1], c.dragValueRange = p[1] - p[0]), c.unitsPerPixel = c.dragValueRange / (e.plotter_.area.h - 1), a.axes.push(c), h.valueRange && (a.is2DPan = !0) } }, movePan: function (t, e, a) { a.dragEndX = g.dragGetX_(t, a), a.dragEndY = g.dragGetY_(t, a); var t = a.initialLeftmostDate - (a.dragEndX - a.dragStartX) * a.xUnitsPerPixel, n = (t = a.boundedDates ? Math.max(t, a.boundedDates[0]) : t) + a.dateRange; if (a.boundedDates && n > a.boundedDates[1] && (n = (t -= n - a.boundedDates[1]) + a.dateRange), e.getOptionForAxis("logscale", "x") ? e.dateWindow_ = [Math.pow(g.LOG_SCALE, t), Math.pow(g.LOG_SCALE, n)] : e.dateWindow_ = [t, n], a.is2DPan) for (var i = a.dragEndY - a.dragStartY, r = 0; r < e.axes_.length; r++) { var o = e.axes_[r], s = a.axes[r], l = i * s.unitsPerPixel, h = a.boundedValues ? a.boundedValues[r] : null, l = s.initialTopValue + l, d = (l = h ? Math.min(l, h[1]) : l) - s.dragValueRange; h && d < h[0] && (d = (l -= d - h[0]) - s.dragValueRange), e.attributes_.getForAxis("logscale", r) ? o.valueRange = [Math.pow(g.LOG_SCALE, d), Math.pow(g.LOG_SCALE, l)] : o.valueRange = [d, l] } e.drawGraph_(!1) } }, l = (s.endPan = s.maybeTreatMouseOpAsClick, s.startZoom = function (t, e, a) { a.isZooming = !0, a.zoomMoved = !1 }, s.moveZoom = function (t, e, a) { a.zoomMoved = !0, a.dragEndX = g.dragGetX_(t, a), a.dragEndY = g.dragGetY_(t, a); var t = Math.abs(a.dragStartX - a.dragEndX), n = Math.abs(a.dragStartY - a.dragEndY); a.dragDirection = t < n / 2 ? g.VERTICAL : g.HORIZONTAL, e.drawZoomRect_(a.dragDirection, a.dragStartX, a.dragEndX, a.dragStartY, a.dragEndY, a.prevDragDirection, a.prevEndX, a.prevEndY), a.prevEndX = a.dragEndX, a.prevEndY = a.dragEndY, a.prevDragDirection = a.dragDirection }, s.treatMouseOpAsClick = function (t, e, a) { for (var n = t.getFunctionOption("clickCallback"), i = t.getFunctionOption("pointClickCallback"), r = null, o = -1, s = Number.MAX_VALUE, l = 0; l < t.selPoints_.length; l++) { var h = t.selPoints_[l], h = Math.pow(h.canvasx - a.dragEndX, 2) + Math.pow(h.canvasy - a.dragEndY, 2); !isNaN(h) && (-1 == o || h < s) && (s = h, o = l) } var d = t.getNumericOption("highlightCircleSize") + 2; if (r = s <= d * d ? t.selPoints_[o] : r) { var u = { cancelable: !0, point: r, canvasx: a.dragEndX, canvasy: a.dragEndY }; if (t.cascadeEvents_("pointClick", u)) return; i && i.call(t, e, r) } u = { cancelable: !0, xval: t.lastx_, pts: t.selPoints_, canvasx: a.dragEndX, canvasy: a.dragEndY }; t.cascadeEvents_("click", u) || n && n.call(t, e, t.lastx_, t.selPoints_) }, s.endZoom = function (t, e, a) { e.clearZoomRect_(), a.isZooming = !1, s.maybeTreatMouseOpAsClick(t, e, a); var n, i, t = e.getArea(); 10 <= a.regionWidth && a.dragDirection == g.HORIZONTAL ? (n = Math.min(a.dragStartX, a.dragEndX), i = Math.max(a.dragStartX, a.dragEndX), (n = Math.max(n, t.x)) < (i = Math.min(i, t.x + t.w)) && e.doZoomX_(n, i), a.cancelNextDblclick = !0) : 10 <= a.regionHeight && a.dragDirection == g.VERTICAL && (n = Math.min(a.dragStartY, a.dragEndY), i = Math.max(a.dragStartY, a.dragEndY), (n = Math.max(n, t.y)) < (i = Math.min(i, t.y + t.h)) && e.doZoomY_(n, i), a.cancelNextDblclick = !0), a.dragStartX = null, a.dragStartY = null }, s.startTouch = function (t, e, a) { t.preventDefault(), 1 < t.touches.length && (a.startTimeForDoubleTapMs = null); for (var n, i = [], r = 0; r < t.touches.length; r++) { var o = t.touches[r], s = o.target.getBoundingClientRect(); i.push({ pageX: o.pageX, pageY: o.pageY, dataX: e.toDataXCoord(o.clientX - s.left), dataY: e.toDataYCoord(o.clientY - s.top) }) } 1 == (a.initialTouches = i).length ? (a.initialPinchCenter = i[0], a.touchDirections = { x: !0, y: !0 }) : 2 <= i.length && (a.initialPinchCenter = { pageX: .5 * (i[0].pageX + i[1].pageX), pageY: .5 * (i[0].pageY + i[1].pageY), dataX: .5 * (i[0].dataX + i[1].dataX), dataY: .5 * (i[0].dataY + i[1].dataY) }, n = 180 / Math.PI * Math.atan2(a.initialPinchCenter.pageY - i[0].pageY, i[0].pageX - a.initialPinchCenter.pageX), n = Math.abs(n), a.touchDirections = { x: (n = 90 < n ? 90 - n : n) < 67.5, y: 22.5 < n }), a.initialRange = { x: e.xAxisRange(), y: e.yAxisRange() } }, s.moveTouch = function (t, e, a) { a.startTimeForDoubleTapMs = null; for (var n = [], i = 0; i < t.touches.length; i++) { var r = t.touches[i]; n.push({ pageX: r.pageX, pageY: r.pageY }) } var o, s, l = a.initialTouches, h = a.initialPinchCenter, d = 1 == n.length ? n[0] : { pageX: .5 * (n[0].pageX + n[1].pageX), pageY: .5 * (n[0].pageY + n[1].pageY) }, u = { pageX: d.pageX - h.pageX, pageY: d.pageY - h.pageY }, c = a.initialRange.x[1] - a.initialRange.x[0], p = a.initialRange.y[0] - a.initialRange.y[1], g = (u.dataX = u.pageX / e.plotter_.area.w * c, u.dataY = u.pageY / e.plotter_.area.h * p, 1 == n.length ? s = o = 1 : 2 <= n.length && (c = l[1].pageX - h.pageX, o = (n[1].pageX - d.pageX) / c, p = l[1].pageY - h.pageY, s = (n[1].pageY - d.pageY) / p), o = Math.min(8, Math.max(.125, o)), s = Math.min(8, Math.max(.125, s)), !1); if (a.touchDirections.x && (f = h.dataX - u.dataX / o, e.dateWindow_ = [f + (a.initialRange.x[0] - h.dataX) / o, f + (a.initialRange.x[1] - h.dataX) / o], g = !0), a.touchDirections.y) for (i = 0; i < 1; i++) { var f, _ = e.axes_[i]; e.attributes_.getForAxis("logscale", i) || (f = h.dataY - u.dataY / s, _.valueRange = [f + (a.initialRange.y[0] - h.dataY) / s, f + (a.initialRange.y[1] - h.dataY) / s], g = !0) } e.drawGraph_(!1), g && 1 < n.length && e.getFunctionOption("zoomCallback") && (c = e.xAxisRange(), e.getFunctionOption("zoomCallback").call(e, c[0], c[1], e.yAxisRanges())) }, s.endTouch = function (t, e, a) { var n; 0 !== t.touches.length ? s.startTouch(t, e, a) : 1 == t.changedTouches.length && (n = (new Date).getTime(), t = t.changedTouches[0], a.startTimeForDoubleTapMs && n - a.startTimeForDoubleTapMs < 500 && a.doubleTapX && Math.abs(a.doubleTapX - t.screenX) < 50 && a.doubleTapY && Math.abs(a.doubleTapY - t.screenY) < 50 ? e.resetZoom() : (a.startTimeForDoubleTapMs = n, a.doubleTapX = t.screenX, a.doubleTapY = t.screenY)) }, function (t, e, a) { return t < e ? e - t : a < t ? t - a : 0 }); s.defaultModel = { mousedown: function (t, i, r) { var a; t.button && 2 == t.button || (r.initializeMouseDown(t, i, r), t.altKey || t.shiftKey ? s.startPan(t, i, r) : s.startZoom(t, i, r), a = function (t) { var e, a, n; r.isZooming ? (e = t, a = i, n = { left: (n = g.findPos(a.canvas_)).x, right: n.x + a.canvas_.offsetWidth, top: n.y, bottom: n.y + a.canvas_.offsetHeight }, a = { x: g.pageX(e), y: g.pageY(e) }, e = l(a.x, n.left, n.right), a = l(a.y, n.top, n.bottom), Math.max(e, a) < 100 ? s.moveZoom(t, i, r) : null !== r.dragEndX && (r.dragEndX = null, r.dragEndY = null, i.clearZoomRect_())) : r.isPanning && s.movePan(t, i, r) }, t = function t(e) { r.isZooming ? null !== r.dragEndX ? s.endZoom(e, i, r) : s.maybeTreatMouseOpAsClick(e, i, r) : r.isPanning && s.endPan(e, i, r), g.removeEvent(document, "mousemove", a), g.removeEvent(document, "mouseup", t), r.destroy() }, i.addAndTrackEvent(document, "mousemove", a), i.addAndTrackEvent(document, "mouseup", t)) }, willDestroyContextMyself: !0, touchstart: function (t, e, a) { s.startTouch(t, e, a) }, touchmove: function (t, e, a) { s.moveTouch(t, e, a) }, touchend: function (t, e, a) { s.endTouch(t, e, a) }, dblclick: function (t, e, a) { a.cancelNextDblclick ? a.cancelNextDblclick = !1 : (a = { canvasx: a.dragEndX, canvasy: a.dragEndY, cancelable: !0 }, e.cascadeEvents_("dblclick", a) || t.altKey || t.shiftKey || e.resetZoom()) } }, s.nonInteractiveModel_ = { mousedown: function (t, e, a) { a.initializeMouseDown(t, e, a) }, mouseup: s.maybeTreatMouseOpAsClick }, s.dragIsPanInteractionModel = { mousedown: function (t, e, a) { a.initializeMouseDown(t, e, a), s.startPan(t, e, a) }, mousemove: function (t, e, a) { a.isPanning && s.movePan(t, e, a) }, mouseup: function (t, e, a) { a.isPanning && s.endPan(t, e, a) } }, a.default = s, e.exports = a.default }, { "./dygraph-utils": "dygraphs/src/dygraph-utils.js" }], "dygraphs/src/dygraph-layout.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var i = function (t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = o(e); if (e && e.has(t)) return e.get(t); var a, n = {}, i = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) { var r; "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((r = i ? Object.getOwnPropertyDescriptor(t, a) : null) && (r.get || r.set) ? Object.defineProperty(n, a, r) : n[a] = t[a]) } n.default = t, e && e.set(t, n); return n }(t("./dygraph-utils")); function o(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (o = function (t) { return t ? a : e })(t)) } function u(t) { this.dygraph_ = t, this.points = [], this.setNames = [], this.annotations = [], this.yAxes_ = null, this.xTicks_ = null, this.yTicks_ = null } u.prototype.addDataset = function (t, e) { this.points.push(e), this.setNames.push(t) }, u.prototype.getPlotArea = function () { return this.area_ }, u.prototype.computePlotArea = function () { var a = { x: 0, y: 0 }, t = (a.w = this.dygraph_.width_ - a.x - this.dygraph_.getOption("rightGap"), a.h = this.dygraph_.height_, { chart_div: this.dygraph_.graphDiv, reserveSpaceLeft: function (t) { var e = { x: a.x, y: a.y, w: t, h: a.h }; return a.x += t, a.w -= t, e }, reserveSpaceRight: function (t) { var e = { x: a.x + a.w - t, y: a.y, w: t, h: a.h }; return a.w -= t, e }, reserveSpaceTop: function (t) { var e = { x: a.x, y: a.y, w: a.w, h: t }; return a.y += t, a.h -= t, e }, reserveSpaceBottom: function (t) { var e = { x: a.x, y: a.y + a.h - t, w: a.w, h: t }; return a.h -= t, e }, chartRect: function () { return { x: a.x, y: a.y, w: a.w, h: a.h } } }); this.dygraph_.cascadeEvents_("layout", t), this.area_ = a }, u.prototype.setAnnotations = function (t) { this.annotations = []; for (var e = this.dygraph_.getOption("xValueParser") || function (t) { return t }, a = 0; a < t.length; a++) { var n = {}; if (!t[a].xval && void 0 === t[a].x) return void console.error("Annotations must have an 'x' property"); if (t[a].icon && (!t[a].hasOwnProperty("width") || !t[a].hasOwnProperty("height"))) return void console.error("Must set width and height when setting annotation.icon property"); i.update(n, t[a]), n.xval || (n.xval = e(n.x)), this.annotations.push(n) } }, u.prototype.setXTicks = function (t) { this.xTicks_ = t }, u.prototype.setYAxes = function (t) { this.yAxes_ = t }, u.prototype.evaluate = function () { this._xAxis = {}, this._evaluateLimits(), this._evaluateLineCharts(), this._evaluateLineTicks(), this._evaluateAnnotations() }, u.prototype._evaluateLimits = function () { var t = this.dygraph_.xAxisRange(), t = (this._xAxis.minval = t[0], this._xAxis.maxval = t[1], t[1] - t[0]); this._xAxis.scale = 0 != t ? 1 / t : 1, this.dygraph_.getOptionForAxis("logscale", "x") && (this._xAxis.xlogrange = i.log10(this._xAxis.maxval) - i.log10(this._xAxis.minval), this._xAxis.xlogscale = 0 !== this._xAxis.xlogrange ? 1 / this._xAxis.xlogrange : 1); for (var e = 0; e < this.yAxes_.length; e++) { var a = this.yAxes_[e]; a.minyval = a.computedValueRange[0], a.maxyval = a.computedValueRange[1], a.yrange = a.maxyval - a.minyval, a.yscale = 0 !== a.yrange ? 1 / a.yrange : 1, (this.dygraph_.getOption("logscale") || a.logscale) && (a.ylogrange = i.log10(a.maxyval) - i.log10(a.minyval), a.ylogscale = 0 !== a.ylogrange ? 1 / a.ylogrange : 1, isFinite(a.ylogrange) && !isNaN(a.ylogrange) || console.error("axis " + e + " of graph at " + a.g + " can't be displayed in log scale for range [" + a.minyval + " - " + a.maxyval + "]")) } }, u.calcXNormal_ = function (t, e, a) { return a ? (i.log10(t) - i.log10(e.minval)) * e.xlogscale : (t - e.minval) * e.scale }, u.calcYNormal_ = function (t, e, a) { return a ? (a = 1 - (i.log10(e) - i.log10(t.minyval)) * t.ylogscale, isFinite(a) ? a : NaN) : 1 - (e - t.minyval) * t.yscale }, u.prototype._evaluateLineCharts = function () { for (var t = this.dygraph_.getOption("stackedGraph"), e = this.dygraph_.getOptionForAxis("logscale", "x"), a = 0; a < this.points.length; a++) { for (var n = this.points[a], i = this.setNames[a], r = this.dygraph_.getOption("connectSeparatedPoints", i), o = this.dygraph_.axisPropertiesForSeries(i), s = this.dygraph_.attributes_.getForSeries("logscale", i), l = 0; l < n.length; l++) { var h = n[l], d = (h.x = u.calcXNormal_(h.xval, this._xAxis, e), h.yval); t && (h.y_stacked = u.calcYNormal_(o, h.yval_stacked, s), null === d || isNaN(d) || (d = h.yval_stacked)), null === d && (d = NaN, r || (h.yval = NaN)), h.y = u.calcYNormal_(o, d, s) } this.dygraph_.dataHandler_.onLineEvaluated(n, o, s) } }, u.prototype._evaluateLineTicks = function () { var t, e, a, n, i, r; for (this.xticks = [], t = 0; t < this.xTicks_.length; t++)a = (e = this.xTicks_[t]).label, i = (r = !("label_v" in e)) ? e.v : e.label_v, 0 <= (n = this.dygraph_.toPercentXCoord(i)) && n < 1 && this.xticks.push({ pos: n, label: a, has_tick: r }); for (this.yticks = [], t = 0; t < this.yAxes_.length; t++)for (var o = this.yAxes_[t], s = 0; s < o.ticks.length; s++)a = (e = o.ticks[s]).label, i = (r = !("label_v" in e)) ? e.v : e.label_v, 0 < (n = this.dygraph_.toPercentYCoord(i, t)) && n <= 1 && this.yticks.push({ axis: t, pos: n, label: a, has_tick: r }) }, u.prototype._evaluateAnnotations = function () { var t = {}; for (i = 0; i < this.annotations.length; i++) { var e = this.annotations[i]; t[e.xval + "," + e.series] = e } if (this.annotated_points = [], this.annotations && this.annotations.length) for (var a = 0; a < this.points.length; a++)for (var n = this.points[a], i = 0; i < n.length; i++) { var r = n[i], o = r.xval + "," + r.name; o in t && (r.annotation = t[o], this.annotated_points.push(r), delete t[o]) } }, u.prototype.removeAllDatasets = function () { delete this.points, delete this.setNames, delete this.setPointsLengths, delete this.setPointsOffsets, this.points = [], this.setNames = [], this.setPointsLengths = [], this.setPointsOffsets = [] }, a.default = u, e.exports = a.default }, { "./dygraph-utils": "dygraphs/src/dygraph-utils.js" }], "dygraphs/src/dygraph-options-reference.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var n = null; a.default = n, e.exports = a.default }, {}], "dygraphs/src/dygraph-options.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var o = function (t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = s(e); if (e && e.has(t)) return e.get(t); var a, n = {}, i = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) { var r; "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((r = i ? Object.getOwnPropertyDescriptor(t, a) : null) && (r.get || r.set) ? Object.defineProperty(n, a, r) : n[a] = t[a]) } n.default = t, e && e.set(t, n); return n }(t("./dygraph-utils")), i = n(t("./dygraph-default-attrs")); n(t("./dygraph-options-reference")); function n(t) { return t && t.__esModule ? t : { default: t } } function s(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (s = function (t) { return t ? a : e })(t)) } function l(t) { this.dygraph_ = t, this.yAxes_ = [], this.xAxis_ = {}, this.series_ = {}, this.global_ = this.dygraph_.attrs_, this.user_ = this.dygraph_.user_attrs_ || {}, this.labels_ = [], this.highlightSeries_ = this.get("highlightSeriesOpts") || {}, this.reparseSeries() } l.AXIS_STRING_MAPPINGS_ = { y: 0, Y: 0, y1: 0, Y1: 0, y2: 1, Y2: 1 }, l.axisToIndex_ = function (t) { if ("string" == typeof t) { if (l.AXIS_STRING_MAPPINGS_.hasOwnProperty(t)) return l.AXIS_STRING_MAPPINGS_[t]; throw "Unknown axis : " + t } if ("number" == typeof t) { if (0 === t || 1 === t) return t; throw "Dygraphs only supports two y-axes, indexed from 0-1." } if (t) throw "Unknown axis : " + t; return 0 }, l.prototype.reparseSeries = function () { var t = this.get("labels"); if (t) { this.labels_ = t.slice(1), this.yAxes_ = [{ series: [], options: {} }], this.xAxis_ = { options: {} }, this.series_ = {}; for (var e = this.user_.series || {}, a = 0; a < this.labels_.length; a++) { var n = this.labels_[a], i = e[n] || {}, r = l.axisToIndex_(i.axis); this.series_[n] = { idx: a, yAxis: r, options: i }, this.yAxes_[r] ? this.yAxes_[r].series.push(n) : this.yAxes_[r] = { series: [n], options: {} } } t = this.user_.axes || {}; o.update(this.yAxes_[0].options, t.y || {}), 1 < this.yAxes_.length && o.update(this.yAxes_[1].options, t.y2 || {}), o.update(this.xAxis_.options, t.x || {}) } }, l.prototype.get = function (t) { var e = this.getGlobalUser_(t); return null !== e ? e : this.getGlobalDefault_(t) }, l.prototype.getGlobalUser_ = function (t) { return this.user_.hasOwnProperty(t) ? this.user_[t] : null }, l.prototype.getGlobalDefault_ = function (t) { return this.global_.hasOwnProperty(t) ? this.global_[t] : i.default.hasOwnProperty(t) ? i.default[t] : null }, l.prototype.getForAxis = function (t, e) { var a; if ("number" == typeof e) a = 0 === (n = e) ? "y" : "y2"; else { if ("y" == (e = "y1" == e ? "y" : e)) n = 0; else if ("y2" == e) n = 1; else { if ("x" != e) throw "Unknown axis " + e; n = -1 } a = e } var n = -1 == n ? this.xAxis_ : this.yAxes_[n]; if (n) { n = n.options; if (n.hasOwnProperty(t)) return n[t] } if ("x" !== e || "logscale" !== t) { n = this.getGlobalUser_(t); if (null !== n) return n } e = i.default.axes[a]; return e.hasOwnProperty(t) ? e[t] : this.getGlobalDefault_(t) }, l.prototype.getForSeries = function (t, e) { if (e === this.dygraph_.getHighlightSeries() && this.highlightSeries_.hasOwnProperty(t)) return this.highlightSeries_[t]; var a, n; if (this.series_.hasOwnProperty(e)) return (n = (a = this.series_[e]).options).hasOwnProperty(t) ? n[t] : this.getForAxis(t, a.yAxis); throw "Unknown series: " + e }, l.prototype.numAxes = function () { return this.yAxes_.length }, l.prototype.axisForSeries = function (t) { return this.series_[t].yAxis }, l.prototype.axisOptions = function (t) { return this.yAxes_[t].options }, l.prototype.seriesForAxis = function (t) { return this.yAxes_[t].series }, l.prototype.seriesNames = function () { return this.labels_ }, a.default = l, e.exports = a.default }, { "./dygraph-default-attrs": "dygraphs/src/dygraph-default-attrs.js", "./dygraph-options-reference": "dygraphs/src/dygraph-options-reference.js", "./dygraph-utils": "dygraphs/src/dygraph-utils.js" }], "dygraphs/src/dygraph-tickers.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.pickDateTickGranularity = a.numericTicks = a.numericLinearTicks = a.getDateAxis = a.dateTicker = a.Granularity = void 0; var P = function (t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = o(e); if (e && e.has(t)) return e.get(t); var a, n = {}, i = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) { var r; "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((r = i ? Object.getOwnPropertyDescriptor(t, a) : null) && (r.get || r.set) ? Object.defineProperty(n, a, r) : n[a] = t[a]) } n.default = t, e && e.set(t, n); return n }(t("./dygraph-utils")); function o(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (o = function (t) { return t ? a : e })(t)) } a.numericLinearTicks = function (t, e, a, n, i, r) { return s(t, e, a, function (t) { return "logscale" !== t && n(t) }, i, r) }; var s = function (t, e, a, n, i, r) { var o = n("pixelsPerLabel"), s = []; if (r) for (A = 0; A < r.length; A++)s.push({ v: r[A] }); else { if (n("logscale")) { var l = Math.floor(a / o), h = P.binarySearch(t, M, 1), d = P.binarySearch(e, M, -1), u = null; if (l / 4 <= (d = -1 == d ? M.length - 1 : d) - (h = -1 == h ? 0 : h)) { for (var c = d; h <= c; c--) { var p = M[c], g = Math.log(p / t) / Math.log(e / t) * a, f = { v: p }; null === u || Math.abs(g - u.pixel_coord) >= o ? u = { tickValue: p, pixel_coord: g } : f.label = "", s.push(f) } s.reverse() } } if (0 === s.length) { for (var _, y, v, x, d = n("labelsKMG2") ? (_ = [1, 2, 4, 8, 16, 32, 64, 128, 256], 16) : (_ = [1, 2, 5, 10, 20, 50, 100], 10), m = Math.ceil(a / o), m = Math.abs(e - t) / m, m = Math.floor(Math.log(m) / Math.log(d)), b = Math.pow(d, m), w = 0; w < _.length && (y = b * _[w], v = Math.floor(t / y) * y, x = Math.ceil(e / y) * y, !(o < a / (l = Math.abs(x - v) / y))); w++); for (x < v && (y *= -1), A = 0; A <= l; A++)s.push({ v: v + A * y }) } } for (var O = n("axisLabelFormatter"), A = 0; A < s.length; A++)void 0 === s[A].label && (s[A].label = O.call(i, s[A].v, 0, n, i)); return s }, y = (a.numericTicks = s, a.dateTicker = function (t, e, a, n, i, r) { a = l(t, e, a, n); return 0 <= a ? d(t, e, a, n, i) : [] }, { MILLISECONDLY: 0, TWO_MILLISECONDLY: 1, FIVE_MILLISECONDLY: 2, TEN_MILLISECONDLY: 3, FIFTY_MILLISECONDLY: 4, HUNDRED_MILLISECONDLY: 5, FIVE_HUNDRED_MILLISECONDLY: 6, SECONDLY: 7, TWO_SECONDLY: 8, FIVE_SECONDLY: 9, TEN_SECONDLY: 10, THIRTY_SECONDLY: 11, MINUTELY: 12, TWO_MINUTELY: 13, FIVE_MINUTELY: 14, TEN_MINUTELY: 15, THIRTY_MINUTELY: 16, HOURLY: 17, TWO_HOURLY: 18, SIX_HOURLY: 19, DAILY: 20, TWO_DAILY: 21, WEEKLY: 22, MONTHLY: 23, QUARTERLY: 24, BIANNUAL: 25, ANNUAL: 26, DECADAL: 27, CENTENNIAL: 28, NUM_GRANULARITIES: 29 }); a.Granularity = y; var v = 0, x = 1, m = 2, b = 3, w = 4, O = 5, A = 6, S = 7, L = [], M = (L[y.MILLISECONDLY] = { datefield: A, step: 1, spacing: 1 }, L[y.TWO_MILLISECONDLY] = { datefield: A, step: 2, spacing: 2 }, L[y.FIVE_MILLISECONDLY] = { datefield: A, step: 5, spacing: 5 }, L[y.TEN_MILLISECONDLY] = { datefield: A, step: 10, spacing: 10 }, L[y.FIFTY_MILLISECONDLY] = { datefield: A, step: 50, spacing: 50 }, L[y.HUNDRED_MILLISECONDLY] = { datefield: A, step: 100, spacing: 100 }, L[y.FIVE_HUNDRED_MILLISECONDLY] = { datefield: A, step: 500, spacing: 500 }, L[y.SECONDLY] = { datefield: O, step: 1, spacing: 1e3 }, L[y.TWO_SECONDLY] = { datefield: O, step: 2, spacing: 2e3 }, L[y.FIVE_SECONDLY] = { datefield: O, step: 5, spacing: 5e3 }, L[y.TEN_SECONDLY] = { datefield: O, step: 10, spacing: 1e4 }, L[y.THIRTY_SECONDLY] = { datefield: O, step: 30, spacing: 3e4 }, L[y.MINUTELY] = { datefield: w, step: 1, spacing: 6e4 }, L[y.TWO_MINUTELY] = { datefield: w, step: 2, spacing: 12e4 }, L[y.FIVE_MINUTELY] = { datefield: w, step: 5, spacing: 3e5 }, L[y.TEN_MINUTELY] = { datefield: w, step: 10, spacing: 6e5 }, L[y.THIRTY_MINUTELY] = { datefield: w, step: 30, spacing: 18e5 }, L[y.HOURLY] = { datefield: b, step: 1, spacing: 36e5 }, L[y.TWO_HOURLY] = { datefield: b, step: 2, spacing: 72e5 }, L[y.SIX_HOURLY] = { datefield: b, step: 6, spacing: 216e5 }, L[y.DAILY] = { datefield: m, step: 1, spacing: 864e5 }, L[y.TWO_DAILY] = { datefield: m, step: 2, spacing: 1728e5 }, L[y.WEEKLY] = { datefield: m, step: 7, spacing: 6048e5 }, L[y.MONTHLY] = { datefield: x, step: 1, spacing: 2629746e3 }, L[y.QUARTERLY] = { datefield: x, step: 3, spacing: 7889238e3 }, L[y.BIANNUAL] = { datefield: x, step: 6, spacing: 15778476e3 }, L[y.ANNUAL] = { datefield: v, step: 1, spacing: 31556952e3 }, L[y.DECADAL] = { datefield: v, step: 10, spacing: 31556952e4 }, L[y.CENTENNIAL] = { datefield: v, step: 100, spacing: 31556952e5 }, function () { for (var t = [], e = -39; e <= 39; e++)for (var a = Math.pow(10, e), n = 1; n <= 9; n++)t.push(a * n); return t }()), l = function (t, e, a, n) { for (var i = n("pixelsPerLabel"), r = 0; r < y.NUM_GRANULARITIES; r++)if (i <= a / h(t, e, r)) return r; return -1 }, h = (a.pickDateTickGranularity = l, function (t, e, a) { a = L[a].spacing; return Math.round((e - t) / a) }), d = function (t, e, a, n, i) { var r = n("axisLabelFormatter"), o = n("labelsUTC") ? P.DateAccessorsUTC : P.DateAccessorsLocal, s = L[a].datefield, l = L[a].step, h = L[a].spacing, d = new Date(t), u = [], c = (u[v] = o.getFullYear(d), u[x] = o.getMonth(d), u[m] = o.getDate(d), u[b] = o.getHours(d), u[w] = o.getMinutes(d), u[O] = o.getSeconds(d), u[A] = o.getMilliseconds(d), u[s] % l); a == y.WEEKLY && (c = o.getDay(d)), u[s] -= c; for (var p = s + 1; p < S; p++)u[p] = p === m ? 1 : 0; var g = [], f = o.makeDate.apply(null, u), _ = f.getTime(); if (a <= y.HOURLY) for (_ < t && (_ += h, f = new Date(_)); _ <= e;)g.push({ v: _, label: r.call(i, f, a, n, i) }), _ += h, f = new Date(_); else for (_ < t && (u[s] += l, _ = (f = o.makeDate.apply(null, u)).getTime()); _ <= e;)(y.DAILY <= a || o.getHours(f) % l == 0) && g.push({ v: _, label: r.call(i, f, a, n, i) }), u[s] += l, _ = (f = o.makeDate.apply(null, u)).getTime(); return g }; a.getDateAxis = d }, { "./dygraph-utils": "dygraphs/src/dygraph-utils.js" }], "dygraphs/src/dygraph-utils.js": [function (t, F, e) { "use strict"; Object.defineProperty(e, "__esModule", { value: !0 }), e.HORIZONTAL = e.DateAccessorsUTC = e.DateAccessorsLocal = e.DOT_DASH_LINE = e.DOTTED_LINE = e.DASHED_LINE = e.Circles = void 0, e.Iterator = v, e.addEvent = e.VERTICAL = e.LOG_SCALE = e.LN_TEN = void 0, e.binarySearch = function t(e, a, n, i, r) { null != i && null != r || (i = 0, r = a.length - 1); if (r < i) return -1; null == n && (n = 0); var o = function (t) { return 0 <= t && t < a.length }; var s = parseInt((i + r) / 2, 10); var l = a[s]; var h; { if (l == e) return s; if (e < l) return 0 < n && o(h = s - 1) && a[h] < e ? s : t(e, a, n, i, s - 1); if (l < e) return n < 0 && o(h = s + 1) && a[h] > e ? s : t(e, a, n, s + 1, r) } return -1 }, e.cancelEvent = function (t) { (t = t || window.event).stopPropagation && t.stopPropagation(); t.preventDefault && t.preventDefault(); return t.cancelBubble = !0, t.cancel = !0, t.returnValue = !1 }, e.clone = function t(e) { var a = []; for (var n = 0; n < e.length; n++)y(e[n]) ? a.push(t(e[n])) : a.push(e[n]); return a }, e.createCanvas = function () { return document.createElement("canvas") }, e.createIterator = function (t, e, a, n) { return new v(t, e, a, n) }, e.dateAxisLabelFormatter = function (t, e, a) { var a = a("labelsUTC") ? p : c, n = a.getFullYear(t), i = a.getMonth(t), r = a.getDate(t), o = a.getHours(t), s = a.getMinutes(t), l = a.getSeconds(t), a = a.getMilliseconds(t); return e >= h.Granularity.DECADAL ? "" + n : e >= h.Granularity.MONTHLY ? E[i] + " " + n : 0 === 3600 * o + 60 * s + l + .001 * a || e >= h.Granularity.DAILY ? d(r) + " " + E[i] : e < h.Granularity.SECONDLY ? (t = "" + a, d(l) + "." + ("000" + t).substring(t.length)) : e > h.Granularity.MINUTELY ? g(o, s, l, 0) : g(o, s, l, a) }, e.dateParser = function (t) { var e, a; if ((-1 == t.search("-") || -1 != t.search("T") || -1 != t.search("Z")) && (a = l(t)) && !isNaN(a)) return a; if (-1 != t.search("-")) { for (e = t.replace("-", "/", "g"); -1 != e.search("-");)e = e.replace("-", "/"); a = l(e) } else a = l(t); a && !isNaN(a) || console.error("Couldn't parse " + t + " as a date"); return a }, e.dateStrToMillis = l, e.dateString_ = s, e.dateValueFormatter = function (t, e) { return s(t, e("labelsUTC")) }, e.detectLineDelimiter = function (t) { for (var e = 0; e < t.length; e++) { var a = t.charAt(e); if ("\r" === a) return e + 1 < t.length && "\n" === t.charAt(e + 1) ? "\r\n" : a; if ("\n" === a) return e + 1 < t.length && "\r" === t.charAt(e + 1) ? "\n\r" : a } return null }, e.dragGetX_ = function (t, e) { return i(t) - e.px }, e.dragGetY_ = function (t, e) { return r(t) - e.py }, e.findPos = function (t) { var t = t.getBoundingClientRect(), e = window, a = document.documentElement; return { x: t.left + (e.pageXOffset || a.scrollLeft), y: t.top + (e.pageYOffset || a.scrollTop) } }, e.floatFormat = u, e.getContext = void 0, e.getContextPixelRatio = function (t) { try { var e = window.devicePixelRatio, a = t.webkitBackingStorePixelRatio || t.mozBackingStorePixelRatio || t.msBackingStorePixelRatio || t.oBackingStorePixelRatio || t.backingStorePixelRatio || 1; return void 0 !== e ? e / a : 1 } catch (t) { return 1 } }, e.hmsString_ = g, e.hsvToRGB = function (t, e, a) { var n, i, r; if (0 === e) r = i = n = a; else { var o = Math.floor(6 * t), t = 6 * t - o, s = a * (1 - e), l = a * (1 - e * t), h = a * (1 - e * (1 - t)); switch (o) { case 1: n = l, i = a, r = s; break; case 2: n = s, i = a, r = h; break; case 3: n = s, i = l, r = a; break; case 4: n = h, i = s, r = a; break; case 5: n = a, i = s, r = l; break; case 6: case 0: n = a, i = h, r = s } } return n = Math.floor(255 * n + .5), i = Math.floor(255 * i + .5), r = Math.floor(255 * r + .5), "rgb(" + n + "," + i + "," + r + ")" }, e.isArrayLike = y, e.isCanvasSupported = function (t) { try { (t || document.createElement("canvas")).getContext("2d") } catch (t) { return !1 } return !0 }, e.isDateLike = function (t) { return null !== t && "object" == typeof t && "function" == typeof t.getTime }, e.isNodeContainedBy = function (t, e) { if (null === e || null === t) return !1; var a = t; for (; a && a !== e;)a = a.parentNode; return a === e }, e.isOK = function (t) { return !!t && !isNaN(t) }, e.isPixelChangingOptionList = function (t, e) { var a = {}; if (t) for (var n = 1; n < t.length; n++)a[t[n]] = !0; function i(t) { for (var e in t) if (t.hasOwnProperty(e) && !m[e]) return 1 } for (var r in e) if (e.hasOwnProperty(r)) if ("highlightSeriesOpts" == r || a[r] && !e.series) { if (i(e[r])) return !0 } else if ("series" == r || "axes" == r) { var o, s = e[r]; for (o in s) if (s.hasOwnProperty(o) && i(s[o])) return !0 } else if (!m[r]) return !0; return !1 }, e.isValidPoint = function (t, e) { return !!t && null !== t.yval && null !== t.x && void 0 !== t.x && null !== t.y && void 0 !== t.y && !(isNaN(t.x) || !e && isNaN(t.y)) }, e.logRangeFraction = e.log10 = void 0, e.numberAxisLabelFormatter = function (t, e, a) { return D.call(this, t, a) }, e.numberValueFormatter = D, e.pageX = i, e.pageY = r, e.parseFloat_ = function (t, e, a) { var n = parseFloat(t); if (!isNaN(n)) return n; if (!/^ *$/.test(t)) { if (/^ *nan *$/i.test(t)) return NaN; n = "Unable to parse '" + t + "' as a number"; void 0 !== a && void 0 !== e && (n += " on line " + (1 + (e || 0)) + " ('" + a + "') of CSV."), console.error(n) } return null }, e.pow = b, e.removeEvent = function (t, e, a) { t.removeEventListener(e, a, !1) }, e.repeatAndCleanup = function (a, t, n, i) { var r, o, s = 0, l = (new Date).getTime(); a(s), (1 == t ? i : (o = t - 1, function e() { t <= s || x.call(window, function () { var t = (new Date).getTime(), t = (r = s, (s = Math.floor((t - l) / n)) - r); (o < s + t || o <= s ? (a(o), i) : (0 != t && a(s), e))() }) }))() }, e.requestAnimFrame = void 0, e.round_ = f, e.setupDOMready_ = function (a) { { var n; "undefined" != typeof document && (n = function () { if (!k) { k = !0, a.onDOMready = R, document.removeEventListener("DOMContentLoaded", n, !1), window.removeEventListener("load", n, !1); for (var t = 0; t < N.length; ++t)N[t](); N = null } }, a.onDOMready = function (t) { var e; return ("complete" === document.readyState ? a.onDOMready = R : (a.onDOMready = e = function (t) { return "function" == typeof t && N.push(t), !1 }, document.addEventListener("DOMContentLoaded", n, !1), window.addEventListener("load", n, !1), "complete" === document.readyState ? (n(), a.onDOMready = R) : e))(t) }) } }, e.toRGB_ = function (t) { var e = A(t); return e || ((e = document.createElement("div")).style.backgroundColor = t, e.style.visibility = "hidden", document.body.appendChild(e), t = window.getComputedStyle(e, null).backgroundColor, document.body.removeChild(e), A(t)) }, e.type = function (t) { return null === t ? "null" : typeof t }, e.typeArrayLike = function (t) { var e; return null === t ? "null" : ("object" == (e = typeof t) || "function" == e && "function" == typeof t.item) && "number" == typeof t.length && 3 !== t.nodeType && 4 !== t.nodeType ? "array" : e }, e.update = function (t, e) { if (null != e) for (var a in e) e.hasOwnProperty(a) && (t[a] = e[a]); return t }, e.updateDeep = function t(e, a) { if (null != a) for (var n in a) { var i; a.hasOwnProperty(n) && (null === (i = a[n]) ? e[n] = null : y(i) ? e[n] = i.slice() : !_(i) && "object" == typeof i ? ("object" == typeof e[n] && null !== e[n] || (e[n] = {}), t(e[n], i)) : e[n] = i) } return e }, e.zeropad = d; var h = function (t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = o(e); if (e && e.has(t)) return e.get(t); var a, n = {}, i = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) { var r; "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((r = i ? Object.getOwnPropertyDescriptor(t, a) : null) && (r.get || r.set) ? Object.defineProperty(n, a, r) : n[a] = t[a]) } n.default = t, e && e.set(t, n); return n }(t("./dygraph-tickers")); function o(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (o = function (t) { return t ? a : e })(t)) } function n(t) { return Math.log(t) / a } e.LOG_SCALE = 10; var a = Math.log(10); e.LN_TEN = a, e.log10 = n, e.logRangeFraction = function (t, e, a) { t = n(t), e = n(e); return Math.pow(10, t + a * (e - t)) }, e.DOTTED_LINE = [2, 2], e.DASHED_LINE = [7, 3], e.DOT_DASH_LINE = [7, 2, 2, 2], e.HORIZONTAL = 1, e.VERTICAL = 2, e.getContext = function (t) { return t.getContext("2d") }; function i(t) { return !t.pageX || t.pageX < 0 ? 0 : t.pageX } function r(t) { return !t.pageY || t.pageY < 0 ? 0 : t.pageY } function u(t, e) { e = Math.min(Math.max(1, e || 2), 21); return Math.abs(t) < .001 && 0 !== t ? t.toExponential(e - 1) : t.toPrecision(e) } function d(t) { return t < 10 ? "0" + t : "" + t } e.addEvent = function (t, e, a) { t.addEventListener(e, a, !1) }; var c = { getFullYear: function (t) { return t.getFullYear() }, getMonth: function (t) { return t.getMonth() }, getDate: function (t) { return t.getDate() }, getHours: function (t) { return t.getHours() }, getMinutes: function (t) { return t.getMinutes() }, getSeconds: function (t) { return t.getSeconds() }, getMilliseconds: function (t) { return t.getMilliseconds() }, getDay: function (t) { return t.getDay() }, makeDate: function (t, e, a, n, i, r, o) { return new Date(t, e, a, n, i, r, o) } }, p = (e.DateAccessorsLocal = c, { getFullYear: function (t) { return t.getUTCFullYear() }, getMonth: function (t) { return t.getUTCMonth() }, getDate: function (t) { return t.getUTCDate() }, getHours: function (t) { return t.getUTCHours() }, getMinutes: function (t) { return t.getUTCMinutes() }, getSeconds: function (t) { return t.getUTCSeconds() }, getMilliseconds: function (t) { return t.getUTCMilliseconds() }, getDay: function (t) { return t.getUTCDay() }, makeDate: function (t, e, a, n, i, r, o) { return new Date(Date.UTC(t, e, a, n, i, r, o)) } }); function g(t, e, a, n) { t = d(t) + ":" + d(e); return a && (t += ":" + d(a), n) && (t += "." + ("000" + (e = "" + n)).substring(e.length)), t } function s(t, e) { var e = e ? p : c, t = new Date(t), a = e.getFullYear(t), n = e.getMonth(t), i = e.getDate(t), r = e.getHours(t), o = e.getMinutes(t), s = e.getSeconds(t), e = e.getMilliseconds(t), t = "" + a + "/" + d(n + 1) + "/" + d(i); return 3600 * r + 60 * o + s + .001 * e && (t += " " + g(r, o, s, e)), t } function f(t, e) { e = Math.pow(10, e); return Math.round(t * e) / e } function l(t) { return new Date(t).getTime() } e.DateAccessorsUTC = p; var _ = "undefined" != typeof Node && null !== Node && "object" == typeof Node ? function (t) { return t instanceof Node } : function (t) { return "object" == typeof t && "number" == typeof t.nodeType && "string" == typeof t.nodeName }; function y(t) { var e = typeof t; return null !== t && ("object" == e || "function" == e && "function" == typeof t.item) && "number" == typeof t.length && 3 !== t.nodeType && 4 !== t.nodeType } function v(t, e, a, n) { e = e || 0, a = a || t.length, this.hasNext = !0, this.peek = null, this.start_ = e, this.array_ = t, this.predicate_ = n, this.end_ = Math.min(t.length, e + a), this.nextIdx_ = e - 1, this.next() } v.prototype.next = function () { if (!this.hasNext) return null; for (var t = this.peek, e = this.nextIdx_ + 1, a = !1; e < this.end_;) { if (!this.predicate_ || this.predicate_(this.array_, e)) { this.peek = this.array_[e], a = !0; break } e++ } return this.nextIdx_ = e, a || (this.hasNext = !1, this.peek = null), t }; var x = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (t) { window.setTimeout(t, 1e3 / 60) }; e.requestAnimFrame = x; var m = { annotationClickHandler: !0, annotationDblClickHandler: !0, annotationMouseOutHandler: !0, annotationMouseOverHandler: !0, axisLineColor: !0, axisLineWidth: !0, clickCallback: !0, drawCallback: !0, drawHighlightPointCallback: !0, drawPoints: !0, drawPointCallback: !0, drawGrid: !0, fillAlpha: !0, gridLineColor: !0, gridLineWidth: !0, hideOverlayOnMouseOut: !0, highlightCallback: !0, highlightCircleSize: !0, interactionModel: !0, labelsDiv: !0, labelsKMB: !0, labelsKMG2: !0, labelsSeparateLines: !0, labelsShowZeroValues: !0, legend: !0, panEdgeFraction: !0, pixelsPerYLabel: !0, pointClickCallback: !0, pointSize: !0, rangeSelectorPlotFillColor: !0, rangeSelectorPlotFillGradientColor: !0, rangeSelectorPlotStrokeColor: !0, rangeSelectorBackgroundStrokeColor: !0, rangeSelectorBackgroundLineWidth: !0, rangeSelectorPlotLineWidth: !0, rangeSelectorForegroundStrokeColor: !0, rangeSelectorForegroundLineWidth: !0, rangeSelectorAlpha: !0, showLabelsOnHighlight: !0, showRoller: !0, strokeWidth: !0, underlayCallback: !0, unhighlightCallback: !0, zoomCallback: !0 }; function b(t, e) { return e < 0 ? 1 / Math.pow(t, -e) : Math.pow(t, e) } e.Circles = { DEFAULT: function (t, e, a, n, i, r, o) { a.beginPath(), a.fillStyle = r, a.arc(n, i, o, 0, 2 * Math.PI, !1), a.fill() } }; var w = /^#([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})([0-9A-Fa-f]{2})?$/, O = /^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})(?:,\s*([01](?:\.\d+)?))?\)$/; function A(t) { var e, a, n, i, r = null; if (e = w.exec(t)) a = parseInt(e[1], 16), n = parseInt(e[2], 16), i = parseInt(e[3], 16), e[4] && (r = parseInt(e[4], 16)); else { if (!(e = O.exec(t))) return null; a = parseInt(e[1], 10), n = parseInt(e[2], 10), i = parseInt(e[3], 10), e[4] && (r = parseFloat(e[4])) } return null !== r ? { r: a, g: n, b: i, a: r } : { r: a, g: n, b: i } } var P = ["k", "M", "G", "T", "P", "E", "Z", "Y"], S = ["m", "µ", "n", "p", "f", "a", "z", "y"], L = ["Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi"], M = ["p-10", "p-20", "p-30", "p-40", "p-50", "p-60", "p-70", "p-80"], C = ["K", "M", "G", "T", "P", "E", "Z", "Y"], T = S; function D(t, e) { var a = e("sigFigs"); if (null !== a) return u(t, a); if (0 === t) return "0"; var n = e("digitsAfterDecimal"), i = e("maxNumberWidth"), a = e("labelsKMB"), e = e("labelsKMG2"), r = Math.abs(t); if (a || e) { var o, s, l, h = [], d = []; if (a && (o = 1e3, h = P, d = S), e && (o = 1024, h = L, d = M, a) && (h = C, d = T), o <= r) { for (l = h.length; 0 < l;)if (s = b(o, l), --l, s <= r) return r / s >= Math.pow(10, i) ? t.toExponential(n) : f(t / s, n) + h[l] } else if (r < 1) { for (l = 0; l < d.length && !(1 <= r * (s = b(o, ++l)));); return r * s < Math.pow(10, -n) ? t.toExponential(n) : f(t * s, n) + d[l - 1] } } return r >= Math.pow(10, i) || r < Math.pow(10, -n) ? t.toExponential(n) : "" + f(t, n) } var E = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; var N = [], k = !1; function R(t) { return "function" == typeof t && t(), !0 } }, { "./dygraph-tickers": "dygraphs/src/dygraph-tickers.js" }], "dygraphs/src/dygraph.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var i = A(t("./dygraph-layout")), r = A(t("./dygraph-canvas")), u = A(t("./dygraph-options")), n = A(t("./dygraph-interaction-model")), v = O(t("./dygraph-tickers")), M = O(t("./dygraph-utils")), c = A(t("./dygraph-default-attrs")), o = (A(t("./dygraph-options-reference")), A(t("./iframe-tarp"))), s = A(t("./datahandler/default")), l = A(t("./datahandler/bars-error")), h = A(t("./datahandler/bars-custom")), d = A(t("./datahandler/default-fractions")), p = A(t("./datahandler/bars-fractions")), g = A(t("./datahandler/bars")), f = A(t("./plugins/annotations")), _ = A(t("./plugins/axes")), y = A(t("./plugins/chart-labels")), x = A(t("./plugins/grid")), m = A(t("./plugins/legend")), b = A(t("./plugins/range-selector")), t = A(t("./dygraph-gviz")); function w(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (w = function (t) { return t ? a : e })(t)) } function O(t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = w(e); if (e && e.has(t)) return e.get(t); var a, n, i = {}, r = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((n = r ? Object.getOwnPropertyDescriptor(t, a) : null) && (n.get || n.set) ? Object.defineProperty(i, a, n) : i[a] = t[a]); return i.default = t, e && e.set(t, i), i } function A(t) { return t && t.__esModule ? t : { default: t } } function P(t, e) { return function (t) { if (Array.isArray(t)) return t }(t) || function (t, e) { var a = null == t ? null : "undefined" != typeof Symbol && t[Symbol.iterator] || t["@@iterator"]; if (null != a) { var n, i, r, o, s = [], l = !0, h = !1; try { if (r = (a = a.call(t)).next, 0 === e) { if (Object(a) !== a) return; l = !1 } else for (; !(l = (n = r.call(a)).done) && (s.push(n.value), s.length !== e); l = !0); } catch (t) { h = !0, i = t } finally { try { if (!l && null != a.return && (o = a.return(), Object(o) !== o)) return } finally { if (h) throw i } } return s } }(t, e) || function (t, e) { var a; if (t) return "string" == typeof t ? S(t, e) : "Map" === (a = "Object" === (a = Object.prototype.toString.call(t).slice(8, -1)) && t.constructor ? t.constructor.name : a) || "Set" === a ? Array.from(t) : "Arguments" === a || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(a) ? S(t, e) : void 0 }(t, e) || function () { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.") }() } function S(t, e) { (null == e || e > t.length) && (e = t.length); for (var a = 0, n = new Array(e); a < e; a++)n[a] = t[a]; return n } function L(t, e, a) { this.__init__(t, e, a) } L.NAME = "Dygraph", L.VERSION = "2.2.1"; var C = {}; (L._require = function (t) { return t in C ? C[t] : L._require._b(t) })._b = null, L._require.add = function (t, e) { C[t] = e }, L.DEFAULT_ROLL_PERIOD = 1, L.DEFAULT_WIDTH = 480, L.DEFAULT_HEIGHT = 320, L.ANIMATION_STEPS = 12, L.ANIMATION_DURATION = 200, L.Plotters = r.default._Plotters, L.addedAnnotationCSS = !1, L.prototype.__init__ = function (t, e, a) { if (this.is_initial_draw_ = !0, this.readyFns_ = [], a = L.copyUserAttrs_(a = null == a ? {} : a), !(t = "string" == typeof t ? document.getElementById(t) : t)) throw new Error("Constructing dygraph with a non-existent div!"); this.maindiv_ = t, this.file_ = e, this.rollPeriod_ = a.rollPeriod || L.DEFAULT_ROLL_PERIOD, this.previousVerticalX_ = -1, this.fractions_ = a.fractions || !1, this.dateWindow_ = a.dateWindow || null, this.annotations_ = [], t.innerHTML = ""; for (var e = window.getComputedStyle(t, null), n = ("0px" === e.paddingLeft && "0px" === e.paddingRight && "0px" === e.paddingTop && "0px" === e.paddingBottom || console.error("Main div contains padding; graph will misbehave"), "" === t.style.width && a.width && (t.style.width = a.width + "px"), "" === t.style.height && a.height && (t.style.height = a.height + "px"), "" === t.style.height && 0 === t.clientHeight && (t.style.height = L.DEFAULT_HEIGHT + "px", "" === t.style.width) && (t.style.width = L.DEFAULT_WIDTH + "px"), this.width_ = t.clientWidth || a.width || 0, this.height_ = t.clientHeight || a.height || 0, a.stackedGraph && (a.fillGraph = !0), this.user_attrs_ = {}, M.update(this.user_attrs_, a), this.attrs_ = {}, M.updateDeep(this.attrs_, c.default), this.boundaryIds_ = [], this.setIndexByName_ = {}, this.datasetIndex_ = [], this.registeredEvents_ = [], this.eventListeners_ = {}, this.attributes_ = new u.default(this), this.createInterface_(), this.plugins_ = [], L.PLUGINS.concat(this.getOption("plugins"))), i = 0; i < n.length; i++) { var r = n[i], r = void 0 !== r.activate ? r : new r, o = { plugin: r, events: {}, options: {}, pluginOptions: {} }, s = r.activate(this); for (l in s) s.hasOwnProperty(l) && (o.events[l] = s[l]); this.plugins_.push(o) } for (i = 0; i < this.plugins_.length; i++) { var l, h, d = this.plugins_[i]; for (l in d.events) d.events.hasOwnProperty(l) && (h = d.events[l], h = [d.plugin, h], l in this.eventListeners_ ? this.eventListeners_[l].push(h) : this.eventListeners_[l] = [h]) } this.createDragInterface_(), this.start_() }, L.prototype.cascadeEvents_ = function (t, e) { if (!(t in this.eventListeners_)) return !1; var a = { dygraph: this, cancelable: !1, defaultPrevented: !1, preventDefault: function () { if (!a.cancelable) throw "Cannot call preventDefault on non-cancelable event."; a.defaultPrevented = !0 }, propagationStopped: !1, stopPropagation: function () { a.propagationStopped = !0 } }, n = (M.update(a, e), this.eventListeners_[t]); if (n) for (var i = n.length - 1; 0 <= i; i--) { var r = n[i][0]; if (n[i][1].call(r, a), a.propagationStopped) break } return a.defaultPrevented }, L.prototype.getPluginInstance_ = function (t) { for (var e = 0; e < this.plugins_.length; e++) { var a = this.plugins_[e]; if (a.plugin instanceof t) return a.plugin } return null }, L.prototype.isZoomed = function (t) { var e = !!this.dateWindow_; if ("x" === t) return e; var a = 0 <= this.axes_.map(function (t) { return !!t.valueRange }).indexOf(!0); if (null == t) return e || a; if ("y" === t) return a; throw new Error("axis parameter is [".concat(t, "] must be null, 'x' or 'y'.")) }, L.prototype.toString = function () { var t = this.maindiv_; return "[Dygraph " + (t && t.id ? t.id : t) + "]" }, L.prototype.attr_ = function (t, e) { return e ? this.attributes_.getForSeries(t, e) : this.attributes_.get(t) }, L.prototype.getOption = function (t, e) { return this.attr_(t, e) }, L.prototype.getNumericOption = function (t, e) { return this.getOption(t, e) }, L.prototype.getStringOption = function (t, e) { return this.getOption(t, e) }, L.prototype.getBooleanOption = function (t, e) { return this.getOption(t, e) }, L.prototype.getFunctionOption = function (t, e) { return this.getOption(t, e) }, L.prototype.getOptionForAxis = function (t, e) { return this.attributes_.getForAxis(t, e) }, L.prototype.optionsViewForAxis_ = function (a) { var n = this; return function (t) { var e = n.user_attrs_.axes; return e && e[a] && e[a].hasOwnProperty(t) ? e[a][t] : ("x" !== a || "logscale" !== t) && (void 0 !== n.user_attrs_[t] ? n.user_attrs_[t] : (e = n.attrs_.axes) && e[a] && e[a].hasOwnProperty(t) ? e[a][t] : "y" == a && n.axes_[0].hasOwnProperty(t) ? n.axes_[0][t] : "y2" == a && n.axes_[1].hasOwnProperty(t) ? n.axes_[1][t] : n.attr_(t)) } }, L.prototype.rollPeriod = function () { return this.rollPeriod_ }, L.prototype.xAxisRange = function () { return this.dateWindow_ || this.xAxisExtremes() }, L.prototype.xAxisExtremes = function () { var t, e, a, n = this.getNumericOption("xRangePad") / this.plotter_.area.w; return 0 === this.numRows() ? [0 - n, 1 + n] : (t = this.rawData_[0][0], e = this.rawData_[this.rawData_.length - 1][0], n && (t -= (a = e - t) * n, e += a * n), [t, e]) }, L.prototype.yAxisExtremes = function () { var t = this.gatherDatasets_(this.rolledSeries_, null).extremes, e = this.axes_, t = (this.computeYAxisRanges_(t), this.axes_); return this.axes_ = e, t.map(function (t) { return t.extremeRange }) }, L.prototype.yAxisRange = function (t) { return (t = void 0 === t ? 0 : t) < 0 || t >= this.axes_.length ? null : [(t = this.axes_[t]).computedValueRange[0], t.computedValueRange[1]] }, L.prototype.yAxisRanges = function () { for (var t = [], e = 0; e < this.axes_.length; e++)t.push(this.yAxisRange(e)); return t }, L.prototype.toDomCoords = function (t, e, a) { return [this.toDomXCoord(t), this.toDomYCoord(e, a)] }, L.prototype.toDomXCoord = function (t) { var e, a; return null === t ? null : (e = this.plotter_.area, a = this.xAxisRange(), e.x + (t - a[0]) / (a[1] - a[0]) * e.w) }, L.prototype.toDomYCoord = function (t, e) { t = this.toPercentYCoord(t, e); return null === t ? null : (e = this.plotter_.area).y + t * e.h }, L.prototype.toDataCoords = function (t, e, a) { return [this.toDataXCoord(t), this.toDataYCoord(e, a)] }, L.prototype.toDataXCoord = function (t) { var e, a, n; return null === t ? null : (e = this.plotter_.area, a = this.xAxisRange(), this.attributes_.getForAxis("logscale", "x") ? (n = (t - e.x) / e.w, M.logRangeFraction(a[0], a[1], n)) : a[0] + (t - e.x) / e.w * (a[1] - a[0])) }, L.prototype.toDataYCoord = function (t, e) { var a, n; return null === t ? null : (a = this.plotter_.area, n = this.yAxisRange(e), this.attributes_.getForAxis("logscale", e = void 0 === e ? 0 : e) ? (e = (t - a.y) / a.h, M.logRangeFraction(n[1], n[0], e)) : n[0] + (a.y + a.h - t) / a.h * (n[1] - n[0])) }, L.prototype.toPercentYCoord = function (t, e) { var a, n; return null === t ? null : (a = this.yAxisRange(e = void 0 === e ? 0 : e), this.attributes_.getForAxis("logscale", e) ? (e = M.log10(a[0]), ((n = M.log10(a[1])) - M.log10(t)) / (n - e)) : (a[1] - t) / (a[1] - a[0])) }, L.prototype.toPercentXCoord = function (t) { var e, a, n; return null === t ? null : (e = this.xAxisRange(), !0 === this.attributes_.getForAxis("logscale", "x") ? (a = M.log10(e[0]), n = M.log10(e[1]), (M.log10(t) - a) / (n - a)) : (t - e[0]) / (e[1] - e[0])) }, L.prototype.numColumns = function () { return this.rawData_ ? (this.rawData_[0] || this.attr_("labels")).length : 0 }, L.prototype.numRows = function () { return this.rawData_ ? this.rawData_.length : 0 }, L.prototype.getValue = function (t, e) { return t < 0 || t >= this.rawData_.length || e < 0 || e >= this.rawData_[t].length ? null : this.rawData_[t][e] }, L.prototype.createInterface_ = function () { var t, e = this.maindiv_, n = (this.graphDiv = document.createElement("div"), this.graphDiv.style.textAlign = "left", this.graphDiv.style.position = "relative", e.appendChild(this.graphDiv), this.canvas_ = M.createCanvas(), this.canvas_.style.position = "absolute", this.canvas_.style.top = 0, this.canvas_.style.left = 0, this.hidden_ = this.createPlotKitCanvas_(this.canvas_), this.canvas_ctx_ = M.getContext(this.canvas_), this.hidden_ctx_ = M.getContext(this.hidden_), this.resizeElements_(), this.graphDiv.appendChild(this.hidden_), this.graphDiv.appendChild(this.canvas_), this.mouseEventElement_ = this.createMouseEventElement_(), this.layout_ = new i.default(this), this); this.mouseMoveHandler_ = function (t) { n.mouseMove_(t) }, this.mouseOutHandler_ = function (t) { var e = t.target || t.fromElement, a = t.relatedTarget || t.toElement; M.isNodeContainedBy(e, n.graphDiv) && !M.isNodeContainedBy(a, n.graphDiv) && n.mouseOut_(t) }, this.addAndTrackEvent(window, "mouseout", this.mouseOutHandler_), this.addAndTrackEvent(this.mouseEventElement_, "mousemove", this.mouseMoveHandler_), this.resizeHandler_ || (this.resizeHandler_ = function (t) { n.resize() }, this.addAndTrackEvent(window, "resize", this.resizeHandler_), this.resizeObserver_ = null, t = this.getStringOption("resizable"), "undefined" == typeof ResizeObserver && "no" !== t && (console.error("ResizeObserver unavailable; ignoring resizable property"), t = "no"), "horizontal" === t || "vertical" === t || "both" === t ? e.style.resize = t : "passive" !== t && (t = "no"), "no" !== t && (window.getComputedStyle(e).overflow, "visible" === window.getComputedStyle(e).overflow && (e.style.overflow = "hidden"), this.resizeObserver_ = new ResizeObserver(this.resizeHandler_), this.resizeObserver_.observe(e))) }, L.prototype.resizeElements_ = function () { this.graphDiv.style.width = this.width_ + "px", this.graphDiv.style.height = this.height_ + "px"; var t = this.getNumericOption("pixelRatio"), e = t || M.getContextPixelRatio(this.canvas_ctx_), e = (this.canvas_.width = this.width_ * e, this.canvas_.height = this.height_ * e, this.canvas_.style.width = this.width_ + "px", this.canvas_.style.height = this.height_ + "px", 1 !== e && this.canvas_ctx_.scale(e, e), t || M.getContextPixelRatio(this.hidden_ctx_)); this.hidden_.width = this.width_ * e, this.hidden_.height = this.height_ * e, this.hidden_.style.width = this.width_ + "px", this.hidden_.style.height = this.height_ + "px", 1 !== e && this.hidden_ctx_.scale(e, e) }, L.prototype.destroy = function () { this.canvas_ctx_.restore(), this.hidden_ctx_.restore(); for (var t = this.plugins_.length - 1; 0 <= t; t--) { var e = this.plugins_.pop(); e.plugin.destroy && e.plugin.destroy() } function a(t) { for (; t.hasChildNodes();)a(t.firstChild), t.removeChild(t.firstChild) } function n(t) { for (var e in t) "object" == typeof t[e] && (t[e] = null) } this.removeTrackedEvents_(), M.removeEvent(window, "mouseout", this.mouseOutHandler_), M.removeEvent(this.mouseEventElement_, "mousemove", this.mouseMoveHandler_), this.resizeObserver_ && (this.resizeObserver_.disconnect(), this.resizeObserver_ = null), M.removeEvent(window, "resize", this.resizeHandler_), this.resizeHandler_ = null, a(this.maindiv_); n(this.layout_), n(this.plotter_), n(this) }, L.prototype.createPlotKitCanvas_ = function (t) { var e = M.createCanvas(); return e.style.position = "absolute", e.style.top = t.style.top, e.style.left = t.style.left, e.width = this.width_, e.height = this.height_, e.style.width = this.width_ + "px", e.style.height = this.height_ + "px", e }, L.prototype.createMouseEventElement_ = function () { return this.canvas_ }, L.prototype.setColors_ = function () { for (var t, e, a, n = this.getLabels(), i = n.length - 1, r = (this.colors_ = [], this.colorsMap_ = {}, this.getNumericOption("colorSaturation") || 1), o = this.getNumericOption("colorValue") || .5, s = Math.ceil(i / 2), l = this.getOption("colors"), h = this.visibility(), d = 0; d < i; d++)h[d] && (t = n[d + 1], a = (a = this.attributes_.getForSeries("color", t)) || (l ? l[d % l.length] : (e = d % 2 ? s + (d + 1) / 2 : Math.ceil((d + 1) / 2), M.hsvToRGB(+e / (1 + i), r, o))), this.colors_.push(a), this.colorsMap_[t] = a) }, L.prototype.getColors = function () { return this.colors_ }, L.prototype.getPropertiesForSeries = function (t) { for (var e = -1, a = this.getLabels(), n = 1; n < a.length; n++)if (a[n] == t) { e = n; break } return -1 == e ? null : { name: t, column: e, visible: this.visibility()[e - 1], color: this.colorsMap_[t], axis: 1 + this.attributes_.axisForSeries(t) } }, L.prototype.createRollInterface_ = function () { var t = this.roller_, e = (t || (this.roller_ = t = document.createElement("input"), t.type = "text", t.style.display = "none", t.className = "dygraph-roller", this.graphDiv.appendChild(t)), this.getBooleanOption("showRoller") ? "block" : "none"), a = this.getArea(), a = { top: a.y + a.h - 25 + "px", left: a.x + 1 + "px", display: e }, n = (t.size = "2", t.value = this.rollPeriod_, M.update(t.style, a), this); t.onchange = function () { return n.adjustRoll(t.value) } }, L.prototype.createDragInterface_ = function () { var t, a = { isZooming: !1, isPanning: !1, is2DPan: !1, dragStartX: null, dragStartY: null, dragEndX: null, dragEndY: null, dragDirection: null, prevEndX: null, prevEndY: null, prevDragDirection: null, cancelNextDblclick: !1, initialLeftmostDate: null, xUnitsPerPixel: null, dateRange: null, px: 0, py: 0, boundedDates: null, boundedValues: null, tarp: new o.default, initializeMouseDown: function (t, e, a) { t.preventDefault ? t.preventDefault() : (t.returnValue = !1, t.cancelBubble = !0); e = M.findPos(e.canvas_); a.px = e.x, a.py = e.y, a.dragStartX = M.dragGetX_(t, a), a.dragStartY = M.dragGetY_(t, a), a.cancelNextDblclick = !1, a.tarp.cover() }, destroy: function () { var t = this; if ((t.isZooming || t.isPanning) && (t.isZooming = !1, t.dragStartX = null, t.dragStartY = null), t.isPanning) { t.isPanning = !1, t.draggingDate = null, t.dateRange = null; for (var e = 0; e < n.axes_.length; e++)delete n.axes_[e].draggingValue, delete n.axes_[e].dragValueRange } t.tarp.uncover() } }, e = this.getOption("interactionModel"), n = this; for (t in e) e.hasOwnProperty(t) && this.addAndTrackEvent(this.mouseEventElement_, t, function (e) { return function (t) { e(t, n, a) } }(e[t])); e.willDestroyContextMyself || this.addAndTrackEvent(document, "mouseup", function (t) { a.destroy() }) }, L.prototype.drawZoomRect_ = function (t, e, a, n, i, r, o, s) { var l = this.canvas_ctx_; r == M.HORIZONTAL ? l.clearRect(Math.min(e, o), this.layout_.getPlotArea().y, Math.abs(e - o), this.layout_.getPlotArea().h) : r == M.VERTICAL && l.clearRect(this.layout_.getPlotArea().x, Math.min(n, s), this.layout_.getPlotArea().w, Math.abs(n - s)), t == M.HORIZONTAL ? a && e && (l.fillStyle = "rgba(128,128,128,0.33)", l.fillRect(Math.min(e, a), this.layout_.getPlotArea().y, Math.abs(a - e), this.layout_.getPlotArea().h)) : t == M.VERTICAL && i && n && (l.fillStyle = "rgba(128,128,128,0.33)", l.fillRect(this.layout_.getPlotArea().x, Math.min(n, i), this.layout_.getPlotArea().w, Math.abs(i - n))) }, L.prototype.clearZoomRect_ = function () { this.currentZoomRectArgs_ = null, this.canvas_ctx_.clearRect(0, 0, this.width_, this.height_) }, L.prototype.doZoomX_ = function (t, e) { this.currentZoomRectArgs_ = null; t = this.toDataXCoord(t), e = this.toDataXCoord(e); this.doZoomXDates_(t, e) }, L.prototype.doZoomXDates_ = function (t, e) { var a = this.xAxisRange(), n = [t, e], i = this.getFunctionOption("zoomCallback"), r = this; this.doAnimatedZoom(a, n, null, null, function () { i && i.call(r, t, e, r.yAxisRanges()) }) }, L.prototype.doZoomY_ = function (t, e) { this.currentZoomRectArgs_ = null; for (var a = this.yAxisRanges(), n = [], i = 0; i < this.axes_.length; i++) { var r = this.toDataYCoord(t, i), o = this.toDataYCoord(e, i); n.push([o, r]) } var s = this.getFunctionOption("zoomCallback"), l = this; this.doAnimatedZoom(null, null, a, n, function () { var t, e; s && (t = (e = P(l.xAxisRange(), 2))[0], e = e[1], s.call(l, t, e, l.yAxisRanges())) }) }, L.zoomAnimationFunction = function (t, e) { return (1 - Math.pow(1.5, -t)) / (1 - Math.pow(1.5, -e)) }, L.prototype.resetZoom = function () { var t, e, a, n, i, r, o, s = this.isZoomed("x"), l = this.isZoomed("y"), h = s || l; this.clearSelection(), h && (h = P(this.xAxisExtremes(), 2), t = h[0], e = h[1], h = this.getBooleanOption("animatedZooms"), a = this.getFunctionOption("zoomCallback"), h ? (r = i = n = h = null, s && (h = this.xAxisRange(), n = [t, e]), l && (i = this.yAxisRanges(), r = this.yAxisExtremes()), (o = this).doAnimatedZoom(h, n, i, r, function () { o.dateWindow_ = null, o.axes_.forEach(function (t) { t.valueRange && delete t.valueRange }), a && a.call(o, t, e, o.yAxisRanges()) })) : (this.dateWindow_ = null, this.axes_.forEach(function (t) { t.valueRange && delete t.valueRange }), this.drawGraph_(), a && a.call(this, t, e, this.yAxisRanges()))) }, L.prototype.doAnimatedZoom = function (t, e, a, n, i) { var r, o = this.getBooleanOption("animatedZooms") ? L.ANIMATION_STEPS : 1, s = [], l = []; if (null !== t && null !== e) for (r = 1; r <= o; r++)h = L.zoomAnimationFunction(r, o), s[r - 1] = [t[0] * (1 - h) + h * e[0], t[1] * (1 - h) + h * e[1]]; if (null !== a && null !== n) for (r = 1; r <= o; r++) { for (var h = L.zoomAnimationFunction(r, o), d = [], u = 0; u < this.axes_.length; u++)d.push([a[u][0] * (1 - h) + h * n[u][0], a[u][1] * (1 - h) + h * n[u][1]]); l[r - 1] = d } var c = this; M.repeatAndCleanup(function (t) { if (l.length) for (var e = 0; e < c.axes_.length; e++) { var a = l[t][e]; c.axes_[e].valueRange = [a[0], a[1]] } s.length && (c.dateWindow_ = s[t]), c.drawGraph_() }, o, L.ANIMATION_DURATION / o, i) }, L.prototype.getArea = function () { return this.plotter_.area }, L.prototype.eventToDomCoords = function (t) { var e; return t.offsetX && t.offsetY ? [t.offsetX, t.offsetY] : (e = M.findPos(this.mouseEventElement_), [M.pageX(t) - e.x, M.pageY(t) - e.y]) }, L.prototype.findClosestRow = function (t) { for (var e = 1 / 0, a = -1, n = this.layout_.points, i = 0; i < n.length; i++)for (var r = n[i], o = r.length, s = 0; s < o; s++) { var l, h = r[s]; M.isValidPoint(h, !0) && (l = Math.abs(h.canvasx - t)) < e && (e = l, a = h.idx) } return a }, L.prototype.findClosestPoint = function (t, e) { for (var a, n, i, r, o, s = 1 / 0, l = this.layout_.points.length - 1; 0 <= l; --l)for (var h = this.layout_.points[l], d = 0; d < h.length; ++d)n = h[d], M.isValidPoint(n) && (a = (a = n.canvasx - t) * a + (a = n.canvasy - e) * a) < s && (s = a, r = l, o = (i = n).idx); return { row: o, seriesName: this.layout_.setNames[r], point: i } }, L.prototype.findStackedPoint = function (t, e) { for (var a, n, i = this.findClosestRow(t), r = 0; r < this.layout_.points.length; ++r) { var o, s, l, h, d = i - this.getLeftBoundary_(r), u = this.layout_.points[r]; d >= u.length || (o = u[d], M.isValidPoint(o) && (s = o.canvasy, t > o.canvasx && 1 + d < u.length ? (l = u[1 + d], M.isValidPoint(l) && 0 < (h = l.canvasx - o.canvasx) && (s += (t - o.canvasx) / h * (l.canvasy - o.canvasy))) : t < o.canvasx && 0 < d && (l = u[d - 1], M.isValidPoint(l)) && 0 < (h = o.canvasx - l.canvasx) && (s += (o.canvasx - t) / h * (l.canvasy - o.canvasy)), 0 === r || s < e) && (a = o, n = r)) } return { row: i, seriesName: this.layout_.setNames[n], point: a } }, L.prototype.mouseMove_ = function (t) { var e, a, n = this.layout_.points; null != n && (a = (n = this.eventToDomCoords(t))[0], n = n[1], e = !1, e = this.getOption("highlightSeriesOpts") && !this.isSeriesLocked() ? (n = this.getBooleanOption("stackedGraph") ? this.findStackedPoint(a, n) : this.findClosestPoint(a, n), this.setSelection(n.row, n.seriesName)) : (n = this.findClosestRow(a), this.setSelection(n)), a = this.getFunctionOption("highlightCallback")) && e && a.call(this, t, this.lastx_, this.selPoints_, this.lastRow_, this.highlightSet_) }, L.prototype.getLeftBoundary_ = function (t) { if (this.boundaryIds_[t]) return this.boundaryIds_[t][0]; for (var e = 0; e < this.boundaryIds_.length; e++)if (void 0 !== this.boundaryIds_[e]) return this.boundaryIds_[e][0]; return 0 }, L.prototype.animateSelection_ = function (e) { void 0 === this.fadeLevel && (this.fadeLevel = 0), void 0 === this.animateId && (this.animateId = 0); var a, n, t = this.fadeLevel, t = e < 0 ? t : 10 - t; t <= 0 ? this.fadeLevel && this.updateSelection_(1) : (a = ++this.animateId, n = this, M.repeatAndCleanup(function (t) { n.animateId == a && (n.fadeLevel += e, 0 === n.fadeLevel ? n.clearSelection() : n.updateSelection_(n.fadeLevel / 10)) }, t, 30, function () { 0 !== n.fadeLevel && e < 0 && (n.fadeLevel = 0, n.clearSelection()) })) }, L.prototype.updateSelection_ = function (t) { this.cascadeEvents_("select", { selectedRow: -1 === this.lastRow_ ? void 0 : this.lastRow_, selectedX: null === this.lastx_ ? void 0 : this.lastx_, selectedPoints: this.selPoints_ }); var e = this.canvas_ctx_; if (this.getOption("highlightSeriesOpts")) { e.clearRect(0, 0, this.width_, this.height_); var a = 1 - this.getNumericOption("highlightSeriesBackgroundAlpha"), n = M.toRGB_(this.getOption("highlightSeriesBackgroundColor")); if (a) { if (this.getBooleanOption("animateBackgroundFade")) { if (void 0 === t) return void this.animateSelection_(1); a *= t } e.fillStyle = "rgba(" + n.r + "," + n.g + "," + n.b + "," + a + ")", e.fillRect(0, 0, this.width_, this.height_) } this.plotter_._renderLineChart(this.highlightSet_, e) } else if (0 <= this.previousVerticalX_) { for (var i = 0, r = this.attr_("labels"), o = 1; o < r.length; o++) { var s = this.getNumericOption("highlightCircleSize", r[o]); i < s && (i = s) } t = this.previousVerticalX_; e.clearRect(t - i - 1, 0, 2 * i + 2, this.height_) } if (0 < this.selPoints_.length) { var l = this.selPoints_[0].canvasx; for (e.save(), o = 0; o < this.selPoints_.length; o++) { var h, d, u, c = this.selPoints_[o]; isNaN(c.canvasy) || (h = this.getNumericOption("highlightCircleSize", c.name), u = this.getFunctionOption("drawHighlightPointCallback", c.name), d = this.plotter_.colors[c.name], u = u || M.Circles.DEFAULT, e.lineWidth = this.getNumericOption("strokeWidth", c.name), e.strokeStyle = d, e.fillStyle = d, u.call(this, this, c.name, e, l, c.canvasy, d, h, c.idx)) } e.restore(), this.previousVerticalX_ = l } }, L.prototype.setSelection = function (t, e, a, n) { var i = !(this.selPoints_ = []); if (!1 !== t && 0 <= t) { t != this.lastRow_ && (i = !0), this.lastRow_ = t; for (var r = 0; r < this.layout_.points.length; ++r) { var o = this.layout_.points[r], s = t - this.getLeftBoundary_(r); if (0 <= s && s < o.length && o[s].idx == t) null !== (l = o[s]).yval && this.selPoints_.push(l); else for (var l, h = 0; h < o.length; ++h)if ((l = o[h]).idx == t) { null !== l.yval && this.selPoints_.push(l); break } } } else 0 <= this.lastRow_ && (i = !0), this.lastRow_ = -1; return this.selPoints_.length ? this.lastx_ = this.selPoints_[0].xval : this.lastx_ = null, void 0 !== e && (this.highlightSet_ !== e && (i = !0), this.highlightSet_ = e), void 0 !== a && (this.lockedSet_ = a), i && (this.updateSelection_(void 0), n) && (e = this.getFunctionOption("highlightCallback")) && e.call(this, {}, this.lastx_, this.selPoints_, this.lastRow_, this.highlightSet_), i }, L.prototype.mouseOut_ = function (t) { this.getFunctionOption("unhighlightCallback") && this.getFunctionOption("unhighlightCallback").call(this, t), this.getBooleanOption("hideOverlayOnMouseOut") && !this.lockedSet_ && this.clearSelection() }, L.prototype.clearSelection = function () { this.cascadeEvents_("deselect", {}), this.lockedSet_ = !1, this.fadeLevel ? this.animateSelection_(-1) : (this.canvas_ctx_.clearRect(0, 0, this.width_, this.height_), this.fadeLevel = 0, this.selPoints_ = [], this.lastx_ = null, this.lastRow_ = -1, this.highlightSet_ = null) }, L.prototype.getSelection = function () { if (this.selPoints_ && !(this.selPoints_.length < 1)) for (var t = 0; t < this.layout_.points.length; t++)for (var e = this.layout_.points[t], a = 0; a < e.length; a++)if (e[a].x == this.selPoints_[0].x) return e[a].idx; return -1 }, L.prototype.getHighlightSeries = function () { return this.highlightSet_ }, L.prototype.isSeriesLocked = function () { return this.lockedSet_ }, L.prototype.loadedEvent_ = function (t) { this.rawData_ = this.parseCSV_(t), this.cascadeDataDidUpdateEvent_(), this.predraw_() }, L.prototype.addXTicks_ = function () { var t = this.dateWindow_ ? [this.dateWindow_[0], this.dateWindow_[1]] : this.xAxisExtremes(), e = this.optionsViewForAxis_("x"), t = e("ticker")(t[0], t[1], this.plotter_.area.w, e, this); this.layout_.setXTicks(t) }, L.prototype.getHandlerClass_ = function () { var t = this.attr_("dataHandler") ? this.attr_("dataHandler") : (this.fractions_ ? this.getBooleanOption("errorBars") ? p : d : this.getBooleanOption("customBars") ? h : this.getBooleanOption("errorBars") ? l : s).default; return t }, L.prototype.predraw_ = function () { var t = new Date; this.dataHandler_ = new (this.getHandlerClass_()), this.layout_.computePlotArea(), this.computeYAxes_(), this.is_initial_draw_ || (this.canvas_ctx_.restore(), this.hidden_ctx_.restore()), this.canvas_ctx_.save(), this.hidden_ctx_.save(), this.plotter_ = new r.default(this, this.hidden_, this.hidden_ctx_, this.layout_), this.createRollInterface_(), this.cascadeEvents_("predraw"), this.rolledSeries_ = [null]; for (var e = 1; e < this.numColumns(); e++) { var a = this.dataHandler_.extractSeries(this.rawData_, e, this.attributes_); 1 < this.rollPeriod_ && (a = this.dataHandler_.rollingAverage(a, this.rollPeriod_, this.attributes_, e)), this.rolledSeries_.push(a) } this.drawGraph_(); var n = new Date; this.drawingTimeMs_ = n - t }, L.PointType = void 0, L.stackPoints_ = function (t, e, a, n) { for (var i = null, r = null, o = null, s = -1, l = 0; l < t.length; ++l) { var h = t[l], d = h.xval, u = (void 0 === e[d] && (e[d] = 0), h.yval); if (isNaN(u) || null === u) if ("none" == n) u = 0; else { p = void 0; var c = l; if (!(c <= s)) for (var p = c; p < t.length; ++p)if (o = null, !isNaN(t[p].yval) && null !== t[p].yval) { o = t[s = p]; break } u = r && o && "none" != n ? r.yval + (o.yval - r.yval) * ((d - r.xval) / (o.xval - r.xval)) : r && "all" == n ? r.yval : o && "all" == n ? o.yval : 0 } else r = h; c = e[d]; i != d && (c += u, e[d] = c), i = d, (h.yval_stacked = c) > a[1] && (a[1] = c), c < a[0] && (a[0] = c) } }, L.prototype.gatherDatasets_ = function (t, e) { for (var a, n = [], i = [], r = [], o = {}, s = t.length - 1; 1 <= s; s--)if (this.visibility()[s - 1]) { if (e) { for (var l = t[s], h = e[0], d = e[1], u = null, c = null, p = 0; p < l.length; p++)l[p][0] >= h && null === u && (u = p), l[p][0] <= d && (c = p); for (var g = u = null === u ? 0 : u, f = !0; f && 0 < g;)f = null === l[--g][1]; for (var _ = c = null === c ? l.length - 1 : c, f = !0; f && _ < l.length - 1;)f = null === l[++_][1]; g !== u && (u = g), _ !== c && (c = _), n[s - 1] = [u, c], l = l.slice(u, c + 1) } else l = t[s], n[s - 1] = [0, l.length - 1]; var y = this.attr_("labels")[s], v = this.dataHandler_.getExtremeYValues(l, e, this.getBooleanOption("stepPlot", y)), x = this.dataHandler_.seriesToPoints(l, y, n[s - 1][0]); this.getBooleanOption("stackedGraph") && (void 0 === r[a = this.attributes_.axisForSeries(y)] && (r[a] = []), L.stackPoints_(x, r[a], v, this.getBooleanOption("stackedGraphNaNFill"))), o[y] = v, i[s] = x } return { points: i, extremes: o, boundaryIds: n } }, L.prototype.drawGraph_ = function () { for (var t = new Date, e = this.is_initial_draw_, a = (this.is_initial_draw_ = !1, this.layout_.removeAllDatasets(), this.setColors_(), this.attrs_.pointSize = .5 * this.getNumericOption("highlightCircleSize"), this.gatherDatasets_(this.rolledSeries_, this.dateWindow_)), n = a.points, i = a.extremes, r = (this.boundaryIds_ = a.boundaryIds, this.setIndexByName_ = {}, this.attr_("labels")), o = 0, s = 1; s < n.length; s++)this.visibility()[s - 1] && (this.layout_.addDataset(r[s], n[s]), this.datasetIndex_[s] = o++); for (s = 0; s < r.length; s++)this.setIndexByName_[r[s]] = s; this.computeYAxisRanges_(i), this.layout_.setYAxes(this.axes_), this.addXTicks_(), this.layout_.evaluate(), this.renderGraph_(e), this.getStringOption("timingName") && (a = new Date, console.log(this.getStringOption("timingName") + " - drawGraph: " + (a - t) + "ms")) }, L.prototype.renderGraph_ = function (t) { this.cascadeEvents_("clearChart"), this.plotter_.clear(); var e = this.getFunctionOption("underlayCallback"), e = (e && e.call(this, this.hidden_ctx_, this.layout_.getPlotArea(), this, this), { canvas: this.hidden_, drawingContext: this.hidden_ctx_ }), e = (this.cascadeEvents_("willDrawChart", e), this.plotter_.render(), this.cascadeEvents_("didDrawChart", e), this.lastRow_ = -1, this.canvas_.getContext("2d").clearRect(0, 0, this.width_, this.height_), this.getFunctionOption("drawCallback")); if (null !== e && e.call(this, this, t), t) for (this.readyFired_ = !0; 0 < this.readyFns_.length;)this.readyFns_.pop()(this) }, L.prototype.computeYAxes_ = function () { var t, e, a, n; for (this.axes_ = [], t = 0; t < this.attributes_.numAxes(); t++)M.update(e = { g: this }, this.attributes_.axisOptions(t)), this.axes_[t] = e; for (t = 0; t < this.axes_.length; t++)0 === t ? (a = (e = this.optionsViewForAxis_("y" + (t ? "2" : "")))("valueRange")) && (this.axes_[t].valueRange = a) : (n = this.user_attrs_.axes) && n.y2 && (a = n.y2.valueRange) && (this.axes_[t].valueRange = a) }, L.prototype.numAxes = function () { return this.attributes_.numAxes() }, L.prototype.axisPropertiesForSeries = function (t) { return this.axes_[this.attributes_.axisForSeries(t)] }, L.prototype.computeYAxisRanges_ = function (t) { for (var e, a, n = function (t) { return isNaN(parseFloat(t)) }, i = this.attributes_.numAxes(), r = 0; r < i; r++) { var o, s, l = this.axes_[r], h = this.attributes_.getForAxis("logscale", r), d = this.attributes_.getForAxis("includeZero", r), u = this.attributes_.getForAxis("independentTicks", r), c = this.attributes_.seriesForAxis(r), p = !0, g = .1, f = this.getNumericOption("yRangePad"); if (null !== f && (p = !1, g = f / this.plotter_.area.h), 0 === c.length) l.extremeRange = [0, 1]; else { for (var _, y = 1 / 0, v = -1 / 0, x = 0; x < c.length; x++)t.hasOwnProperty(c[x]) && (null !== (_ = t[c[x]][0]) && (y = Math.min(_, y)), null !== (_ = t[c[x]][1])) && (v = Math.max(_, v)); 0 === (e = (v = (v = d && !h && (0 < y && (y = 0), v < 0) ? 0 : v) == -1 / 0 ? 1 : v) - (y = y == 1 / 0 ? 0 : y)) && (e = 0 !== v ? Math.abs(v) : v = 1); var f = v, d = y; p && (h ? (f = v + g * e, d = y) : ((d = y - g * e) < 0 && 0 <= y && (d = 0), 0 < (f = v + g * e) && v <= 0 && (f = 0))), l.extremeRange = [d, f] } l.valueRange ? (o = (n(l.valueRange[0]) ? l.extremeRange : l.valueRange)[0], s = (n(l.valueRange[1]) ? l.extremeRange : l.valueRange)[1], l.computedValueRange = [o, s]) : l.computedValueRange = l.extremeRange, p || ((o = l.computedValueRange[0]) === (s = l.computedValueRange[1]) && (0 === o ? s = 1 : (o -= d = Math.abs(o / 10), s += d)), h ? (f = (g - 1) / (2 * g - 1), l.computedValueRange[0] = M.logRangeFraction(o, s, g / (2 * g - 1)), l.computedValueRange[1] = M.logRangeFraction(o, s, f)) : (l.computedValueRange[0] = o - (e = s - o) * g, l.computedValueRange[1] = s + e * g)), u && (l.independentTicks = u, b = (m = this.optionsViewForAxis_("y" + (r ? "2" : "")))("ticker"), l.ticks = b(l.computedValueRange[0], l.computedValueRange[1], this.plotter_.area.h, m, this), a = a || l) } if (void 0 === a) throw 'Configuration Error: At least one axis has to have the "independentTicks" option activated.'; for (r = 0; r < i; r++)if (!(l = this.axes_[r]).independentTicks) { for (var m, b = (m = this.optionsViewForAxis_("y" + (r ? "2" : "")))("ticker"), w = a.ticks, O = a.computedValueRange[1] - a.computedValueRange[0], A = l.computedValueRange[1] - l.computedValueRange[0], P = [], S = 0; S < w.length; S++) { var L = (w[S].v - a.computedValueRange[0]) / O, L = l.computedValueRange[0] + L * A; P.push(L) } l.ticks = b(l.computedValueRange[0], l.computedValueRange[1], this.plotter_.area.h, m, this, P) } }, L.prototype.detectTypeFromString_ = function (t) { var e = !1, a = t.indexOf("-"); (0 < a && "e" != t[a - 1] && "E" != t[a - 1] || 0 <= t.indexOf("/") || isNaN(parseFloat(t))) && (e = !0), this.setXAxisOptions_(e) }, L.prototype.setXAxisOptions_ = function (t) { t ? (this.attrs_.xValueParser = M.dateParser, this.attrs_.axes.x.valueFormatter = M.dateValueFormatter, this.attrs_.axes.x.ticker = v.dateTicker, this.attrs_.axes.x.axisLabelFormatter = M.dateAxisLabelFormatter) : (this.attrs_.xValueParser = function (t) { return parseFloat(t) }, this.attrs_.axes.x.valueFormatter = function (t) { return t }, this.attrs_.axes.x.ticker = v.numericTicks, this.attrs_.axes.x.axisLabelFormatter = this.attrs_.axes.x.valueFormatter) }, L.prototype.parseCSV_ = function (t) { for (var e, a, n = [], i = M.detectLineDelimiter(t), r = t.split(i || "\n"), o = this.getStringOption("delimiter"), t = (-1 == r[0].indexOf(o) && 0 <= r[0].indexOf("\t") && (o = "\t"), 0), s = ("labels" in this.user_attrs_ || (t = 1, this.attrs_.labels = r[0].split(o), this.attributes_.reparseSeries()), !1), l = this.attr_("labels").length, h = !1, d = t; d < r.length; d++) { var u = r[d]; if (0 !== u.length && "#" != u[0]) { var c = u.split(o); if (!(c.length < 2)) { var p = []; if (s || (this.detectTypeFromString_(c[0]), a = this.getFunctionOption("xValueParser"), s = !0), p[0] = a(c[0], this), this.fractions_) for (_ = 1; _ < c.length; _++)2 != (e = c[_].split("/")).length ? (console.error('Expected fractional "num/den" values in CSV data but found a value \'' + c[_] + "' on line " + (1 + d) + " ('" + u + "') which is not of this form."), p[_] = [0, 0]) : p[_] = [M.parseFloat_(e[0], d, u), M.parseFloat_(e[1], d, u)]; else if (this.getBooleanOption("errorBars")) for (c.length % 2 != 1 && console.error("Expected alternating (value, stdev.) pairs in CSV data but line " + (1 + d) + " has an odd number of values (" + (c.length - 1) + "): '" + u + "'"), _ = 1; _ < c.length; _ += 2)p[(_ + 1) / 2] = [M.parseFloat_(c[_], d, u), M.parseFloat_(c[_ + 1], d, u)]; else if (this.getBooleanOption("customBars")) for (_ = 1; _ < c.length; _++) { var g = c[_]; /^ *$/.test(g) ? p[_] = [null, null, null] : 3 == (e = g.split(";")).length ? p[_] = [M.parseFloat_(e[0], d, u), M.parseFloat_(e[1], d, u), M.parseFloat_(e[2], d, u)] : console.warn('When using customBars, values must be either blank or "low;center;high" tuples (got "' + g + '" on line ' + (1 + d) + ")") } else for (_ = 1; _ < c.length; _++)p[_] = M.parseFloat_(c[_], d, u); if (0 < n.length && p[0] < n[n.length - 1][0] && (h = !0), p.length != l && console.error("Number of columns in line " + d + " (" + p.length + ") does not agree with number of labels (" + l + ") " + u), 0 === d && this.attr_("labels")) { for (var f = !0, _ = 0; f && _ < p.length; _++)p[_] && (f = !1); if (f) { console.warn("The dygraphs 'labels' option is set, but the first row of CSV data ('" + u + "') appears to also contain labels. Will drop the CSV labels and use the option labels."); continue } } n.push(p) } } } return h && (console.warn("CSV is out of order; order it correctly to speed loading."), n.sort(function (t, e) { return t[0] - e[0] })), n }, L.prototype.parseArray_ = function (t) { if (0 === (t = 0 === t.length ? [[0]] : t)[0].length) return console.error("Data set cannot contain an empty row"), null; var e = t, a = e[0]; if ("number" != typeof (e = a[0]) && !M.isDateLike(e)) throw new Error("Expected number or date but got ".concat(typeof e, ": ").concat(e, ".")); for (var n = 1; n < a.length; n++) { var i = a[n]; if (null != i && ("number" != typeof i && !M.isArrayLike(i))) throw new Error("Expected number or array but got ".concat(typeof i, ": ").concat(i, ".")) } if (null === this.attr_("labels")) { for (console.warn("Using default labels. Set labels explicitly via 'labels' in the options parameter"), this.attrs_.labels = ["X"], o = 1; o < t[0].length; o++)this.attrs_.labels.push("Y" + o); this.attributes_.reparseSeries() } else { e = this.attr_("labels"); if (e.length != t[0].length) return console.error("Mismatch between number of labels (" + e + ") and number of columns in array (" + t[0].length + ")"), null } if (M.isDateLike(t[0][0])) { this.attrs_.axes.x.valueFormatter = M.dateValueFormatter, this.attrs_.axes.x.ticker = v.dateTicker, this.attrs_.axes.x.axisLabelFormatter = M.dateAxisLabelFormatter; for (var r = M.clone(t), o = 0; o < t.length; o++) { if (0 === r[o].length) return console.error("Row " + (1 + o) + " of data is empty"), null; if (null === r[o][0] || "function" != typeof r[o][0].getTime || isNaN(r[o][0].getTime())) return console.error("x value in row " + (1 + o) + " is not a Date"), null; r[o][0] = r[o][0].getTime() } return r } return this.attrs_.axes.x.valueFormatter = function (t) { return t }, this.attrs_.axes.x.ticker = v.numericTicks, this.attrs_.axes.x.axisLabelFormatter = M.numberAxisLabelFormatter, t }, L.prototype.parseDataTable_ = function (t) { var e = t.getNumberOfColumns(), a = t.getNumberOfRows(), n = t.getColumnType(0); if ("date" == n || "datetime" == n) this.attrs_.xValueParser = M.dateParser, this.attrs_.axes.x.valueFormatter = M.dateValueFormatter, this.attrs_.axes.x.ticker = v.dateTicker, this.attrs_.axes.x.axisLabelFormatter = M.dateAxisLabelFormatter; else { if ("number" != n) throw new Error("only 'date', 'datetime' and 'number' types are supported for column 1 of DataTable input (Got '" + n + "')"); this.attrs_.xValueParser = function (t) { return parseFloat(t) }, this.attrs_.axes.x.valueFormatter = function (t) { return t }, this.attrs_.axes.x.ticker = v.numericTicks, this.attrs_.axes.x.axisLabelFormatter = this.attrs_.axes.x.valueFormatter } for (var i, r = [], o = {}, s = !1, l = 1; l < e; l++) { var h = t.getColumnType(l); if ("number" == h) r.push(l); else { if ("string" != h || !this.getBooleanOption("displayAnnotations")) throw new Error("Only 'number' is supported as a dependent type with Gviz. 'string' is only supported if displayAnnotations is true"); h = r[r.length - 1]; o.hasOwnProperty(h) ? o[h].push(l) : o[h] = [l], s = !0 } } var d = [t.getColumnLabel(0)]; for (l = 0; l < r.length; l++)d.push(t.getColumnLabel(r[l])), this.getBooleanOption("errorBars") && (l += 1); var e = (this.attrs_.labels = d).length, u = [], c = !1, p = []; for (l = 0; l < a; l++) { var g = []; if (void 0 === t.getValue(l, 0) || null === t.getValue(l, 0)) console.warn("Ignoring row " + l + " of DataTable because of undefined or null first column."); else { if (g.push("date" == n || "datetime" == n ? t.getValue(l, 0).getTime() : t.getValue(l, 0)), this.getBooleanOption("errorBars")) for (i = 0; i < e - 1; i++)g.push([t.getValue(l, 1 + 2 * i), t.getValue(l, 2 + 2 * i)]); else { for (i = 0; i < r.length; i++) { var f = r[i]; if (g.push(t.getValue(l, f)), s && o.hasOwnProperty(f) && null !== t.getValue(l, o[f][0])) { var _ = {}; _.series = t.getColumnLabel(f), _.xval = g[0], _.shortText = function (t) { var e = String.fromCharCode(65 + t % 26); for (t = Math.floor(t / 26); 0 < t;)e = String.fromCharCode(65 + (t - 1) % 26) + e.toLowerCase(), t = Math.floor((t - 1) / 26); return e }(p.length), _.text = ""; for (var y = 0; y < o[f].length; y++)y && (_.text += "\n"), _.text += t.getValue(l, o[f][y]); p.push(_) } } for (i = 0; i < g.length; i++)isFinite(g[i]) || (g[i] = null) } 0 < u.length && g[0] < u[u.length - 1][0] && (c = !0), u.push(g) } } c && (console.warn("DataTable is out of order; order it correctly to speed loading."), u.sort(function (t, e) { return t[0] - e[0] })), this.rawData_ = u, 0 < p.length && this.setAnnotations(p, !0), this.attributes_.reparseSeries() }, L.prototype.cascadeDataDidUpdateEvent_ = function () { this.cascadeEvents_("dataDidUpdate", {}) }, L.prototype.start_ = function () { var t, e, a = this.file_, n = ("function" == typeof a && (a = a()), M.typeArrayLike(a)); "array" == n ? (this.rawData_ = this.parseArray_(a), this.cascadeDataDidUpdateEvent_(), this.predraw_()) : "object" == n && "function" == typeof a.getColumnRange ? (this.parseDataTable_(a), this.cascadeDataDidUpdateEvent_(), this.predraw_()) : "string" == n ? M.detectLineDelimiter(a) ? this.loadedEvent_(a) : (t = window.XMLHttpRequest ? new XMLHttpRequest : new ActiveXObject("Microsoft.XMLHTTP"), e = this, t.onreadystatechange = function () { 4 != t.readyState || 200 !== t.status && 0 !== t.status || e.loadedEvent_(t.responseText) }, t.open("GET", a, !0), t.send(null)) : console.error("Unknown data format: " + n) }, L.prototype.updateOptions = function (t, e) { void 0 === e && (e = !1); var a = t.file, t = L.copyUserAttrs_(t), n = this.attributes_.numAxes(), i = ("rollPeriod" in t && (this.rollPeriod_ = t.rollPeriod), "dateWindow" in t && (this.dateWindow_ = t.dateWindow), M.isPixelChangingOptionList(this.attr_("labels"), t)); M.updateDeep(this.user_attrs_, t), this.attributes_.reparseSeries(), n < this.attributes_.numAxes() && this.plotter_.clear(), a ? (this.cascadeEvents_("dataWillUpdate", {}), this.file_ = a, e || this.start_()) : e || (i ? this.predraw_() : this.renderGraph_(!1)) }, L.copyUserAttrs_ = function (t) { var e, a = {}; for (e in t) t.hasOwnProperty(e) && "file" != e && t.hasOwnProperty(e) && (a[e] = t[e]); return a }, L.prototype.resize = function (t, e) { var a, n; this.resize_lock || (this.resize_lock = !0, null === t != (null === e) && (console.warn("Dygraph.resize() should be called with zero parameters or two non-NULL parameters. Pretending it was zero."), t = e = null), a = this.width_, n = this.height_, t ? (this.maindiv_.style.width = t + "px", this.maindiv_.style.height = e + "px", this.width_ = t, this.height_ = e) : (this.width_ = this.maindiv_.clientWidth, this.height_ = this.maindiv_.clientHeight), a == this.width_ && n == this.height_ || (this.resizeElements_(), this.predraw_()), this.resize_lock = !1) }, L.prototype.adjustRoll = function (t) { this.rollPeriod_ = t, this.predraw_() }, L.prototype.visibility = function () { for (this.getOption("visibility") || (this.attrs_.visibility = []); this.getOption("visibility").length < this.numColumns() - 1;)this.attrs_.visibility.push(!0); return this.getOption("visibility") }, L.prototype.setVisibility = function (t, e) { var a = this.visibility(), n = !1; if (Array.isArray(t) || (null !== t && "object" == typeof t ? n = !0 : t = [t]), n) for (var i in t) t.hasOwnProperty(i) && (i < 0 || i >= a.length ? console.warn("Invalid series number in setVisibility: " + i) : a[i] = t[i]); else for (i = 0; i < t.length; i++)"boolean" == typeof t[i] ? i >= a.length ? console.warn("Invalid series number in setVisibility: " + i) : a[i] = t[i] : t[i] < 0 || t[i] >= a.length ? console.warn("Invalid series number in setVisibility: " + t[i]) : a[t[i]] = e; this.predraw_() }, L.prototype.size = function () { return { width: this.width_, height: this.height_ } }, L.prototype.setAnnotations = function (t, e) { this.annotations_ = t, this.layout_ ? (this.layout_.setAnnotations(this.annotations_), e || this.predraw_()) : console.warn("Tried to setAnnotations before dygraph was ready. Try setting them in a ready() block. See dygraphs.com/tests/annotation.html") }, L.prototype.annotations = function () { return this.annotations_ }, L.prototype.getLabels = function () { var t = this.attr_("labels"); return t ? t.slice() : null }, L.prototype.indexFromSetName = function (t) { return this.setIndexByName_[t] }, L.prototype.getRowForX = function (t) { for (var e = 0, a = this.numRows() - 1; e <= a;) { var n = a + e >> 1, i = this.getValue(n, 0); if (i < t) e = 1 + n; else if (t < i) a = n - 1; else { if (e == n) return n; a = n } } return null }, L.prototype.ready = function (t) { this.is_initial_draw_ ? this.readyFns_.push(t) : t.call(this, this) }, L.prototype.addAndTrackEvent = function (t, e, a) { M.addEvent(t, e, a), this.registeredEvents_.push({ elem: t, type: e, fn: a }) }, L.prototype.removeTrackedEvents_ = function () { if (this.registeredEvents_) for (var t = 0; t < this.registeredEvents_.length; t++) { var e = this.registeredEvents_[t]; M.removeEvent(e.elem, e.type, e.fn) } this.registeredEvents_ = [] }, L.PLUGINS = [m.default, _.default, b.default, y.default, f.default, x.default], L.GVizChart = t.default, L.DASHED_LINE = M.DASHED_LINE, L.DOT_DASH_LINE = M.DOT_DASH_LINE, L.dateAxisLabelFormatter = M.dateAxisLabelFormatter, L.toRGB_ = M.toRGB_, L.findPos = M.findPos, L.pageX = M.pageX, L.pageY = M.pageY, L.dateString_ = M.dateString_, L.defaultInteractionModel = n.default.defaultModel, L.nonInteractiveModel = L.nonInteractiveModel_ = n.default.nonInteractiveModel_, L.Circles = M.Circles, L.Plugins = { Legend: m.default, Axes: _.default, Annotations: f.default, ChartLabels: y.default, Grid: x.default, RangeSelector: b.default }, L.DataHandlers = { DefaultHandler: s.default, BarsHandler: g.default, CustomBarsHandler: h.default, DefaultFractionHandler: d.default, ErrorBarsHandler: l.default, FractionsBarsHandler: p.default }, L.startPan = n.default.startPan, L.startZoom = n.default.startZoom, L.movePan = n.default.movePan, L.moveZoom = n.default.moveZoom, L.endPan = n.default.endPan, L.endZoom = n.default.endZoom, L.numericLinearTicks = v.numericLinearTicks, L.numericTicks = v.numericTicks, L.dateTicker = v.dateTicker, L.Granularity = v.Granularity, L.getDateAxis = v.getDateAxis, L.floatFormat = M.floatFormat, M.setupDOMready_(L), a.default = L, e.exports = a.default }, { "./datahandler/bars": "dygraphs/src/datahandler/bars.js", "./datahandler/bars-custom": "dygraphs/src/datahandler/bars-custom.js", "./datahandler/bars-error": "dygraphs/src/datahandler/bars-error.js", "./datahandler/bars-fractions": "dygraphs/src/datahandler/bars-fractions.js", "./datahandler/default": "dygraphs/src/datahandler/default.js", "./datahandler/default-fractions": "dygraphs/src/datahandler/default-fractions.js", "./dygraph-canvas": "dygraphs/src/dygraph-canvas.js", "./dygraph-default-attrs": "dygraphs/src/dygraph-default-attrs.js", "./dygraph-gviz": "dygraphs/src/dygraph-gviz.js", "./dygraph-interaction-model": "dygraphs/src/dygraph-interaction-model.js", "./dygraph-layout": "dygraphs/src/dygraph-layout.js", "./dygraph-options": "dygraphs/src/dygraph-options.js", "./dygraph-options-reference": "dygraphs/src/dygraph-options-reference.js", "./dygraph-tickers": "dygraphs/src/dygraph-tickers.js", "./dygraph-utils": "dygraphs/src/dygraph-utils.js", "./iframe-tarp": "dygraphs/src/iframe-tarp.js", "./plugins/annotations": "dygraphs/src/plugins/annotations.js", "./plugins/axes": "dygraphs/src/plugins/axes.js", "./plugins/chart-labels": "dygraphs/src/plugins/chart-labels.js", "./plugins/grid": "dygraphs/src/plugins/grid.js", "./plugins/legend": "dygraphs/src/plugins/legend.js", "./plugins/range-selector": "dygraphs/src/plugins/range-selector.js" }], "dygraphs/src/iframe-tarp.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var s = function (t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = o(e); if (e && e.has(t)) return e.get(t); var a, n = {}, i = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) { var r; "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((r = i ? Object.getOwnPropertyDescriptor(t, a) : null) && (r.get || r.set) ? Object.defineProperty(n, a, r) : n[a] = t[a]) } n.default = t, e && e.set(t, n); return n }(t("./dygraph-utils")); function o(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (o = function (t) { return t ? a : e })(t)) } function n() { this.tarps = [] } n.prototype.cover = function () { for (var t = document.getElementsByTagName("iframe"), e = 0; e < t.length; e++) { var a = t[e], n = s.findPos(a), i = n.x, n = n.y, r = a.offsetWidth, a = a.offsetHeight, o = document.createElement("div"); o.style.position = "absolute", o.style.left = i + "px", o.style.top = n + "px", o.style.width = r + "px", o.style.height = a + "px", o.style.zIndex = 999, document.body.appendChild(o), this.tarps.push(o) } }, n.prototype.uncover = function () { for (var t = 0; t < this.tarps.length; t++)this.tarps[t].parentNode.removeChild(this.tarps[t]); this.tarps = [] }, a.default = n, e.exports = a.default }, { "./dygraph-utils": "dygraphs/src/dygraph-utils.js" }], "dygraphs/src/plugins/annotations.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; function n() { this.annotations_ = [] } n.prototype.toString = function () { return "Annotations Plugin" }, n.prototype.activate = function (t) { return { clearChart: this.clearChart, didDrawChart: this.didDrawChart } }, n.prototype.detachLabels = function () { for (var t = 0; t < this.annotations_.length; t++) { var e = this.annotations_[t]; e.parentNode && e.parentNode.removeChild(e), this.annotations_[t] = null } this.annotations_ = [] }, n.prototype.clearChart = function (t) { this.detachLabels() }, n.prototype.didDrawChart = function (t) { var r = t.dygraph, e = r.layout_.annotated_points; if (e && 0 !== e.length) for (var a = t.canvas.parentNode, n = function (a, n, i) { return function (t) { var e = i.annotation; e.hasOwnProperty(a) ? e[a](e, i, r, t) : r.getOption(n) && r.getOption(n)(e, i, r, t) } }, i = t.dygraph.getArea(), o = {}, s = 0; s < e.length; s++) { var l, h, d, u, c, p, g, f, _ = e[s]; _.canvasx < i.x || _.canvasx > i.x + i.w || _.canvasy < i.y || _.canvasy > i.y + i.h || (h = 6, (l = _.annotation).hasOwnProperty("tickHeight") && (h = l.tickHeight), (d = document.createElement("div")).style.fontSize = r.getOption("axisLabelFontSize") + "px", g = "dygraph-annotation", l.hasOwnProperty("icon") || (g += " dygraphDefaultAnnotation dygraph-default-annotation"), l.hasOwnProperty("cssClass") && (g += " " + l.cssClass), d.className = g, g = l.hasOwnProperty("width") ? l.width : 16, u = l.hasOwnProperty("height") ? l.height : 16, l.hasOwnProperty("icon") ? ((c = document.createElement("img")).src = l.icon, c.width = g, c.height = u, d.appendChild(c)) : _.annotation.hasOwnProperty("shortText") && d.appendChild(document.createTextNode(_.annotation.shortText)), c = _.canvasx - g / 2, d.style.left = c + "px", p = 0, p = l.attachAtBottom ? (f = i.y + i.h - u - h, o[c] ? f -= o[c] : o[c] = 0, o[c] += h + u, f) : _.canvasy - u - h, d.style.top = p + "px", d.style.width = g + "px", d.style.height = u + "px", d.title = _.annotation.text, d.style.color = r.colorsMap_[_.name], d.style.borderColor = r.colorsMap_[_.name], l.div = d, r.addAndTrackEvent(d, "click", n("clickHandler", "annotationClickHandler", _)), r.addAndTrackEvent(d, "mouseover", n("mouseOverHandler", "annotationMouseOverHandler", _)), r.addAndTrackEvent(d, "mouseout", n("mouseOutHandler", "annotationMouseOutHandler", _)), r.addAndTrackEvent(d, "dblclick", n("dblClickHandler", "annotationDblClickHandler", _)), a.appendChild(d), this.annotations_.push(d), (g = t.drawingContext).save(), g.strokeStyle = l.hasOwnProperty("tickColor") ? l.tickColor : r.colorsMap_[_.name], g.lineWidth = l.hasOwnProperty("tickWidth") ? l.tickWidth : r.getOption("strokeWidth"), g.beginPath(), l.attachAtBottom ? (g.moveTo(_.canvasx, f = p + u), g.lineTo(_.canvasx, f + h)) : (g.moveTo(_.canvasx, _.canvasy), g.lineTo(_.canvasx, _.canvasy - 2 - h)), g.closePath(), g.stroke(), g.restore()) } }, n.prototype.destroy = function () { this.detachLabels() }, a.default = n, e.exports = a.default }, {}], "dygraphs/src/plugins/axes.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var b = function (t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = o(e); if (e && e.has(t)) return e.get(t); var a, n = {}, i = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) { var r; "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((r = i ? Object.getOwnPropertyDescriptor(t, a) : null) && (r.get || r.set) ? Object.defineProperty(n, a, r) : n[a] = t[a]) } n.default = t, e && e.set(t, n); return n }(t("../dygraph-utils")); function o(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (o = function (t) { return t ? a : e })(t)) } function n() { this.xlabels_ = [], this.ylabels_ = [] } n.prototype.toString = function () { return "Axes Plugin" }, n.prototype.activate = function (t) { return { layout: this.layout, clearChart: this.clearChart, willDrawChart: this.willDrawChart } }, n.prototype.layout = function (t) { var e, a, n = t.dygraph; n.getOptionForAxis("drawAxis", "y") && (a = n.getOptionForAxis("axisLabelWidth", "y") + 2 * n.getOptionForAxis("axisTickSize", "y"), t.reserveSpaceLeft(a)), n.getOptionForAxis("drawAxis", "x") && (e = n.getOption("xAxisHeight") ? n.getOption("xAxisHeight") : n.getOptionForAxis("axisLabelFontSize", "x") + 2 * n.getOptionForAxis("axisTickSize", "x"), t.reserveSpaceBottom(e)), 2 == n.numAxes() ? n.getOptionForAxis("drawAxis", "y2") && (a = n.getOptionForAxis("axisLabelWidth", "y2") + 2 * n.getOptionForAxis("axisTickSize", "y2"), t.reserveSpaceRight(a)) : 2 < n.numAxes() && n.error("Only two y-axes are supported at this time. (Trying to use " + n.numAxes() + ")") }, n.prototype.detachLabels = function () { function t(t) { for (var e = 0; e < t.length; e++) { var a = t[e]; a.parentNode && a.parentNode.removeChild(a) } } t(this.xlabels_), t(this.ylabels_), this.xlabels_ = [], this.ylabels_ = [] }, n.prototype.clearChart = function (t) { this.detachLabels() }, n.prototype.willDrawChart = function (t) { var e, i, a, r, o, s, l, h, d, n, u, c, p, g, f, _, y, v = t.dygraph; function x(t) { return Math.round(t) + .5 } function m(t) { return Math.round(t) - .5 } (v.getOptionForAxis("drawAxis", "x") || v.getOptionForAxis("drawAxis", "y") || v.getOptionForAxis("drawAxis", "y2")) && (e = t.drawingContext, i = t.canvas.parentNode, a = v.width_, r = v.height_, h = { x: (n = function (t) { return { position: "absolute", fontSize: v.getOptionForAxis("axisLabelFontSize", t) + "px", width: v.getOptionForAxis("axisLabelWidth", t) + "px" } })("x"), y: n("y"), y2: n("y2") }, d = function (t, e, a) { var n = document.createElement("div"), i = h["y2" == a ? "y2" : e], i = (b.update(n.style, i), document.createElement("div")); return i.className = "dygraph-axis-label dygraph-axis-label-" + e + (a ? " dygraph-axis-label-" + a : ""), i.innerHTML = t, n.appendChild(i), n }, e.save(), n = v.layout_, u = t.dygraph.plotter_.area, t = function (e) { return function (t) { return v.getOptionForAxis(t, e) } }, c = this, (v.getOptionForAxis("drawAxis", "y") || 2 == v.numAxes() && v.getOptionForAxis("drawAxis", "y2")) && (n.yticks && 0 < n.yticks.length && (p = v.numAxes(), g = [t("y"), t("y2")], n.yticks.forEach(function (t) { var e, a, n; void 0 !== t.label && (s = u.x, n = "y1", e = g[0], 1 == t.axis && (s = u.x + u.w, n = "y2", e = g[1]), e("drawAxis")) && (a = e("axisLabelFontSize"), l = u.y + t.pos * u.h, o = d(t.label, "y", 2 == p ? n : null), r < (n = (n = l - a / 2) < 0 ? 0 : n) + a + 3 ? o.style.bottom = "0" : o.style.top = Math.min(n, r - 2 * a) + "px", 0 === t.axis ? (o.style.left = u.x - e("axisLabelWidth") - e("axisTickSize") + "px", o.style.textAlign = "right") : 1 == t.axis && (o.style.left = u.x + u.w + e("axisTickSize") + "px", o.style.textAlign = "left"), o.style.width = e("axisLabelWidth") + "px", i.appendChild(o), c.ylabels_.push(o)) })), y = v.getOption("drawAxesAtZero") ? ((1 < (_ = v.toPercentXCoord(0)) || _ < 0 || isNaN(_)) && (_ = 0), x(u.x + _ * u.w)) : x(u.x), e.strokeStyle = v.getOptionForAxis("axisLineColor", "y"), e.lineWidth = v.getOptionForAxis("axisLineWidth", "y"), e.beginPath(), e.moveTo(y, m(u.y)), e.lineTo(y, m(u.y + u.h)), e.closePath(), e.stroke(), 2 == v.numAxes()) && v.getOptionForAxis("drawAxis", "y2") && (e.strokeStyle = v.getOptionForAxis("axisLineColor", "y2"), e.lineWidth = v.getOptionForAxis("axisLineWidth", "y2"), e.beginPath(), e.moveTo(m(u.x + u.w), m(u.y)), e.lineTo(m(u.x + u.w), m(u.y + u.h)), e.closePath(), e.stroke()), v.getOptionForAxis("drawAxis", "x") && (n.xticks && (f = t("x"), n.xticks.forEach(function (t) { void 0 !== t.label && (s = u.x + t.pos * u.w, l = u.y + u.h, (o = d(t.label, "x")).style.textAlign = "center", o.style.top = l + f("axisTickSize") + "px", (t = s - f("axisLabelWidth") / 2) + f("axisLabelWidth") > a && (t = a - f("axisLabelWidth"), o.style.textAlign = "right"), t < 0 && (t = 0, o.style.textAlign = "left"), o.style.left = t + "px", o.style.width = f("axisLabelWidth") + "px", i.appendChild(o), c.xlabels_.push(o)) })), e.strokeStyle = v.getOptionForAxis("axisLineColor", "x"), e.lineWidth = v.getOptionForAxis("axisLineWidth", "x"), e.beginPath(), y = v.getOption("drawAxesAtZero") ? (_ = v.toPercentYCoord(0, 0), m(u.y + (_ = 1 < _ || _ < 0 ? 1 : _) * u.h)) : m(u.y + u.h), e.moveTo(x(u.x), y), e.lineTo(x(u.x + u.w), y), e.closePath(), e.stroke()), e.restore()) }, a.default = n, e.exports = a.default }, { "../dygraph-utils": "dygraphs/src/dygraph-utils.js" }], "dygraphs/src/plugins/chart-labels.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; function n() { this.title_div_ = null, this.xlabel_div_ = null, this.ylabel_div_ = null, this.y2label_div_ = null } function r(t) { var e = document.createElement("div"); return e.style.position = "absolute", e.style.left = t.x + "px", e.style.top = t.y + "px", e.style.width = t.w + "px", e.style.height = t.h + "px", e } function o(t, e, a, n, i) { var r = document.createElement("div"); return r.style.position = "absolute", r.style.left = 1 == a ? "0px" : e.x + "px", r.style.top = e.y + "px", r.style.width = e.w + "px", r.style.height = e.h + "px", r.style.fontSize = t.getOption("yLabelWidth") - 2 + "px", (t = document.createElement("div")).style.position = "absolute", t.style.width = e.h + "px", t.style.height = e.w + "px", t.style.top = e.h / 2 - e.w / 2 + "px", t.style.left = e.w / 2 - e.h / 2 + "px", t.className = "dygraph-label-rotate-" + (1 == a ? "right" : "left"), (e = document.createElement("div")).className = n, e.innerHTML = i, t.appendChild(e), r.appendChild(t), r } n.prototype.toString = function () { return "ChartLabels Plugin" }, n.prototype.activate = function (t) { return { layout: this.layout, didDrawChart: this.didDrawChart } }, n.prototype.detachLabels_ = function () { for (var t = [this.title_div_, this.xlabel_div_, this.ylabel_div_, this.y2label_div_], e = 0; e < t.length; e++) { var a = t[e]; a && a.parentNode && a.parentNode.removeChild(a) } this.title_div_ = null, this.xlabel_div_ = null, this.ylabel_div_ = null, this.y2label_div_ = null }; n.prototype.layout = function (t) { this.detachLabels_(); var e, a, n = t.dygraph, i = t.chart_div; n.getOption("title") && (a = t.reserveSpaceTop(n.getOption("titleHeight")), this.title_div_ = r(a), this.title_div_.style.fontSize = n.getOption("titleHeight") - 8 + "px", (a = document.createElement("div")).className = "dygraph-label dygraph-title", a.innerHTML = n.getOption("title"), this.title_div_.appendChild(a), i.appendChild(this.title_div_)), n.getOption("xlabel") && (e = t.reserveSpaceBottom(n.getOption("xLabelHeight")), this.xlabel_div_ = r(e), this.xlabel_div_.style.fontSize = n.getOption("xLabelHeight") - 2 + "px", (a = document.createElement("div")).className = "dygraph-label dygraph-xlabel", a.innerHTML = n.getOption("xlabel"), this.xlabel_div_.appendChild(a), i.appendChild(this.xlabel_div_)), n.getOption("ylabel") && (e = t.reserveSpaceLeft(0), this.ylabel_div_ = o(n, e, 1, "dygraph-label dygraph-ylabel", n.getOption("ylabel")), i.appendChild(this.ylabel_div_)), n.getOption("y2label") && 2 == n.numAxes() && (a = t.reserveSpaceRight(0), this.y2label_div_ = o(n, a, 2, "dygraph-label dygraph-y2label", n.getOption("y2label")), i.appendChild(this.y2label_div_)) }, n.prototype.didDrawChart = function (t) { t = t.dygraph; this.title_div_ && (this.title_div_.children[0].innerHTML = t.getOption("title")), this.xlabel_div_ && (this.xlabel_div_.children[0].innerHTML = t.getOption("xlabel")), this.ylabel_div_ && (this.ylabel_div_.children[0].children[0].innerHTML = t.getOption("ylabel")), this.y2label_div_ && (this.y2label_div_.children[0].children[0].innerHTML = t.getOption("y2label")) }, n.prototype.clearChart = function () { }, n.prototype.destroy = function () { this.detachLabels_() }, a.default = n, e.exports = a.default }, {}], "dygraphs/src/plugins/grid.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; function n() { } n.prototype.toString = function () { return "Gridline Plugin" }, n.prototype.activate = function (t) { return { willDrawChart: this.willDrawChart } }, n.prototype.willDrawChart = function (t) { var a, n, e, i = t.dygraph, r = t.drawingContext, o = i.layout_, s = t.dygraph.plotter_.area; function l(t) { return Math.round(t) + .5 } function h(t) { return Math.round(t) - .5 } if (i.getOptionForAxis("drawGrid", "y")) { for (var d = ["y", "y2"], u = [], c = [], p = [], g = [], f = [], _ = 0; _ < d.length; _++)p[_] = i.getOptionForAxis("drawGrid", d[_]), p[_] && (u[_] = i.getOptionForAxis("gridLineColor", d[_]), c[_] = i.getOptionForAxis("gridLineWidth", d[_]), f[_] = i.getOptionForAxis("gridLinePattern", d[_]), g[_] = f[_] && 2 <= f[_].length); e = o.yticks, r.save(), e.forEach(function (t) { var e; t.has_tick && (e = t.axis, p[e]) && (r.save(), g[e] && r.setLineDash && r.setLineDash(f[e]), r.strokeStyle = u[e], r.lineWidth = c[e], a = l(s.x), n = h(s.y + t.pos * s.h), r.beginPath(), r.moveTo(a, n), r.lineTo(a + s.w, n), r.stroke(), r.restore()) }), r.restore() } i.getOptionForAxis("drawGrid", "x") && (e = o.xticks, r.save(), f = i.getOptionForAxis("gridLinePattern", "x"), (g = f && 2 <= f.length) && r.setLineDash && r.setLineDash(f), r.strokeStyle = i.getOptionForAxis("gridLineColor", "x"), r.lineWidth = i.getOptionForAxis("gridLineWidth", "x"), e.forEach(function (t) { t.has_tick && (a = l(s.x + t.pos * s.w), n = h(s.y + s.h), r.beginPath(), r.moveTo(a, n), r.lineTo(a, s.y), r.stroke()) }), g && r.setLineDash && r.setLineDash([]), r.restore()) }, n.prototype.destroy = function () { }, a.default = n, e.exports = a.default }, {}], "dygraphs/src/plugins/legend.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var x = function (t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = o(e); if (e && e.has(t)) return e.get(t); var a, n = {}, i = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) { var r; "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((r = i ? Object.getOwnPropertyDescriptor(t, a) : null) && (r.get || r.set) ? Object.defineProperty(n, a, r) : n[a] = t[a]) } n.default = t, e && e.set(t, n); return n }(t("../dygraph-utils")); function o(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (o = function (t) { return t ? a : e })(t)) } function m() { this.legend_div_ = null, this.is_generated_div_ = !1 } m.prototype.toString = function () { return "Legend Plugin" }, m.prototype.activate = function (t) { var e, a = t.getOption("labelsDiv"); return a && null !== a ? e = "string" == typeof a || a instanceof String ? document.getElementById(a) : a : ((e = document.createElement("div")).className = "dygraph-legend", t.graphDiv.appendChild(e), this.is_generated_div_ = !0), this.legend_div_ = e, this.one_em_width_ = 10, { select: this.select, deselect: this.deselect, predraw: this.predraw, didDrawChart: this.didDrawChart } }; m.prototype.select = function (t) { var e, a, n, i, r, o = t.selectedX, s = t.selectedPoints, l = t.selectedRow, h = t.dygraph.getOption("legend"); "never" === h ? this.legend_div_.style.display = "none" : ((o = m.generateLegendHTML(t.dygraph, o, s, this.one_em_width_, l)) instanceof Node && o.nodeType === Node.DOCUMENT_FRAGMENT_NODE ? (this.legend_div_.innerHTML = "", this.legend_div_.appendChild(o)) : this.legend_div_.innerHTML = o, this.legend_div_.style.display = "", "follow" === h ? (i = t.dygraph.plotter_.area, r = this.legend_div_.offsetWidth, l = t.dygraph.getOptionForAxis("axisLabelWidth", "y"), n = (e = t.dygraph.getHighlightSeries()) && (n = s.find(function (t) { return t.name === e })) || s[0], o = t.dygraph.getNumericOption("legendFollowOffsetX"), s = t.dygraph.getNumericOption("legendFollowOffsetY"), a = n.x * i.w + o, n = n.y * i.h + s, a + r + 1 > i.w && (a = a - 2 * o - r - (l - i.x)), this.legend_div_.style.left = l + a + "px", this.legend_div_.style.top = n + "px") : "onmouseover" === h && this.is_generated_div_ && (i = t.dygraph.plotter_.area, r = this.legend_div_.offsetWidth, this.legend_div_.style.left = i.x + i.w - r - 1 + "px", this.legend_div_.style.top = i.y + "px")) }, m.prototype.deselect = function (t) { "always" !== t.dygraph.getOption("legend") && (this.legend_div_.style.display = "none"), a = this.legend_div_, (n = document.createElement("span")).setAttribute("style", "margin: 0; padding: 0 0 0 1em; border: 0;"), a.appendChild(n), e = n.offsetWidth, a.removeChild(n); var e, a = e, n = (this.one_em_width_ = a, m.generateLegendHTML(t.dygraph, void 0, void 0, a, null)); n instanceof Node && n.nodeType === Node.DOCUMENT_FRAGMENT_NODE ? (this.legend_div_.innerHTML = "", this.legend_div_.appendChild(n)) : this.legend_div_.innerHTML = n }, m.prototype.didDrawChart = function (t) { this.deselect(t) }, m.prototype.predraw = function (t) { var e; this.is_generated_div_ && (t.dygraph.graphDiv.appendChild(this.legend_div_), t = t.dygraph.plotter_.area, e = this.legend_div_.offsetWidth, this.legend_div_.style.left = t.x + t.w - e - 1 + "px", this.legend_div_.style.top = t.y + "px") }, m.prototype.destroy = function () { this.legend_div_ = null }, m.generateLegendHTML = function (t, e, a, n, i) { var r = { dygraph: t, x: e, i: i, series: [] }, o = {}, s = t.getLabels(); if (s) for (var l = 1; l < s.length; l++) { var h = t.getPropertiesForSeries(s[l]), d = { dashHTML: function (t, e, a) { if (!t || t.length <= 1) return '
'); var n, i, r, o, s, l = 0, h = 0, d = []; for (n = 0; n <= t.length; n++)l += t[n % t.length]; if (1 < (s = Math.floor(a / (l - t[0])))) { for (n = 0; n < t.length; n++)d[n] = t[n] / a; h = d.length } else { for (s = 1, n = 0; n < t.length; n++)d[n] = t[n] / l; h = d.length + 1 } var u = ""; for (i = 0; i < s; i++)for (n = 0; n < h; n += 2)r = d[n % d.length], o = n < t.length ? d[(n + 1) % d.length] : 0, u += '
'); return u }(t.getOption("strokePattern", s[l]), h.color, n), label: s[l], labelHTML: s[l].replace(/&/g, "&").replace(/"/g, """).replace(//g, ">"), isVisible: h.visible, color: h.color }; r.series.push(d), o[s[l]] = d } if (void 0 !== e) { for (var u = t.optionsViewForAxis_("x"), c = u("valueFormatter"), p = (r.xHTML = c.call(t, e, u, s[0], t, i, 0), []), g = t.numAxes(), l = 0; l < g; l++)p[l] = t.optionsViewForAxis_("y" + (l ? 1 + l : "")); var f = t.getOption("labelsShowZeroValues"), _ = t.getHighlightSeries(); for (l = 0; l < a.length; l++) { var y, v = a[l]; (d = o[v.name]).y = v.yval, 0 === v.yval && !f || isNaN(v.canvasy) ? d.isVisible = !1 : (y = (y = p[(h = t.getPropertiesForSeries(v.name)).axis - 1])("valueFormatter").call(t, v.yval, y, v.name, t, i, s.indexOf(v.name)), x.update(d, { yHTML: y }), v.name == _ && (d.isHighlighted = !0)) } } return (t.getOption("legendFormatter") || m.defaultFormatter).call(t, r) }, m.defaultFormatter = function (t) { var e = t.dygraph; if (!0 !== e.getOption("showLabelsOnHighlight")) return ""; var a = e.getOption("labelsSeparateLines"); if (void 0 === t.x) { if ("always" != e.getOption("legend")) return ""; for (var n = "", i = 0; i < t.series.length; i++)(r = t.series[i]).isVisible && ("" !== n && (n += a ? "
" : " "), n += "").concat(r.dashHTML, " ").concat(r.labelHTML, "")) } else { n = t.xHTML + ":"; for (var r, o, i = 0; i < t.series.length; i++)((r = t.series[i]).y || r.yHTML) && r.isVisible && (a && (n += "
"), o = r.isHighlighted ? ' class="highlight"' : "", n += " ").concat(r.labelHTML, ": ").concat(r.yHTML, "")) } return n }, a.default = m, e.exports = a.default }, { "../dygraph-utils": "dygraphs/src/dygraph-utils.js" }], "dygraphs/src/plugins/range-selector.js": [function (t, e, a) { "use strict"; Object.defineProperty(a, "__esModule", { value: !0 }), a.default = void 0; var O = function (t, e) { if (!e && t && t.__esModule) return t; if (null === t || "object" != typeof t && "function" != typeof t) return { default: t }; e = o(e); if (e && e.has(t)) return e.get(t); var a, n = {}, i = Object.defineProperty && Object.getOwnPropertyDescriptor; for (a in t) { var r; "default" !== a && Object.prototype.hasOwnProperty.call(t, a) && ((r = i ? Object.getOwnPropertyDescriptor(t, a) : null) && (r.get || r.set) ? Object.defineProperty(n, a, r) : n[a] = t[a]) } n.default = t, e && e.set(t, n); return n }(t("../dygraph-utils")), A = n(t("../dygraph-interaction-model")), P = n(t("../iframe-tarp")); function n(t) { return t && t.__esModule ? t : { default: t } } function o(t) { var e, a; return "function" != typeof WeakMap ? null : (e = new WeakMap, a = new WeakMap, (o = function (t) { return t ? a : e })(t)) } function i() { this.hasTouchInterface_ = "undefined" != typeof TouchEvent, this.isMobileDevice_ = /mobile|android/gi.test(navigator.appVersion), this.interfaceCreated_ = !1 } i.prototype.toString = function () { return "RangeSelector Plugin" }, i.prototype.activate = function (t) { return this.dygraph_ = t, this.getOption_("showRangeSelector") && this.createInterface_(), { layout: this.reserveSpace_, predraw: this.renderStaticLayer_, didDrawChart: this.renderInteractiveLayer_ } }, i.prototype.destroy = function () { this.bgcanvas_ = null, this.fgcanvas_ = null, this.leftZoomHandle_ = null, this.rightZoomHandle_ = null }, i.prototype.getOption_ = function (t, e) { return this.dygraph_.getOption(t, e) }, i.prototype.setDefaultOption_ = function (t, e) { this.dygraph_.attrs_[t] = e }, i.prototype.createInterface_ = function () { this.createCanvases_(), this.createZoomHandles_(), this.initInteraction_(), this.getOption_("animatedZooms") && (console.warn("Animated zooms and range selector are not compatible; disabling animatedZooms."), this.dygraph_.updateOptions({ animatedZooms: !1 }, !0)), this.interfaceCreated_ = !0, this.addToGraph_() }, i.prototype.addToGraph_ = function () { var t = this.graphDiv_ = this.dygraph_.graphDiv; t.appendChild(this.bgcanvas_), t.appendChild(this.fgcanvas_), t.appendChild(this.leftZoomHandle_), t.appendChild(this.rightZoomHandle_) }, i.prototype.removeFromGraph_ = function () { var t = this.graphDiv_; t.removeChild(this.bgcanvas_), t.removeChild(this.fgcanvas_), t.removeChild(this.leftZoomHandle_), t.removeChild(this.rightZoomHandle_), this.graphDiv_ = null }, i.prototype.reserveSpace_ = function (t) { this.getOption_("showRangeSelector") && t.reserveSpaceBottom(this.getOption_("rangeSelectorHeight") + 4) }, i.prototype.renderStaticLayer_ = function () { this.updateVisibility_() && (this.resize_(), this.drawStaticLayer_()) }, i.prototype.renderInteractiveLayer_ = function () { this.updateVisibility_() && !this.isChangingRange_ && (this.placeZoomHandles_(), this.drawInteractiveLayer_()) }, i.prototype.updateVisibility_ = function () { var t, e = this.getOption_("showRangeSelector"); return e ? this.interfaceCreated_ ? this.graphDiv_ && this.graphDiv_.parentNode || this.addToGraph_() : this.createInterface_() : this.graphDiv_ && (this.removeFromGraph_(), t = this.dygraph_, setTimeout(function () { t.width_ = 0, t.resize() }, 1)), e }, i.prototype.resize_ = function () { function t(t, e, a, n) { n = n || O.getContextPixelRatio(e); t.style.top = a.y + "px", t.style.left = a.x + "px", t.width = a.w * n, t.height = a.h * n, t.style.width = a.w + "px", t.style.height = a.h + "px", 1 != n && e.scale(n, n) } var e = this.dygraph_.layout_.getPlotArea(), a = 0, a = (this.dygraph_.getOptionForAxis("drawAxis", "x") && (a = this.getOption_("xAxisHeight") || this.getOption_("axisLabelFontSize") + 2 * this.getOption_("axisTickSize")), this.canvasRect_ = { x: e.x, y: e.y + e.h + a + 4, w: e.w, h: this.getOption_("rangeSelectorHeight") }, this.dygraph_.getNumericOption("pixelRatio")); t(this.bgcanvas_, this.bgcanvas_ctx_, this.canvasRect_, a), t(this.fgcanvas_, this.fgcanvas_ctx_, this.canvasRect_, a) }, i.prototype.createCanvases_ = function () { this.bgcanvas_ = O.createCanvas(), this.bgcanvas_.className = "dygraph-rangesel-bgcanvas", this.bgcanvas_.style.position = "absolute", this.bgcanvas_.style.zIndex = 9, this.bgcanvas_ctx_ = O.getContext(this.bgcanvas_), this.fgcanvas_ = O.createCanvas(), this.fgcanvas_.className = "dygraph-rangesel-fgcanvas", this.fgcanvas_.style.position = "absolute", this.fgcanvas_.style.zIndex = 9, this.fgcanvas_.style.cursor = "default", this.fgcanvas_ctx_ = O.getContext(this.fgcanvas_) }, i.prototype.createZoomHandles_ = function () { var t = new Image; t.className = "dygraph-rangesel-zoomhandle", t.style.position = "absolute", t.style.zIndex = 10, t.style.visibility = "hidden", t.style.cursor = "col-resize", t.width = 9, t.height = 16, t.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAQCAYAAADESFVDAAAAAXNSR0IArs4c6QAAAAZiS0dEANAAzwDP4Z7KegAAAAlwSFlzAAAOxAAADsQBlSsOGwAAAAd0SU1FB9sHGw0cMqdt1UwAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAaElEQVQoz+3SsRFAQBCF4Z9WJM8KCDVwownl6YXsTmCUsyKGkZzcl7zkz3YLkypgAnreFmDEpHkIwVOMfpdi9CEEN2nGpFdwD03yEqDtOgCaun7sqSTDH32I1pQA2Pb9sZecAxc5r3IAb21d6878xsAAAAAASUVORK5CYII=", this.isMobileDevice_ && (t.width *= 2, t.height *= 2), this.leftZoomHandle_ = t, this.rightZoomHandle_ = t.cloneNode(!1) }, i.prototype.initInteraction_ = function () { var i = this, e = document, r = 0, n = null, o = !1, s = !1, l = !this.isMobileDevice_, a = new P.default, h = function (t) { var e = i.dygraph_.xAxisExtremes(), a = (e[1] - e[0]) / i.canvasRect_.w; return [e[0] + (t.leftHandlePos - i.canvasRect_.x) * a, e[0] + (t.rightHandlePos - i.canvasRect_.x) * a] }, d = function (t) { return O.cancelEvent(t), o = !0, r = t.clientX, n = t.target || t.srcElement, "mousedown" !== t.type && "dragstart" !== t.type || (O.addEvent(e, "mousemove", u), O.addEvent(e, "mouseup", c)), i.fgcanvas_.style.cursor = "col-resize", a.cover(), !0 }, u = function (t) { if (!o) return !1; O.cancelEvent(t); var e, a = t.clientX - r; return Math.abs(a) < 4 || (r = t.clientX, t = i.getZoomHandleStatus_(), e = n == i.leftZoomHandle_ ? (e = t.leftHandlePos + a, e = Math.min(e, t.rightHandlePos - n.width - 3), Math.max(e, i.canvasRect_.x)) : (e = t.rightHandlePos + a, e = Math.min(e, i.canvasRect_.x + i.canvasRect_.w), Math.max(e, t.leftHandlePos + n.width + 3)), a = n.width / 2, n.style.left = e - a + "px", i.drawInteractiveLayer_(), l && p()), !0 }, c = function (t) { return !!o && (o = !1, a.uncover(), O.removeEvent(e, "mousemove", u), O.removeEvent(e, "mouseup", c), i.fgcanvas_.style.cursor = "default", l || p(), !0) }, p = function () { try { var t, e = i.getZoomHandleStatus_(); i.isChangingRange_ = !0, e.isZoomed ? (t = h(e), i.dygraph_.doZoomXDates_(t[0], t[1])) : i.dygraph_.resetZoom() } finally { i.isChangingRange_ = !1 } }, g = function (t) { var e = i.leftZoomHandle_.getBoundingClientRect(), a = e.left + e.width / 2, e = (e = i.rightZoomHandle_.getBoundingClientRect()).left + e.width / 2; return t.clientX > a && t.clientX < e }, f = function (t) { return !(s || !g(t) || !i.getZoomHandleStatus_().isZoomed || (O.cancelEvent(t), s = !0, r = t.clientX, "mousedown" === t.type && (O.addEvent(e, "mousemove", _), O.addEvent(e, "mouseup", y)), 0)) }, _ = function (t) { if (!s) return !1; O.cancelEvent(t); var e, a, n = t.clientX - r; return Math.abs(n) < 4 || (r = t.clientX, e = (t = i.getZoomHandleStatus_()).leftHandlePos, a = (t = t.rightHandlePos) - e, e + n <= i.canvasRect_.x ? t = (e = i.canvasRect_.x) + a : t + n >= i.canvasRect_.x + i.canvasRect_.w ? e = (t = i.canvasRect_.x + i.canvasRect_.w) - a : (e += n, t += n), a = i.leftZoomHandle_.width / 2, i.leftZoomHandle_.style.left = e - a + "px", i.rightZoomHandle_.style.left = t - a + "px", i.drawInteractiveLayer_(), l && v()), !0 }, y = function (t) { return !!s && (s = !1, O.removeEvent(e, "mousemove", _), O.removeEvent(e, "mouseup", y), l || v(), !0) }, v = function () { try { i.isChangingRange_ = !0, i.dygraph_.dateWindow_ = h(i.getZoomHandleStatus_()), i.dygraph_.drawGraph_(!1) } finally { i.isChangingRange_ = !1 } }, t = function (t) { o || s || (t = g(t) ? "move" : "default") != i.fgcanvas_.style.cursor && (i.fgcanvas_.style.cursor = t) }, x = function (t) { "touchstart" == t.type && 1 == t.targetTouches.length ? d(t.targetTouches[0]) && O.cancelEvent(t) : "touchmove" == t.type && 1 == t.targetTouches.length ? u(t.targetTouches[0]) && O.cancelEvent(t) : c(t) }, m = function (t) { "touchstart" == t.type && 1 == t.targetTouches.length ? f(t.targetTouches[0]) && O.cancelEvent(t) : "touchmove" == t.type && 1 == t.targetTouches.length ? _(t.targetTouches[0]) && O.cancelEvent(t) : y(t) }, b = function (t, e) { for (var a = ["touchstart", "touchend", "touchmove", "touchcancel"], n = 0; n < a.length; n++)i.dygraph_.addAndTrackEvent(t, a[n], e) }, w = (this.setDefaultOption_("interactionModel", A.default.dragIsPanInteractionModel), this.setDefaultOption_("panEdgeFraction", 1e-4), window.opera ? "mousedown" : "dragstart"); this.dygraph_.addAndTrackEvent(this.leftZoomHandle_, w, d), this.dygraph_.addAndTrackEvent(this.rightZoomHandle_, w, d), this.dygraph_.addAndTrackEvent(this.fgcanvas_, "mousedown", f), this.dygraph_.addAndTrackEvent(this.fgcanvas_, "mousemove", t), this.hasTouchInterface_ && (b(this.leftZoomHandle_, x), b(this.rightZoomHandle_, x), b(this.fgcanvas_, m)) }, i.prototype.drawStaticLayer_ = function () { var t = this.bgcanvas_ctx_; t.clearRect(0, 0, this.canvasRect_.w, this.canvasRect_.h); try { this.drawMiniPlot_() } catch (t) { console.warn(t) } this.bgcanvas_ctx_.lineWidth = this.getOption_("rangeSelectorBackgroundLineWidth"), t.strokeStyle = this.getOption_("rangeSelectorBackgroundStrokeColor"), t.beginPath(), t.moveTo(.5, .5), t.lineTo(.5, this.canvasRect_.h - .5), t.lineTo(this.canvasRect_.w - .5, this.canvasRect_.h - .5), t.lineTo(this.canvasRect_.w - .5, .5), t.stroke() }, i.prototype.drawMiniPlot_ = function () { var t = this.getOption_("rangeSelectorPlotFillColor"), e = this.getOption_("rangeSelectorPlotFillGradientColor"), a = this.getOption_("rangeSelectorPlotStrokeColor"); if (t || a) { var n = this.getOption_("stepPlot"), i = this.computeCombinedSeriesAndLimits_(), r = i.yMax - i.yMin, o = this.bgcanvas_ctx_, s = this.dygraph_.xAxisExtremes(), l = Math.max(s[1] - s[0], 1e-30), h = (this.canvasRect_.w - .5) / l, d = (this.canvasRect_.h - .5) / r, l = this.canvasRect_.w - .5, u = this.canvasRect_.h - .5, c = null, p = null; o.beginPath(), o.moveTo(.5, u); for (var g = 0; g < i.data.length; g++) { var f = i.data[g], _ = null !== f[0] ? (f[0] - s[0]) * h : NaN, f = null !== f[1] ? u - (f[1] - i.yMin) * d : NaN; !n && null !== c && Math.round(_) == Math.round(c) || (isFinite(_) && isFinite(f) ? (null === c ? o.lineTo(_, u) : n && o.lineTo(_, p), o.lineTo(_, f), c = _, p = f) : (null !== c && (n ? (o.lineTo(_, p), o.lineTo(_, u)) : o.lineTo(c, u)), c = p = null)) } o.lineTo(l, u), o.closePath(), t && (r = this.bgcanvas_ctx_.createLinearGradient(0, 0, 0, u), e && r.addColorStop(0, e), r.addColorStop(1, t), this.bgcanvas_ctx_.fillStyle = r, o.fill()), a && (this.bgcanvas_ctx_.strokeStyle = a, this.bgcanvas_ctx_.lineWidth = this.getOption_("rangeSelectorPlotLineWidth"), o.stroke()) } }, i.prototype.computeCombinedSeriesAndLimits_ = function () { for (var t = this.dygraph_, e = this.getOption_("logscale"), a = t.numColumns(), n = t.getLabels(), i = new Array(a), r = !1, o = t.visibility(), s = [], l = 1; l < a; l++) { var h = this.getOption_("showInRangeSelector", n[l]); s.push(h), null !== h && (r = !0) } if (r) for (l = 1; l < a; l++)i[l] = s[l - 1]; else for (l = 1; l < a; l++)i[l] = o[l - 1]; var d, u = [], c = t.dataHandler_, p = t.attributes_; for (l = 1; l < t.numColumns(); l++)i[l] && (d = c.extractSeries(t.rawData_, l, p), 1 < t.rollPeriod() && (d = c.rollingAverage(d, t.rollPeriod(), p, l)), u.push(d)); var g = []; for (l = 0; l < u[0].length; l++) { for (var f = 0, _ = 0, y = 0; y < u.length; y++) { var v = u[y][l][1]; null === v || isNaN(v) || (_++, f += v) } g.push([u[0][l][0], f / _]) } var x = Number.MAX_VALUE, m = -Number.MAX_VALUE; for (l = 0; l < g.length; l++) { var b = g[l][1]; null !== b && isFinite(b) && (!e || 0 < b) && (x = Math.min(x, b), m = Math.max(m, b)) } if (e) for (m = O.log10(m), m += .25 * m, x = O.log10(x), l = 0; l < g.length; l++)g[l][1] = O.log10(g[l][1]); else { var w = m - x, w = w <= Number.MIN_VALUE ? .25 * m : .25 * w; m += w, x -= w } return { data: g, yMin: x, yMax: m } }, i.prototype.placeZoomHandles_ = function () { var t = this.dygraph_.xAxisExtremes(), e = this.dygraph_.xAxisRange(), a = t[1] - t[0], n = Math.max(0, (e[0] - t[0]) / a), t = Math.max(0, (t[1] - e[1]) / a), e = this.canvasRect_.x + this.canvasRect_.w * n, a = this.canvasRect_.x + this.canvasRect_.w * (1 - t), n = Math.max(this.canvasRect_.y, this.canvasRect_.y + (this.canvasRect_.h - this.leftZoomHandle_.height) / 2), t = this.leftZoomHandle_.width / 2; this.leftZoomHandle_.style.left = e - t + "px", this.leftZoomHandle_.style.top = n + "px", this.rightZoomHandle_.style.left = a - t + "px", this.rightZoomHandle_.style.top = this.leftZoomHandle_.style.top, this.leftZoomHandle_.style.visibility = "visible", this.rightZoomHandle_.style.visibility = "visible" }, i.prototype.drawInteractiveLayer_ = function () { var t, e, a = this.fgcanvas_ctx_, n = (a.clearRect(0, 0, this.canvasRect_.w, this.canvasRect_.h), this.canvasRect_.w - 1), i = this.canvasRect_.h - 1, r = this.getZoomHandleStatus_(); a.strokeStyle = this.getOption_("rangeSelectorForegroundStrokeColor"), a.lineWidth = this.getOption_("rangeSelectorForegroundLineWidth"), r.isZoomed ? (t = Math.max(1, r.leftHandlePos - this.canvasRect_.x), r = Math.min(n, r.rightHandlePos - this.canvasRect_.x), e = this.getOption_("rangeSelectorVeilColour"), a.fillStyle = e || "rgba(240, 240, 240, " + this.getOption_("rangeSelectorAlpha").toString() + ")", a.fillRect(0, 0, t, this.canvasRect_.h), a.fillRect(r, 0, this.canvasRect_.w - r, this.canvasRect_.h), a.beginPath(), a.moveTo(1, 1), a.lineTo(t, 1), a.lineTo(t, i), a.lineTo(r, i), a.lineTo(r, 1)) : (a.beginPath(), a.moveTo(1, 1), a.lineTo(1, i), a.lineTo(n, i)), a.lineTo(n, 1), a.stroke() }, i.prototype.getZoomHandleStatus_ = function () { var t = this.leftZoomHandle_.width / 2, e = parseFloat(this.leftZoomHandle_.style.left) + t, t = parseFloat(this.rightZoomHandle_.style.left) + t; return { leftHandlePos: e, rightHandlePos: t, isZoomed: e - 1 > this.canvasRect_.x || t + 1 < this.canvasRect_.x + this.canvasRect_.w } }, a.default = i, e.exports = a.default }, { "../dygraph-interaction-model": "dygraphs/src/dygraph-interaction-model.js", "../dygraph-utils": "dygraphs/src/dygraph-utils.js", "../iframe-tarp": "dygraphs/src/iframe-tarp.js" }] }, {}, ["dygraphs/src/dygraph.js"]), e = t("dygraphs/src/dygraph.js"); return e._require._b = t, e }); +//# sourceMappingURL=dygraph.min.js.map diff --git a/src/BaseModelicaLibraryTesting.jl b/src/BaseModelicaLibraryTesting.jl index a4642a585..383507fad 100644 --- a/src/BaseModelicaLibraryTesting.jl +++ b/src/BaseModelicaLibraryTesting.jl @@ -1,5 +1,42 @@ module BaseModelicaLibraryTesting -# Write your package code here. +import OMJulia +import OMJulia: sendExpression +import BaseModelica +import DifferentialEquations: solve, Rodas5P, ReturnCode +import ModelingToolkit +import Dates: now +import Printf: @sprintf -end +include("types.jl") +include("compare.jl") # defines _clean_var_name used by simulate.jl +include("export.jl") +include("parse_bm.jl") +include("simulate.jl") +include("report.jl") +include("pipeline.jl") + +# ── Public API ───────────────────────────────────────────────────────────────── + +# Shared types and constants +export ModelResult, CompareSettings +export LIBRARY, LIBRARY_VERSION, CMP_REL_TOL, CMP_ABS_TOL + +# Comparison configuration +export configure_comparison!, compare_settings + +# Pipeline phases +export run_export # Phase 1: Base Modelica export via OMC +export run_parse # Phase 2: BaseModelica.jl → ODEProblem +export run_simulate # Phase 3: DifferentialEquations solve + CSV + +# Reference comparison +export compare_with_reference, write_diff_html + +# HTML report +export generate_report + +# Top-level orchestration +export test_model, main + +end # module BaseModelicaLibraryTesting diff --git a/src/compare.jl b/src/compare.jl new file mode 100644 index 000000000..647a63212 --- /dev/null +++ b/src/compare.jl @@ -0,0 +1,393 @@ +# ── Variable name utilities ──────────────────────────────────────────────────── + +import ModelingToolkit +import Printf: @sprintf + +"""Strip Julia var"..." quoting and MTK time annotation from a variable name. + +MTK unknowns may be printed as `var"C1.v"(t)` (Julia's non-standard identifier +syntax). This function removes the surrounding `var"…"` wrapper and the trailing +`(t)` so that the result is a plain, human-readable name like `C1.v`. +""" +function _clean_var_name(name::AbstractString)::String + s = strip(string(name)) + # Remove Julia's var"..." identifier quoting: var"foo"(t) → foo(t) + if startswith(s, "var\"") && endswith(s, "\"") + s = s[5:end-1] + elseif startswith(s, "var\"") && endswith(s, "\"(t)") + s = s[5:end-4] + end + # Remove trailing (t) time annotation + if endswith(s, "(t)") + s = s[1:end-3] + end + return s +end + +"""Normalize a variable name for fuzzy matching across naming conventions. + +MTK uses '₊' as the hierarchy separator and appends '(t)' to time-dependent +symbols; the MAP-LIB CSVs use plain dots. This function maps both to a common +lowercase dot-separated form. +""" +function _normalize_var(name::AbstractString)::String + s = _clean_var_name(name) # strip var"..." quoting and trailing (t) + s = replace(s, "₊" => ".") # MTK hierarchy → dot + return lowercase(strip(s)) +end + +# ── Reference CSV helpers ────────────────────────────────────────────────────── + +""" + _ref_csv_path(ref_root, model) → path or nothing + +Return the path to the reference CSV for `model` inside the MAP-LIB checkout +at `ref_root`, or `nothing` if the file does not exist. + +Example: model = "Modelica.Electrical.Analog.Examples.ChuaCircuit" + → /Modelica/Electrical/Analog/Examples/ChuaCircuit/ChuaCircuit.csv +""" +function _ref_csv_path(ref_root::String, model::String)::Union{String,Nothing} + parts = split(model, ".") + csv_path = joinpath(ref_root, parts..., parts[end] * ".csv") + isfile(csv_path) ? csv_path : nothing +end + +""" + _read_ref_csv(path) → (times, data) + +Read a MAP-LIB reference CSV and return the time vector and a +column-name → value-vector dictionary. +""" +function _read_ref_csv(path::String)::Tuple{Vector{Float64}, Dict{String,Vector{Float64}}} + lines = filter(!isempty ∘ strip, readlines(path)) + isempty(lines) && return Float64[], Dict{String,Vector{Float64}}() + + # Header row may have quoted column names: "time","C1.v","C2.v","L.i" + headers = [replace(strip(h), "\"" => "") for h in split(lines[1], ",")] + + data = Dict{String,Vector{Float64}}(h => Float64[] for h in headers) + for line in lines[2:end] + isempty(strip(line)) && continue + for (h, tok) in zip(headers, split(strip(line), ",")) + v = tryparse(Float64, strip(tok)) + push!(data[h], something(v, NaN)) + end + end + + times = get(data, "time", Float64[]) + return times, data +end + +# ── Asset management ─────────────────────────────────────────────────────────── + +# Path to the package's bundled assets directory (../assets relative to src/) +const _ASSETS_DIR = joinpath(dirname(@__DIR__), "assets") + +""" + _install_assets(results_root) + +Copy the bundled Dygraph JS/CSS and HTML template from the package `assets/` +directory into `/assets/` so that generated HTML pages can +reference them with a relative path. Files that already exist are skipped. +""" +function _install_assets(results_root::String) + dst = joinpath(results_root, "assets") + isdir(dst) || mkpath(dst) + for fname in ("dygraph.min.js", "dygraph.min.css") + src_file = joinpath(_ASSETS_DIR, fname) + dst_file = joinpath(dst, fname) + isfile(dst_file) || cp(src_file, dst_file) + end +end + +# ── Comparison settings and error functions ──────────────────────────────────── + +"""Module-level default comparison settings. Modify via `configure_comparison!`.""" +const _CMP_SETTINGS = CompareSettings() + +""" + _check_relative(s, r, ref_scale, cfg) → Bool + +Classic relative-error check. Passes when + + |s − r| ≤ max(rel_tol · |r|, abs_tol) + +This is the traditional approach used by many validation tools. It works well +when the signal stays well away from zero, but may produce false failures at +zero crossings because the per-point tolerance shrinks to `abs_tol ≈ 0` when +`r ≈ 0`. +""" +function _check_relative(s::Real, r::Real, ::Real, cfg::CompareSettings)::Bool + abs(s - r) <= max(cfg.rel_tol * abs(r), cfg.abs_tol) +end + +""" + _check_mixed(s, r, ref_scale, cfg) → Bool + +Scale-aware relative-error check (default). Passes when + + |s − r| ≤ max(rel_tol · |r|, rel_tol · ref_scale, abs_tol) + +The middle term (`rel_tol · ref_scale`) provides an amplitude-proportional +absolute floor. Near zero crossings the tolerance is set by the peak magnitude +of the reference signal rather than the near-zero instantaneous value, so +physically correct simulations are not falsely rejected. +""" +function _check_mixed(s::Real, r::Real, ref_scale::Real, cfg::CompareSettings)::Bool + abs(s - r) <= max(cfg.rel_tol * abs(r), cfg.rel_tol * ref_scale, cfg.abs_tol) +end + +""" + _check_absolute(s, r, ref_scale, cfg) → Bool + +Pure absolute check. Passes when + + |s − r| ≤ abs_tol + +Useful when all compared signals have known, small magnitudes or when a +signal-independent tolerance threshold is required. +""" +function _check_absolute(s::Real, r::Real, ::Real, cfg::CompareSettings)::Bool + abs(s - r) <= cfg.abs_tol +end + +""" + _check_point(s, r, ref_scale, cfg) → Bool + +Dispatch to the error function selected by `cfg.error_fn`. + +| `error_fn` | Description | +|:--------------|:----------------------------------------------------| +| `:mixed` | Scale-aware relative error (default, recommended) | +| `:relative` | Classic relative error (may fail at zero crossings) | +| `:absolute` | Pure absolute error | +""" +function _check_point(s::Real, r::Real, ref_scale::Real, cfg::CompareSettings)::Bool + fn = cfg.error_fn + fn === :mixed && return _check_mixed(s, r, ref_scale, cfg) + fn === :relative && return _check_relative(s, r, ref_scale, cfg) + fn === :absolute && return _check_absolute(s, r, ref_scale, cfg) + throw(ArgumentError( + "Unknown error_fn $(repr(fn)); choose :mixed, :relative, or :absolute")) +end + +""" + configure_comparison!(; rel_tol, abs_tol, error_fn) → CompareSettings + +Update the module-level comparison settings in-place and return them. + +# Keyword arguments + +- `rel_tol` — maximum allowed relative error. Default: `$(CMP_REL_TOL)` (2 %). +- `abs_tol` — hard absolute-error floor applied when signals are near zero. + Default: `$(CMP_ABS_TOL)`. +- `error_fn` — selects the point-wise check function. One of: + - `:mixed` — scale-aware relative error (default, recommended); + - `:relative` — classic relative error (may reject valid zero-crossing signals); + - `:absolute` — pure absolute error. + +# Example + +```julia +configure_comparison!(rel_tol = 0.01, error_fn = :relative) +``` +""" +function configure_comparison!(; + rel_tol :: Union{Float64,Nothing} = nothing, + abs_tol :: Union{Float64,Nothing} = nothing, + error_fn :: Union{Symbol,Nothing} = nothing, +) + isnothing(rel_tol) || (_CMP_SETTINGS.rel_tol = rel_tol) + isnothing(abs_tol) || (_CMP_SETTINGS.abs_tol = abs_tol) + isnothing(error_fn) || (_CMP_SETTINGS.error_fn = error_fn) + return _CMP_SETTINGS +end + +""" + compare_settings() → CompareSettings + +Return the current module-level comparison settings. + +Pass the returned object (or a freshly constructed `CompareSettings(...)`) to +`compare_with_reference` via the `settings` keyword to override the defaults +for a single call without changing the global state. +""" +compare_settings() = _CMP_SETTINGS + +# ── Interactive diff HTML ────────────────────────────────────────────────────── + +""" + write_diff_html(diff_csv_path, model) + +Generate an interactive HTML page for a `_diff.csv` file using the bundled +Dygraphs library. One zoomable chart is created per failing signal, showing +the reference trace, the simulation trace, and the relative error on a second +y-axis. The HTML file is written next to the CSV with a `.html` extension. + +The page references `../../assets/dygraph.min.*` relative to its location +(`/files//`). `_install_assets` is called automatically +to copy the library files to `/assets/` if not already present. +""" +function write_diff_html(diff_csv_path::String, model::String) + lines = readlines(diff_csv_path) + isempty(lines) && return + + headers = [replace(strip(h), "\"" => "") for h in split(lines[1], ",")] + + # Extract unique signal names from headers like "C1.v_ref", "C1.v_sim", … + fail_sigs = String[] + for h in headers + if length(h) > 4 && h[end-3:end] == "_ref" + push!(fail_sigs, h[1:end-4]) + end + end + isempty(fail_sigs) && return + + short_name = split(model, ".")[end] + + # Escape CSV content for embedding as a JS template literal. + # The only characters that would break a template literal are \ and `. + csv_text = read(diff_csv_path, String) + csv_js = replace(replace(csv_text, "\\" => "\\\\"), "`" => "\\`") + + # Derive results_root from diff_csv_path: /files// + results_root = dirname(dirname(dirname(abspath(diff_csv_path)))) + _install_assets(results_root) + + # Fill template placeholders + template = read(joinpath(_ASSETS_DIR, "diff_template.html"), String) + html = replace( + template, + "{{TITLE}}" => short_name, + "{{MODEL}}" => model, + "{{N_FAIL}}" => string(length(fail_sigs)), + "{{REL_TOL_PCT}}" => string(round(Int, _CMP_SETTINGS.rel_tol * 100)), + "{{ABS_TOL}}" => string(_CMP_SETTINGS.abs_tol), + "{{CSV_NAME}}" => "$(short_name)_diff.csv", + "{{CSV_DATA}}" => csv_js, + ) + + html_path = replace(diff_csv_path, r"\.csv$" => ".html") + write(html_path, html) +end + +# ── Reference comparison ─────────────────────────────────────────────────────── + +""" + compare_with_reference(sol, ref_csv_path, model_dir, model; + settings) → (total, pass, diff_csv) + +Compare a DifferentialEquations solution against the MAP-LIB reference CSV. + +Returns: + total — number of signals successfully compared + pass — number of signals within tolerance + diff_csv — absolute path to the written diff CSV (empty string if all pass) + +Signals that cannot be matched to an MTK state variable are skipped. + +# Keyword arguments +- `settings` — a `CompareSettings` instance controlling tolerances and the + error function. Defaults to the module-level settings returned + by `compare_settings()`. Use `configure_comparison!` to change + the defaults, or pass a local `CompareSettings(...)` here. +""" +function compare_with_reference( + sol, + ref_csv_path::String, + model_dir::String, + model::String; + settings::CompareSettings = _CMP_SETTINGS, +)::Tuple{Int,Int,String} + + times, ref_data = _read_ref_csv(ref_csv_path) + isempty(times) && return 0, 0, "" + + # Determine which signals to compare: prefer comparisonSignals.txt + sig_file = joinpath(dirname(ref_csv_path), "comparisonSignals.txt") + signals = if isfile(sig_file) + filter(s -> s != "time" && !isempty(s), strip.(readlines(sig_file))) + else + filter(k -> k != "time", collect(keys(ref_data))) + end + + # Build normalized-name → state-variable-index map from the MTK system + sys = sol.prob.f.sys + vars = ModelingToolkit.unknowns(sys) + var_norm = Dict(_normalize_var(string(v)) => i for (i, v) in enumerate(vars)) + + # Clip reference time points to the simulation interval + t_start = sol.t[1] + t_end = sol.t[end] + valid_mask = (times .>= t_start) .& (times .<= t_end) + t_ref = times[valid_mask] + isempty(t_ref) && return 0, 0, "" + + n_total = 0 + n_pass = 0 + fail_sigs = String[] + fail_scales = Dict{String,Float64}() # peak |ref| per failing signal + + for sig in signals + haskey(ref_data, sig) || continue + haskey(var_norm, _normalize_var(sig)) || continue # skip non-state signals + + ref_vals = ref_data[sig][valid_mask] + idx = var_norm[_normalize_var(sig)] + n_total += 1 + + # Peak magnitude of the reference signal — used as the absolute-error scale + # near zero crossings so that relative error does not blow up. + ref_scale = isempty(ref_vals) ? 0.0 : maximum(abs, ref_vals) + + # Interpolate simulation at reference time points + sim_vals = [sol(t)[idx] for t in t_ref] + + pass = all(zip(sim_vals, ref_vals)) do (s, r) + _check_point(s, r, ref_scale, settings) + end + + if pass + n_pass += 1 + else + push!(fail_sigs, sig) + fail_scales[sig] = ref_scale + end + end + + # Write diff CSV for failing signals (wide format: ref + sim + relerr per signal) + diff_csv = "" + if !isempty(fail_sigs) + short_name = split(model, ".")[end] + diff_csv = joinpath(model_dir, "$(short_name)_diff.csv") + + open(diff_csv, "w") do f + cols = ["time"] + for sig in fail_sigs + push!(cols, "$(sig)_ref", "$(sig)_sim", "$(sig)_relerr") + end + println(f, join(cols, ",")) + + for (ti, t) in enumerate(t_ref) + row = [@sprintf("%.10g", t)] + for sig in fail_sigs + ref_vals = ref_data[sig][valid_mask] + r = ref_vals[ti] + idx = var_norm[_normalize_var(sig)] + s = sol(t)[idx] + ref_scale = get(fail_scales, sig, 0.0) + relerr = abs(s - r) / max(abs(r), ref_scale, settings.abs_tol) + push!(row, @sprintf("%.10g", r), + @sprintf("%.10g", s), + @sprintf("%.6g", relerr)) + end + println(f, join(row, ",")) + end + end + + write_diff_html(diff_csv, model) + end + + return n_total, n_pass, diff_csv +end diff --git a/src/export.jl b/src/export.jl new file mode 100644 index 000000000..894825c73 --- /dev/null +++ b/src/export.jl @@ -0,0 +1,47 @@ +# ── Phase 1: Base Modelica export via OMC ───────────────────────────────────── + +""" + run_export(omc, model, model_dir, bm_path) → (success, time, error) + +Export the Base Modelica representation of `model` via the given OMC session. +Writes a `_export.log` file in `model_dir`. +The `.bmo` file is written to `bm_path` (which must use forward slashes). +""" +function run_export(omc::OMJulia.OMCSession, model::String, model_dir::String, + bm_path::String)::Tuple{Bool,Float64,String} + bm_path_esc = replace(bm_path, "\"" => "\\\"") + + export_success = false + export_time = 0.0 + export_error = "" + + t0 = time() + try + result = sendExpression(omc, + """writeFile("$bm_path_esc", OpenModelica.Scripting.instantiateModel($model))""") + export_time = time() - t0 + + if result == false + export_error = sendExpression(omc, "getErrorString()") + elseif !isfile(bm_path) || filesize(bm_path) == 0 + errmsg = sendExpression(omc, "getErrorString()") + export_error = isempty(errmsg) ? + "Base Modelica file missing or empty at: $bm_path" : errmsg + else + sendExpression(omc, "getErrorString()") # drain any non-fatal warnings + export_success = true + end + catch e + export_time = time() - t0 + export_error = sprint(showerror, e, catch_backtrace()) + end + + open(joinpath(model_dir, "$(model)_export.log"), "w") do f + println(f, "Model: $model") + println(f, "Time: $(round(export_time; digits=3)) s") + println(f, "Success: $export_success") + isempty(export_error) || println(f, "\n--- Error ---\n$export_error") + end + + return export_success, export_time, export_error +end diff --git a/src/parse_bm.jl b/src/parse_bm.jl new file mode 100644 index 000000000..9db205313 --- /dev/null +++ b/src/parse_bm.jl @@ -0,0 +1,40 @@ +# ── Phase 2: Base Modelica parsing with BaseModelica.jl ─────────────────────── + +import BaseModelica + +""" + run_parse(bm_path, model_dir, model) → (success, time, error, ode_prob) + +Parse a Base Modelica `.bmo` file with BaseModelica.jl and create an +`ODEProblem` from the `Experiment` annotation. +Writes a `_parsing.log` file in `model_dir`. +Returns `nothing` as the fourth element on failure. +""" +function run_parse(bm_path::String, model_dir::String, + model::String)::Tuple{Bool,Float64,String,Any} + parse_success = false + parse_time = 0.0 + parse_error = "" + ode_prob = nothing + + t0 = time() + try + # create_odeproblem returns an ODEProblem using the Experiment + # annotation for StartTime/StopTime/Tolerance/Interval. + ode_prob = BaseModelica.create_odeproblem(bm_path) + parse_time = time() - t0 + parse_success = true + catch e + parse_time = time() - t0 + parse_error = sprint(showerror, e, catch_backtrace()) + end + + open(joinpath(model_dir, "$(model)_parsing.log"), "w") do f + println(f, "Model: $model") + println(f, "Time: $(round(parse_time; digits=3)) s") + println(f, "Success: $parse_success") + isempty(parse_error) || println(f, "\n--- Error ---\n$parse_error") + end + + return parse_success, parse_time, parse_error, ode_prob +end diff --git a/src/pipeline.jl b/src/pipeline.jl new file mode 100644 index 000000000..3e6bb2adf --- /dev/null +++ b/src/pipeline.jl @@ -0,0 +1,141 @@ +# ── Per-model orchestrator ───────────────────────────────────────────────────── + +""" + test_model(omc, model, results_root, ref_root) → ModelResult + +Run the four-phase pipeline for a single model and return its result. +""" +function test_model(omc::OMJulia.OMCSession, model::String, results_root::String, + ref_root::String)::ModelResult + model_dir = joinpath(results_root, "files", model) + mkpath(model_dir) + + # Use forward slashes so the path is valid as an OMC string literal on all + # platforms (OMC accepts forward slashes on Windows too). + bm_path = replace(abspath(joinpath(model_dir, "$(model).bmo")), "\\" => "/") + + # Phase 1 ────────────────────────────────────────────────────────────────── + exp_ok, exp_t, exp_err = run_export(omc, model, model_dir, bm_path) + exp_ok || return ModelResult( + model, false, exp_t, exp_err, false, 0.0, "", false, 0.0, "", 0, 0, "") + + # Phase 2 ────────────────────────────────────────────────────────────────── + par_ok, par_t, par_err, ode_prob = run_parse(bm_path, model_dir, model) + par_ok || return ModelResult( + model, true, exp_t, exp_err, false, par_t, par_err, false, 0.0, "", 0, 0, "") + + # Phase 3 ────────────────────────────────────────────────────────────────── + sim_ok, sim_t, sim_err, sol = run_simulate(ode_prob, model_dir, model) + + # Phase 4 (optional) ─────────────────────────────────────────────────────── + cmp_total, cmp_pass, cmp_csv = 0, 0, "" + if sim_ok && !isempty(ref_root) + ref_csv = _ref_csv_path(ref_root, model) + if ref_csv !== nothing + try + cmp_total, cmp_pass, cmp_csv = + compare_with_reference(sol, ref_csv, model_dir, model) + catch e + @warn "Reference comparison failed for $model: $(sprint(showerror, e))" + end + end + end + + return ModelResult( + model, + true, exp_t, exp_err, + true, par_t, par_err, + sim_ok, sim_t, sim_err, + cmp_total, cmp_pass, cmp_csv) +end + +# ── Main ─────────────────────────────────────────────────────────────────────── + +""" + main(; library, version, filter, omc_exe, results_root, ref_root) → results + +Run the full pipeline over all experiment models in `library` `version`. +Discovers models via OMC, runs `test_model` for each, then writes the HTML +report. Returns a `Vector{ModelResult}`. +""" +function main(; + library :: String = LIBRARY, + version :: String = LIBRARY_VERSION, + filter :: Union{String,Nothing} = nothing, + omc_exe :: String = get(ENV, "OMC_EXE", "omc"), + results_root :: String = "", + ref_root :: String = get(ENV, "MAPLIB_REF", ""), +) + if isempty(results_root) + results_root = joinpath(library, version) + end + results_root = abspath(results_root) + mkpath(joinpath(results_root, "files")) + @info "Writing results to: $results_root" + + @info "Starting OMC session ($(omc_exe))..." + omc = OMJulia.OMCSession(omc_exe) + + results = ModelResult[] + try + omc_version = sendExpression(omc, "getVersion()") + @info "OMC version: $omc_version" + + ok = sendExpression(omc, """setCommandLineOptions("--baseModelica --frontendInline --baseModelicaOptions=scalarize -d=evaluateAllParameters")""") + ok || @warn "Failed to set Base Modelica options: $(sendExpression(omc, "getErrorString()"))" + + ok = sendExpression(omc, """loadModel($library, {"$version"})""") + ok || error("Failed to load $library $version: $(sendExpression(omc, "getErrorString()"))") + @info "Loaded $library $version" + + @info "Discovering experiment models..." + # OMC's ZMQ interactive mode does not support the {expr for var guard cond + # in list} comprehension syntax. Instead we fetch all qualified class names + # and a parallel boolean array of isExperiment flags, then zip-filter in Julia. + all_names = sendExpression(omc, + "{typeNameString(c) for c in getClassNames($library, recursive=true, qualified=true)}") + is_exp = sendExpression(omc, + "{isExperiment(c) for c in getClassNames($library, recursive=true, qualified=true)}") + all_names = all_names isa Vector ? all_names : [all_names] + is_exp = is_exp isa Vector ? is_exp : [is_exp] + models = String[string(n) for (n, e) in zip(all_names, is_exp) if e === true] + + if filter !== nothing + pat = Regex(filter) + models = [m for m in models if occursin(pat, m)] + @info "Filter '$(filter)': $(length(models)) model(s) remaining" + end + @info "Testing $(length(models)) model(s)" + + if !isempty(ref_root) + ref_root = abspath(ref_root) + if !isdir(ref_root) + @warn "Reference results root '$ref_root' does not exist or is not a directory. Skipping reference comparison." + ref_root = "" + else + @info "Reference results root: $ref_root" + end + end + + for (i, model) in enumerate(models) + @info "[$i/$(length(models))] $model" + result = test_model(omc, model, results_root, ref_root) + push!(results, result) + + phase = result.sim_success ? "SIM OK" : + result.parse_success ? "SIM FAIL" : + result.export_success ? "PARSE FAIL" : "EXPORT FAIL" + cmp_info = result.cmp_total > 0 ? + " cmp=$(result.cmp_pass)/$(result.cmp_total)" : "" + @info " → $phase export=$(round(result.export_time;digits=2))s" * + " parse=$(round(result.parse_time;digits=2))s" * + " sim=$(round(result.sim_time;digits=2))s$cmp_info" + end + + finally + OMJulia.quit(omc) + end + + generate_report(results, results_root, library, version) + return results +end diff --git a/src/report.jl b/src/report.jl new file mode 100644 index 000000000..f85f7ae4a --- /dev/null +++ b/src/report.jl @@ -0,0 +1,118 @@ +# ── HTML report generation ───────────────────────────────────────────────────── + +import Dates: now +import Printf: @sprintf +import BaseModelica + +function _status_cell(ok::Bool, t::Float64, logFile::Union{String,Nothing}) + link = isnothing(logFile) ? "" : """ (log)""" + if ok + return """✓ $(@sprintf "%.2f" t) s$link""" + else + return """✗$link""" + end +end + +function _cmp_cell(r::ModelResult, results_root::String) + if r.cmp_total == 0 + return """—""" + end + n, p = r.cmp_total, r.cmp_pass + if p == n + return """✓ $p/$n""" + else + # Link to the interactive diff HTML (next to the CSV, same name, .html extension) + diff_html = replace(r.cmp_csv, r"\.csv$" => ".html") + rel = relpath(isfile(diff_html) ? diff_html : r.cmp_csv, results_root) + return """$p/$n""" + end +end + +function rel_log_file_or_nothing(results_root::String, model::String, + phase::String)::Union{String,Nothing} + path = joinpath(results_root, "files", model, "$(model)_$(phase).log") + isfile(path) ? joinpath("files", model, "$(model)_$(phase).log") : nothing +end + +""" + generate_report(results, results_root, library, version) → report_path + +Write an `index.html` overview report to `results_root` and return its path. +""" +function generate_report(results::Vector{ModelResult}, results_root::String, + library::String, version::String) + n = length(results) + n_exp = count(r -> r.export_success, results) + n_par = count(r -> r.parse_success, results) + n_sim = count(r -> r.sim_success, results) + + # Comparison summary (only models where cmp_total > 0) + cmp_results = filter(r -> r.cmp_total > 0, results) + n_cmp_models = length(cmp_results) + n_cmp_pass = count(r -> r.cmp_pass == r.cmp_total, cmp_results) + + pct(num, den) = den > 0 ? @sprintf("%.1f%%", 100 * num / den) : "n/a" + + cmp_summary_row = n_cmp_models > 0 ? """ + Reference Comparison (MAP-LIB)$n_cmp_pass$n_cmp_models$(pct(n_cmp_pass,n_cmp_models))""" : "" + + rows = join([""" + $(r.name).bmo + $(_status_cell(r.export_success, r.export_time, rel_log_file_or_nothing(results_root, r.name, "export"))) + $(_status_cell(r.parse_success, r.parse_time, rel_log_file_or_nothing(results_root, r.name, "parsing"))) + $(_status_cell(r.sim_success, r.sim_time, rel_log_file_or_nothing(results_root, r.name, "sim"))) + $(_cmp_cell(r, results_root)) + """ for r in results], "\n") + + omc_ver = try sendExpression(OMJulia.OMCSession("omc"), "getVersion()") catch; "unknown" end + bm_ver = string(pkgversion(BaseModelica)) + + html = """ + + + + $library $version — Base Modelica / MTK Results + + + +

$library $version — Base Modelica / MTK Pipeline Test Results

+

Generated: $(now())
+OpenModelica: $omc_ver
+BaseModelica.jl: $bm_ver

+ + + + + + $cmp_summary_row +
StagePassedTotalRate
Base Modelica Export (OpenModelica)$n_exp$n $(pct(n_exp,n))
Parsing (BaseModelica.jl) $n_par$n_exp$(pct(n_par,n_exp))
Simulation (MTK.jl) $n_sim$n_par$(pct(n_sim,n_par))
+ + + + + + + + + +$rows +
ModelBM ExportBM ParseMTK SimRef Cmp
+ +""" + + report_path = joinpath(results_root, "index.html") + write(report_path, html) + @info "Report written to $report_path" + return report_path +end diff --git a/src/simulate.jl b/src/simulate.jl new file mode 100644 index 000000000..3bdb9867d --- /dev/null +++ b/src/simulate.jl @@ -0,0 +1,68 @@ +# ── Phase 3: ODE simulation with DifferentialEquations / MTK ────────────────── + +import DifferentialEquations: solve, Rodas5P, ReturnCode +import ModelingToolkit +import Printf: @sprintf + +""" + run_simulate(ode_prob, model_dir, model) → (success, time, error, sol) + +Solve `ode_prob` with Rodas5P (stiff solver). On success, also writes the +full solution as a CSV file `_sim.csv` in `model_dir`. +Writes a `_sim.log` file in `model_dir`. +Returns `nothing` as the fourth element on failure. +""" +function run_simulate(ode_prob, model_dir::String, + model::String)::Tuple{Bool,Float64,String,Any} + sim_success = false + sim_time = 0.0 + sim_error = "" + sol = nothing + + t0 = time() + try + # Rodas5P handles stiff DAE-like systems well. + sol = solve(ode_prob, Rodas5P()) + sim_time = time() - t0 + if sol.retcode == ReturnCode.Success + sim_success = true + else + sim_error = "Solver returned: $(sol.retcode)" + end + catch e + sim_time = time() - t0 + sim_error = sprint(showerror, e, catch_backtrace()) + end + + open(joinpath(model_dir, "$(model)_sim.log"), "w") do f + println(f, "Model: $model") + println(f, "Time: $(round(sim_time; digits=3)) s") + println(f, "Success: $sim_success") + isempty(sim_error) || println(f, "\n--- Error ---\n$sim_error") + end + + # Write simulation results CSV (time + all state variables) + if sim_success && sol !== nothing + short_name = split(model, ".")[end] + sim_csv = joinpath(model_dir, "$(short_name)_sim.csv") + try + sys = sol.prob.f.sys + vars = ModelingToolkit.unknowns(sys) + col_names = [_clean_var_name(string(v)) for v in vars] + open(sim_csv, "w") do f + println(f, join(["time"; col_names], ",")) + for (ti, t) in enumerate(sol.t) + row = [@sprintf("%.10g", t)] + for vi in eachindex(vars) + push!(row, @sprintf("%.10g", sol[vi, ti])) + end + println(f, join(row, ",")) + end + end + catch e + @warn "Failed to write simulation CSV for $model: $(sprint(showerror, e))" + end + end + + return sim_success, sim_time, sim_error, sol +end diff --git a/src/types.jl b/src/types.jl new file mode 100644 index 000000000..9830ac08f --- /dev/null +++ b/src/types.jl @@ -0,0 +1,52 @@ +# ── Shared constants ─────────────────────────────────────────────────────────── + +const LIBRARY = "Modelica" +const LIBRARY_VERSION = "4.1.0" + +# Comparison tolerances (2 % relative, 1e-6 absolute — matches Modelica +# Association compliance tooling defaults). +const CMP_REL_TOL = 0.02 +const CMP_ABS_TOL = 1e-6 + +# ── Comparison settings ──────────────────────────────────────────────────────── + +""" + CompareSettings + +Mutable configuration struct for signal comparison. + +# Fields +- `rel_tol` — maximum allowed relative error (default: `$(CMP_REL_TOL)`, i.e. 2 %). +- `abs_tol` — hard absolute-error floor used when signals are near zero + (default: `$(CMP_ABS_TOL)`). +- `error_fn` — selects the point-wise pass/fail function. One of: + - `:mixed` — scale-aware relative error (default, recommended); + - `:relative` — classic relative error (may reject valid zero-crossing signals); + - `:absolute` — pure absolute error. + +Use `configure_comparison!` to update the module-level defaults, or construct a +local instance to pass to `compare_with_reference` for a single run. +""" +Base.@kwdef mutable struct CompareSettings + rel_tol :: Float64 = CMP_REL_TOL + abs_tol :: Float64 = CMP_ABS_TOL + error_fn :: Symbol = :mixed +end + +# ── Result type ──────────────────────────────────────────────────────────────── + +struct ModelResult + name :: String + export_success :: Bool + export_time :: Float64 + export_error :: String + parse_success :: Bool + parse_time :: Float64 + parse_error :: String + sim_success :: Bool + sim_time :: Float64 + sim_error :: String + cmp_total :: Int # 0 = no reference data available + cmp_pass :: Int + cmp_csv :: String # absolute path to diff CSV; "" if all pass or no comparison +end diff --git a/test/runtests.jl b/test/runtests.jl index 0f7eee51d..0c6096ce2 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,140 @@ -using BaseModelicaLibraryTesting -using Test +""" +Tests for the BaseModelicaLibraryTesting package. -@testset "BaseModelicaLibraryTesting.jl" begin - # Write your tests here. +Sections: + 1. Unit tests — pure helper functions, no OMC or simulation needed. + 2. Integration — full pipeline for Modelica.Electrical.Analog.Examples.ChuaCircuit. + +Run from the julia/ directory: + julia --project=. test/runtests.jl + +Or via Pkg: + julia --project=. -e 'import Pkg; Pkg.test()' + +Environment variables: + OMC_EXE Path to the omc binary (default: system PATH) +""" + +import Test: @test, @testset +import OMJulia +import BaseModelicaLibraryTesting: run_export, run_parse, run_simulate, + _clean_var_name, _normalize_var, + _ref_csv_path, _read_ref_csv + +# ── 1. Unit tests ────────────────────────────────────────────────────────────── + +@testset "Unit tests" begin + + @testset "_clean_var_name" begin + # Standard MTK form: var"name"(t) + @test _clean_var_name("var\"C1.v\"(t)") == "C1.v" + # Without (t) + @test _clean_var_name("var\"C1.v\"") == "C1.v" + # Plain name with (t) suffix + @test _clean_var_name("C1.v(t)") == "C1.v" + # Plain name, no annotation + @test _clean_var_name("x") == "x" + # Leading/trailing whitespace is stripped + @test _clean_var_name(" foo(t) ") == "foo" + # ₊ hierarchy separator is preserved (it is the job of _normalize_var) + @test _clean_var_name("var\"C1₊v\"(t)") == "C1₊v" + end + + @testset "_normalize_var" begin + # Reference-CSV side: plain dot-separated name + @test _normalize_var("C1.v") == "c1.v" + @test _normalize_var("L.i") == "l.i" + # MTK side with ₊ hierarchy separator and (t) annotation + @test _normalize_var("C1₊v(t)") == "c1.v" + # MTK side with var"..." quoting + @test _normalize_var("var\"C1₊v\"(t)") == "c1.v" + # Already normalized input + @test _normalize_var("c1.v") == "c1.v" + # Multi-level hierarchy + @test _normalize_var("a₊b₊c(t)") == "a.b.c" + end + + @testset "_ref_csv_path" begin + mktempdir() do dir + model = "Modelica.Electrical.Analog.Examples.ChuaCircuit" + csv_dir = joinpath(dir, "Modelica", "Electrical", "Analog", + "Examples", "ChuaCircuit") + mkpath(csv_dir) + csv_file = joinpath(csv_dir, "ChuaCircuit.csv") + write(csv_file, "") + @test _ref_csv_path(dir, model) == csv_file + @test _ref_csv_path(dir, "Modelica.NotExisting") === nothing + end + end + + @testset "_read_ref_csv" begin + mktempdir() do dir + csv = joinpath(dir, "test.csv") + + # Quoted headers (MAP-LIB format) + write(csv, "\"time\",\"C1.v\",\"L.i\"\n0,4,0\n0.5,3.5,0.1\n1,3.0,0.2\n") + times, data = _read_ref_csv(csv) + @test times ≈ [0.0, 0.5, 1.0] + @test data["C1.v"] ≈ [4.0, 3.5, 3.0] + @test data["L.i"] ≈ [0.0, 0.1, 0.2] + @test !haskey(data, "\"time\"") # quotes must be stripped from keys + + # Unquoted headers + write(csv, "time,x,y\n0,1,2\n1,3,4\n") + times2, data2 = _read_ref_csv(csv) + @test times2 ≈ [0.0, 1.0] + @test data2["x"] ≈ [1.0, 3.0] + @test data2["y"] ≈ [2.0, 4.0] + + # Empty file → empty collections + write(csv, "") + t0, d0 = _read_ref_csv(csv) + @test isempty(t0) + @test isempty(d0) + + # Blank lines between data rows are ignored + write(csv, "time,v\n0,1\n\n1,2\n\n") + times3, data3 = _read_ref_csv(csv) + @test times3 ≈ [0.0, 1.0] + @test data3["v"] ≈ [1.0, 2.0] + end + end + +end # "Unit tests" + +# ── 2. Integration test ──────────────────────────────────────────────────────── + +const TEST_MODEL = "Modelica.Electrical.Analog.Examples.ChuaCircuit" +const TEST_OMC = get(ENV, "OMC_EXE", "omc") + +@testset "ChuaCircuit pipeline" begin + tmpdir = mktempdir() + model_dir = joinpath(tmpdir, "files", TEST_MODEL) + mkpath(model_dir) + bm_path = replace(abspath(joinpath(model_dir, "$TEST_MODEL.bmo")), "\\" => "/") + + omc = OMJulia.OMCSession(TEST_OMC) + try + OMJulia.sendExpression(omc, """setCommandLineOptions("--baseModelica --frontendInline --baseModelicaOptions=scalarize -d=evaluateAllParameters")""") + ok = OMJulia.sendExpression(omc, """loadModel(Modelica, {"4.1.0"})""") + @test ok == true + + exp_ok, _, exp_err = run_export(omc, TEST_MODEL, model_dir, bm_path) + @test exp_ok + exp_ok || @warn "Export error: $exp_err" + + if exp_ok + par_ok, _, par_err, ode_prob = run_parse(bm_path, model_dir, TEST_MODEL) + @test par_ok + par_ok || @warn "Parse error: $par_err" + + if par_ok + sim_ok, _, sim_err, _ = run_simulate(ode_prob, model_dir, TEST_MODEL) + @test sim_ok + sim_ok || @warn "Simulation error: $sim_err" + end + end + finally + OMJulia.quit(omc) + end end