From d086fa0e9aa8cc3afa7f2b4d9bf2c14ea2427249 Mon Sep 17 00:00:00 2001 From: Molly Smith Date: Thu, 8 Jun 2023 13:57:31 -0600 Subject: [PATCH 01/50] Cloned precipGauge to create ensemble app --- apps/ensemble/.eslintrc.json | 49 + apps/ensemble/.meteor/.finished-upgraders | 19 + apps/ensemble/.meteor/.gitignore | 1 + apps/ensemble/.meteor/.id | 7 + apps/ensemble/.meteor/packages | 31 + apps/ensemble/.meteor/platforms | 2 + apps/ensemble/.meteor/release | 1 + apps/ensemble/.meteor/versions | 109 + apps/ensemble/.prettierrc | 3 + apps/ensemble/app.css | 159 + apps/ensemble/client/main.js | 8 + apps/ensemble/package-lock.json | 6699 +++++++++++++++++ apps/ensemble/package.json | 42 + apps/ensemble/public/favicon.ico | Bin 0 -> 5430 bytes apps/ensemble/public/title | 1 + .../server/dataFunctions/data_contour.js | 231 + .../server/dataFunctions/data_contour_diff.js | 259 + .../dataFunctions/data_dailymodelcycle.js | 254 + .../server/dataFunctions/data_dieoff.js | 274 + .../server/dataFunctions/data_histogram.js | 207 + .../server/dataFunctions/data_perfDiagram.js | 266 + .../server/dataFunctions/data_series.js | 271 + .../server/dataFunctions/data_threshold.js | 244 + .../server/dataFunctions/data_validtime.js | 245 + apps/ensemble/server/main.js | 1451 ++++ 25 files changed, 10833 insertions(+) create mode 100644 apps/ensemble/.eslintrc.json create mode 100644 apps/ensemble/.meteor/.finished-upgraders create mode 100644 apps/ensemble/.meteor/.gitignore create mode 100644 apps/ensemble/.meteor/.id create mode 100644 apps/ensemble/.meteor/packages create mode 100644 apps/ensemble/.meteor/platforms create mode 100644 apps/ensemble/.meteor/release create mode 100644 apps/ensemble/.meteor/versions create mode 100644 apps/ensemble/.prettierrc create mode 100644 apps/ensemble/app.css create mode 100644 apps/ensemble/client/main.js create mode 100644 apps/ensemble/package-lock.json create mode 100644 apps/ensemble/package.json create mode 100755 apps/ensemble/public/favicon.ico create mode 100644 apps/ensemble/public/title create mode 100644 apps/ensemble/server/dataFunctions/data_contour.js create mode 100644 apps/ensemble/server/dataFunctions/data_contour_diff.js create mode 100644 apps/ensemble/server/dataFunctions/data_dailymodelcycle.js create mode 100644 apps/ensemble/server/dataFunctions/data_dieoff.js create mode 100644 apps/ensemble/server/dataFunctions/data_histogram.js create mode 100644 apps/ensemble/server/dataFunctions/data_perfDiagram.js create mode 100644 apps/ensemble/server/dataFunctions/data_series.js create mode 100644 apps/ensemble/server/dataFunctions/data_threshold.js create mode 100644 apps/ensemble/server/dataFunctions/data_validtime.js create mode 100644 apps/ensemble/server/main.js diff --git a/apps/ensemble/.eslintrc.json b/apps/ensemble/.eslintrc.json new file mode 100644 index 0000000000..8b795b7df7 --- /dev/null +++ b/apps/ensemble/.eslintrc.json @@ -0,0 +1,49 @@ +{ + "env": { + "node": true, + "browser": true + }, + "parser": "@babel/eslint-parser", + "parserOptions": { + "sourceType": "module", + "requireConfigFile": false, + "allowImportExportEverywhere": true + }, + "extends": ["airbnb", "prettier", "plugin:meteor/recommended"], + "plugins": ["prettier", "meteor"], + "settings": { + "import/resolver": "meteor" + }, + "rules": { + "prettier/prettier": "error", + "react/jsx-filename-extension": "off", + "import/no-absolute-path": "off", + "import/extensions": "off", + // disabled so that we're not expecting to find 'meteor' within + // our dependencies. + // XXX: this *should* be taken care of by eslint-import-resolver-meteor, investigate. + // "import/no-extraneous-dependencies": "off", + "no-underscore-dangle": ["error", { "allow": ["_id", "_ensureIndex"] }], + "object-shorthand": ["error", "always", { "avoidQuotes": false }], + "space-before-function-paren": "off", + // for Meteor API's that rely on `this` context, e.g. Template.onCreated and publications + "func-names": "off", + "prefer-arrow-callback": "off", + + // Vx Team modifications - Warn on rules that would require refactoring to implement. + // We want to be able to turn these back into "error"'s at some point. However, for + // our first pass, we'll only consider the checks that ESLint can auto-fix as errors. + // https://eslint.org/docs/latest/use/configure/rules#rule-severities + "no-undef": "warn", + "no-plusplus": "warn", + "vars-on-top": "warn", + "no-var": "warn", + "block-scoped-var": "warn", + "no-loop-func": "warn", + "no-unused-vars": "warn", + "prefer-destructuring": "warn", + "no-param-reassign": "warn", + "camelcase": "warn", + "no-redeclare": "warn" + } +} diff --git a/apps/ensemble/.meteor/.finished-upgraders b/apps/ensemble/.meteor/.finished-upgraders new file mode 100644 index 0000000000..c07b6ff75a --- /dev/null +++ b/apps/ensemble/.meteor/.finished-upgraders @@ -0,0 +1,19 @@ +# This file contains information which helps Meteor properly upgrade your +# app when you run 'meteor update'. You should check it into version control +# with your project. + +notices-for-0.9.0 +notices-for-0.9.1 +0.9.4-platform-file +notices-for-facebook-graph-api-2 +1.2.0-standard-minifiers-package +1.2.0-meteor-platform-split +1.2.0-cordova-changes +1.2.0-breaking-changes +1.3.0-split-minifiers-package +1.4.0-remove-old-dev-bundle-link +1.4.1-add-shell-server-package +1.4.3-split-account-service-packages +1.5-add-dynamic-import-package +1.7-split-underscore-from-meteor-base +1.8.3-split-jquery-from-blaze diff --git a/apps/ensemble/.meteor/.gitignore b/apps/ensemble/.meteor/.gitignore new file mode 100644 index 0000000000..4083037423 --- /dev/null +++ b/apps/ensemble/.meteor/.gitignore @@ -0,0 +1 @@ +local diff --git a/apps/ensemble/.meteor/.id b/apps/ensemble/.meteor/.id new file mode 100644 index 0000000000..d134f932ce --- /dev/null +++ b/apps/ensemble/.meteor/.id @@ -0,0 +1,7 @@ +# This file contains a token that is unique to your project. +# Check it into your repository along with the rest of this directory. +# It can be used for purposes such as: +# - ensuring you don't accidentally deploy one app on top of another +# - providing package authors with aggregated statistics + +17m0cbn1e1jjc21wsi83n diff --git a/apps/ensemble/.meteor/packages b/apps/ensemble/.meteor/packages new file mode 100644 index 0000000000..c1f540349b --- /dev/null +++ b/apps/ensemble/.meteor/packages @@ -0,0 +1,31 @@ +# Meteor packages used by this project, one per line. +# Check this file (and the other files in this directory) into your repository. +# +# 'meteor add' and 'meteor remove' will edit this file for you, +# but you can also edit it by hand. + +meteor-base@1.5.1 # Packages every Meteor app needs to have +mobile-experience@1.1.0 # Packages for a great mobile UX +mongo@1.16.5 # The database Meteor supports right now +blaze-html-templates # Compile .html files into Meteor Blaze views +reactive-var@1.0.12 # Reactive variable for tracker +jquery@1.11.10 # Helpful client-side library +tracker@1.3.1 # Meteor's client-side reactive programming library +standard-minifier-js@2.8.1 # JS minifier run for production mode +es5-shim@4.8.0 # ECMAScript 5 compatibility for older browsers. +ecmascript@0.16.6 # Enable ECMAScript2015+ syntax in app code +shell-server@0.5.0 # Server-side component of the `meteor shell` command +pcel:mysql +seba:minifiers-autoprefixer +session@1.2.1 +momentjs:moment +randyp:mats-common@5.1.0 +accounts-google@1.4.0 +accounts-base@2.2.7 +accounts-ui@1.4.2 +google-config-ui@1.0.3 +dynamic-import@0.7.2 +underscore@1.0.12 +kadira:blaze-layout +ostrio:flow-router-extra +meteorhacks:picker diff --git a/apps/ensemble/.meteor/platforms b/apps/ensemble/.meteor/platforms new file mode 100644 index 0000000000..efeba1b50c --- /dev/null +++ b/apps/ensemble/.meteor/platforms @@ -0,0 +1,2 @@ +server +browser diff --git a/apps/ensemble/.meteor/release b/apps/ensemble/.meteor/release new file mode 100644 index 0000000000..31dd9a2ea8 --- /dev/null +++ b/apps/ensemble/.meteor/release @@ -0,0 +1 @@ +METEOR@2.11.0 diff --git a/apps/ensemble/.meteor/versions b/apps/ensemble/.meteor/versions new file mode 100644 index 0000000000..9b76c4ab05 --- /dev/null +++ b/apps/ensemble/.meteor/versions @@ -0,0 +1,109 @@ +accounts-base@2.2.7 +accounts-google@1.4.0 +accounts-oauth@1.4.2 +accounts-password@2.3.4 +accounts-ui@1.4.2 +accounts-ui-unstyled@1.7.0 +allow-deny@1.1.1 +autoupdate@1.8.0 +babel-compiler@7.10.3 +babel-runtime@1.5.1 +base64@1.0.12 +binary-heap@1.0.11 +blaze@2.6.1 +blaze-html-templates@2.0.0 +blaze-tools@1.1.3 +boilerplate-generator@1.7.1 +caching-compiler@1.2.2 +caching-html-compiler@1.2.1 +callback-hook@1.5.0 +check@1.3.2 +ddp@1.4.1 +ddp-client@2.6.1 +ddp-common@1.4.0 +ddp-rate-limiter@1.1.1 +ddp-server@2.6.0 +diff-sequence@1.1.2 +differential:event-hooks@1.5.0 +dynamic-import@0.7.2 +ecmascript@0.16.6 +ecmascript-runtime@0.8.0 +ecmascript-runtime-client@0.12.1 +ecmascript-runtime-server@0.11.0 +ejson@1.1.3 +email@2.2.4 +es5-shim@4.8.0 +fetch@0.1.3 +geojson-utils@1.0.11 +google-config-ui@1.0.3 +google-oauth@1.4.3 +hot-code-push@1.0.4 +html-tools@1.1.3 +htmljs@1.1.1 +id-map@1.1.1 +inter-process-messaging@0.1.1 +jquery@1.11.11 +kadira:blaze-layout@2.3.0 +launch-screen@1.3.0 +less@4.0.0 +localstorage@1.2.0 +logging@1.3.2 +mdg:validated-method@1.3.0 +meteor@1.11.1 +meteor-base@1.5.1 +meteorhacks:picker@1.0.3 +meteortoys:toykit@10.0.0 +minifier-css@1.6.2 +minifier-js@2.7.5 +minimongo@1.9.2 +mobile-experience@1.1.0 +mobile-status-bar@1.1.0 +modern-browsers@0.1.9 +modules@0.19.0 +modules-runtime@0.13.1 +momentjs:moment@2.29.3 +mongo@1.16.5 +mongo-decimal@0.1.3 +mongo-dev-server@1.1.0 +mongo-id@1.0.8 +msavin:mongol@10.0.1 +natestrauser:select2@4.0.3 +npm-mongo@4.14.0 +oauth@2.2.0 +oauth2@1.3.2 +observe-sequence@1.0.20 +ordered-dict@1.1.0 +ostrio:flow-router-extra@3.9.0 +pcel:mysql@0.1.0 +promise@0.12.2 +random@1.2.1 +randyp:mats-common@5.1.0 +rate-limit@1.0.9 +react-fast-refresh@0.2.6 +reactive-dict@1.3.1 +reactive-var@1.0.12 +reload@1.3.1 +retry@1.1.0 +risul:bootstrap-colorpicker@2.3.6 +routepolicy@1.1.1 +seba:minifiers-autoprefixer@2.0.1 +service-configuration@1.3.1 +session@1.2.1 +sha@1.0.9 +shell-server@0.5.0 +socket-stream-client@0.5.0 +spacebars@1.3.0 +spacebars-compiler@1.3.1 +standard-minifier-js@2.8.1 +templating@1.4.2 +templating-compiler@1.4.1 +templating-runtime@1.6.1 +templating-tools@1.2.2 +tracker@1.3.1 +twbs:bootstrap@3.3.6 +underscore@1.0.12 +url@1.3.2 +webapp@1.13.4 +webapp-hashing@1.1.1 +yasinuslu:json-view@1.2.3 +zodern:types@1.0.9 diff --git a/apps/ensemble/.prettierrc b/apps/ensemble/.prettierrc new file mode 100644 index 0000000000..b90ca94e60 --- /dev/null +++ b/apps/ensemble/.prettierrc @@ -0,0 +1,3 @@ +{ + "printWidth": 88 +} diff --git a/apps/ensemble/app.css b/apps/ensemble/app.css new file mode 100644 index 0000000000..5e50cb8e28 --- /dev/null +++ b/apps/ensemble/app.css @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +/* CSS declarations go here */ +html, +body { + height: 100%; +} + +@font-face { + font-family: "PublicSans-Regular"; + src: url("/packages/randyp_mats-common/public/fonts/PublicSans-Regular.ttf"); +} + +@font-face { + font-family: "PublicSans-SemiBold"; + src: url("/packages/randyp_mats-common/public/fonts/PublicSans-SemiBold.ttf"); +} + +@font-face { + font-family: "PublicSans-Medium"; + src: url("/packages/randyp_mats-common/public/fonts/PublicSans-Medium.ttf"); +} + +body { + margin-top: 1%; + margin-left: 2%; + margin-right: 2%; + margin-bottom: 1%; + padding: 0; + background: url("/packages/randyp_mats-common/public/img/bg.png") repeat; + font-family: PublicSans-Regular, Arial, Helvetica, sans-serif; + font-size: 15px; + color: #333333; /*#545454;*/ +} + +.main { + width: 100%; + margin: 0; + padding: 0; + background-color: white; + font-family: PublicSans-Regular, Arial, Helvetica, sans-serif; + font-size: 15px; +} + +.modal-backdrop { + background-color: grey; +} + +.modal-header { + background-image: url("/packages/randyp_mats-common/public/img/subtle_grunge_@2X.png"); +} + +.modal-body { + background-image: url("/packages/randyp_mats-common/public/img/texturetastic_gray.png"); +} + +.modal-content { + background-image: url("/packages/randyp_mats-common/public/img/subtle_grunge_@2X.png"); +} + +.modal-footer { + background-image: url("/packages/randyp_mats-common/public/img/subtle_grunge_@2X.png"); +} + +#Mongol.Mongol_expand { + max-width: 720px !important; +} + +#placeholder .button { + position: absolute; + cursor: pointer; +} + +#placeholder div.button { + font-size: smaller; + color: #999; + background-color: #eee; + padding: 2px; +} + +.message { + padding-left: 50px; + font-size: smaller; +} + +hr { + height: 0; + border-top: 1px; + color: #eee; + background-color: #eee; +} + +.spacer { + padding-left: 1em; +} + +.rule { + width: 100%; + height: 7px; + overflow: hidden; +} + +.spacebutton { + background: transparent; + border: none; +} + +.input { + max-width: 100%; +} + +.select2-selection--multiple { + max-height: 200px; + overflow: auto; +} + +.boldedPublicSans { + font-family: PublicSans-SemiBold, Arial, Helvetica, serif; +} + +.regularPublicSans { + font-family: PublicSans-Regular, Arial, Helvetica, sans-serif; +} + +.mediumPublicSans { + font-family: PublicSans-Medium, Arial, Helvetica, serif; +} + +.item + .tooltip > .tooltip-inner { + background-color: #73ad21; + color: #ffffff; + border: 1px solid green; + padding: 5px; + font-size: 15px; + max-width: 350px; + width: 350px; +} + +.daterangepicker .ranges li { + background-color: #bfdfff; + font-size: 14px !important; + margin: 5px 2px; + border-radius: 10px; + border-color: #dddddd; + border-width: 1px; +} + +.daterangepicker .drp-selected { + font-size: 18px !important; + color: #990000; +} + +.login-link-text { + color: white; + font-size: medium; + text-decoration: none !important; +} diff --git a/apps/ensemble/client/main.js b/apps/ensemble/client/main.js new file mode 100644 index 0000000000..a87407a1f4 --- /dev/null +++ b/apps/ensemble/client/main.js @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +import { matsTypes, matsCollections, methods } from "meteor/randyp:mats-common"; +import "@fortawesome/fontawesome-free"; +import "@fortawesome/fontawesome-free/css/all.css"; +import "@fortawesome/fontawesome-free/js/all.js"; diff --git a/apps/ensemble/package-lock.json b/apps/ensemble/package-lock.json new file mode 100644 index 0000000000..a193d171c3 --- /dev/null +++ b/apps/ensemble/package-lock.json @@ -0,0 +1,6699 @@ +{ + "name": "ensemble", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "ensemble", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@fortawesome/fontawesome-free": "^6.3.0", + "@popperjs/core": "^2.11.6", + "bootstrap": "^4.6.2", + "chai": "^4.3.7", + "daterangepicker": "^3.1.0", + "downsample-lttb": "0.0.1", + "fibers": "^5.0.3", + "fs-extra": "^7.0.1", + "html2canvas": "^1.4.1", + "jquery": "^2.2.4", + "jspdf": "^2.5.1", + "modules": "^0.4.0", + "object-hash": "^1.3.1", + "object-sizeof": "^1.6.3", + "xmlbuilder": "^10.1.1" + }, + "devDependencies": { + "@babel/core": "^7.21.3", + "@babel/eslint-parser": "^7.21.3", + "eslint": "^8.36.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-prettier": "^8.8.0", + "eslint-import-resolver-meteor": "^0.4.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-meteor": "^7.3.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react-hooks": "^4.6.0", + "prettier": "^2.8.5" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", + "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", + "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.3", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-module-transforms": "^7.21.2", + "@babel/helpers": "^7.21.0", + "@babel/parser": "^7.21.3", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.3", + "@babel/types": "^7.21.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/eslint-parser": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.21.3.tgz", + "integrity": "sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg==", + "dev": true, + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": ">=7.11.0", + "eslint": "^7.5.0 || ^8.0.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", + "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.21.3", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", + "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "dev": true, + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", + "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", + "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", + "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", + "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.3", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.21.3", + "@babel/types": "^7.21.3", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", + "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", + "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", + "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@fortawesome/fontawesome-free": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.3.0.tgz", + "integrity": "sha512-qVtd5i1Cc7cdrqnTWqTObKQHjPWAiRwjUPaXObaeNPcy7+WKxJumGBx66rfSFgK6LNpIasVKkEgW8oyf0tmPLA==", + "hasInstallScript": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/raf": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.0.tgz", + "integrity": "sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==", + "optional": true + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "engines": { + "node": "*" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "dev": true + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", + "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "dependencies": { + "deep-equal": "^2.0.5" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bootstrap": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz", + "integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/twbs" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/bootstrap" + } + ], + "peerDependencies": { + "jquery": "1.9.1 - 3", + "popper.js": "^1.16.1" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "bin": { + "btoa": "bin/btoa.js" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001468", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001468.tgz", + "integrity": "sha512-zgAo8D5kbOyUcRAgSmgyuvBkjrGk5CGYG5TYgFdpQv+ywcyEpo1LOWoG8YmoflGnh+V+UsNuKYedsoYs0hzV5A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/canvg": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", + "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", + "optional": true, + "dependencies": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/chai": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "engines": { + "node": "*" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "node_modules/core-js": { + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz", + "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==", + "hasInstallScript": true, + "optional": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/daterangepicker": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/daterangepicker/-/daterangepicker-3.1.0.tgz", + "integrity": "sha512-DxWXvvPq4srWLCqFugqSV+6CBt/CvQ0dnpXhQ3gl0autcIDAruG1PuGG3gC7yPRNytAD1oU1AcUOzaYhOawhTw==", + "dependencies": { + "jquery": ">=1.10", + "moment": "^2.9.0" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-equal": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", + "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.2", + "get-intrinsic": "^1.1.3", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dompurify": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.5.tgz", + "integrity": "sha512-jggCCd+8Iqp4Tsz0nIvpcb22InKEBrGz5dw3EQJMs8HPJDsKbFIO3STYtAvCfDx26Muevn1MHVI0XxjgFfmiSA==", + "optional": true + }, + "node_modules/downsample-lttb": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/downsample-lttb/-/downsample-lttb-0.0.1.tgz", + "integrity": "sha512-Olebo5gyh44OAXTd2BKdcbN5VaZOIKFzoeo9JUFwxDlGt6Sd8fUo6SKaLcafy8aP2UrsKmWDpsscsFEghMjeZA==" + }, + "node_modules/electron-to-chromium": { + "version": "1.4.333", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.333.tgz", + "integrity": "sha512-YyE8+GKyGtPEP1/kpvqsdhD6rA/TP1DUFDN4uiU/YI52NzDxmwHkEb3qjId8hLBa5siJvG0sfC3O66501jMruQ==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.5.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-airbnb": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", + "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", + "dev": true, + "dependencies": { + "eslint-config-airbnb-base": "^15.0.0", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5" + }, + "engines": { + "node": "^10.12.0 || ^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.3", + "eslint-plugin-jsx-a11y": "^6.5.1", + "eslint-plugin-react": "^7.28.0", + "eslint-plugin-react-hooks": "^4.3.0" + } + }, + "node_modules/eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "dependencies": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.32.0 || ^8.2.0", + "eslint-plugin-import": "^2.25.2" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-meteor": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-meteor/-/eslint-import-resolver-meteor-0.4.0.tgz", + "integrity": "sha512-BSqvgt6QZvk9EGhDGnM4azgbxyBD8b0y6FYA52WFzpWpHcZV9ys8PxM33bx8dlCy3HyopRLLsMUnlhTpZzsZmQ==", + "dev": true, + "dependencies": { + "object-assign": "^4.0.1", + "resolve": "^1.1.6" + }, + "peerDependencies": { + "eslint-plugin-import": ">=1.4.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", + "has": "^1.0.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", + "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-meteor": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-meteor/-/eslint-plugin-meteor-7.3.0.tgz", + "integrity": "sha512-z+O+tZQDo9tMw4drgcDSFLpMglJCtMYA1BGX5DA2uUldQw+FPewHerZFLIQVJvSgWpQ2RC+SKaI033RhmU0d1g==", + "dev": true, + "dependencies": { + "invariant": "2.2.4" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": ">= 3.7.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", + "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.8" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==" + }, + "node_modules/fibers": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/fibers/-/fibers-5.0.3.tgz", + "integrity": "sha512-/qYTSoZydQkM21qZpGLDLuCq8c+B8KhuCQ1kLPvnRNhxhVbvrpmH9l2+Lblf5neDuEsY4bfT7LeO553TXQDvJw==", + "hasInstallScript": true, + "dependencies": { + "detect-libc": "^1.0.3" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jquery": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz", + "integrity": "sha512-lBHj60ezci2u1v2FqnZIraShGgEXq35qCzMv4lITyHGppTnA13rwR0MgwyNJh9TnDs3aXUvd1xjAotfraMHX/Q==" + }, + "node_modules/js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jspdf": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz", + "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==", + "dependencies": { + "@babel/runtime": "^7.14.0", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "fflate": "^0.4.8" + }, + "optionalDependencies": { + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^2.2.0", + "html2canvas": "^1.0.0-rc.5" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "dev": true, + "dependencies": { + "language-subtag-registry": "~0.3.2" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/modules": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/modules/-/modules-0.4.0.tgz", + "integrity": "sha512-LX4JgwPHJr1FurPDKp1BlGgMXqZXtxO1O8ABGmj2g15CbLGlInTHcA9flqw6uN6oYKE2T0ngWdiHvcX97mdBsw==", + "engines": { + "node": "*" + } + }, + "node_modules/moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "dev": true + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", + "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==", + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-sizeof": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/object-sizeof/-/object-sizeof-1.6.3.tgz", + "integrity": "sha512-LGtilAKuDGKCcvu1Xg3UvAhAeJJlFmblo3faltmOQ80xrGwAHxnauIXucalKdTEksHp/Pq9tZGz1hfyEmjFJPQ==", + "dependencies": { + "buffer": "^5.6.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "engines": { + "node": "*" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "optional": true + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.5.tgz", + "integrity": "sha512-3gzuxrHbKUePRBB4ZeU08VNkUcqEHaUaouNt0m7LGP4Hti/NuB07C7PPTM/LkWqXoJYJn2McEo5+kxPNrtQkLQ==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "optional": true, + "dependencies": { + "performance-now": "^2.1.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "optional": true, + "engines": { + "node": ">= 0.8.15" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stackblur-canvas": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.5.0.tgz", + "integrity": "sha512-EeNzTVfj+1In7aSLPKDD03F/ly4RxEuF/EX0YcOG0cKoPXs+SLZxDawQbexQDBzwROs4VKLWTOaZQlZkGBFEIQ==", + "optional": true, + "engines": { + "node": ">=0.1.14" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/xmlbuilder": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz", + "integrity": "sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dev": true, + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", + "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "dev": true + }, + "@babel/core": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.3.tgz", + "integrity": "sha512-qIJONzoa/qiHghnm0l1n4i/6IIziDpzqc36FBs4pzMhDUraHqponwJLiAKm1hGLP3OSB/TVNz6rMwVGpwxxySw==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.3", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-module-transforms": "^7.21.2", + "@babel/helpers": "^7.21.0", + "@babel/parser": "^7.21.3", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.3", + "@babel/types": "^7.21.3", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.2", + "semver": "^6.3.0" + } + }, + "@babel/eslint-parser": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.21.3.tgz", + "integrity": "sha512-kfhmPimwo6k4P8zxNs8+T7yR44q1LdpsZdE1NkCsVlfiuTPRfnGgjaF8Qgug9q9Pou17u6wneYF0lDCZJATMFg==", + "dev": true, + "requires": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.0" + } + }, + "@babel/generator": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.3.tgz", + "integrity": "sha512-QS3iR1GYC/YGUnW7IdggFeN5c1poPUurnGttOV/bZgPGV+izC/D8HnD6DLwod0fsatNyVn1G3EVWMYIF0nHbeA==", + "dev": true, + "requires": { + "@babel/types": "^7.21.3", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-compilation-targets": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", + "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.21.3", + "lru-cache": "^5.1.1", + "semver": "^6.3.0" + } + }, + "@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "dev": true + }, + "@babel/helper-function-name": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", + "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "dev": true, + "requires": { + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", + "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "dev": true, + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.19.1", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.2", + "@babel/types": "^7.21.2" + } + }, + "@babel/helper-simple-access": { + "version": "7.20.2", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", + "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "dev": true, + "requires": { + "@babel/types": "^7.20.2" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dev": true, + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.19.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", + "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", + "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", + "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "dev": true + }, + "@babel/helpers": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", + "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "dev": true, + "requires": { + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.0", + "@babel/types": "^7.21.0" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.3.tgz", + "integrity": "sha512-lobG0d7aOfQRXh8AyklEAgZGvA4FShxo6xQbUrrT/cNBPUdIDojlokwJsQyCC/eKia7ifqM0yP+2DRZ4WKw2RQ==", + "dev": true + }, + "@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "requires": { + "regenerator-runtime": "^0.13.11" + } + }, + "@babel/template": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", + "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7" + } + }, + "@babel/traverse": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.3.tgz", + "integrity": "sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.21.3", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.21.3", + "@babel/types": "^7.21.3", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.3.tgz", + "integrity": "sha512-sBGdETxC+/M4o/zKC0sl6sjWv62WFR/uzxrJ6uYyMLZOUlPnwzw0tKgVHOXxaAd5l2g8pEDM5RZ495GPQI77kg==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-validator-identifier": "^7.19.1", + "to-fast-properties": "^2.0.0" + } + }, + "@eslint-community/eslint-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.3.0.tgz", + "integrity": "sha512-v3oplH6FYCULtFuCeqyuTd9D2WKO937Dxdq+GmHOLL72TTRriLxz2VLlNfkZRsvj6PKnOPAtuT6dwrs/pA5DvA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + } + } + }, + "@eslint-community/regexpp": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", + "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.1.tgz", + "integrity": "sha512-eFRmABvW2E5Ho6f5fHLqgena46rOj7r7OKHYfLElqcBfGFHHpjBhivyi5+jOEQuSpdc/1phIZJlbC2te+tZNIw==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.5.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + } + } + }, + "@eslint/js": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.36.0.tgz", + "integrity": "sha512-lxJ9R5ygVm8ZWgYdUweoq5ownDlJ4upvoWmO4eLxBYHdMo+vZ/Rx0EN6MbKWDJOSUGrqJy2Gt+Dyv/VKml0fjg==", + "dev": true + }, + "@fortawesome/fontawesome-free": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.3.0.tgz", + "integrity": "sha512-qVtd5i1Cc7cdrqnTWqTObKQHjPWAiRwjUPaXObaeNPcy7+WKxJumGBx66rfSFgK6LNpIasVKkEgW8oyf0tmPLA==" + }, + "@humanwhocodes/config-array": { + "version": "0.11.8", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", + "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", + "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "requires": { + "eslint-scope": "5.1.1" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@popperjs/core": { + "version": "2.11.6", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", + "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==" + }, + "@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "@types/raf": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@types/raf/-/raf-3.4.0.tgz", + "integrity": "sha512-taW5/WYqo36N7V39oYyHP9Ipfd5pNFvGTIQsNGj86xV88YQ7GnI30/yMfKDF7Zgin0m3e+ikX88FvImnK4RjGw==", + "optional": true + }, + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "aria-query": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", + "integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==", + "dev": true, + "requires": { + "deep-equal": "^2.0.5" + } + }, + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } + }, + "array-includes": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", + "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + } + }, + "array.prototype.flat": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", + "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.flatmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", + "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + } + }, + "array.prototype.tosorted": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz", + "integrity": "sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.1.3" + } + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==" + }, + "ast-types-flow": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.7.tgz", + "integrity": "sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" + }, + "available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "dev": true + }, + "axe-core": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.3.tgz", + "integrity": "sha512-/BQzOX780JhsxDnPpH4ZiyrJAzcd8AfzFPkv+89veFSr1rcMjuq2JDCwypKaPeB6ljHp9KjXhPpjgCvQlWYuqg==", + "dev": true + }, + "axobject-query": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.1.1.tgz", + "integrity": "sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg==", + "dev": true, + "requires": { + "deep-equal": "^2.0.5" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bootstrap": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz", + "integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==", + "requires": {} + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" + } + }, + "btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==" + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001468", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001468.tgz", + "integrity": "sha512-zgAo8D5kbOyUcRAgSmgyuvBkjrGk5CGYG5TYgFdpQv+ywcyEpo1LOWoG8YmoflGnh+V+UsNuKYedsoYs0hzV5A==", + "dev": true + }, + "canvg": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/canvg/-/canvg-3.0.10.tgz", + "integrity": "sha512-qwR2FRNO9NlzTeKIPIKpnTY6fqwuYSequ8Ru8c0YkYU7U0oW+hLUvWadLvAu1Rl72OMNiFhoLu4f8eUjQ7l/+Q==", + "optional": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@types/raf": "^3.4.0", + "core-js": "^3.8.3", + "raf": "^3.4.1", + "regenerator-runtime": "^0.13.7", + "rgbcolor": "^1.0.1", + "stackblur-canvas": "^2.0.0", + "svg-pathdata": "^6.0.3" + } + }, + "chai": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==" + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "confusing-browser-globals": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", + "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", + "dev": true + }, + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, + "core-js": { + "version": "3.29.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz", + "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==", + "optional": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "requires": { + "utrie": "^1.0.2" + } + }, + "damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "daterangepicker": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/daterangepicker/-/daterangepicker-3.1.0.tgz", + "integrity": "sha512-DxWXvvPq4srWLCqFugqSV+6CBt/CvQ0dnpXhQ3gl0autcIDAruG1PuGG3gC7yPRNytAD1oU1AcUOzaYhOawhTw==", + "requires": { + "jquery": ">=1.10", + "moment": "^2.9.0" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-equal": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", + "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-get-iterator": "^1.1.2", + "get-intrinsic": "^1.1.3", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "define-properties": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "dev": true, + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==" + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dompurify": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.5.tgz", + "integrity": "sha512-jggCCd+8Iqp4Tsz0nIvpcb22InKEBrGz5dw3EQJMs8HPJDsKbFIO3STYtAvCfDx26Muevn1MHVI0XxjgFfmiSA==", + "optional": true + }, + "downsample-lttb": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/downsample-lttb/-/downsample-lttb-0.0.1.tgz", + "integrity": "sha512-Olebo5gyh44OAXTd2BKdcbN5VaZOIKFzoeo9JUFwxDlGt6Sd8fUo6SKaLcafy8aP2UrsKmWDpsscsFEghMjeZA==" + }, + "electron-to-chromium": { + "version": "1.4.333", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.333.tgz", + "integrity": "sha512-YyE8+GKyGtPEP1/kpvqsdhD6rA/TP1DUFDN4uiU/YI52NzDxmwHkEb3qjId8hLBa5siJvG0sfC3O66501jMruQ==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "es-abstract": { + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + } + }, + "es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + } + }, + "es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + } + }, + "es-shim-unscopables": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", + "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "eslint": { + "version": "8.36.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.36.0.tgz", + "integrity": "sha512-Y956lmS7vDqomxlaaQAHVmeb4tNMp2FWIvU/RnU5BD3IKMD/MJPr76xdyr68P8tV1iNMvN2mRK0yy3c+UjL+bw==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.4.0", + "@eslint/eslintrc": "^2.0.1", + "@eslint/js": "8.36.0", + "@humanwhocodes/config-array": "^0.11.8", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.5.0", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "grapheme-splitter": "^1.0.4", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-sdsl": "^4.1.4", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + }, + "globals": { + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "eslint-config-airbnb": { + "version": "19.0.4", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-19.0.4.tgz", + "integrity": "sha512-T75QYQVQX57jiNgpF9r1KegMICE94VYwoFQyMGhrvc+lB8YF2E/M/PYDaQe1AJcWaEgqLE+ErXV1Og/+6Vyzew==", + "dev": true, + "requires": { + "eslint-config-airbnb-base": "^15.0.0", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5" + } + }, + "eslint-config-airbnb-base": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", + "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", + "dev": true, + "requires": { + "confusing-browser-globals": "^1.0.10", + "object.assign": "^4.1.2", + "object.entries": "^1.1.5", + "semver": "^6.3.0" + } + }, + "eslint-config-prettier": { + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", + "dev": true, + "requires": {} + }, + "eslint-import-resolver-meteor": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-meteor/-/eslint-import-resolver-meteor-0.4.0.tgz", + "integrity": "sha512-BSqvgt6QZvk9EGhDGnM4azgbxyBD8b0y6FYA52WFzpWpHcZV9ys8PxM33bx8dlCy3HyopRLLsMUnlhTpZzsZmQ==", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "resolve": "^1.1.6" + } + }, + "eslint-import-resolver-node": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", + "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "dev": true, + "requires": { + "debug": "^3.2.7", + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-module-utils": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", + "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "dev": true, + "requires": { + "debug": "^3.2.7" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + } + } + }, + "eslint-plugin-import": { + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", + "dev": true, + "requires": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", + "has": "^1.0.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + } + } + }, + "eslint-plugin-jsx-a11y": { + "version": "6.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz", + "integrity": "sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==", + "dev": true, + "requires": { + "@babel/runtime": "^7.20.7", + "aria-query": "^5.1.3", + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "ast-types-flow": "^0.0.7", + "axe-core": "^4.6.2", + "axobject-query": "^3.1.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "has": "^1.0.3", + "jsx-ast-utils": "^3.3.3", + "language-tags": "=1.0.5", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "semver": "^6.3.0" + } + }, + "eslint-plugin-meteor": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-meteor/-/eslint-plugin-meteor-7.3.0.tgz", + "integrity": "sha512-z+O+tZQDo9tMw4drgcDSFLpMglJCtMYA1BGX5DA2uUldQw+FPewHerZFLIQVJvSgWpQ2RC+SKaI033RhmU0d1g==", + "dev": true, + "requires": { + "invariant": "2.2.4" + } + }, + "eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-plugin-react": { + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", + "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", + "dev": true, + "requires": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.0", + "string.prototype.matchall": "^4.0.8" + }, + "dependencies": { + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "resolve": { + "version": "2.0.0-next.4", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.4.tgz", + "integrity": "sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + } + } + }, + "eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "requires": {} + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + }, + "espree": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.0.tgz", + "integrity": "sha512-JPbJGhKc47++oo4JkEoTe2wjy4fmMwvFpgJT9cQzmfXKp22Dr6Hf1tdCteLz1h0P3t+mGvWZ+4Uankvh8+c6zw==", + "dev": true, + "requires": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + } + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fflate": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.4.8.tgz", + "integrity": "sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA==" + }, + "fibers": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/fibers/-/fibers-5.0.3.tgz", + "integrity": "sha512-/qYTSoZydQkM21qZpGLDLuCq8c+B8KhuCQ1kLPvnRNhxhVbvrpmH9l2+Lblf5neDuEsY4bfT7LeO553TXQDvJw==", + "requires": { + "detect-libc": "^1.0.3" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + } + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==" + }, + "get-intrinsic": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", + "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "requires": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "ignore": { + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "internal-slot": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true + }, + "is-core-module": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", + "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "dev": true + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "dev": true + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typed-array": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", + "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + } + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "dev": true + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-weakset": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", + "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "jquery": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.4.tgz", + "integrity": "sha512-lBHj60ezci2u1v2FqnZIraShGgEXq35qCzMv4lITyHGppTnA13rwR0MgwyNJh9TnDs3aXUvd1xjAotfraMHX/Q==" + }, + "js-sdsl": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", + "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jspdf": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz", + "integrity": "sha512-hXObxz7ZqoyhxET78+XR34Xu2qFGrJJ2I2bE5w4SM8eFaFEkW2xcGRVUss360fYelwRSid/jT078kbNvmoW0QA==", + "requires": { + "@babel/runtime": "^7.14.0", + "atob": "^2.1.2", + "btoa": "^1.2.1", + "canvg": "^3.0.6", + "core-js": "^3.6.0", + "dompurify": "^2.2.0", + "fflate": "^0.4.8", + "html2canvas": "^1.0.0-rc.5" + } + }, + "jsx-ast-utils": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz", + "integrity": "sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==", + "dev": true, + "requires": { + "array-includes": "^3.1.5", + "object.assign": "^4.1.3" + } + }, + "language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "dev": true + }, + "language-tags": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.5.tgz", + "integrity": "sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==", + "dev": true, + "requires": { + "language-subtag-registry": "~0.3.2" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "requires": { + "get-func-name": "^2.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true + }, + "modules": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/modules/-/modules-0.4.0.tgz", + "integrity": "sha512-LX4JgwPHJr1FurPDKp1BlGgMXqZXtxO1O8ABGmj2g15CbLGlInTHcA9flqw6uN6oYKE2T0ngWdiHvcX97mdBsw==" + }, + "moment": { + "version": "2.29.4", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", + "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node-releases": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", + "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true + }, + "object-hash": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz", + "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==" + }, + "object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "dev": true + }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-sizeof": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/object-sizeof/-/object-sizeof-1.6.3.tgz", + "integrity": "sha512-LGtilAKuDGKCcvu1Xg3UvAhAeJJlFmblo3faltmOQ80xrGwAHxnauIXucalKdTEksHp/Pq9tZGz1hfyEmjFJPQ==", + "requires": { + "buffer": "^5.6.0" + } + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "object.entries": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", + "integrity": "sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "object.fromentries": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.6.tgz", + "integrity": "sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "object.hasown": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.2.tgz", + "integrity": "sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==", + "dev": true, + "requires": { + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "object.values": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", + "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "optional": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", + "dev": true + }, + "popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "peer": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.5.tgz", + "integrity": "sha512-3gzuxrHbKUePRBB4ZeU08VNkUcqEHaUaouNt0m7LGP4Hti/NuB07C7PPTM/LkWqXoJYJn2McEo5+kxPNrtQkLQ==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "raf": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz", + "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==", + "optional": true, + "requires": { + "performance-now": "^2.1.0" + } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dev": true, + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rgbcolor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgbcolor/-/rgbcolor-1.0.1.tgz", + "integrity": "sha512-9aZLIrhRaD97sgVhtJOW6ckOEh6/GnvQtdVNfdZ6s67+3/XwLS9lBcQYzEEhYVeUowN7pRzMLsyGhK2i/xvWbw==", + "optional": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "stackblur-canvas": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/stackblur-canvas/-/stackblur-canvas-2.5.0.tgz", + "integrity": "sha512-EeNzTVfj+1In7aSLPKDD03F/ly4RxEuF/EX0YcOG0cKoPXs+SLZxDawQbexQDBzwROs4VKLWTOaZQlZkGBFEIQ==", + "optional": true + }, + "stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dev": true, + "requires": { + "internal-slot": "^1.0.4" + } + }, + "string.prototype.matchall": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz", + "integrity": "sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.3", + "regexp.prototype.flags": "^1.4.3", + "side-channel": "^1.0.4" + } + }, + "string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "string.prototype.trimend": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", + "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "string.prototype.trimstart": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", + "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "svg-pathdata": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svg-pathdata/-/svg-pathdata-6.0.3.tgz", + "integrity": "sha512-qsjeeq5YjBZ5eMdFuUa4ZosMLxgr5RZ+F+Y1OrDhuOCEInRMA3x74XdBtggJcj9kOeInz0WE+LgCPDkZFlBYJw==", + "optional": true + }, + "text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "requires": { + "utrie": "^1.0.2" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true + }, + "tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==" + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "requires": { + "base64-arraybuffer": "^1.0.2" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "dev": true, + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-typed-array": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", + "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "dev": true, + "requires": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "xmlbuilder": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-10.1.1.tgz", + "integrity": "sha512-OyzrcFLL/nb6fMGHbiRDuPup9ljBycsdCypwuyg5AAHvyWzGfChJpCXMG88AGTIMFhGZ9RccFN1e6lhg3hkwKg==" + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/apps/ensemble/package.json b/apps/ensemble/package.json new file mode 100644 index 0000000000..33feadf956 --- /dev/null +++ b/apps/ensemble/package.json @@ -0,0 +1,42 @@ +{ + "name": "ensemble", + "private": true, + "scripts": { + "start": "meteor run", + "lint": "prettier --ignore-path ../../.prettierignore --check . && eslint --ignore-path ../../.gitignore .", + "format": "prettier --ignore-path ../../.prettierignore --write . && eslint --ignore-path ../../.gitignore --fix ." + }, + "dependencies": { + "@babel/runtime": "^7.21.0", + "@fortawesome/fontawesome-free": "^6.3.0", + "@popperjs/core": "^2.11.6", + "bootstrap": "^4.6.2", + "chai": "^4.3.7", + "daterangepicker": "^3.1.0", + "downsample-lttb": "0.0.1", + "fibers": "^5.0.3", + "fs-extra": "^7.0.1", + "html2canvas": "^1.4.1", + "jquery": "^2.2.4", + "jspdf": "^2.5.1", + "modules": "^0.4.0", + "object-hash": "^1.3.1", + "object-sizeof": "^1.6.3", + "xmlbuilder": "^10.1.1" + }, + "devDependencies": { + "@babel/core": "^7.21.3", + "@babel/eslint-parser": "^7.21.3", + "eslint": "^8.36.0", + "eslint-config-airbnb": "^19.0.4", + "eslint-config-prettier": "^8.8.0", + "eslint-import-resolver-meteor": "^0.4.0", + "eslint-plugin-import": "^2.27.5", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-meteor": "^7.3.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react-hooks": "^4.6.0", + "prettier": "^2.8.5" + } +} diff --git a/apps/ensemble/public/favicon.ico b/apps/ensemble/public/favicon.ico new file mode 100755 index 0000000000000000000000000000000000000000..b14c1291ae908fabf84dbc344d466df7cc0af93e GIT binary patch literal 5430 zcmeHL3sh9c8J-1}%PzXRB8WtENkk#mC{mNsH1QElTBA{G@sYz@5TdrkP$Rw~;K8>7 z1z*j1{LH@F&5(zQ+ zWCHQqyM`2(#1k;f*fmBMaY}pD#Kgq3w|FY0ndR5(gf1Mzp3_RPy(k!?|F#s-TPNlV zro^D8uS1kYoRjp#w+{(LEXO{MUqSY`{U9f^)YTkCaHq}hOt?E*fpoJ^i| z{ZUIj9zA$~m80J5!txkPEeGO$)3>;P`xG=`@-ltAHa#_b?D23z zu+tc9nK2E)qa5+qh2CrkmMoebq>p!WbQ~4o?$*e(Zl5s&yO#tYGh!RGtAbIGmIBSP zK={z#QbN9JaUSP1ULVie_JXj0;TJ0u_){b++msHDg`{7tIas&bd0b{JJ7W9PW zeFG&DXIH7Tn$Mg2nS_*$R4QliaeaAPL6|gF5SF)U;g)2V8n1Wd(1yu8Dv3*P5TY;-VsC& zm&A9T0o-Rs+t&Kcw_jOUU*5cR$F``SQWQHI7SAP{^PXneFq_xv9LYlgZXDRBO}(ejA4JQ0!9CRs<+2lPC6Vz zn!EG#R4+@l!m%sKu+LtEVOa}dN9{ySJdW;>H4hssrW`LV6M(YI`%s!>j``CRfks9~Gz09t7#kB)O(?18 ziN7Lc5N;F);$A~Ko<8~)o_v1?_ih|Qeg0gWi0iNq8g67t>FzgRWvN zG9wk&O{GRZ$dB~Z3?4}AdgA7NXK4;pq7iWA&{VWH)r#kSM@I*qwBEwqYx`+#q{Xe$ z<)}aHiG-SDypin-&*CkpDGh>+rLmnppMKkQDhcFVKk#u9)E%FN*2Y4#x3%KN#R?Rs zB%rROSk!T+ViR;(zoO6REtDq6P)*-S?UnuFd*N5I9UC@$u~VN)FH!od8*yM?DH!^}7J#yV75^VbTx43)z8{GfqII1$og5`=VPUS%doUDn% zCp16QHXMVKlasSPCvUTFR!)pc%on)^#(nAFTX@)X32dFK^79d3Z7t?ZzLc9A%b_-Y z{5!OL_kiw=W?U;;h_jkb4d;`UxO`?2j%E1O%49Nwc{bA#A4V#>bJyg3DDE}3z>RfR z;7_?Zr@r^58dyHZbap&@irbapbgxLnbzm`BY(7^*p7XPL*B+aWCl8xC_ZVIGZL?>J zIj=r%_qLC@9M>x=o@1WUb?~LnqEo|*@W+Lc%JYdz+$vjzXYFmBap-)G?uvo8k;LHK zxdxV}vb^}|2X|0Ctqju!wW*_bAp3HSA6#Z4xhYr!OdGlw=_)lu~Au(hv zcKP`rD=Gqq_r{3)n$@e2pOS==3Gp}>^B06qncRi*k;}2hbxyJVy^?bo@&n}ZVF4Bv zt(>1}33=BAdwjjIh~8hLJ>0Qxu|ND&N@RwIA>_Sx5#c%qxjVLE5#1*o_l2EZtFwc{ zR6{(y_1h3KlkxIc%=0$;-toE@t@Adk^YP1VZDFlYyi$%VBjmOB2#Mt}U)0Z+%d01k zAK&Ypw70o;|4l9ks$W}K1`3DO(I1AERbCh6jBo#dtRbpiRx0ME`Gr0^XVc literal 0 HcmV?d00001 diff --git a/apps/ensemble/public/title b/apps/ensemble/public/title new file mode 100644 index 0000000000..7d0141ae0e --- /dev/null +++ b/apps/ensemble/public/title @@ -0,0 +1 @@ +Ensemble \ No newline at end of file diff --git a/apps/ensemble/server/dataFunctions/data_contour.js b/apps/ensemble/server/dataFunctions/data_contour.js new file mode 100644 index 0000000000..e4cd3b9a06 --- /dev/null +++ b/apps/ensemble/server/dataFunctions/data_contour.js @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +import { + matsCollections, + matsTypes, + matsDataUtils, + matsDataQueryUtils, + matsDataCurveOpsUtils, + matsDataProcessUtils, +} from "meteor/randyp:mats-common"; +import { moment } from "meteor/momentjs:moment"; + +dataContour = function (plotParams, plotFunction) { + // initialize variables common to all curves + const appParams = { + plotType: matsTypes.PlotTypes.contour, + matching: plotParams.plotAction === matsTypes.PlotActions.matched, + completeness: plotParams.completeness, + outliers: plotParams.outliers, + hideGaps: plotParams.noGapsCheck, + hasLevels: false, + }; + const dataRequests = {}; // used to store data queries + let dataFoundForCurve = true; + const totalProcessingStart = moment(); + const dateRange = matsDataUtils.getDateRange(plotParams.dates); + const fromSecs = dateRange.fromSeconds; + const toSecs = dateRange.toSeconds; + const xAxisParam = plotParams["x-axis-parameter"]; + const yAxisParam = plotParams["y-axis-parameter"]; + const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" }) + .optionsMap[xAxisParam]; + const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" }) + .optionsMap[yAxisParam]; + let error = ""; + const curves = JSON.parse(JSON.stringify(plotParams.curves)); + if (curves.length > 1) { + throw new Error("INFO: There must only be one added curve."); + } + const dataset = []; + const axisMap = Object.create(null); + + // initialize variables specific to the curve + const curve = curves[0]; + const { label } = curve; + const model = matsCollections["data-source"].findOne({ name: "data-source" }) + .optionsMap[curve["data-source"]][0]; + const regionStr = curve.region; + const region = Object.keys( + matsCollections.region.findOne({ name: "region" }).valuesMap + ).find( + (key) => + matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr + ); + const source = curve.truth; + let sourceStr = ""; + if (source !== "All") { + sourceStr = `_${source}`; + } + const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + let thresholdClause = ""; + let validTimeClause = ""; + let forecastLengthClause = ""; + let dateString = ""; + let dateClause = ""; + if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") { + const thresholdStr = curve.threshold; + const threshold = Object.keys( + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + ).find( + (key) => + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === + thresholdStr + ); + thresholdClause = `and m0.thresh = ${threshold}`; + } + if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") { + const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; + if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) { + validTimeClause = `and m0.valid_time%(24*3600)/3600 IN(${validTimes})`; + } + } + if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") { + const forecastLength = curve["forecast-length"]; + forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; + } + if ( + (xAxisParam === "Init Date" || yAxisParam === "Init Date") && + xAxisParam !== "Valid Date" && + yAxisParam !== "Valid Date" + ) { + dateString = "m0.valid_time-m0.fcst_len*3600"; + } else { + dateString = "m0.valid_time"; + } + dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`; + const statisticSelect = curve.statistic; + const statisticOptionsMap = matsCollections.statistic.findOne( + { name: "statistic" }, + { optionsMap: 1 } + ).optionsMap; + const statisticClause = + "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + // For contours, this functions as the colorbar label. + const statType = statisticOptionsMap[statisticSelect][0]; + curve.unitKey = statisticOptionsMap[statisticSelect][1]; + + let d; + // this is a database driven curve, not a difference curve + // prepare the query from the above parameters + let statement = + "{{xValClause}} " + + "{{yValClause}} " + + "count(distinct {{dateString}}) as N_times, " + + "min({{dateString}}) as min_secs, " + + "max({{dateString}}) as max_secs, " + + "{{statisticClause}} " + + "{{queryTableClause}} " + + "where 1=1 " + + "{{dateClause}} " + + "{{thresholdClause}} " + + "{{validTimeClause}} " + + "{{forecastLengthClause}} " + + "group by xVal,yVal " + + "order by xVal,yVal" + + ";"; + + statement = statement.replace("{{xValClause}}", xValClause); + statement = statement.replace("{{yValClause}}", yValClause); + statement = statement.replace("{{statisticClause}}", statisticClause); + statement = statement.replace("{{queryTableClause}}", queryTableClause); + statement = statement.replace("{{thresholdClause}}", thresholdClause); + statement = statement.replace("{{validTimeClause}}", validTimeClause); + statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause); + statement = statement.replace("{{dateClause}}", dateClause); + statement = statement.split("{{dateString}}").join(dateString); + dataRequests[label] = statement; + + let queryResult; + const startMoment = moment(); + let finishMoment; + try { + // send the query statement to the query function + queryResult = matsDataQueryUtils.queryDBContour( + sumPool, + statement, + appParams, + statisticSelect + ); + finishMoment = moment(); + dataRequests[`data retrieval (query) time - ${label}`] = { + begin: startMoment.format(), + finish: finishMoment.format(), + duration: `${moment + .duration(finishMoment.diff(startMoment)) + .asSeconds()} seconds`, + recordCount: queryResult.data.xTextOutput.length, + }; + // get the data back from the query + d = queryResult.data; + } catch (e) { + // this is an error produced by a bug in the query function, not an error returned by the mysql database + e.message = `Error in queryDB: ${e.message} for statement: ${statement}`; + throw new Error(e.message); + } + if (queryResult.error !== undefined && queryResult.error !== "") { + if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) { + // this is NOT an error just a no data condition + dataFoundForCurve = false; + } else { + // this is an error returned by the mysql database + error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; + throw new Error(error); + } + } + + if (!dataFoundForCurve) { + // we found no data for any curves so don't bother proceeding + throw new Error("INFO: No valid data for any curves."); + } + + const postQueryStartMoment = moment(); + + // set curve annotation to be the curve mean -- may be recalculated later + // also pass previously calculated axis stats to curve options + const { mean } = d.glob_stats; + const annotation = + mean === undefined + ? `${label}- mean = NoData` + : `${label}- mean = ${mean.toPrecision(4)}`; + curve.annotation = annotation; + curve.xmin = d.xmin; + curve.xmax = d.xmax; + curve.ymin = d.ymin; + curve.ymax = d.ymax; + curve.zmin = d.zmin; + curve.zmax = d.zmax; + curve.xAxisKey = xAxisParam; + curve.yAxisKey = yAxisParam; + const cOptions = matsDataCurveOpsUtils.generateContourCurveOptions( + curve, + axisMap, + d, + appParams + ); // generate plot with data, curve annotation, axis labels, etc. + dataset.push(cOptions); + const postQueryFinishMoment = moment(); + dataRequests[`post data retrieval (query) process time - ${label}`] = { + begin: postQueryStartMoment.format(), + finish: postQueryFinishMoment.format(), + duration: `${moment + .duration(postQueryFinishMoment.diff(postQueryStartMoment)) + .asSeconds()} seconds`, + }; + + // process the data returned by the query + const curveInfoParams = { curve: curves, statType, axisMap }; + const bookkeepingParams = { + dataRequests, + totalProcessingStart, + }; + const result = matsDataProcessUtils.processDataContour( + dataset, + curveInfoParams, + plotParams, + bookkeepingParams + ); + plotFunction(result); +}; diff --git a/apps/ensemble/server/dataFunctions/data_contour_diff.js b/apps/ensemble/server/dataFunctions/data_contour_diff.js new file mode 100644 index 0000000000..5460fe0f7f --- /dev/null +++ b/apps/ensemble/server/dataFunctions/data_contour_diff.js @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +import { + matsCollections, + matsTypes, + matsDataUtils, + matsDataQueryUtils, + matsDataDiffUtils, + matsDataCurveOpsUtils, + matsDataProcessUtils, + matsPlotUtils, +} from "meteor/randyp:mats-common"; +import { moment } from "meteor/momentjs:moment"; + +dataContourDiff = function (plotParams, plotFunction) { + // initialize variables common to all curves + const appParams = { + plotType: matsTypes.PlotTypes.contourDiff, + matching: plotParams.plotAction === matsTypes.PlotActions.matched, + completeness: plotParams.completeness, + outliers: plotParams.outliers, + hideGaps: plotParams.noGapsCheck, + hasLevels: false, + }; + const dataRequests = {}; // used to store data queries + let dataFoundForCurve = true; + let dataNotFoundForAnyCurve = false; + const showSignificance = plotParams.significance !== "none"; + const totalProcessingStart = moment(); + const dateRange = matsDataUtils.getDateRange(plotParams.dates); + const fromSecs = dateRange.fromSeconds; + const toSecs = dateRange.toSeconds; + const xAxisParam = plotParams["x-axis-parameter"]; + const yAxisParam = plotParams["y-axis-parameter"]; + const xValClause = matsCollections.PlotParams.findOne({ name: "x-axis-parameter" }) + .optionsMap[xAxisParam]; + const yValClause = matsCollections.PlotParams.findOne({ name: "y-axis-parameter" }) + .optionsMap[yAxisParam]; + let error = ""; + let curves = JSON.parse(JSON.stringify(plotParams.curves)); + const curvesLength = curves.length; + if (curvesLength !== 2) { + throw new Error("INFO: There must be two added curves."); + } + let dataset = []; + const axisMap = Object.create(null); + + for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) { + // initialize variables specific to each curve + const curve = curves[curveIndex]; + const { label } = curve; + const model = matsCollections["data-source"].findOne({ name: "data-source" }) + .optionsMap[curve["data-source"]][0]; + var regionStr = curve.region; + const region = Object.keys( + matsCollections.region.findOne({ name: "region" }).valuesMap + ).find( + (key) => + matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr + ); + const source = curve.truth; + let sourceStr = ""; + if (source !== "All") { + sourceStr = `_${source}`; + } + const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + let thresholdClause = ""; + let validTimeClause = ""; + let forecastLengthClause = ""; + let dateString = ""; + let dateClause = ""; + if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") { + var thresholdStr = curve.threshold; + const threshold = Object.keys( + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + ).find( + (key) => + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === + thresholdStr + ); + thresholdClause = `and m0.thresh = ${threshold}`; + } + if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") { + const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; + if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) { + validTimeClause = `and m0.valid_time%(24*3600)/3600 IN(${validTimes})`; + } + } + if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") { + const forecastLength = curve["forecast-length"]; + forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; + } + if ( + (xAxisParam === "Init Date" || yAxisParam === "Init Date") && + xAxisParam !== "Valid Date" && + yAxisParam !== "Valid Date" + ) { + dateString = "m0.valid_time-m0.fcst_len*3600"; + } else { + dateString = "m0.valid_time"; + } + dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`; + var statisticSelect = curve.statistic; + const statisticOptionsMap = matsCollections.statistic.findOne( + { name: "statistic" }, + { optionsMap: 1 } + ).optionsMap; + const statisticClause = + "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + // For contours, this functions as the colorbar label. + var statType = statisticOptionsMap[statisticSelect][0]; + curves[curveIndex].unitKey = statisticOptionsMap[statisticSelect][1]; + + var d; + // this is a database driven curve, not a difference curve + // prepare the query from the above parameters + let statement = + "{{xValClause}} " + + "{{yValClause}} " + + "count(distinct {{dateString}}) as N_times, " + + "min({{dateString}}) as min_secs, " + + "max({{dateString}}) as max_secs, " + + "{{statisticClause}} " + + "{{queryTableClause}} " + + "where 1=1 " + + "{{dateClause}} " + + "{{thresholdClause}} " + + "{{validTimeClause}} " + + "{{forecastLengthClause}} " + + "group by xVal,yVal " + + "order by xVal,yVal" + + ";"; + + statement = statement.replace("{{xValClause}}", xValClause); + statement = statement.replace("{{yValClause}}", yValClause); + statement = statement.replace("{{statisticClause}}", statisticClause); + statement = statement.replace("{{queryTableClause}}", queryTableClause); + statement = statement.replace("{{thresholdClause}}", thresholdClause); + statement = statement.replace("{{validTimeClause}}", validTimeClause); + statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause); + statement = statement.replace("{{dateClause}}", dateClause); + statement = statement.split("{{dateString}}").join(dateString); + dataRequests[label] = statement; + + var queryResult; + const startMoment = moment(); + var finishMoment; + try { + // send the query statement to the query function + queryResult = matsDataQueryUtils.queryDBContour( + sumPool, + statement, + appParams, + statisticSelect + ); + finishMoment = moment(); + dataRequests[`data retrieval (query) time - ${label}`] = { + begin: startMoment.format(), + finish: finishMoment.format(), + duration: `${moment + .duration(finishMoment.diff(startMoment)) + .asSeconds()} seconds`, + recordCount: queryResult.data.xTextOutput.length, + }; + // get the data back from the query + d = queryResult.data; + } catch (e) { + // this is an error produced by a bug in the query function, not an error returned by the mysql database + e.message = `Error in queryDB: ${e.message} for statement: ${statement}`; + throw new Error(e.message); + } + if (queryResult.error !== undefined && queryResult.error !== "") { + if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) { + // this is NOT an error just a no data condition + dataFoundForCurve = false; + } else { + // this is an error returned by the mysql database + error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; + throw new Error(error); + } + dataNotFoundForAnyCurve = true; + } + + const postQueryStartMoment = moment(); + + // set curve annotation to be the curve mean -- may be recalculated later + // also pass previously calculated axis stats to curve options + const { mean } = d.glob_stats; + const annotation = + mean === undefined + ? `${label}- mean = NoData` + : `${label}- mean = ${mean.toPrecision(4)}`; + curve.annotation = annotation; + curve.xmin = d.xmin; + curve.xmax = d.xmax; + curve.ymin = d.ymin; + curve.ymax = d.ymax; + curve.zmin = d.zmin; + curve.zmax = d.zmax; + curve.xAxisKey = xAxisParam; + curve.yAxisKey = yAxisParam; + const cOptions = matsDataCurveOpsUtils.generateContourCurveOptions( + curve, + axisMap, + d, + appParams + ); // generate plot with data, curve annotation, axis labels, etc. + dataset.push(cOptions); + const postQueryFinishMoment = moment(); + dataRequests[`post data retrieval (query) process time - ${label}`] = { + begin: postQueryStartMoment.format(), + finish: postQueryFinishMoment.format(), + duration: `${moment + .duration(postQueryFinishMoment.diff(postQueryStartMoment)) + .asSeconds()} seconds`, + }; + } // end for curves + + if (dataNotFoundForAnyCurve) { + // we found no data for at least one curve so don't bother proceeding + throw new Error( + "INFO: No valid data for at least one curve. Try making individual contour plots to determine which one." + ); + } + + // turn the two contours into one difference contour + dataset = matsDataDiffUtils.getDataForDiffContour( + dataset, + appParams, + showSignificance, + plotParams.significance, + statisticSelect, + statType === "ctc", + statType === "scalar" + ); + plotParams.curves = matsDataUtils.getDiffContourCurveParams(plotParams.curves); + curves = plotParams.curves; + dataset[0].name = matsPlotUtils.getCurveText( + matsTypes.PlotTypes.contourDiff, + curves[0] + ); + dataset[1] = matsDataCurveOpsUtils.getContourSignificanceLayer(dataset); + + // process the data returned by the query + const curveInfoParams = { curve: curves, statType, axisMap }; + const bookkeepingParams = { + dataRequests, + totalProcessingStart, + }; + const result = matsDataProcessUtils.processDataContour( + dataset, + curveInfoParams, + plotParams, + bookkeepingParams + ); + plotFunction(result); +}; diff --git a/apps/ensemble/server/dataFunctions/data_dailymodelcycle.js b/apps/ensemble/server/dataFunctions/data_dailymodelcycle.js new file mode 100644 index 0000000000..e0f4721495 --- /dev/null +++ b/apps/ensemble/server/dataFunctions/data_dailymodelcycle.js @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +import { + matsCollections, + matsTypes, + matsDataUtils, + matsDataQueryUtils, + matsDataDiffUtils, + matsDataCurveOpsUtils, + matsDataProcessUtils, +} from "meteor/randyp:mats-common"; +import { moment } from "meteor/momentjs:moment"; + +dataDailyModelCycle = function (plotParams, plotFunction) { + // initialize variables common to all curves + const appParams = { + plotType: matsTypes.PlotTypes.dailyModelCycle, + matching: plotParams.plotAction === matsTypes.PlotActions.matched, + completeness: plotParams.completeness, + outliers: plotParams.outliers, + hideGaps: plotParams.noGapsCheck, + hasLevels: false, + }; + const dataRequests = {}; // used to store data queries + let dataFoundForCurve = true; + let dataFoundForAnyCurve = false; + const totalProcessingStart = moment(); + const dateRange = matsDataUtils.getDateRange(plotParams.dates); + const fromSecs = dateRange.fromSeconds; + const toSecs = dateRange.toSeconds; + let error = ""; + const curves = JSON.parse(JSON.stringify(plotParams.curves)); + const curvesLength = curves.length; + const dataset = []; + const utcCycleStarts = []; + const axisMap = Object.create(null); + let xmax = -1 * Number.MAX_VALUE; + let ymax = -1 * Number.MAX_VALUE; + let xmin = Number.MAX_VALUE; + let ymin = Number.MAX_VALUE; + const idealValues = []; + + for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) { + // initialize variables specific to each curve + const curve = curves[curveIndex]; + const { diffFrom } = curve; + const { label } = curve; + const model = matsCollections["data-source"].findOne({ name: "data-source" }) + .optionsMap[curve["data-source"]][0]; + var regionStr = curve.region; + const region = Object.keys( + matsCollections.region.findOne({ name: "region" }).valuesMap + ).find( + (key) => + matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr + ); + const source = curve.truth; + let sourceStr = ""; + if (source !== "All") { + sourceStr = `_${source}`; + } + const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var thresholdStr = curve.threshold; + const threshold = Object.keys( + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + ).find( + (key) => + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === + thresholdStr + ); + const thresholdClause = `and m0.thresh = ${threshold}`; + if (curve["utc-cycle-start"].length !== 1) { + throw new Error( + "INFO: Please select exactly one UTC Cycle Init Hour for this plot type." + ); + } + const utcCycleStart = Number(curve["utc-cycle-start"][0]); + utcCycleStarts[curveIndex] = utcCycleStart; + const utcCycleStartClause = `and floor((m0.valid_time - m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`; + const forecastLengthClause = "and m0.fcst_len < 24"; + const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + const statisticSelect = curve.statistic; + const statisticOptionsMap = matsCollections.statistic.findOne( + { name: "statistic" }, + { optionsMap: 1 } + ).optionsMap; + const statisticClause = + "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + // axisKey is used to determine which axis a curve should use. + // This axisKeySet object is used like a set and if a curve has the same + // units (axisKey) it will use the same axis. + // The axis number is assigned to the axisKeySet value, which is the axisKey. + var statType = statisticOptionsMap[statisticSelect][0]; + const axisKey = statisticOptionsMap[statisticSelect][1]; + curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options + const idealVal = statisticOptionsMap[statisticSelect][2]; + if (idealVal !== null && idealValues.indexOf(idealVal) === -1) { + idealValues.push(idealVal); + } + + var d; + if (!diffFrom) { + // this is a database driven curve, not a difference curve + // prepare the query from the above parameters + let statement = + "select m0.valid_time as avtime, " + + "count(distinct m0.valid_time) as N_times, " + + "min(m0.valid_time) as min_secs, " + + "max(m0.valid_time) as max_secs, " + + "{{statisticClause}} " + + "{{queryTableClause}} " + + "where 1=1 " + + "{{dateClause}} " + + "{{utcCycleStartClause}} " + + "{{thresholdClause}} " + + "{{forecastLengthClause}} " + + "group by avtime " + + "order by avtime" + + ";"; + + statement = statement.replace("{{statisticClause}}", statisticClause); + statement = statement.replace("{{queryTableClause}}", queryTableClause); + statement = statement.replace("{{thresholdClause}}", thresholdClause); + statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause); + statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause); + statement = statement.replace("{{dateClause}}", dateClause); + dataRequests[label] = statement; + + var queryResult; + const startMoment = moment(); + var finishMoment; + try { + // send the query statement to the query function + queryResult = matsDataQueryUtils.queryDBSpecialtyCurve( + sumPool, + statement, + appParams, + statisticSelect + ); + finishMoment = moment(); + dataRequests[`data retrieval (query) time - ${label}`] = { + begin: startMoment.format(), + finish: finishMoment.format(), + duration: `${moment + .duration(finishMoment.diff(startMoment)) + .asSeconds()} seconds`, + recordCount: queryResult.data.x.length, + }; + // get the data back from the query + d = queryResult.data; + } catch (e) { + // this is an error produced by a bug in the query function, not an error returned by the mysql database + e.message = `Error in queryDB: ${e.message} for statement: ${statement}`; + throw new Error(e.message); + } + if (queryResult.error !== undefined && queryResult.error !== "") { + if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) { + // this is NOT an error just a no data condition + dataFoundForCurve = false; + } else { + // this is an error returned by the mysql database + error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; + throw new Error(error); + } + } else { + dataFoundForAnyCurve = true; + } + + // set axis limits based on returned data + var postQueryStartMoment = moment(); + if (dataFoundForCurve) { + xmin = xmin < d.xmin ? xmin : d.xmin; + xmax = xmax > d.xmax ? xmax : d.xmax; + ymin = ymin < d.ymin ? ymin : d.ymin; + ymax = ymax > d.ymax ? ymax : d.ymax; + } + } else { + // this is a difference curve + const diffResult = matsDataDiffUtils.getDataForDiffCurve( + dataset, + diffFrom, + appParams, + statType === "ctc", + statType === "scalar" + ); + d = diffResult.dataset; + xmin = xmin < d.xmin ? xmin : d.xmin; + xmax = xmax > d.xmax ? xmax : d.xmax; + ymin = ymin < d.ymin ? ymin : d.ymin; + ymax = ymax > d.ymax ? ymax : d.ymax; + } + + // set curve annotation to be the curve mean -- may be recalculated later + // also pass previously calculated axis stats to curve options + const mean = d.sum / d.x.length; + const annotation = + mean === undefined + ? `${label}- mean = NoData` + : `${label}- mean = ${mean.toPrecision(4)}`; + curve.annotation = annotation; + curve.xmin = d.xmin; + curve.xmax = d.xmax; + curve.ymin = d.ymin; + curve.ymax = d.ymax; + curve.axisKey = axisKey; + const cOptions = matsDataCurveOpsUtils.generateSeriesCurveOptions( + curve, + curveIndex, + axisMap, + d, + appParams + ); // generate plot with data, curve annotation, axis labels, etc. + dataset.push(cOptions); + const postQueryFinishMoment = moment(); + dataRequests[`post data retrieval (query) process time - ${label}`] = { + begin: postQueryStartMoment.format(), + finish: postQueryFinishMoment.format(), + duration: `${moment + .duration(postQueryFinishMoment.diff(postQueryStartMoment)) + .asSeconds()} seconds`, + }; + } // end for curves + + if (!dataFoundForAnyCurve) { + // we found no data for any curves so don't bother proceeding + throw new Error("INFO: No valid data for any curves."); + } + + // process the data returned by the query + const curveInfoParams = { + curves, + curvesLength, + idealValues, + utcCycleStarts, + statType, + axisMap, + xmax, + xmin, + }; + const bookkeepingParams = { + dataRequests, + totalProcessingStart, + }; + const result = matsDataProcessUtils.processDataXYCurve( + dataset, + appParams, + curveInfoParams, + plotParams, + bookkeepingParams + ); + plotFunction(result); +}; diff --git a/apps/ensemble/server/dataFunctions/data_dieoff.js b/apps/ensemble/server/dataFunctions/data_dieoff.js new file mode 100644 index 0000000000..9a61398c19 --- /dev/null +++ b/apps/ensemble/server/dataFunctions/data_dieoff.js @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +import { + matsCollections, + matsTypes, + matsDataUtils, + matsDataQueryUtils, + matsDataDiffUtils, + matsDataCurveOpsUtils, + matsDataProcessUtils, +} from "meteor/randyp:mats-common"; +import { moment } from "meteor/momentjs:moment"; + +dataDieOff = function (plotParams, plotFunction) { + // initialize variables common to all curves + const appParams = { + plotType: matsTypes.PlotTypes.dieoff, + matching: plotParams.plotAction === matsTypes.PlotActions.matched, + completeness: plotParams.completeness, + outliers: plotParams.outliers, + hideGaps: plotParams.noGapsCheck, + hasLevels: false, + }; + const dataRequests = {}; // used to store data queries + let dataFoundForCurve = true; + let dataFoundForAnyCurve = false; + const totalProcessingStart = moment(); + let error = ""; + const curves = JSON.parse(JSON.stringify(plotParams.curves)); + const curvesLength = curves.length; + const dataset = []; + const utcCycleStarts = []; + const axisMap = Object.create(null); + let xmax = -1 * Number.MAX_VALUE; + let ymax = -1 * Number.MAX_VALUE; + let xmin = Number.MAX_VALUE; + let ymin = Number.MAX_VALUE; + const idealValues = []; + + for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) { + // initialize variables specific to each curve + const curve = curves[curveIndex]; + const { diffFrom } = curve; + const { label } = curve; + const model = matsCollections["data-source"].findOne({ name: "data-source" }) + .optionsMap[curve["data-source"]][0]; + var regionStr = curve.region; + const region = Object.keys( + matsCollections.region.findOne({ name: "region" }).valuesMap + ).find( + (key) => + matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr + ); + const source = curve.truth; + let sourceStr = ""; + if (source !== "All") { + sourceStr = `_${source}`; + } + const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var thresholdStr = curve.threshold; + const threshold = Object.keys( + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + ).find( + (key) => + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === + thresholdStr + ); + const thresholdClause = `and m0.thresh = ${threshold}`; + var validTimes; + let validTimeClause = ""; + var utcCycleStart; + let utcCycleStartClause = ""; + const forecastLengthStr = curve["dieoff-type"]; + const forecastLengthOptionsMap = matsCollections["dieoff-type"].findOne( + { name: "dieoff-type" }, + { optionsMap: 1 } + ).optionsMap; + const forecastLength = forecastLengthOptionsMap[forecastLengthStr][0]; + const forecastLengthClause = ""; + const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]); + const fromSecs = dateRange.fromSeconds; + const toSecs = dateRange.toSeconds; + var dateClause; + if (forecastLength === matsTypes.ForecastTypes.dieoff) { + validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; + if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) { + validTimeClause = `and floor((m0.valid_time)%(24*3600)/3600) IN(${validTimes})`; + } + dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + } else if (forecastLength === matsTypes.ForecastTypes.utcCycle) { + utcCycleStart = + curve["utc-cycle-start"] === undefined ? [] : curve["utc-cycle-start"]; + if (utcCycleStart.length !== 0 && utcCycleStart !== matsTypes.InputTypes.unused) { + utcCycleStartClause = `and floor(((m0.valid_time) - m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`; // adjust by 1800 seconds to center obs at the top of the hour + } + dateClause = `and m0.valid_time-m0.fcst_len*3600 >= ${fromSecs} and m0.valid_time-m0.fcst_len*3600 <= ${toSecs}`; + } else { + dateClause = `and m0.valid_time-m0.fcst_len*3600 = ${fromSecs}`; + } + const statisticSelect = curve.statistic; + const statisticOptionsMap = matsCollections.statistic.findOne( + { name: "statistic" }, + { optionsMap: 1 } + ).optionsMap; + const statisticClause = + "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + // axisKey is used to determine which axis a curve should use. + // This axisKeySet object is used like a set and if a curve has the same + // units (axisKey) it will use the same axis. + // The axis number is assigned to the axisKeySet value, which is the axisKey. + var statType = statisticOptionsMap[statisticSelect][0]; + const axisKey = statisticOptionsMap[statisticSelect][1]; + curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options + const idealVal = statisticOptionsMap[statisticSelect][2]; + if (idealVal !== null && idealValues.indexOf(idealVal) === -1) { + idealValues.push(idealVal); + } + + var d; + if (!diffFrom) { + // this is a database driven curve, not a difference curve + // prepare the query from the above parameters + let statement = + "select m0.fcst_len as fcst_lead, " + + "count(distinct m0.valid_time) as N_times, " + + "min(m0.valid_time) as min_secs, " + + "max(m0.valid_time) as max_secs, " + + "{{statisticClause}} " + + "{{queryTableClause}} " + + "where 1=1 " + + "{{dateClause}} " + + "{{thresholdClause}} " + + "{{validTimeClause}} " + + "{{forecastLengthClause}} " + + "{{utcCycleStartClause}} " + + "group by fcst_lead " + + "order by fcst_lead" + + ";"; + + statement = statement.replace("{{statisticClause}}", statisticClause); + statement = statement.replace("{{queryTableClause}}", queryTableClause); + statement = statement.replace("{{thresholdClause}}", thresholdClause); + statement = statement.replace("{{validTimeClause}}", validTimeClause); + statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause); + statement = statement.replace("{{utcCycleStartClause}}", utcCycleStartClause); + statement = statement.replace("{{dateClause}}", dateClause); + dataRequests[label] = statement; + + var queryResult; + const startMoment = moment(); + var finishMoment; + try { + // send the query statement to the query function + queryResult = matsDataQueryUtils.queryDBSpecialtyCurve( + sumPool, + statement, + appParams, + statisticSelect + ); + finishMoment = moment(); + dataRequests[`data retrieval (query) time - ${label}`] = { + begin: startMoment.format(), + finish: finishMoment.format(), + duration: `${moment + .duration(finishMoment.diff(startMoment)) + .asSeconds()} seconds`, + recordCount: queryResult.data.x.length, + }; + // get the data back from the query + d = queryResult.data; + } catch (e) { + // this is an error produced by a bug in the query function, not an error returned by the mysql database + e.message = `Error in queryDB: ${e.message} for statement: ${statement}`; + throw new Error(e.message); + } + if (queryResult.error !== undefined && queryResult.error !== "") { + if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) { + // this is NOT an error just a no data condition + dataFoundForCurve = false; + } else { + // this is an error returned by the mysql database + error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; + throw new Error(error); + } + } else { + dataFoundForAnyCurve = true; + } + + // set axis limits based on returned data + var postQueryStartMoment = moment(); + if (dataFoundForCurve) { + xmin = xmin < d.xmin ? xmin : d.xmin; + xmax = xmax > d.xmax ? xmax : d.xmax; + ymin = ymin < d.ymin ? ymin : d.ymin; + ymax = ymax > d.ymax ? ymax : d.ymax; + } + } else { + // this is a difference curve + const diffResult = matsDataDiffUtils.getDataForDiffCurve( + dataset, + diffFrom, + appParams, + statType === "ctc", + statType === "scalar" + ); + d = diffResult.dataset; + xmin = xmin < d.xmin ? xmin : d.xmin; + xmax = xmax > d.xmax ? xmax : d.xmax; + ymin = ymin < d.ymin ? ymin : d.ymin; + ymax = ymax > d.ymax ? ymax : d.ymax; + } + + // set curve annotation to be the curve mean -- may be recalculated later + // also pass previously calculated axis stats to curve options + const mean = d.sum / d.x.length; + const annotation = + mean === undefined + ? `${label}- mean = NoData` + : `${label}- mean = ${mean.toPrecision(4)}`; + curve.annotation = annotation; + curve.xmin = d.xmin; + curve.xmax = d.xmax; + curve.ymin = d.ymin; + curve.ymax = d.ymax; + curve.axisKey = axisKey; + const cOptions = matsDataCurveOpsUtils.generateSeriesCurveOptions( + curve, + curveIndex, + axisMap, + d, + appParams + ); // generate plot with data, curve annotation, axis labels, etc. + dataset.push(cOptions); + const postQueryFinishMoment = moment(); + dataRequests[`post data retrieval (query) process time - ${label}`] = { + begin: postQueryStartMoment.format(), + finish: postQueryFinishMoment.format(), + duration: `${moment + .duration(postQueryFinishMoment.diff(postQueryStartMoment)) + .asSeconds()} seconds`, + }; + } // end for curves + + if (!dataFoundForAnyCurve) { + // we found no data for any curves so don't bother proceeding + throw new Error("INFO: No valid data for any curves."); + } + + // process the data returned by the query + const curveInfoParams = { + curves, + curvesLength, + idealValues, + utcCycleStarts, + statType, + axisMap, + xmax, + xmin, + }; + const bookkeepingParams = { + dataRequests, + totalProcessingStart, + }; + const result = matsDataProcessUtils.processDataXYCurve( + dataset, + appParams, + curveInfoParams, + plotParams, + bookkeepingParams + ); + plotFunction(result); +}; diff --git a/apps/ensemble/server/dataFunctions/data_histogram.js b/apps/ensemble/server/dataFunctions/data_histogram.js new file mode 100644 index 0000000000..08e43cd2e6 --- /dev/null +++ b/apps/ensemble/server/dataFunctions/data_histogram.js @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +import { + matsCollections, + matsTypes, + matsDataUtils, + matsDataQueryUtils, + matsDataProcessUtils, +} from "meteor/randyp:mats-common"; +import { moment } from "meteor/momentjs:moment"; + +dataHistogram = function (plotParams, plotFunction) { + // initialize variables common to all curves + const appParams = { + plotType: matsTypes.PlotTypes.histogram, + matching: plotParams.plotAction === matsTypes.PlotActions.matched, + completeness: plotParams.completeness, + outliers: plotParams.outliers, + hideGaps: plotParams.noGapsCheck, + hasLevels: false, + }; + const alreadyMatched = false; + const dataRequests = {}; // used to store data queries + const dataFoundForCurve = []; + let dataFoundForAnyCurve = false; + const totalProcessingStart = moment(); + let error = ""; + const curves = JSON.parse(JSON.stringify(plotParams.curves)); + const curvesLength = curves.length; + const dataset = []; + const allReturnedSubStats = []; + const allReturnedSubSecs = []; + const axisMap = Object.create(null); + + // process user bin customizations + const binParams = matsDataUtils.setHistogramParameters(plotParams); + const { yAxisFormat } = binParams; + const { binNum } = binParams; + + for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) { + // initialize variables specific to each curve + const curve = curves[curveIndex]; + const { diffFrom } = curve; + dataFoundForCurve[curveIndex] = true; + const { label } = curve; + const model = matsCollections["data-source"].findOne({ name: "data-source" }) + .optionsMap[curve["data-source"]][0]; + var regionStr = curve.region; + const region = Object.keys( + matsCollections.region.findOne({ name: "region" }).valuesMap + ).find( + (key) => + matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr + ); + const source = curve.truth; + let sourceStr = ""; + if (source !== "All") { + sourceStr = `_${source}`; + } + const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var thresholdStr = curve.threshold; + const threshold = Object.keys( + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + ).find( + (key) => + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === + thresholdStr + ); + const thresholdClause = `and m0.thresh = ${threshold}`; + let validTimeClause = ""; + const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; + if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) { + validTimeClause = `and floor((m0.valid_time)%(24*3600)/3600) IN(${validTimes})`; + } + const forecastLength = curve["forecast-length"]; + const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; + const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]); + const fromSecs = dateRange.fromSeconds; + const toSecs = dateRange.toSeconds; + const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + const statisticSelect = curve.statistic; + const statisticOptionsMap = matsCollections.statistic.findOne( + { name: "statistic" }, + { optionsMap: 1 } + ).optionsMap; + const statisticClause = + "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + // axisKey is used to determine which axis a curve should use. + // This axisKeySet object is used like a set and if a curve has the same + // units (axisKey) it will use the same axis. + // The axis number is assigned to the axisKeySet value, which is the axisKey. + var statType = statisticOptionsMap[statisticSelect][0]; + var varUnits = statisticOptionsMap[statisticSelect][1]; + let axisKey = yAxisFormat; + if (yAxisFormat === "Relative frequency") { + axisKey += " (x100)"; + } + curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options + curves[curveIndex].binNum = binNum; // stash the binNum to use it later for bar chart options + + var d; + if (!diffFrom) { + // this is a database driven curve, not a difference curve + // prepare the query from the above parameters + let statement = + "select m0.valid_time as avtime, " + + "count(distinct m0.valid_time) as N_times, " + + "min(m0.valid_time) as min_secs, " + + "max(m0.valid_time) as max_secs, " + + "{{statisticClause}} " + + "{{queryTableClause}} " + + "where 1=1 " + + "{{dateClause}} " + + "{{thresholdClause}} " + + "{{validTimeClause}} " + + "{{forecastLengthClause}} " + + "group by avtime " + + "order by avtime" + + ";"; + + statement = statement.replace("{{statisticClause}}", statisticClause); + statement = statement.replace("{{queryTableClause}}", queryTableClause); + statement = statement.replace("{{thresholdClause}}", thresholdClause); + statement = statement.replace("{{validTimeClause}}", validTimeClause); + statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause); + statement = statement.replace("{{dateClause}}", dateClause); + dataRequests[label] = statement; + + var queryResult; + const startMoment = moment(); + var finishMoment; + try { + // send the query statement to the query function + queryResult = matsDataQueryUtils.queryDBSpecialtyCurve( + sumPool, + statement, + appParams, + statisticSelect + ); + finishMoment = moment(); + dataRequests[`data retrieval (query) time - ${label}`] = { + begin: startMoment.format(), + finish: finishMoment.format(), + duration: `${moment + .duration(finishMoment.diff(startMoment)) + .asSeconds()} seconds`, + recordCount: queryResult.data.x.length, + }; + // get the data back from the query + d = queryResult.data; + allReturnedSubStats.push(d.subVals); // save returned data so that we can calculate histogram stats once all the queries are done + allReturnedSubSecs.push(d.subSecs); + } catch (e) { + // this is an error produced by a bug in the query function, not an error returned by the mysql database + e.message = `Error in queryDB: ${e.message} for statement: ${statement}`; + throw new Error(e.message); + } + if (queryResult.error !== undefined && queryResult.error !== "") { + if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) { + // this is NOT an error just a no data condition + dataFoundForCurve[curveIndex] = false; + } else { + // this is an error returned by the mysql database + error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; + throw new Error(error); + } + } else { + dataFoundForAnyCurve = true; + } + } + } + + if (!dataFoundForAnyCurve) { + // we found no data for any curves so don't bother proceeding + throw new Error("INFO: No valid data for any curves."); + } + + // process the data returned by the query + const curveInfoParams = { + curves, + curvesLength, + dataFoundForCurve, + statType, + axisMap, + yAxisFormat, + varUnits, + }; + const bookkeepingParams = { + alreadyMatched, + dataRequests, + totalProcessingStart, + }; + const result = matsDataProcessUtils.processDataHistogram( + allReturnedSubStats, + allReturnedSubSecs, + [], + dataset, + appParams, + curveInfoParams, + plotParams, + binParams, + bookkeepingParams + ); + plotFunction(result); +}; diff --git a/apps/ensemble/server/dataFunctions/data_perfDiagram.js b/apps/ensemble/server/dataFunctions/data_perfDiagram.js new file mode 100644 index 0000000000..12c3fb5d20 --- /dev/null +++ b/apps/ensemble/server/dataFunctions/data_perfDiagram.js @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +import { + matsCollections, + matsTypes, + matsDataUtils, + matsDataQueryUtils, + matsDataCurveOpsUtils, + matsDataProcessUtils, +} from "meteor/randyp:mats-common"; +import { moment } from "meteor/momentjs:moment"; + +dataPerformanceDiagram = function (plotParams, plotFunction) { + // initialize variables common to all curves + const appParams = { + plotType: matsTypes.PlotTypes.performanceDiagram, + matching: plotParams.plotAction === matsTypes.PlotActions.matched, + completeness: plotParams.completeness, + outliers: plotParams.outliers, + hideGaps: plotParams.noGapsCheck, + hasLevels: false, + }; + const dataRequests = {}; // used to store data queries + let dataFoundForCurve = true; + let dataFoundForAnyCurve = false; + const totalProcessingStart = moment(); + let error = ""; + const curves = JSON.parse(JSON.stringify(plotParams.curves)); + const curvesLength = curves.length; + const dataset = []; + const axisMap = Object.create(null); + let xmax = -1 * Number.MAX_VALUE; + let ymax = -1 * Number.MAX_VALUE; + let xmin = Number.MAX_VALUE; + let ymin = Number.MAX_VALUE; + + for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) { + // initialize variables specific to each curve + const curve = curves[curveIndex]; + const { diffFrom } = curve; + const { label } = curve; + const binParam = curve["bin-parameter"]; + const binClause = matsCollections["bin-parameter"].findOne({ + name: "bin-parameter", + }).optionsMap[binParam]; + const model = matsCollections["data-source"].findOne({ name: "data-source" }) + .optionsMap[curve["data-source"]][0]; + var regionStr = curve.region; + const region = Object.keys( + matsCollections.region.findOne({ name: "region" }).valuesMap + ).find( + (key) => + matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr + ); + const source = curve.truth; + let sourceStr = ""; + if (source !== "All") { + sourceStr = `_${source}`; + } + const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + let thresholdClause = ""; + let validTimeClause = ""; + let forecastLengthClause = ""; + const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]); + const fromSecs = dateRange.fromSeconds; + const toSecs = dateRange.toSeconds; + let dateString = ""; + let dateClause = ""; + if (binParam !== "Threshold") { + var thresholdStr = curve.threshold; + if (thresholdStr === undefined) { + throw new Error( + `INFO: ${label}'s threshold is undefined. Please assign it a value.` + ); + } + const threshold = Object.keys( + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + ).find( + (key) => + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === + thresholdStr + ); + thresholdClause = `and m0.thresh = ${threshold}`; + } + if (binParam !== "Valid UTC hour") { + const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; + if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) { + validTimeClause = `and m0.valid_time%(24*3600)/3600 IN(${validTimes})`; + } + } + if (binParam !== "Fcst lead time") { + const forecastLength = curve["forecast-length"]; + if (forecastLength === undefined) { + throw new Error( + `INFO: ${label}'s forecast lead time is undefined. Please assign it a value.` + ); + } + forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; + } + if (binParam === "Init Date") { + dateString = "m0.valid_time-m0.fcst_len*3600"; + } else { + dateString = "m0.valid_time"; + } + dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`; + const statisticSelect = "PerformanceDiagram"; + var statType = "ctc"; + // axisKey is used to determine which axis a curve should use. + // This axisKeySet object is used like a set and if a curve has the same + // variable + statistic (axisKey) it will use the same axis. + // The axis number is assigned to the axisKeySet value, which is the axisKey. + curves[curveIndex].axisKey = statisticSelect; // stash the axisKey to use it later for axis options + + var d; + if (!diffFrom) { + // this is a database driven curve, not a difference curve + // prepare the query from the above parameters + let statement = + "{{binClause}} " + + "count(distinct {{dateString}}) as N_times, " + + "min({{dateString}}) as min_secs, " + + "max({{dateString}}) as max_secs, " + + "((sum(m0.yy)+0.00)/sum(m0.yy+m0.ny)) as pod, ((sum(m0.yn)+0.00)/sum(m0.yn+m0.yy)) as far, " + + "sum(m0.yy+m0.ny) as oy_all, sum(m0.yn+m0.nn) as on_all, group_concat(m0.valid_time, ';', m0.yy, ';', " + + "m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0 " + + "{{queryTableClause}} " + + "where 1=1 " + + "{{dateClause}} " + + "{{thresholdClause}} " + + "{{validTimeClause}} " + + "{{forecastLengthClause}} " + + "group by binVal " + + "order by binVal" + + ";"; + + statement = statement.replace("{{binClause}}", binClause); + statement = statement.replace("{{queryTableClause}}", queryTableClause); + statement = statement.replace("{{thresholdClause}}", thresholdClause); + statement = statement.replace("{{validTimeClause}}", validTimeClause); + statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause); + statement = statement.replace("{{dateClause}}", dateClause); + statement = statement.split("{{dateString}}").join(dateString); + dataRequests[label] = statement; + + var queryResult; + const startMoment = moment(); + var finishMoment; + try { + // send the query statement to the query function + queryResult = matsDataQueryUtils.queryDBPerformanceDiagram( + sumPool, + statement, + appParams + ); + finishMoment = moment(); + dataRequests[`data retrieval (query) time - ${label}`] = { + begin: startMoment.format(), + finish: finishMoment.format(), + duration: `${moment + .duration(finishMoment.diff(startMoment)) + .asSeconds()} seconds`, + recordCount: queryResult.data.x.length, + }; + // get the data back from the query + d = queryResult.data; + } catch (e) { + // this is an error produced by a bug in the query function, not an error returned by the mysql database + e.message = `Error in queryDB: ${e.message} for statement: ${statement}`; + throw new Error(e.message); + } + if (queryResult.error !== undefined && queryResult.error !== "") { + if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) { + // this is NOT an error just a no data condition + dataFoundForCurve = false; + } else { + // this is an error returned by the mysql database + error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; + if (error.includes("ER_NO_SUCH_TABLE")) { + throw new Error( + `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` + + `Choose a different scale to continue using this region.` + ); + } else { + throw new Error(error); + } + } + } else { + dataFoundForAnyCurve = true; + } + + // set axis limits based on returned data + var postQueryStartMoment = moment(); + if (dataFoundForCurve) { + xmin = xmin < d.xmin ? xmin : d.xmin; + xmax = xmax > d.xmax ? xmax : d.xmax; + ymin = ymin < d.ymin ? ymin : d.ymin; + ymax = ymax > d.ymax ? ymax : d.ymax; + } + } else { + // this is a difference curve -- not supported for ROC plots + throw new Error( + "INFO: Difference curves are not supported for performance diagrams, as they do not feature consistent x or y values across all curves." + ); + } + + // set curve annotation to be the curve mean -- may be recalculated later + // also pass previously calculated axis stats to curve options + const mean = d.sum / d.x.length; + const annotation = + mean === undefined + ? `${label}- mean = NoData` + : `${label}- mean = ${mean.toPrecision(4)}`; + curve.annotation = annotation; + curve.xmin = d.xmin; + curve.xmax = d.xmax; + curve.ymin = d.ymin; + curve.ymax = d.ymax; + curve.axisKey = statisticSelect; + curve.binParam = binParam; + const cOptions = matsDataCurveOpsUtils.generateSeriesCurveOptions( + curve, + curveIndex, + axisMap, + d, + appParams + ); // generate plot with data, curve annotation, axis labels, etc. + dataset.push(cOptions); + const postQueryFinishMoment = moment(); + dataRequests[`post data retrieval (query) process time - ${label}`] = { + begin: postQueryStartMoment.format(), + finish: postQueryFinishMoment.format(), + duration: `${moment + .duration(postQueryFinishMoment.diff(postQueryStartMoment)) + .asSeconds()} seconds`, + }; + } // end for curves + + if (!dataFoundForAnyCurve) { + // we found no data for any curves so don't bother proceeding + throw new Error("INFO: No valid data for any curves."); + } + + // process the data returned by the query + const curveInfoParams = { + curves, + curvesLength, + statType, + axisMap, + xmax, + xmin, + }; + const bookkeepingParams = { + dataRequests, + totalProcessingStart, + }; + const result = matsDataProcessUtils.processDataPerformanceDiagram( + dataset, + appParams, + curveInfoParams, + plotParams, + bookkeepingParams + ); + plotFunction(result); +}; diff --git a/apps/ensemble/server/dataFunctions/data_series.js b/apps/ensemble/server/dataFunctions/data_series.js new file mode 100644 index 0000000000..7a929ba26b --- /dev/null +++ b/apps/ensemble/server/dataFunctions/data_series.js @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +import { + matsCollections, + matsTypes, + matsDataUtils, + matsDataQueryUtils, + matsDataDiffUtils, + matsDataCurveOpsUtils, + matsDataProcessUtils, +} from "meteor/randyp:mats-common"; +import { moment } from "meteor/momentjs:moment"; + +dataSeries = function (plotParams, plotFunction) { + // initialize variables common to all curves + const appParams = { + plotType: matsTypes.PlotTypes.timeSeries, + matching: plotParams.plotAction === matsTypes.PlotActions.matched, + completeness: plotParams.completeness, + outliers: plotParams.outliers, + hideGaps: plotParams.noGapsCheck, + hasLevels: false, + }; + const dataRequests = {}; // used to store data queries + let dataFoundForCurve = true; + let dataFoundForAnyCurve = false; + const totalProcessingStart = moment(); + const dateRange = matsDataUtils.getDateRange(plotParams.dates); + const fromSecs = dateRange.fromSeconds; + const toSecs = dateRange.toSeconds; + let error = ""; + const curves = JSON.parse(JSON.stringify(plotParams.curves)); + const curvesLength = curves.length; + const dataset = []; + const utcCycleStarts = []; + const axisMap = Object.create(null); + let xmax = -1 * Number.MAX_VALUE; + let ymax = -1 * Number.MAX_VALUE; + let xmin = Number.MAX_VALUE; + let ymin = Number.MAX_VALUE; + const idealValues = []; + + for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) { + // initialize variables specific to each curve + const curve = curves[curveIndex]; + const { diffFrom } = curve; + const { label } = curve; + const model = matsCollections["data-source"].findOne({ name: "data-source" }) + .optionsMap[curve["data-source"]][0]; + var regionStr = curve.region; + const region = Object.keys( + matsCollections.region.findOne({ name: "region" }).valuesMap + ).find( + (key) => + matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr + ); + const source = curve.truth; + let sourceStr = ""; + if (source !== "All") { + sourceStr = `_${source}`; + } + const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var thresholdStr = curve.threshold; + const threshold = Object.keys( + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + ).find( + (key) => + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === + thresholdStr + ); + const thresholdClause = `and m0.thresh = ${threshold}`; + let validTimeClause = ""; + const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; + if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) { + validTimeClause = `and floor((m0.valid_time)%(24*3600)/3600) IN(${validTimes})`; + } + let forecastLength = curve["forecast-length"]; + const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; + const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + const averageStr = curve.average; + const averageOptionsMap = matsCollections.average.findOne( + { name: "average" }, + { optionsMap: 1 } + ).optionsMap; + const average = averageOptionsMap[averageStr][0]; + const statisticSelect = curve.statistic; + const statisticOptionsMap = matsCollections.statistic.findOne( + { name: "statistic" }, + { optionsMap: 1 } + ).optionsMap; + const statisticClause = + "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + // axisKey is used to determine which axis a curve should use. + // This axisKeySet object is used like a set and if a curve has the same + // units (axisKey) it will use the same axis. + // The axis number is assigned to the axisKeySet value, which is the axisKey. + var statType = statisticOptionsMap[statisticSelect][0]; + const axisKey = statisticOptionsMap[statisticSelect][1]; + curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options + const idealVal = statisticOptionsMap[statisticSelect][2]; + if (idealVal !== null && idealValues.indexOf(idealVal) === -1) { + idealValues.push(idealVal); + } + + var d; + if (!diffFrom) { + // this is a database driven curve, not a difference curve + // prepare the query from the above parameters + let statement = + "select {{average}} as avtime, " + + "count(distinct m0.valid_time) as N_times, " + + "min(m0.valid_time) as min_secs, " + + "max(m0.valid_time) as max_secs, " + + "{{statisticClause}} " + + "{{queryTableClause}} " + + "where 1=1 " + + "{{dateClause}} " + + "{{thresholdClause}} " + + "{{validTimeClause}} " + + "{{forecastLengthClause}} " + + "group by avtime " + + "order by avtime" + + ";"; + + statement = statement.replace("{{average}}", average); + statement = statement.replace("{{statisticClause}}", statisticClause); + statement = statement.replace("{{queryTableClause}}", queryTableClause); + statement = statement.replace("{{thresholdClause}}", thresholdClause); + statement = statement.replace("{{validTimeClause}}", validTimeClause); + statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause); + statement = statement.replace("{{dateClause}}", dateClause); + dataRequests[label] = statement; + + // math is done on forecastLength later on -- set all analyses to 0 + if (forecastLength === "-99") { + forecastLength = "0"; + } + + var queryResult; + const startMoment = moment(); + var finishMoment; + try { + // send the query statement to the query function + queryResult = matsDataQueryUtils.queryDBTimeSeries( + sumPool, + statement, + model, + forecastLength, + fromSecs, + toSecs, + averageStr, + statisticSelect, + validTimes, + appParams, + false + ); + finishMoment = moment(); + dataRequests[`data retrieval (query) time - ${label}`] = { + begin: startMoment.format(), + finish: finishMoment.format(), + duration: `${moment + .duration(finishMoment.diff(startMoment)) + .asSeconds()} seconds`, + recordCount: queryResult.data.x.length, + }; + // get the data back from the query + d = queryResult.data; + } catch (e) { + // this is an error produced by a bug in the query function, not an error returned by the mysql database + e.message = `Error in queryDB: ${e.message} for statement: ${statement}`; + throw new Error(e.message); + } + if (queryResult.error !== undefined && queryResult.error !== "") { + if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) { + // this is NOT an error just a no data condition + dataFoundForCurve = false; + } else { + // this is an error returned by the mysql database + error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; + throw new Error(error); + } + } else { + dataFoundForAnyCurve = true; + } + + // set axis limits based on returned data + var postQueryStartMoment = moment(); + if (dataFoundForCurve) { + xmin = xmin < d.xmin ? xmin : d.xmin; + xmax = xmax > d.xmax ? xmax : d.xmax; + ymin = ymin < d.ymin ? ymin : d.ymin; + ymax = ymax > d.ymax ? ymax : d.ymax; + } + } else { + // this is a difference curve + const diffResult = matsDataDiffUtils.getDataForDiffCurve( + dataset, + diffFrom, + appParams, + statType === "ctc", + statType === "scalar" + ); + d = diffResult.dataset; + xmin = xmin < d.xmin ? xmin : d.xmin; + xmax = xmax > d.xmax ? xmax : d.xmax; + ymin = ymin < d.ymin ? ymin : d.ymin; + ymax = ymax > d.ymax ? ymax : d.ymax; + } + + // set curve annotation to be the curve mean -- may be recalculated later + // also pass previously calculated axis stats to curve options + const mean = d.sum / d.x.length; + const annotation = + mean === undefined + ? `${label}- mean = NoData` + : `${label}- mean = ${mean.toPrecision(4)}`; + curve.annotation = annotation; + curve.xmin = d.xmin; + curve.xmax = d.xmax; + curve.ymin = d.ymin; + curve.ymax = d.ymax; + curve.axisKey = axisKey; + const cOptions = matsDataCurveOpsUtils.generateSeriesCurveOptions( + curve, + curveIndex, + axisMap, + d, + appParams + ); // generate plot with data, curve annotation, axis labels, etc. + dataset.push(cOptions); + const postQueryFinishMoment = moment(); + dataRequests[`post data retrieval (query) process time - ${label}`] = { + begin: postQueryStartMoment.format(), + finish: postQueryFinishMoment.format(), + duration: `${moment + .duration(postQueryFinishMoment.diff(postQueryStartMoment)) + .asSeconds()} seconds`, + }; + } // end for curves + + if (!dataFoundForAnyCurve) { + // we found no data for any curves so don't bother proceeding + throw new Error("INFO: No valid data for any curves."); + } + + // process the data returned by the query + const curveInfoParams = { + curves, + curvesLength, + idealValues, + utcCycleStarts, + statType, + axisMap, + xmax, + xmin, + }; + const bookkeepingParams = { + dataRequests, + totalProcessingStart, + }; + const result = matsDataProcessUtils.processDataXYCurve( + dataset, + appParams, + curveInfoParams, + plotParams, + bookkeepingParams + ); + plotFunction(result); +}; diff --git a/apps/ensemble/server/dataFunctions/data_threshold.js b/apps/ensemble/server/dataFunctions/data_threshold.js new file mode 100644 index 0000000000..1e8b3b36da --- /dev/null +++ b/apps/ensemble/server/dataFunctions/data_threshold.js @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +import { + matsCollections, + matsTypes, + matsDataUtils, + matsDataQueryUtils, + matsDataDiffUtils, + matsDataCurveOpsUtils, + matsDataProcessUtils, +} from "meteor/randyp:mats-common"; +import { moment } from "meteor/momentjs:moment"; + +dataThreshold = function (plotParams, plotFunction) { + // initialize variables common to all curves + const appParams = { + plotType: matsTypes.PlotTypes.threshold, + matching: plotParams.plotAction === matsTypes.PlotActions.matched, + completeness: plotParams.completeness, + outliers: plotParams.outliers, + hideGaps: plotParams.noGapsCheck, + hasLevels: false, + }; + const dataRequests = {}; // used to store data queries + let dataFoundForCurve = true; + let dataFoundForAnyCurve = false; + const totalProcessingStart = moment(); + let error = ""; + const curves = JSON.parse(JSON.stringify(plotParams.curves)); + const curvesLength = curves.length; + const dataset = []; + const utcCycleStarts = []; + const axisMap = Object.create(null); + let xmax = -1 * Number.MAX_VALUE; + let ymax = -1 * Number.MAX_VALUE; + let xmin = Number.MAX_VALUE; + let ymin = Number.MAX_VALUE; + const idealValues = []; + + for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) { + // initialize variables specific to each curve + const curve = curves[curveIndex]; + const { diffFrom } = curve; + const { label } = curve; + const model = matsCollections["data-source"].findOne({ name: "data-source" }) + .optionsMap[curve["data-source"]][0]; + var regionStr = curve.region; + const region = Object.keys( + matsCollections.region.findOne({ name: "region" }).valuesMap + ).find( + (key) => + matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr + ); + const source = curve.truth; + let sourceStr = ""; + if (source !== "All") { + sourceStr = `_${source}`; + } + const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + const thresholdClause = ""; + let validTimeClause = ""; + const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; + if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) { + validTimeClause = `and floor((m0.valid_time)%(24*3600)/3600) IN(${validTimes})`; + } + const forecastLength = curve["forecast-length"]; + const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; + const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]); + const fromSecs = dateRange.fromSeconds; + const toSecs = dateRange.toSeconds; + const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + const statisticSelect = curve.statistic; + const statisticOptionsMap = matsCollections.statistic.findOne( + { name: "statistic" }, + { optionsMap: 1 } + ).optionsMap; + const statisticClause = + "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + // axisKey is used to determine which axis a curve should use. + // This axisKeySet object is used like a set and if a curve has the same + // units (axisKey) it will use the same axis. + // The axis number is assigned to the axisKeySet value, which is the axisKey. + var statType = statisticOptionsMap[statisticSelect][0]; + const axisKey = statisticOptionsMap[statisticSelect][1]; + curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options + const idealVal = statisticOptionsMap[statisticSelect][2]; + if (idealVal !== null && idealValues.indexOf(idealVal) === -1) { + idealValues.push(idealVal); + } + + var d; + if (!diffFrom) { + // this is a database driven curve, not a difference curve + // prepare the query from the above parameters + let statement = + "select m0.thresh/100 as thresh, " + // produces thresholds in inches + "count(distinct m0.valid_time) as N_times, " + + "min(m0.valid_time) as min_secs, " + + "max(m0.valid_time) as max_secs, " + + "{{statisticClause}} " + + "{{queryTableClause}} " + + "where 1=1 " + + "{{dateClause}} " + + "{{thresholdClause}} " + + "{{validTimeClause}} " + + "{{forecastLengthClause}} " + + "group by thresh " + + "order by thresh" + + ";"; + + statement = statement.replace("{{statisticClause}}", statisticClause); + statement = statement.replace("{{queryTableClause}}", queryTableClause); + statement = statement.replace("{{thresholdClause}}", thresholdClause); + statement = statement.replace("{{validTimeClause}}", validTimeClause); + statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause); + statement = statement.replace("{{dateClause}}", dateClause); + dataRequests[label] = statement; + + var queryResult; + const startMoment = moment(); + var finishMoment; + try { + // send the query statement to the query function + queryResult = matsDataQueryUtils.queryDBSpecialtyCurve( + sumPool, + statement, + appParams, + statisticSelect + ); + finishMoment = moment(); + dataRequests[`data retrieval (query) time - ${label}`] = { + begin: startMoment.format(), + finish: finishMoment.format(), + duration: `${moment + .duration(finishMoment.diff(startMoment)) + .asSeconds()} seconds`, + recordCount: queryResult.data.x.length, + }; + // get the data back from the query + d = queryResult.data; + } catch (e) { + // this is an error produced by a bug in the query function, not an error returned by the mysql database + e.message = `Error in queryDB: ${e.message} for statement: ${statement}`; + throw new Error(e.message); + } + if (queryResult.error !== undefined && queryResult.error !== "") { + if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) { + // this is NOT an error just a no data condition + dataFoundForCurve = false; + } else { + // this is an error returned by the mysql database + error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; + throw new Error(error); + } + } else { + dataFoundForAnyCurve = true; + } + + // set axis limits based on returned data + var postQueryStartMoment = moment(); + if (dataFoundForCurve) { + xmin = xmin < d.xmin ? xmin : d.xmin; + xmax = xmax > d.xmax ? xmax : d.xmax; + ymin = ymin < d.ymin ? ymin : d.ymin; + ymax = ymax > d.ymax ? ymax : d.ymax; + } + } else { + // this is a difference curve + const diffResult = matsDataDiffUtils.getDataForDiffCurve( + dataset, + diffFrom, + appParams, + statType === "ctc", + statType === "scalar" + ); + d = diffResult.dataset; + xmin = xmin < d.xmin ? xmin : d.xmin; + xmax = xmax > d.xmax ? xmax : d.xmax; + ymin = ymin < d.ymin ? ymin : d.ymin; + ymax = ymax > d.ymax ? ymax : d.ymax; + } + + // set curve annotation to be the curve mean -- may be recalculated later + // also pass previously calculated axis stats to curve options + const mean = d.sum / d.x.length; + const annotation = + mean === undefined + ? `${label}- mean = NoData` + : `${label}- mean = ${mean.toPrecision(4)}`; + curve.annotation = annotation; + curve.xmin = d.xmin; + curve.xmax = d.xmax; + curve.ymin = d.ymin; + curve.ymax = d.ymax; + curve.axisKey = axisKey; + const cOptions = matsDataCurveOpsUtils.generateSeriesCurveOptions( + curve, + curveIndex, + axisMap, + d, + appParams + ); // generate plot with data, curve annotation, axis labels, etc. + dataset.push(cOptions); + const postQueryFinishMoment = moment(); + dataRequests[`post data retrieval (query) process time - ${label}`] = { + begin: postQueryStartMoment.format(), + finish: postQueryFinishMoment.format(), + duration: `${moment + .duration(postQueryFinishMoment.diff(postQueryStartMoment)) + .asSeconds()} seconds`, + }; + } // end for curves + + if (!dataFoundForAnyCurve) { + // we found no data for any curves so don't bother proceeding + throw new Error("INFO: No valid data for any curves."); + } + + // process the data returned by the query + const curveInfoParams = { + curves, + curvesLength, + idealValues, + utcCycleStarts, + statType, + axisMap, + xmax, + xmin, + }; + const bookkeepingParams = { + dataRequests, + totalProcessingStart, + }; + const result = matsDataProcessUtils.processDataXYCurve( + dataset, + appParams, + curveInfoParams, + plotParams, + bookkeepingParams + ); + plotFunction(result); +}; diff --git a/apps/ensemble/server/dataFunctions/data_validtime.js b/apps/ensemble/server/dataFunctions/data_validtime.js new file mode 100644 index 0000000000..6df0ed4397 --- /dev/null +++ b/apps/ensemble/server/dataFunctions/data_validtime.js @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +import { + matsCollections, + matsTypes, + matsDataUtils, + matsDataQueryUtils, + matsDataDiffUtils, + matsDataCurveOpsUtils, + matsDataProcessUtils, +} from "meteor/randyp:mats-common"; +import { moment } from "meteor/momentjs:moment"; + +dataValidTime = function (plotParams, plotFunction) { + // initialize variables common to all curves + const appParams = { + plotType: matsTypes.PlotTypes.validtime, + matching: plotParams.plotAction === matsTypes.PlotActions.matched, + completeness: plotParams.completeness, + outliers: plotParams.outliers, + hideGaps: plotParams.noGapsCheck, + hasLevels: false, + }; + const dataRequests = {}; // used to store data queries + let dataFoundForCurve = true; + let dataFoundForAnyCurve = false; + const totalProcessingStart = moment(); + let error = ""; + const curves = JSON.parse(JSON.stringify(plotParams.curves)); + const curvesLength = curves.length; + const dataset = []; + const utcCycleStarts = []; + const axisMap = Object.create(null); + let xmax = -1 * Number.MAX_VALUE; + let ymax = -1 * Number.MAX_VALUE; + let xmin = Number.MAX_VALUE; + let ymin = Number.MAX_VALUE; + const idealValues = []; + + for (let curveIndex = 0; curveIndex < curvesLength; curveIndex++) { + // initialize variables specific to each curve + const curve = curves[curveIndex]; + const { diffFrom } = curve; + const { label } = curve; + const model = matsCollections["data-source"].findOne({ name: "data-source" }) + .optionsMap[curve["data-source"]][0]; + var regionStr = curve.region; + const region = Object.keys( + matsCollections.region.findOne({ name: "region" }).valuesMap + ).find( + (key) => + matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr + ); + const source = curve.truth; + let sourceStr = ""; + if (source !== "All") { + sourceStr = `_${source}`; + } + const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var thresholdStr = curve.threshold; + const threshold = Object.keys( + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + ).find( + (key) => + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === + thresholdStr + ); + const thresholdClause = `and m0.thresh = ${threshold}`; + const forecastLength = curve["forecast-length"]; + const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; + const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]); + const fromSecs = dateRange.fromSeconds; + const toSecs = dateRange.toSeconds; + const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + const statisticSelect = curve.statistic; + const statisticOptionsMap = matsCollections.statistic.findOne( + { name: "statistic" }, + { optionsMap: 1 } + ).optionsMap; + const statisticClause = + "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + // axisKey is used to determine which axis a curve should use. + // This axisKeySet object is used like a set and if a curve has the same + // units (axisKey) it will use the same axis. + // The axis number is assigned to the axisKeySet value, which is the axisKey. + var statType = statisticOptionsMap[statisticSelect][0]; + const axisKey = statisticOptionsMap[statisticSelect][1]; + curves[curveIndex].axisKey = axisKey; // stash the axisKey to use it later for axis options + const idealVal = statisticOptionsMap[statisticSelect][2]; + if (idealVal !== null && idealValues.indexOf(idealVal) === -1) { + idealValues.push(idealVal); + } + + var d; + if (!diffFrom) { + // this is a database driven curve, not a difference curve + // prepare the query from the above parameters + let statement = + "select floor(m0.valid_time%(24*3600)/3600) as hr_of_day, " + + "count(distinct m0.valid_time) as N_times, " + + "min(m0.valid_time) as min_secs, " + + "max(m0.valid_time) as max_secs, " + + "{{statisticClause}} " + + "{{queryTableClause}} " + + "where 1=1 " + + "{{dateClause}} " + + "{{thresholdClause}} " + + "{{forecastLengthClause}} " + + "group by hr_of_day " + + "order by hr_of_day" + + ";"; + + statement = statement.replace("{{statisticClause}}", statisticClause); + statement = statement.replace("{{queryTableClause}}", queryTableClause); + statement = statement.replace("{{thresholdClause}}", thresholdClause); + statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause); + statement = statement.replace("{{dateClause}}", dateClause); + dataRequests[label] = statement; + + var queryResult; + const startMoment = moment(); + var finishMoment; + try { + // send the query statement to the query function + queryResult = matsDataQueryUtils.queryDBSpecialtyCurve( + sumPool, + statement, + appParams, + statisticSelect + ); + finishMoment = moment(); + dataRequests[`data retrieval (query) time - ${label}`] = { + begin: startMoment.format(), + finish: finishMoment.format(), + duration: `${moment + .duration(finishMoment.diff(startMoment)) + .asSeconds()} seconds`, + recordCount: queryResult.data.x.length, + }; + // get the data back from the query + d = queryResult.data; + } catch (e) { + // this is an error produced by a bug in the query function, not an error returned by the mysql database + e.message = `Error in queryDB: ${e.message} for statement: ${statement}`; + throw new Error(e.message); + } + if (queryResult.error !== undefined && queryResult.error !== "") { + if (queryResult.error === matsTypes.Messages.NO_DATA_FOUND) { + // this is NOT an error just a no data condition + dataFoundForCurve = false; + } else { + // this is an error returned by the mysql database + error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; + throw new Error(error); + } + } else { + dataFoundForAnyCurve = true; + } + + // set axis limits based on returned data + var postQueryStartMoment = moment(); + if (dataFoundForCurve) { + xmin = xmin < d.xmin ? xmin : d.xmin; + xmax = xmax > d.xmax ? xmax : d.xmax; + ymin = ymin < d.ymin ? ymin : d.ymin; + ymax = ymax > d.ymax ? ymax : d.ymax; + } + } else { + // this is a difference curve + const diffResult = matsDataDiffUtils.getDataForDiffCurve( + dataset, + diffFrom, + appParams, + statType === "ctc", + statType === "scalar" + ); + d = diffResult.dataset; + xmin = xmin < d.xmin ? xmin : d.xmin; + xmax = xmax > d.xmax ? xmax : d.xmax; + ymin = ymin < d.ymin ? ymin : d.ymin; + ymax = ymax > d.ymax ? ymax : d.ymax; + } + + // set curve annotation to be the curve mean -- may be recalculated later + // also pass previously calculated axis stats to curve options + const mean = d.sum / d.x.length; + const annotation = + mean === undefined + ? `${label}- mean = NoData` + : `${label}- mean = ${mean.toPrecision(4)}`; + curve.annotation = annotation; + curve.xmin = d.xmin; + curve.xmax = d.xmax; + curve.ymin = d.ymin; + curve.ymax = d.ymax; + curve.axisKey = axisKey; + const cOptions = matsDataCurveOpsUtils.generateSeriesCurveOptions( + curve, + curveIndex, + axisMap, + d, + appParams + ); // generate plot with data, curve annotation, axis labels, etc. + dataset.push(cOptions); + const postQueryFinishMoment = moment(); + dataRequests[`post data retrieval (query) process time - ${label}`] = { + begin: postQueryStartMoment.format(), + finish: postQueryFinishMoment.format(), + duration: `${moment + .duration(postQueryFinishMoment.diff(postQueryStartMoment)) + .asSeconds()} seconds`, + }; + } // end for curves + + if (!dataFoundForAnyCurve) { + // we found no data for any curves so don't bother proceeding + throw new Error("INFO: No valid data for any curves."); + } + + // process the data returned by the query + const curveInfoParams = { + curves, + curvesLength, + idealValues, + utcCycleStarts, + statType, + axisMap, + xmax, + xmin, + }; + const bookkeepingParams = { + dataRequests, + totalProcessingStart, + }; + const result = matsDataProcessUtils.processDataXYCurve( + dataset, + appParams, + curveInfoParams, + plotParams, + bookkeepingParams + ); + plotFunction(result); +}; diff --git a/apps/ensemble/server/main.js b/apps/ensemble/server/main.js new file mode 100644 index 0000000000..498df19815 --- /dev/null +++ b/apps/ensemble/server/main.js @@ -0,0 +1,1451 @@ +/* + * Copyright (c) 2021 Colorado State University and Regents of the University of Colorado. All rights reserved. + */ + +import { Meteor } from "meteor/meteor"; +import { mysql } from "meteor/pcel:mysql"; +import { + matsTypes, + matsCollections, + matsDataUtils, + matsDataQueryUtils, + matsParamUtils, + matsCouchbaseUtils, +} from "meteor/randyp:mats-common"; + +// determined in doCurveParanms +let minDate; +let maxDate; +let dstr; + +const doPlotParams = function () { + if ( + matsCollections.Settings.findOne({}) === undefined || + matsCollections.Settings.findOne({}).resetFromCode === undefined || + matsCollections.Settings.findOne({}).resetFromCode === true + ) { + matsCollections.PlotParams.remove({}); + } + if (matsCollections.PlotParams.find().count() === 0) { + matsCollections.PlotParams.insert({ + name: "dates", + type: matsTypes.InputTypes.dateRange, + options: [""], + startDate: minDate, + stopDate: maxDate, + superiorNames: ["data-source"], + controlButtonCovered: true, + default: dstr, + controlButtonVisibility: "block", + displayOrder: 1, + displayPriority: 1, + displayGroup: 1, + help: "dateHelp.html", + }); + + const plotFormats = {}; + plotFormats[matsTypes.PlotFormats.matching] = "show matching diffs"; + plotFormats[matsTypes.PlotFormats.pairwise] = "pairwise diffs"; + plotFormats[matsTypes.PlotFormats.none] = "no diffs"; + matsCollections.PlotParams.insert({ + name: "plotFormat", + type: matsTypes.InputTypes.radioGroup, + optionsMap: plotFormats, + options: [ + matsTypes.PlotFormats.matching, + matsTypes.PlotFormats.pairwise, + matsTypes.PlotFormats.none, + ], + default: matsTypes.PlotFormats.none, + controlButtonCovered: false, + controlButtonVisibility: "block", + displayOrder: 1, + displayPriority: 1, + displayGroup: 3, + }); + + const yAxisOptionsMap = { + "Relative frequency": ["relFreq"], + Number: ["number"], + }; + matsCollections.PlotParams.insert({ + name: "histogram-yaxis-controls", + type: matsTypes.InputTypes.select, + optionsMap: yAxisOptionsMap, + options: Object.keys(yAxisOptionsMap), + default: Object.keys(yAxisOptionsMap)[0], + controlButtonCovered: true, + controlButtonText: "Y-axis mode", + displayOrder: 2, + displayPriority: 1, + displayGroup: 2, + }); + + const binOptionsMap = { + "Default bins": ["default"], + "Set number of bins": ["binNumber"], + "Make zero a bin bound": ["zeroBound"], + "Choose a bin bound": ["chooseBound"], + "Set number of bins and make zero a bin bound": ["binNumberWithZero"], + "Set number of bins and choose a bin bound": ["binNumberWithChosen"], + "Manual bins": ["manual"], + "Manual bin start, number, and stride": ["manualStride"], + }; + matsCollections.PlotParams.insert({ + name: "histogram-bin-controls", + type: matsTypes.InputTypes.select, + optionsMap: binOptionsMap, + options: Object.keys(binOptionsMap), + hideOtherFor: { + "bin-number": [ + "Default bins", + "Make zero a bin bound", + "Manual bins", + "Choose a bin bound", + ], + "bin-pivot": [ + "Default bins", + "Set number of bins", + "Make zero a bin bound", + "Set number of bins and make zero a bin bound", + "Manual bins", + "Manual bin start, number, and stride", + ], + "bin-start": [ + "Default bins", + "Set number of bins", + "Make zero a bin bound", + "Choose a bin bound", + "Set number of bins and make zero a bin bound", + "Set number of bins and choose a bin bound", + "Manual bins", + ], + "bin-stride": [ + "Default bins", + "Set number of bins", + "Make zero a bin bound", + "Choose a bin bound", + "Set number of bins and make zero a bin bound", + "Set number of bins and choose a bin bound", + "Manual bins", + ], + "bin-bounds": [ + "Default bins", + "Set number of bins", + "Make zero a bin bound", + "Choose a bin bound", + "Set number of bins and make zero a bin bound", + "Set number of bins and choose a bin bound", + "Manual bin start, number, and stride", + ], + }, + default: Object.keys(binOptionsMap)[0], + controlButtonCovered: true, + controlButtonText: "customize bins", + displayOrder: 3, + displayPriority: 1, + displayGroup: 2, + }); + + matsCollections.PlotParams.insert({ + name: "bin-number", + type: matsTypes.InputTypes.numberSpinner, + optionsMap: {}, + options: [], + min: "2", + max: "100", + step: "any", + default: "12", + controlButtonCovered: true, + controlButtonText: "number of bins", + displayOrder: 4, + displayPriority: 1, + displayGroup: 2, + }); + + matsCollections.PlotParams.insert({ + name: "bin-pivot", + type: matsTypes.InputTypes.numberSpinner, + optionsMap: {}, + options: [], + min: "-10000", + max: "10000", + step: "any", + default: "0", + controlButtonCovered: true, + controlButtonText: "bin pivot value", + displayOrder: 5, + displayPriority: 1, + displayGroup: 2, + }); + + matsCollections.PlotParams.insert({ + name: "bin-start", + type: matsTypes.InputTypes.numberSpinner, + optionsMap: {}, + options: [], + min: "-10000", + max: "10000", + step: "any", + default: "0", + controlButtonCovered: true, + controlButtonText: "bin start", + displayOrder: 6, + displayPriority: 1, + displayGroup: 2, + }); + + matsCollections.PlotParams.insert({ + name: "bin-stride", + type: matsTypes.InputTypes.numberSpinner, + optionsMap: {}, + options: [], + min: "-10000", + max: "10000", + step: "any", + default: "0", + controlButtonCovered: true, + controlButtonText: "bin stride", + displayOrder: 7, + displayPriority: 1, + displayGroup: 2, + }); + + matsCollections.PlotParams.insert({ + name: "bin-bounds", + type: matsTypes.InputTypes.textInput, + optionsMap: {}, + options: [], + default: " ", + controlButtonCovered: true, + controlButtonText: "bin bounds (Enter numbers separated by commas)", + displayOrder: 8, + displayPriority: 1, + displayGroup: 2, + }); + + const xOptionsMap = { + "Fcst lead time": "select m0.fcst_len as xVal, ", + Threshold: "select m0.thresh/100 as xVal, ", // produces thresholds in in + "Valid UTC hour": "select m0.valid_time%(24*3600)/3600 as xVal, ", + "Init UTC hour": + "select (m0.valid_time-m0.fcst_len*3600)%(24*3600)/3600 as xVal, ", + "Valid Date": "select m0.valid_time as xVal, ", + "Init Date": "select m0.valid_time-m0.fcst_len*3600 as xVal, ", + }; + + matsCollections.PlotParams.insert({ + name: "x-axis-parameter", + type: matsTypes.InputTypes.select, + options: Object.keys(xOptionsMap), + optionsMap: xOptionsMap, + selected: "", + controlButtonCovered: true, + unique: false, + default: Object.keys(xOptionsMap)[2], + controlButtonVisibility: "block", + displayOrder: 9, + displayPriority: 1, + displayGroup: 2, + }); + + const yOptionsMap = { + "Fcst lead time": "m0.fcst_len as yVal, ", + Threshold: "m0.thresh/100 as yVal, ", // produces thresholds in in + "Valid UTC hour": "m0.valid_time%(24*3600)/3600 as yVal, ", + "Init UTC hour": "(m0.valid_time-m0.fcst_len*3600)%(24*3600)/3600 as yVal, ", + "Valid Date": "m0.valid_time as yVal, ", + "Init Date": "m0.valid_time-m0.fcst_len*3600 as yVal, ", + }; + + matsCollections.PlotParams.insert({ + name: "y-axis-parameter", + type: matsTypes.InputTypes.select, + options: Object.keys(yOptionsMap), + optionsMap: yOptionsMap, + selected: "", + controlButtonCovered: true, + unique: false, + default: Object.keys(yOptionsMap)[0], + controlButtonVisibility: "block", + displayOrder: 10, + displayPriority: 1, + displayGroup: 2, + }); + + matsCollections.PlotParams.insert({ + name: "significance", + type: matsTypes.InputTypes.select, + options: ["none", "significance at 95th percentile"], + selected: "", + controlButtonCovered: true, + unique: false, + default: "none", + controlButtonVisibility: "block", + controlButtonText: "overlay significance", + displayOrder: 11, + displayPriority: 1, + displayGroup: 2, + }); + } else { + // need to update the dates selector if the metadata has changed + const currentParam = matsCollections.PlotParams.findOne({ name: "dates" }); + if ( + !matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) || + !matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) || + !matsDataUtils.areObjectsEqual(currentParam.default, dstr) + ) { + // have to reload model data + matsCollections.PlotParams.update( + { name: "dates" }, + { + $set: { + startDate: minDate, + stopDate: maxDate, + default: dstr, + }, + } + ); + } + } +}; + +const doCurveParams = function () { + // force a reset if requested - simply remove all the existing params to force a reload + if ( + matsCollections.Settings.findOne({}) === undefined || + matsCollections.Settings.findOne({}).resetFromCode === undefined || + matsCollections.Settings.findOne({}).resetFromCode === true + ) { + const params = matsCollections.CurveParamsInfo.find({ + curve_params: { $exists: true }, + }).fetch()[0].curve_params; + for (let cp = 0; cp < params.length; cp++) { + matsCollections[params[cp]].remove({}); + } + } + const modelOptionsMap = {}; + let modelDateRangeMap = {}; + const regionModelOptionsMap = {}; + const forecastLengthOptionsMap = {}; + const thresholdsModelOptionsMap = {}; + const sourceOptionsMap = {}; + const masterRegionValuesMap = {}; + const masterThresholdValuesMap = {}; + + try { + const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous( + metadataPool, + "select short_name,description from region_descriptions;" + ); + let masterRegDescription; + let masterShortName; + for (var j = 0; j < rows.length; j++) { + masterRegDescription = rows[j].description.trim(); + masterShortName = rows[j].short_name.trim(); + masterRegionValuesMap[masterShortName] = masterRegDescription; + } + } catch (err) { + console.log(err.message); + } + + try { + const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous( + modelPool, + "select trsh,description from threshold_descriptions;" + ); + let masterDescription; + let masterTrsh; + for (var j = 0; j < rows.length; j++) { + masterDescription = rows[j].description.trim(); + masterTrsh = rows[j].trsh.trim(); + masterThresholdValuesMap[masterTrsh] = masterDescription; + } + } catch (err) { + console.log(err.message); + } + + try { + const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous( + sumPool, + "select model,regions,sources,display_text,fcst_lens,trsh,mindate,maxdate from regions_per_model_mats_all_categories order by display_category, display_order;" + ); + for (let i = 0; i < rows.length; i++) { + const model_value = rows[i].model.trim(); + const model = rows[i].display_text.trim(); + modelOptionsMap[model] = [model_value]; + + const rowMinDate = moment.utc(rows[i].mindate * 1000).format("MM/DD/YYYY HH:mm"); + const rowMaxDate = moment.utc(rows[i].maxdate * 1000).format("MM/DD/YYYY HH:mm"); + modelDateRangeMap[model] = { minDate: rowMinDate, maxDate: rowMaxDate }; + + const { sources } = rows[i]; + const sourceArr = sources + .split(",") + .map(Function.prototype.call, String.prototype.trim); + for (var j = 0; j < sourceArr.length; j++) { + sourceArr[j] = sourceArr[j].replace(/'|\[|\]/g, ""); + } + sourceOptionsMap[model] = sourceArr; + + const forecastLengths = rows[i].fcst_lens; + const forecastLengthArr = forecastLengths + .split(",") + .map(Function.prototype.call, String.prototype.trim); + for (var j = 0; j < forecastLengthArr.length; j++) { + forecastLengthArr[j] = forecastLengthArr[j].replace(/'|\[|\]/g, ""); + } + forecastLengthOptionsMap[model] = forecastLengthArr; + + const thresholds = rows[i].trsh; + const thresholdsArrRaw = thresholds + .split(",") + .map(Function.prototype.call, String.prototype.trim); + const thresholdsArr = []; + var dummyThresh; + for (var j = 0; j < thresholdsArrRaw.length; j++) { + dummyThresh = thresholdsArrRaw[j].replace(/'|\[|\]/g, ""); + thresholdsArr.push(masterThresholdValuesMap[dummyThresh]); + } + thresholdsModelOptionsMap[model] = thresholdsArr; + + const { regions } = rows[i]; + const regionsArrRaw = regions + .split(",") + .map(Function.prototype.call, String.prototype.trim); + const regionsArr = []; + var dummyRegion; + for (var j = 0; j < regionsArrRaw.length; j++) { + dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, ""); + regionsArr.push(masterRegionValuesMap[dummyRegion]); + } + regionModelOptionsMap[model] = regionsArr; + } + } catch (err) { + console.log(err.message); + } + + if (matsCollections.label.findOne({ name: "label" }) === undefined) { + matsCollections.label.insert({ + name: "label", + type: matsTypes.InputTypes.textInput, + optionsMap: {}, + options: [], + controlButtonCovered: true, + default: "", + unique: true, + controlButtonVisibility: "block", + displayOrder: 1, + displayPriority: 1, + displayGroup: 1, + help: "label.html", + }); + } + + if (matsCollections["data-source"].findOne({ name: "data-source" }) === undefined) { + matsCollections["data-source"].insert({ + name: "data-source", + type: matsTypes.InputTypes.select, + optionsMap: modelOptionsMap, + dates: modelDateRangeMap, + options: Object.keys(modelOptionsMap), + dependentNames: [ + "region", + "forecast-length", + "threshold", + "truth", + "dates", + "curve-dates", + ], + controlButtonCovered: true, + default: Object.keys(modelOptionsMap)[0], + unique: false, + controlButtonVisibility: "block", + displayOrder: 3, + displayPriority: 1, + displayGroup: 1, + }); + } else { + // it is defined but check for necessary update + var currentParam = matsCollections["data-source"].findOne({ name: "data-source" }); + if ( + !matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap) || + !matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap) + ) { + // have to reload model data + matsCollections["data-source"].update( + { name: "data-source" }, + { + $set: { + optionsMap: modelOptionsMap, + dates: modelDateRangeMap, + options: Object.keys(modelOptionsMap), + default: Object.keys(modelOptionsMap)[0], + }, + } + ); + } + } + + if (matsCollections.region.findOne({ name: "region" }) === undefined) { + matsCollections.region.insert({ + name: "region", + type: matsTypes.InputTypes.select, + optionsMap: regionModelOptionsMap, + options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]], + valuesMap: masterRegionValuesMap, + superiorNames: ["data-source"], + controlButtonCovered: true, + unique: false, + default: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]][0], + controlButtonVisibility: "block", + displayOrder: 2, + displayPriority: 1, + displayGroup: 2, + }); + } else { + // it is defined but check for necessary update + var currentParam = matsCollections.region.findOne({ name: "region" }); + if ( + !matsDataUtils.areObjectsEqual(currentParam.optionsMap, regionModelOptionsMap) || + !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterRegionValuesMap) + ) { + // have to reload region data + matsCollections.region.update( + { name: "region" }, + { + $set: { + optionsMap: regionModelOptionsMap, + valuesMap: masterRegionValuesMap, + options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]], + default: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]][0], + }, + } + ); + } + } + + if (matsCollections.statistic.findOne({ name: "statistic" }) === undefined) { + const optionsMap = { + "CSI (Critical Success Index)": ["ctc", "x100", 100], + + "TSS (True Skill Score)": ["ctc", "x100", 100], + + "PODy (POD of value > threshold)": ["ctc", "x100", 100], + + "PODn (POD of value < threshold)": ["ctc", "x100", 100], + + "FAR (False Alarm Ratio)": ["ctc", "x100", 0], + + "Bias (forecast/actual)": ["ctc", "Ratio", 1], + + "HSS (Heidke Skill Score)": ["ctc", "x100", 100], + + "ETS (Equitable Threat Score)": ["ctc", "x100", 100], + + "Nlow (Number of obs < threshold (false alarms + correct nulls))": [ + "ctc", + "Number", + null, + ], + + "Nhigh (Number of obs > threshold (hits + misses))": ["ctc", "Number", null], + + "Ntot (Total number of obs, (Nlow + Nhigh))": ["ctc", "Number", null], + + "Ratio Nlow / Ntot ((fa + cn)/(hit + miss + fa + cn))": ["ctc", "Ratio", null], + + "Ratio Nhigh / Ntot ((hit + miss)/(hit + miss + fa + cn))": [ + "ctc", + "Ratio", + null, + ], + + "N times*levels(*stations if station plot) per graph point": [ + "ctc", + "Number", + null, + ], + }; + matsCollections.statistic.insert({ + name: "statistic", + type: matsTypes.InputTypes.select, + optionsMap, + options: Object.keys(optionsMap), + controlButtonCovered: true, + unique: false, + default: Object.keys(optionsMap)[0], + controlButtonVisibility: "block", + displayOrder: 1, + displayPriority: 1, + displayGroup: 2, + }); + } + + if (matsCollections.threshold.findOne({ name: "threshold" }) === undefined) { + matsCollections.threshold.insert({ + name: "threshold", + type: matsTypes.InputTypes.select, + optionsMap: thresholdsModelOptionsMap, + options: thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]], + valuesMap: masterThresholdValuesMap, + superiorNames: ["data-source"], + controlButtonCovered: true, + unique: false, + default: thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]][0], + controlButtonVisibility: "block", + displayOrder: 1, + displayPriority: 1, + displayGroup: 3, + }); + } else { + // it is defined but check for necessary update + var currentParam = matsCollections.threshold.findOne({ name: "threshold" }); + if ( + !matsDataUtils.areObjectsEqual( + currentParam.optionsMap, + thresholdsModelOptionsMap + ) || + !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterThresholdValuesMap) + ) { + // have to reload threshold data + matsCollections.threshold.update( + { name: "threshold" }, + { + $set: { + optionsMap: thresholdsModelOptionsMap, + valuesMap: masterThresholdValuesMap, + options: + thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]], + default: + thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]][0], + }, + } + ); + } + } + + if (matsCollections.truth.find({ name: "truth" }).count() === 0) { + matsCollections.truth.insert({ + name: "truth", + type: matsTypes.InputTypes.select, + optionsMap: sourceOptionsMap, + options: sourceOptionsMap[Object.keys(sourceOptionsMap)[0]], + superiorNames: ["data-source"], + controlButtonCovered: true, + unique: false, + default: sourceOptionsMap[Object.keys(sourceOptionsMap)[0]][0], + controlButtonVisibility: "block", + displayOrder: 3, + displayPriority: 1, + displayGroup: 3, + }); + } else { + // it is defined but check for necessary update + var currentParam = matsCollections.truth.findOne({ name: "truth" }); + if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, sourceOptionsMap)) { + // have to reload truth data + matsCollections.truth.update( + { name: "truth" }, + { + $set: { + optionsMap: sourceOptionsMap, + options: sourceOptionsMap[Object.keys(sourceOptionsMap)[0]], + default: sourceOptionsMap[Object.keys(sourceOptionsMap)[0]][0], + }, + } + ); + } + } + + if ( + matsCollections["forecast-length"].findOne({ name: "forecast-length" }) === + undefined + ) { + matsCollections["forecast-length"].insert({ + name: "forecast-length", + type: matsTypes.InputTypes.select, + optionsMap: forecastLengthOptionsMap, + options: forecastLengthOptionsMap[Object.keys(forecastLengthOptionsMap)[0]], + superiorNames: ["data-source"], + selected: "", + controlButtonCovered: true, + unique: false, + default: 6, + controlButtonVisibility: "block", + controlButtonText: "forecast lead time (h)", + displayOrder: 1, + displayPriority: 1, + displayGroup: 4, + }); + } else { + // it is defined but check for necessary update + var currentParam = matsCollections["forecast-length"].findOne({ + name: "forecast-length", + }); + if ( + !matsDataUtils.areObjectsEqual(currentParam.optionsMap, forecastLengthOptionsMap) + ) { + // have to reload forecast length data + matsCollections["forecast-length"].update( + { name: "forecast-length" }, + { + $set: { + optionsMap: forecastLengthOptionsMap, + options: forecastLengthOptionsMap[Object.keys(forecastLengthOptionsMap)[0]], + }, + } + ); + } + } + + if (matsCollections["dieoff-type"].findOne({ name: "dieoff-type" }) === undefined) { + const dieoffOptionsMap = { + Dieoff: [matsTypes.ForecastTypes.dieoff], + "Dieoff for a specified UTC cycle init hour": [matsTypes.ForecastTypes.utcCycle], + "Single cycle forecast (uses first date in range)": [ + matsTypes.ForecastTypes.singleCycle, + ], + }; + matsCollections["dieoff-type"].insert({ + name: "dieoff-type", + type: matsTypes.InputTypes.select, + optionsMap: dieoffOptionsMap, + options: Object.keys(dieoffOptionsMap), + hideOtherFor: { + "valid-time": [ + "Dieoff for a specified UTC cycle init hour", + "Single cycle forecast (uses first date in range)", + ], + "utc-cycle-start": [ + "Dieoff", + "Single cycle forecast (uses first date in range)", + ], + }, + selected: "", + controlButtonCovered: true, + unique: false, + default: Object.keys(dieoffOptionsMap)[0], + controlButtonVisibility: "block", + controlButtonText: "dieoff type", + displayOrder: 2, + displayPriority: 1, + displayGroup: 4, + }); + } + + if (matsCollections["valid-time"].findOne({ name: "valid-time" }) === undefined) { + matsCollections["valid-time"].insert({ + name: "valid-time", + type: matsTypes.InputTypes.select, + options: [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20", + "21", + "22", + "23", + ], + controlButtonCovered: true, + selected: [], + unique: false, + default: matsTypes.InputTypes.unused, + controlButtonVisibility: "block", + controlButtonText: "valid utc hour", + displayOrder: 3, + displayPriority: 1, + displayGroup: 4, + multiple: true, + }); + } + + if ( + matsCollections["utc-cycle-start"].findOne({ name: "utc-cycle-start" }) === + undefined + ) { + matsCollections["utc-cycle-start"].insert({ + name: "utc-cycle-start", + type: matsTypes.InputTypes.select, + options: [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "14", + "15", + "16", + "17", + "18", + "19", + "20", + "21", + "22", + "23", + ], + selected: "", + controlButtonCovered: true, + unique: false, + default: ["12"], + controlButtonVisibility: "block", + controlButtonText: "utc cycle init hour", + displayOrder: 4, + displayPriority: 1, + displayGroup: 4, + multiple: true, + }); + } + + if (matsCollections.average.findOne({ name: "average" }) === undefined) { + const optionsMap = { + None: [`ceil(${3600}*floor(((m0.valid_time)+${3600}/2)/${3600}))`], + "3hr": [`ceil(${3600 * 3}*floor(((m0.valid_time)+${3600 * 3}/2)/${3600 * 3}))`], + "6hr": [`ceil(${3600 * 6}*floor(((m0.valid_time)+${3600 * 6}/2)/${3600 * 6}))`], + "12hr": [ + `ceil(${3600 * 12}*floor(((m0.valid_time)+${3600 * 12}/2)/${3600 * 12}))`, + ], + "1D": [`ceil(${3600 * 24}*floor(((m0.valid_time)+${3600 * 24}/2)/${3600 * 24}))`], + "3D": [ + `ceil(${3600 * 24 * 3}*floor(((m0.valid_time)+${3600 * 24 * 3}/2)/${ + 3600 * 24 * 3 + }))`, + ], + "7D": [ + `ceil(${3600 * 24 * 7}*floor(((m0.valid_time)+${3600 * 24 * 7}/2)/${ + 3600 * 24 * 7 + }))`, + ], + "30D": [ + `ceil(${3600 * 24 * 30}*floor(((m0.valid_time)+${3600 * 24 * 30}/2)/${ + 3600 * 24 * 30 + }))`, + ], + "60D": [ + `ceil(${3600 * 24 * 60}*floor(((m0.valid_time)+${3600 * 24 * 60}/2)/${ + 3600 * 24 * 60 + }))`, + ], + "90D": [ + `ceil(${3600 * 24 * 90}*floor(((m0.valid_time)+${3600 * 24 * 90}/2)/${ + 3600 * 24 * 90 + }))`, + ], + "180D": [ + `ceil(${3600 * 24 * 180}*floor(((m0.valid_time)+${3600 * 24 * 180}/2)/${ + 3600 * 24 * 180 + }))`, + ], + }; + matsCollections.average.insert({ + name: "average", + type: matsTypes.InputTypes.select, + optionsMap, + options: Object.keys(optionsMap), + controlButtonCovered: true, + unique: false, + selected: "None", + default: "None", + controlButtonVisibility: "block", + displayOrder: 1, + displayPriority: 1, + displayGroup: 5, + }); + } + + if ( + matsCollections["bin-parameter"].findOne({ name: "bin-parameter" }) === undefined + ) { + const optionsMap = { + "Fcst lead time": "select m0.fcst_len as binVal, ", + Threshold: "select m0.thresh/100 as binVal, ", + "Valid UTC hour": "select m0.valid_time%(24*3600)/3600 as binVal, ", + "Init UTC hour": + "select (m0.valid_time-m0.fcst_len*3600)%(24*3600)/3600 as binVal, ", + "Valid Date": "select m0.valid_time as binVal, ", + "Init Date": "select m0.valid_time-m0.fcst_len*3600 as binVal, ", + }; + + matsCollections["bin-parameter"].insert({ + name: "bin-parameter", + type: matsTypes.InputTypes.select, + options: Object.keys(optionsMap), + optionsMap, + hideOtherFor: { + "forecast-length": ["Fcst lead time"], + threshold: ["Threshold"], + "valid-time": ["Valid UTC hour"], + }, + selected: "", + controlButtonCovered: true, + unique: false, + default: Object.keys(optionsMap)[4], + controlButtonVisibility: "block", + displayOrder: 3, + displayPriority: 1, + displayGroup: 6, + }); + } + + // determine date defaults for dates and curveDates + const defaultDataSource = matsCollections["data-source"].findOne( + { name: "data-source" }, + { default: 1 } + ).default; + modelDateRangeMap = matsCollections["data-source"].findOne( + { name: "data-source" }, + { dates: 1 } + ).dates; + minDate = modelDateRangeMap[defaultDataSource].minDate; + maxDate = modelDateRangeMap[defaultDataSource].maxDate; + + // need to turn the raw max and min from the metadata into the last valid month of data + const newDateRange = matsParamUtils.getMinMaxDates(minDate, maxDate); + const minusMonthMinDate = newDateRange.minDate; + maxDate = newDateRange.maxDate; + dstr = `${moment.utc(minusMonthMinDate).format("MM/DD/YYYY HH:mm")} - ${moment + .utc(maxDate) + .format("MM/DD/YYYY HH:mm")}`; + + if (matsCollections["curve-dates"].findOne({ name: "curve-dates" }) === undefined) { + const optionsMap = { + "1 day": ["1 day"], + "3 days": ["3 days"], + "7 days": ["7 days"], + "31 days": ["31 days"], + "90 days": ["90 days"], + "180 days": ["180 days"], + "365 days": ["365 days"], + }; + matsCollections["curve-dates"].insert({ + name: "curve-dates", + type: matsTypes.InputTypes.dateRange, + optionsMap, + options: Object.keys(optionsMap).sort(), + startDate: minDate, + stopDate: maxDate, + superiorNames: ["data-source"], + controlButtonCovered: true, + unique: false, + default: dstr, + controlButtonVisibility: "block", + displayOrder: 1, + displayPriority: 1, + displayGroup: 7, + help: "dateHelp.html", + }); + } else { + // it is defined but check for necessary update + var currentParam = matsCollections["curve-dates"].findOne({ name: "curve-dates" }); + if ( + !matsDataUtils.areObjectsEqual(currentParam.startDate, minDate) || + !matsDataUtils.areObjectsEqual(currentParam.stopDate, maxDate) || + !matsDataUtils.areObjectsEqual(currentParam.default, dstr) + ) { + // have to reload dates data + matsCollections["curve-dates"].update( + { name: "curve-dates" }, + { + $set: { + startDate: minDate, + stopDate: maxDate, + default: dstr, + }, + } + ); + } + } +}; + +/* The format of a curveTextPattern is an array of arrays, each sub array has + [labelString, localVariableName, delimiterString] any of which can be null. + Each sub array will be joined (the localVariableName is always dereferenced first) + and then the sub arrays will be joined maintaining order. + + The curveTextPattern is found by its name which must match the corresponding matsCollections.PlotGraphFunctions.PlotType value. + See curve_item.js and standAlone.js. + */ +const doCurveTextPatterns = function () { + if ( + matsCollections.Settings.findOne({}) === undefined || + matsCollections.Settings.findOne({}).resetFromCode === undefined || + matsCollections.Settings.findOne({}).resetFromCode === true + ) { + matsCollections.CurveTextPatterns.remove({}); + } + if (matsCollections.CurveTextPatterns.find().count() === 0) { + matsCollections.CurveTextPatterns.insert({ + plotType: matsTypes.PlotTypes.timeSeries, + textPattern: [ + ["", "label", ": "], + ["", "data-source", " in "], + ["", "region", ", "], + ["", "threshold", " "], + ["", "statistic", ", "], + ["fcst_len: ", "forecast-length", "h, "], + ["valid-time: ", "valid-time", ", "], + ["avg: ", "average", ", "], + ["", "truth", ""], + ], + displayParams: [ + "label", + "data-source", + "region", + "statistic", + "threshold", + "average", + "forecast-length", + "valid-time", + "truth", + ], + groupSize: 6, + }); + matsCollections.CurveTextPatterns.insert({ + plotType: matsTypes.PlotTypes.dieoff, + textPattern: [ + ["", "label", ": "], + ["", "data-source", " in "], + ["", "region", ", "], + ["", "threshold", " "], + ["", "statistic", ", "], + ["", "dieoff-type", ", "], + ["valid-time: ", "valid-time", ", "], + ["start utc: ", "utc-cycle-start", ", "], + ["", "truth", ", "], + ["", "curve-dates", ""], + ], + displayParams: [ + "label", + "data-source", + "region", + "statistic", + "threshold", + "dieoff-type", + "valid-time", + "utc-cycle-start", + "truth", + "curve-dates", + ], + groupSize: 6, + }); + matsCollections.CurveTextPatterns.insert({ + plotType: matsTypes.PlotTypes.threshold, + textPattern: [ + ["", "label", ": "], + ["", "data-source", " in "], + ["", "region", ", "], + ["", "statistic", ", "], + ["fcst_len: ", "forecast-length", "h, "], + ["valid-time: ", "valid-time", ", "], + ["", "truth", ", "], + ["", "curve-dates", ""], + ], + displayParams: [ + "label", + "data-source", + "region", + "statistic", + "forecast-length", + "valid-time", + "truth", + "curve-dates", + ], + groupSize: 6, + }); + matsCollections.CurveTextPatterns.insert({ + plotType: matsTypes.PlotTypes.validtime, + textPattern: [ + ["", "label", ": "], + ["", "data-source", " in "], + ["", "region", ", "], + ["", "threshold", " "], + ["", "statistic", ", "], + ["fcst_len: ", "forecast-length", "h, "], + ["", "truth", ", "], + ["", "curve-dates", ""], + ], + displayParams: [ + "label", + "data-source", + "region", + "statistic", + "threshold", + "forecast-length", + "truth", + "curve-dates", + ], + groupSize: 6, + }); + matsCollections.CurveTextPatterns.insert({ + plotType: matsTypes.PlotTypes.dailyModelCycle, + textPattern: [ + ["", "label", ": "], + ["", "data-source", " in "], + ["", "region", ", "], + ["", "threshold", " "], + ["", "statistic", ", "], + ["start utc: ", "utc-cycle-start", ", "], + ["", "truth", ""], + ], + displayParams: [ + "label", + "data-source", + "region", + "statistic", + "threshold", + "utc-cycle-start", + "truth", + ], + groupSize: 6, + }); + matsCollections.CurveTextPatterns.insert({ + plotType: matsTypes.PlotTypes.performanceDiagram, + textPattern: [ + ["", "label", ": "], + ["", "data-source", " in "], + ["", "region", ", "], + ["", "threshold", " "], + ["fcst_len: ", "forecast-length", "h, "], + ["valid-time: ", "valid-time", ", "], + ["", "truth", ", "], + ["", "curve-dates", ""], + ], + displayParams: [ + "label", + "data-source", + "region", + "threshold", + "forecast-length", + "valid-time", + "truth", + "bin-parameter", + "curve-dates", + ], + groupSize: 6, + }); + matsCollections.CurveTextPatterns.insert({ + plotType: matsTypes.PlotTypes.histogram, + textPattern: [ + ["", "label", ": "], + ["", "data-source", " in "], + ["", "region", ", "], + ["", "threshold", " "], + ["", "statistic", ", "], + ["fcst_len: ", "forecast-length", "h, "], + ["valid-time: ", "valid-time", ", "], + ["", "truth", ", "], + ["", "curve-dates", ""], + ], + displayParams: [ + "label", + "data-source", + "region", + "statistic", + "threshold", + "forecast-length", + "valid-time", + "truth", + "curve-dates", + ], + groupSize: 6, + }); + matsCollections.CurveTextPatterns.insert({ + plotType: matsTypes.PlotTypes.contour, + textPattern: [ + ["", "label", ": "], + ["", "data-source", " in "], + ["", "region", ", "], + ["", "threshold", " "], + ["", "statistic", ", "], + ["fcst_len: ", "forecast-length", "h, "], + ["valid-time: ", "valid-time", ", "], + ["", "truth", ""], + ], + displayParams: [ + "label", + "data-source", + "region", + "statistic", + "threshold", + "forecast-length", + "valid-time", + "truth", + ], + groupSize: 6, + }); + matsCollections.CurveTextPatterns.insert({ + plotType: matsTypes.PlotTypes.contourDiff, + textPattern: [ + ["", "label", ": "], + ["", "data-source", " in "], + ["", "region", ", "], + ["", "threshold", " "], + ["", "statistic", ", "], + ["fcst_len: ", "forecast-length", "h, "], + ["valid-time: ", "valid-time", ", "], + ["", "truth", ""], + ], + displayParams: [ + "label", + "data-source", + "region", + "statistic", + "threshold", + "forecast-length", + "valid-time", + "truth", + ], + groupSize: 6, + }); + } +}; + +const doSavedCurveParams = function () { + if ( + matsCollections.Settings.findOne({}) === undefined || + matsCollections.Settings.findOne({}).resetFromCode === undefined || + matsCollections.Settings.findOne({}).resetFromCode === true + ) { + matsCollections.SavedCurveParams.remove({}); + } + if (matsCollections.SavedCurveParams.find().count() === 0) { + matsCollections.SavedCurveParams.insert({ clName: "changeList", changeList: [] }); + } +}; + +const doPlotGraph = function () { + if ( + matsCollections.Settings.findOne({}) === undefined || + matsCollections.Settings.findOne({}).resetFromCode === undefined || + matsCollections.Settings.findOne({}).resetFromCode === true + ) { + matsCollections.PlotGraphFunctions.remove({}); + } + if (matsCollections.PlotGraphFunctions.find().count() === 0) { + matsCollections.PlotGraphFunctions.insert({ + plotType: matsTypes.PlotTypes.timeSeries, + graphFunction: "graphPlotly", + dataFunction: "dataSeries", + checked: true, + }); + matsCollections.PlotGraphFunctions.insert({ + plotType: matsTypes.PlotTypes.dieoff, + graphFunction: "graphPlotly", + dataFunction: "dataDieOff", + checked: false, + }); + matsCollections.PlotGraphFunctions.insert({ + plotType: matsTypes.PlotTypes.threshold, + graphFunction: "graphPlotly", + dataFunction: "dataThreshold", + checked: false, + }); + matsCollections.PlotGraphFunctions.insert({ + plotType: matsTypes.PlotTypes.validtime, + graphFunction: "graphPlotly", + dataFunction: "dataValidTime", + checked: false, + }); + matsCollections.PlotGraphFunctions.insert({ + plotType: matsTypes.PlotTypes.dailyModelCycle, + graphFunction: "graphPlotly", + dataFunction: "dataDailyModelCycle", + checked: false, + }); + matsCollections.PlotGraphFunctions.insert({ + plotType: matsTypes.PlotTypes.performanceDiagram, + graphFunction: "graphPlotly", + dataFunction: "dataPerformanceDiagram", + checked: false, + }); + matsCollections.PlotGraphFunctions.insert({ + plotType: matsTypes.PlotTypes.histogram, + graphFunction: "graphPlotly", + dataFunction: "dataHistogram", + checked: false, + }); + matsCollections.PlotGraphFunctions.insert({ + plotType: matsTypes.PlotTypes.contour, + graphFunction: "graphPlotly", + dataFunction: "dataContour", + checked: false, + }); + matsCollections.PlotGraphFunctions.insert({ + plotType: matsTypes.PlotTypes.contourDiff, + graphFunction: "graphPlotly", + dataFunction: "dataContourDiff", + checked: false, + }); + } +}; + +Meteor.startup(function () { + matsCollections.Databases.remove({}); + if (matsCollections.Databases.find({}).count() < 0) { + console.log( + "main startup: corrupted Databases collection: dropping Databases collection" + ); + matsCollections.Databases.drop(); + } + if (matsCollections.Databases.find({}).count() === 0) { + let databases; + if ( + Meteor.settings === undefined || + Meteor.settings.private === undefined || + Meteor.settings.private.databases === undefined + ) { + databases = undefined; + } else { + databases = Meteor.settings.private.databases; + } + if (databases !== null && databases !== undefined && Array.isArray(databases)) { + for (let di = 0; di < databases.length; di++) { + matsCollections.Databases.insert(databases[di]); + } + } + } + + // create list of all pools + const allPools = []; + + // connect to the couchbase cluster + const cbConnection = matsCollections.Databases.findOne( + { + role: matsTypes.DatabaseRoles.COUCHBASE, + status: "active", + }, + { + host: 1, + port: 1, + bucket: 1, + scope: 1, + collection: 1, + user: 1, + password: 1, + } + ); + if (cbConnection) { + // global cbScorecardSettingsPool + cbScorecardSettingsPool = new matsCouchbaseUtils.CBUtilities( + cbConnection.host, + cbConnection.bucket, + cbConnection.scope, + cbConnection.collection, + cbConnection.user, + cbConnection.password + ); + } + + const metadataSettings = matsCollections.Databases.findOne( + { + role: matsTypes.DatabaseRoles.META_DATA, + status: "active", + }, + { + host: 1, + port: 1, + user: 1, + password: 1, + database: 1, + connectionLimit: 1, + } + ); + // the pool is intended to be global + if (metadataSettings) { + metadataPool = mysql.createPool(metadataSettings); + allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA }); + } + + const modelSettings = matsCollections.Databases.findOne( + { role: matsTypes.DatabaseRoles.MODEL_DATA, status: "active" }, + { + host: 1, + port: 1, + user: 1, + password: 1, + database: 1, + connectionLimit: 1, + } + ); + // the pool is intended to be global + if (modelSettings) { + modelPool = mysql.createPool(modelSettings); + allPools.push({ pool: "modelPool", role: matsTypes.DatabaseRoles.MODEL_DATA }); + } + + const sumSettings = matsCollections.Databases.findOne( + { + role: matsTypes.DatabaseRoles.SUMS_DATA, + status: "active", + }, + { + host: 1, + port: 1, + user: 1, + password: 1, + database: 1, + connectionLimit: 1, + } + ); + // the pool is intended to be global + if (sumSettings) { + sumPool = mysql.createPool(sumSettings); + allPools.push({ pool: "sumPool", role: matsTypes.DatabaseRoles.SUMS_DATA }); + } + + // create list of tables we need to monitor for update + const mdr = new matsTypes.MetaDataDBRecord("metadataPool", "mats_common", [ + "region_descriptions", + ]); + mdr.addRecord("modelPool", "precip_mesonets2", ["threshold_descriptions"]); + mdr.addRecord("sumPool", "precip_mesonets2_sums", [ + "regions_per_model_mats_all_categories", + ]); + try { + matsMethods.resetApp({ + appPools: allPools, + appMdr: mdr, + appType: matsTypes.AppTypes.mats, + }); + } catch (error) { + console.log(error.message); + } +}); + +// this object is global so that the reset code can get to it +// These are application specific mongo data - like curve params +// The appSpecificResetRoutines object is a special name, +// as is doCurveParams. The refreshMetaData mechanism depends on them being named that way. +appSpecificResetRoutines = [ + doPlotGraph, + doCurveParams, + doSavedCurveParams, + doPlotParams, + doCurveTextPatterns, +]; From 91f04a1386e95df6010736fd00195589e9a48140 Mon Sep 17 00:00:00 2001 From: Molly Smith Date: Tue, 13 Jun 2023 13:14:08 -0600 Subject: [PATCH 02/50] Switched dummy ensemble functions from gaugePrecip to radar, which is more apt. --- .../server/dataFunctions/data_contour.js | 47 +- .../server/dataFunctions/data_contour_diff.js | 46 +- .../dataFunctions/data_dailymodelcycle.js | 52 +- .../server/dataFunctions/data_dieoff.js | 56 +- .../server/dataFunctions/data_histogram.js | 52 +- .../server/dataFunctions/data_perfDiagram.js | 41 +- .../server/dataFunctions/data_series.js | 50 +- .../server/dataFunctions/data_threshold.js | 46 +- .../server/dataFunctions/data_validtime.js | 50 +- apps/ensemble/server/main.js | 546 +++++++++++------- 10 files changed, 619 insertions(+), 367 deletions(-) diff --git a/apps/ensemble/server/dataFunctions/data_contour.js b/apps/ensemble/server/dataFunctions/data_contour.js index e4cd3b9a06..f37c909014 100644 --- a/apps/ensemble/server/dataFunctions/data_contour.js +++ b/apps/ensemble/server/dataFunctions/data_contour.js @@ -45,8 +45,12 @@ dataContour = function (plotParams, plotFunction) { // initialize variables specific to the curve const curve = curves[0]; const { label } = curve; + const { variable } = curve; + const databaseRef = matsCollections.variable.findOne({ name: "variable" }).optionsMap[ + variable + ]; const model = matsCollections["data-source"].findOne({ name: "data-source" }) - .optionsMap[curve["data-source"]][0]; + .optionsMap[variable][curve["data-source"]][0]; const regionStr = curve.region; const region = Object.keys( matsCollections.region.findOne({ name: "region" }).valuesMap @@ -54,12 +58,15 @@ dataContour = function (plotParams, plotFunction) { (key) => matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr ); - const source = curve.truth; - let sourceStr = ""; - if (source !== "All") { - sourceStr = `_${source}`; - } - const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + const scaleStr = curve.scale; + const grid_scale = Object.keys( + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable] + ).find( + (key) => + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] === + scaleStr + ); + const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`; let thresholdClause = ""; let validTimeClause = ""; let forecastLengthClause = ""; @@ -68,18 +75,19 @@ dataContour = function (plotParams, plotFunction) { if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") { const thresholdStr = curve.threshold; const threshold = Object.keys( - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable] ).find( (key) => - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === - thresholdStr + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable][ + key + ] === thresholdStr ); - thresholdClause = `and m0.thresh = ${threshold}`; + thresholdClause = `and m0.trsh = ${threshold / 10000}`; } if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") { const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) { - validTimeClause = `and m0.valid_time%(24*3600)/3600 IN(${validTimes})`; + validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`; } } if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") { @@ -91,9 +99,9 @@ dataContour = function (plotParams, plotFunction) { xAxisParam !== "Valid Date" && yAxisParam !== "Valid Date" ) { - dateString = "m0.valid_time-m0.fcst_len*3600"; + dateString = "m0.time-m0.fcst_len*3600"; } else { - dateString = "m0.valid_time"; + dateString = "m0.time"; } dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`; const statisticSelect = curve.statistic; @@ -102,7 +110,7 @@ dataContour = function (plotParams, plotFunction) { { optionsMap: 1 } ).optionsMap; const statisticClause = - "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0"; // For contours, this functions as the colorbar label. const statType = statisticOptionsMap[statisticSelect][0]; curve.unitKey = statisticOptionsMap[statisticSelect][1]; @@ -172,7 +180,14 @@ dataContour = function (plotParams, plotFunction) { } else { // this is an error returned by the mysql database error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; - throw new Error(error); + if (error.includes("ER_NO_SUCH_TABLE")) { + throw new Error( + `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` + + `Choose a different scale to continue using this region.` + ); + } else { + throw new Error(error); + } } } diff --git a/apps/ensemble/server/dataFunctions/data_contour_diff.js b/apps/ensemble/server/dataFunctions/data_contour_diff.js index 5460fe0f7f..f367787887 100644 --- a/apps/ensemble/server/dataFunctions/data_contour_diff.js +++ b/apps/ensemble/server/dataFunctions/data_contour_diff.js @@ -51,8 +51,11 @@ dataContourDiff = function (plotParams, plotFunction) { // initialize variables specific to each curve const curve = curves[curveIndex]; const { label } = curve; + var { variable } = curve; + const databaseRef = matsCollections.variable.findOne({ name: "variable" }) + .optionsMap[variable]; const model = matsCollections["data-source"].findOne({ name: "data-source" }) - .optionsMap[curve["data-source"]][0]; + .optionsMap[variable][curve["data-source"]][0]; var regionStr = curve.region; const region = Object.keys( matsCollections.region.findOne({ name: "region" }).valuesMap @@ -60,12 +63,15 @@ dataContourDiff = function (plotParams, plotFunction) { (key) => matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr ); - const source = curve.truth; - let sourceStr = ""; - if (source !== "All") { - sourceStr = `_${source}`; - } - const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var scaleStr = curve.scale; + const grid_scale = Object.keys( + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable] + ).find( + (key) => + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] === + scaleStr + ); + const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`; let thresholdClause = ""; let validTimeClause = ""; let forecastLengthClause = ""; @@ -74,18 +80,19 @@ dataContourDiff = function (plotParams, plotFunction) { if (xAxisParam !== "Threshold" && yAxisParam !== "Threshold") { var thresholdStr = curve.threshold; const threshold = Object.keys( - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable] ).find( (key) => - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === - thresholdStr + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable][ + key + ] === thresholdStr ); - thresholdClause = `and m0.thresh = ${threshold}`; + thresholdClause = `and m0.trsh = ${threshold / 10000}`; } if (xAxisParam !== "Valid UTC hour" && yAxisParam !== "Valid UTC hour") { const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) { - validTimeClause = `and m0.valid_time%(24*3600)/3600 IN(${validTimes})`; + validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`; } } if (xAxisParam !== "Fcst lead time" && yAxisParam !== "Fcst lead time") { @@ -97,9 +104,9 @@ dataContourDiff = function (plotParams, plotFunction) { xAxisParam !== "Valid Date" && yAxisParam !== "Valid Date" ) { - dateString = "m0.valid_time-m0.fcst_len*3600"; + dateString = "m0.time-m0.fcst_len*3600"; } else { - dateString = "m0.valid_time"; + dateString = "m0.time"; } dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`; var statisticSelect = curve.statistic; @@ -108,7 +115,7 @@ dataContourDiff = function (plotParams, plotFunction) { { optionsMap: 1 } ).optionsMap; const statisticClause = - "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0"; // For contours, this functions as the colorbar label. var statType = statisticOptionsMap[statisticSelect][0]; curves[curveIndex].unitKey = statisticOptionsMap[statisticSelect][1]; @@ -178,7 +185,14 @@ dataContourDiff = function (plotParams, plotFunction) { } else { // this is an error returned by the mysql database error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; - throw new Error(error); + if (error.includes("ER_NO_SUCH_TABLE")) { + throw new Error( + `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` + + `Choose a different scale to continue using this region.` + ); + } else { + throw new Error(error); + } } dataNotFoundForAnyCurve = true; } diff --git a/apps/ensemble/server/dataFunctions/data_dailymodelcycle.js b/apps/ensemble/server/dataFunctions/data_dailymodelcycle.js index e0f4721495..be4a3b51b7 100644 --- a/apps/ensemble/server/dataFunctions/data_dailymodelcycle.js +++ b/apps/ensemble/server/dataFunctions/data_dailymodelcycle.js @@ -47,8 +47,11 @@ dataDailyModelCycle = function (plotParams, plotFunction) { const curve = curves[curveIndex]; const { diffFrom } = curve; const { label } = curve; + var { variable } = curve; + const databaseRef = matsCollections.variable.findOne({ name: "variable" }) + .optionsMap[variable]; const model = matsCollections["data-source"].findOne({ name: "data-source" }) - .optionsMap[curve["data-source"]][0]; + .optionsMap[variable][curve["data-source"]][0]; var regionStr = curve.region; const region = Object.keys( matsCollections.region.findOne({ name: "region" }).valuesMap @@ -56,21 +59,25 @@ dataDailyModelCycle = function (plotParams, plotFunction) { (key) => matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr ); - const source = curve.truth; - let sourceStr = ""; - if (source !== "All") { - sourceStr = `_${source}`; - } - const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var scaleStr = curve.scale; + const grid_scale = Object.keys( + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable] + ).find( + (key) => + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] === + scaleStr + ); + const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`; var thresholdStr = curve.threshold; const threshold = Object.keys( - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable] ).find( (key) => - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === - thresholdStr + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable][ + key + ] === thresholdStr ); - const thresholdClause = `and m0.thresh = ${threshold}`; + const thresholdClause = `and m0.trsh = ${threshold / 10000}`; if (curve["utc-cycle-start"].length !== 1) { throw new Error( "INFO: Please select exactly one UTC Cycle Init Hour for this plot type." @@ -78,16 +85,16 @@ dataDailyModelCycle = function (plotParams, plotFunction) { } const utcCycleStart = Number(curve["utc-cycle-start"][0]); utcCycleStarts[curveIndex] = utcCycleStart; - const utcCycleStartClause = `and floor((m0.valid_time - m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`; + const utcCycleStartClause = `and floor((m0.time - m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`; const forecastLengthClause = "and m0.fcst_len < 24"; - const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`; const statisticSelect = curve.statistic; const statisticOptionsMap = matsCollections.statistic.findOne( { name: "statistic" }, { optionsMap: 1 } ).optionsMap; const statisticClause = - "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0"; // axisKey is used to determine which axis a curve should use. // This axisKeySet object is used like a set and if a curve has the same // units (axisKey) it will use the same axis. @@ -105,10 +112,10 @@ dataDailyModelCycle = function (plotParams, plotFunction) { // this is a database driven curve, not a difference curve // prepare the query from the above parameters let statement = - "select m0.valid_time as avtime, " + - "count(distinct m0.valid_time) as N_times, " + - "min(m0.valid_time) as min_secs, " + - "max(m0.valid_time) as max_secs, " + + "select m0.time as avtime, " + + "count(distinct m0.time) as N_times, " + + "min(m0.time) as min_secs, " + + "max(m0.time) as max_secs, " + "{{statisticClause}} " + "{{queryTableClause}} " + "where 1=1 " + @@ -162,7 +169,14 @@ dataDailyModelCycle = function (plotParams, plotFunction) { } else { // this is an error returned by the mysql database error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; - throw new Error(error); + if (error.includes("ER_NO_SUCH_TABLE")) { + throw new Error( + `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` + + `Choose a different scale to continue using this region.` + ); + } else { + throw new Error(error); + } } } else { dataFoundForAnyCurve = true; diff --git a/apps/ensemble/server/dataFunctions/data_dieoff.js b/apps/ensemble/server/dataFunctions/data_dieoff.js index 9a61398c19..40e1e4e8ff 100644 --- a/apps/ensemble/server/dataFunctions/data_dieoff.js +++ b/apps/ensemble/server/dataFunctions/data_dieoff.js @@ -44,8 +44,11 @@ dataDieOff = function (plotParams, plotFunction) { const curve = curves[curveIndex]; const { diffFrom } = curve; const { label } = curve; + var { variable } = curve; + const databaseRef = matsCollections.variable.findOne({ name: "variable" }) + .optionsMap[variable]; const model = matsCollections["data-source"].findOne({ name: "data-source" }) - .optionsMap[curve["data-source"]][0]; + .optionsMap[variable][curve["data-source"]][0]; var regionStr = curve.region; const region = Object.keys( matsCollections.region.findOne({ name: "region" }).valuesMap @@ -53,21 +56,25 @@ dataDieOff = function (plotParams, plotFunction) { (key) => matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr ); - const source = curve.truth; - let sourceStr = ""; - if (source !== "All") { - sourceStr = `_${source}`; - } - const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var scaleStr = curve.scale; + const grid_scale = Object.keys( + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable] + ).find( + (key) => + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] === + scaleStr + ); + const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`; var thresholdStr = curve.threshold; const threshold = Object.keys( - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable] ).find( (key) => - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === - thresholdStr + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable][ + key + ] === thresholdStr ); - const thresholdClause = `and m0.thresh = ${threshold}`; + const thresholdClause = `and m0.trsh = ${threshold / 10000}`; var validTimes; let validTimeClause = ""; var utcCycleStart; @@ -86,18 +93,18 @@ dataDieOff = function (plotParams, plotFunction) { if (forecastLength === matsTypes.ForecastTypes.dieoff) { validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) { - validTimeClause = `and floor((m0.valid_time)%(24*3600)/3600) IN(${validTimes})`; + validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`; } - dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`; } else if (forecastLength === matsTypes.ForecastTypes.utcCycle) { utcCycleStart = curve["utc-cycle-start"] === undefined ? [] : curve["utc-cycle-start"]; if (utcCycleStart.length !== 0 && utcCycleStart !== matsTypes.InputTypes.unused) { - utcCycleStartClause = `and floor(((m0.valid_time) - m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`; // adjust by 1800 seconds to center obs at the top of the hour + utcCycleStartClause = `and floor(((m0.time) - m0.fcst_len*3600)%(24*3600)/3600) IN(${utcCycleStart})`; // adjust by 1800 seconds to center obs at the top of the hour } - dateClause = `and m0.valid_time-m0.fcst_len*3600 >= ${fromSecs} and m0.valid_time-m0.fcst_len*3600 <= ${toSecs}`; + dateClause = `and m0.time-m0.fcst_len*3600 >= ${fromSecs} and m0.time-m0.fcst_len*3600 <= ${toSecs}`; } else { - dateClause = `and m0.valid_time-m0.fcst_len*3600 = ${fromSecs}`; + dateClause = `and m0.time-m0.fcst_len*3600 = ${fromSecs}`; } const statisticSelect = curve.statistic; const statisticOptionsMap = matsCollections.statistic.findOne( @@ -105,7 +112,7 @@ dataDieOff = function (plotParams, plotFunction) { { optionsMap: 1 } ).optionsMap; const statisticClause = - "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0"; // axisKey is used to determine which axis a curve should use. // This axisKeySet object is used like a set and if a curve has the same // units (axisKey) it will use the same axis. @@ -124,9 +131,9 @@ dataDieOff = function (plotParams, plotFunction) { // prepare the query from the above parameters let statement = "select m0.fcst_len as fcst_lead, " + - "count(distinct m0.valid_time) as N_times, " + - "min(m0.valid_time) as min_secs, " + - "max(m0.valid_time) as max_secs, " + + "count(distinct m0.time) as N_times, " + + "min(m0.time) as min_secs, " + + "max(m0.time) as max_secs, " + "{{statisticClause}} " + "{{queryTableClause}} " + "where 1=1 " + @@ -182,7 +189,14 @@ dataDieOff = function (plotParams, plotFunction) { } else { // this is an error returned by the mysql database error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; - throw new Error(error); + if (error.includes("ER_NO_SUCH_TABLE")) { + throw new Error( + `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` + + `Choose a different scale to continue using this region.` + ); + } else { + throw new Error(error); + } } } else { dataFoundForAnyCurve = true; diff --git a/apps/ensemble/server/dataFunctions/data_histogram.js b/apps/ensemble/server/dataFunctions/data_histogram.js index 08e43cd2e6..1ea2f4bb97 100644 --- a/apps/ensemble/server/dataFunctions/data_histogram.js +++ b/apps/ensemble/server/dataFunctions/data_histogram.js @@ -45,8 +45,11 @@ dataHistogram = function (plotParams, plotFunction) { const { diffFrom } = curve; dataFoundForCurve[curveIndex] = true; const { label } = curve; + var { variable } = curve; + const databaseRef = matsCollections.variable.findOne({ name: "variable" }) + .optionsMap[variable]; const model = matsCollections["data-source"].findOne({ name: "data-source" }) - .optionsMap[curve["data-source"]][0]; + .optionsMap[variable][curve["data-source"]][0]; var regionStr = curve.region; const region = Object.keys( matsCollections.region.findOne({ name: "region" }).valuesMap @@ -54,39 +57,43 @@ dataHistogram = function (plotParams, plotFunction) { (key) => matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr ); - const source = curve.truth; - let sourceStr = ""; - if (source !== "All") { - sourceStr = `_${source}`; - } - const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var scaleStr = curve.scale; + const grid_scale = Object.keys( + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable] + ).find( + (key) => + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] === + scaleStr + ); + const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`; var thresholdStr = curve.threshold; const threshold = Object.keys( - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable] ).find( (key) => - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === - thresholdStr + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable][ + key + ] === thresholdStr ); - const thresholdClause = `and m0.thresh = ${threshold}`; + const thresholdClause = `and m0.trsh = ${threshold / 10000}`; let validTimeClause = ""; const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) { - validTimeClause = `and floor((m0.valid_time)%(24*3600)/3600) IN(${validTimes})`; + validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`; } const forecastLength = curve["forecast-length"]; const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]); const fromSecs = dateRange.fromSeconds; const toSecs = dateRange.toSeconds; - const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`; const statisticSelect = curve.statistic; const statisticOptionsMap = matsCollections.statistic.findOne( { name: "statistic" }, { optionsMap: 1 } ).optionsMap; const statisticClause = - "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0"; // axisKey is used to determine which axis a curve should use. // This axisKeySet object is used like a set and if a curve has the same // units (axisKey) it will use the same axis. @@ -105,10 +112,10 @@ dataHistogram = function (plotParams, plotFunction) { // this is a database driven curve, not a difference curve // prepare the query from the above parameters let statement = - "select m0.valid_time as avtime, " + - "count(distinct m0.valid_time) as N_times, " + - "min(m0.valid_time) as min_secs, " + - "max(m0.valid_time) as max_secs, " + + "select m0.time as avtime, " + + "count(distinct m0.time) as N_times, " + + "min(m0.time) as min_secs, " + + "max(m0.time) as max_secs, " + "{{statisticClause}} " + "{{queryTableClause}} " + "where 1=1 " + @@ -164,7 +171,14 @@ dataHistogram = function (plotParams, plotFunction) { } else { // this is an error returned by the mysql database error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; - throw new Error(error); + if (error.includes("ER_NO_SUCH_TABLE")) { + throw new Error( + `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` + + `Choose a different scale to continue using this region.` + ); + } else { + throw new Error(error); + } } } else { dataFoundForAnyCurve = true; diff --git a/apps/ensemble/server/dataFunctions/data_perfDiagram.js b/apps/ensemble/server/dataFunctions/data_perfDiagram.js index 12c3fb5d20..037bc7324f 100644 --- a/apps/ensemble/server/dataFunctions/data_perfDiagram.js +++ b/apps/ensemble/server/dataFunctions/data_perfDiagram.js @@ -45,8 +45,11 @@ dataPerformanceDiagram = function (plotParams, plotFunction) { const binClause = matsCollections["bin-parameter"].findOne({ name: "bin-parameter", }).optionsMap[binParam]; + var { variable } = curve; + const databaseRef = matsCollections.variable.findOne({ name: "variable" }) + .optionsMap[variable]; const model = matsCollections["data-source"].findOne({ name: "data-source" }) - .optionsMap[curve["data-source"]][0]; + .optionsMap[variable][curve["data-source"]][0]; var regionStr = curve.region; const region = Object.keys( matsCollections.region.findOne({ name: "region" }).valuesMap @@ -54,12 +57,15 @@ dataPerformanceDiagram = function (plotParams, plotFunction) { (key) => matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr ); - const source = curve.truth; - let sourceStr = ""; - if (source !== "All") { - sourceStr = `_${source}`; - } - const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var scaleStr = curve.scale; + const grid_scale = Object.keys( + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable] + ).find( + (key) => + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] === + scaleStr + ); + const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`; let thresholdClause = ""; let validTimeClause = ""; let forecastLengthClause = ""; @@ -76,18 +82,19 @@ dataPerformanceDiagram = function (plotParams, plotFunction) { ); } const threshold = Object.keys( - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable] ).find( (key) => - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === - thresholdStr + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable][ + key + ] === thresholdStr ); - thresholdClause = `and m0.thresh = ${threshold}`; + thresholdClause = `and m0.trsh = ${threshold / 10000}`; } if (binParam !== "Valid UTC hour") { const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; if (validTimes.length > 0 && validTimes !== matsTypes.InputTypes.unused) { - validTimeClause = `and m0.valid_time%(24*3600)/3600 IN(${validTimes})`; + validTimeClause = `and m0.time%(24*3600)/3600 IN(${validTimes})`; } } if (binParam !== "Fcst lead time") { @@ -100,9 +107,9 @@ dataPerformanceDiagram = function (plotParams, plotFunction) { forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; } if (binParam === "Init Date") { - dateString = "m0.valid_time-m0.fcst_len*3600"; + dateString = "m0.time-m0.fcst_len*3600"; } else { - dateString = "m0.valid_time"; + dateString = "m0.time"; } dateClause = `and ${dateString} >= ${fromSecs} and ${dateString} <= ${toSecs}`; const statisticSelect = "PerformanceDiagram"; @@ -122,9 +129,9 @@ dataPerformanceDiagram = function (plotParams, plotFunction) { "count(distinct {{dateString}}) as N_times, " + "min({{dateString}}) as min_secs, " + "max({{dateString}}) as max_secs, " + - "((sum(m0.yy)+0.00)/sum(m0.yy+m0.ny)) as pod, ((sum(m0.yn)+0.00)/sum(m0.yn+m0.yy)) as far, " + - "sum(m0.yy+m0.ny) as oy_all, sum(m0.yn+m0.nn) as on_all, group_concat(m0.valid_time, ';', m0.yy, ';', " + - "m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0 " + + "((sum(m0.yy)+0.00)/sum(m0.yy+m0.yn)) as pod, ((sum(m0.ny)+0.00)/sum(m0.ny+m0.yy)) as far, " + + "sum(m0.yy+m0.yn) as oy_all, sum(m0.ny+m0.nn) as on_all, group_concat(m0.time, ';', m0.yy, ';', " + + "m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0 " + "{{queryTableClause}} " + "where 1=1 " + "{{dateClause}} " + diff --git a/apps/ensemble/server/dataFunctions/data_series.js b/apps/ensemble/server/dataFunctions/data_series.js index 7a929ba26b..efe9d2e739 100644 --- a/apps/ensemble/server/dataFunctions/data_series.js +++ b/apps/ensemble/server/dataFunctions/data_series.js @@ -47,8 +47,11 @@ dataSeries = function (plotParams, plotFunction) { const curve = curves[curveIndex]; const { diffFrom } = curve; const { label } = curve; + var { variable } = curve; + const databaseRef = matsCollections.variable.findOne({ name: "variable" }) + .optionsMap[variable]; const model = matsCollections["data-source"].findOne({ name: "data-source" }) - .optionsMap[curve["data-source"]][0]; + .optionsMap[variable][curve["data-source"]][0]; var regionStr = curve.region; const region = Object.keys( matsCollections.region.findOne({ name: "region" }).valuesMap @@ -56,29 +59,33 @@ dataSeries = function (plotParams, plotFunction) { (key) => matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr ); - const source = curve.truth; - let sourceStr = ""; - if (source !== "All") { - sourceStr = `_${source}`; - } - const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var scaleStr = curve.scale; + const grid_scale = Object.keys( + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable] + ).find( + (key) => + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] === + scaleStr + ); + const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`; var thresholdStr = curve.threshold; const threshold = Object.keys( - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable] ).find( (key) => - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === - thresholdStr + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable][ + key + ] === thresholdStr ); - const thresholdClause = `and m0.thresh = ${threshold}`; + const thresholdClause = `and m0.trsh = ${threshold / 10000}`; let validTimeClause = ""; const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) { - validTimeClause = `and floor((m0.valid_time)%(24*3600)/3600) IN(${validTimes})`; + validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`; } let forecastLength = curve["forecast-length"]; const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; - const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`; const averageStr = curve.average; const averageOptionsMap = matsCollections.average.findOne( { name: "average" }, @@ -91,7 +98,7 @@ dataSeries = function (plotParams, plotFunction) { { optionsMap: 1 } ).optionsMap; const statisticClause = - "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0"; // axisKey is used to determine which axis a curve should use. // This axisKeySet object is used like a set and if a curve has the same // units (axisKey) it will use the same axis. @@ -110,9 +117,9 @@ dataSeries = function (plotParams, plotFunction) { // prepare the query from the above parameters let statement = "select {{average}} as avtime, " + - "count(distinct m0.valid_time) as N_times, " + - "min(m0.valid_time) as min_secs, " + - "max(m0.valid_time) as max_secs, " + + "count(distinct m0.time) as N_times, " + + "min(m0.time) as min_secs, " + + "max(m0.time) as max_secs, " + "{{statisticClause}} " + "{{queryTableClause}} " + "where 1=1 " + @@ -179,7 +186,14 @@ dataSeries = function (plotParams, plotFunction) { } else { // this is an error returned by the mysql database error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; - throw new Error(error); + if (error.includes("ER_NO_SUCH_TABLE")) { + throw new Error( + `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` + + `Choose a different scale to continue using this region.` + ); + } else { + throw new Error(error); + } } } else { dataFoundForAnyCurve = true; diff --git a/apps/ensemble/server/dataFunctions/data_threshold.js b/apps/ensemble/server/dataFunctions/data_threshold.js index 1e8b3b36da..7e5d769ea3 100644 --- a/apps/ensemble/server/dataFunctions/data_threshold.js +++ b/apps/ensemble/server/dataFunctions/data_threshold.js @@ -44,8 +44,11 @@ dataThreshold = function (plotParams, plotFunction) { const curve = curves[curveIndex]; const { diffFrom } = curve; const { label } = curve; + var { variable } = curve; + const databaseRef = matsCollections.variable.findOne({ name: "variable" }) + .optionsMap[variable]; const model = matsCollections["data-source"].findOne({ name: "data-source" }) - .optionsMap[curve["data-source"]][0]; + .optionsMap[variable][curve["data-source"]][0]; var regionStr = curve.region; const region = Object.keys( matsCollections.region.findOne({ name: "region" }).valuesMap @@ -53,31 +56,33 @@ dataThreshold = function (plotParams, plotFunction) { (key) => matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr ); - const source = curve.truth; - let sourceStr = ""; - if (source !== "All") { - sourceStr = `_${source}`; - } - const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; - const thresholdClause = ""; + var scaleStr = curve.scale; + const grid_scale = Object.keys( + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable] + ).find( + (key) => + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] === + scaleStr + ); + const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`; let validTimeClause = ""; const validTimes = curve["valid-time"] === undefined ? [] : curve["valid-time"]; if (validTimes.length !== 0 && validTimes !== matsTypes.InputTypes.unused) { - validTimeClause = `and floor((m0.valid_time)%(24*3600)/3600) IN(${validTimes})`; + validTimeClause = `and floor((m0.time)%(24*3600)/3600) IN(${validTimes})`; } const forecastLength = curve["forecast-length"]; const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]); const fromSecs = dateRange.fromSeconds; const toSecs = dateRange.toSeconds; - const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`; const statisticSelect = curve.statistic; const statisticOptionsMap = matsCollections.statistic.findOne( { name: "statistic" }, { optionsMap: 1 } ).optionsMap; const statisticClause = - "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0"; // axisKey is used to determine which axis a curve should use. // This axisKeySet object is used like a set and if a curve has the same // units (axisKey) it will use the same axis. @@ -95,15 +100,14 @@ dataThreshold = function (plotParams, plotFunction) { // this is a database driven curve, not a difference curve // prepare the query from the above parameters let statement = - "select m0.thresh/100 as thresh, " + // produces thresholds in inches - "count(distinct m0.valid_time) as N_times, " + - "min(m0.valid_time) as min_secs, " + - "max(m0.valid_time) as max_secs, " + + "select m0.trsh as thresh, " + + "count(distinct m0.time) as N_times, " + + "min(m0.time) as min_secs, " + + "max(m0.time) as max_secs, " + "{{statisticClause}} " + "{{queryTableClause}} " + "where 1=1 " + "{{dateClause}} " + - "{{thresholdClause}} " + "{{validTimeClause}} " + "{{forecastLengthClause}} " + "group by thresh " + @@ -112,7 +116,6 @@ dataThreshold = function (plotParams, plotFunction) { statement = statement.replace("{{statisticClause}}", statisticClause); statement = statement.replace("{{queryTableClause}}", queryTableClause); - statement = statement.replace("{{thresholdClause}}", thresholdClause); statement = statement.replace("{{validTimeClause}}", validTimeClause); statement = statement.replace("{{forecastLengthClause}}", forecastLengthClause); statement = statement.replace("{{dateClause}}", dateClause); @@ -152,7 +155,14 @@ dataThreshold = function (plotParams, plotFunction) { } else { // this is an error returned by the mysql database error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; - throw new Error(error); + if (error.includes("ER_NO_SUCH_TABLE")) { + throw new Error( + `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` + + `Choose a different scale to continue using this region.` + ); + } else { + throw new Error(error); + } } } else { dataFoundForAnyCurve = true; diff --git a/apps/ensemble/server/dataFunctions/data_validtime.js b/apps/ensemble/server/dataFunctions/data_validtime.js index 6df0ed4397..006c9be2e6 100644 --- a/apps/ensemble/server/dataFunctions/data_validtime.js +++ b/apps/ensemble/server/dataFunctions/data_validtime.js @@ -44,8 +44,11 @@ dataValidTime = function (plotParams, plotFunction) { const curve = curves[curveIndex]; const { diffFrom } = curve; const { label } = curve; + var { variable } = curve; + const databaseRef = matsCollections.variable.findOne({ name: "variable" }) + .optionsMap[variable]; const model = matsCollections["data-source"].findOne({ name: "data-source" }) - .optionsMap[curve["data-source"]][0]; + .optionsMap[variable][curve["data-source"]][0]; var regionStr = curve.region; const region = Object.keys( matsCollections.region.findOne({ name: "region" }).valuesMap @@ -53,34 +56,38 @@ dataValidTime = function (plotParams, plotFunction) { (key) => matsCollections.region.findOne({ name: "region" }).valuesMap[key] === regionStr ); - const source = curve.truth; - let sourceStr = ""; - if (source !== "All") { - sourceStr = `_${source}`; - } - const queryTableClause = `from ${model}_${region}${sourceStr} as m0`; + var scaleStr = curve.scale; + const grid_scale = Object.keys( + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable] + ).find( + (key) => + matsCollections.scale.findOne({ name: "scale" }).valuesMap[variable][key] === + scaleStr + ); + const queryTableClause = `from ${databaseRef}.${model}_${grid_scale}_${region} as m0`; var thresholdStr = curve.threshold; const threshold = Object.keys( - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable] ).find( (key) => - matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[key] === - thresholdStr + matsCollections.threshold.findOne({ name: "threshold" }).valuesMap[variable][ + key + ] === thresholdStr ); - const thresholdClause = `and m0.thresh = ${threshold}`; + const thresholdClause = `and m0.trsh = ${threshold / 10000}`; const forecastLength = curve["forecast-length"]; const forecastLengthClause = `and m0.fcst_len = ${forecastLength}`; const dateRange = matsDataUtils.getDateRange(curve["curve-dates"]); const fromSecs = dateRange.fromSeconds; const toSecs = dateRange.toSeconds; - const dateClause = `and m0.valid_time >= ${fromSecs} and m0.valid_time <= ${toSecs}`; + const dateClause = `and m0.time >= ${fromSecs} and m0.time <= ${toSecs}`; const statisticSelect = curve.statistic; const statisticOptionsMap = matsCollections.statistic.findOne( { name: "statistic" }, { optionsMap: 1 } ).optionsMap; const statisticClause = - "sum(m0.yy) as hit, sum(m0.yn) as fa, sum(m0.ny) as miss, sum(m0.nn) as cn, group_concat(m0.valid_time, ';', m0.yy, ';', m0.yn, ';', m0.ny, ';', m0.nn order by m0.valid_time) as sub_data, count(m0.yy) as N0"; + "sum(m0.yy) as hit, sum(m0.ny) as fa, sum(m0.yn) as miss, sum(m0.nn) as cn, group_concat(m0.time, ';', m0.yy, ';', m0.ny, ';', m0.yn, ';', m0.nn order by m0.time) as sub_data, count(m0.yy) as N0"; // axisKey is used to determine which axis a curve should use. // This axisKeySet object is used like a set and if a curve has the same // units (axisKey) it will use the same axis. @@ -98,10 +105,10 @@ dataValidTime = function (plotParams, plotFunction) { // this is a database driven curve, not a difference curve // prepare the query from the above parameters let statement = - "select floor(m0.valid_time%(24*3600)/3600) as hr_of_day, " + - "count(distinct m0.valid_time) as N_times, " + - "min(m0.valid_time) as min_secs, " + - "max(m0.valid_time) as max_secs, " + + "select floor(m0.time%(24*3600)/3600) as hr_of_day, " + + "count(distinct m0.time) as N_times, " + + "min(m0.time) as min_secs, " + + "max(m0.time) as max_secs, " + "{{statisticClause}} " + "{{queryTableClause}} " + "where 1=1 " + @@ -153,7 +160,14 @@ dataValidTime = function (plotParams, plotFunction) { } else { // this is an error returned by the mysql database error += `Error from verification query:
${queryResult.error}
query:
${statement}
`; - throw new Error(error); + if (error.includes("ER_NO_SUCH_TABLE")) { + throw new Error( + `INFO: The region/scale combination [${regionStr} and ${scaleStr}] is not supported by the database for the model [${model}]. ` + + `Choose a different scale to continue using this region.` + ); + } else { + throw new Error(error); + } } } else { dataFoundForAnyCurve = true; diff --git a/apps/ensemble/server/main.js b/apps/ensemble/server/main.js index 498df19815..b05aa6c1ae 100644 --- a/apps/ensemble/server/main.js +++ b/apps/ensemble/server/main.js @@ -13,6 +13,15 @@ import { matsCouchbaseUtils, } from "meteor/randyp:mats-common"; +// This app combines three previous apps, cref, echotop, and vil. +// This is where we store the databases referenced by those apps. +const variableDBNames = { + "Composite Reflectivity": "cref", + "Echo Top": "echotop", + "Vertically Integrated Liquid": "vil", +}; +const variables = Object.keys(variableDBNames); + // determined in doCurveParanms let minDate; let maxDate; @@ -33,7 +42,7 @@ const doPlotParams = function () { options: [""], startDate: minDate, stopDate: maxDate, - superiorNames: ["data-source"], + superiorNames: ["variable", "data-source"], controlButtonCovered: true, default: dstr, controlButtonVisibility: "block", @@ -226,12 +235,11 @@ const doPlotParams = function () { const xOptionsMap = { "Fcst lead time": "select m0.fcst_len as xVal, ", - Threshold: "select m0.thresh/100 as xVal, ", // produces thresholds in in - "Valid UTC hour": "select m0.valid_time%(24*3600)/3600 as xVal, ", - "Init UTC hour": - "select (m0.valid_time-m0.fcst_len*3600)%(24*3600)/3600 as xVal, ", - "Valid Date": "select m0.valid_time as xVal, ", - "Init Date": "select m0.valid_time-m0.fcst_len*3600 as xVal, ", + Threshold: "select m0.trsh as xVal, ", + "Valid UTC hour": "select m0.time%(24*3600)/3600 as xVal, ", + "Init UTC hour": "select (m0.time-m0.fcst_len*3600)%(24*3600)/3600 as xVal, ", + "Valid Date": "select m0.time as xVal, ", + "Init Date": "select m0.time-m0.fcst_len*3600 as xVal, ", }; matsCollections.PlotParams.insert({ @@ -251,11 +259,11 @@ const doPlotParams = function () { const yOptionsMap = { "Fcst lead time": "m0.fcst_len as yVal, ", - Threshold: "m0.thresh/100 as yVal, ", // produces thresholds in in - "Valid UTC hour": "m0.valid_time%(24*3600)/3600 as yVal, ", - "Init UTC hour": "(m0.valid_time-m0.fcst_len*3600)%(24*3600)/3600 as yVal, ", - "Valid Date": "m0.valid_time as yVal, ", - "Init Date": "m0.valid_time-m0.fcst_len*3600 as yVal, ", + Threshold: "m0.trsh as yVal, ", + "Valid UTC hour": "m0.time%(24*3600)/3600 as yVal, ", + "Init UTC hour": "(m0.time-m0.fcst_len*3600)%(24*3600)/3600 as yVal, ", + "Valid Date": "m0.time as yVal, ", + "Init Date": "m0.time-m0.fcst_len*3600 as yVal, ", }; matsCollections.PlotParams.insert({ @@ -266,7 +274,7 @@ const doPlotParams = function () { selected: "", controlButtonCovered: true, unique: false, - default: Object.keys(yOptionsMap)[0], + default: Object.keys(yOptionsMap)[1], controlButtonVisibility: "block", displayOrder: 10, displayPriority: 1, @@ -324,14 +332,16 @@ const doCurveParams = function () { matsCollections[params[cp]].remove({}); } } + const modelOptionsMap = {}; let modelDateRangeMap = {}; const regionModelOptionsMap = {}; const forecastLengthOptionsMap = {}; const thresholdsModelOptionsMap = {}; - const sourceOptionsMap = {}; + const scaleModelOptionsMap = {}; const masterRegionValuesMap = {}; const masterThresholdValuesMap = {}; + const masterScaleValuesMap = {}; try { const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous( @@ -349,77 +359,129 @@ const doCurveParams = function () { console.log(err.message); } + let rows; + let didx; + try { - const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous( - modelPool, - "select trsh,description from threshold_descriptions;" - ); - let masterDescription; - let masterTrsh; - for (var j = 0; j < rows.length; j++) { - masterDescription = rows[j].description.trim(); - masterTrsh = rows[j].trsh.trim(); - masterThresholdValuesMap[masterTrsh] = masterDescription; + for (didx = 0; didx < variables.length; didx++) { + masterThresholdValuesMap[variables[didx]] = {}; + rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous( + sumPool, + `select trsh,description from ${ + variableDBNames[variables[didx]] + }.threshold_descriptions;` + ); + var masterDescription; + var masterTrsh; + var trshTemp; + for (var j = 0; j < rows.length; j++) { + masterDescription = rows[j].description.trim(); + trshTemp = rows[j].trsh.trim(); + masterTrsh = trshTemp * 10000; + masterThresholdValuesMap[variables[didx]][masterTrsh] = masterDescription; + } } } catch (err) { console.log(err.message); } try { - const rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous( - sumPool, - "select model,regions,sources,display_text,fcst_lens,trsh,mindate,maxdate from regions_per_model_mats_all_categories order by display_category, display_order;" - ); - for (let i = 0; i < rows.length; i++) { - const model_value = rows[i].model.trim(); - const model = rows[i].display_text.trim(); - modelOptionsMap[model] = [model_value]; - - const rowMinDate = moment.utc(rows[i].mindate * 1000).format("MM/DD/YYYY HH:mm"); - const rowMaxDate = moment.utc(rows[i].maxdate * 1000).format("MM/DD/YYYY HH:mm"); - modelDateRangeMap[model] = { minDate: rowMinDate, maxDate: rowMaxDate }; - - const { sources } = rows[i]; - const sourceArr = sources - .split(",") - .map(Function.prototype.call, String.prototype.trim); - for (var j = 0; j < sourceArr.length; j++) { - sourceArr[j] = sourceArr[j].replace(/'|\[|\]/g, ""); - } - sourceOptionsMap[model] = sourceArr; - - const forecastLengths = rows[i].fcst_lens; - const forecastLengthArr = forecastLengths - .split(",") - .map(Function.prototype.call, String.prototype.trim); - for (var j = 0; j < forecastLengthArr.length; j++) { - forecastLengthArr[j] = forecastLengthArr[j].replace(/'|\[|\]/g, ""); - } - forecastLengthOptionsMap[model] = forecastLengthArr; - - const thresholds = rows[i].trsh; - const thresholdsArrRaw = thresholds - .split(",") - .map(Function.prototype.call, String.prototype.trim); - const thresholdsArr = []; - var dummyThresh; - for (var j = 0; j < thresholdsArrRaw.length; j++) { - dummyThresh = thresholdsArrRaw[j].replace(/'|\[|\]/g, ""); - thresholdsArr.push(masterThresholdValuesMap[dummyThresh]); + for (didx = 0; didx < variables.length; didx++) { + masterScaleValuesMap[variables[didx]] = {}; + rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous( + sumPool, + `select scale,description from ${ + variableDBNames[variables[didx]] + }.scale_descriptions;` + ); + var masterDescription; + var masterScale; + for (var j = 0; j < rows.length; j++) { + masterDescription = rows[j].description.trim(); + masterScale = rows[j].scale.trim(); + masterScaleValuesMap[variables[didx]][masterScale] = masterDescription; } - thresholdsModelOptionsMap[model] = thresholdsArr; - - const { regions } = rows[i]; - const regionsArrRaw = regions - .split(",") - .map(Function.prototype.call, String.prototype.trim); - const regionsArr = []; - var dummyRegion; - for (var j = 0; j < regionsArrRaw.length; j++) { - dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, ""); - regionsArr.push(masterRegionValuesMap[dummyRegion]); + } + } catch (err) { + console.log(err.message); + } + + try { + for (didx = 0; didx < variables.length; didx++) { + modelOptionsMap[variables[didx]] = {}; + modelDateRangeMap[variables[didx]] = {}; + forecastLengthOptionsMap[variables[didx]] = {}; + thresholdsModelOptionsMap[variables[didx]] = {}; + scaleModelOptionsMap[variables[didx]] = {}; + regionModelOptionsMap[variables[didx]] = {}; + + rows = matsDataQueryUtils.simplePoolQueryWrapSynchronous( + sumPool, + `select model,regions,display_text,fcst_lens,trsh,scale,mindate,maxdate from ${ + variableDBNames[variables[didx]] + }.regions_per_model_mats_all_categories order by display_category, display_order;` + ); + for (let i = 0; i < rows.length; i++) { + const model_value = rows[i].model.trim(); + const model = rows[i].display_text.trim(); + modelOptionsMap[variables[didx]][model] = [model_value]; + + const rowMinDate = moment + .utc(rows[i].mindate * 1000) + .format("MM/DD/YYYY HH:mm"); + const rowMaxDate = moment + .utc(rows[i].maxdate * 1000) + .format("MM/DD/YYYY HH:mm"); + modelDateRangeMap[variables[didx]][model] = { + minDate: rowMinDate, + maxDate: rowMaxDate, + }; + + const forecastLengths = rows[i].fcst_lens; + const forecastLengthArr = forecastLengths + .split(",") + .map(Function.prototype.call, String.prototype.trim); + for (var j = 0; j < forecastLengthArr.length; j++) { + forecastLengthArr[j] = forecastLengthArr[j].replace(/'|\[|\]/g, ""); + } + forecastLengthOptionsMap[variables[didx]][model] = forecastLengthArr; + + const thresholds = rows[i].trsh; + const thresholdsArrRaw = thresholds + .split(",") + .map(Function.prototype.call, String.prototype.trim); + const thresholdsArr = []; + var dummyThresh; + for (var j = 0; j < thresholdsArrRaw.length; j++) { + dummyThresh = thresholdsArrRaw[j].replace(/'|\[|\]/g, "") * 10000; + thresholdsArr.push(masterThresholdValuesMap[variables[didx]][dummyThresh]); + } + thresholdsModelOptionsMap[variables[didx]][model] = thresholdsArr; + + const scales = rows[i].scale; + const scalesArrRaw = scales + .split(",") + .map(Function.prototype.call, String.prototype.trim); + const scalesArr = []; + var dummyScale; + for (var j = 0; j < scalesArrRaw.length; j++) { + dummyScale = scalesArrRaw[j].replace(/'|\[|\]/g, ""); + scalesArr.push(masterScaleValuesMap[variables[didx]][dummyScale]); + } + scaleModelOptionsMap[variables[didx]][model] = scalesArr; + + const { regions } = rows[i]; + const regionsArrRaw = regions + .split(",") + .map(Function.prototype.call, String.prototype.trim); + const regionsArr = []; + var dummyRegion; + for (var j = 0; j < regionsArrRaw.length; j++) { + dummyRegion = regionsArrRaw[j].replace(/'|\[|\]/g, ""); + regionsArr.push(masterRegionValuesMap[dummyRegion]); + } + regionModelOptionsMap[variables[didx]][model] = regionsArr; } - regionModelOptionsMap[model] = regionsArr; } } catch (err) { console.log(err.message); @@ -442,23 +504,55 @@ const doCurveParams = function () { }); } + if (matsCollections.variable.findOne({ name: "variable" }) === undefined) { + matsCollections.variable.insert({ + name: "variable", + type: matsTypes.InputTypes.select, + optionsMap: variableDBNames, + options: variables, + dates: modelDateRangeMap, + dependentNames: ["data-source"], + controlButtonCovered: true, + default: variables[0], + unique: false, + controlButtonVisibility: "block", + displayOrder: 2, + displayPriority: 1, + displayGroup: 1, + }); + } else { + // it is defined but check for necessary update + var currentParam = matsCollections.variable.findOne({ name: "variable" }); + if (!matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap)) { + // have to reload variable data + matsCollections.variable.update( + { name: "variable" }, + { + $set: { + dates: modelDateRangeMap, + }, + } + ); + } + } + if (matsCollections["data-source"].findOne({ name: "data-source" }) === undefined) { matsCollections["data-source"].insert({ name: "data-source", type: matsTypes.InputTypes.select, optionsMap: modelOptionsMap, - dates: modelDateRangeMap, - options: Object.keys(modelOptionsMap), + options: Object.keys(modelOptionsMap[variables[0]]), + superiorNames: ["variable"], dependentNames: [ "region", "forecast-length", "threshold", - "truth", + "scale", "dates", "curve-dates", ], controlButtonCovered: true, - default: Object.keys(modelOptionsMap)[0], + default: Object.keys(modelOptionsMap[variables[0]])[0], unique: false, controlButtonVisibility: "block", displayOrder: 3, @@ -468,19 +562,15 @@ const doCurveParams = function () { } else { // it is defined but check for necessary update var currentParam = matsCollections["data-source"].findOne({ name: "data-source" }); - if ( - !matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap) || - !matsDataUtils.areObjectsEqual(currentParam.dates, modelDateRangeMap) - ) { + if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, modelOptionsMap)) { // have to reload model data matsCollections["data-source"].update( { name: "data-source" }, { $set: { optionsMap: modelOptionsMap, - dates: modelDateRangeMap, - options: Object.keys(modelOptionsMap), - default: Object.keys(modelOptionsMap)[0], + options: Object.keys(modelOptionsMap[variables[0]]), + default: Object.keys(modelOptionsMap[variables[0]])[0], }, } ); @@ -492,12 +582,18 @@ const doCurveParams = function () { name: "region", type: matsTypes.InputTypes.select, optionsMap: regionModelOptionsMap, - options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]], + options: + regionModelOptionsMap[variables[0]][ + Object.keys(regionModelOptionsMap[variables[0]])[0] + ], valuesMap: masterRegionValuesMap, - superiorNames: ["data-source"], + superiorNames: ["variable", "data-source"], controlButtonCovered: true, unique: false, - default: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]][0], + default: + regionModelOptionsMap[variables[0]][ + Object.keys(regionModelOptionsMap[variables[0]])[0] + ][0], controlButtonVisibility: "block", displayOrder: 2, displayPriority: 1, @@ -517,8 +613,14 @@ const doCurveParams = function () { $set: { optionsMap: regionModelOptionsMap, valuesMap: masterRegionValuesMap, - options: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]], - default: regionModelOptionsMap[Object.keys(regionModelOptionsMap)[0]][0], + options: + regionModelOptionsMap[variables[0]][ + Object.keys(regionModelOptionsMap[variables[0]])[0] + ], + default: + regionModelOptionsMap[variables[0]][ + Object.keys(regionModelOptionsMap[variables[0]])[0] + ][0], }, } ); @@ -587,12 +689,18 @@ const doCurveParams = function () { name: "threshold", type: matsTypes.InputTypes.select, optionsMap: thresholdsModelOptionsMap, - options: thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]], + options: + thresholdsModelOptionsMap[variables[0]][ + Object.keys(thresholdsModelOptionsMap[variables[0]])[0] + ], valuesMap: masterThresholdValuesMap, - superiorNames: ["data-source"], + superiorNames: ["variable", "data-source"], controlButtonCovered: true, unique: false, - default: thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]][0], + default: + thresholdsModelOptionsMap[variables[0]][ + Object.keys(thresholdsModelOptionsMap[variables[0]])[0] + ][0], controlButtonVisibility: "block", displayOrder: 1, displayPriority: 1, @@ -616,42 +724,63 @@ const doCurveParams = function () { optionsMap: thresholdsModelOptionsMap, valuesMap: masterThresholdValuesMap, options: - thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]], + thresholdsModelOptionsMap[variables[0]][ + Object.keys(thresholdsModelOptionsMap[variables[0]])[0] + ], default: - thresholdsModelOptionsMap[Object.keys(thresholdsModelOptionsMap)[0]][0], + thresholdsModelOptionsMap[variables[0]][ + Object.keys(thresholdsModelOptionsMap[variables[0]])[0] + ][0], }, } ); } } - if (matsCollections.truth.find({ name: "truth" }).count() === 0) { - matsCollections.truth.insert({ - name: "truth", + if (matsCollections.scale.findOne({ name: "scale" }) === undefined) { + matsCollections.scale.insert({ + name: "scale", type: matsTypes.InputTypes.select, - optionsMap: sourceOptionsMap, - options: sourceOptionsMap[Object.keys(sourceOptionsMap)[0]], - superiorNames: ["data-source"], + optionsMap: scaleModelOptionsMap, + options: + scaleModelOptionsMap[variables[0]][ + Object.keys(scaleModelOptionsMap[variables[0]])[0] + ], + valuesMap: masterScaleValuesMap, + superiorNames: ["variable", "data-source"], controlButtonCovered: true, unique: false, - default: sourceOptionsMap[Object.keys(sourceOptionsMap)[0]][0], + default: + scaleModelOptionsMap[variables[0]][ + Object.keys(scaleModelOptionsMap[variables[0]])[0] + ][0], controlButtonVisibility: "block", - displayOrder: 3, + displayOrder: 2, displayPriority: 1, displayGroup: 3, }); } else { // it is defined but check for necessary update - var currentParam = matsCollections.truth.findOne({ name: "truth" }); - if (!matsDataUtils.areObjectsEqual(currentParam.optionsMap, sourceOptionsMap)) { - // have to reload truth data - matsCollections.truth.update( - { name: "truth" }, + var currentParam = matsCollections.scale.findOne({ name: "scale" }); + if ( + !matsDataUtils.areObjectsEqual(currentParam.optionsMap, scaleModelOptionsMap) || + !matsDataUtils.areObjectsEqual(currentParam.valuesMap, masterScaleValuesMap) + ) { + // have to reload scale data + matsCollections.scale.update( + { name: "scale" }, { $set: { - optionsMap: sourceOptionsMap, - options: sourceOptionsMap[Object.keys(sourceOptionsMap)[0]], - default: sourceOptionsMap[Object.keys(sourceOptionsMap)[0]][0], + optionsMap: scaleModelOptionsMap, + valuesMap: masterScaleValuesMap, + options: + scaleModelOptionsMap[variables[0]][ + Object.keys(scaleModelOptionsMap[variables[0]])[0] + ], + default: + scaleModelOptionsMap[variables[0]][ + Object.keys(scaleModelOptionsMap[variables[0]])[0] + ][0], }, } ); @@ -666,8 +795,11 @@ const doCurveParams = function () { name: "forecast-length", type: matsTypes.InputTypes.select, optionsMap: forecastLengthOptionsMap, - options: forecastLengthOptionsMap[Object.keys(forecastLengthOptionsMap)[0]], - superiorNames: ["data-source"], + options: + forecastLengthOptionsMap[variables[0]][ + Object.keys(forecastLengthOptionsMap[variables[0]])[0] + ], + superiorNames: ["variable", "data-source"], selected: "", controlButtonCovered: true, unique: false, @@ -692,7 +824,10 @@ const doCurveParams = function () { { $set: { optionsMap: forecastLengthOptionsMap, - options: forecastLengthOptionsMap[Object.keys(forecastLengthOptionsMap)[0]], + options: + forecastLengthOptionsMap[variables[0]][ + Object.keys(forecastLengthOptionsMap[variables[0]])[0] + ], }, } ); @@ -825,40 +960,34 @@ const doCurveParams = function () { if (matsCollections.average.findOne({ name: "average" }) === undefined) { const optionsMap = { - None: [`ceil(${3600}*floor(((m0.valid_time)+${3600}/2)/${3600}))`], - "3hr": [`ceil(${3600 * 3}*floor(((m0.valid_time)+${3600 * 3}/2)/${3600 * 3}))`], - "6hr": [`ceil(${3600 * 6}*floor(((m0.valid_time)+${3600 * 6}/2)/${3600 * 6}))`], - "12hr": [ - `ceil(${3600 * 12}*floor(((m0.valid_time)+${3600 * 12}/2)/${3600 * 12}))`, - ], - "1D": [`ceil(${3600 * 24}*floor(((m0.valid_time)+${3600 * 24}/2)/${3600 * 24}))`], + None: [`ceil(${3600}*floor(((m0.time)+${3600}/2)/${3600}))`], + "3hr": [`ceil(${3600 * 3}*floor(((m0.time)+${3600 * 3}/2)/${3600 * 3}))`], + "6hr": [`ceil(${3600 * 6}*floor(((m0.time)+${3600 * 6}/2)/${3600 * 6}))`], + "12hr": [`ceil(${3600 * 12}*floor(((m0.time)+${3600 * 12}/2)/${3600 * 12}))`], + "1D": [`ceil(${3600 * 24}*floor(((m0.time)+${3600 * 24}/2)/${3600 * 24}))`], "3D": [ - `ceil(${3600 * 24 * 3}*floor(((m0.valid_time)+${3600 * 24 * 3}/2)/${ - 3600 * 24 * 3 - }))`, + `ceil(${3600 * 24 * 3}*floor(((m0.time)+${3600 * 24 * 3}/2)/${3600 * 24 * 3}))`, ], "7D": [ - `ceil(${3600 * 24 * 7}*floor(((m0.valid_time)+${3600 * 24 * 7}/2)/${ - 3600 * 24 * 7 - }))`, + `ceil(${3600 * 24 * 7}*floor(((m0.time)+${3600 * 24 * 7}/2)/${3600 * 24 * 7}))`, ], "30D": [ - `ceil(${3600 * 24 * 30}*floor(((m0.valid_time)+${3600 * 24 * 30}/2)/${ + `ceil(${3600 * 24 * 30}*floor(((m0.time)+${3600 * 24 * 30}/2)/${ 3600 * 24 * 30 }))`, ], "60D": [ - `ceil(${3600 * 24 * 60}*floor(((m0.valid_time)+${3600 * 24 * 60}/2)/${ + `ceil(${3600 * 24 * 60}*floor(((m0.time)+${3600 * 24 * 60}/2)/${ 3600 * 24 * 60 }))`, ], "90D": [ - `ceil(${3600 * 24 * 90}*floor(((m0.valid_time)+${3600 * 24 * 90}/2)/${ + `ceil(${3600 * 24 * 90}*floor(((m0.time)+${3600 * 24 * 90}/2)/${ 3600 * 24 * 90 }))`, ], "180D": [ - `ceil(${3600 * 24 * 180}*floor(((m0.valid_time)+${3600 * 24 * 180}/2)/${ + `ceil(${3600 * 24 * 180}*floor(((m0.time)+${3600 * 24 * 180}/2)/${ 3600 * 24 * 180 }))`, ], @@ -884,12 +1013,11 @@ const doCurveParams = function () { ) { const optionsMap = { "Fcst lead time": "select m0.fcst_len as binVal, ", - Threshold: "select m0.thresh/100 as binVal, ", - "Valid UTC hour": "select m0.valid_time%(24*3600)/3600 as binVal, ", - "Init UTC hour": - "select (m0.valid_time-m0.fcst_len*3600)%(24*3600)/3600 as binVal, ", - "Valid Date": "select m0.valid_time as binVal, ", - "Init Date": "select m0.valid_time-m0.fcst_len*3600 as binVal, ", + Threshold: "select m0.trsh as binVal, ", + "Valid UTC hour": "select m0.time%(24*3600)/3600 as binVal, ", + "Init UTC hour": "select (m0.time-m0.fcst_len*3600)%(24*3600)/3600 as binVal, ", + "Valid Date": "select m0.time as binVal, ", + "Init Date": "select m0.time-m0.fcst_len*3600 as binVal, ", }; matsCollections["bin-parameter"].insert({ @@ -907,23 +1035,27 @@ const doCurveParams = function () { unique: false, default: Object.keys(optionsMap)[4], controlButtonVisibility: "block", - displayOrder: 3, + displayOrder: 1, displayPriority: 1, displayGroup: 6, }); } // determine date defaults for dates and curveDates - const defaultDataSource = matsCollections["data-source"].findOne( - { name: "data-source" }, + const defaultDb = matsCollections.variable.findOne( + { name: "variable" }, { default: 1 } ).default; - modelDateRangeMap = matsCollections["data-source"].findOne( - { name: "data-source" }, + modelDateRangeMap = matsCollections.variable.findOne( + { name: "variable" }, { dates: 1 } ).dates; - minDate = modelDateRangeMap[defaultDataSource].minDate; - maxDate = modelDateRangeMap[defaultDataSource].maxDate; + const defaultDataSource = matsCollections["data-source"].findOne( + { name: "data-source" }, + { default: 1 } + ).default; + minDate = modelDateRangeMap[variables[0]][defaultDataSource].minDate; + maxDate = modelDateRangeMap[variables[0]][defaultDataSource].maxDate; // need to turn the raw max and min from the metadata into the last valid month of data const newDateRange = matsParamUtils.getMinMaxDates(minDate, maxDate); @@ -950,7 +1082,7 @@ const doCurveParams = function () { options: Object.keys(optionsMap).sort(), startDate: minDate, stopDate: maxDate, - superiorNames: ["data-source"], + superiorNames: ["variable", "data-source"], controlButtonCovered: true, unique: false, default: dstr, @@ -1006,23 +1138,25 @@ const doCurveTextPatterns = function () { ["", "label", ": "], ["", "data-source", " in "], ["", "region", ", "], - ["", "threshold", " "], - ["", "statistic", ", "], + ["", "scale", " "], + ["", "variable", " "], + ["", "statistic", " at "], + ["", "threshold", ", "], ["fcst_len: ", "forecast-length", "h, "], ["valid-time: ", "valid-time", ", "], - ["avg: ", "average", ", "], - ["", "truth", ""], + ["avg: ", "average", ""], ], displayParams: [ "label", + "variable", "data-source", "region", "statistic", "threshold", + "scale", "average", "forecast-length", "valid-time", - "truth", ], groupSize: 6, }); @@ -1032,24 +1166,26 @@ const doCurveTextPatterns = function () { ["", "label", ": "], ["", "data-source", " in "], ["", "region", ", "], - ["", "threshold", " "], - ["", "statistic", ", "], + ["", "scale", " "], + ["", "variable", " "], + ["", "statistic", " at "], + ["", "threshold", ", "], ["", "dieoff-type", ", "], ["valid-time: ", "valid-time", ", "], ["start utc: ", "utc-cycle-start", ", "], - ["", "truth", ", "], ["", "curve-dates", ""], ], displayParams: [ "label", + "variable", "data-source", "region", "statistic", "threshold", + "scale", "dieoff-type", "valid-time", "utc-cycle-start", - "truth", "curve-dates", ], groupSize: 6, @@ -1060,20 +1196,22 @@ const doCurveTextPatterns = function () { ["", "label", ": "], ["", "data-source", " in "], ["", "region", ", "], + ["", "scale", " "], + ["", "variable", " "], ["", "statistic", ", "], ["fcst_len: ", "forecast-length", "h, "], ["valid-time: ", "valid-time", ", "], - ["", "truth", ", "], ["", "curve-dates", ""], ], displayParams: [ "label", + "variable", "data-source", "region", "statistic", + "scale", "forecast-length", "valid-time", - "truth", "curve-dates", ], groupSize: 6, @@ -1084,20 +1222,22 @@ const doCurveTextPatterns = function () { ["", "label", ": "], ["", "data-source", " in "], ["", "region", ", "], - ["", "threshold", " "], - ["", "statistic", ", "], + ["", "scale", " "], + ["", "variable", " "], + ["", "statistic", " at "], + ["", "threshold", ", "], ["fcst_len: ", "forecast-length", "h, "], - ["", "truth", ", "], ["", "curve-dates", ""], ], displayParams: [ "label", + "variable", "data-source", "region", "statistic", "threshold", + "scale", "forecast-length", - "truth", "curve-dates", ], groupSize: 6, @@ -1108,19 +1248,21 @@ const doCurveTextPatterns = function () { ["", "label", ": "], ["", "data-source", " in "], ["", "region", ", "], - ["", "threshold", " "], - ["", "statistic", ", "], - ["start utc: ", "utc-cycle-start", ", "], - ["", "truth", ""], + ["", "scale", " "], + ["", "variable", " "], + ["", "statistic", " at "], + ["", "threshold", ", "], + ["start utc: ", "utc-cycle-start", ""], ], displayParams: [ "label", + "variable", "data-source", "region", "statistic", "threshold", + "scale", "utc-cycle-start", - "truth", ], groupSize: 6, }); @@ -1130,20 +1272,22 @@ const doCurveTextPatterns = function () { ["", "label", ": "], ["", "data-source", " in "], ["", "region", ", "], - ["", "threshold", " "], + ["", "scale", " "], + ["", "variable", " at "], + ["", "threshold", ", "], ["fcst_len: ", "forecast-length", "h, "], ["valid-time: ", "valid-time", ", "], - ["", "truth", ", "], ["", "curve-dates", ""], ], displayParams: [ "label", + "variable", "data-source", "region", "threshold", + "scale", "forecast-length", "valid-time", - "truth", "bin-parameter", "curve-dates", ], @@ -1155,22 +1299,24 @@ const doCurveTextPatterns = function () { ["", "label", ": "], ["", "data-source", " in "], ["", "region", ", "], - ["", "threshold", " "], - ["", "statistic", ", "], + ["", "scale", " "], + ["", "variable", " "], + ["", "statistic", " at "], + ["", "threshold", ", "], ["fcst_len: ", "forecast-length", "h, "], ["valid-time: ", "valid-time", ", "], - ["", "truth", ", "], ["", "curve-dates", ""], ], displayParams: [ "label", + "variable", "data-source", "region", "statistic", "threshold", + "scale", "forecast-length", "valid-time", - "truth", "curve-dates", ], groupSize: 6, @@ -1181,21 +1327,23 @@ const doCurveTextPatterns = function () { ["", "label", ": "], ["", "data-source", " in "], ["", "region", ", "], - ["", "threshold", " "], - ["", "statistic", ", "], + ["", "scale", " "], + ["", "variable", " "], + ["", "statistic", " at "], + ["", "threshold", ", "], ["fcst_len: ", "forecast-length", "h, "], - ["valid-time: ", "valid-time", ", "], - ["", "truth", ""], + ["valid-time: ", "valid-time", ""], ], displayParams: [ "label", + "variable", "data-source", "region", "statistic", "threshold", + "scale", "forecast-length", "valid-time", - "truth", ], groupSize: 6, }); @@ -1205,21 +1353,23 @@ const doCurveTextPatterns = function () { ["", "label", ": "], ["", "data-source", " in "], ["", "region", ", "], - ["", "threshold", " "], - ["", "statistic", ", "], + ["", "scale", " "], + ["", "variable", " "], + ["", "statistic", " at "], + ["", "threshold", ", "], ["fcst_len: ", "forecast-length", "h, "], - ["valid-time: ", "valid-time", ", "], - ["", "truth", ""], + ["valid-time: ", "valid-time", ""], ], displayParams: [ "label", + "variable", "data-source", "region", "statistic", "threshold", + "scale", "forecast-length", "valid-time", - "truth", ], groupSize: 6, }); @@ -1382,23 +1532,6 @@ Meteor.startup(function () { allPools.push({ pool: "metadataPool", role: matsTypes.DatabaseRoles.META_DATA }); } - const modelSettings = matsCollections.Databases.findOne( - { role: matsTypes.DatabaseRoles.MODEL_DATA, status: "active" }, - { - host: 1, - port: 1, - user: 1, - password: 1, - database: 1, - connectionLimit: 1, - } - ); - // the pool is intended to be global - if (modelSettings) { - modelPool = mysql.createPool(modelSettings); - allPools.push({ pool: "modelPool", role: matsTypes.DatabaseRoles.MODEL_DATA }); - } - const sumSettings = matsCollections.Databases.findOne( { role: matsTypes.DatabaseRoles.SUMS_DATA, @@ -1423,10 +1556,13 @@ Meteor.startup(function () { const mdr = new matsTypes.MetaDataDBRecord("metadataPool", "mats_common", [ "region_descriptions", ]); - mdr.addRecord("modelPool", "precip_mesonets2", ["threshold_descriptions"]); - mdr.addRecord("sumPool", "precip_mesonets2_sums", [ - "regions_per_model_mats_all_categories", - ]); + for (let didx = 0; didx < variables.length; didx++) { + mdr.addRecord("sumPool", variableDBNames[variables[didx]], [ + "threshold_descriptions", + "scale_descriptions", + "regions_per_model_mats_all_categories", + ]); + } try { matsMethods.resetApp({ appPools: allPools, From e6138737407991f1b2952e20be1f0dfaaa1a5759 Mon Sep 17 00:00:00 2001 From: Molly Smith Date: Tue, 13 Jun 2023 13:50:01 -0600 Subject: [PATCH 03/50] Updated static HTML templates --- static/applist.json | 193 ++++++++++++++++++++++++----------------- static/index.html | 5 +- static/mats.html | 5 +- static/metexpress.html | 2 +- 4 files changed, 121 insertions(+), 84 deletions(-) diff --git a/static/applist.json b/static/applist.json index e6162de5b3..66db24bfd0 100644 --- a/static/applist.json +++ b/static/applist.json @@ -1,81 +1,112 @@ -[{ - "app": "upperair", - "displayName": "Upper Air (RAOBS)", - "group": "Upper Air" -}, { - "app": "aircraft", - "displayName": "Upper Air (AMDAR)", - "group": "Upper Air" -}, { - "app": "anomalycor", - "displayName": "Anomaly Correlation", - "group": "Upper Air" -}, { - "app": "ceiling", - "displayName": "Ceiling", - "group": "Ceiling and Visibility" -}, { - "app": "ceiling15", - "displayName": "Ceiling 15 Min", - "group": "Ceiling and Visibility" -}, { - "app": "visibility", - "displayName": "Visibility", - "group": "Ceiling and Visibility" -}, { - "app": "visibility15", - "displayName": "Visibility 15 Min", - "group": "Ceiling and Visibility" -}, { - "app": "surface", - "displayName": "Surface", - "group": "Surface" -}, { - "app": "landuse", - "displayName": "Surface Land Use", - "group": "Surface" -}, { - "app": "surfrad", - "displayName": "Surface Radiation", - "group": "Surface" -}, { - "app": "precipGauge", - "displayName": "AQPI Precipitation", - "group": "Precipitation" -}, { - "app": "precipitation24hr", - "displayName": "24 Hour Precipitation", - "group": "Precipitation" -}, { - "app": "precipitationSub24hr", - "displayName": "Sub 24 Hour Precipitation", - "group": "Precipitation" -}, { - "app": "compositeReflectivity", - "displayName": "Composite Reflectivity", - "group": "Radar" -}, { - "app": "echotop", - "displayName": "Echo Top", - "group": "Radar" -}, { - "app": "vil", - "displayName": "Vertically Integrated Liquid", - "group": "Radar" -}, { - "app": "wfip2", - "displayName": "Wfip2", - "group": "Experimental" -}, { - "app": "met-upperair", - "displayName": "MET Upper Air", - "group": "MET Express" -}, { - "app": "met-anomalycor", - "displayName": "MET Anomaly Correlation", - "group": "MET Express" -}, { - "app": "met-surface", - "displayName": "MET Surface", - "group": "MET Express" -}] +[ + { + "app": "upperair", + "title": "Upper Air", + "group": "Upper Air" + }, + { + "app": "met-upperair", + "title": "MET Upper Air", + "group": "Upper Air" + }, + { + "app": "met-anomalycor", + "title": "MET Anomaly Correlation", + "group": "Upper Air" + }, + { + "app": "ceil-vis", + "title": "Ceiling and Visibility", + "group": "Ceiling and Visibility" + }, + { + "app": "cb-ceiling", + "title": "CB-Ceiling", + "group": "Ceiling and Visibility" + }, + { + "app": "ceil-vis15", + "title": "15 Minute Ceiling and Visibility", + "group": "Ceiling and Visibility" + }, + { + "app": "surface", + "title": "Surface", + "group": "Surface" + }, + { + "app": "met-surface", + "title": "MET Surface", + "group": "Surface" + }, + { + "app": "landuse", + "title": "Surface Land Use", + "group": "Surface" + }, + { + "app": "surfrad", + "title": "Surface Radiation", + "group": "Surface" + }, + { + "app": "met-airquality", + "title": "MET Air Quality", + "group": "Surface" + }, + { + "app": "precipAccum", + "title": "24 Hour / Sub 24 Hour Precipitation", + "group": "Precipitation By Accumulation Interval" + }, + { + "app": "precipGauge", + "title": "Gauge Precipitation", + "group": "Precipitation By Lead Time" + }, + { + "app": "precipitation1hr", + "title": "1 Hour Precipitation", + "group": "Precipitation By Lead Time" + }, + { + "app": "met-precip", + "title": "MET Precipitation", + "group": "Precipitation By Lead Time" + }, + { + "app": "ptype", + "title": "Precipitation Type", + "group": "Precipitation Type" + }, + { + "app": "radar", + "title": "Radar", + "group": "Radar" + }, + { + "app": "ensemble", + "title": "Ensemble", + "group": "Ensemble" + }, + { + "app": "met-ensemble", + "title": "MET Ensemble", + "group": "Ensemble" + }, + { + "app": "scorecard", + "title": "Scorecard", + "group": "Miscellaneous" + }, + { + "app": "met-cyclone", + "title": "MET Cyclone", + "group": "Miscellaneous" + }, + { + "app": "met-object", + "title": "MET Objects", + "group": "Miscellaneous" + } +] diff --git a/static/index.html b/static/index.html index 63e77e6c7f..e2066a4cd1 100644 --- a/static/index.html +++ b/static/index.html @@ -47,9 +47,12 @@ success(function (data) { for (var di = 0; di < data.length; di++) { data[di].itemColor = '#3366bb'; - if (data[di].group.startsWith("MET")) { + if (data[di].group.startsWith("met-")) { data[di].itemColor = 'darkorchid'; } + if (data[di].group.startsWith("cb-")) { + data[di].itemColor = 'teal'; + } if ($scope.items[data[di].group] == null) { $scope.items[data[di].group] = [data[di]]; $scope.groups.push(data[di].group); diff --git a/static/mats.html b/static/mats.html index 63e77e6c7f..e2066a4cd1 100644 --- a/static/mats.html +++ b/static/mats.html @@ -47,9 +47,12 @@ success(function (data) { for (var di = 0; di < data.length; di++) { data[di].itemColor = '#3366bb'; - if (data[di].group.startsWith("MET")) { + if (data[di].group.startsWith("met-")) { data[di].itemColor = 'darkorchid'; } + if (data[di].group.startsWith("cb-")) { + data[di].itemColor = 'teal'; + } if ($scope.items[data[di].group] == null) { $scope.items[data[di].group] = [data[di]]; $scope.groups.push(data[di].group); diff --git a/static/metexpress.html b/static/metexpress.html index 32a6840327..63b7383824 100644 --- a/static/metexpress.html +++ b/static/metexpress.html @@ -47,7 +47,7 @@ success(function (data) { for (var di = 0; di < data.length; di++) { - if (data[di].group.startsWith("MET")) { + if (data[di].group.startsWith("met-")) { data[di].itemColor = '#3366bb'; if ($scope.items[data[di].group] == null) { $scope.items[data[di].group] = [data[di]]; From fb30161f050eae24d6ccd2e8abed70690d6d98ec Mon Sep 17 00:00:00 2001 From: Molly Smith Date: Tue, 13 Jun 2023 13:58:29 -0600 Subject: [PATCH 04/50] Updated static HTML templates (correctly this time) --- static/index.html | 4 ++-- static/mats.html | 4 ++-- static/metexpress.html | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/static/index.html b/static/index.html index e2066a4cd1..52a6261cc3 100644 --- a/static/index.html +++ b/static/index.html @@ -47,10 +47,10 @@ success(function (data) { for (var di = 0; di < data.length; di++) { data[di].itemColor = '#3366bb'; - if (data[di].group.startsWith("met-")) { + if (data[di].app.startsWith("met-")) { data[di].itemColor = 'darkorchid'; } - if (data[di].group.startsWith("cb-")) { + if (data[di].app.startsWith("cb-")) { data[di].itemColor = 'teal'; } if ($scope.items[data[di].group] == null) { diff --git a/static/mats.html b/static/mats.html index e2066a4cd1..52a6261cc3 100644 --- a/static/mats.html +++ b/static/mats.html @@ -47,10 +47,10 @@ success(function (data) { for (var di = 0; di < data.length; di++) { data[di].itemColor = '#3366bb'; - if (data[di].group.startsWith("met-")) { + if (data[di].app.startsWith("met-")) { data[di].itemColor = 'darkorchid'; } - if (data[di].group.startsWith("cb-")) { + if (data[di].app.startsWith("cb-")) { data[di].itemColor = 'teal'; } if ($scope.items[data[di].group] == null) { diff --git a/static/metexpress.html b/static/metexpress.html index 63b7383824..de4974a16e 100644 --- a/static/metexpress.html +++ b/static/metexpress.html @@ -47,7 +47,7 @@ success(function (data) { for (var di = 0; di < data.length; di++) { - if (data[di].group.startsWith("met-")) { + if (data[di].app.startsWith("met-")) { data[di].itemColor = '#3366bb'; if ($scope.items[data[di].group] == null) { $scope.items[data[di].group] = [data[di]]; From c3bc6ab83be6b16e124f32c2eb05c9a92d216bca Mon Sep 17 00:00:00 2001 From: Molly Smith Date: Tue, 13 Jun 2023 15:41:20 -0600 Subject: [PATCH 05/50] Fixed links on static home pages --- static/index.html | 14 ++++++-------- static/mats.html | 14 ++++++-------- static/metexpress.html | 10 ++++------ 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/static/index.html b/static/index.html index 52a6261cc3..0124074512 100644 --- a/static/index.html +++ b/static/index.html @@ -142,7 +142,7 @@ style="color:white">U.S. Department of Commerce
  • National Oceanic and Atmospheric Administration
  • -
  • NOAA Research
  • @@ -172,7 +172,7 @@ @@ -172,7 +172,7 @@