({
+ defaultValues: protocol,
+ });
+ useDirty(isDirty);
+ const [ updateProtocol ] = useProtocolUpdateMutation();
+
+ const { fields: doses, append: appendDose, remove: removeDose } = useFieldArray({
+ control,
+ name: "doses",
+ });
+
+ useEffect(() => {
+ reset(protocol);
+ }, [protocol, reset]);
+
+ const handleSave = handleSubmit((data: Protocol) => {
+ if (JSON.stringify(data) !== JSON.stringify(protocol)) {
+ updateProtocol({ id: protocol.id, protocol: data })
+ }
+ });
+
+ // save protocol every second if dirty
+ useEffect(() => {
+ const intervalId = setInterval(() => {
+ if (isDirty) {
+ console.log('saving protocol')
+ handleSave();
+ }
+ }, 1000);
+
+ return () => clearInterval(intervalId);
+ }, [handleSave, isDirty]);
+
+
+ useEffect(() => () => { handleSave(); }, []);
+
+ if (isVariableLoading) {
+ return Loading...
;
+ }
+
+ if (!variable) {
+ return Variable not found
;
+ }
+
+ const handleAddRow = () => {
+ appendDose({ amount: 0, repeats: 0, start_time: 0, repeat_interval: 1 });
+ }
+
+ const handleDeleteRow = (index: number) => {
+ removeDose(index);
+ }
+
+ const isPreclinical = project.species !== 'H';
+
+ return (
+ <>
+ {doses.map((dose, index) => (
+
+
+ {variable.name}
+
+
+
+
+
+ { protocol.amount_unit && index === 0 && (
+ u.id === protocol.amount_unit)} isPreclinicalPerKg={isPreclinical} />
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ { protocol.time_unit && index === 0 && (
+ u.id === protocol.time_unit)}/>
+ )}
+
+
+ { index === 0 ? (
+
+
+
+ ) : (
+ handleDeleteRow(index)}>
+
+
+
+ )}
+
+
+ ))}
+ >
+ );
+};
+
+export default Doses;
diff --git a/frontend-v2/src/features/trial/Protocols.tsx b/frontend-v2/src/features/trial/Protocols.tsx
new file mode 100644
index 00000000..f5ff39b7
--- /dev/null
+++ b/frontend-v2/src/features/trial/Protocols.tsx
@@ -0,0 +1,69 @@
+// src/components/ProjectTable.tsx
+import React from "react";
+import { useSelector } from "react-redux";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableContainer,
+ TableHead,
+ TableRow,
+} from "@mui/material";
+import { useUnitListQuery, useProjectRetrieveQuery, useProtocolListQuery } from "../../app/backendApi";
+import { RootState } from "../../app/store";
+import Doses from "./Doses";
+import HelpButton from "../../components/HelpButton";
+
+
+const Protocols: React.FC = () => {
+ const selectedProject = useSelector((state: RootState) => state.main.selectedProject);
+ const { data: project, error: projectError, isLoading: isProjectLoading } = useProjectRetrieveQuery({id: selectedProject || 0}, { skip: !selectedProject })
+ const { data: protocols, error: protocolsError, isLoading: isProtocolsLoading } = useProtocolListQuery({projectId: selectedProject || 0}, { skip: !selectedProject })
+ const { data: units, isLoading: unitsLoading } = useUnitListQuery({ compoundId: project?.compound || 0}, { skip: !project?.compound})
+
+ if (isProjectLoading || isProtocolsLoading || unitsLoading) {
+ return Loading...
;
+ }
+
+ if (!project || !protocols || !units) {
+ return Project not found
;
+ }
+
+ const filteredProtocols = protocols?.filter((protocol) => protocol.variables.length > 0);
+
+
+ return (
+
+
+
+
+ Site of AdminDefined in Model/Map Variables
+ Dose
+ Dose UnitDefault selection: mg/kg for preclinical, mg for clinical
+ Number of Doses
+ Start TimeStart time of the first dose
+ Dose DurationDuration of dosing. For IV bolus PO/SC dosing use the default value 0.0833 h
+ Dosing Interval
+ Time Unit
+
+ Add Dose Line Adding an additional dosing line allows defining complex dosing regimens (e.g. changing dosing frequency and/or dosing levels)
+
+
+
+
+ {protocols?.length === 0 && (
+
+ No protocols found
+
+ )}
+ {filteredProtocols?.map((protocol) => (
+
+ ))}
+
+
+
+
+ );
+};
+
+export default Protocols;
diff --git a/frontend-v2/src/hooks/useDirty.ts b/frontend-v2/src/hooks/useDirty.ts
new file mode 100644
index 00000000..2a504137
--- /dev/null
+++ b/frontend-v2/src/hooks/useDirty.ts
@@ -0,0 +1,18 @@
+import { useDispatch } from "react-redux";
+import { decrementDirtyCount, incrementDirtyCount } from "../features/main/mainSlice";
+import { useEffect, useState } from "react";
+
+function useDirty(isDirty: boolean) {
+ const dispatch = useDispatch();
+ useEffect(() => {
+ if (isDirty) {
+ dispatch(incrementDirtyCount())
+ return () => {
+ dispatch(decrementDirtyCount())
+ };
+ }
+
+ }, [isDirty]);
+}
+
+export default useDirty;
\ No newline at end of file
diff --git a/frontend-v2/src/hooks/usePrevious.ts b/frontend-v2/src/hooks/usePrevious.ts
new file mode 100644
index 00000000..638b9d3f
--- /dev/null
+++ b/frontend-v2/src/hooks/usePrevious.ts
@@ -0,0 +1,11 @@
+import { useEffect, useRef } from "react";
+
+function usePrevious(value: any) {
+ const ref = useRef();
+ useEffect(() => {
+ ref.current = value; //assign the value of ref to the argument
+ },[value]); //this code will run when the value of 'value' changes
+
+ return ref.current; //in the end, return the current ref value.
+}
+export default usePrevious;
\ No newline at end of file
diff --git a/frontend-v2/src/index.css b/frontend-v2/src/index.css
new file mode 100644
index 00000000..ec2585e8
--- /dev/null
+++ b/frontend-v2/src/index.css
@@ -0,0 +1,13 @@
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+ sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+code {
+ font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
+ monospace;
+}
diff --git a/frontend-v2/src/index.tsx b/frontend-v2/src/index.tsx
new file mode 100644
index 00000000..0e6466fa
--- /dev/null
+++ b/frontend-v2/src/index.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import { createRoot } from 'react-dom/client';
+import { Provider } from 'react-redux';
+import { store } from './app/store';
+import App from './App';
+import reportWebVitals from './reportWebVitals';
+import './index.css';
+
+const container = document.getElementById('root')!;
+const root = createRoot(container);
+
+root.render(
+
+
+
+
+
+);
+
+// If you want to start measuring performance in your app, pass a function
+// to log results (for example: reportWebVitals(console.log))
+// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
+reportWebVitals();
diff --git a/frontend-v2/src/logo.svg b/frontend-v2/src/logo.svg
new file mode 100644
index 00000000..84667388
--- /dev/null
+++ b/frontend-v2/src/logo.svg
@@ -0,0 +1 @@
+
diff --git a/frontend-v2/src/logo_pkpdapp_with_text.svg b/frontend-v2/src/logo_pkpdapp_with_text.svg
new file mode 100644
index 00000000..1b524776
--- /dev/null
+++ b/frontend-v2/src/logo_pkpdapp_with_text.svg
@@ -0,0 +1 @@
+PKPD APP
\ No newline at end of file
diff --git a/frontend-v2/src/react-app-env.d.ts b/frontend-v2/src/react-app-env.d.ts
new file mode 100644
index 00000000..6431bc5f
--- /dev/null
+++ b/frontend-v2/src/react-app-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/frontend-v2/src/reportWebVitals.ts b/frontend-v2/src/reportWebVitals.ts
new file mode 100644
index 00000000..49a2a16e
--- /dev/null
+++ b/frontend-v2/src/reportWebVitals.ts
@@ -0,0 +1,15 @@
+import { ReportHandler } from 'web-vitals';
+
+const reportWebVitals = (onPerfEntry?: ReportHandler) => {
+ if (onPerfEntry && onPerfEntry instanceof Function) {
+ import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
+ getCLS(onPerfEntry);
+ getFID(onPerfEntry);
+ getFCP(onPerfEntry);
+ getLCP(onPerfEntry);
+ getTTFB(onPerfEntry);
+ });
+ }
+};
+
+export default reportWebVitals;
diff --git a/frontend-v2/src/setupProxy.js b/frontend-v2/src/setupProxy.js
new file mode 100644
index 00000000..606ea6e2
--- /dev/null
+++ b/frontend-v2/src/setupProxy.js
@@ -0,0 +1,11 @@
+const { createProxyMiddleware } = require('http-proxy-middleware');
+
+module.exports = function(app) {
+ const backend = createProxyMiddleware({
+ target: 'http://localhost:8000',
+ changeOrigin: true,
+ pathRewrite: { '^/backend': '/static' },
+ });
+ app.use('/api', backend);
+ app.use('/backend', backend);
+};
\ No newline at end of file
diff --git a/frontend-v2/src/setupTests.ts b/frontend-v2/src/setupTests.ts
new file mode 100644
index 00000000..74b1a275
--- /dev/null
+++ b/frontend-v2/src/setupTests.ts
@@ -0,0 +1,5 @@
+// jest-dom adds custom jest matchers for asserting on DOM nodes.
+// allows you to do things like:
+// expect(element).toHaveTextContent(/react/i)
+// learn more: https://github.com/testing-library/jest-dom
+import '@testing-library/jest-dom/extend-expect';
diff --git a/frontend-v2/tsconfig.json b/frontend-v2/tsconfig.json
new file mode 100644
index 00000000..a273b0cf
--- /dev/null
+++ b/frontend-v2/tsconfig.json
@@ -0,0 +1,26 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noFallthroughCasesInSwitch": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx"
+ },
+ "include": [
+ "src"
+ ]
+}
diff --git a/frontend-v2/yarn.lock b/frontend-v2/yarn.lock
new file mode 100644
index 00000000..6a4756e4
--- /dev/null
+++ b/frontend-v2/yarn.lock
@@ -0,0 +1,12081 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@adobe/css-tools@^4.0.1":
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.2.0.tgz#e1a84fca468f4b337816fcb7f0964beb620ba855"
+ integrity sha512-E09FiIft46CmH5Qnjb0wsW54/YQd69LsxeKUOWawmws1XWvyFGURnAChH0mlr7YPFR1ofwvUQfcL0J3lMxXqPA==
+
+"@alloc/quick-lru@^5.2.0":
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
+ integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
+
+"@ampproject/remapping@^2.2.0":
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630"
+ integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.0"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@apideck/better-ajv-errors@^0.3.1":
+ version "0.3.6"
+ resolved "https://registry.yarnpkg.com/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz#957d4c28e886a64a8141f7522783be65733ff097"
+ integrity sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==
+ dependencies:
+ json-schema "^0.4.0"
+ jsonpointer "^5.0.0"
+ leven "^3.1.0"
+
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.22.5", "@babel/code-frame@^7.8.3":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.22.5.tgz#234d98e1551960604f1246e6475891a570ad5658"
+ integrity sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==
+ dependencies:
+ "@babel/highlight" "^7.22.5"
+
+"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.5.tgz#b1f6c86a02d85d2dd3368a2b67c09add8cd0c255"
+ integrity sha512-4Jc/YuIaYqKnDDz892kPIledykKg12Aw1PYX5i/TY28anJtacvM1Rrr8wbieB9GfEJwlzqT0hUEao0CxEebiDA==
+
+"@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.7.2", "@babel/core@^7.8.0":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.22.5.tgz#d67d9747ecf26ee7ecd3ebae1ee22225fe902a89"
+ integrity sha512-SBuTAjg91A3eKOvD+bPEz3LlhHZRNu1nFOVts9lzDJTXshHTjII0BAtDS3Y2DAkdZdDKWVZGVwkDfc4Clxn1dg==
+ dependencies:
+ "@ampproject/remapping" "^2.2.0"
+ "@babel/code-frame" "^7.22.5"
+ "@babel/generator" "^7.22.5"
+ "@babel/helper-compilation-targets" "^7.22.5"
+ "@babel/helper-module-transforms" "^7.22.5"
+ "@babel/helpers" "^7.22.5"
+ "@babel/parser" "^7.22.5"
+ "@babel/template" "^7.22.5"
+ "@babel/traverse" "^7.22.5"
+ "@babel/types" "^7.22.5"
+ 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@^7.16.3":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.22.5.tgz#fa032503b9e2d188e25b1b95d29e8b8431042d78"
+ integrity sha512-C69RWYNYtrgIRE5CmTd77ZiLDXqgBipahJc/jHP3sLcAGj6AJzxNIuKNpVnICqbyK7X3pFUfEvL++rvtbQpZkQ==
+ dependencies:
+ "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1"
+ eslint-visitor-keys "^2.1.0"
+ semver "^6.3.0"
+
+"@babel/generator@^7.22.5", "@babel/generator@^7.7.2":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.5.tgz#1e7bf768688acfb05cf30b2369ef855e82d984f7"
+ integrity sha512-+lcUbnTRhd0jOewtFSedLyiPsD5tswKkbgcezOqqWFUVNEwoUTlpPOBmvhG7OXWLR4jMdv0czPGH5XbflnD1EA==
+ dependencies:
+ "@babel/types" "^7.22.5"
+ "@jridgewell/gen-mapping" "^0.3.2"
+ "@jridgewell/trace-mapping" "^0.3.17"
+ jsesc "^2.5.1"
+
+"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882"
+ integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.5.tgz#a3f4758efdd0190d8927fcffd261755937c71878"
+ integrity sha512-m1EP3lVOPptR+2DwD125gziZNcmoNSHGmJROKoy87loWUQyJaVXDgpmruWqDARZSmtYQ+Dl25okU8+qhVzuykw==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.5.tgz#fc7319fc54c5e2fa14b2909cf3c5fd3046813e02"
+ integrity sha512-Ji+ywpHeuqxB8WDxraCiqR0xfhYjiDE/e6k7FuIaANnoOFxAHskHChz4vA1mJC9Lbm01s1PVAGhQY4FUKSkGZw==
+ dependencies:
+ "@babel/compat-data" "^7.22.5"
+ "@babel/helper-validator-option" "^7.22.5"
+ browserslist "^4.21.3"
+ lru-cache "^5.1.1"
+ semver "^6.3.0"
+
+"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.5.tgz#2192a1970ece4685fbff85b48da2c32fcb130b7c"
+ integrity sha512-xkb58MyOYIslxu3gKmVXmjTtUPvBU4odYzbiIQbWwLKIHCsx6UGZGX6F1IznMFVnDdirseUZopzN+ZRt8Xb33Q==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-environment-visitor" "^7.22.5"
+ "@babel/helper-function-name" "^7.22.5"
+ "@babel/helper-member-expression-to-functions" "^7.22.5"
+ "@babel/helper-optimise-call-expression" "^7.22.5"
+ "@babel/helper-replace-supers" "^7.22.5"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.5"
+ semver "^6.3.0"
+
+"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.5.tgz#bb2bf0debfe39b831986a4efbf4066586819c6e4"
+ integrity sha512-1VpEFOIbMRaXyDeUwUfmTIxExLwQ+zkW+Bh5zXpApA3oQedBx9v/updixWxnx/bZpKw7u8VxWjb/qWpIcmPq8A==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ regexpu-core "^5.3.1"
+ semver "^6.3.0"
+
+"@babel/helper-define-polyfill-provider@^0.4.0":
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.4.0.tgz#487053f103110f25b9755c5980e031e93ced24d8"
+ integrity sha512-RnanLx5ETe6aybRi1cO/edaRH+bNYWaryCEmjDDYyNr4wnSzyOp8T0dWipmqVHKEY3AbVKUom50AKSlj1zmKbg==
+ dependencies:
+ "@babel/helper-compilation-targets" "^7.17.7"
+ "@babel/helper-plugin-utils" "^7.16.7"
+ debug "^4.1.1"
+ lodash.debounce "^4.0.8"
+ resolve "^1.14.2"
+ semver "^6.1.2"
+
+"@babel/helper-environment-visitor@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98"
+ integrity sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==
+
+"@babel/helper-function-name@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz#ede300828905bb15e582c037162f99d5183af1be"
+ integrity sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==
+ dependencies:
+ "@babel/template" "^7.22.5"
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-hoist-variables@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb"
+ integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-member-expression-to-functions@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz#0a7c56117cad3372fbf8d2fb4bf8f8d64a1e76b2"
+ integrity sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz#1a8f4c9f4027d23f520bd76b364d44434a72660c"
+ integrity sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-module-transforms@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.22.5.tgz#0f65daa0716961b6e96b164034e737f60a80d2ef"
+ integrity sha512-+hGKDt/Ze8GFExiVHno/2dvG5IdstpzCq0y4Qc9OJ25D4q3pKfiIP/4Vp3/JvhDkLKsDK2api3q3fpIgiIF5bw==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.22.5"
+ "@babel/helper-module-imports" "^7.22.5"
+ "@babel/helper-simple-access" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.5"
+ "@babel/helper-validator-identifier" "^7.22.5"
+ "@babel/template" "^7.22.5"
+ "@babel/traverse" "^7.22.5"
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-optimise-call-expression@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz#f21531a9ccbff644fdd156b4077c16ff0c3f609e"
+ integrity sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295"
+ integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==
+
+"@babel/helper-remap-async-to-generator@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.5.tgz#14a38141a7bf2165ad38da61d61cf27b43015da2"
+ integrity sha512-cU0Sq1Rf4Z55fgz7haOakIyM7+x/uCFwXpLPaeRzfoUtAEAuUZjZvFPjL/rk5rW693dIgn2hng1W7xbT7lWT4g==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-environment-visitor" "^7.22.5"
+ "@babel/helper-wrap-function" "^7.22.5"
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-replace-supers@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.5.tgz#71bc5fb348856dea9fdc4eafd7e2e49f585145dc"
+ integrity sha512-aLdNM5I3kdI/V9xGNyKSF3X/gTyMUBohTZ+/3QdQKAA9vxIiy12E+8E2HoOP1/DjeqU+g6as35QHJNMDDYpuCg==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.22.5"
+ "@babel/helper-member-expression-to-functions" "^7.22.5"
+ "@babel/helper-optimise-call-expression" "^7.22.5"
+ "@babel/template" "^7.22.5"
+ "@babel/traverse" "^7.22.5"
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-simple-access@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz#4938357dc7d782b80ed6dbb03a0fba3d22b1d5de"
+ integrity sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz#007f15240b5751c537c40e77abb4e89eeaaa8847"
+ integrity sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-split-export-declaration@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.5.tgz#88cf11050edb95ed08d596f7a044462189127a08"
+ integrity sha512-thqK5QFghPKWLhAV321lxF95yCg2K3Ob5yw+M3VHWfdia0IkPXUtoLH8x/6Fh486QUvzhb8YOWHChTVen2/PoQ==
+ dependencies:
+ "@babel/types" "^7.22.5"
+
+"@babel/helper-string-parser@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f"
+ integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==
+
+"@babel/helper-validator-identifier@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193"
+ integrity sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==
+
+"@babel/helper-validator-option@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz#de52000a15a177413c8234fa3a8af4ee8102d0ac"
+ integrity sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==
+
+"@babel/helper-wrap-function@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.22.5.tgz#44d205af19ed8d872b4eefb0d2fa65f45eb34f06"
+ integrity sha512-bYqLIBSEshYcYQyfks8ewYA8S30yaGSeRslcvKMvoUk6HHPySbxHq9YRi6ghhzEU+yhQv9bP/jXnygkStOcqZw==
+ dependencies:
+ "@babel/helper-function-name" "^7.22.5"
+ "@babel/template" "^7.22.5"
+ "@babel/traverse" "^7.22.5"
+ "@babel/types" "^7.22.5"
+
+"@babel/helpers@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.22.5.tgz#74bb4373eb390d1ceed74a15ef97767e63120820"
+ integrity sha512-pSXRmfE1vzcUIDFQcSGA5Mr+GxBV9oiRKDuDxXvWQQBCh8HoIjs/2DlDB7H8smac1IVrB9/xdXj2N3Wol9Cr+Q==
+ dependencies:
+ "@babel/template" "^7.22.5"
+ "@babel/traverse" "^7.22.5"
+ "@babel/types" "^7.22.5"
+
+"@babel/highlight@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.22.5.tgz#aa6c05c5407a67ebce408162b7ede789b4d22031"
+ integrity sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.22.5"
+ chalk "^2.0.0"
+ js-tokens "^4.0.0"
+
+"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.5.tgz#721fd042f3ce1896238cf1b341c77eb7dee7dbea"
+ integrity sha512-DFZMC9LJUG9PLOclRC32G63UXwzqS2koQC8dkx+PLdmt1xSePYpbT/NbsrJy8Q/muXz7o/h/d4A7Fuyixm559Q==
+
+"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e"
+ integrity sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz#fef09f9499b1f1c930da8a0c419db42167d792ca"
+ integrity sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
+ "@babel/plugin-transform-optional-chaining" "^7.22.5"
+
+"@babel/plugin-proposal-class-properties@^7.16.0":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3"
+ integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-proposal-decorators@^7.16.4":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.22.5.tgz#dc8cdda048e5aea947efda920e030199806b868d"
+ integrity sha512-h8hlezQ4dl6ixodgXkH8lUfcD7x+WAuIqPUjwGoItynrXOAv4a4Tci1zA/qjzQjjcl0v3QpLdc2LM6ZACQuY7A==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-replace-supers" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.5"
+ "@babel/plugin-syntax-decorators" "^7.22.5"
+
+"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1"
+ integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+
+"@babel/plugin-proposal-numeric-separator@^7.16.0":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75"
+ integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.18.6"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+
+"@babel/plugin-proposal-optional-chaining@^7.16.0":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz#886f5c8978deb7d30f678b2e24346b287234d3ea"
+ integrity sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.20.2"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.20.0"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+
+"@babel/plugin-proposal-private-methods@^7.16.0":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea"
+ integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2":
+ version "7.21.0-placeholder-for-preset-env.2"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703"
+ integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==
+
+"@babel/plugin-proposal-private-property-in-object@^7.21.11":
+ version "7.21.11"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c"
+ integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.18.6"
+ "@babel/helper-create-class-features-plugin" "^7.21.0"
+ "@babel/helper-plugin-utils" "^7.20.2"
+ "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+
+"@babel/plugin-proposal-unicode-property-regex@^7.4.4":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e"
+ integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-syntax-async-generators@^7.8.4":
+ version "7.8.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
+ integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-bigint@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea"
+ integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3":
+ version "7.12.13"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10"
+ integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.12.13"
+
+"@babel/plugin-syntax-class-static-block@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406"
+ integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-decorators@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.22.5.tgz#329fe2907c73de184033775637dbbc507f09116a"
+ integrity sha512-avpUOBS7IU6al8MmF1XpAyj9QYeLPuSDJI5D4pVMSMdL7xQokKqJPYQC67RCT0aCTashUXPiGwMJ0DEXXCEmMA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-syntax-dynamic-import@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
+ integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-export-namespace-from@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a"
+ integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.3"
+
+"@babel/plugin-syntax-flow@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.22.5.tgz#163b820b9e7696ce134df3ee716d9c0c98035859"
+ integrity sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-syntax-import-assertions@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz#07d252e2aa0bc6125567f742cd58619cb14dce98"
+ integrity sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-syntax-import-attributes@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.22.5.tgz#ab840248d834410b829f569f5262b9e517555ecb"
+ integrity sha512-KwvoWDeNKPETmozyFE0P2rOLqh39EoQHNjqizrI5B8Vt0ZNS7M56s7dAiAqbYfiAYOuIzIh96z3iR2ktgu3tEg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51"
+ integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-json-strings@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
+ integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-jsx@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz#a6b68e84fb76e759fc3b93e901876ffabbe1d918"
+ integrity sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
+ integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
+ integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97"
+ integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-object-rest-spread@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
+ integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-optional-catch-binding@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1"
+ integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-optional-chaining@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a"
+ integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-private-property-in-object@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad"
+ integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c"
+ integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-typescript@^7.22.5", "@babel/plugin-syntax-typescript@^7.7.2":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz#aac8d383b062c5072c647a31ef990c1d0af90272"
+ integrity sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-syntax-unicode-sets-regex@^7.18.6":
+ version "7.18.6"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz#d49a3b3e6b52e5be6740022317580234a6a47357"
+ integrity sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.18.6"
+ "@babel/helper-plugin-utils" "^7.18.6"
+
+"@babel/plugin-transform-arrow-functions@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz#e5ba566d0c58a5b2ba2a8b795450641950b71958"
+ integrity sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-async-generator-functions@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.5.tgz#7336356d23380eda9a56314974f053a020dab0c3"
+ integrity sha512-gGOEvFzm3fWoyD5uZq7vVTD57pPJ3PczPUD/xCFGjzBpUosnklmXyKnGQbbbGs1NPNPskFex0j93yKbHt0cHyg==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-remap-async-to-generator" "^7.22.5"
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+
+"@babel/plugin-transform-async-to-generator@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.22.5.tgz#c7a85f44e46f8952f6d27fe57c2ed3cc084c3775"
+ integrity sha512-b1A8D8ZzE/VhNDoV1MSJTnpKkCG5bJo+19R4o4oy03zM7ws8yEMK755j61Dc3EyvdysbqH5BOOTquJ7ZX9C6vQ==
+ dependencies:
+ "@babel/helper-module-imports" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-remap-async-to-generator" "^7.22.5"
+
+"@babel/plugin-transform-block-scoped-functions@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz#27978075bfaeb9fa586d3cb63a3d30c1de580024"
+ integrity sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-block-scoping@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.5.tgz#8bfc793b3a4b2742c0983fadc1480d843ecea31b"
+ integrity sha512-EcACl1i5fSQ6bt+YGuU/XGCeZKStLmyVGytWkpyhCLeQVA0eu6Wtiw92V+I1T/hnezUv7j74dA/Ro69gWcU+hg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-class-properties@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.22.5.tgz#97a56e31ad8c9dc06a0b3710ce7803d5a48cca77"
+ integrity sha512-nDkQ0NfkOhPTq8YCLiWNxp1+f9fCobEjCb0n8WdbNUBc4IB5V7P1QnX9IjpSoquKrXF5SKojHleVNs2vGeHCHQ==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-class-static-block@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.22.5.tgz#3e40c46f048403472d6f4183116d5e46b1bff5ba"
+ integrity sha512-SPToJ5eYZLxlnp1UzdARpOGeC2GbHvr9d/UV0EukuVx8atktg194oe+C5BqQ8jRTkgLRVOPYeXRSBg1IlMoVRA==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-class-static-block" "^7.14.5"
+
+"@babel/plugin-transform-classes@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.5.tgz#635d4e98da741fad814984639f4c0149eb0135e1"
+ integrity sha512-2edQhLfibpWpsVBx2n/GKOz6JdGQvLruZQfGr9l1qes2KQaWswjBzhQF7UDUZMNaMMQeYnQzxwOMPsbYF7wqPQ==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-compilation-targets" "^7.22.5"
+ "@babel/helper-environment-visitor" "^7.22.5"
+ "@babel/helper-function-name" "^7.22.5"
+ "@babel/helper-optimise-call-expression" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-replace-supers" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.5"
+ globals "^11.1.0"
+
+"@babel/plugin-transform-computed-properties@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz#cd1e994bf9f316bd1c2dafcd02063ec261bb3869"
+ integrity sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/template" "^7.22.5"
+
+"@babel/plugin-transform-destructuring@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.5.tgz#d3aca7438f6c26c78cdd0b0ba920a336001b27cc"
+ integrity sha512-GfqcFuGW8vnEqTUBM7UtPd5A4q797LTvvwKxXTgRsFjoqaJiEg9deBG6kWeQYkVEL569NpnmpC0Pkr/8BLKGnQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-dotall-regex@^7.22.5", "@babel/plugin-transform-dotall-regex@^7.4.4":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.22.5.tgz#dbb4f0e45766eb544e193fb00e65a1dd3b2a4165"
+ integrity sha512-5/Yk9QxCQCl+sOIB1WelKnVRxTJDSAIxtJLL2/pqL14ZVlbH0fUQUZa/T5/UnQtBNgghR7mfB8ERBKyKPCi7Vw==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-duplicate-keys@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.22.5.tgz#b6e6428d9416f5f0bba19c70d1e6e7e0b88ab285"
+ integrity sha512-dEnYD+9BBgld5VBXHnF/DbYGp3fqGMsyxKbtD1mDyIA7AkTSpKXFhCVuj/oQVOoALfBs77DudA0BE4d5mcpmqw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-dynamic-import@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.22.5.tgz#d6908a8916a810468c4edff73b5b75bda6ad393e"
+ integrity sha512-0MC3ppTB1AMxd8fXjSrbPa7LT9hrImt+/fcj+Pg5YMD7UQyWp/02+JWpdnCymmsXwIx5Z+sYn1bwCn4ZJNvhqQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.3"
+
+"@babel/plugin-transform-exponentiation-operator@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.22.5.tgz#402432ad544a1f9a480da865fda26be653e48f6a"
+ integrity sha512-vIpJFNM/FjZ4rh1myqIya9jXwrwwgFRHPjT3DkUA9ZLHuzox8jiXkOLvwm1H+PQIP3CqfC++WPKeuDi0Sjdj1g==
+ dependencies:
+ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-export-namespace-from@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.22.5.tgz#57c41cb1d0613d22f548fddd8b288eedb9973a5b"
+ integrity sha512-X4hhm7FRnPgd4nDA4b/5V280xCx6oL7Oob5+9qVS5C13Zq4bh1qq7LU0GgRU6b5dBWBvhGaXYVB4AcN6+ol6vg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
+
+"@babel/plugin-transform-flow-strip-types@^7.16.0":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.22.5.tgz#0bb17110c7bf5b35a60754b2f00c58302381dee2"
+ integrity sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-flow" "^7.22.5"
+
+"@babel/plugin-transform-for-of@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz#ab1b8a200a8f990137aff9a084f8de4099ab173f"
+ integrity sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-function-name@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz#935189af68b01898e0d6d99658db6b164205c143"
+ integrity sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==
+ dependencies:
+ "@babel/helper-compilation-targets" "^7.22.5"
+ "@babel/helper-function-name" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-json-strings@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.22.5.tgz#14b64352fdf7e1f737eed68de1a1468bd2a77ec0"
+ integrity sha512-DuCRB7fu8MyTLbEQd1ew3R85nx/88yMoqo2uPSjevMj3yoN7CDM8jkgrY0wmVxfJZyJ/B9fE1iq7EQppWQmR5A==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+
+"@babel/plugin-transform-literals@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz#e9341f4b5a167952576e23db8d435849b1dd7920"
+ integrity sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-logical-assignment-operators@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.22.5.tgz#66ae5f068fd5a9a5dc570df16f56c2a8462a9d6c"
+ integrity sha512-MQQOUW1KL8X0cDWfbwYP+TbVbZm16QmQXJQ+vndPtH/BoO0lOKpVoEDMI7+PskYxH+IiE0tS8xZye0qr1lGzSA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+
+"@babel/plugin-transform-member-expression-literals@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz#4fcc9050eded981a468347dd374539ed3e058def"
+ integrity sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-modules-amd@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.22.5.tgz#4e045f55dcf98afd00f85691a68fc0780704f526"
+ integrity sha512-R+PTfLTcYEmb1+kK7FNkhQ1gP4KgjpSO6HfH9+f8/yfp2Nt3ggBjiVpRwmwTlfqZLafYKJACy36yDXlEmI9HjQ==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-modules-commonjs@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz#7d9875908d19b8c0536085af7b053fd5bd651bfa"
+ integrity sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-simple-access" "^7.22.5"
+
+"@babel/plugin-transform-modules-systemjs@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.22.5.tgz#18c31410b5e579a0092638f95c896c2a98a5d496"
+ integrity sha512-emtEpoaTMsOs6Tzz+nbmcePl6AKVtS1yC4YNAeMun9U8YCsgadPNxnOPQ8GhHFB2qdx+LZu9LgoC0Lthuu05DQ==
+ dependencies:
+ "@babel/helper-hoist-variables" "^7.22.5"
+ "@babel/helper-module-transforms" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-validator-identifier" "^7.22.5"
+
+"@babel/plugin-transform-modules-umd@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.22.5.tgz#4694ae40a87b1745e3775b6a7fe96400315d4f98"
+ integrity sha512-+S6kzefN/E1vkSsKx8kmQuqeQsvCKCd1fraCM7zXm4SFoggI099Tr4G8U81+5gtMdUeMQ4ipdQffbKLX0/7dBQ==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.22.5.tgz#67fe18ee8ce02d57c855185e27e3dc959b2e991f"
+ integrity sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-new-target@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.22.5.tgz#1b248acea54ce44ea06dfd37247ba089fcf9758d"
+ integrity sha512-AsF7K0Fx/cNKVyk3a+DW0JLo+Ua598/NxMRvxDnkpCIGFh43+h/v2xyhRUYf6oD8gE4QtL83C7zZVghMjHd+iw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-nullish-coalescing-operator@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.22.5.tgz#f8872c65776e0b552e0849d7596cddd416c3e381"
+ integrity sha512-6CF8g6z1dNYZ/VXok5uYkkBBICHZPiGEl7oDnAx2Mt1hlHVHOSIKWJaXHjQJA5VB43KZnXZDIexMchY4y2PGdA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+
+"@babel/plugin-transform-numeric-separator@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.22.5.tgz#57226a2ed9e512b9b446517ab6fa2d17abb83f58"
+ integrity sha512-NbslED1/6M+sXiwwtcAB/nieypGw02Ejf4KtDeMkCEpP6gWFMX1wI9WKYua+4oBneCCEmulOkRpwywypVZzs/g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+
+"@babel/plugin-transform-object-rest-spread@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.5.tgz#9686dc3447df4753b0b2a2fae7e8bc33cdc1f2e1"
+ integrity sha512-Kk3lyDmEslH9DnvCDA1s1kkd3YWQITiBOHngOtDL9Pt6BZjzqb6hiOlb8VfjiiQJ2unmegBqZu0rx5RxJb5vmQ==
+ dependencies:
+ "@babel/compat-data" "^7.22.5"
+ "@babel/helper-compilation-targets" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-transform-parameters" "^7.22.5"
+
+"@babel/plugin-transform-object-super@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz#794a8d2fcb5d0835af722173c1a9d704f44e218c"
+ integrity sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-replace-supers" "^7.22.5"
+
+"@babel/plugin-transform-optional-catch-binding@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.22.5.tgz#842080be3076703be0eaf32ead6ac8174edee333"
+ integrity sha512-pH8orJahy+hzZje5b8e2QIlBWQvGpelS76C63Z+jhZKsmzfNaPQ+LaW6dcJ9bxTpo1mtXbgHwy765Ro3jftmUg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+
+"@babel/plugin-transform-optional-chaining@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.5.tgz#1003762b9c14295501beb41be72426736bedd1e0"
+ integrity sha512-AconbMKOMkyG+xCng2JogMCDcqW8wedQAqpVIL4cOSescZ7+iW8utC6YDZLMCSUIReEA733gzRSaOSXMAt/4WQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+
+"@babel/plugin-transform-parameters@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz#c3542dd3c39b42c8069936e48717a8d179d63a18"
+ integrity sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-private-methods@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.22.5.tgz#21c8af791f76674420a147ae62e9935d790f8722"
+ integrity sha512-PPjh4gyrQnGe97JTalgRGMuU4icsZFnWkzicB/fUtzlKUqvsWBKEpPPfr5a2JiyirZkHxnAqkQMO5Z5B2kK3fA==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-private-property-in-object@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.22.5.tgz#07a77f28cbb251546a43d175a1dda4cf3ef83e32"
+ integrity sha512-/9xnaTTJcVoBtSSmrVyhtSvO3kbqS2ODoh2juEU72c3aYonNF0OMGiaz2gjukyKM2wBBYJP38S4JiE0Wfb5VMQ==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-create-class-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+
+"@babel/plugin-transform-property-literals@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz#b5ddabd73a4f7f26cd0e20f5db48290b88732766"
+ integrity sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-react-constant-elements@^7.12.1":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.22.5.tgz#6dfa7c1c37f7d7279e417ceddf5a04abb8bb9c29"
+ integrity sha512-BF5SXoO+nX3h5OhlN78XbbDrBOffv+AxPP2ENaJOVqjWCgBDeOY3WcaUcddutGSfoap+5NEQ/q/4I3WZIvgkXA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz#3c4326f9fce31c7968d6cb9debcaf32d9e279a2b"
+ integrity sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-react-jsx-development@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.22.5.tgz#e716b6edbef972a92165cd69d92f1255f7e73e87"
+ integrity sha512-bDhuzwWMuInwCYeDeMzyi7TaBgRQei6DqxhbyniL7/VG4RSS7HtSL2QbY4eESy1KJqlWt8g3xeEBGPuo+XqC8A==
+ dependencies:
+ "@babel/plugin-transform-react-jsx" "^7.22.5"
+
+"@babel/plugin-transform-react-jsx@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz#932c291eb6dd1153359e2a90cb5e557dcf068416"
+ integrity sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-module-imports" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-jsx" "^7.22.5"
+ "@babel/types" "^7.22.5"
+
+"@babel/plugin-transform-react-pure-annotations@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.22.5.tgz#1f58363eef6626d6fa517b95ac66fe94685e32c0"
+ integrity sha512-gP4k85wx09q+brArVinTXhWiyzLl9UpmGva0+mWyKxk6JZequ05x3eUcIUE+FyttPKJFRRVtAvQaJ6YF9h1ZpA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-regenerator@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.22.5.tgz#cd8a68b228a5f75fa01420e8cc2fc400f0fc32aa"
+ integrity sha512-rR7KePOE7gfEtNTh9Qw+iO3Q/e4DEsoQ+hdvM6QUDH7JRJ5qxq5AA52ZzBWbI5i9lfNuvySgOGP8ZN7LAmaiPw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ regenerator-transform "^0.15.1"
+
+"@babel/plugin-transform-reserved-words@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.22.5.tgz#832cd35b81c287c4bcd09ce03e22199641f964fb"
+ integrity sha512-DTtGKFRQUDm8svigJzZHzb/2xatPc6TzNvAIJ5GqOKDsGFYgAskjRulbR/vGsPKq3OPqtexnz327qYpP57RFyA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-runtime@^7.16.4":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.22.5.tgz#ca975fb5e260044473c8142e1b18b567d33c2a3b"
+ integrity sha512-bg4Wxd1FWeFx3daHFTWk1pkSWK/AyQuiyAoeZAOkAOUBjnZPH6KT7eMxouV47tQ6hl6ax2zyAWBdWZXbrvXlaw==
+ dependencies:
+ "@babel/helper-module-imports" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ babel-plugin-polyfill-corejs2 "^0.4.3"
+ babel-plugin-polyfill-corejs3 "^0.8.1"
+ babel-plugin-polyfill-regenerator "^0.5.0"
+ semver "^6.3.0"
+
+"@babel/plugin-transform-shorthand-properties@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz#6e277654be82b5559fc4b9f58088507c24f0c624"
+ integrity sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-spread@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz#6487fd29f229c95e284ba6c98d65eafb893fea6b"
+ integrity sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5"
+
+"@babel/plugin-transform-sticky-regex@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.22.5.tgz#295aba1595bfc8197abd02eae5fc288c0deb26aa"
+ integrity sha512-zf7LuNpHG0iEeiyCNwX4j3gDg1jgt1k3ZdXBKbZSoA3BbGQGvMiSvfbZRR3Dr3aeJe3ooWFZxOOG3IRStYp2Bw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-template-literals@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz#8f38cf291e5f7a8e60e9f733193f0bcc10909bff"
+ integrity sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-typeof-symbol@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.22.5.tgz#5e2ba478da4b603af8673ff7c54f75a97b716b34"
+ integrity sha512-bYkI5lMzL4kPii4HHEEChkD0rkc+nvnlR6+o/qdqR6zrm0Sv/nodmyLhlq2DO0YKLUNd2VePmPRjJXSBh9OIdA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-typescript@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.5.tgz#5c0f7adfc1b5f38c4dbc8f79b1f0f8074134bd7d"
+ integrity sha512-SMubA9S7Cb5sGSFFUlqxyClTA9zWJ8qGQrppNUm05LtFuN1ELRFNndkix4zUJrC9F+YivWwa1dHMSyo0e0N9dA==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.22.5"
+ "@babel/helper-create-class-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/plugin-syntax-typescript" "^7.22.5"
+
+"@babel/plugin-transform-unicode-escapes@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.22.5.tgz#ce0c248522b1cb22c7c992d88301a5ead70e806c"
+ integrity sha512-biEmVg1IYB/raUO5wT1tgfacCef15Fbzhkx493D3urBI++6hpJ+RFG4SrWMn0NEZLfvilqKf3QDrRVZHo08FYg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-unicode-property-regex@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.22.5.tgz#098898f74d5c1e86660dc112057b2d11227f1c81"
+ integrity sha512-HCCIb+CbJIAE6sXn5CjFQXMwkCClcOfPCzTlilJ8cUatfzwHlWQkbtV0zD338u9dZskwvuOYTuuaMaA8J5EI5A==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-unicode-regex@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.22.5.tgz#ce7e7bb3ef208c4ff67e02a22816656256d7a183"
+ integrity sha512-028laaOKptN5vHJf9/Arr/HiJekMd41hOEZYvNsrsXqJ7YPYuX2bQxh31fkZzGmq3YqHRJzYFFAVYvKfMPKqyg==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/plugin-transform-unicode-sets-regex@^7.22.5":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.22.5.tgz#77788060e511b708ffc7d42fdfbc5b37c3004e91"
+ integrity sha512-lhMfi4FC15j13eKrh3DnYHjpGj6UKQHtNKTbtc1igvAhRy4+kLhV07OpLcsN0VgDEw/MjAvJO4BdMJsHwMhzCg==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+
+"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.16.4":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.22.5.tgz#3da66078b181f3d62512c51cf7014392c511504e"
+ integrity sha512-fj06hw89dpiZzGZtxn+QybifF07nNiZjZ7sazs2aVDcysAZVGjW7+7iFYxg6GLNM47R/thYfLdrXc+2f11Vi9A==
+ dependencies:
+ "@babel/compat-data" "^7.22.5"
+ "@babel/helper-compilation-targets" "^7.22.5"
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-validator-option" "^7.22.5"
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.22.5"
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.22.5"
+ "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2"
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+ "@babel/plugin-syntax-class-properties" "^7.12.13"
+ "@babel/plugin-syntax-class-static-block" "^7.14.5"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.3"
+ "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
+ "@babel/plugin-syntax-import-assertions" "^7.22.5"
+ "@babel/plugin-syntax-import-attributes" "^7.22.5"
+ "@babel/plugin-syntax-import-meta" "^7.10.4"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+ "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+ "@babel/plugin-syntax-top-level-await" "^7.14.5"
+ "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6"
+ "@babel/plugin-transform-arrow-functions" "^7.22.5"
+ "@babel/plugin-transform-async-generator-functions" "^7.22.5"
+ "@babel/plugin-transform-async-to-generator" "^7.22.5"
+ "@babel/plugin-transform-block-scoped-functions" "^7.22.5"
+ "@babel/plugin-transform-block-scoping" "^7.22.5"
+ "@babel/plugin-transform-class-properties" "^7.22.5"
+ "@babel/plugin-transform-class-static-block" "^7.22.5"
+ "@babel/plugin-transform-classes" "^7.22.5"
+ "@babel/plugin-transform-computed-properties" "^7.22.5"
+ "@babel/plugin-transform-destructuring" "^7.22.5"
+ "@babel/plugin-transform-dotall-regex" "^7.22.5"
+ "@babel/plugin-transform-duplicate-keys" "^7.22.5"
+ "@babel/plugin-transform-dynamic-import" "^7.22.5"
+ "@babel/plugin-transform-exponentiation-operator" "^7.22.5"
+ "@babel/plugin-transform-export-namespace-from" "^7.22.5"
+ "@babel/plugin-transform-for-of" "^7.22.5"
+ "@babel/plugin-transform-function-name" "^7.22.5"
+ "@babel/plugin-transform-json-strings" "^7.22.5"
+ "@babel/plugin-transform-literals" "^7.22.5"
+ "@babel/plugin-transform-logical-assignment-operators" "^7.22.5"
+ "@babel/plugin-transform-member-expression-literals" "^7.22.5"
+ "@babel/plugin-transform-modules-amd" "^7.22.5"
+ "@babel/plugin-transform-modules-commonjs" "^7.22.5"
+ "@babel/plugin-transform-modules-systemjs" "^7.22.5"
+ "@babel/plugin-transform-modules-umd" "^7.22.5"
+ "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5"
+ "@babel/plugin-transform-new-target" "^7.22.5"
+ "@babel/plugin-transform-nullish-coalescing-operator" "^7.22.5"
+ "@babel/plugin-transform-numeric-separator" "^7.22.5"
+ "@babel/plugin-transform-object-rest-spread" "^7.22.5"
+ "@babel/plugin-transform-object-super" "^7.22.5"
+ "@babel/plugin-transform-optional-catch-binding" "^7.22.5"
+ "@babel/plugin-transform-optional-chaining" "^7.22.5"
+ "@babel/plugin-transform-parameters" "^7.22.5"
+ "@babel/plugin-transform-private-methods" "^7.22.5"
+ "@babel/plugin-transform-private-property-in-object" "^7.22.5"
+ "@babel/plugin-transform-property-literals" "^7.22.5"
+ "@babel/plugin-transform-regenerator" "^7.22.5"
+ "@babel/plugin-transform-reserved-words" "^7.22.5"
+ "@babel/plugin-transform-shorthand-properties" "^7.22.5"
+ "@babel/plugin-transform-spread" "^7.22.5"
+ "@babel/plugin-transform-sticky-regex" "^7.22.5"
+ "@babel/plugin-transform-template-literals" "^7.22.5"
+ "@babel/plugin-transform-typeof-symbol" "^7.22.5"
+ "@babel/plugin-transform-unicode-escapes" "^7.22.5"
+ "@babel/plugin-transform-unicode-property-regex" "^7.22.5"
+ "@babel/plugin-transform-unicode-regex" "^7.22.5"
+ "@babel/plugin-transform-unicode-sets-regex" "^7.22.5"
+ "@babel/preset-modules" "^0.1.5"
+ "@babel/types" "^7.22.5"
+ babel-plugin-polyfill-corejs2 "^0.4.3"
+ babel-plugin-polyfill-corejs3 "^0.8.1"
+ babel-plugin-polyfill-regenerator "^0.5.0"
+ core-js-compat "^3.30.2"
+ semver "^6.3.0"
+
+"@babel/preset-modules@^0.1.5":
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9"
+ integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-proposal-unicode-property-regex" "^7.4.4"
+ "@babel/plugin-transform-dotall-regex" "^7.4.4"
+ "@babel/types" "^7.4.4"
+ esutils "^2.0.2"
+
+"@babel/preset-react@^7.12.5", "@babel/preset-react@^7.16.0":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.22.5.tgz#c4d6058fbf80bccad02dd8c313a9aaa67e3c3dd6"
+ integrity sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-validator-option" "^7.22.5"
+ "@babel/plugin-transform-react-display-name" "^7.22.5"
+ "@babel/plugin-transform-react-jsx" "^7.22.5"
+ "@babel/plugin-transform-react-jsx-development" "^7.22.5"
+ "@babel/plugin-transform-react-pure-annotations" "^7.22.5"
+
+"@babel/preset-typescript@^7.16.0":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.22.5.tgz#16367d8b01d640e9a507577ed4ee54e0101e51c8"
+ integrity sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.22.5"
+ "@babel/helper-validator-option" "^7.22.5"
+ "@babel/plugin-syntax-jsx" "^7.22.5"
+ "@babel/plugin-transform-modules-commonjs" "^7.22.5"
+ "@babel/plugin-transform-typescript" "^7.22.5"
+
+"@babel/regjsgen@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
+ integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
+
+"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.18.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.5.tgz#8564dd588182ce0047d55d7a75e93921107b57ec"
+ integrity sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==
+ dependencies:
+ regenerator-runtime "^0.13.11"
+
+"@babel/template@^7.22.5", "@babel/template@^7.3.3":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec"
+ integrity sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==
+ dependencies:
+ "@babel/code-frame" "^7.22.5"
+ "@babel/parser" "^7.22.5"
+ "@babel/types" "^7.22.5"
+
+"@babel/traverse@^7.22.5", "@babel/traverse@^7.7.2":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.5.tgz#44bd276690db6f4940fdb84e1cb4abd2f729ccd1"
+ integrity sha512-7DuIjPgERaNo6r+PZwItpjCZEa5vyw4eJGufeLxrPdBXBoLcCJCIasvK6pK/9DVNrLZTLFhUGqaC6X/PA007TQ==
+ dependencies:
+ "@babel/code-frame" "^7.22.5"
+ "@babel/generator" "^7.22.5"
+ "@babel/helper-environment-visitor" "^7.22.5"
+ "@babel/helper-function-name" "^7.22.5"
+ "@babel/helper-hoist-variables" "^7.22.5"
+ "@babel/helper-split-export-declaration" "^7.22.5"
+ "@babel/parser" "^7.22.5"
+ "@babel/types" "^7.22.5"
+ debug "^4.1.0"
+ globals "^11.1.0"
+
+"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
+ version "7.22.5"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.22.5.tgz#cd93eeaab025880a3a47ec881f4b096a5b786fbe"
+ integrity sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==
+ dependencies:
+ "@babel/helper-string-parser" "^7.22.5"
+ "@babel/helper-validator-identifier" "^7.22.5"
+ to-fast-properties "^2.0.0"
+
+"@bcoe/v8-coverage@^0.2.3":
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
+ integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
+
+"@choojs/findup@^0.2.0":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@choojs/findup/-/findup-0.2.1.tgz#ac13c59ae7be6e1da64de0779a0a7f03d75615a3"
+ integrity sha512-YstAqNb0MCN8PjdLCDfRsBcGVRN41f3vgLvaI0IrIcBp4AqILRSS0DeWNGkicC+f/zRIPJLc+9RURVSepwvfBw==
+ dependencies:
+ commander "^2.15.1"
+
+"@colors/colors@1.5.0":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
+ integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
+
+"@csstools/normalize.css@*":
+ version "12.0.0"
+ resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-12.0.0.tgz#a9583a75c3f150667771f30b60d9f059473e62c4"
+ integrity sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg==
+
+"@csstools/postcss-cascade-layers@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz#8a997edf97d34071dd2e37ea6022447dd9e795ad"
+ integrity sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==
+ dependencies:
+ "@csstools/selector-specificity" "^2.0.2"
+ postcss-selector-parser "^6.0.10"
+
+"@csstools/postcss-color-function@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz#2bd36ab34f82d0497cfacdc9b18d34b5e6f64b6b"
+ integrity sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties" "^1.1.0"
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-font-format-keywords@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz#677b34e9e88ae997a67283311657973150e8b16a"
+ integrity sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-hwb-function@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz#ab54a9fce0ac102c754854769962f2422ae8aa8b"
+ integrity sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-ic-unit@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz#28237d812a124d1a16a5acc5c3832b040b303e58"
+ integrity sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties" "^1.1.0"
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-is-pseudo-class@^2.0.7":
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz#846ae6c0d5a1eaa878fce352c544f9c295509cd1"
+ integrity sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==
+ dependencies:
+ "@csstools/selector-specificity" "^2.0.0"
+ postcss-selector-parser "^6.0.10"
+
+"@csstools/postcss-nested-calc@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz#d7e9d1d0d3d15cf5ac891b16028af2a1044d0c26"
+ integrity sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-normalize-display-values@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz#15da54a36e867b3ac5163ee12c1d7f82d4d612c3"
+ integrity sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-oklab-function@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz#88cee0fbc8d6df27079ebd2fa016ee261eecf844"
+ integrity sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties" "^1.1.0"
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-progressive-custom-properties@^1.1.0", "@csstools/postcss-progressive-custom-properties@^1.3.0":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz#542292558384361776b45c85226b9a3a34f276fa"
+ integrity sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-stepped-value-functions@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz#f8772c3681cc2befed695e2b0b1d68e22f08c4f4"
+ integrity sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-text-decoration-shorthand@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz#ea96cfbc87d921eca914d3ad29340d9bcc4c953f"
+ integrity sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-trigonometric-functions@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz#94d3e4774c36d35dcdc88ce091336cb770d32756"
+ integrity sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-unset-value@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz#c99bb70e2cdc7312948d1eb41df2412330b81f77"
+ integrity sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==
+
+"@csstools/selector-specificity@^2.0.0", "@csstools/selector-specificity@^2.0.2":
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz#2cbcf822bf3764c9658c4d2e568bd0c0cb748016"
+ integrity sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==
+
+"@cypress/request@^2.88.10":
+ version "2.88.11"
+ resolved "https://registry.yarnpkg.com/@cypress/request/-/request-2.88.11.tgz#5a4c7399bc2d7e7ed56e92ce5acb620c8b187047"
+ integrity sha512-M83/wfQ1EkspjkE2lNWNV5ui2Cv7UCv1swW1DqljahbzLVWltcsexQh8jYtuS/vzFXP+HySntGM83ZXA9fn17w==
+ dependencies:
+ aws-sign2 "~0.7.0"
+ aws4 "^1.8.0"
+ caseless "~0.12.0"
+ combined-stream "~1.0.6"
+ extend "~3.0.2"
+ forever-agent "~0.6.1"
+ form-data "~2.3.2"
+ http-signature "~1.3.6"
+ is-typedarray "~1.0.0"
+ isstream "~0.1.2"
+ json-stringify-safe "~5.0.1"
+ mime-types "~2.1.19"
+ performance-now "^2.1.0"
+ qs "~6.10.3"
+ safe-buffer "^5.1.2"
+ tough-cookie "~2.5.0"
+ tunnel-agent "^0.6.0"
+ uuid "^8.3.2"
+
+"@cypress/xvfb@^1.2.4":
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.2.4.tgz#2daf42e8275b39f4aa53c14214e557bd14e7748a"
+ integrity sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==
+ dependencies:
+ debug "^3.1.0"
+ lodash.once "^4.1.1"
+
+"@emotion/babel-plugin@^11.11.0":
+ version "11.11.0"
+ resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz#c2d872b6a7767a9d176d007f5b31f7d504bb5d6c"
+ integrity sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==
+ dependencies:
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/runtime" "^7.18.3"
+ "@emotion/hash" "^0.9.1"
+ "@emotion/memoize" "^0.8.1"
+ "@emotion/serialize" "^1.1.2"
+ babel-plugin-macros "^3.1.0"
+ convert-source-map "^1.5.0"
+ escape-string-regexp "^4.0.0"
+ find-root "^1.1.0"
+ source-map "^0.5.7"
+ stylis "4.2.0"
+
+"@emotion/cache@^11.11.0":
+ version "11.11.0"
+ resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff"
+ integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==
+ dependencies:
+ "@emotion/memoize" "^0.8.1"
+ "@emotion/sheet" "^1.2.2"
+ "@emotion/utils" "^1.2.1"
+ "@emotion/weak-memoize" "^0.3.1"
+ stylis "4.2.0"
+
+"@emotion/hash@^0.9.1":
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.1.tgz#4ffb0055f7ef676ebc3a5a91fb621393294e2f43"
+ integrity sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==
+
+"@emotion/is-prop-valid@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc"
+ integrity sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==
+ dependencies:
+ "@emotion/memoize" "^0.8.1"
+
+"@emotion/memoize@^0.8.1":
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17"
+ integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==
+
+"@emotion/react@^11.10.8":
+ version "11.11.1"
+ resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.1.tgz#b2c36afac95b184f73b08da8c214fdf861fa4157"
+ integrity sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==
+ dependencies:
+ "@babel/runtime" "^7.18.3"
+ "@emotion/babel-plugin" "^11.11.0"
+ "@emotion/cache" "^11.11.0"
+ "@emotion/serialize" "^1.1.2"
+ "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1"
+ "@emotion/utils" "^1.2.1"
+ "@emotion/weak-memoize" "^0.3.1"
+ hoist-non-react-statics "^3.3.1"
+
+"@emotion/serialize@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.2.tgz#017a6e4c9b8a803bd576ff3d52a0ea6fa5a62b51"
+ integrity sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==
+ dependencies:
+ "@emotion/hash" "^0.9.1"
+ "@emotion/memoize" "^0.8.1"
+ "@emotion/unitless" "^0.8.1"
+ "@emotion/utils" "^1.2.1"
+ csstype "^3.0.2"
+
+"@emotion/sheet@^1.2.2":
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec"
+ integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==
+
+"@emotion/styled@^11.10.8":
+ version "11.11.0"
+ resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.11.0.tgz#26b75e1b5a1b7a629d7c0a8b708fbf5a9cdce346"
+ integrity sha512-hM5Nnvu9P3midq5aaXj4I+lnSfNi7Pmd4EWk1fOZ3pxookaQTNew6bp4JaCBYM4HVFZF9g7UjJmsUmC2JlxOng==
+ dependencies:
+ "@babel/runtime" "^7.18.3"
+ "@emotion/babel-plugin" "^11.11.0"
+ "@emotion/is-prop-valid" "^1.2.1"
+ "@emotion/serialize" "^1.1.2"
+ "@emotion/use-insertion-effect-with-fallbacks" "^1.0.1"
+ "@emotion/utils" "^1.2.1"
+
+"@emotion/unitless@^0.8.1":
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.1.tgz#182b5a4704ef8ad91bde93f7a860a88fd92c79a3"
+ integrity sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==
+
+"@emotion/use-insertion-effect-with-fallbacks@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963"
+ integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==
+
+"@emotion/utils@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4"
+ integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==
+
+"@emotion/weak-memoize@^0.3.1":
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6"
+ integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==
+
+"@eslint-community/eslint-utils@^4.2.0":
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
+ integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
+ dependencies:
+ eslint-visitor-keys "^3.3.0"
+
+"@eslint-community/regexpp@^4.4.0":
+ version "4.5.1"
+ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.5.1.tgz#cdd35dce4fa1a89a4fd42b1599eb35b3af408884"
+ integrity sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==
+
+"@eslint/eslintrc@^2.0.3":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.0.3.tgz#4910db5505f4d503f27774bf356e3704818a0331"
+ integrity sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==
+ dependencies:
+ ajv "^6.12.4"
+ debug "^4.3.2"
+ espree "^9.5.2"
+ 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"
+
+"@eslint/js@8.43.0":
+ version "8.43.0"
+ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.43.0.tgz#559ca3d9ddbd6bf907ad524320a0d14b85586af0"
+ integrity sha512-s2UHCoiXfxMvmfzqoN+vrQ84ahUSYde9qNO1MdxmoEhyHWsfmwOpFlwYV+ePJEVc7gFnATGUi376WowX1N7tFg==
+
+"@hapi/hoek@^9.0.0":
+ version "9.3.0"
+ resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb"
+ integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==
+
+"@hapi/topo@^5.0.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-5.1.0.tgz#dc448e332c6c6e37a4dc02fd84ba8d44b9afb012"
+ integrity sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==
+ dependencies:
+ "@hapi/hoek" "^9.0.0"
+
+"@humanwhocodes/config-array@^0.11.10":
+ version "0.11.10"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.10.tgz#5a3ffe32cc9306365fb3fd572596cd602d5e12d2"
+ integrity sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==
+ dependencies:
+ "@humanwhocodes/object-schema" "^1.2.1"
+ debug "^4.1.1"
+ minimatch "^3.0.5"
+
+"@humanwhocodes/module-importer@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
+ integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
+
+"@humanwhocodes/object-schema@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
+ integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
+
+"@istanbuljs/load-nyc-config@^1.0.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
+ integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==
+ dependencies:
+ camelcase "^5.3.1"
+ find-up "^4.1.0"
+ get-package-type "^0.1.0"
+ js-yaml "^3.13.1"
+ resolve-from "^5.0.0"
+
+"@istanbuljs/schema@^0.1.2":
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
+ integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==
+
+"@jest/console@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba"
+ integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ jest-message-util "^27.5.1"
+ jest-util "^27.5.1"
+ slash "^3.0.0"
+
+"@jest/console@^28.1.3":
+ version "28.1.3"
+ resolved "https://registry.yarnpkg.com/@jest/console/-/console-28.1.3.tgz#2030606ec03a18c31803b8a36382762e447655df"
+ integrity sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==
+ dependencies:
+ "@jest/types" "^28.1.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ jest-message-util "^28.1.3"
+ jest-util "^28.1.3"
+ slash "^3.0.0"
+
+"@jest/core@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626"
+ integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==
+ dependencies:
+ "@jest/console" "^27.5.1"
+ "@jest/reporters" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ emittery "^0.8.1"
+ exit "^0.1.2"
+ graceful-fs "^4.2.9"
+ jest-changed-files "^27.5.1"
+ jest-config "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-resolve-dependencies "^27.5.1"
+ jest-runner "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ jest-watcher "^27.5.1"
+ micromatch "^4.0.4"
+ rimraf "^3.0.0"
+ slash "^3.0.0"
+ strip-ansi "^6.0.0"
+
+"@jest/environment@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74"
+ integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==
+ dependencies:
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ jest-mock "^27.5.1"
+
+"@jest/expect-utils@^29.5.0":
+ version "29.5.0"
+ resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.5.0.tgz#f74fad6b6e20f924582dc8ecbf2cb800fe43a036"
+ integrity sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==
+ dependencies:
+ jest-get-type "^29.4.3"
+
+"@jest/fake-timers@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74"
+ integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@sinonjs/fake-timers" "^8.0.1"
+ "@types/node" "*"
+ jest-message-util "^27.5.1"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
+
+"@jest/globals@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b"
+ integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ expect "^27.5.1"
+
+"@jest/reporters@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04"
+ integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==
+ dependencies:
+ "@bcoe/v8-coverage" "^0.2.3"
+ "@jest/console" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ collect-v8-coverage "^1.0.0"
+ exit "^0.1.2"
+ glob "^7.1.2"
+ graceful-fs "^4.2.9"
+ istanbul-lib-coverage "^3.0.0"
+ istanbul-lib-instrument "^5.1.0"
+ istanbul-lib-report "^3.0.0"
+ istanbul-lib-source-maps "^4.0.0"
+ istanbul-reports "^3.1.3"
+ jest-haste-map "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
+ slash "^3.0.0"
+ source-map "^0.6.0"
+ string-length "^4.0.1"
+ terminal-link "^2.0.0"
+ v8-to-istanbul "^8.1.0"
+
+"@jest/schemas@^28.1.3":
+ version "28.1.3"
+ resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-28.1.3.tgz#ad8b86a66f11f33619e3d7e1dcddd7f2d40ff905"
+ integrity sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==
+ dependencies:
+ "@sinclair/typebox" "^0.24.1"
+
+"@jest/schemas@^29.4.3":
+ version "29.4.3"
+ resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.3.tgz#39cf1b8469afc40b6f5a2baaa146e332c4151788"
+ integrity sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==
+ dependencies:
+ "@sinclair/typebox" "^0.25.16"
+
+"@jest/source-map@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf"
+ integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==
+ dependencies:
+ callsites "^3.0.0"
+ graceful-fs "^4.2.9"
+ source-map "^0.6.0"
+
+"@jest/test-result@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb"
+ integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==
+ dependencies:
+ "@jest/console" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ collect-v8-coverage "^1.0.0"
+
+"@jest/test-result@^28.1.3":
+ version "28.1.3"
+ resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-28.1.3.tgz#5eae945fd9f4b8fcfce74d239e6f725b6bf076c5"
+ integrity sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==
+ dependencies:
+ "@jest/console" "^28.1.3"
+ "@jest/types" "^28.1.3"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ collect-v8-coverage "^1.0.0"
+
+"@jest/test-sequencer@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b"
+ integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==
+ dependencies:
+ "@jest/test-result" "^27.5.1"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-runtime "^27.5.1"
+
+"@jest/transform@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409"
+ integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==
+ dependencies:
+ "@babel/core" "^7.1.0"
+ "@jest/types" "^27.5.1"
+ babel-plugin-istanbul "^6.1.1"
+ chalk "^4.0.0"
+ convert-source-map "^1.4.0"
+ fast-json-stable-stringify "^2.0.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-util "^27.5.1"
+ micromatch "^4.0.4"
+ pirates "^4.0.4"
+ slash "^3.0.0"
+ source-map "^0.6.1"
+ write-file-atomic "^3.0.0"
+
+"@jest/types@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80"
+ integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^16.0.0"
+ chalk "^4.0.0"
+
+"@jest/types@^28.1.3":
+ version "28.1.3"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.3.tgz#b05de80996ff12512bc5ceb1d208285a7d11748b"
+ integrity sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==
+ dependencies:
+ "@jest/schemas" "^28.1.3"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^17.0.8"
+ chalk "^4.0.0"
+
+"@jest/types@^29.5.0":
+ version "29.5.0"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.5.0.tgz#f59ef9b031ced83047c67032700d8c807d6e1593"
+ integrity sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==
+ dependencies:
+ "@jest/schemas" "^29.4.3"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^17.0.8"
+ chalk "^4.0.0"
+
+"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2":
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098"
+ integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==
+ dependencies:
+ "@jridgewell/set-array" "^1.0.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/resolve-uri@3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
+ integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
+
+"@jridgewell/set-array@^1.0.1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
+ integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
+
+"@jridgewell/source-map@^0.3.3":
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.3.tgz#8108265659d4c33e72ffe14e33d6cc5eb59f2fda"
+ integrity sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.0"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/sourcemap-codec@1.4.14":
+ version "1.4.14"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
+ integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
+
+"@jridgewell/sourcemap-codec@^1.4.10":
+ version "1.4.15"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+ integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
+"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9":
+ version "0.3.18"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6"
+ integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==
+ dependencies:
+ "@jridgewell/resolve-uri" "3.1.0"
+ "@jridgewell/sourcemap-codec" "1.4.14"
+
+"@leichtgewicht/ip-codec@^2.0.1":
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"
+ integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==
+
+"@mapbox/geojson-rewind@^0.5.0":
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz#591a5d71a9cd1da1a0bf3420b3bea31b0fc7946a"
+ integrity sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==
+ dependencies:
+ get-stream "^6.0.1"
+ minimist "^1.2.6"
+
+"@mapbox/geojson-types@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@mapbox/geojson-types/-/geojson-types-1.0.2.tgz#9aecf642cb00eab1080a57c4f949a65b4a5846d6"
+ integrity sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw==
+
+"@mapbox/jsonlint-lines-primitives@^2.0.2":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@mapbox/jsonlint-lines-primitives/-/jsonlint-lines-primitives-2.0.2.tgz#ce56e539f83552b58d10d672ea4d6fc9adc7b234"
+ integrity sha512-rY0o9A5ECsTQRVhv7tL/OyDpGAoUB4tTvLiW1DSzQGq4bvTPhNw1VpSNjDJc5GFZ2XuyOtSWSVN05qOtcD71qQ==
+
+"@mapbox/mapbox-gl-supported@^1.5.0":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.5.0.tgz#f60b6a55a5d8e5ee908347d2ce4250b15103dc8e"
+ integrity sha512-/PT1P6DNf7vjEEiPkVIRJkvibbqWtqnyGaBz3nfRdcxclNSnSdaLU5tfAgcD7I8Yt5i+L19s406YLl1koLnLbg==
+
+"@mapbox/point-geometry@0.1.0", "@mapbox/point-geometry@^0.1.0", "@mapbox/point-geometry@~0.1.0":
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz#8a83f9335c7860effa2eeeca254332aa0aeed8f2"
+ integrity sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==
+
+"@mapbox/tiny-sdf@^1.1.1":
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/@mapbox/tiny-sdf/-/tiny-sdf-1.2.5.tgz#424c620a96442b20402552be70a7f62a8407cc59"
+ integrity sha512-cD8A/zJlm6fdJOk6DqPUV8mcpyJkRz2x2R+/fYcWDYG3oWbG7/L7Yl/WqQ1VZCjnL9OTIMAn6c+BC5Eru4sQEw==
+
+"@mapbox/unitbezier@^0.0.0":
+ version "0.0.0"
+ resolved "https://registry.yarnpkg.com/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz#15651bd553a67b8581fb398810c98ad86a34524e"
+ integrity sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==
+
+"@mapbox/vector-tile@^1.3.1":
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz#d3a74c90402d06e89ec66de49ec817ff53409666"
+ integrity sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==
+ dependencies:
+ "@mapbox/point-geometry" "~0.1.0"
+
+"@mapbox/whoots-js@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe"
+ integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==
+
+"@mui/base@5.0.0-beta.5":
+ version "5.0.0-beta.5"
+ resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-beta.5.tgz#b566f3beb1eb2823139eabaf52014cf7be900015"
+ integrity sha512-vy3TWLQYdGNecTaufR4wDNQFV2WEg6wRPi6BVbx6q1vP3K1mbxIn1+XOqOzfYBXjFHvMx0gZAo2TgWbaqfgvAA==
+ dependencies:
+ "@babel/runtime" "^7.22.5"
+ "@emotion/is-prop-valid" "^1.2.1"
+ "@mui/types" "^7.2.4"
+ "@mui/utils" "^5.13.6"
+ "@popperjs/core" "^2.11.8"
+ clsx "^1.2.1"
+ prop-types "^15.8.1"
+ react-is "^18.2.0"
+
+"@mui/core-downloads-tracker@^5.13.4":
+ version "5.13.4"
+ resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.13.4.tgz#7e4b491d8081b6d45ae51556d82cb16b31315a19"
+ integrity sha512-yFrMWcrlI0TqRN5jpb6Ma9iI7sGTHpytdzzL33oskFHNQ8UgrtPas33Y1K7sWAMwCrr1qbWDrOHLAQG4tAzuSw==
+
+"@mui/icons-material@^5.11.16":
+ version "5.11.16"
+ resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.11.16.tgz#417fa773c56672e39d6ccfed9ac55591985f0d38"
+ integrity sha512-oKkx9z9Kwg40NtcIajF9uOXhxiyTZrrm9nmIJ4UjkU2IdHpd4QVLbCc/5hZN/y0C6qzi2Zlxyr9TGddQx2vx2A==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+
+"@mui/material@^5.12.2":
+ version "5.13.6"
+ resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.13.6.tgz#caaba1e071e394c415208404ce6964e6c14c16d6"
+ integrity sha512-/c2ZApeQm2sTYdQXjqEnldaBMBcUEiyu2VRS6bS39ZeNaAcCLBQbYocLR46R+f0S5dgpBzB0T4AsOABPOFYZ5Q==
+ dependencies:
+ "@babel/runtime" "^7.22.5"
+ "@mui/base" "5.0.0-beta.5"
+ "@mui/core-downloads-tracker" "^5.13.4"
+ "@mui/system" "^5.13.6"
+ "@mui/types" "^7.2.4"
+ "@mui/utils" "^5.13.6"
+ "@types/react-transition-group" "^4.4.6"
+ clsx "^1.2.1"
+ csstype "^3.1.2"
+ prop-types "^15.8.1"
+ react-is "^18.2.0"
+ react-transition-group "^4.4.5"
+
+"@mui/private-theming@^5.13.1":
+ version "5.13.1"
+ resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.13.1.tgz#c3e9a0b44f9c5a51b92cfcfb660536060cb61ed7"
+ integrity sha512-HW4npLUD9BAkVppOUZHeO1FOKUJWAwbpy0VQoGe3McUYTlck1HezGHQCfBQ5S/Nszi7EViqiimECVl9xi+/WjQ==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+ "@mui/utils" "^5.13.1"
+ prop-types "^15.8.1"
+
+"@mui/styled-engine@^5.13.2":
+ version "5.13.2"
+ resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.13.2.tgz#c87bd61c0ab8086d34828b6defe97c02bcd642ef"
+ integrity sha512-VCYCU6xVtXOrIN8lcbuPmoG+u7FYuOERG++fpY74hPpEWkyFQG97F+/XfTQVYzlR2m7nPjnwVUgATcTCMEaMvw==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+ "@emotion/cache" "^11.11.0"
+ csstype "^3.1.2"
+ prop-types "^15.8.1"
+
+"@mui/system@^5.13.6":
+ version "5.13.6"
+ resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.13.6.tgz#5bf4f84fad0c9ed771458f821e384f61abfa33ca"
+ integrity sha512-G3Xr28uLqU3DyF6r2LQkHGw/ku4P0AHzlKVe7FGXOPl7X1u+hoe2xxj8Vdiq/69II/mh9OP21i38yBWgWb7WgQ==
+ dependencies:
+ "@babel/runtime" "^7.22.5"
+ "@mui/private-theming" "^5.13.1"
+ "@mui/styled-engine" "^5.13.2"
+ "@mui/types" "^7.2.4"
+ "@mui/utils" "^5.13.6"
+ clsx "^1.2.1"
+ csstype "^3.1.2"
+ prop-types "^15.8.1"
+
+"@mui/types@^7.2.4":
+ version "7.2.4"
+ resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.4.tgz#b6fade19323b754c5c6de679a38f068fd50b9328"
+ integrity sha512-LBcwa8rN84bKF+f5sDyku42w1NTxaPgPyYKODsh01U1fVstTClbUoSA96oyRBnSNyEiAVjKm6Gwx9vjR+xyqHA==
+
+"@mui/utils@^5.13.1", "@mui/utils@^5.13.6":
+ version "5.13.6"
+ resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.13.6.tgz#aa29d75de59577585b9f23891b03592d40459ed7"
+ integrity sha512-ggNlxl5NPSbp+kNcQLmSig6WVB0Id+4gOxhx644987v4fsji+CSXc+MFYLocFB/x4oHtzCUlSzbVHlJfP/fXoQ==
+ dependencies:
+ "@babel/runtime" "^7.22.5"
+ "@types/prop-types" "^15.7.5"
+ "@types/react-is" "^18.2.0"
+ prop-types "^15.8.1"
+ react-is "^18.2.0"
+
+"@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1":
+ version "5.1.1-v1"
+ resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129"
+ integrity sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==
+ dependencies:
+ eslint-scope "5.1.1"
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@plotly/d3-sankey-circular@0.33.1":
+ version "0.33.1"
+ resolved "https://registry.yarnpkg.com/@plotly/d3-sankey-circular/-/d3-sankey-circular-0.33.1.tgz#15d1e0337e0e4b1135bdf0e2195c88adacace1a7"
+ integrity sha512-FgBV1HEvCr3DV7RHhDsPXyryknucxtfnLwPtCKKxdolKyTFYoLX/ibEfX39iFYIL7DYbVeRtP43dbFcrHNE+KQ==
+ dependencies:
+ d3-array "^1.2.1"
+ d3-collection "^1.0.4"
+ d3-shape "^1.2.0"
+ elementary-circuits-directed-graph "^1.0.4"
+
+"@plotly/d3-sankey@0.7.2":
+ version "0.7.2"
+ resolved "https://registry.yarnpkg.com/@plotly/d3-sankey/-/d3-sankey-0.7.2.tgz#ddd5290d3b02c60037ced018a162644a2ccef33b"
+ integrity sha512-2jdVos1N3mMp3QW0k2q1ph7Gd6j5PY1YihBrwpkFnKqO+cqtZq3AdEYUeSGXMeLsBDQYiqTVcihYfk8vr5tqhw==
+ dependencies:
+ d3-array "1"
+ d3-collection "1"
+ d3-shape "^1.2.0"
+
+"@plotly/d3@3.8.1":
+ version "3.8.1"
+ resolved "https://registry.yarnpkg.com/@plotly/d3/-/d3-3.8.1.tgz#674bf19809ffcc359e0ab388a1051f2dac5e6877"
+ integrity sha512-x49ThEu1FRA00kTso4Jdfyf2byaCPLBGmLjAYQz5OzaPyLUhHesX3/Nfv2OHEhynhdy2UB39DLXq6thYe2L2kg==
+
+"@plotly/point-cluster@^3.1.9":
+ version "3.1.9"
+ resolved "https://registry.yarnpkg.com/@plotly/point-cluster/-/point-cluster-3.1.9.tgz#8ffec77fbf5041bf15401079e4fdf298220291c1"
+ integrity sha512-MwaI6g9scKf68Orpr1pHZ597pYx9uP8UEFXLPbsCmuw3a84obwz6pnMXGc90VhgDNeNiLEdlmuK7CPo+5PIxXw==
+ dependencies:
+ array-bounds "^1.0.1"
+ binary-search-bounds "^2.0.4"
+ clamp "^1.0.1"
+ defined "^1.0.0"
+ dtype "^2.0.0"
+ flatten-vertex-data "^1.0.2"
+ is-obj "^1.0.1"
+ math-log2 "^1.0.1"
+ parse-rect "^1.2.0"
+ pick-by-alias "^1.2.0"
+
+"@pmmmwh/react-refresh-webpack-plugin@^0.5.3":
+ version "0.5.10"
+ resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz#2eba163b8e7dbabb4ce3609ab5e32ab63dda3ef8"
+ integrity sha512-j0Ya0hCFZPd4x40qLzbhGsh9TMtdb+CJQiso+WxLOPNasohq9cc5SNUcwsZaRH6++Xh91Xkm/xHCkuIiIu0LUA==
+ dependencies:
+ ansi-html-community "^0.0.8"
+ common-path-prefix "^3.0.0"
+ core-js-pure "^3.23.3"
+ error-stack-parser "^2.0.6"
+ find-up "^5.0.0"
+ html-entities "^2.1.0"
+ loader-utils "^2.0.4"
+ schema-utils "^3.0.0"
+ source-map "^0.7.3"
+
+"@popperjs/core@^2.11.8":
+ version "2.11.8"
+ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
+ integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
+
+"@reduxjs/toolkit@^1.8.1":
+ version "1.9.5"
+ resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.9.5.tgz#d3987849c24189ca483baa7aa59386c8e52077c4"
+ integrity sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==
+ dependencies:
+ immer "^9.0.21"
+ redux "^4.2.1"
+ redux-thunk "^2.4.2"
+ reselect "^4.1.8"
+
+"@rollup/plugin-babel@^5.2.0":
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283"
+ integrity sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==
+ dependencies:
+ "@babel/helper-module-imports" "^7.10.4"
+ "@rollup/pluginutils" "^3.1.0"
+
+"@rollup/plugin-node-resolve@^11.2.1":
+ version "11.2.1"
+ resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60"
+ integrity sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==
+ dependencies:
+ "@rollup/pluginutils" "^3.1.0"
+ "@types/resolve" "1.17.1"
+ builtin-modules "^3.1.0"
+ deepmerge "^4.2.2"
+ is-module "^1.0.0"
+ resolve "^1.19.0"
+
+"@rollup/plugin-replace@^2.4.1":
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz#a2d539314fbc77c244858faa523012825068510a"
+ integrity sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==
+ dependencies:
+ "@rollup/pluginutils" "^3.1.0"
+ magic-string "^0.25.7"
+
+"@rollup/pluginutils@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
+ integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
+ dependencies:
+ "@types/estree" "0.0.39"
+ estree-walker "^1.0.1"
+ picomatch "^2.2.2"
+
+"@rushstack/eslint-patch@^1.1.0":
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.3.2.tgz#31b9c510d8cada9683549e1dbb4284cca5001faf"
+ integrity sha512-V+MvGwaHH03hYhY+k6Ef/xKd6RYlc4q8WBx+2ANmipHJcKuktNcI/NgEsJgdSUF6Lw32njT6OnrRsKYCdgHjYw==
+
+"@sideway/address@^4.1.3":
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0"
+ integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==
+ dependencies:
+ "@hapi/hoek" "^9.0.0"
+
+"@sideway/formula@^3.0.1":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@sideway/formula/-/formula-3.0.1.tgz#80fcbcbaf7ce031e0ef2dd29b1bfc7c3f583611f"
+ integrity sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==
+
+"@sideway/pinpoint@^2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df"
+ integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==
+
+"@sinclair/typebox@^0.24.1":
+ version "0.24.51"
+ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f"
+ integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==
+
+"@sinclair/typebox@^0.25.16":
+ version "0.25.24"
+ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.24.tgz#8c7688559979f7079aacaf31aa881c3aa410b718"
+ integrity sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==
+
+"@sinonjs/commons@^1.7.0":
+ version "1.8.6"
+ resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.6.tgz#80c516a4dc264c2a69115e7578d62581ff455ed9"
+ integrity sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==
+ dependencies:
+ type-detect "4.0.8"
+
+"@sinonjs/fake-timers@^8.0.1":
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7"
+ integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==
+ dependencies:
+ "@sinonjs/commons" "^1.7.0"
+
+"@surma/rollup-plugin-off-main-thread@^2.2.3":
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053"
+ integrity sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==
+ dependencies:
+ ejs "^3.1.6"
+ json5 "^2.2.0"
+ magic-string "^0.25.0"
+ string.prototype.matchall "^4.0.6"
+
+"@svgr/babel-plugin-add-jsx-attribute@^5.4.0":
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz#81ef61947bb268eb9d50523446f9c638fb355906"
+ integrity sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==
+
+"@svgr/babel-plugin-remove-jsx-attribute@^5.4.0":
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz#6b2c770c95c874654fd5e1d5ef475b78a0a962ef"
+ integrity sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==
+
+"@svgr/babel-plugin-remove-jsx-empty-expression@^5.0.1":
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz#25621a8915ed7ad70da6cea3d0a6dbc2ea933efd"
+ integrity sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==
+
+"@svgr/babel-plugin-replace-jsx-attribute-value@^5.0.1":
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz#0b221fc57f9fcd10e91fe219e2cd0dd03145a897"
+ integrity sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==
+
+"@svgr/babel-plugin-svg-dynamic-title@^5.4.0":
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz#139b546dd0c3186b6e5db4fefc26cb0baea729d7"
+ integrity sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==
+
+"@svgr/babel-plugin-svg-em-dimensions@^5.4.0":
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz#6543f69526632a133ce5cabab965deeaea2234a0"
+ integrity sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==
+
+"@svgr/babel-plugin-transform-react-native-svg@^5.4.0":
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz#00bf9a7a73f1cad3948cdab1f8dfb774750f8c80"
+ integrity sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==
+
+"@svgr/babel-plugin-transform-svg-component@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz#583a5e2a193e214da2f3afeb0b9e8d3250126b4a"
+ integrity sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==
+
+"@svgr/babel-preset@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-5.5.0.tgz#8af54f3e0a8add7b1e2b0fcd5a882c55393df327"
+ integrity sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==
+ dependencies:
+ "@svgr/babel-plugin-add-jsx-attribute" "^5.4.0"
+ "@svgr/babel-plugin-remove-jsx-attribute" "^5.4.0"
+ "@svgr/babel-plugin-remove-jsx-empty-expression" "^5.0.1"
+ "@svgr/babel-plugin-replace-jsx-attribute-value" "^5.0.1"
+ "@svgr/babel-plugin-svg-dynamic-title" "^5.4.0"
+ "@svgr/babel-plugin-svg-em-dimensions" "^5.4.0"
+ "@svgr/babel-plugin-transform-react-native-svg" "^5.4.0"
+ "@svgr/babel-plugin-transform-svg-component" "^5.5.0"
+
+"@svgr/core@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/core/-/core-5.5.0.tgz#82e826b8715d71083120fe8f2492ec7d7874a579"
+ integrity sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==
+ dependencies:
+ "@svgr/plugin-jsx" "^5.5.0"
+ camelcase "^6.2.0"
+ cosmiconfig "^7.0.0"
+
+"@svgr/hast-util-to-babel-ast@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz#5ee52a9c2533f73e63f8f22b779f93cd432a5461"
+ integrity sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==
+ dependencies:
+ "@babel/types" "^7.12.6"
+
+"@svgr/plugin-jsx@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz#1aa8cd798a1db7173ac043466d7b52236b369000"
+ integrity sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==
+ dependencies:
+ "@babel/core" "^7.12.3"
+ "@svgr/babel-preset" "^5.5.0"
+ "@svgr/hast-util-to-babel-ast" "^5.5.0"
+ svg-parser "^2.0.2"
+
+"@svgr/plugin-svgo@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz#02da55d85320549324e201c7b2e53bf431fcc246"
+ integrity sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==
+ dependencies:
+ cosmiconfig "^7.0.0"
+ deepmerge "^4.2.2"
+ svgo "^1.2.2"
+
+"@svgr/webpack@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-5.5.0.tgz#aae858ee579f5fa8ce6c3166ef56c6a1b381b640"
+ integrity sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==
+ dependencies:
+ "@babel/core" "^7.12.3"
+ "@babel/plugin-transform-react-constant-elements" "^7.12.1"
+ "@babel/preset-env" "^7.12.1"
+ "@babel/preset-react" "^7.12.5"
+ "@svgr/core" "^5.5.0"
+ "@svgr/plugin-jsx" "^5.5.0"
+ "@svgr/plugin-svgo" "^5.5.0"
+ loader-utils "^2.0.0"
+
+"@testing-library/dom@^8.5.0":
+ version "8.20.1"
+ resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.20.1.tgz#2e52a32e46fc88369eef7eef634ac2a192decd9f"
+ integrity sha512-/DiOQ5xBxgdYRC8LNk7U+RWat0S3qRLeIw3ZIkMQ9kkVlRmwD/Eg8k8CqIpD6GW7u20JIUOfMKbxtiLutpjQ4g==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/runtime" "^7.12.5"
+ "@types/aria-query" "^5.0.1"
+ aria-query "5.1.3"
+ chalk "^4.1.0"
+ dom-accessibility-api "^0.5.9"
+ lz-string "^1.5.0"
+ pretty-format "^27.0.2"
+
+"@testing-library/jest-dom@^5.16.4":
+ version "5.16.5"
+ resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.5.tgz#3912846af19a29b2dbf32a6ae9c31ef52580074e"
+ integrity sha512-N5ixQ2qKpi5OLYfwQmUb/5mSV9LneAcaUfp32pn4yCnpb8r/Yz0pXFPck21dIicKmi+ta5WRAknkZCfA8refMA==
+ dependencies:
+ "@adobe/css-tools" "^4.0.1"
+ "@babel/runtime" "^7.9.2"
+ "@types/testing-library__jest-dom" "^5.9.1"
+ aria-query "^5.0.0"
+ chalk "^3.0.0"
+ css.escape "^1.5.1"
+ dom-accessibility-api "^0.5.6"
+ lodash "^4.17.15"
+ redent "^3.0.0"
+
+"@testing-library/react@^13.0.1":
+ version "13.4.0"
+ resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.4.0.tgz#6a31e3bf5951615593ad984e96b9e5e2d9380966"
+ integrity sha512-sXOGON+WNTh3MLE9rve97ftaZukN3oNf2KjDy7YTx6hcTO2uuLHuCGynMDhFwGw/jYf4OJ2Qk0i4i79qMNNkyw==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+ "@testing-library/dom" "^8.5.0"
+ "@types/react-dom" "^18.0.0"
+
+"@testing-library/user-event@^14.1.1":
+ version "14.4.3"
+ resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.4.3.tgz#af975e367743fa91989cd666666aec31a8f50591"
+ integrity sha512-kCUc5MEwaEMakkO5x7aoD+DLi02ehmEM2QCGWvNqAS1dV/fAvORWEjnjsEIvml59M7Y5kCkWN6fCCyPOe8OL6Q==
+
+"@tootallnate/once@1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
+ integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
+
+"@trysound/sax@0.2.0":
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
+ integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
+
+"@turf/area@^6.4.0":
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/@turf/area/-/area-6.5.0.tgz#1d0d7aee01d8a4a3d4c91663ed35cc615f36ad56"
+ integrity sha512-xCZdiuojokLbQ+29qR6qoMD89hv+JAgWjLrwSEWL+3JV8IXKeNFl6XkEJz9HGkVpnXvQKJoRz4/liT+8ZZ5Jyg==
+ dependencies:
+ "@turf/helpers" "^6.5.0"
+ "@turf/meta" "^6.5.0"
+
+"@turf/bbox@^6.4.0":
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/@turf/bbox/-/bbox-6.5.0.tgz#bec30a744019eae420dac9ea46fb75caa44d8dc5"
+ integrity sha512-RBbLaao5hXTYyyg577iuMtDB8ehxMlUqHEJiMs8jT1GHkFhr6sYre3lmLsPeYEi/ZKj5TP5tt7fkzNdJ4GIVyw==
+ dependencies:
+ "@turf/helpers" "^6.5.0"
+ "@turf/meta" "^6.5.0"
+
+"@turf/centroid@^6.0.2":
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/@turf/centroid/-/centroid-6.5.0.tgz#ecaa365412e5a4d595bb448e7dcdacfb49eb0009"
+ integrity sha512-MwE1oq5E3isewPprEClbfU5pXljIK/GUOMbn22UM3IFPDJX0KeoyLNwghszkdmFp/qMGL/M13MMWvU+GNLXP/A==
+ dependencies:
+ "@turf/helpers" "^6.5.0"
+ "@turf/meta" "^6.5.0"
+
+"@turf/helpers@^6.5.0":
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/@turf/helpers/-/helpers-6.5.0.tgz#f79af094bd6b8ce7ed2bd3e089a8493ee6cae82e"
+ integrity sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==
+
+"@turf/meta@^6.5.0":
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/@turf/meta/-/meta-6.5.0.tgz#b725c3653c9f432133eaa04d3421f7e51e0418ca"
+ integrity sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==
+ dependencies:
+ "@turf/helpers" "^6.5.0"
+
+"@types/aria-query@^5.0.1":
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.1.tgz#3286741fb8f1e1580ac28784add4c7a1d49bdfbc"
+ integrity sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==
+
+"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14":
+ version "7.20.1"
+ resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.1.tgz#916ecea274b0c776fec721e333e55762d3a9614b"
+ integrity sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==
+ dependencies:
+ "@babel/parser" "^7.20.7"
+ "@babel/types" "^7.20.7"
+ "@types/babel__generator" "*"
+ "@types/babel__template" "*"
+ "@types/babel__traverse" "*"
+
+"@types/babel__generator@*":
+ version "7.6.4"
+ resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7"
+ integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==
+ dependencies:
+ "@babel/types" "^7.0.0"
+
+"@types/babel__template@*":
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969"
+ integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==
+ dependencies:
+ "@babel/parser" "^7.1.0"
+ "@babel/types" "^7.0.0"
+
+"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6":
+ version "7.20.1"
+ resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.1.tgz#dd6f1d2411ae677dcb2db008c962598be31d6acf"
+ integrity sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==
+ dependencies:
+ "@babel/types" "^7.20.7"
+
+"@types/body-parser@*":
+ version "1.19.2"
+ resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0"
+ integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==
+ dependencies:
+ "@types/connect" "*"
+ "@types/node" "*"
+
+"@types/bonjour@^3.5.9":
+ version "3.5.10"
+ resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275"
+ integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==
+ dependencies:
+ "@types/node" "*"
+
+"@types/connect-history-api-fallback@^1.3.5":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.0.tgz#9fd20b3974bdc2bcd4ac6567e2e0f6885cb2cf41"
+ integrity sha512-4x5FkPpLipqwthjPsF7ZRbOv3uoLUFkTA9G9v583qi4pACvq0uTELrB8OLUzPWUI4IJIyvM85vzkV1nyiI2Lig==
+ dependencies:
+ "@types/express-serve-static-core" "*"
+ "@types/node" "*"
+
+"@types/connect@*":
+ version "3.4.35"
+ resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1"
+ integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==
+ dependencies:
+ "@types/node" "*"
+
+"@types/eslint-scope@^3.7.3":
+ version "3.7.4"
+ resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16"
+ integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==
+ dependencies:
+ "@types/eslint" "*"
+ "@types/estree" "*"
+
+"@types/eslint@*", "@types/eslint@^7.29.0 || ^8.4.1":
+ version "8.40.2"
+ resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.40.2.tgz#2833bc112d809677864a4b0e7d1de4f04d7dac2d"
+ integrity sha512-PRVjQ4Eh9z9pmmtaq8nTjZjQwKFk7YIHIud3lRoKRBgUQjgjRmoGxxGEPXQkF+lH7QkHJRNr5F4aBgYCW0lqpQ==
+ dependencies:
+ "@types/estree" "*"
+ "@types/json-schema" "*"
+
+"@types/estree@*", "@types/estree@^1.0.0":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194"
+ integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==
+
+"@types/estree@0.0.39":
+ version "0.0.39"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
+ integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
+
+"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.33":
+ version "4.17.35"
+ resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz#c95dd4424f0d32e525d23812aa8ab8e4d3906c4f"
+ integrity sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==
+ dependencies:
+ "@types/node" "*"
+ "@types/qs" "*"
+ "@types/range-parser" "*"
+ "@types/send" "*"
+
+"@types/express@*", "@types/express@^4.17.13":
+ version "4.17.17"
+ resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.17.tgz#01d5437f6ef9cfa8668e616e13c2f2ac9a491ae4"
+ integrity sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==
+ dependencies:
+ "@types/body-parser" "*"
+ "@types/express-serve-static-core" "^4.17.33"
+ "@types/qs" "*"
+ "@types/serve-static" "*"
+
+"@types/graceful-fs@^4.1.2":
+ version "4.1.6"
+ resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.6.tgz#e14b2576a1c25026b7f02ede1de3b84c3a1efeae"
+ integrity sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==
+ dependencies:
+ "@types/node" "*"
+
+"@types/hoist-non-react-statics@^3.3.1":
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
+ integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
+ dependencies:
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+
+"@types/html-minifier-terser@^6.0.0":
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35"
+ integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==
+
+"@types/http-errors@*":
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.1.tgz#20172f9578b225f6c7da63446f56d4ce108d5a65"
+ integrity sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==
+
+"@types/http-proxy@^1.17.8":
+ version "1.17.11"
+ resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.11.tgz#0ca21949a5588d55ac2b659b69035c84bd5da293"
+ integrity sha512-HC8G7c1WmaF2ekqpnFq626xd3Zz0uvaqFmBJNRZCGEZCXkvSdJoNFn/8Ygbd9fKNQj8UzLdCETaI0UWPAjK7IA==
+ dependencies:
+ "@types/node" "*"
+
+"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44"
+ integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==
+
+"@types/istanbul-lib-report@*":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686"
+ integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==
+ dependencies:
+ "@types/istanbul-lib-coverage" "*"
+
+"@types/istanbul-reports@^3.0.0":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff"
+ integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==
+ dependencies:
+ "@types/istanbul-lib-report" "*"
+
+"@types/jest@*":
+ version "29.5.2"
+ resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.2.tgz#86b4afc86e3a8f3005b297ed8a72494f89e6395b"
+ integrity sha512-mSoZVJF5YzGVCk+FsDxzDuH7s+SCkzrgKZzf0Z0T2WudhBUPoF6ktoTPC4R0ZoCPCV5xUvuU6ias5NvxcBcMMg==
+ dependencies:
+ expect "^29.0.0"
+ pretty-format "^29.0.0"
+
+"@types/jest@^27.4.1":
+ version "27.5.2"
+ resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.5.2.tgz#ec49d29d926500ffb9fd22b84262e862049c026c"
+ integrity sha512-mpT8LJJ4CMeeahobofYWIjFo0xonRS/HfxnVEPMPFSQdGUt1uHCnoPT7Zhb+sjDU2wz0oKV0OLUR0WzrHNgfeA==
+ dependencies:
+ jest-matcher-utils "^27.0.0"
+ pretty-format "^27.0.0"
+
+"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
+ version "7.0.12"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
+ integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
+
+"@types/json5@^0.0.29":
+ version "0.0.29"
+ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
+ integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
+
+"@types/mime@*":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10"
+ integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==
+
+"@types/mime@^1":
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
+ integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
+
+"@types/node@*":
+ version "20.3.2"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.3.2.tgz#fa6a90f2600e052a03c18b8cb3fd83dd4e599898"
+ integrity sha512-vOBLVQeCQfIcF/2Y7eKFTqrMnizK5lRNQ7ykML/5RuwVXVWxYkgwS7xbt4B6fKCUPgbSL5FSsjHQpaGQP/dQmw==
+
+"@types/node@^14.14.31":
+ version "14.18.53"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.53.tgz#42855629b8773535ab868238718745bf56c56219"
+ integrity sha512-soGmOpVBUq+gaBMwom1M+krC/NNbWlosh4AtGA03SyWNDiqSKtwp7OulO1M6+mg8YkHMvJ/y0AkCeO8d1hNb7A==
+
+"@types/node@^17.0.25":
+ version "17.0.45"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
+ integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
+
+"@types/papaparse@^5.3.10":
+ version "5.3.10"
+ resolved "https://registry.yarnpkg.com/@types/papaparse/-/papaparse-5.3.10.tgz#d315347dfafd0458aa25062ec9e3dcebb948b6de"
+ integrity sha512-mS1Fta/xJ9EDYmAvpeWzcV9Gr0cOl1ClpW7di9+wSUNDIDO55tBtyXg97O7K+Syrd9rDEmuejM2iqmJIJ1SO5g==
+ dependencies:
+ "@types/node" "*"
+
+"@types/parse-json@^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
+ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
+
+"@types/plotly.js@*":
+ version "2.12.18"
+ resolved "https://registry.yarnpkg.com/@types/plotly.js/-/plotly.js-2.12.18.tgz#7a231ce72a73fafe4842096b8c99d10a41b60962"
+ integrity sha512-ff+CIEWnqZNjZqHtQZvkEAVuLs9fkm1f54QnPVmgoET7wMHdSqUka2hasVN4e5yfHD05YwGjsAtCseewJh/BMw==
+
+"@types/prettier@^2.1.5":
+ version "2.7.3"
+ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f"
+ integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==
+
+"@types/prop-types@*", "@types/prop-types@^15.7.5":
+ version "15.7.5"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
+ integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
+
+"@types/q@^1.5.1":
+ version "1.5.5"
+ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df"
+ integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==
+
+"@types/qs@*":
+ version "6.9.7"
+ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
+ integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
+
+"@types/range-parser@*":
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
+ integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
+
+"@types/react-dom@^18.0.0", "@types/react-dom@^18.0.2":
+ version "18.2.6"
+ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.6.tgz#ad621fa71a8db29af7c31b41b2ea3d8a6f4144d1"
+ integrity sha512-2et4PDvg6PVCyS7fuTc4gPoksV58bW0RwSxWKcPRcHZf0PRUGq03TKcD/rUHe3azfV6/5/biUBJw+HhCQjaP0A==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react-is@^18.2.0":
+ version "18.2.1"
+ resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-18.2.1.tgz#61d01c2a6fc089a53520c0b66996d458fdc46863"
+ integrity sha512-wyUkmaaSZEzFZivD8F2ftSyAfk6L+DfFliVj/mYdOXbVjRcS87fQJLTnhk6dRZPuJjI+9g6RZJO4PNCngUrmyw==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react-plotly.js@^2.6.0":
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/@types/react-plotly.js/-/react-plotly.js-2.6.0.tgz#1b856c2ed1219babda3e95ef3270091f156ff987"
+ integrity sha512-nJJ57U0/CNDAO+F3dpnMgM8PtjLE/O1I3O6gq4+5Q13uKqrPnHGYOttfdzQJ4D7KYgF609miVzEYakUS2zds8w==
+ dependencies:
+ "@types/plotly.js" "*"
+ "@types/react" "*"
+
+"@types/react-transition-group@^4.4.6":
+ version "4.4.6"
+ resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.6.tgz#18187bcda5281f8e10dfc48f0943e2fdf4f75e2e"
+ integrity sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react@*", "@types/react@^18.0.6":
+ version "18.2.14"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.14.tgz#fa7a6fecf1ce35ca94e74874f70c56ce88f7a127"
+ integrity sha512-A0zjq+QN/O0Kpe30hA1GidzyFjatVvrpIvWLxD+xv67Vt91TWWgco9IvrJBkeyHm1trGaFS/FSGqPlhyeZRm0g==
+ dependencies:
+ "@types/prop-types" "*"
+ "@types/scheduler" "*"
+ csstype "^3.0.2"
+
+"@types/resolve@1.17.1":
+ version "1.17.1"
+ resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
+ integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==
+ dependencies:
+ "@types/node" "*"
+
+"@types/retry@0.12.0":
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
+ integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
+
+"@types/scheduler@*":
+ version "0.16.3"
+ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.3.tgz#cef09e3ec9af1d63d2a6cc5b383a737e24e6dcf5"
+ integrity sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==
+
+"@types/semver@^7.3.12":
+ version "7.5.0"
+ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a"
+ integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==
+
+"@types/send@*":
+ version "0.17.1"
+ resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.1.tgz#ed4932b8a2a805f1fe362a70f4e62d0ac994e301"
+ integrity sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==
+ dependencies:
+ "@types/mime" "^1"
+ "@types/node" "*"
+
+"@types/serve-index@^1.9.1":
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278"
+ integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==
+ dependencies:
+ "@types/express" "*"
+
+"@types/serve-static@*", "@types/serve-static@^1.13.10":
+ version "1.15.2"
+ resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.2.tgz#3e5419ecd1e40e7405d34093f10befb43f63381a"
+ integrity sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==
+ dependencies:
+ "@types/http-errors" "*"
+ "@types/mime" "*"
+ "@types/node" "*"
+
+"@types/sinonjs__fake-timers@8.1.1":
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3"
+ integrity sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==
+
+"@types/sizzle@^2.3.2":
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.3.tgz#ff5e2f1902969d305225a047c8a0fd5c915cebef"
+ integrity sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==
+
+"@types/sockjs@^0.3.33":
+ version "0.3.33"
+ resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f"
+ integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==
+ dependencies:
+ "@types/node" "*"
+
+"@types/stack-utils@^2.0.0":
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
+ integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
+
+"@types/testing-library__jest-dom@^5.9.1":
+ version "5.14.6"
+ resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.6.tgz#4887f6e1af11215428ab02777873bcede98a53b0"
+ integrity sha512-FkHXCb+ikSoUP4Y4rOslzTdX5sqYwMxfefKh1GmZ8ce1GOkEHntSp6b5cGadmNfp5e4BMEWOMx+WSKd5/MqlDA==
+ dependencies:
+ "@types/jest" "*"
+
+"@types/trusted-types@^2.0.2":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.3.tgz#a136f83b0758698df454e328759dbd3d44555311"
+ integrity sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==
+
+"@types/use-sync-external-store@^0.0.3":
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43"
+ integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
+
+"@types/ws@^8.5.5":
+ version "8.5.5"
+ resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.5.tgz#af587964aa06682702ee6dcbc7be41a80e4b28eb"
+ integrity sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==
+ dependencies:
+ "@types/node" "*"
+
+"@types/yargs-parser@*":
+ version "21.0.0"
+ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
+ integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==
+
+"@types/yargs@^16.0.0":
+ version "16.0.5"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.5.tgz#12cc86393985735a283e387936398c2f9e5f88e3"
+ integrity sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==
+ dependencies:
+ "@types/yargs-parser" "*"
+
+"@types/yargs@^17.0.8":
+ version "17.0.24"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.24.tgz#b3ef8d50ad4aa6aecf6ddc97c580a00f5aa11902"
+ integrity sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==
+ dependencies:
+ "@types/yargs-parser" "*"
+
+"@types/yauzl@^2.9.1":
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.0.tgz#b3248295276cf8c6f153ebe6a9aba0c988cb2599"
+ integrity sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==
+ dependencies:
+ "@types/node" "*"
+
+"@typescript-eslint/eslint-plugin@^5.5.0":
+ version "5.60.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.60.1.tgz#81382d6ecb92b8dda70e91f9035611cb2fecd1c3"
+ integrity sha512-KSWsVvsJsLJv3c4e73y/Bzt7OpqMCADUO846bHcuWYSYM19bldbAeDv7dYyV0jwkbMfJ2XdlzwjhXtuD7OY6bw==
+ dependencies:
+ "@eslint-community/regexpp" "^4.4.0"
+ "@typescript-eslint/scope-manager" "5.60.1"
+ "@typescript-eslint/type-utils" "5.60.1"
+ "@typescript-eslint/utils" "5.60.1"
+ debug "^4.3.4"
+ grapheme-splitter "^1.0.4"
+ ignore "^5.2.0"
+ natural-compare-lite "^1.4.0"
+ semver "^7.3.7"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/experimental-utils@^5.0.0":
+ version "5.60.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.60.1.tgz#d783bb63b9183541019a945eda6a9d96b096d985"
+ integrity sha512-TXUdLxv2t8181nh5yLXl/Gr/zKj1ZofQ7m+ZdmG2+El0TYOHCvlZfc35D4nturemC3RUnf3KmLuFp3bVBjkG5w==
+ dependencies:
+ "@typescript-eslint/utils" "5.60.1"
+
+"@typescript-eslint/parser@^5.5.0":
+ version "5.60.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.60.1.tgz#0f2f58209c0862a73e3d5a56099abfdfa21d0fd3"
+ integrity sha512-pHWlc3alg2oSMGwsU/Is8hbm3XFbcrb6P5wIxcQW9NsYBfnrubl/GhVVD/Jm/t8HXhA2WncoIRfBtnCgRGV96Q==
+ dependencies:
+ "@typescript-eslint/scope-manager" "5.60.1"
+ "@typescript-eslint/types" "5.60.1"
+ "@typescript-eslint/typescript-estree" "5.60.1"
+ debug "^4.3.4"
+
+"@typescript-eslint/scope-manager@5.60.1":
+ version "5.60.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.60.1.tgz#35abdb47f500c68c08f2f2b4f22c7c79472854bb"
+ integrity sha512-Dn/LnN7fEoRD+KspEOV0xDMynEmR3iSHdgNsarlXNLGGtcUok8L4N71dxUgt3YvlO8si7E+BJ5Fe3wb5yUw7DQ==
+ dependencies:
+ "@typescript-eslint/types" "5.60.1"
+ "@typescript-eslint/visitor-keys" "5.60.1"
+
+"@typescript-eslint/type-utils@5.60.1":
+ version "5.60.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.60.1.tgz#17770540e98d65ab4730c7aac618003f702893f4"
+ integrity sha512-vN6UztYqIu05nu7JqwQGzQKUJctzs3/Hg7E2Yx8rz9J+4LgtIDFWjjl1gm3pycH0P3mHAcEUBd23LVgfrsTR8A==
+ dependencies:
+ "@typescript-eslint/typescript-estree" "5.60.1"
+ "@typescript-eslint/utils" "5.60.1"
+ debug "^4.3.4"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/types@5.60.1":
+ version "5.60.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.60.1.tgz#a17473910f6b8d388ea83c9d7051af89c4eb7561"
+ integrity sha512-zDcDx5fccU8BA0IDZc71bAtYIcG9PowaOwaD8rjYbqwK7dpe/UMQl3inJ4UtUK42nOCT41jTSCwg76E62JpMcg==
+
+"@typescript-eslint/typescript-estree@5.60.1":
+ version "5.60.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.60.1.tgz#8c71824b7165b64d5ebd7aa42968899525959834"
+ integrity sha512-hkX70J9+2M2ZT6fhti5Q2FoU9zb+GeZK2SLP1WZlvUDqdMbEKhexZODD1WodNRyO8eS+4nScvT0dts8IdaBzfw==
+ dependencies:
+ "@typescript-eslint/types" "5.60.1"
+ "@typescript-eslint/visitor-keys" "5.60.1"
+ debug "^4.3.4"
+ globby "^11.1.0"
+ is-glob "^4.0.3"
+ semver "^7.3.7"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/utils@5.60.1", "@typescript-eslint/utils@^5.58.0":
+ version "5.60.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.60.1.tgz#6861ebedbefba1ac85482d2bdef6f2ff1eb65b80"
+ integrity sha512-tiJ7FFdFQOWssFa3gqb94Ilexyw0JVxj6vBzaSpfN/8IhoKkDuSAenUKvsSHw2A/TMpJb26izIszTXaqygkvpQ==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.2.0"
+ "@types/json-schema" "^7.0.9"
+ "@types/semver" "^7.3.12"
+ "@typescript-eslint/scope-manager" "5.60.1"
+ "@typescript-eslint/types" "5.60.1"
+ "@typescript-eslint/typescript-estree" "5.60.1"
+ eslint-scope "^5.1.1"
+ semver "^7.3.7"
+
+"@typescript-eslint/visitor-keys@5.60.1":
+ version "5.60.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.60.1.tgz#19a877358bf96318ec35d90bfe6bd1445cce9434"
+ integrity sha512-xEYIxKcultP6E/RMKqube11pGjXH1DCo60mQoWhVYyKfLkwbIVVjYxmOenNMxILx0TjCujPTjjnTIVzm09TXIw==
+ dependencies:
+ "@typescript-eslint/types" "5.60.1"
+ eslint-visitor-keys "^3.3.0"
+
+"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24"
+ integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==
+ dependencies:
+ "@webassemblyjs/helper-numbers" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+
+"@webassemblyjs/floating-point-hex-parser@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431"
+ integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==
+
+"@webassemblyjs/helper-api-error@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768"
+ integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==
+
+"@webassemblyjs/helper-buffer@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093"
+ integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==
+
+"@webassemblyjs/helper-numbers@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5"
+ integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==
+ dependencies:
+ "@webassemblyjs/floating-point-hex-parser" "1.11.6"
+ "@webassemblyjs/helper-api-error" "1.11.6"
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/helper-wasm-bytecode@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9"
+ integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==
+
+"@webassemblyjs/helper-wasm-section@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577"
+ integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@webassemblyjs/helper-buffer" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/wasm-gen" "1.11.6"
+
+"@webassemblyjs/ieee754@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a"
+ integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==
+ dependencies:
+ "@xtuc/ieee754" "^1.2.0"
+
+"@webassemblyjs/leb128@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7"
+ integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==
+ dependencies:
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/utf8@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a"
+ integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==
+
+"@webassemblyjs/wasm-edit@^1.11.5":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab"
+ integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@webassemblyjs/helper-buffer" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/helper-wasm-section" "1.11.6"
+ "@webassemblyjs/wasm-gen" "1.11.6"
+ "@webassemblyjs/wasm-opt" "1.11.6"
+ "@webassemblyjs/wasm-parser" "1.11.6"
+ "@webassemblyjs/wast-printer" "1.11.6"
+
+"@webassemblyjs/wasm-gen@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268"
+ integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/ieee754" "1.11.6"
+ "@webassemblyjs/leb128" "1.11.6"
+ "@webassemblyjs/utf8" "1.11.6"
+
+"@webassemblyjs/wasm-opt@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2"
+ integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@webassemblyjs/helper-buffer" "1.11.6"
+ "@webassemblyjs/wasm-gen" "1.11.6"
+ "@webassemblyjs/wasm-parser" "1.11.6"
+
+"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1"
+ integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@webassemblyjs/helper-api-error" "1.11.6"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.6"
+ "@webassemblyjs/ieee754" "1.11.6"
+ "@webassemblyjs/leb128" "1.11.6"
+ "@webassemblyjs/utf8" "1.11.6"
+
+"@webassemblyjs/wast-printer@1.11.6":
+ version "1.11.6"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20"
+ integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.6"
+ "@xtuc/long" "4.2.2"
+
+"@xtuc/ieee754@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
+ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
+
+"@xtuc/long@4.2.2":
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
+ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+
+abab@^2.0.3, abab@^2.0.5:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
+ integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
+
+abs-svg-path@^0.1.1, abs-svg-path@~0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/abs-svg-path/-/abs-svg-path-0.1.1.tgz#df601c8e8d2ba10d4a76d625e236a9a39c2723bf"
+ integrity sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==
+
+accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
+ integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
+ dependencies:
+ mime-types "~2.1.34"
+ negotiator "0.6.3"
+
+acorn-globals@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45"
+ integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==
+ dependencies:
+ acorn "^7.1.1"
+ acorn-walk "^7.1.1"
+
+acorn-import-assertions@^1.9.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac"
+ integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==
+
+acorn-jsx@^5.3.2:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
+ integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
+
+acorn-walk@^7.1.1:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
+ integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
+
+acorn@^7.1.1:
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
+ integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
+
+acorn@^8.2.4, acorn@^8.7.1, acorn@^8.8.0, acorn@^8.8.2:
+ version "8.9.0"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.9.0.tgz#78a16e3b2bcc198c10822786fa6679e245db5b59"
+ integrity sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==
+
+address@^1.0.1, address@^1.1.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e"
+ integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==
+
+adjust-sourcemap-loader@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz#fc4a0fd080f7d10471f30a7320f25560ade28c99"
+ integrity sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==
+ dependencies:
+ loader-utils "^2.0.0"
+ regex-parser "^2.2.11"
+
+agent-base@6:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
+ integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
+ dependencies:
+ debug "4"
+
+aggregate-error@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a"
+ integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==
+ dependencies:
+ clean-stack "^2.0.0"
+ indent-string "^4.0.0"
+
+ajv-formats@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
+ integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==
+ dependencies:
+ ajv "^8.0.0"
+
+ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
+ integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
+
+ajv-keywords@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16"
+ integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==
+ dependencies:
+ fast-deep-equal "^3.1.3"
+
+ajv@^6.10.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ 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"
+
+ajv@^8.0.0, ajv@^8.6.0, ajv@^8.9.0:
+ version "8.12.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
+ integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ json-schema-traverse "^1.0.0"
+ require-from-string "^2.0.2"
+ uri-js "^4.2.2"
+
+almost-equal@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/almost-equal/-/almost-equal-1.1.0.tgz#f851c631138757994276aa2efbe8dfa3066cccdd"
+ integrity sha512-0V/PkoculFl5+0Lp47JoxUcO0xSxhIBvm+BxHdD/OgXNmdRpRHCFnKVuUoWyS9EzQP+otSGv0m9Lb4yVkQBn2A==
+
+ansi-colors@^4.1.1:
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.3.tgz#37611340eb2243e70cc604cad35d63270d48781b"
+ integrity sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==
+
+ansi-escapes@^4.2.1, ansi-escapes@^4.3.0, ansi-escapes@^4.3.1:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
+ integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
+ dependencies:
+ type-fest "^0.21.3"
+
+ansi-html-community@^0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41"
+ integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
+
+ansi-regex@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+ integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
+ansi-regex@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
+ integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
+
+ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ dependencies:
+ color-convert "^1.9.0"
+
+ansi-styles@^4.0.0, ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
+ansi-styles@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
+ integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
+
+any-promise@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
+ integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
+
+anymatch@^3.0.3, anymatch@~3.1.2:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+arch@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11"
+ integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==
+
+arg@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
+ integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
+
+argparse@^1.0.7:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+ integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+ dependencies:
+ sprintf-js "~1.0.2"
+
+argparse@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
+aria-query@5.1.3:
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e"
+ integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==
+ dependencies:
+ deep-equal "^2.0.5"
+
+aria-query@^5.0.0, aria-query@^5.1.3:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e"
+ integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==
+ dependencies:
+ dequal "^2.0.3"
+
+array-bounds@^1.0.0, array-bounds@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/array-bounds/-/array-bounds-1.0.1.tgz#da11356b4e18e075a4f0c86e1f179a67b7d7ea31"
+ integrity sha512-8wdW3ZGk6UjMPJx/glyEt0sLzzwAE1bhToPsO1W2pbpR2gULyxe3BjSiuJFheP50T/GgODVPz2fuMUmIywt8cQ==
+
+array-buffer-byte-length@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead"
+ integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==
+ dependencies:
+ call-bind "^1.0.2"
+ is-array-buffer "^3.0.1"
+
+array-find-index@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1"
+ integrity sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==
+
+array-flatten@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+ integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==
+
+array-flatten@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099"
+ integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==
+
+array-includes@^3.1.5, array-includes@^3.1.6:
+ version "3.1.6"
+ resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.6.tgz#9e9e720e194f198266ba9e18c29e6a9b0e4b225f"
+ integrity sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==
+ 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"
+
+array-normalize@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/array-normalize/-/array-normalize-1.1.4.tgz#d75cec57383358af38efdf6a78071aa36ae4174c"
+ integrity sha512-fCp0wKFLjvSPmCn4F5Tiw4M3lpMZoHlCjfcs7nNzuj3vqQQ1/a8cgB9DXcpDSn18c+coLnaW7rqfcYCvKbyJXg==
+ dependencies:
+ array-bounds "^1.0.0"
+
+array-range@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/array-range/-/array-range-1.0.1.tgz#f56e46591843611c6a56f77ef02eda7c50089bfc"
+ integrity sha512-shdaI1zT3CVNL2hnx9c0JMc0ZogGaxDs5e85akgHWKYa0yVbIyp06Ind3dVkTj/uuFrzaHBOyqFzo+VV6aXgtA==
+
+array-rearrange@^2.2.2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/array-rearrange/-/array-rearrange-2.2.2.tgz#fa1a2acf8d02e88dd0c9602aa0e06a79158b2283"
+ integrity sha512-UfobP5N12Qm4Qu4fwLDIi2v6+wZsSf6snYSxAMeKhrh37YGnNWZPRmVEKc/2wfms53TLQnzfpG8wCx2Y/6NG1w==
+
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+array.prototype.flat@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz#ffc6576a7ca3efc2f46a143b9d1dda9b4b3cf5e2"
+ integrity sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ es-shim-unscopables "^1.0.0"
+
+array.prototype.flatmap@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183"
+ integrity sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ es-shim-unscopables "^1.0.0"
+
+array.prototype.reduce@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz#6b20b0daa9d9734dd6bc7ea66b5bbce395471eac"
+ integrity sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+ es-array-method-boxes-properly "^1.0.0"
+ is-string "^1.0.7"
+
+array.prototype.tosorted@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz#ccf44738aa2b5ac56578ffda97c03fd3e23dd532"
+ integrity sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==
+ 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"
+
+asap@~2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+ integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
+
+asn1@~0.2.3:
+ version "0.2.6"
+ resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d"
+ integrity sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==
+ dependencies:
+ safer-buffer "~2.1.0"
+
+assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+ integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==
+
+ast-types-flow@^0.0.7:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
+ integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==
+
+astral-regex@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31"
+ integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
+
+async@^3.2.0, async@^3.2.3:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
+ integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
+at-least-node@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
+ integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
+
+autoprefixer@^10.4.13:
+ version "10.4.14"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.14.tgz#e28d49902f8e759dd25b153264e862df2705f79d"
+ integrity sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==
+ dependencies:
+ browserslist "^4.21.5"
+ caniuse-lite "^1.0.30001464"
+ fraction.js "^4.2.0"
+ normalize-range "^0.1.2"
+ picocolors "^1.0.0"
+ postcss-value-parser "^4.2.0"
+
+available-typed-arrays@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
+ integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
+
+aws-sign2@~0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
+ integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==
+
+aws4@^1.8.0:
+ version "1.12.0"
+ resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3"
+ integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==
+
+axe-core@^4.6.2:
+ version "4.7.2"
+ resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0"
+ integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==
+
+axios@^0.27.2:
+ version "0.27.2"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-0.27.2.tgz#207658cc8621606e586c85db4b41a750e756d972"
+ integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==
+ dependencies:
+ follow-redirects "^1.14.9"
+ form-data "^4.0.0"
+
+axobject-query@^3.1.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a"
+ integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==
+ dependencies:
+ dequal "^2.0.3"
+
+babel-jest@^27.4.2, babel-jest@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444"
+ integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==
+ dependencies:
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/babel__core" "^7.1.14"
+ babel-plugin-istanbul "^6.1.1"
+ babel-preset-jest "^27.5.1"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ slash "^3.0.0"
+
+babel-loader@^8.2.3:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8"
+ integrity sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q==
+ dependencies:
+ find-cache-dir "^3.3.1"
+ loader-utils "^2.0.0"
+ make-dir "^3.1.0"
+ schema-utils "^2.6.5"
+
+babel-plugin-istanbul@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73"
+ integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@istanbuljs/load-nyc-config" "^1.0.0"
+ "@istanbuljs/schema" "^0.1.2"
+ istanbul-lib-instrument "^5.0.4"
+ test-exclude "^6.0.0"
+
+babel-plugin-jest-hoist@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e"
+ integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==
+ dependencies:
+ "@babel/template" "^7.3.3"
+ "@babel/types" "^7.3.3"
+ "@types/babel__core" "^7.0.0"
+ "@types/babel__traverse" "^7.0.6"
+
+babel-plugin-macros@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1"
+ integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+ cosmiconfig "^7.0.0"
+ resolve "^1.19.0"
+
+babel-plugin-named-asset-import@^0.3.8:
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz#6b7fa43c59229685368683c28bc9734f24524cc2"
+ integrity sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==
+
+babel-plugin-polyfill-corejs2@^0.4.3:
+ version "0.4.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.3.tgz#75044d90ba5043a5fb559ac98496f62f3eb668fd"
+ integrity sha512-bM3gHc337Dta490gg+/AseNB9L4YLHxq1nGKZZSHbhXv4aTYU2MD2cjza1Ru4S6975YLTaL1K8uJf6ukJhhmtw==
+ dependencies:
+ "@babel/compat-data" "^7.17.7"
+ "@babel/helper-define-polyfill-provider" "^0.4.0"
+ semver "^6.1.1"
+
+babel-plugin-polyfill-corejs3@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.8.1.tgz#39248263c38191f0d226f928d666e6db1b4b3a8a"
+ integrity sha512-ikFrZITKg1xH6pLND8zT14UPgjKHiGLqex7rGEZCH2EvhsneJaJPemmpQaIZV5AL03II+lXylw3UmddDK8RU5Q==
+ dependencies:
+ "@babel/helper-define-polyfill-provider" "^0.4.0"
+ core-js-compat "^3.30.1"
+
+babel-plugin-polyfill-regenerator@^0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.0.tgz#e7344d88d9ef18a3c47ded99362ae4a757609380"
+ integrity sha512-hDJtKjMLVa7Z+LwnTCxoDLQj6wdc+B8dun7ayF2fYieI6OzfuvcLMB32ihJZ4UhCBwNYGl5bg/x/P9cMdnkc2g==
+ dependencies:
+ "@babel/helper-define-polyfill-provider" "^0.4.0"
+
+babel-plugin-transform-react-remove-prop-types@^0.4.24:
+ version "0.4.24"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a"
+ integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==
+
+babel-preset-current-node-syntax@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b"
+ integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==
+ dependencies:
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+ "@babel/plugin-syntax-bigint" "^7.8.3"
+ "@babel/plugin-syntax-class-properties" "^7.8.3"
+ "@babel/plugin-syntax-import-meta" "^7.8.3"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+ "@babel/plugin-syntax-numeric-separator" "^7.8.3"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+ "@babel/plugin-syntax-top-level-await" "^7.8.3"
+
+babel-preset-jest@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81"
+ integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==
+ dependencies:
+ babel-plugin-jest-hoist "^27.5.1"
+ babel-preset-current-node-syntax "^1.0.0"
+
+babel-preset-react-app@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz#ed6005a20a24f2c88521809fa9aea99903751584"
+ integrity sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==
+ dependencies:
+ "@babel/core" "^7.16.0"
+ "@babel/plugin-proposal-class-properties" "^7.16.0"
+ "@babel/plugin-proposal-decorators" "^7.16.4"
+ "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.0"
+ "@babel/plugin-proposal-numeric-separator" "^7.16.0"
+ "@babel/plugin-proposal-optional-chaining" "^7.16.0"
+ "@babel/plugin-proposal-private-methods" "^7.16.0"
+ "@babel/plugin-transform-flow-strip-types" "^7.16.0"
+ "@babel/plugin-transform-react-display-name" "^7.16.0"
+ "@babel/plugin-transform-runtime" "^7.16.4"
+ "@babel/preset-env" "^7.16.4"
+ "@babel/preset-react" "^7.16.0"
+ "@babel/preset-typescript" "^7.16.0"
+ "@babel/runtime" "^7.16.3"
+ babel-plugin-macros "^3.1.0"
+ babel-plugin-transform-react-remove-prop-types "^0.4.24"
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+base64-js@^1.3.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
+ integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
+
+batch@0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
+ integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==
+
+bcrypt-pbkdf@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
+ integrity sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==
+ dependencies:
+ tweetnacl "^0.14.3"
+
+bfj@^7.0.2:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.0.2.tgz#1988ce76f3add9ac2913fd8ba47aad9e651bfbb2"
+ integrity sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==
+ dependencies:
+ bluebird "^3.5.5"
+ check-types "^11.1.1"
+ hoopy "^0.1.4"
+ tryer "^1.0.1"
+
+big.js@^5.2.2:
+ version "5.2.2"
+ resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
+ integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
+
+binary-extensions@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+ integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
+
+binary-search-bounds@^2.0.4:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/binary-search-bounds/-/binary-search-bounds-2.0.5.tgz#125e5bd399882f71e6660d4bf1186384e989fba7"
+ integrity sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==
+
+bit-twiddle@^1.0.0, bit-twiddle@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/bit-twiddle/-/bit-twiddle-1.0.2.tgz#0c6c1fabe2b23d17173d9a61b7b7093eb9e1769e"
+ integrity sha512-B9UhK0DKFZhoTFcfvAzhqsjStvGJp9vYWf3+6SNTtdSQnvIgfkHbgHrg/e4+TH71N2GDu8tpmCVoyfrL1d7ntA==
+
+bitmap-sdf@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/bitmap-sdf/-/bitmap-sdf-1.0.4.tgz#e87b8b1d84ee846567cfbb29d60eedd34bca5b6f"
+ integrity sha512-1G3U4n5JE6RAiALMxu0p1XmeZkTeCwGKykzsLTCqVzfSDaN6S7fKnkIkfejogz+iwqBWc0UYAIKnKHNN7pSfDg==
+
+bl@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/bl/-/bl-2.2.1.tgz#8c11a7b730655c5d56898cdc871224f40fd901d5"
+ integrity sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==
+ dependencies:
+ readable-stream "^2.3.5"
+ safe-buffer "^5.1.1"
+
+blob-util@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb"
+ integrity sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==
+
+bluebird@3.7.2, bluebird@^3.5.5, bluebird@^3.7.2:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
+ integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
+
+body-parser@1.20.1:
+ version "1.20.1"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668"
+ integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==
+ dependencies:
+ bytes "3.1.2"
+ content-type "~1.0.4"
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ http-errors "2.0.0"
+ iconv-lite "0.4.24"
+ on-finished "2.4.1"
+ qs "6.11.0"
+ raw-body "2.5.1"
+ type-is "~1.6.18"
+ unpipe "1.0.0"
+
+bonjour-service@^1.0.11:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.1.1.tgz#960948fa0e0153f5d26743ab15baf8e33752c135"
+ integrity sha512-Z/5lQRMOG9k7W+FkeGTNjh7htqn/2LMnfOvBZ8pynNZCM9MwkQkI3zeI4oz09uWdcgmgHugVvBqxGg4VQJ5PCg==
+ dependencies:
+ array-flatten "^2.1.2"
+ dns-equal "^1.0.0"
+ fast-deep-equal "^3.1.3"
+ multicast-dns "^7.2.5"
+
+boolbase@^1.0.0, boolbase@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+ integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+brace-expansion@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
+ integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
+ dependencies:
+ balanced-match "^1.0.0"
+
+braces@^3.0.2, braces@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+browser-process-hrtime@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
+ integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
+
+browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.18.1, browserslist@^4.21.3, browserslist@^4.21.4, browserslist@^4.21.5:
+ version "4.21.9"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.9.tgz#e11bdd3c313d7e2a9e87e8b4b0c7872b13897635"
+ integrity sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==
+ dependencies:
+ caniuse-lite "^1.0.30001503"
+ electron-to-chromium "^1.4.431"
+ node-releases "^2.0.12"
+ update-browserslist-db "^1.0.11"
+
+bser@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
+ integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==
+ dependencies:
+ node-int64 "^0.4.0"
+
+buffer-crc32@~0.2.3:
+ version "0.2.13"
+ resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
+ integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
+
+buffer-from@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
+ integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
+
+buffer@^5.6.0:
+ version "5.7.1"
+ resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
+ integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
+ dependencies:
+ base64-js "^1.3.1"
+ ieee754 "^1.1.13"
+
+builtin-modules@^3.1.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
+ integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==
+
+bytes@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+ integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==
+
+bytes@3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
+ integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
+
+cachedir@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/cachedir/-/cachedir-2.3.0.tgz#0c75892a052198f0b21c7c1804d8331edfcae0e8"
+ integrity sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==
+
+call-bind@^1.0.0, call-bind@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
+ integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
+ dependencies:
+ function-bind "^1.1.1"
+ get-intrinsic "^1.0.2"
+
+callsites@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+ integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+camel-case@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a"
+ integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==
+ dependencies:
+ pascal-case "^3.1.2"
+ tslib "^2.0.3"
+
+camelcase-css@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
+ integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
+
+camelcase@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+camelcase@^6.2.0, camelcase@^6.2.1:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
+ integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
+
+caniuse-api@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
+ integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==
+ dependencies:
+ browserslist "^4.0.0"
+ caniuse-lite "^1.0.0"
+ lodash.memoize "^4.1.2"
+ lodash.uniq "^4.5.0"
+
+caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001464, caniuse-lite@^1.0.30001503:
+ version "1.0.30001508"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001508.tgz#4461bbc895c692a96da399639cc1e146e7302a33"
+ integrity sha512-sdQZOJdmt3GJs1UMNpCCCyeuS2IEGLXnHyAo9yIO5JJDjbjoVRij4M1qep6P6gFpptD1PqIYgzM+gwJbOi92mw==
+
+canvas-fit@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/canvas-fit/-/canvas-fit-1.5.0.tgz#ae13be66ade42f5be0e487e345fce30a5e5b5e5f"
+ integrity sha512-onIcjRpz69/Hx5bB5HGbYKUF2uC6QT6Gp+pfpGm3A7mPfcluSLV5v4Zu+oflDUwLdUw0rLIBhUbi0v8hM4FJQQ==
+ dependencies:
+ element-size "^1.1.1"
+
+case-sensitive-paths-webpack-plugin@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4"
+ integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==
+
+caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
+ integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==
+
+chalk@^2.0.0, chalk@^2.4.1:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+chalk@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
+ integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+char-regex@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
+ integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==
+
+char-regex@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.1.tgz#6dafdb25f9d3349914079f010ba8d0e6ff9cd01e"
+ integrity sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==
+
+check-more-types@2.24.0, check-more-types@^2.24.0:
+ version "2.24.0"
+ resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600"
+ integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==
+
+check-types@^11.1.1:
+ version "11.2.2"
+ resolved "https://registry.yarnpkg.com/check-types/-/check-types-11.2.2.tgz#7afc0b6a860d686885062f2dba888ba5710335b4"
+ integrity sha512-HBiYvXvn9Z70Z88XKjz3AEKd4HJhBXsa3j7xFnITAzoS8+q6eIGi8qDB8FKPBAjtuxjI/zFpwuiCb8oDtKOYrA==
+
+chokidar@^3.4.2, chokidar@^3.5.3:
+ version "3.5.3"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
+ integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
+ dependencies:
+ anymatch "~3.1.2"
+ braces "~3.0.2"
+ glob-parent "~5.1.2"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.6.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+chrome-trace-event@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
+ integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
+
+ci-info@^3.2.0:
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.8.0.tgz#81408265a5380c929f0bc665d62256628ce9ef91"
+ integrity sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==
+
+cjs-module-lexer@^1.0.0:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107"
+ integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==
+
+clamp@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/clamp/-/clamp-1.0.1.tgz#66a0e64011816e37196828fdc8c8c147312c8634"
+ integrity sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA==
+
+clean-css@^5.2.2:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.2.tgz#70ecc7d4d4114921f5d298349ff86a31a9975224"
+ integrity sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==
+ dependencies:
+ source-map "~0.6.0"
+
+clean-stack@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
+ integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
+
+cli-cursor@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
+ integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
+ dependencies:
+ restore-cursor "^3.1.0"
+
+cli-table3@~0.6.1:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2"
+ integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==
+ dependencies:
+ string-width "^4.2.0"
+ optionalDependencies:
+ "@colors/colors" "1.5.0"
+
+cli-truncate@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7"
+ integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==
+ dependencies:
+ slice-ansi "^3.0.0"
+ string-width "^4.2.0"
+
+cliui@^7.0.2:
+ version "7.0.4"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
+ integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.0"
+ wrap-ansi "^7.0.0"
+
+clsx@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
+ integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
+
+co@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+ integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==
+
+coa@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3"
+ integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==
+ dependencies:
+ "@types/q" "^1.5.1"
+ chalk "^2.4.1"
+ q "^1.1.2"
+
+collect-v8-coverage@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
+ integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==
+
+color-alpha@1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/color-alpha/-/color-alpha-1.0.4.tgz#c141dc926e95fc3db647d0e14e5bc3651c29e040"
+ integrity sha512-lr8/t5NPozTSqli+duAN+x+no/2WaKTeWvxhHGN+aXT6AJ8vPlzLa7UriyjWak0pSC2jHol9JgjBYnnHsGha9A==
+ dependencies:
+ color-parse "^1.3.8"
+
+color-alpha@^1.0.4:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-alpha/-/color-alpha-1.1.3.tgz#71250189e9f02bba8261a94d5e7d5f5606d1749a"
+ integrity sha512-krPYBO1RSO5LH4AGb/b6z70O1Ip2o0F0+0cVFN5FN99jfQtZFT08rQyg+9oOBNJYAn3SRwJIFC8jUEOKz7PisA==
+ dependencies:
+ color-parse "^1.4.1"
+
+color-convert@^1.9.0:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+ dependencies:
+ color-name "1.1.3"
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-id@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/color-id/-/color-id-1.1.0.tgz#5e9159b99a73ac98f74820cb98a15fde3d7e034c"
+ integrity sha512-2iRtAn6dC/6/G7bBIo0uupVrIne1NsQJvJxZOBCzQOfk7jRq97feaDZ3RdzuHakRXXnHGNwglto3pqtRx1sX0g==
+ dependencies:
+ clamp "^1.0.1"
+
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+ integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
+
+color-name@^1.0.0, color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+color-normalize@1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/color-normalize/-/color-normalize-1.5.0.tgz#ee610af9acb15daf73e77a945a847b18e40772da"
+ integrity sha512-rUT/HDXMr6RFffrR53oX3HGWkDOP9goSAQGBkUaAYKjOE2JxozccdGyufageWDlInRAjm/jYPrf/Y38oa+7obw==
+ dependencies:
+ clamp "^1.0.1"
+ color-rgba "^2.1.1"
+ dtype "^2.0.0"
+
+color-normalize@^1.5.0:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/color-normalize/-/color-normalize-1.5.2.tgz#d6c8beb02966849548f91a6ac0274c6f19924509"
+ integrity sha512-yYMIoyFJmUoKbCK6sBShljBWfkt8DXVfaZJn9/zvRJkF9eQJDbZhcYC6LdOVy40p4tfVwYYb9cXl8oqpu7pzBw==
+ dependencies:
+ color-rgba "^2.2.0"
+ dtype "^2.0.0"
+
+color-parse@1.3.8:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/color-parse/-/color-parse-1.3.8.tgz#eaf54cd385cb34c0681f18c218aca38478082fa3"
+ integrity sha512-1Y79qFv0n1xair3lNMTNeoFvmc3nirMVBij24zbs1f13+7fPpQClMg5b4AuKXLt3szj7BRlHMCXHplkce6XlmA==
+ dependencies:
+ color-name "^1.0.0"
+ defined "^1.0.0"
+ is-plain-obj "^1.1.0"
+
+color-parse@^1.3.8, color-parse@^1.4.1, color-parse@^1.4.2:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/color-parse/-/color-parse-1.4.2.tgz#78651f5d34df1a57f997643d86f7f87268ad4eb5"
+ integrity sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA==
+ dependencies:
+ color-name "^1.0.0"
+
+color-rgba@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/color-rgba/-/color-rgba-2.1.1.tgz#4633b83817c7406c90b3d7bf4d1acfa48dde5c83"
+ integrity sha512-VaX97wsqrMwLSOR6H7rU1Doa2zyVdmShabKrPEIFywLlHoibgD3QW9Dw6fSqM4+H/LfjprDNAUUW31qEQcGzNw==
+ dependencies:
+ clamp "^1.0.1"
+ color-parse "^1.3.8"
+ color-space "^1.14.6"
+
+color-rgba@^2.1.1, color-rgba@^2.2.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/color-rgba/-/color-rgba-2.4.0.tgz#ae85819c530262c29fc2da129fc7c8f9efc57015"
+ integrity sha512-Nti4qbzr/z2LbUWySr7H9dk3Rl7gZt7ihHAxlgT4Ho90EXWkjtkL1avTleu9yeGuqrt/chxTB6GKK8nZZ6V0+Q==
+ dependencies:
+ color-parse "^1.4.2"
+ color-space "^2.0.0"
+
+color-space@^1.14.6:
+ version "1.16.0"
+ resolved "https://registry.yarnpkg.com/color-space/-/color-space-1.16.0.tgz#611781bca41cd8582a1466fd9e28a7d3d89772a2"
+ integrity sha512-A6WMiFzunQ8KEPFmj02OnnoUnqhmSaHaZ/0LVFcPTdlvm8+3aMJ5x1HRHy3bDHPkovkf4sS0f4wsVvwk71fKkg==
+ dependencies:
+ hsluv "^0.0.3"
+ mumath "^3.3.4"
+
+color-space@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-space/-/color-space-2.0.1.tgz#da39871175baf4a5785ba519397df04b8d67e0fa"
+ integrity sha512-nKqUYlo0vZATVOFHY810BSYjmCARrG7e5R3UE3CQlyjJTvv5kSSmPG1kzm/oDyyqjehM+lW1RnEt9It9GNa5JA==
+
+colord@^2.9.1:
+ version "2.9.3"
+ resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43"
+ integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==
+
+colorette@^2.0.10, colorette@^2.0.16:
+ version "2.0.20"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
+ integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
+
+combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+commander@2, commander@^2.15.1, commander@^2.20.0:
+ version "2.20.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+commander@^4.0.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
+ integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
+
+commander@^6.2.1:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
+ integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
+
+commander@^7.2.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
+ integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
+
+commander@^8.3.0:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
+ integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
+
+common-path-prefix@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0"
+ integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==
+
+common-tags@^1.8.0:
+ version "1.8.2"
+ resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6"
+ integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==
+
+commondir@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+ integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
+
+compressible@~2.0.16:
+ version "2.0.18"
+ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
+ integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
+ dependencies:
+ mime-db ">= 1.43.0 < 2"
+
+compression@^1.7.4:
+ version "1.7.4"
+ resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
+ integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
+ dependencies:
+ accepts "~1.3.5"
+ bytes "3.0.0"
+ compressible "~2.0.16"
+ debug "2.6.9"
+ on-headers "~1.0.2"
+ safe-buffer "5.1.2"
+ vary "~1.1.2"
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+concat-stream@^1.5.2:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34"
+ integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==
+ dependencies:
+ buffer-from "^1.0.0"
+ inherits "^2.0.3"
+ readable-stream "^2.2.2"
+ typedarray "^0.0.6"
+
+confusing-browser-globals@^1.0.11:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81"
+ integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==
+
+connect-history-api-fallback@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8"
+ integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==
+
+content-disposition@0.5.4:
+ version "0.5.4"
+ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
+ integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
+ dependencies:
+ safe-buffer "5.2.1"
+
+content-type@~1.0.4:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918"
+ integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==
+
+convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f"
+ integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
+
+cookie-signature@1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+ integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
+
+cookie@0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
+ integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
+
+core-js-compat@^3.30.1, core-js-compat@^3.30.2:
+ version "3.31.0"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.31.0.tgz#4030847c0766cc0e803dcdfb30055d7ef2064bf1"
+ integrity sha512-hM7YCu1cU6Opx7MXNu0NuumM0ezNeAeRKadixyiQELWY3vT3De9S4J5ZBMraWV2vZnrE1Cirl0GtFtDtMUXzPw==
+ dependencies:
+ browserslist "^4.21.5"
+
+core-js-pure@^3.23.3:
+ version "3.31.0"
+ resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.31.0.tgz#052fd9e82fbaaf86457f5db1fadcd06f15966ff2"
+ integrity sha512-/AnE9Y4OsJZicCzIe97JP5XoPKQJfTuEG43aEVLFJGOJpyqELod+pE6LEl63DfG1Mp8wX97LDaDpy1GmLEUxlg==
+
+core-js@^3.19.2:
+ version "3.31.0"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.31.0.tgz#4471dd33e366c79d8c0977ed2d940821719db344"
+ integrity sha512-NIp2TQSGfR6ba5aalZD+ZQ1fSxGhDo/s1w0nx3RYzf2pnJxt7YynxFlFScP6eV7+GZsKO95NSjGxyJsU3DZgeQ==
+
+core-util-is@1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
+ integrity sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==
+
+core-util-is@~1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
+ integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
+
+cosmiconfig@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982"
+ integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==
+ dependencies:
+ "@types/parse-json" "^4.0.0"
+ import-fresh "^3.1.0"
+ parse-json "^5.0.0"
+ path-type "^4.0.0"
+ yaml "^1.7.2"
+
+cosmiconfig@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6"
+ integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==
+ dependencies:
+ "@types/parse-json" "^4.0.0"
+ import-fresh "^3.2.1"
+ parse-json "^5.0.0"
+ path-type "^4.0.0"
+ yaml "^1.10.0"
+
+country-regex@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/country-regex/-/country-regex-1.1.0.tgz#51c333dcdf12927b7e5eeb9c10ac8112a6120896"
+ integrity sha512-iSPlClZP8vX7MC3/u6s3lrDuoQyhQukh5LyABJ3hvfzbQ3Yyayd4fp04zjLnfi267B/B2FkumcWWgrbban7sSA==
+
+cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+ integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+crypto-random-string@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
+ integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
+
+css-blank-pseudo@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz#36523b01c12a25d812df343a32c322d2a2324561"
+ integrity sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+
+css-declaration-sorter@^6.3.1:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.4.0.tgz#630618adc21724484b3e9505bce812def44000ad"
+ integrity sha512-jDfsatwWMWN0MODAFuHszfjphEXfNw9JUAhmY4pLu3TyTU+ohUpsbVtbU+1MZn4a47D9kqh03i4eyOm+74+zew==
+
+css-font-size-keywords@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/css-font-size-keywords/-/css-font-size-keywords-1.0.0.tgz#854875ace9aca6a8d2ee0d345a44aae9bb6db6cb"
+ integrity sha512-Q+svMDbMlelgCfH/RVDKtTDaf5021O486ZThQPIpahnIjUkMUslC+WuOQSWTgGSrNCH08Y7tYNEmmy0hkfMI8Q==
+
+css-font-stretch-keywords@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/css-font-stretch-keywords/-/css-font-stretch-keywords-1.0.1.tgz#50cee9b9ba031fb5c952d4723139f1e107b54b10"
+ integrity sha512-KmugPO2BNqoyp9zmBIUGwt58UQSfyk1X5DbOlkb2pckDXFSAfjsD5wenb88fNrD6fvS+vu90a/tsPpb9vb0SLg==
+
+css-font-style-keywords@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/css-font-style-keywords/-/css-font-style-keywords-1.0.1.tgz#5c3532813f63b4a1de954d13cea86ab4333409e4"
+ integrity sha512-0Fn0aTpcDktnR1RzaBYorIxQily85M2KXRpzmxQPgh8pxUN9Fcn00I8u9I3grNr1QXVgCl9T5Imx0ZwKU973Vg==
+
+css-font-weight-keywords@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/css-font-weight-keywords/-/css-font-weight-keywords-1.0.0.tgz#9bc04671ac85bc724b574ef5d3ac96b0d604fd97"
+ integrity sha512-5So8/NH+oDD+EzsnF4iaG4ZFHQ3vaViePkL1ZbZ5iC/KrsCY+WHq/lvOgrtmuOQ9pBBZ1ADGpaf+A4lj1Z9eYA==
+
+css-font@^1.0.0, css-font@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/css-font/-/css-font-1.2.0.tgz#e73cbdc11fd87c8e6c928ad7098a9771c8c2b6e3"
+ integrity sha512-V4U4Wps4dPDACJ4WpgofJ2RT5Yqwe1lEH6wlOOaIxMi0gTjdIijsc5FmxQlZ7ZZyKQkkutqqvULOp07l9c7ssA==
+ dependencies:
+ css-font-size-keywords "^1.0.0"
+ css-font-stretch-keywords "^1.0.1"
+ css-font-style-keywords "^1.0.1"
+ css-font-weight-keywords "^1.0.0"
+ css-global-keywords "^1.0.1"
+ css-system-font-keywords "^1.0.0"
+ pick-by-alias "^1.2.0"
+ string-split-by "^1.0.0"
+ unquote "^1.1.0"
+
+css-global-keywords@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/css-global-keywords/-/css-global-keywords-1.0.1.tgz#72a9aea72796d019b1d2a3252de4e5aaa37e4a69"
+ integrity sha512-X1xgQhkZ9n94WDwntqst5D/FKkmiU0GlJSFZSV3kLvyJ1WC5VeyoXDOuleUD+SIuH9C7W05is++0Woh0CGfKjQ==
+
+css-has-pseudo@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz#57f6be91ca242d5c9020ee3e51bbb5b89fc7af73"
+ integrity sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+
+css-loader@^6.5.1:
+ version "6.8.1"
+ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.8.1.tgz#0f8f52699f60f5e679eab4ec0fcd68b8e8a50a88"
+ integrity sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==
+ dependencies:
+ icss-utils "^5.1.0"
+ postcss "^8.4.21"
+ postcss-modules-extract-imports "^3.0.0"
+ postcss-modules-local-by-default "^4.0.3"
+ postcss-modules-scope "^3.0.0"
+ postcss-modules-values "^4.0.0"
+ postcss-value-parser "^4.2.0"
+ semver "^7.3.8"
+
+css-minimizer-webpack-plugin@^3.2.0:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f"
+ integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==
+ dependencies:
+ cssnano "^5.0.6"
+ jest-worker "^27.0.2"
+ postcss "^8.3.5"
+ schema-utils "^4.0.0"
+ serialize-javascript "^6.0.0"
+ source-map "^0.6.1"
+
+css-prefers-color-scheme@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz#ca8a22e5992c10a5b9d315155e7caee625903349"
+ integrity sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==
+
+css-select-base-adapter@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7"
+ integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==
+
+css-select@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef"
+ integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==
+ dependencies:
+ boolbase "^1.0.0"
+ css-what "^3.2.1"
+ domutils "^1.7.0"
+ nth-check "^1.0.2"
+
+css-select@^4.1.3:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b"
+ integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==
+ dependencies:
+ boolbase "^1.0.0"
+ css-what "^6.0.1"
+ domhandler "^4.3.1"
+ domutils "^2.8.0"
+ nth-check "^2.0.1"
+
+css-system-font-keywords@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/css-system-font-keywords/-/css-system-font-keywords-1.0.0.tgz#85c6f086aba4eb32c571a3086affc434b84823ed"
+ integrity sha512-1umTtVd/fXS25ftfjB71eASCrYhilmEsvDEI6wG/QplnmlfmVM5HkZ/ZX46DT5K3eblFPgLUHt5BRCb0YXkSFA==
+
+css-tree@1.0.0-alpha.37:
+ version "1.0.0-alpha.37"
+ resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22"
+ integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==
+ dependencies:
+ mdn-data "2.0.4"
+ source-map "^0.6.1"
+
+css-tree@^1.1.2, css-tree@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d"
+ integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==
+ dependencies:
+ mdn-data "2.0.14"
+ source-map "^0.6.1"
+
+css-what@^3.2.1:
+ version "3.4.2"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4"
+ integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==
+
+css-what@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
+ integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
+
+css.escape@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
+ integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==
+
+csscolorparser@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/csscolorparser/-/csscolorparser-1.0.3.tgz#b34f391eea4da8f3e98231e2ccd8df9c041f171b"
+ integrity sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==
+
+cssdb@^7.1.0:
+ version "7.6.0"
+ resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-7.6.0.tgz#beac8f7a5f676db62d3c33da517ef4c9eb008f8b"
+ integrity sha512-Nna7rph8V0jC6+JBY4Vk4ndErUmfJfV6NJCaZdurL0omggabiy+QB2HCQtu5c/ACLZ0I7REv7A4QyPIoYzZx0w==
+
+cssesc@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
+ integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+
+cssnano-preset-default@^5.2.14:
+ version "5.2.14"
+ resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz#309def4f7b7e16d71ab2438052093330d9ab45d8"
+ integrity sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==
+ dependencies:
+ css-declaration-sorter "^6.3.1"
+ cssnano-utils "^3.1.0"
+ postcss-calc "^8.2.3"
+ postcss-colormin "^5.3.1"
+ postcss-convert-values "^5.1.3"
+ postcss-discard-comments "^5.1.2"
+ postcss-discard-duplicates "^5.1.0"
+ postcss-discard-empty "^5.1.1"
+ postcss-discard-overridden "^5.1.0"
+ postcss-merge-longhand "^5.1.7"
+ postcss-merge-rules "^5.1.4"
+ postcss-minify-font-values "^5.1.0"
+ postcss-minify-gradients "^5.1.1"
+ postcss-minify-params "^5.1.4"
+ postcss-minify-selectors "^5.2.1"
+ postcss-normalize-charset "^5.1.0"
+ postcss-normalize-display-values "^5.1.0"
+ postcss-normalize-positions "^5.1.1"
+ postcss-normalize-repeat-style "^5.1.1"
+ postcss-normalize-string "^5.1.0"
+ postcss-normalize-timing-functions "^5.1.0"
+ postcss-normalize-unicode "^5.1.1"
+ postcss-normalize-url "^5.1.0"
+ postcss-normalize-whitespace "^5.1.1"
+ postcss-ordered-values "^5.1.3"
+ postcss-reduce-initial "^5.1.2"
+ postcss-reduce-transforms "^5.1.0"
+ postcss-svgo "^5.1.0"
+ postcss-unique-selectors "^5.1.1"
+
+cssnano-utils@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861"
+ integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==
+
+cssnano@^5.0.6:
+ version "5.1.15"
+ resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.15.tgz#ded66b5480d5127fcb44dac12ea5a983755136bf"
+ integrity sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==
+ dependencies:
+ cssnano-preset-default "^5.2.14"
+ lilconfig "^2.0.3"
+ yaml "^1.10.2"
+
+csso@^4.0.2, csso@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529"
+ integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==
+ dependencies:
+ css-tree "^1.1.2"
+
+cssom@^0.4.4:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
+ integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==
+
+cssom@~0.3.6:
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
+ integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
+
+cssstyle@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852"
+ integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==
+ dependencies:
+ cssom "~0.3.6"
+
+csstype@^3.0.2, csstype@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
+ integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==
+
+cypress@^12.16.0:
+ version "12.16.0"
+ resolved "https://registry.yarnpkg.com/cypress/-/cypress-12.16.0.tgz#d0dcd0725a96497f4c60cf54742242259847924c"
+ integrity sha512-mwv1YNe48hm0LVaPgofEhGCtLwNIQEjmj2dJXnAkY1b4n/NE9OtgPph4TyS+tOtYp5CKtRmDvBzWseUXQTjbTg==
+ dependencies:
+ "@cypress/request" "^2.88.10"
+ "@cypress/xvfb" "^1.2.4"
+ "@types/node" "^14.14.31"
+ "@types/sinonjs__fake-timers" "8.1.1"
+ "@types/sizzle" "^2.3.2"
+ arch "^2.2.0"
+ blob-util "^2.0.2"
+ bluebird "^3.7.2"
+ buffer "^5.6.0"
+ cachedir "^2.3.0"
+ chalk "^4.1.0"
+ check-more-types "^2.24.0"
+ cli-cursor "^3.1.0"
+ cli-table3 "~0.6.1"
+ commander "^6.2.1"
+ common-tags "^1.8.0"
+ dayjs "^1.10.4"
+ debug "^4.3.4"
+ enquirer "^2.3.6"
+ eventemitter2 "6.4.7"
+ execa "4.1.0"
+ executable "^4.1.1"
+ extract-zip "2.0.1"
+ figures "^3.2.0"
+ fs-extra "^9.1.0"
+ getos "^3.2.1"
+ is-ci "^3.0.0"
+ is-installed-globally "~0.4.0"
+ lazy-ass "^1.6.0"
+ listr2 "^3.8.3"
+ lodash "^4.17.21"
+ log-symbols "^4.0.0"
+ minimist "^1.2.8"
+ ospath "^1.2.2"
+ pretty-bytes "^5.6.0"
+ proxy-from-env "1.0.0"
+ request-progress "^3.0.0"
+ semver "^7.3.2"
+ supports-color "^8.1.1"
+ tmp "~0.2.1"
+ untildify "^4.0.0"
+ yauzl "^2.10.0"
+
+d3-array@1, d3-array@^1.2.1:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.4.tgz#635ce4d5eea759f6f605863dbcfc30edc737f71f"
+ integrity sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==
+
+d3-collection@1, d3-collection@^1.0.4:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/d3-collection/-/d3-collection-1.0.7.tgz#349bd2aa9977db071091c13144d5e4f16b5b310e"
+ integrity sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==
+
+"d3-color@1 - 3":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2"
+ integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==
+
+d3-dispatch@1:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.6.tgz#00d37bcee4dd8cd97729dd893a0ac29caaba5d58"
+ integrity sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==
+
+d3-force@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-1.2.1.tgz#fd29a5d1ff181c9e7f0669e4bd72bdb0e914ec0b"
+ integrity sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==
+ dependencies:
+ d3-collection "1"
+ d3-dispatch "1"
+ d3-quadtree "1"
+ d3-timer "1"
+
+d3-format@^1.4.5:
+ version "1.4.5"
+ resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.4.5.tgz#374f2ba1320e3717eb74a9356c67daee17a7edb4"
+ integrity sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==
+
+d3-geo-projection@^2.9.0:
+ version "2.9.0"
+ resolved "https://registry.yarnpkg.com/d3-geo-projection/-/d3-geo-projection-2.9.0.tgz#826db62f748e8ecd67cd00aced4c26a236ec030c"
+ integrity sha512-ZULvK/zBn87of5rWAfFMc9mJOipeSo57O+BBitsKIXmU4rTVAnX1kSsJkE0R+TxY8pGNoM1nbyRRE7GYHhdOEQ==
+ dependencies:
+ commander "2"
+ d3-array "1"
+ d3-geo "^1.12.0"
+ resolve "^1.1.10"
+
+d3-geo@^1.12.0, d3-geo@^1.12.1:
+ version "1.12.1"
+ resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.12.1.tgz#7fc2ab7414b72e59fbcbd603e80d9adc029b035f"
+ integrity sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==
+ dependencies:
+ d3-array "1"
+
+d3-hierarchy@^1.1.9:
+ version "1.1.9"
+ resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz#2f6bee24caaea43f8dc37545fa01628559647a83"
+ integrity sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==
+
+d3-interpolate@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
+ integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
+ dependencies:
+ d3-color "1 - 3"
+
+d3-path@1:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf"
+ integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==
+
+d3-quadtree@1:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.7.tgz#ca8b84df7bb53763fe3c2f24bd435137f4e53135"
+ integrity sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==
+
+d3-shape@^1.2.0:
+ version "1.3.7"
+ resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7"
+ integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==
+ dependencies:
+ d3-path "1"
+
+d3-time-format@^2.2.3:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-2.3.0.tgz#107bdc028667788a8924ba040faf1fbccd5a7850"
+ integrity sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==
+ dependencies:
+ d3-time "1"
+
+d3-time@1, d3-time@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-1.1.0.tgz#b1e19d307dae9c900b7e5b25ffc5dcc249a8a0f1"
+ integrity sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==
+
+d3-timer@1:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.10.tgz#dfe76b8a91748831b13b6d9c793ffbd508dd9de5"
+ integrity sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==
+
+d@1, d@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a"
+ integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==
+ dependencies:
+ es5-ext "^0.10.50"
+ type "^1.0.1"
+
+damerau-levenshtein@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
+ integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
+
+dashdash@^1.12.0:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
+ integrity sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==
+ dependencies:
+ assert-plus "^1.0.0"
+
+data-urls@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
+ integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==
+ dependencies:
+ abab "^2.0.3"
+ whatwg-mimetype "^2.3.0"
+ whatwg-url "^8.0.0"
+
+dayjs@^1.10.4:
+ version "1.11.9"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.9.tgz#9ca491933fadd0a60a2c19f6c237c03517d71d1a"
+ integrity sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==
+
+debug@2, debug@2.6.9, debug@^2.6.0:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+ dependencies:
+ ms "2.0.0"
+
+debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
+debug@^3.1.0, debug@^3.2.6, debug@^3.2.7:
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+ integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+ dependencies:
+ ms "^2.1.1"
+
+decimal.js@^10.2.1:
+ version "10.4.3"
+ resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23"
+ integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==
+
+dedent@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
+ integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==
+
+deep-equal@^2.0.5:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.1.tgz#c72ab22f3a7d3503a4ca87dde976fe9978816739"
+ integrity sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==
+ dependencies:
+ array-buffer-byte-length "^1.0.0"
+ call-bind "^1.0.2"
+ es-get-iterator "^1.1.3"
+ get-intrinsic "^1.2.0"
+ is-arguments "^1.1.1"
+ is-array-buffer "^3.0.2"
+ 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.5.0"
+ side-channel "^1.0.4"
+ which-boxed-primitive "^1.0.2"
+ which-collection "^1.0.1"
+ which-typed-array "^1.1.9"
+
+deep-is@^0.1.3, deep-is@~0.1.3:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
+ integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
+
+deepmerge@^4.0.0, deepmerge@^4.2.2:
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
+ integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
+
+default-gateway@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71"
+ integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==
+ dependencies:
+ execa "^5.0.0"
+
+define-lazy-prop@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
+ integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
+
+define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5"
+ integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==
+ dependencies:
+ has-property-descriptors "^1.0.0"
+ object-keys "^1.1.1"
+
+defined@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.1.tgz#c0b9db27bfaffd95d6f61399419b893df0f91ebf"
+ integrity sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
+depd@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
+ integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
+
+depd@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+ integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
+
+dequal@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
+ integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
+
+destroy@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
+ integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
+
+detect-kerning@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/detect-kerning/-/detect-kerning-2.1.2.tgz#4ecd548e4a5a3fc880fe2a50609312d000fa9fc2"
+ integrity sha512-I3JIbrnKPAntNLl1I6TpSQQdQ4AutYzv/sKMFKbepawV/hlH0GmYKhUoOEMd4xqaUHT+Bm0f4127lh5qs1m1tw==
+
+detect-newline@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
+ integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
+
+detect-node@^2.0.4:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
+ integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
+
+detect-port-alt@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275"
+ integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==
+ dependencies:
+ address "^1.0.1"
+ debug "^2.6.0"
+
+didyoumean@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
+ integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
+
+diff-sequences@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
+ integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==
+
+diff-sequences@^29.4.3:
+ version "29.4.3"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.4.3.tgz#9314bc1fabe09267ffeca9cbafc457d8499a13f2"
+ integrity sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==
+
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
+dlv@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
+ integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
+
+dns-equal@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
+ integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==
+
+dns-packet@^5.2.2:
+ version "5.6.0"
+ resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.6.0.tgz#2202c947845c7a63c23ece58f2f70ff6ab4c2f7d"
+ integrity sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==
+ dependencies:
+ "@leichtgewicht/ip-codec" "^2.0.1"
+
+doctrine@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
+ integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==
+ dependencies:
+ esutils "^2.0.2"
+
+doctrine@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
+ integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
+ dependencies:
+ esutils "^2.0.2"
+
+dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9:
+ version "0.5.16"
+ resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453"
+ integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==
+
+dom-converter@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
+ integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==
+ dependencies:
+ utila "~0.4"
+
+dom-helpers@^5.0.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
+ integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
+ dependencies:
+ "@babel/runtime" "^7.8.7"
+ csstype "^3.0.2"
+
+dom-serializer@0:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
+ integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==
+ dependencies:
+ domelementtype "^2.0.1"
+ entities "^2.0.0"
+
+dom-serializer@^1.0.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30"
+ integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==
+ dependencies:
+ domelementtype "^2.0.1"
+ domhandler "^4.2.0"
+ entities "^2.0.0"
+
+domelementtype@1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
+ integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
+
+domelementtype@^2.0.1, domelementtype@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
+ integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
+
+domexception@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304"
+ integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==
+ dependencies:
+ webidl-conversions "^5.0.0"
+
+domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1:
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c"
+ integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==
+ dependencies:
+ domelementtype "^2.2.0"
+
+domutils@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
+ integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==
+ dependencies:
+ dom-serializer "0"
+ domelementtype "1"
+
+domutils@^2.5.2, domutils@^2.8.0:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
+ integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==
+ dependencies:
+ dom-serializer "^1.0.1"
+ domelementtype "^2.2.0"
+ domhandler "^4.2.0"
+
+dot-case@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
+ integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==
+ dependencies:
+ no-case "^3.0.4"
+ tslib "^2.0.3"
+
+dotenv-expand@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0"
+ integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==
+
+dotenv@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
+ integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
+
+draw-svg-path@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/draw-svg-path/-/draw-svg-path-1.0.0.tgz#6f116d962dd314b99ea534d6f58dd66cdbd69379"
+ integrity sha512-P8j3IHxcgRMcY6sDzr0QvJDLzBnJJqpTG33UZ2Pvp8rw0apCHhJCWqYprqrXjrgHnJ6tuhP1iTJSAodPDHxwkg==
+ dependencies:
+ abs-svg-path "~0.1.1"
+ normalize-svg-path "~0.1.0"
+
+dtype@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/dtype/-/dtype-2.0.0.tgz#cd052323ce061444ecd2e8f5748f69a29be28434"
+ integrity sha512-s2YVcLKdFGS0hpFqJaTwscsyt0E8nNFdmo73Ocd81xNPj4URI4rj6D60A+vFMIw7BXWlb4yRkEwfBqcZzPGiZg==
+
+dup@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/dup/-/dup-1.0.0.tgz#51fc5ac685f8196469df0b905e934b20af5b4029"
+ integrity sha512-Bz5jxMMC0wgp23Zm15ip1x8IhYRqJvF3nFC0UInJUDkN1z4uNPk9jTnfCUJXbOGiQ1JbXLQsiV41Fb+HXcj5BA==
+
+duplexer@^0.1.2, duplexer@~0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
+ integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
+
+duplexify@^3.4.5:
+ version "3.7.1"
+ resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
+ integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
+ dependencies:
+ end-of-stream "^1.0.0"
+ inherits "^2.0.1"
+ readable-stream "^2.0.0"
+ stream-shift "^1.0.0"
+
+earcut@^2.1.5, earcut@^2.2.2:
+ version "2.2.4"
+ resolved "https://registry.yarnpkg.com/earcut/-/earcut-2.2.4.tgz#6d02fd4d68160c114825d06890a92ecaae60343a"
+ integrity sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==
+
+ecc-jsbn@~0.1.1:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
+ integrity sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==
+ dependencies:
+ jsbn "~0.1.0"
+ safer-buffer "^2.1.0"
+
+ee-first@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+ integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
+
+ejs@^3.1.6:
+ version "3.1.9"
+ resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.9.tgz#03c9e8777fe12686a9effcef22303ca3d8eeb361"
+ integrity sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==
+ dependencies:
+ jake "^10.8.5"
+
+electron-to-chromium@^1.4.431:
+ version "1.4.441"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.441.tgz#94dd9c1cbf081d83f032a4f1cd9f787e21fc24ce"
+ integrity sha512-LlCgQ8zgYZPymf5H4aE9itwiIWH4YlCiv1HFLmmcBeFYi5E+3eaIFnjHzYtcFQbaKfAW+CqZ9pgxo33DZuoqPg==
+
+element-size@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/element-size/-/element-size-1.1.1.tgz#64e5f159d97121631845bcbaecaf279c39b5e34e"
+ integrity sha512-eaN+GMOq/Q+BIWy0ybsgpcYImjGIdNLyjLFJU4XsLHXYQao5jCNb36GyN6C2qwmDDYSfIBmKpPpr4VnBdLCsPQ==
+
+elementary-circuits-directed-graph@^1.0.4:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/elementary-circuits-directed-graph/-/elementary-circuits-directed-graph-1.3.1.tgz#31c5a1c69517de833127247e5460472168e9e1c1"
+ integrity sha512-ZEiB5qkn2adYmpXGnJKkxT8uJHlW/mxmBpmeqawEHzPxh9HkLD4/1mFYX5l0On+f6rcPIt8/EWlRU2Vo3fX6dQ==
+ dependencies:
+ strongly-connected-components "^1.0.1"
+
+emittery@^0.10.2:
+ version "0.10.2"
+ resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933"
+ integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==
+
+emittery@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860"
+ integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==
+
+emoji-regex@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+ integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
+emoji-regex@^9.2.2:
+ version "9.2.2"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
+ integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
+
+emojis-list@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
+ integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
+
+encodeurl@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+ integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
+
+end-of-stream@^1.0.0, end-of-stream@^1.1.0:
+ version "1.4.4"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
+ integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
+ dependencies:
+ once "^1.4.0"
+
+enhanced-resolve@^5.15.0:
+ version "5.15.0"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35"
+ integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==
+ dependencies:
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
+
+enquirer@^2.3.6:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
+ integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
+ dependencies:
+ ansi-colors "^4.1.1"
+
+entities@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
+ integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
+
+error-ex@^1.3.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+ dependencies:
+ is-arrayish "^0.2.1"
+
+error-stack-parser@^2.0.6:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286"
+ integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==
+ dependencies:
+ stackframe "^1.3.4"
+
+es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.20.4, es-abstract@^1.21.2:
+ version "1.21.2"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff"
+ integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==
+ 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"
+
+es-array-method-boxes-properly@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
+ integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==
+
+es-get-iterator@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.3.tgz#3ef87523c5d464d41084b2c3c9c214f1199763d6"
+ integrity sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==
+ 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"
+
+es-module-lexer@^1.2.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.3.0.tgz#6be9c9e0b4543a60cd166ff6f8b4e9dae0b0c16f"
+ integrity sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==
+
+es-set-tostringtag@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8"
+ integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==
+ dependencies:
+ get-intrinsic "^1.1.3"
+ has "^1.0.3"
+ has-tostringtag "^1.0.0"
+
+es-shim-unscopables@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241"
+ integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==
+ dependencies:
+ has "^1.0.3"
+
+es-to-primitive@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
+ integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
+ dependencies:
+ is-callable "^1.1.4"
+ is-date-object "^1.0.1"
+ is-symbol "^1.0.2"
+
+es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50:
+ version "0.10.62"
+ resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5"
+ integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==
+ dependencies:
+ es6-iterator "^2.0.3"
+ es6-symbol "^3.1.3"
+ next-tick "^1.1.0"
+
+es6-iterator@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7"
+ integrity sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==
+ dependencies:
+ d "1"
+ es5-ext "^0.10.35"
+ es6-symbol "^3.1.1"
+
+es6-symbol@^3.1.1, es6-symbol@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18"
+ integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==
+ dependencies:
+ d "^1.0.1"
+ ext "^1.1.2"
+
+es6-weak-map@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53"
+ integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==
+ dependencies:
+ d "1"
+ es5-ext "^0.10.46"
+ es6-iterator "^2.0.3"
+ es6-symbol "^3.1.1"
+
+escalade@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
+ integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+
+escape-html@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+ integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
+
+escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+ integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+
+escape-string-regexp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
+ integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
+
+escape-string-regexp@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
+ integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
+escodegen@^1.11.1:
+ version "1.14.3"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
+ integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==
+ dependencies:
+ esprima "^4.0.1"
+ estraverse "^4.2.0"
+ esutils "^2.0.2"
+ optionator "^0.8.1"
+ optionalDependencies:
+ source-map "~0.6.1"
+
+escodegen@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd"
+ integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==
+ dependencies:
+ esprima "^4.0.1"
+ estraverse "^5.2.0"
+ esutils "^2.0.2"
+ optionator "^0.8.1"
+ optionalDependencies:
+ source-map "~0.6.1"
+
+eslint-config-react-app@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz#73ba3929978001c5c86274c017ea57eb5fa644b4"
+ integrity sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==
+ dependencies:
+ "@babel/core" "^7.16.0"
+ "@babel/eslint-parser" "^7.16.3"
+ "@rushstack/eslint-patch" "^1.1.0"
+ "@typescript-eslint/eslint-plugin" "^5.5.0"
+ "@typescript-eslint/parser" "^5.5.0"
+ babel-preset-react-app "^10.0.1"
+ confusing-browser-globals "^1.0.11"
+ eslint-plugin-flowtype "^8.0.3"
+ eslint-plugin-import "^2.25.3"
+ eslint-plugin-jest "^25.3.0"
+ eslint-plugin-jsx-a11y "^6.5.1"
+ eslint-plugin-react "^7.27.1"
+ eslint-plugin-react-hooks "^4.3.0"
+ eslint-plugin-testing-library "^5.0.1"
+
+eslint-import-resolver-node@^0.3.7:
+ version "0.3.7"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz#83b375187d412324a1963d84fa664377a23eb4d7"
+ integrity sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==
+ dependencies:
+ debug "^3.2.7"
+ is-core-module "^2.11.0"
+ resolve "^1.22.1"
+
+eslint-module-utils@^2.7.4:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49"
+ integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==
+ dependencies:
+ debug "^3.2.7"
+
+eslint-plugin-flowtype@^8.0.3:
+ version "8.0.3"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz#e1557e37118f24734aa3122e7536a038d34a4912"
+ integrity sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==
+ dependencies:
+ lodash "^4.17.21"
+ string-natural-compare "^3.0.1"
+
+eslint-plugin-import@^2.25.3:
+ version "2.27.5"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz#876a6d03f52608a3e5bb439c2550588e51dd6c65"
+ integrity sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==
+ 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"
+
+eslint-plugin-jest@^25.3.0:
+ version "25.7.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz#ff4ac97520b53a96187bad9c9814e7d00de09a6a"
+ integrity sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==
+ dependencies:
+ "@typescript-eslint/experimental-utils" "^5.0.0"
+
+eslint-plugin-jsx-a11y@^6.5.1:
+ version "6.7.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.7.1.tgz#fca5e02d115f48c9a597a6894d5bcec2f7a76976"
+ integrity sha512-63Bog4iIethyo8smBklORknVjB0T2dwB8Mr/hIC+fBS0uyHdYYpzM/Ed+YC8VxTjlXHEWFOdmgwcDn1U2L9VCA==
+ 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"
+
+eslint-plugin-react-hooks@^4.3.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
+ integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
+
+eslint-plugin-react@^7.27.1:
+ version "7.32.2"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz#e71f21c7c265ebce01bcbc9d0955170c55571f10"
+ integrity sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==
+ 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"
+
+eslint-plugin-testing-library@^5.0.1:
+ version "5.11.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.11.0.tgz#0bad7668e216e20dd12f8c3652ca353009163121"
+ integrity sha512-ELY7Gefo+61OfXKlQeXNIDVVLPcvKTeiQOoMZG9TeuWa7Ln4dUNRv8JdRWBQI9Mbb427XGlVB1aa1QPZxBJM8Q==
+ dependencies:
+ "@typescript-eslint/utils" "^5.58.0"
+
+eslint-scope@5.1.1, eslint-scope@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
+eslint-scope@^7.2.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.0.tgz#f21ebdafda02352f103634b96dd47d9f81ca117b"
+ integrity sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^5.2.0"
+
+eslint-visitor-keys@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
+ integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
+
+eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994"
+ integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==
+
+eslint-webpack-plugin@^3.1.1:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-3.2.0.tgz#1978cdb9edc461e4b0195a20da950cf57988347c"
+ integrity sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==
+ dependencies:
+ "@types/eslint" "^7.29.0 || ^8.4.1"
+ jest-worker "^28.0.2"
+ micromatch "^4.0.5"
+ normalize-path "^3.0.0"
+ schema-utils "^4.0.0"
+
+eslint@^8.3.0:
+ version "8.43.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.43.0.tgz#3e8c6066a57097adfd9d390b8fc93075f257a094"
+ integrity sha512-aaCpf2JqqKesMFGgmRPessmVKjcGXqdlAYLLC3THM8t5nBRZRQ+st5WM/hoJXkdioEXLLbXgclUpM0TXo5HX5Q==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.2.0"
+ "@eslint-community/regexpp" "^4.4.0"
+ "@eslint/eslintrc" "^2.0.3"
+ "@eslint/js" "8.43.0"
+ "@humanwhocodes/config-array" "^0.11.10"
+ "@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.2.0"
+ eslint-visitor-keys "^3.4.1"
+ espree "^9.5.2"
+ 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"
+ graphemer "^1.4.0"
+ 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-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"
+
+espree@^9.5.2:
+ version "9.5.2"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-9.5.2.tgz#e994e7dc33a082a7a82dceaf12883a829353215b"
+ integrity sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==
+ dependencies:
+ acorn "^8.8.0"
+ acorn-jsx "^5.3.2"
+ eslint-visitor-keys "^3.4.1"
+
+esprima@^4.0.0, esprima@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+esquery@^1.4.2:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
+ integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
+ dependencies:
+ estraverse "^5.1.0"
+
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
+estraverse@^4.1.1, estraverse@^4.2.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
+ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+estree-walker@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
+ integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
+
+esutils@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+ integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+etag@~1.8.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+ integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
+
+event-stream@=3.3.4:
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/event-stream/-/event-stream-3.3.4.tgz#4ab4c9a0f5a54db9338b4c34d86bfce8f4b35571"
+ integrity sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==
+ dependencies:
+ duplexer "~0.1.1"
+ from "~0"
+ map-stream "~0.1.0"
+ pause-stream "0.0.11"
+ split "0.3"
+ stream-combiner "~0.0.4"
+ through "~2.3.1"
+
+eventemitter2@6.4.7:
+ version "6.4.7"
+ resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.7.tgz#a7f6c4d7abf28a14c1ef3442f21cb306a054271d"
+ integrity sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==
+
+eventemitter3@^4.0.0:
+ version "4.0.7"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
+ integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+
+events@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
+execa@4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a"
+ integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==
+ dependencies:
+ cross-spawn "^7.0.0"
+ get-stream "^5.0.0"
+ human-signals "^1.1.1"
+ is-stream "^2.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^4.0.0"
+ onetime "^5.1.0"
+ signal-exit "^3.0.2"
+ strip-final-newline "^2.0.0"
+
+execa@5.1.1, execa@^5.0.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
+ integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
+ dependencies:
+ cross-spawn "^7.0.3"
+ get-stream "^6.0.0"
+ human-signals "^2.1.0"
+ is-stream "^2.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^4.0.1"
+ onetime "^5.1.2"
+ signal-exit "^3.0.3"
+ strip-final-newline "^2.0.0"
+
+executable@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c"
+ integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==
+ dependencies:
+ pify "^2.2.0"
+
+exit@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
+ integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==
+
+expect@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74"
+ integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+
+expect@^29.0.0:
+ version "29.5.0"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-29.5.0.tgz#68c0509156cb2a0adb8865d413b137eeaae682f7"
+ integrity sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==
+ dependencies:
+ "@jest/expect-utils" "^29.5.0"
+ jest-get-type "^29.4.3"
+ jest-matcher-utils "^29.5.0"
+ jest-message-util "^29.5.0"
+ jest-util "^29.5.0"
+
+express@^4.17.3:
+ version "4.18.2"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
+ integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
+ dependencies:
+ accepts "~1.3.8"
+ array-flatten "1.1.1"
+ body-parser "1.20.1"
+ content-disposition "0.5.4"
+ content-type "~1.0.4"
+ cookie "0.5.0"
+ cookie-signature "1.0.6"
+ debug "2.6.9"
+ depd "2.0.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ finalhandler "1.2.0"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "2.4.1"
+ parseurl "~1.3.3"
+ path-to-regexp "0.1.7"
+ proxy-addr "~2.0.7"
+ qs "6.11.0"
+ range-parser "~1.2.1"
+ safe-buffer "5.2.1"
+ send "0.18.0"
+ serve-static "1.15.0"
+ setprototypeof "1.2.0"
+ statuses "2.0.1"
+ type-is "~1.6.18"
+ utils-merge "1.0.1"
+ vary "~1.1.2"
+
+ext@^1.1.2:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f"
+ integrity sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==
+ dependencies:
+ type "^2.7.2"
+
+extend@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
+ integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
+
+extract-zip@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
+ integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
+ dependencies:
+ debug "^4.1.1"
+ get-stream "^5.1.0"
+ yauzl "^2.10.0"
+ optionalDependencies:
+ "@types/yauzl" "^2.9.1"
+
+extsprintf@1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
+ integrity sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==
+
+extsprintf@^1.2.0:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07"
+ integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==
+
+falafel@^2.1.0:
+ version "2.2.5"
+ resolved "https://registry.yarnpkg.com/falafel/-/falafel-2.2.5.tgz#3ccb4970a09b094e9e54fead2deee64b4a589d56"
+ integrity sha512-HuC1qF9iTnHDnML9YZAdCDQwT0yKl/U55K4XSUXqGAA2GLoafFgWRqdAbhWJxXaYD4pyoVxAJ8wH670jMpI9DQ==
+ dependencies:
+ acorn "^7.1.1"
+ isarray "^2.0.1"
+
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-glob@^3.2.12, fast-glob@^3.2.9:
+ version "3.2.12"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80"
+ integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
+fast-isnumeric@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/fast-isnumeric/-/fast-isnumeric-1.1.4.tgz#e165786ff471c439e9ace2b8c8e66cceb47e2ea4"
+ integrity sha512-1mM8qOr2LYz8zGaUdmiqRDiuue00Dxjgcb1NQR7TnhLVh6sQyngP9xvLo7Sl7LZpP/sk5eb+bcyWXw530NTBZw==
+ dependencies:
+ is-string-blank "^1.0.1"
+
+fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+ integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
+
+fastq@^1.6.0:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a"
+ integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==
+ dependencies:
+ reusify "^1.0.4"
+
+faye-websocket@^0.11.3:
+ version "0.11.4"
+ resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da"
+ integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==
+ dependencies:
+ websocket-driver ">=0.5.1"
+
+fb-watchman@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c"
+ integrity sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==
+ dependencies:
+ bser "2.1.1"
+
+fd-slicer@~1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
+ integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==
+ dependencies:
+ pend "~1.2.0"
+
+figures@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
+ integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
+ dependencies:
+ escape-string-regexp "^1.0.5"
+
+file-entry-cache@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
+ integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
+ dependencies:
+ flat-cache "^3.0.4"
+
+file-loader@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d"
+ integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==
+ dependencies:
+ loader-utils "^2.0.0"
+ schema-utils "^3.0.0"
+
+filelist@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5"
+ integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==
+ dependencies:
+ minimatch "^5.0.1"
+
+filesize@^8.0.6:
+ version "8.0.7"
+ resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8"
+ integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==
+
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+finalhandler@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
+ integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
+ dependencies:
+ debug "2.6.9"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ on-finished "2.4.1"
+ parseurl "~1.3.3"
+ statuses "2.0.1"
+ unpipe "~1.0.0"
+
+find-cache-dir@^3.3.1:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b"
+ integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==
+ dependencies:
+ commondir "^1.0.1"
+ make-dir "^3.0.2"
+ pkg-dir "^4.1.0"
+
+find-root@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
+ integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
+
+find-up@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+ integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+ dependencies:
+ locate-path "^3.0.0"
+
+find-up@^4.0.0, find-up@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
+find-up@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+ dependencies:
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
+
+flat-cache@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
+ integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
+ dependencies:
+ flatted "^3.1.0"
+ rimraf "^3.0.2"
+
+flatted@^3.1.0:
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
+ integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
+
+flatten-vertex-data@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/flatten-vertex-data/-/flatten-vertex-data-1.0.2.tgz#889fd60bea506006ca33955ee1105175fb620219"
+ integrity sha512-BvCBFK2NZqerFTdMDgqfHBwxYWnxeCkwONsw6PvBMcUXqo8U/KDWwmXhqx1x2kLIg7DqIsJfOaJFOmlua3Lxuw==
+ dependencies:
+ dtype "^2.0.0"
+
+follow-redirects@^1.0.0, follow-redirects@^1.14.9:
+ version "1.15.2"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
+ integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
+
+font-atlas@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/font-atlas/-/font-atlas-2.1.0.tgz#aa2d6dcf656a6c871d66abbd3dfbea2f77178348"
+ integrity sha512-kP3AmvX+HJpW4w3d+PiPR2X6E1yvsBXt2yhuCw+yReO9F1WYhvZwx3c95DGZGwg9xYzDGrgJYa885xmVA+28Cg==
+ dependencies:
+ css-font "^1.0.0"
+
+font-measure@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/font-measure/-/font-measure-1.2.2.tgz#41dbdac5d230dbf4db08865f54da28a475e83026"
+ integrity sha512-mRLEpdrWzKe9hbfaF3Qpr06TAjquuBVP5cHy4b3hyeNdjc9i0PO6HniGsX5vjL5OWv7+Bd++NiooNpT/s8BvIA==
+ dependencies:
+ css-font "^1.2.0"
+
+for-each@^0.3.3:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
+ integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==
+ dependencies:
+ is-callable "^1.1.3"
+
+forever-agent@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
+ integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==
+
+fork-ts-checker-webpack-plugin@^6.5.0:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz#eda2eff6e22476a2688d10661688c47f611b37f3"
+ integrity sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==
+ dependencies:
+ "@babel/code-frame" "^7.8.3"
+ "@types/json-schema" "^7.0.5"
+ chalk "^4.1.0"
+ chokidar "^3.4.2"
+ cosmiconfig "^6.0.0"
+ deepmerge "^4.2.2"
+ fs-extra "^9.0.0"
+ glob "^7.1.6"
+ memfs "^3.1.2"
+ minimatch "^3.0.4"
+ schema-utils "2.7.0"
+ semver "^7.3.2"
+ tapable "^1.0.0"
+
+form-data@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
+ integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+form-data@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
+ integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+form-data@~2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
+ integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.6"
+ mime-types "^2.1.12"
+
+forwarded@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
+ integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
+
+fraction.js@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
+ integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
+
+fresh@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+ integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
+
+from2@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af"
+ integrity sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==
+ dependencies:
+ inherits "^2.0.1"
+ readable-stream "^2.0.0"
+
+from@~0:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
+ integrity sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==
+
+fs-extra@^10.0.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
+ integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
+ dependencies:
+ graceful-fs "^4.2.0"
+ jsonfile "^6.0.1"
+ universalify "^2.0.0"
+
+fs-extra@^9.0.0, fs-extra@^9.0.1, fs-extra@^9.1.0:
+ version "9.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
+ integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
+ dependencies:
+ at-least-node "^1.0.0"
+ graceful-fs "^4.2.0"
+ jsonfile "^6.0.1"
+ universalify "^2.0.0"
+
+fs-monkey@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.4.tgz#ee8c1b53d3fe8bb7e5d2c5c5dfc0168afdd2f747"
+ integrity sha512-INM/fWAxMICjttnD0DX1rBvinKskj5G1w+oy/pnm9u/tSlnBrzFonJMcalKJ30P8RRsPzKcCG7Q8l0jx5Fh9YQ==
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+fsevents@^2.3.2, fsevents@~2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
+function-bind@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+function.prototype.name@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
+ integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.0"
+ functions-have-names "^1.2.2"
+
+functions-have-names@^1.2.2, functions-have-names@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
+ integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
+
+gensync@^1.0.0-beta.2:
+ version "1.0.0-beta.2"
+ resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
+ integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
+
+geojson-vt@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/geojson-vt/-/geojson-vt-3.2.1.tgz#f8adb614d2c1d3f6ee7c4265cad4bbf3ad60c8b7"
+ integrity sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==
+
+get-caller-file@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+ integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
+get-canvas-context@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/get-canvas-context/-/get-canvas-context-1.0.2.tgz#d6e7b50bc4e4c86357cd39f22647a84b73601e93"
+ integrity sha512-LnpfLf/TNzr9zVOGiIY6aKCz8EKuXmlYNV7CM2pUjBa/B+c2I15tS7KLySep75+FuerJdmArvJLcsAXWEy2H0A==
+
+get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82"
+ integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==
+ dependencies:
+ function-bind "^1.1.1"
+ has "^1.0.3"
+ has-proto "^1.0.1"
+ has-symbols "^1.0.3"
+
+get-own-enumerable-property-symbols@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
+ integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==
+
+get-package-type@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
+ integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==
+
+get-stream@^5.0.0, get-stream@^5.1.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
+ integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
+ dependencies:
+ pump "^3.0.0"
+
+get-stream@^6.0.0, get-stream@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
+ integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+
+get-symbol-description@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
+ integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.1"
+
+getos@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/getos/-/getos-3.2.1.tgz#0134d1f4e00eb46144c5a9c0ac4dc087cbb27dc5"
+ integrity sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==
+ dependencies:
+ async "^3.2.0"
+
+getpass@^0.1.1:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
+ integrity sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==
+ dependencies:
+ assert-plus "^1.0.0"
+
+gl-mat4@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/gl-mat4/-/gl-mat4-1.2.0.tgz#49d8a7636b70aa00819216635f4a3fd3f4669b26"
+ integrity sha512-sT5C0pwB1/e9G9AvAoLsoaJtbMGjfd/jfxo8jMCKqYYEnjZuFvqV5rehqar0538EmssjdDeiEWnKyBSTw7quoA==
+
+gl-matrix@^3.2.1:
+ version "3.4.3"
+ resolved "https://registry.yarnpkg.com/gl-matrix/-/gl-matrix-3.4.3.tgz#fc1191e8320009fd4d20e9339595c6041ddc22c9"
+ integrity sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA==
+
+gl-text@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/gl-text/-/gl-text-1.3.1.tgz#f36594464101b5b053178d6d219c3d08fb9144c8"
+ integrity sha512-/f5gcEMiZd+UTBJLTl3D+CkCB/0UFGTx3nflH8ZmyWcLkZhsZ1+Xx5YYkw2rgWAzgPeE35xCqBuHSoMKQVsR+w==
+ dependencies:
+ bit-twiddle "^1.0.2"
+ color-normalize "^1.5.0"
+ css-font "^1.2.0"
+ detect-kerning "^2.1.2"
+ es6-weak-map "^2.0.3"
+ flatten-vertex-data "^1.0.2"
+ font-atlas "^2.1.0"
+ font-measure "^1.2.2"
+ gl-util "^3.1.2"
+ is-plain-obj "^1.1.0"
+ object-assign "^4.1.1"
+ parse-rect "^1.2.0"
+ parse-unit "^1.0.1"
+ pick-by-alias "^1.2.0"
+ regl "^2.0.0"
+ to-px "^1.0.1"
+ typedarray-pool "^1.1.0"
+
+gl-util@^3.1.2:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/gl-util/-/gl-util-3.1.3.tgz#1e9a724f844b802597c6e30565d4c1e928546861"
+ integrity sha512-dvRTggw5MSkJnCbh74jZzSoTOGnVYK+Bt+Ckqm39CVcl6+zSsxqWk4lr5NKhkqXHL6qvZAU9h17ZF8mIskY9mA==
+ dependencies:
+ is-browser "^2.0.1"
+ is-firefox "^1.0.3"
+ is-plain-obj "^1.1.0"
+ number-is-integer "^1.0.1"
+ object-assign "^4.1.0"
+ pick-by-alias "^1.2.0"
+ weak-map "^1.0.5"
+
+glob-parent@^5.1.2, glob-parent@~5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob-parent@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+ dependencies:
+ is-glob "^4.0.3"
+
+glob-to-regexp@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
+ integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
+
+glob@7.1.6:
+ version "7.1.6"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
+ integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
+ version "7.2.3"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
+ integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
+ 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"
+
+global-dirs@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485"
+ integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==
+ dependencies:
+ ini "2.0.0"
+
+global-modules@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
+ integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==
+ dependencies:
+ global-prefix "^3.0.0"
+
+global-prefix@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97"
+ integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==
+ dependencies:
+ ini "^1.3.5"
+ kind-of "^6.0.2"
+ which "^1.3.1"
+
+globals@^11.1.0:
+ version "11.12.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
+ integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
+globals@^13.19.0:
+ version "13.20.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82"
+ integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==
+ dependencies:
+ type-fest "^0.20.2"
+
+globalthis@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
+ integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
+ dependencies:
+ define-properties "^1.1.3"
+
+globby@^11.0.4, globby@^11.1.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
+glsl-inject-defines@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/glsl-inject-defines/-/glsl-inject-defines-1.0.3.tgz#dd1aacc2c17fcb2bd3fc32411c6633d0d7b60fd4"
+ integrity sha512-W49jIhuDtF6w+7wCMcClk27a2hq8znvHtlGnrYkSWEr8tHe9eA2dcnohlcAmxLYBSpSSdzOkRdyPTrx9fw49+A==
+ dependencies:
+ glsl-token-inject-block "^1.0.0"
+ glsl-token-string "^1.0.1"
+ glsl-tokenizer "^2.0.2"
+
+glsl-resolve@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/glsl-resolve/-/glsl-resolve-0.0.1.tgz#894bef73910d792c81b5143180035d0a78af76d3"
+ integrity sha512-xxFNsfnhZTK9NBhzJjSBGX6IOqYpvBHxxmo+4vapiljyGNCY0Bekzn0firQkQrazK59c1hYxMDxYS8MDlhw4gA==
+ dependencies:
+ resolve "^0.6.1"
+ xtend "^2.1.2"
+
+glsl-token-assignments@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/glsl-token-assignments/-/glsl-token-assignments-2.0.2.tgz#a5d82ab78499c2e8a6b83cb69495e6e665ce019f"
+ integrity sha512-OwXrxixCyHzzA0U2g4btSNAyB2Dx8XrztY5aVUCjRSh4/D0WoJn8Qdps7Xub3sz6zE73W3szLrmWtQ7QMpeHEQ==
+
+glsl-token-defines@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/glsl-token-defines/-/glsl-token-defines-1.0.0.tgz#cb892aa959936231728470d4f74032489697fa9d"
+ integrity sha512-Vb5QMVeLjmOwvvOJuPNg3vnRlffscq2/qvIuTpMzuO/7s5kT+63iL6Dfo2FYLWbzuiycWpbC0/KV0biqFwHxaQ==
+ dependencies:
+ glsl-tokenizer "^2.0.0"
+
+glsl-token-depth@^1.1.0, glsl-token-depth@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/glsl-token-depth/-/glsl-token-depth-1.1.2.tgz#23c5e30ee2bd255884b4a28bc850b8f791e95d84"
+ integrity sha512-eQnIBLc7vFf8axF9aoi/xW37LSWd2hCQr/3sZui8aBJnksq9C7zMeUYHVJWMhFzXrBU7fgIqni4EhXVW4/krpg==
+
+glsl-token-descope@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/glsl-token-descope/-/glsl-token-descope-1.0.2.tgz#0fc90ab326186b82f597b2e77dc9e21efcd32076"
+ integrity sha512-kS2PTWkvi/YOeicVjXGgX5j7+8N7e56srNDEHDTVZ1dcESmbmpmgrnpjPcjxJjMxh56mSXYoFdZqb90gXkGjQw==
+ dependencies:
+ glsl-token-assignments "^2.0.0"
+ glsl-token-depth "^1.1.0"
+ glsl-token-properties "^1.0.0"
+ glsl-token-scope "^1.1.0"
+
+glsl-token-inject-block@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/glsl-token-inject-block/-/glsl-token-inject-block-1.1.0.tgz#e1015f5980c1091824adaa2625f1dfde8bd00034"
+ integrity sha512-q/m+ukdUBuHCOtLhSr0uFb/qYQr4/oKrPSdIK2C4TD+qLaJvqM9wfXIF/OOBjuSA3pUoYHurVRNao6LTVVUPWA==
+
+glsl-token-properties@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/glsl-token-properties/-/glsl-token-properties-1.0.1.tgz#483dc3d839f0d4b5c6171d1591f249be53c28a9e"
+ integrity sha512-dSeW1cOIzbuUoYH0y+nxzwK9S9O3wsjttkq5ij9ZGw0OS41BirKJzzH48VLm8qLg+au6b0sINxGC0IrGwtQUcA==
+
+glsl-token-scope@^1.1.0, glsl-token-scope@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/glsl-token-scope/-/glsl-token-scope-1.1.2.tgz#a1728e78df24444f9cb93fd18ef0f75503a643b1"
+ integrity sha512-YKyOMk1B/tz9BwYUdfDoHvMIYTGtVv2vbDSLh94PT4+f87z21FVdou1KNKgF+nECBTo0fJ20dpm0B1vZB1Q03A==
+
+glsl-token-string@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/glsl-token-string/-/glsl-token-string-1.0.1.tgz#59441d2f857de7c3449c945666021ece358e48ec"
+ integrity sha512-1mtQ47Uxd47wrovl+T6RshKGkRRCYWhnELmkEcUAPALWGTFe2XZpH3r45XAwL2B6v+l0KNsCnoaZCSnhzKEksg==
+
+glsl-token-whitespace-trim@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/glsl-token-whitespace-trim/-/glsl-token-whitespace-trim-1.0.0.tgz#46d1dfe98c75bd7d504c05d7d11b1b3e9cc93b10"
+ integrity sha512-ZJtsPut/aDaUdLUNtmBYhaCmhIjpKNg7IgZSfX5wFReMc2vnj8zok+gB/3Quqs0TsBSX/fGnqUUYZDqyuc2xLQ==
+
+glsl-tokenizer@^2.0.0, glsl-tokenizer@^2.0.2:
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/glsl-tokenizer/-/glsl-tokenizer-2.1.5.tgz#1c2e78c16589933c274ba278d0a63b370c5fee1a"
+ integrity sha512-XSZEJ/i4dmz3Pmbnpsy3cKh7cotvFlBiZnDOwnj/05EwNp2XrhQ4XKJxT7/pDt4kp4YcpRSKz8eTV7S+mwV6MA==
+ dependencies:
+ through2 "^0.6.3"
+
+glslify-bundle@^5.0.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/glslify-bundle/-/glslify-bundle-5.1.1.tgz#30d2ddf2e6b935bf44d1299321e3b729782c409a"
+ integrity sha512-plaAOQPv62M1r3OsWf2UbjN0hUYAB7Aph5bfH58VxJZJhloRNbxOL9tl/7H71K7OLJoSJ2ZqWOKk3ttQ6wy24A==
+ dependencies:
+ glsl-inject-defines "^1.0.1"
+ glsl-token-defines "^1.0.0"
+ glsl-token-depth "^1.1.1"
+ glsl-token-descope "^1.0.2"
+ glsl-token-scope "^1.1.1"
+ glsl-token-string "^1.0.1"
+ glsl-token-whitespace-trim "^1.0.0"
+ glsl-tokenizer "^2.0.2"
+ murmurhash-js "^1.0.0"
+ shallow-copy "0.0.1"
+
+glslify-deps@^1.2.5:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/glslify-deps/-/glslify-deps-1.3.2.tgz#c09ee945352bfc07ac2d8a1cc9e3de776328c72b"
+ integrity sha512-7S7IkHWygJRjcawveXQjRXLO2FTjijPDYC7QfZyAQanY+yGLCFHYnPtsGT9bdyHiwPTw/5a1m1M9hamT2aBpag==
+ dependencies:
+ "@choojs/findup" "^0.2.0"
+ events "^3.2.0"
+ glsl-resolve "0.0.1"
+ glsl-tokenizer "^2.0.0"
+ graceful-fs "^4.1.2"
+ inherits "^2.0.1"
+ map-limit "0.0.1"
+ resolve "^1.0.0"
+
+glslify@^7.0.0, glslify@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/glslify/-/glslify-7.1.1.tgz#454d9172b410cb49864029c86d5613947fefd30b"
+ integrity sha512-bud98CJ6kGZcP9Yxcsi7Iz647wuDz3oN+IZsjCRi5X1PI7t/xPKeL0mOwXJjo+CRZMqvq0CkSJiywCcY7kVYog==
+ dependencies:
+ bl "^2.2.1"
+ concat-stream "^1.5.2"
+ duplexify "^3.4.5"
+ falafel "^2.1.0"
+ from2 "^2.3.0"
+ glsl-resolve "0.0.1"
+ glsl-token-whitespace-trim "^1.0.0"
+ glslify-bundle "^5.0.0"
+ glslify-deps "^1.2.5"
+ minimist "^1.2.5"
+ resolve "^1.1.5"
+ stack-trace "0.0.9"
+ static-eval "^2.0.5"
+ through2 "^2.0.1"
+ xtend "^4.0.0"
+
+gopd@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
+ integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
+ dependencies:
+ get-intrinsic "^1.1.3"
+
+graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
+ version "4.2.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+grapheme-splitter@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
+ integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
+
+graphemer@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
+ integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
+
+grid-index@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/grid-index/-/grid-index-1.1.0.tgz#97f8221edec1026c8377b86446a7c71e79522ea7"
+ integrity sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==
+
+gzip-size@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
+ integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==
+ dependencies:
+ duplexer "^0.1.2"
+
+handle-thing@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e"
+ integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==
+
+harmony-reflect@^1.4.6:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710"
+ integrity sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==
+
+has-bigints@^1.0.1, has-bigints@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
+ integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
+
+has-flag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+ integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+has-hover@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/has-hover/-/has-hover-1.0.1.tgz#3d97437aeb199c62b8ac08acbdc53d3bc52c17f7"
+ integrity sha512-0G6w7LnlcpyDzpeGUTuT0CEw05+QlMuGVk1IHNAlHrGJITGodjZu3x8BNDUMfKJSZXNB2ZAclqc1bvrd+uUpfg==
+ dependencies:
+ is-browser "^2.0.1"
+
+has-passive-events@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-passive-events/-/has-passive-events-1.0.0.tgz#75fc3dc6dada182c58f24ebbdc018276d1ea3515"
+ integrity sha512-2vSj6IeIsgvsRMyeQ0JaCX5Q3lX4zMn5HpoVc7MEhQ6pv8Iq9rsXjsp+E5ZwaT7T0xhMT0KmU8gtt1EFVdbJiw==
+ dependencies:
+ is-browser "^2.0.1"
+
+has-property-descriptors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
+ integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
+ dependencies:
+ get-intrinsic "^1.1.1"
+
+has-proto@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
+ integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==
+
+has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
+ integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
+
+has-tostringtag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
+ integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
+ dependencies:
+ has-symbols "^1.0.2"
+
+has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+he@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
+ integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
+
+hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
+ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
+ dependencies:
+ react-is "^16.7.0"
+
+hoopy@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
+ integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==
+
+hpack.js@^2.1.6:
+ version "2.1.6"
+ resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
+ integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==
+ dependencies:
+ inherits "^2.0.1"
+ obuf "^1.0.0"
+ readable-stream "^2.0.1"
+ wbuf "^1.1.0"
+
+hsluv@^0.0.3:
+ version "0.0.3"
+ resolved "https://registry.yarnpkg.com/hsluv/-/hsluv-0.0.3.tgz#829107dafb4a9f8b52a1809ed02e091eade6754c"
+ integrity sha512-08iL2VyCRbkQKBySkSh6m8zMUa3sADAxGVWs3Z1aPcUkTJeK0ETG4Fc27tEmQBGUAXZjIsXOZqBvacuVNSC/fQ==
+
+html-encoding-sniffer@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
+ integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==
+ dependencies:
+ whatwg-encoding "^1.0.5"
+
+html-entities@^2.1.0, html-entities@^2.3.2:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.4.0.tgz#edd0cee70402584c8c76cc2c0556db09d1f45061"
+ integrity sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ==
+
+html-escaper@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
+ integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
+
+html-minifier-terser@^6.0.2:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab"
+ integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==
+ dependencies:
+ camel-case "^4.1.2"
+ clean-css "^5.2.2"
+ commander "^8.3.0"
+ he "^1.2.0"
+ param-case "^3.0.4"
+ relateurl "^0.2.7"
+ terser "^5.10.0"
+
+html-webpack-plugin@^5.5.0:
+ version "5.5.3"
+ resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.3.tgz#72270f4a78e222b5825b296e5e3e1328ad525a3e"
+ integrity sha512-6YrDKTuqaP/TquFH7h4srYWsZx+x6k6+FbsTm0ziCwGHDP78Unr1r9F/H4+sGmMbX08GQcJ+K64x55b+7VM/jg==
+ dependencies:
+ "@types/html-minifier-terser" "^6.0.0"
+ html-minifier-terser "^6.0.2"
+ lodash "^4.17.21"
+ pretty-error "^4.0.0"
+ tapable "^2.0.0"
+
+htmlparser2@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
+ integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==
+ dependencies:
+ domelementtype "^2.0.1"
+ domhandler "^4.0.0"
+ domutils "^2.5.2"
+ entities "^2.0.0"
+
+http-deceiver@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
+ integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==
+
+http-errors@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
+ integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
+ dependencies:
+ depd "2.0.0"
+ inherits "2.0.4"
+ setprototypeof "1.2.0"
+ statuses "2.0.1"
+ toidentifier "1.0.1"
+
+http-errors@~1.6.2:
+ version "1.6.3"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
+ integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==
+ dependencies:
+ depd "~1.1.2"
+ inherits "2.0.3"
+ setprototypeof "1.1.0"
+ statuses ">= 1.4.0 < 2"
+
+http-parser-js@>=0.5.1:
+ version "0.5.8"
+ resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3"
+ integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==
+
+http-proxy-agent@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
+ integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
+ dependencies:
+ "@tootallnate/once" "1"
+ agent-base "6"
+ debug "4"
+
+http-proxy-middleware@^2.0.3, http-proxy-middleware@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f"
+ integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==
+ dependencies:
+ "@types/http-proxy" "^1.17.8"
+ http-proxy "^1.18.1"
+ is-glob "^4.0.1"
+ is-plain-obj "^3.0.0"
+ micromatch "^4.0.2"
+
+http-proxy@^1.18.1:
+ version "1.18.1"
+ resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
+ integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==
+ dependencies:
+ eventemitter3 "^4.0.0"
+ follow-redirects "^1.0.0"
+ requires-port "^1.0.0"
+
+http-signature@~1.3.6:
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.3.6.tgz#cb6fbfdf86d1c974f343be94e87f7fc128662cf9"
+ integrity sha512-3adrsD6zqo4GsTqtO7FyrejHNv+NgiIfAfv68+jVlFmSr9OGy7zrxONceFRLKvnnZA5jbxQBX1u9PpB6Wi32Gw==
+ dependencies:
+ assert-plus "^1.0.0"
+ jsprim "^2.0.2"
+ sshpk "^1.14.1"
+
+https-proxy-agent@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
+ integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
+ dependencies:
+ agent-base "6"
+ debug "4"
+
+human-signals@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
+ integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
+
+human-signals@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
+ integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+
+iconv-lite@0.4.24, iconv-lite@^0.4.4:
+ version "0.4.24"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+ integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
+iconv-lite@^0.6.3:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
+ integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3.0.0"
+
+icss-utils@^5.0.0, icss-utils@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
+ integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==
+
+idb@^7.0.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b"
+ integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==
+
+identity-obj-proxy@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14"
+ integrity sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==
+ dependencies:
+ harmony-reflect "^1.4.6"
+
+ieee754@^1.1.12, ieee754@^1.1.13:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
+ integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
+
+ignore@^5.2.0:
+ version "5.2.4"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
+ integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
+
+immer@^9.0.21, immer@^9.0.7:
+ version "9.0.21"
+ resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.21.tgz#1e025ea31a40f24fb064f1fef23e931496330176"
+ integrity sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==
+
+import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
+ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+ dependencies:
+ parent-module "^1.0.0"
+ resolve-from "^4.0.0"
+
+import-local@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4"
+ integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==
+ dependencies:
+ pkg-dir "^4.2.0"
+ resolve-cwd "^3.0.0"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+ integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
+
+indent-string@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+ integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+inherits@2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+ integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
+
+ini@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
+ integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
+
+ini@^1.3.5:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
+ integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
+
+internal-slot@^1.0.3, internal-slot@^1.0.4, internal-slot@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986"
+ integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==
+ dependencies:
+ get-intrinsic "^1.2.0"
+ has "^1.0.3"
+ side-channel "^1.0.4"
+
+ipaddr.js@1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
+ integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
+
+ipaddr.js@^2.0.1:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.1.0.tgz#2119bc447ff8c257753b196fc5f1ce08a4cdf39f"
+ integrity sha512-LlbxQ7xKzfBusov6UMi4MFpEg0m+mAm9xyNGEduwXMEDuf4WfzB/RZwMVYEd7IKGvh4IUkEXYxtAVu9T3OelJQ==
+
+is-arguments@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b"
+ integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-array-buffer@^3.0.1, is-array-buffer@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe"
+ integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.2.0"
+ is-typed-array "^1.1.10"
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+ integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
+
+is-bigint@^1.0.1:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
+ integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==
+ dependencies:
+ has-bigints "^1.0.1"
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-boolean-object@^1.1.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719"
+ integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-browser@^2.0.1:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-browser/-/is-browser-2.1.0.tgz#fc084d59a5fced307d6708c59356bad7007371a9"
+ integrity sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ==
+
+is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
+ integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
+
+is-ci@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-3.0.1.tgz#db6ecbed1bd659c43dac0f45661e7674103d1867"
+ integrity sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==
+ dependencies:
+ ci-info "^3.2.0"
+
+is-core-module@^2.11.0, is-core-module@^2.9.0:
+ version "2.12.1"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd"
+ integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==
+ dependencies:
+ has "^1.0.3"
+
+is-date-object@^1.0.1, is-date-object@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
+ integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-docker@^2.0.0, is-docker@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
+ integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-finite@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3"
+ integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==
+
+is-firefox@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/is-firefox/-/is-firefox-1.0.3.tgz#2a2a1567783a417f6e158323108f3861b0918562"
+ integrity sha512-6Q9ITjvWIm0Xdqv+5U12wgOKEM2KoBw4Y926m0OFkvlCxnbG94HKAsVz8w3fWcfAS5YA2fJORXX1dLrkprCCxA==
+
+is-fullwidth-code-point@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+ integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
+is-generator-fn@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
+ integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
+
+is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-iexplorer@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-iexplorer/-/is-iexplorer-1.0.0.tgz#1d72bc66d3fe22eaf6170dda8cf10943248cfc76"
+ integrity sha512-YeLzceuwg3K6O0MLM3UyUUjKAlyULetwryFp1mHy1I5PfArK0AEqlfa+MR4gkJjcbuJXoDJCvXbyqZVf5CR2Sg==
+
+is-installed-globally@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.4.0.tgz#9a0fd407949c30f86eb6959ef1b7994ed0b7b520"
+ integrity sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==
+ dependencies:
+ global-dirs "^3.0.0"
+ is-path-inside "^3.0.2"
+
+is-map@^2.0.1, is-map@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127"
+ integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==
+
+is-mobile@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/is-mobile/-/is-mobile-4.0.0.tgz#bba396eb9656e2739afde3053d7191da310fc758"
+ integrity sha512-mlcHZA84t1qLSuWkt2v0I2l61PYdyQDt4aG1mLIXF5FDMm4+haBCxCPYSr/uwqQNRk1MiTizn0ypEuRAOLRAew==
+
+is-module@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
+ integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==
+
+is-negative-zero@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
+ integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
+
+is-number-object@^1.0.4:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
+ integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-obj@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
+ integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==
+
+is-path-inside@^3.0.2, is-path-inside@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
+ integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
+
+is-plain-obj@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
+ integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==
+
+is-plain-obj@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7"
+ integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==
+
+is-potential-custom-element-name@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
+ integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
+
+is-regex@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
+ integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
+ integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==
+
+is-root@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c"
+ integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==
+
+is-set@^2.0.1, is-set@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec"
+ integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==
+
+is-shared-array-buffer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79"
+ integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==
+ dependencies:
+ call-bind "^1.0.2"
+
+is-stream@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
+ integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
+
+is-string-blank@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-string-blank/-/is-string-blank-1.0.1.tgz#866dca066d41d2894ebdfd2d8fe93e586e583a03"
+ integrity sha512-9H+ZBCVs3L9OYqv8nuUAzpcT9OTgMD1yAWrG7ihlnibdkbtB850heAmYWxHuXc4CHy4lKeK69tN+ny1K7gBIrw==
+
+is-string@^1.0.5, is-string@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
+ integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-svg-path@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-svg-path/-/is-svg-path-1.0.2.tgz#77ab590c12b3d20348e5c7a13d0040c87784dda0"
+ integrity sha512-Lj4vePmqpPR1ZnRctHv8ltSh1OrSxHkhUkd7wi+VQdcdP15/KvQFyk7LhNuM7ZW0EVbJz8kZLVmL9quLrfq4Kg==
+
+is-symbol@^1.0.2, is-symbol@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
+ integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==
+ dependencies:
+ has-symbols "^1.0.2"
+
+is-typed-array@^1.1.10, is-typed-array@^1.1.9:
+ version "1.1.10"
+ resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f"
+ integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==
+ 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-typedarray@^1.0.0, is-typedarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+ integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==
+
+is-unicode-supported@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7"
+ integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==
+
+is-weakmap@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2"
+ integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==
+
+is-weakref@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
+ integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==
+ dependencies:
+ call-bind "^1.0.2"
+
+is-weakset@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d"
+ integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.1"
+
+is-wsl@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
+ integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
+ dependencies:
+ is-docker "^2.0.0"
+
+isarray@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+ integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==
+
+isarray@^2.0.1, isarray@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
+ integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
+
+isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+ integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+isstream@~0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
+ integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==
+
+istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3"
+ integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==
+
+istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz#d10c8885c2125574e1c231cacadf955675e1ce3d"
+ integrity sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==
+ dependencies:
+ "@babel/core" "^7.12.3"
+ "@babel/parser" "^7.14.7"
+ "@istanbuljs/schema" "^0.1.2"
+ istanbul-lib-coverage "^3.2.0"
+ semver "^6.3.0"
+
+istanbul-lib-report@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6"
+ integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==
+ dependencies:
+ istanbul-lib-coverage "^3.0.0"
+ make-dir "^3.0.0"
+ supports-color "^7.1.0"
+
+istanbul-lib-source-maps@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551"
+ integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==
+ dependencies:
+ debug "^4.1.1"
+ istanbul-lib-coverage "^3.0.0"
+ source-map "^0.6.1"
+
+istanbul-reports@^3.1.3:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae"
+ integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w==
+ dependencies:
+ html-escaper "^2.0.0"
+ istanbul-lib-report "^3.0.0"
+
+jake@^10.8.5:
+ version "10.8.7"
+ resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.7.tgz#63a32821177940c33f356e0ba44ff9d34e1c7d8f"
+ integrity sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==
+ dependencies:
+ async "^3.2.3"
+ chalk "^4.0.2"
+ filelist "^1.0.4"
+ minimatch "^3.1.2"
+
+jest-changed-files@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5"
+ integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ execa "^5.0.0"
+ throat "^6.0.1"
+
+jest-circus@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc"
+ integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ co "^4.6.0"
+ dedent "^0.7.0"
+ expect "^27.5.1"
+ is-generator-fn "^2.0.0"
+ jest-each "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+ throat "^6.0.1"
+
+jest-cli@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145"
+ integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==
+ dependencies:
+ "@jest/core" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ exit "^0.1.2"
+ graceful-fs "^4.2.9"
+ import-local "^3.0.2"
+ jest-config "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ prompts "^2.0.1"
+ yargs "^16.2.0"
+
+jest-config@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41"
+ integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==
+ dependencies:
+ "@babel/core" "^7.8.0"
+ "@jest/test-sequencer" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ babel-jest "^27.5.1"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ deepmerge "^4.2.2"
+ glob "^7.1.1"
+ graceful-fs "^4.2.9"
+ jest-circus "^27.5.1"
+ jest-environment-jsdom "^27.5.1"
+ jest-environment-node "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-jasmine2 "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-runner "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ micromatch "^4.0.4"
+ parse-json "^5.2.0"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ strip-json-comments "^3.1.1"
+
+jest-diff@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def"
+ integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==
+ dependencies:
+ chalk "^4.0.0"
+ diff-sequences "^27.5.1"
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-diff@^29.5.0:
+ version "29.5.0"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.5.0.tgz#e0d83a58eb5451dcc1fa61b1c3ee4e8f5a290d63"
+ integrity sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==
+ dependencies:
+ chalk "^4.0.0"
+ diff-sequences "^29.4.3"
+ jest-get-type "^29.4.3"
+ pretty-format "^29.5.0"
+
+jest-docblock@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0"
+ integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==
+ dependencies:
+ detect-newline "^3.0.0"
+
+jest-each@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e"
+ integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ jest-get-type "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-environment-jsdom@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546"
+ integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
+ jsdom "^16.6.0"
+
+jest-environment-node@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e"
+ integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
+
+jest-get-type@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1"
+ integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==
+
+jest-get-type@^29.4.3:
+ version "29.4.3"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.4.3.tgz#1ab7a5207c995161100b5187159ca82dd48b3dd5"
+ integrity sha512-J5Xez4nRRMjk8emnTpWrlkyb9pfRQQanDrvWHhsR1+VUfbwxi30eVcZFlcdGInRibU4G5LwHXpI7IRHU0CY+gg==
+
+jest-haste-map@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f"
+ integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/graceful-fs" "^4.1.2"
+ "@types/node" "*"
+ anymatch "^3.0.3"
+ fb-watchman "^2.0.0"
+ graceful-fs "^4.2.9"
+ jest-regex-util "^27.5.1"
+ jest-serializer "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
+ micromatch "^4.0.4"
+ walker "^1.0.7"
+ optionalDependencies:
+ fsevents "^2.3.2"
+
+jest-jasmine2@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4"
+ integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/source-map" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ co "^4.6.0"
+ expect "^27.5.1"
+ is-generator-fn "^2.0.0"
+ jest-each "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+ throat "^6.0.1"
+
+jest-leak-detector@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8"
+ integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==
+ dependencies:
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
+ integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
+ dependencies:
+ chalk "^4.0.0"
+ jest-diff "^27.5.1"
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-matcher-utils@^29.5.0:
+ version "29.5.0"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz#d957af7f8c0692c5453666705621ad4abc2c59c5"
+ integrity sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==
+ dependencies:
+ chalk "^4.0.0"
+ jest-diff "^29.5.0"
+ jest-get-type "^29.4.3"
+ pretty-format "^29.5.0"
+
+jest-message-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf"
+ integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==
+ dependencies:
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^27.5.1"
+ "@types/stack-utils" "^2.0.0"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
+jest-message-util@^28.1.3:
+ version "28.1.3"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.3.tgz#232def7f2e333f1eecc90649b5b94b0055e7c43d"
+ integrity sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==
+ dependencies:
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^28.1.3"
+ "@types/stack-utils" "^2.0.0"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^28.1.3"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
+jest-message-util@^29.5.0:
+ version "29.5.0"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.5.0.tgz#1f776cac3aca332ab8dd2e3b41625435085c900e"
+ integrity sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==
+ dependencies:
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^29.5.0"
+ "@types/stack-utils" "^2.0.0"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^29.5.0"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
+jest-mock@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6"
+ integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+
+jest-pnp-resolver@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz#930b1546164d4ad5937d5540e711d4d38d4cad2e"
+ integrity sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==
+
+jest-regex-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95"
+ integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==
+
+jest-regex-util@^28.0.0:
+ version "28.0.2"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-28.0.2.tgz#afdc377a3b25fb6e80825adcf76c854e5bf47ead"
+ integrity sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==
+
+jest-resolve-dependencies@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8"
+ integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-snapshot "^27.5.1"
+
+jest-resolve@^27.4.2, jest-resolve@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384"
+ integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-pnp-resolver "^1.2.2"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ resolve "^1.20.0"
+ resolve.exports "^1.1.0"
+ slash "^3.0.0"
+
+jest-runner@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5"
+ integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==
+ dependencies:
+ "@jest/console" "^27.5.1"
+ "@jest/environment" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ emittery "^0.8.1"
+ graceful-fs "^4.2.9"
+ jest-docblock "^27.5.1"
+ jest-environment-jsdom "^27.5.1"
+ jest-environment-node "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-leak-detector "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
+ source-map-support "^0.5.6"
+ throat "^6.0.1"
+
+jest-runtime@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af"
+ integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/globals" "^27.5.1"
+ "@jest/source-map" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ cjs-module-lexer "^1.0.0"
+ collect-v8-coverage "^1.0.0"
+ execa "^5.0.0"
+ glob "^7.1.3"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-mock "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ slash "^3.0.0"
+ strip-bom "^4.0.0"
+
+jest-serializer@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64"
+ integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==
+ dependencies:
+ "@types/node" "*"
+ graceful-fs "^4.2.9"
+
+jest-snapshot@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1"
+ integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==
+ dependencies:
+ "@babel/core" "^7.7.2"
+ "@babel/generator" "^7.7.2"
+ "@babel/plugin-syntax-typescript" "^7.7.2"
+ "@babel/traverse" "^7.7.2"
+ "@babel/types" "^7.0.0"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/babel__traverse" "^7.0.4"
+ "@types/prettier" "^2.1.5"
+ babel-preset-current-node-syntax "^1.0.0"
+ chalk "^4.0.0"
+ expect "^27.5.1"
+ graceful-fs "^4.2.9"
+ jest-diff "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-util "^27.5.1"
+ natural-compare "^1.4.0"
+ pretty-format "^27.5.1"
+ semver "^7.3.2"
+
+jest-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9"
+ integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
+
+jest-util@^28.1.3:
+ version "28.1.3"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.3.tgz#f4f932aa0074f0679943220ff9cbba7e497028b0"
+ integrity sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==
+ dependencies:
+ "@jest/types" "^28.1.3"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
+
+jest-util@^29.5.0:
+ version "29.5.0"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.5.0.tgz#24a4d3d92fc39ce90425311b23c27a6e0ef16b8f"
+ integrity sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==
+ dependencies:
+ "@jest/types" "^29.5.0"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
+
+jest-validate@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067"
+ integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ camelcase "^6.2.0"
+ chalk "^4.0.0"
+ jest-get-type "^27.5.1"
+ leven "^3.1.0"
+ pretty-format "^27.5.1"
+
+jest-watch-typeahead@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz#b4a6826dfb9c9420da2f7bc900de59dad11266a9"
+ integrity sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==
+ dependencies:
+ ansi-escapes "^4.3.1"
+ chalk "^4.0.0"
+ jest-regex-util "^28.0.0"
+ jest-watcher "^28.0.0"
+ slash "^4.0.0"
+ string-length "^5.0.1"
+ strip-ansi "^7.0.1"
+
+jest-watcher@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2"
+ integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==
+ dependencies:
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ jest-util "^27.5.1"
+ string-length "^4.0.1"
+
+jest-watcher@^28.0.0:
+ version "28.1.3"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.3.tgz#c6023a59ba2255e3b4c57179fc94164b3e73abd4"
+ integrity sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==
+ dependencies:
+ "@jest/test-result" "^28.1.3"
+ "@jest/types" "^28.1.3"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ emittery "^0.10.2"
+ jest-util "^28.1.3"
+ string-length "^4.0.1"
+
+jest-worker@^26.2.1:
+ version "26.6.2"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed"
+ integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==
+ dependencies:
+ "@types/node" "*"
+ merge-stream "^2.0.0"
+ supports-color "^7.0.0"
+
+jest-worker@^27.0.2, jest-worker@^27.4.5, jest-worker@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0"
+ integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==
+ dependencies:
+ "@types/node" "*"
+ merge-stream "^2.0.0"
+ supports-color "^8.0.0"
+
+jest-worker@^28.0.2:
+ version "28.1.3"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-28.1.3.tgz#7e3c4ce3fa23d1bb6accb169e7f396f98ed4bb98"
+ integrity sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==
+ dependencies:
+ "@types/node" "*"
+ merge-stream "^2.0.0"
+ supports-color "^8.0.0"
+
+jest@^27.4.3:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc"
+ integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==
+ dependencies:
+ "@jest/core" "^27.5.1"
+ import-local "^3.0.2"
+ jest-cli "^27.5.1"
+
+jiti@^1.18.2:
+ version "1.18.2"
+ resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.18.2.tgz#80c3ef3d486ebf2450d9335122b32d121f2a83cd"
+ integrity sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==
+
+joi@^17.7.0:
+ version "17.9.2"
+ resolved "https://registry.yarnpkg.com/joi/-/joi-17.9.2.tgz#8b2e4724188369f55451aebd1d0b1d9482470690"
+ integrity sha512-Itk/r+V4Dx0V3c7RLFdRh12IOjySm2/WGPMubBT92cQvRfYZhPM2W0hZlctjj72iES8jsRCwp7S/cRmWBnJ4nw==
+ dependencies:
+ "@hapi/hoek" "^9.0.0"
+ "@hapi/topo" "^5.0.0"
+ "@sideway/address" "^4.1.3"
+ "@sideway/formula" "^3.0.1"
+ "@sideway/pinpoint" "^2.0.0"
+
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-yaml@^3.13.1:
+ version "3.14.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
+ integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
+js-yaml@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
+jsbn@~0.1.0:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
+ integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==
+
+jsdom@^16.6.0:
+ version "16.7.0"
+ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710"
+ integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==
+ dependencies:
+ abab "^2.0.5"
+ acorn "^8.2.4"
+ acorn-globals "^6.0.0"
+ cssom "^0.4.4"
+ cssstyle "^2.3.0"
+ data-urls "^2.0.0"
+ decimal.js "^10.2.1"
+ domexception "^2.0.1"
+ escodegen "^2.0.0"
+ form-data "^3.0.0"
+ html-encoding-sniffer "^2.0.1"
+ http-proxy-agent "^4.0.1"
+ https-proxy-agent "^5.0.0"
+ is-potential-custom-element-name "^1.0.1"
+ nwsapi "^2.2.0"
+ parse5 "6.0.1"
+ saxes "^5.0.1"
+ symbol-tree "^3.2.4"
+ tough-cookie "^4.0.0"
+ w3c-hr-time "^1.0.2"
+ w3c-xmlserializer "^2.0.0"
+ webidl-conversions "^6.1.0"
+ whatwg-encoding "^1.0.5"
+ whatwg-mimetype "^2.3.0"
+ whatwg-url "^8.5.0"
+ ws "^7.4.6"
+ xml-name-validator "^3.0.0"
+
+jsesc@^2.5.1:
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+ integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
+jsesc@~0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+ integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
+
+json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json-schema-traverse@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+ integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+
+json-schema@0.4.0, json-schema@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
+ integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
+
+json-stable-stringify-without-jsonify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+ integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
+
+json-stringify-safe@~5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
+ integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==
+
+json5@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
+ integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==
+ dependencies:
+ minimist "^1.2.0"
+
+json5@^2.1.2, json5@^2.2.0, json5@^2.2.2:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
+ integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
+
+jsonfile@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
+ integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
+ dependencies:
+ universalify "^2.0.0"
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+jsonpointer@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559"
+ integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==
+
+jsprim@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d"
+ integrity sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==
+ dependencies:
+ assert-plus "1.0.0"
+ extsprintf "1.3.0"
+ json-schema "0.4.0"
+ verror "1.10.0"
+
+"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.3:
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.3.tgz#76b3e6e6cece5c69d49a5792c3d01bd1a0cdc7ea"
+ integrity sha512-fYQHZTZ8jSfmWZ0iyzfwiU4WDX4HpHbMCZ3gPlWYiCl3BoeOTsqKBqnTVfH2rYT7eP5c3sVbeSPHnnJOaTrWiw==
+ dependencies:
+ array-includes "^3.1.5"
+ object.assign "^4.1.3"
+
+kdbush@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/kdbush/-/kdbush-3.0.0.tgz#f8484794d47004cc2d85ed3a79353dbe0abc2bf0"
+ integrity sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==
+
+kind-of@^6.0.2:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
+ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+
+kleur@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
+ integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
+
+klona@^2.0.4, klona@^2.0.5:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22"
+ integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==
+
+language-subtag-registry@~0.3.2:
+ version "0.3.22"
+ resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d"
+ integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==
+
+language-tags@=1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a"
+ integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==
+ dependencies:
+ language-subtag-registry "~0.3.2"
+
+launch-editor@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/launch-editor/-/launch-editor-2.6.0.tgz#4c0c1a6ac126c572bd9ff9a30da1d2cae66defd7"
+ integrity sha512-JpDCcQnyAAzZZaZ7vEiSqL690w7dAEyLao+KC96zBplnYbJS7TYNjvM3M7y3dGz+v7aIsJk3hllWuc0kWAjyRQ==
+ dependencies:
+ picocolors "^1.0.0"
+ shell-quote "^1.7.3"
+
+lazy-ass@1.6.0, lazy-ass@^1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513"
+ integrity sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==
+
+leven@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
+ integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
+
+levn@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+ integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+ dependencies:
+ prelude-ls "^1.2.1"
+ type-check "~0.4.0"
+
+levn@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+ integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==
+ dependencies:
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+
+lilconfig@^2.0.3, lilconfig@^2.0.5, lilconfig@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
+ integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
+
+lines-and-columns@^1.1.6:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
+ integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+
+listr2@^3.8.3:
+ version "3.14.0"
+ resolved "https://registry.yarnpkg.com/listr2/-/listr2-3.14.0.tgz#23101cc62e1375fd5836b248276d1d2b51fdbe9e"
+ integrity sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==
+ dependencies:
+ cli-truncate "^2.1.0"
+ colorette "^2.0.16"
+ log-update "^4.0.0"
+ p-map "^4.0.0"
+ rfdc "^1.3.0"
+ rxjs "^7.5.1"
+ through "^2.3.8"
+ wrap-ansi "^7.0.0"
+
+load-script@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/load-script/-/load-script-1.0.0.tgz#0491939e0bee5643ee494a7e3da3d2bac70c6ca4"
+ integrity sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==
+
+loader-runner@^4.2.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1"
+ integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==
+
+loader-utils@^2.0.0, loader-utils@^2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c"
+ integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==
+ dependencies:
+ big.js "^5.2.2"
+ emojis-list "^3.0.0"
+ json5 "^2.1.2"
+
+loader-utils@^3.2.0:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.1.tgz#4fb104b599daafd82ef3e1a41fb9265f87e1f576"
+ integrity sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==
+
+locate-path@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+ integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+ dependencies:
+ p-locate "^3.0.0"
+ path-exists "^3.0.0"
+
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
+
+lodash.debounce@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
+ integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
+
+lodash.memoize@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
+ integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==
+
+lodash.merge@^4.6.2:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
+ integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+
+lodash.once@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
+ integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
+
+lodash.sortby@^4.7.0:
+ version "4.7.0"
+ resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
+ integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==
+
+lodash.uniq@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+ integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==
+
+lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+log-symbols@^4.0.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
+ integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
+ dependencies:
+ chalk "^4.1.0"
+ is-unicode-supported "^0.1.0"
+
+log-update@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1"
+ integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==
+ dependencies:
+ ansi-escapes "^4.3.0"
+ cli-cursor "^3.1.0"
+ slice-ansi "^4.0.0"
+ wrap-ansi "^6.2.0"
+
+loose-envify@^1.1.0, loose-envify@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+ dependencies:
+ js-tokens "^3.0.0 || ^4.0.0"
+
+lower-case@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
+ integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==
+ dependencies:
+ tslib "^2.0.3"
+
+lru-cache@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
+ integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
+ dependencies:
+ yallist "^3.0.2"
+
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
+lz-string@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
+ integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==
+
+magic-string@^0.25.0, magic-string@^0.25.7:
+ version "0.25.9"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
+ integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
+ dependencies:
+ sourcemap-codec "^1.4.8"
+
+make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
+ integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
+ dependencies:
+ semver "^6.0.0"
+
+makeerror@1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
+ integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==
+ dependencies:
+ tmpl "1.0.5"
+
+map-limit@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/map-limit/-/map-limit-0.0.1.tgz#eb7961031c0f0e8d001bf2d56fab685d58822f38"
+ integrity sha512-pJpcfLPnIF/Sk3taPW21G/RQsEEirGaFpCW3oXRwH9dnFHPHNGjNyvh++rdmC2fNqEaTw2MhYJraoJWAHx8kEg==
+ dependencies:
+ once "~1.3.0"
+
+map-stream@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
+ integrity sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==
+
+mapbox-gl@1.10.1:
+ version "1.10.1"
+ resolved "https://registry.yarnpkg.com/mapbox-gl/-/mapbox-gl-1.10.1.tgz#7dbd53bdf2f78e45e125c1115e94dea286ef663c"
+ integrity sha512-0aHt+lFUpYfvh0kMIqXqNXqoYMuhuAsMlw87TbhWrw78Tx2zfuPI0Lx31/YPUgJ+Ire0tzQ4JnuBL7acDNXmMg==
+ dependencies:
+ "@mapbox/geojson-rewind" "^0.5.0"
+ "@mapbox/geojson-types" "^1.0.2"
+ "@mapbox/jsonlint-lines-primitives" "^2.0.2"
+ "@mapbox/mapbox-gl-supported" "^1.5.0"
+ "@mapbox/point-geometry" "^0.1.0"
+ "@mapbox/tiny-sdf" "^1.1.1"
+ "@mapbox/unitbezier" "^0.0.0"
+ "@mapbox/vector-tile" "^1.3.1"
+ "@mapbox/whoots-js" "^3.1.0"
+ csscolorparser "~1.0.3"
+ earcut "^2.2.2"
+ geojson-vt "^3.2.1"
+ gl-matrix "^3.2.1"
+ grid-index "^1.1.0"
+ minimist "^1.2.5"
+ murmurhash-js "^1.0.0"
+ pbf "^3.2.1"
+ potpack "^1.0.1"
+ quickselect "^2.0.0"
+ rw "^1.3.3"
+ supercluster "^7.0.0"
+ tinyqueue "^2.0.3"
+ vt-pbf "^3.1.1"
+
+math-log2@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/math-log2/-/math-log2-1.0.1.tgz#fb8941be5f5ebe8979e718e6273b178e58694565"
+ integrity sha512-9W0yGtkaMAkf74XGYVy4Dqw3YUMnTNB2eeiw9aQbUl4A3KmuCEHTt2DgAB07ENzOYAjsYSAYufkAq0Zd+jU7zA==
+
+mdn-data@2.0.14:
+ version "2.0.14"
+ resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
+ integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==
+
+mdn-data@2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
+ integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==
+
+media-typer@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+ integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
+
+memfs@^3.1.2, memfs@^3.4.3:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.6.0.tgz#d7a2110f86f79dd950a8b6df6d57bc984aa185f6"
+ integrity sha512-EGowvkkgbMcIChjMTMkESFDbZeSh8xZ7kNSF0hAiAN4Jh6jgHCRS0Ga/+C8y6Au+oqpezRHCfPsmJ2+DwAgiwQ==
+ dependencies:
+ fs-monkey "^1.0.4"
+
+memoize-one@^5.1.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
+ integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==
+
+merge-descriptors@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+ integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
+
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
+merge2@^1.3.0, merge2@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+methods@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+ integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
+
+micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+ integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+ dependencies:
+ braces "^3.0.2"
+ picomatch "^2.3.1"
+
+mime-db@1.52.0, "mime-db@>= 1.43.0 < 2":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34:
+ version "2.1.35"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+mime@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+ integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+
+mimic-fn@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+ integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+min-indent@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
+ integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
+
+mini-css-extract-plugin@^2.4.5:
+ version "2.7.6"
+ resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.6.tgz#282a3d38863fddcd2e0c220aaed5b90bc156564d"
+ integrity sha512-Qk7HcgaPkGG6eD77mLvZS1nmxlao3j+9PkrT9Uc7HAE1id3F41+DdBRYRYkbyfNRGzm8/YWtzhw7nVPmwhqTQw==
+ dependencies:
+ schema-utils "^4.0.0"
+
+minimalistic-assert@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+ integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
+
+minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimatch@^5.0.1:
+ version "5.1.6"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96"
+ integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==
+ dependencies:
+ brace-expansion "^2.0.1"
+
+minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.7, minimist@^1.2.8:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+ integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+mkdirp@~0.5.1:
+ version "0.5.6"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
+ integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
+ dependencies:
+ minimist "^1.2.6"
+
+mouse-change@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/mouse-change/-/mouse-change-1.4.0.tgz#c2b77e5bfa34a43ce1445c8157a4e4dc9895c14f"
+ integrity sha512-vpN0s+zLL2ykyyUDh+fayu9Xkor5v/zRD9jhSqjRS1cJTGS0+oakVZzNm5n19JvvEj0you+MXlYTpNxUDQUjkQ==
+ dependencies:
+ mouse-event "^1.0.0"
+
+mouse-event-offset@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/mouse-event-offset/-/mouse-event-offset-3.0.2.tgz#dfd86a6e248c6ba8cad53b905d5037a2063e9984"
+ integrity sha512-s9sqOs5B1Ykox3Xo8b3Ss2IQju4UwlW6LSR+Q5FXWpprJ5fzMLefIIItr3PH8RwzfGy6gxs/4GAmiNuZScE25w==
+
+mouse-event@^1.0.0:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/mouse-event/-/mouse-event-1.0.5.tgz#b3789edb7109997d5a932d1d01daa1543a501732"
+ integrity sha512-ItUxtL2IkeSKSp9cyaX2JLUuKk2uMoxBg4bbOWVd29+CskYJR9BGsUqtXenNzKbnDshvupjUewDIYVrOB6NmGw==
+
+mouse-wheel@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/mouse-wheel/-/mouse-wheel-1.2.0.tgz#6d2903b1ea8fb48e61f1b53b9036773f042cdb5c"
+ integrity sha512-+OfYBiUOCTWcTECES49neZwL5AoGkXE+lFjIvzwNCnYRlso+EnfvovcBxGoyQ0yQt806eSPjS675K0EwWknXmw==
+ dependencies:
+ right-now "^1.0.0"
+ signum "^1.0.0"
+ to-px "^1.0.1"
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+ integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
+
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+ms@2.1.3, ms@^2.1.1:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+ integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
+multicast-dns@^7.2.5:
+ version "7.2.5"
+ resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced"
+ integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==
+ dependencies:
+ dns-packet "^5.2.2"
+ thunky "^1.0.2"
+
+mumath@^3.3.4:
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/mumath/-/mumath-3.3.4.tgz#48d4a0f0fd8cad4e7b32096ee89b161a63d30bbf"
+ integrity sha512-VAFIOG6rsxoc7q/IaY3jdjmrsuX9f15KlRLYTHmixASBZkZEKC1IFqE2BC5CdhXmK6WLM1Re33z//AGmeRI6FA==
+ dependencies:
+ almost-equal "^1.1.0"
+
+murmurhash-js@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/murmurhash-js/-/murmurhash-js-1.0.0.tgz#b06278e21fc6c37fa5313732b0412bcb6ae15f51"
+ integrity sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==
+
+mz@^2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
+ integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
+ dependencies:
+ any-promise "^1.0.0"
+ object-assign "^4.0.1"
+ thenify-all "^1.0.0"
+
+nanoid@^3.3.6:
+ version "3.3.6"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
+ integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
+
+native-promise-only@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/native-promise-only/-/native-promise-only-0.8.1.tgz#20a318c30cb45f71fe7adfbf7b21c99c1472ef11"
+ integrity sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==
+
+natural-compare-lite@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz#17b09581988979fddafe0201e931ba933c96cbb4"
+ integrity sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+ integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+
+needle@^2.5.2:
+ version "2.9.1"
+ resolved "https://registry.yarnpkg.com/needle/-/needle-2.9.1.tgz#22d1dffbe3490c2b83e301f7709b6736cd8f2684"
+ integrity sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==
+ dependencies:
+ debug "^3.2.6"
+ iconv-lite "^0.4.4"
+ sax "^1.2.4"
+
+negotiator@0.6.3:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
+ integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
+
+neo-async@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
+ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+
+next-tick@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb"
+ integrity sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==
+
+no-case@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
+ integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==
+ dependencies:
+ lower-case "^2.0.2"
+ tslib "^2.0.3"
+
+node-forge@^1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
+ integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
+
+node-int64@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
+ integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==
+
+node-releases@^2.0.12:
+ version "2.0.12"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.12.tgz#35627cc224a23bfb06fb3380f2b3afaaa7eb1039"
+ integrity sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+normalize-range@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+ integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
+
+normalize-svg-path@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz#0e614eca23c39f0cffe821d6be6cd17e569a766c"
+ integrity sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==
+ dependencies:
+ svg-arc-to-cubic-bezier "^3.0.0"
+
+normalize-svg-path@~0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/normalize-svg-path/-/normalize-svg-path-0.1.0.tgz#456360e60ece75fbef7b5d7e160480e7ffd16fe5"
+ integrity sha512-1/kmYej2iedi5+ROxkRESL/pI02pkg0OBnaR4hJkSIX6+ORzepwbuUXfrdZaPjysTsJInj0Rj5NuX027+dMBvA==
+
+normalize-url@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
+ integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
+
+npm-run-path@^4.0.0, npm-run-path@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
+ integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
+ dependencies:
+ path-key "^3.0.0"
+
+nth-check@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
+ integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==
+ dependencies:
+ boolbase "~1.0.0"
+
+nth-check@^2.0.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
+ integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==
+ dependencies:
+ boolbase "^1.0.0"
+
+number-is-integer@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/number-is-integer/-/number-is-integer-1.0.1.tgz#e59bca172ffed27318e79c7ceb6cb72c095b2152"
+ integrity sha512-Dq3iuiFBkrbmuQjGFFF3zckXNCQoSD37/SdSbgcBailUx6knDvDwb5CympBgcoWHy36sfS12u74MHYkXyHq6bg==
+ dependencies:
+ is-finite "^1.0.1"
+
+nwsapi@^2.2.0:
+ version "2.2.5"
+ resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.5.tgz#a52744c61b3889dd44b0a158687add39b8d935e2"
+ integrity sha512-6xpotnECFy/og7tKSBVmUNft7J3jyXAka4XvG6AUhFWRz+Q/Ljus7znJAA3bxColfQLdS+XsjoodtJfCgeTEFQ==
+
+object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+ integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
+
+object-hash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
+ integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
+
+object-inspect@^1.12.3, object-inspect@^1.9.0:
+ version "1.12.3"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
+ integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
+
+object-is@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac"
+ integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+
+object-keys@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
+ integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
+
+object.assign@^4.1.3, object.assign@^4.1.4:
+ version "4.1.4"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f"
+ integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ has-symbols "^1.0.3"
+ object-keys "^1.1.1"
+
+object.entries@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.6.tgz#9737d0e5b8291edd340a3e3264bb8a3b00d5fa23"
+ integrity sha512-leTPzo4Zvg3pmbQ3rDK69Rl8GQvIqMWubrkxONG9/ojtFE2rD9fjMKfSI5BxW3osRH1m6VdzmqK8oAY9aT4x5w==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
+object.fromentries@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.6.tgz#cdb04da08c539cffa912dcd368b886e0904bfa73"
+ integrity sha512-VciD13dswC4j1Xt5394WR4MzmAQmlgN72phd/riNp9vtD7tp4QQWJ0R4wvclXcafgcYK8veHRed2W6XeGBvcfg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
+object.getownpropertydescriptors@^2.1.0:
+ version "2.1.6"
+ resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz#5e5c384dd209fa4efffead39e3a0512770ccc312"
+ integrity sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ==
+ dependencies:
+ array.prototype.reduce "^1.0.5"
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.21.2"
+ safe-array-concat "^1.0.0"
+
+object.hasown@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.2.tgz#f919e21fad4eb38a57bc6345b3afd496515c3f92"
+ integrity sha512-B5UIT3J1W+WuWIU55h0mjlwaqxiE5vYENJXIXZ4VFe05pNYrkKuK0U/6aFcb0pKywYJh7IhfoqUfKVmrJJHZHw==
+ dependencies:
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
+object.values@^1.1.0, object.values@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.6.tgz#4abbaa71eba47d63589d402856f908243eea9b1d"
+ integrity sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
+obuf@^1.0.0, obuf@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
+ integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
+
+on-finished@2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
+ integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
+ dependencies:
+ ee-first "1.1.1"
+
+on-headers@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
+ integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
+
+once@^1.3.0, once@^1.3.1, once@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+once@~1.3.0:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20"
+ integrity sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w==
+ dependencies:
+ wrappy "1"
+
+onetime@^5.1.0, onetime@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
+ integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
+ dependencies:
+ mimic-fn "^2.1.0"
+
+open@^8.0.9, open@^8.4.0:
+ version "8.4.2"
+ resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9"
+ integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==
+ dependencies:
+ define-lazy-prop "^2.0.0"
+ is-docker "^2.1.1"
+ is-wsl "^2.2.0"
+
+optionator@^0.8.1:
+ version "0.8.3"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
+ integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
+ dependencies:
+ deep-is "~0.1.3"
+ fast-levenshtein "~2.0.6"
+ levn "~0.3.0"
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+ word-wrap "~1.2.3"
+
+optionator@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
+ integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
+ 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"
+
+ospath@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b"
+ integrity sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==
+
+p-limit@^2.0.0, p-limit@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
+p-limit@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
+p-locate@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+ integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+ dependencies:
+ p-limit "^2.0.0"
+
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
+p-map@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
+ integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
+ dependencies:
+ aggregate-error "^3.0.0"
+
+p-retry@^4.5.0:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16"
+ integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==
+ dependencies:
+ "@types/retry" "0.12.0"
+ retry "^0.13.1"
+
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+papaparse@^5.4.1:
+ version "5.4.1"
+ resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.4.1.tgz#f45c0f871853578bd3a30f92d96fdcfb6ebea127"
+ integrity sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw==
+
+param-case@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5"
+ integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==
+ dependencies:
+ dot-case "^3.0.4"
+ tslib "^2.0.3"
+
+parent-module@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
+ integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+ dependencies:
+ callsites "^3.0.0"
+
+parenthesis@^3.1.5:
+ version "3.1.8"
+ resolved "https://registry.yarnpkg.com/parenthesis/-/parenthesis-3.1.8.tgz#3457fccb8f05db27572b841dad9d2630b912f125"
+ integrity sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw==
+
+parse-json@^5.0.0, parse-json@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
+ integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ error-ex "^1.3.1"
+ json-parse-even-better-errors "^2.3.0"
+ lines-and-columns "^1.1.6"
+
+parse-rect@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/parse-rect/-/parse-rect-1.2.0.tgz#e0a5b0dbaaaee637a0a1eb9779969e19399d8dec"
+ integrity sha512-4QZ6KYbnE6RTwg9E0HpLchUM9EZt6DnDxajFZZDSV4p/12ZJEvPO702DZpGvRYEPo00yKDys7jASi+/w7aO8LA==
+ dependencies:
+ pick-by-alias "^1.2.0"
+
+parse-svg-path@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/parse-svg-path/-/parse-svg-path-0.1.2.tgz#7a7ec0d1eb06fa5325c7d3e009b859a09b5d49eb"
+ integrity sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==
+
+parse-unit@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/parse-unit/-/parse-unit-1.0.1.tgz#7e1bb6d5bef3874c28e392526a2541170291eecf"
+ integrity sha512-hrqldJHokR3Qj88EIlV/kAyAi/G5R2+R56TBANxNMy0uPlYcttx0jnMW6Yx5KsKPSbC3KddM/7qQm3+0wEXKxg==
+
+parse5@6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
+ integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
+
+parseurl@~1.3.2, parseurl@~1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
+ integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+
+pascal-case@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb"
+ integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==
+ dependencies:
+ no-case "^3.0.4"
+ tslib "^2.0.3"
+
+path-exists@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+ integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==
+
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-key@^3.0.0, path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+path-to-regexp@0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+ integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+pause-stream@0.0.11:
+ version "0.0.11"
+ resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445"
+ integrity sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==
+ dependencies:
+ through "~2.3"
+
+pbf@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/pbf/-/pbf-3.2.1.tgz#b4c1b9e72af966cd82c6531691115cc0409ffe2a"
+ integrity sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==
+ dependencies:
+ ieee754 "^1.1.12"
+ resolve-protobuf-schema "^2.1.0"
+
+pend@~1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
+ integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
+
+performance-now@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
+ integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==
+
+pick-by-alias@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/pick-by-alias/-/pick-by-alias-1.2.0.tgz#5f7cb2b1f21a6e1e884a0c87855aa4a37361107b"
+ integrity sha512-ESj2+eBxhGrcA1azgHs7lARG5+5iLakc/6nlfbpjcLl00HuuUOIuORhYXN4D1HfvMSKuVtFQjAlnwi1JHEeDIw==
+
+picocolors@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f"
+ integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==
+
+picocolors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
+ integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+pify@^2.2.0, pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+ integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
+
+pirates@^4.0.1, pirates@^4.0.4:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
+ integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==
+
+pkg-dir@^4.1.0, pkg-dir@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
+ integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
+ dependencies:
+ find-up "^4.0.0"
+
+pkg-up@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5"
+ integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==
+ dependencies:
+ find-up "^3.0.0"
+
+plotly.js@^2.23.2:
+ version "2.24.2"
+ resolved "https://registry.yarnpkg.com/plotly.js/-/plotly.js-2.24.2.tgz#2145028c48c6527f2069b2ff4a6f1fdc616473a8"
+ integrity sha512-4Sx0bjEO2K8kdt0lvsne7/b2bc9h45SVEDGoA7hnoyZ6tU58aGMJTwXl+nmbE7P1jTVaPF3FmBy7w0NUCR1qtQ==
+ dependencies:
+ "@plotly/d3" "3.8.1"
+ "@plotly/d3-sankey" "0.7.2"
+ "@plotly/d3-sankey-circular" "0.33.1"
+ "@turf/area" "^6.4.0"
+ "@turf/bbox" "^6.4.0"
+ "@turf/centroid" "^6.0.2"
+ canvas-fit "^1.5.0"
+ color-alpha "1.0.4"
+ color-normalize "1.5.0"
+ color-parse "1.3.8"
+ color-rgba "2.1.1"
+ country-regex "^1.1.0"
+ d3-force "^1.2.1"
+ d3-format "^1.4.5"
+ d3-geo "^1.12.1"
+ d3-geo-projection "^2.9.0"
+ d3-hierarchy "^1.1.9"
+ d3-interpolate "^3.0.1"
+ d3-time "^1.1.0"
+ d3-time-format "^2.2.3"
+ fast-isnumeric "^1.1.4"
+ gl-mat4 "^1.2.0"
+ gl-text "^1.3.1"
+ glslify "^7.1.1"
+ has-hover "^1.0.1"
+ has-passive-events "^1.0.0"
+ is-mobile "^4.0.0"
+ mapbox-gl "1.10.1"
+ mouse-change "^1.4.0"
+ mouse-event-offset "^3.0.2"
+ mouse-wheel "^1.2.0"
+ native-promise-only "^0.8.1"
+ parse-svg-path "^0.1.2"
+ point-in-polygon "^1.1.0"
+ polybooljs "^1.2.0"
+ probe-image-size "^7.2.3"
+ regl "npm:@plotly/regl@^2.1.2"
+ regl-error2d "^2.0.12"
+ regl-line2d "^3.1.2"
+ regl-scatter2d "^3.2.9"
+ regl-splom "^1.0.14"
+ strongly-connected-components "^1.0.1"
+ superscript-text "^1.0.0"
+ svg-path-sdf "^1.1.3"
+ tinycolor2 "^1.4.2"
+ to-px "1.0.1"
+ topojson-client "^3.1.0"
+ webgl-context "^2.2.0"
+ world-calendars "^1.0.3"
+
+point-in-polygon@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/point-in-polygon/-/point-in-polygon-1.1.0.tgz#b0af2616c01bdee341cbf2894df643387ca03357"
+ integrity sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw==
+
+polybooljs@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/polybooljs/-/polybooljs-1.2.0.tgz#b4390c2e079d4c262d3b2504c6288d95ba7a4758"
+ integrity sha512-mKjR5nolISvF+q2BtC1fi/llpxBPTQ3wLWN8+ldzdw2Hocpc8C72ZqnamCM4Z6z+68GVVjkeM01WJegQmZ8MEQ==
+
+postcss-attribute-case-insensitive@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz#03d761b24afc04c09e757e92ff53716ae8ea2741"
+ integrity sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==
+ dependencies:
+ postcss-selector-parser "^6.0.10"
+
+postcss-browser-comments@^4:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz#bcfc86134df5807f5d3c0eefa191d42136b5e72a"
+ integrity sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==
+
+postcss-calc@^8.2.3:
+ version "8.2.4"
+ resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5"
+ integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+ postcss-value-parser "^4.2.0"
+
+postcss-clamp@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-clamp/-/postcss-clamp-4.1.0.tgz#7263e95abadd8c2ba1bd911b0b5a5c9c93e02363"
+ integrity sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-color-functional-notation@^4.2.4:
+ version "4.2.4"
+ resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz#21a909e8d7454d3612d1659e471ce4696f28caec"
+ integrity sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-color-hex-alpha@^8.0.4:
+ version "8.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz#c66e2980f2fbc1a63f5b079663340ce8b55f25a5"
+ integrity sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-color-rebeccapurple@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz#63fdab91d878ebc4dd4b7c02619a0c3d6a56ced0"
+ integrity sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-colormin@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.1.tgz#86c27c26ed6ba00d96c79e08f3ffb418d1d1988f"
+ integrity sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==
+ dependencies:
+ browserslist "^4.21.4"
+ caniuse-api "^3.0.0"
+ colord "^2.9.1"
+ postcss-value-parser "^4.2.0"
+
+postcss-convert-values@^5.1.3:
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz#04998bb9ba6b65aa31035d669a6af342c5f9d393"
+ integrity sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==
+ dependencies:
+ browserslist "^4.21.4"
+ postcss-value-parser "^4.2.0"
+
+postcss-custom-media@^8.0.2:
+ version "8.0.2"
+ resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz#c8f9637edf45fef761b014c024cee013f80529ea"
+ integrity sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-custom-properties@^12.1.10:
+ version "12.1.11"
+ resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz#d14bb9b3989ac4d40aaa0e110b43be67ac7845cf"
+ integrity sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-custom-selectors@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz#1ab4684d65f30fed175520f82d223db0337239d9"
+ integrity sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==
+ dependencies:
+ postcss-selector-parser "^6.0.4"
+
+postcss-dir-pseudo-class@^6.0.5:
+ version "6.0.5"
+ resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz#2bf31de5de76added44e0a25ecf60ae9f7c7c26c"
+ integrity sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==
+ dependencies:
+ postcss-selector-parser "^6.0.10"
+
+postcss-discard-comments@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696"
+ integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==
+
+postcss-discard-duplicates@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848"
+ integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==
+
+postcss-discard-empty@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c"
+ integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==
+
+postcss-discard-overridden@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e"
+ integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==
+
+postcss-double-position-gradients@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz#b96318fdb477be95997e86edd29c6e3557a49b91"
+ integrity sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties" "^1.1.0"
+ postcss-value-parser "^4.2.0"
+
+postcss-env-function@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-4.0.6.tgz#7b2d24c812f540ed6eda4c81f6090416722a8e7a"
+ integrity sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-flexbugs-fixes@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz#2028e145313074fc9abe276cb7ca14e5401eb49d"
+ integrity sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==
+
+postcss-focus-visible@^6.0.4:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz#50c9ea9afa0ee657fb75635fabad25e18d76bf9e"
+ integrity sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+
+postcss-focus-within@^5.0.4:
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz#5b1d2ec603195f3344b716c0b75f61e44e8d2e20"
+ integrity sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+
+postcss-font-variant@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz#efd59b4b7ea8bb06127f2d031bfbb7f24d32fa66"
+ integrity sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==
+
+postcss-gap-properties@^3.0.5:
+ version "3.0.5"
+ resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz#f7e3cddcf73ee19e94ccf7cb77773f9560aa2fff"
+ integrity sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==
+
+postcss-image-set-function@^4.0.7:
+ version "4.0.7"
+ resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz#08353bd756f1cbfb3b6e93182c7829879114481f"
+ integrity sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-import@^15.1.0:
+ version "15.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70"
+ integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==
+ dependencies:
+ postcss-value-parser "^4.0.0"
+ read-cache "^1.0.0"
+ resolve "^1.1.7"
+
+postcss-initial@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-4.0.1.tgz#529f735f72c5724a0fb30527df6fb7ac54d7de42"
+ integrity sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==
+
+postcss-js@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2"
+ integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==
+ dependencies:
+ camelcase-css "^2.0.1"
+
+postcss-lab-function@^4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz#6fe4c015102ff7cd27d1bd5385582f67ebdbdc98"
+ integrity sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties" "^1.1.0"
+ postcss-value-parser "^4.2.0"
+
+postcss-load-config@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.1.tgz#152383f481c2758274404e4962743191d73875bd"
+ integrity sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==
+ dependencies:
+ lilconfig "^2.0.5"
+ yaml "^2.1.1"
+
+postcss-loader@^6.2.1:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef"
+ integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==
+ dependencies:
+ cosmiconfig "^7.0.0"
+ klona "^2.0.5"
+ semver "^7.3.5"
+
+postcss-logical@^5.0.4:
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-5.0.4.tgz#ec75b1ee54421acc04d5921576b7d8db6b0e6f73"
+ integrity sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==
+
+postcss-media-minmax@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz#7140bddec173e2d6d657edbd8554a55794e2a5b5"
+ integrity sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==
+
+postcss-merge-longhand@^5.1.7:
+ version "5.1.7"
+ resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz#24a1bdf402d9ef0e70f568f39bdc0344d568fb16"
+ integrity sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+ stylehacks "^5.1.1"
+
+postcss-merge-rules@^5.1.4:
+ version "5.1.4"
+ resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz#2f26fa5cacb75b1402e213789f6766ae5e40313c"
+ integrity sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==
+ dependencies:
+ browserslist "^4.21.4"
+ caniuse-api "^3.0.0"
+ cssnano-utils "^3.1.0"
+ postcss-selector-parser "^6.0.5"
+
+postcss-minify-font-values@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b"
+ integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-minify-gradients@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c"
+ integrity sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==
+ dependencies:
+ colord "^2.9.1"
+ cssnano-utils "^3.1.0"
+ postcss-value-parser "^4.2.0"
+
+postcss-minify-params@^5.1.4:
+ version "5.1.4"
+ resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz#c06a6c787128b3208b38c9364cfc40c8aa5d7352"
+ integrity sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==
+ dependencies:
+ browserslist "^4.21.4"
+ cssnano-utils "^3.1.0"
+ postcss-value-parser "^4.2.0"
+
+postcss-minify-selectors@^5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6"
+ integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==
+ dependencies:
+ postcss-selector-parser "^6.0.5"
+
+postcss-modules-extract-imports@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d"
+ integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==
+
+postcss-modules-local-by-default@^4.0.3:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz#b08eb4f083050708998ba2c6061b50c2870ca524"
+ integrity sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==
+ dependencies:
+ icss-utils "^5.0.0"
+ postcss-selector-parser "^6.0.2"
+ postcss-value-parser "^4.1.0"
+
+postcss-modules-scope@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06"
+ integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==
+ dependencies:
+ postcss-selector-parser "^6.0.4"
+
+postcss-modules-values@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c"
+ integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==
+ dependencies:
+ icss-utils "^5.0.0"
+
+postcss-nested@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c"
+ integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==
+ dependencies:
+ postcss-selector-parser "^6.0.11"
+
+postcss-nesting@^10.2.0:
+ version "10.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-10.2.0.tgz#0b12ce0db8edfd2d8ae0aaf86427370b898890be"
+ integrity sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==
+ dependencies:
+ "@csstools/selector-specificity" "^2.0.0"
+ postcss-selector-parser "^6.0.10"
+
+postcss-normalize-charset@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed"
+ integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==
+
+postcss-normalize-display-values@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8"
+ integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-positions@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92"
+ integrity sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-repeat-style@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2"
+ integrity sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-string@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228"
+ integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-timing-functions@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb"
+ integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-unicode@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz#f67297fca3fea7f17e0d2caa40769afc487aa030"
+ integrity sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==
+ dependencies:
+ browserslist "^4.21.4"
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-url@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc"
+ integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==
+ dependencies:
+ normalize-url "^6.0.1"
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-whitespace@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa"
+ integrity sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-normalize/-/postcss-normalize-10.0.1.tgz#464692676b52792a06b06880a176279216540dd7"
+ integrity sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==
+ dependencies:
+ "@csstools/normalize.css" "*"
+ postcss-browser-comments "^4"
+ sanitize.css "*"
+
+postcss-opacity-percentage@^1.1.2:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz#5b89b35551a556e20c5d23eb5260fbfcf5245da6"
+ integrity sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==
+
+postcss-ordered-values@^5.1.3:
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38"
+ integrity sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==
+ dependencies:
+ cssnano-utils "^3.1.0"
+ postcss-value-parser "^4.2.0"
+
+postcss-overflow-shorthand@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz#7ed6486fec44b76f0eab15aa4866cda5d55d893e"
+ integrity sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-page-break@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-3.0.4.tgz#7fbf741c233621622b68d435babfb70dd8c1ee5f"
+ integrity sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==
+
+postcss-place@^7.0.5:
+ version "7.0.5"
+ resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-7.0.5.tgz#95dbf85fd9656a3a6e60e832b5809914236986c4"
+ integrity sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-preset-env@^7.0.1:
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz#2a50f5e612c3149cc7af75634e202a5b2ad4f1e2"
+ integrity sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==
+ dependencies:
+ "@csstools/postcss-cascade-layers" "^1.1.1"
+ "@csstools/postcss-color-function" "^1.1.1"
+ "@csstools/postcss-font-format-keywords" "^1.0.1"
+ "@csstools/postcss-hwb-function" "^1.0.2"
+ "@csstools/postcss-ic-unit" "^1.0.1"
+ "@csstools/postcss-is-pseudo-class" "^2.0.7"
+ "@csstools/postcss-nested-calc" "^1.0.0"
+ "@csstools/postcss-normalize-display-values" "^1.0.1"
+ "@csstools/postcss-oklab-function" "^1.1.1"
+ "@csstools/postcss-progressive-custom-properties" "^1.3.0"
+ "@csstools/postcss-stepped-value-functions" "^1.0.1"
+ "@csstools/postcss-text-decoration-shorthand" "^1.0.0"
+ "@csstools/postcss-trigonometric-functions" "^1.0.2"
+ "@csstools/postcss-unset-value" "^1.0.2"
+ autoprefixer "^10.4.13"
+ browserslist "^4.21.4"
+ css-blank-pseudo "^3.0.3"
+ css-has-pseudo "^3.0.4"
+ css-prefers-color-scheme "^6.0.3"
+ cssdb "^7.1.0"
+ postcss-attribute-case-insensitive "^5.0.2"
+ postcss-clamp "^4.1.0"
+ postcss-color-functional-notation "^4.2.4"
+ postcss-color-hex-alpha "^8.0.4"
+ postcss-color-rebeccapurple "^7.1.1"
+ postcss-custom-media "^8.0.2"
+ postcss-custom-properties "^12.1.10"
+ postcss-custom-selectors "^6.0.3"
+ postcss-dir-pseudo-class "^6.0.5"
+ postcss-double-position-gradients "^3.1.2"
+ postcss-env-function "^4.0.6"
+ postcss-focus-visible "^6.0.4"
+ postcss-focus-within "^5.0.4"
+ postcss-font-variant "^5.0.0"
+ postcss-gap-properties "^3.0.5"
+ postcss-image-set-function "^4.0.7"
+ postcss-initial "^4.0.1"
+ postcss-lab-function "^4.2.1"
+ postcss-logical "^5.0.4"
+ postcss-media-minmax "^5.0.0"
+ postcss-nesting "^10.2.0"
+ postcss-opacity-percentage "^1.1.2"
+ postcss-overflow-shorthand "^3.0.4"
+ postcss-page-break "^3.0.4"
+ postcss-place "^7.0.5"
+ postcss-pseudo-class-any-link "^7.1.6"
+ postcss-replace-overflow-wrap "^4.0.0"
+ postcss-selector-not "^6.0.1"
+ postcss-value-parser "^4.2.0"
+
+postcss-pseudo-class-any-link@^7.1.6:
+ version "7.1.6"
+ resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz#2693b221902da772c278def85a4d9a64b6e617ab"
+ integrity sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==
+ dependencies:
+ postcss-selector-parser "^6.0.10"
+
+postcss-reduce-initial@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz#798cd77b3e033eae7105c18c9d371d989e1382d6"
+ integrity sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==
+ dependencies:
+ browserslist "^4.21.4"
+ caniuse-api "^3.0.0"
+
+postcss-reduce-transforms@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9"
+ integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-replace-overflow-wrap@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz#d2df6bed10b477bf9c52fab28c568b4b29ca4319"
+ integrity sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==
+
+postcss-selector-not@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz#8f0a709bf7d4b45222793fc34409be407537556d"
+ integrity sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==
+ dependencies:
+ postcss-selector-parser "^6.0.10"
+
+postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9:
+ version "6.0.13"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz#d05d8d76b1e8e173257ef9d60b706a8e5e99bf1b"
+ integrity sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-svgo@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d"
+ integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+ svgo "^2.7.0"
+
+postcss-unique-selectors@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6"
+ integrity sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==
+ dependencies:
+ postcss-selector-parser "^6.0.5"
+
+postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
+ integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
+
+postcss@^7.0.35:
+ version "7.0.39"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309"
+ integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==
+ dependencies:
+ picocolors "^0.2.1"
+ source-map "^0.6.1"
+
+postcss@^8.3.5, postcss@^8.4.21, postcss@^8.4.23, postcss@^8.4.4:
+ version "8.4.24"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.24.tgz#f714dba9b2284be3cc07dbd2fc57ee4dc972d2df"
+ integrity sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==
+ dependencies:
+ nanoid "^3.3.6"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.2"
+
+potpack@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.2.tgz#23b99e64eb74f5741ffe7656b5b5c4ddce8dfc14"
+ integrity sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==
+
+prelude-ls@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+ integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+
+prelude-ls@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+ integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==
+
+pretty-bytes@^5.3.0, pretty-bytes@^5.4.1, pretty-bytes@^5.6.0:
+ version "5.6.0"
+ resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
+ integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
+
+pretty-error@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6"
+ integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==
+ dependencies:
+ lodash "^4.17.20"
+ renderkid "^3.0.0"
+
+pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
+ integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
+ dependencies:
+ ansi-regex "^5.0.1"
+ ansi-styles "^5.0.0"
+ react-is "^17.0.1"
+
+pretty-format@^28.1.3:
+ version "28.1.3"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.3.tgz#c9fba8cedf99ce50963a11b27d982a9ae90970d5"
+ integrity sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==
+ dependencies:
+ "@jest/schemas" "^28.1.3"
+ ansi-regex "^5.0.1"
+ ansi-styles "^5.0.0"
+ react-is "^18.0.0"
+
+pretty-format@^29.0.0, pretty-format@^29.5.0:
+ version "29.5.0"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.5.0.tgz#283134e74f70e2e3e7229336de0e4fce94ccde5a"
+ integrity sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==
+ dependencies:
+ "@jest/schemas" "^29.4.3"
+ ansi-styles "^5.0.0"
+ react-is "^18.0.0"
+
+probe-image-size@^7.2.3:
+ version "7.2.3"
+ resolved "https://registry.yarnpkg.com/probe-image-size/-/probe-image-size-7.2.3.tgz#d49c64be540ec8edea538f6f585f65a9b3ab4309"
+ integrity sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==
+ dependencies:
+ lodash.merge "^4.6.2"
+ needle "^2.5.2"
+ stream-parser "~0.3.1"
+
+process-nextick-args@~2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
+ integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+
+promise@^8.1.0:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/promise/-/promise-8.3.0.tgz#8cb333d1edeb61ef23869fbb8a4ea0279ab60e0a"
+ integrity sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==
+ dependencies:
+ asap "~2.0.6"
+
+prompts@^2.0.1, prompts@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
+ integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
+ dependencies:
+ kleur "^3.0.3"
+ sisteransi "^1.0.5"
+
+prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
+ version "15.8.1"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
+ integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.13.1"
+
+protocol-buffers-schema@^3.3.1:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz#77bc75a48b2ff142c1ad5b5b90c94cd0fa2efd03"
+ integrity sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw==
+
+proxy-addr@~2.0.7:
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
+ integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
+ dependencies:
+ forwarded "0.2.0"
+ ipaddr.js "1.9.1"
+
+proxy-from-env@1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee"
+ integrity sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==
+
+ps-tree@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/ps-tree/-/ps-tree-1.2.0.tgz#5e7425b89508736cdd4f2224d028f7bb3f722ebd"
+ integrity sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==
+ dependencies:
+ event-stream "=3.3.4"
+
+psl@^1.1.28, psl@^1.1.33:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
+ integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==
+
+pump@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
+ integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==
+ dependencies:
+ end-of-stream "^1.1.0"
+ once "^1.3.1"
+
+punycode@^2.1.0, punycode@^2.1.1:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f"
+ integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==
+
+q@^1.1.2:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
+ integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
+
+qs@6.11.0:
+ version "6.11.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
+ integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
+ dependencies:
+ side-channel "^1.0.4"
+
+qs@~6.10.3:
+ version "6.10.5"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.5.tgz#974715920a80ff6a262264acd2c7e6c2a53282b4"
+ integrity sha512-O5RlPh0VFtR78y79rgcgKK4wbAI0C5zGVLztOIdpWX6ep368q5Hv6XRxDvXuZ9q3C6v+e3n8UfZZJw7IIG27eQ==
+ dependencies:
+ side-channel "^1.0.4"
+
+querystringify@^2.1.1:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
+ integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+quickselect@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/quickselect/-/quickselect-2.0.0.tgz#f19680a486a5eefb581303e023e98faaf25dd018"
+ integrity sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==
+
+raf@^3.4.1:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
+ integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
+ dependencies:
+ performance-now "^2.1.0"
+
+randombytes@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+ dependencies:
+ safe-buffer "^5.1.0"
+
+range-parser@^1.2.1, range-parser@~1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
+ integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
+
+raw-body@2.5.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
+ integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
+ dependencies:
+ bytes "3.1.2"
+ http-errors "2.0.0"
+ iconv-lite "0.4.24"
+ unpipe "1.0.0"
+
+react-app-polyfill@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz#95221e0a9bd259e5ca6b177c7bb1cb6768f68fd7"
+ integrity sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==
+ dependencies:
+ core-js "^3.19.2"
+ object-assign "^4.1.1"
+ promise "^8.1.0"
+ raf "^3.4.1"
+ regenerator-runtime "^0.13.9"
+ whatwg-fetch "^3.6.2"
+
+react-dev-utils@^12.0.1:
+ version "12.0.1"
+ resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73"
+ integrity sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==
+ dependencies:
+ "@babel/code-frame" "^7.16.0"
+ address "^1.1.2"
+ browserslist "^4.18.1"
+ chalk "^4.1.2"
+ cross-spawn "^7.0.3"
+ detect-port-alt "^1.1.6"
+ escape-string-regexp "^4.0.0"
+ filesize "^8.0.6"
+ find-up "^5.0.0"
+ fork-ts-checker-webpack-plugin "^6.5.0"
+ global-modules "^2.0.0"
+ globby "^11.0.4"
+ gzip-size "^6.0.0"
+ immer "^9.0.7"
+ is-root "^2.1.0"
+ loader-utils "^3.2.0"
+ open "^8.4.0"
+ pkg-up "^3.1.0"
+ prompts "^2.4.2"
+ react-error-overlay "^6.0.11"
+ recursive-readdir "^2.2.2"
+ shell-quote "^1.7.3"
+ strip-ansi "^6.0.1"
+ text-table "^0.2.0"
+
+react-dom@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
+ integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
+ dependencies:
+ loose-envify "^1.1.0"
+ scheduler "^0.23.0"
+
+react-error-overlay@^6.0.11:
+ version "6.0.11"
+ resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb"
+ integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==
+
+react-fast-compare@^3.0.1:
+ version "3.2.2"
+ resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"
+ integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
+
+react-hook-form@^7.43.9:
+ version "7.47.0"
+ resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.47.0.tgz#a42f07266bd297ddf1f914f08f4b5f9783262f31"
+ integrity sha512-F/TroLjTICipmHeFlMrLtNLceO2xr1jU3CyiNla5zdwsGUGu2UOxxR4UyJgLlhMwLW/Wzp4cpJ7CPfgJIeKdSg==
+
+react-is@^16.13.1, react-is@^16.7.0:
+ version "16.13.1"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
+ integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+
+react-is@^17.0.1:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
+ integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
+
+react-is@^18.0.0, react-is@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
+ integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
+
+react-player@^2.13.0:
+ version "2.13.0"
+ resolved "https://registry.yarnpkg.com/react-player/-/react-player-2.13.0.tgz#b6fb252bf70574608ac711f6c83d7057c8fb0c14"
+ integrity sha512-gkY7ZdbVFztlKFFhCPcnDrFQm+L399b8fhWsKatZ+b2wpKJwfUHBXQFMRxqYQGT0ic1/wQ7D7EZEWy7ZBqk2pw==
+ dependencies:
+ deepmerge "^4.0.0"
+ load-script "^1.0.0"
+ memoize-one "^5.1.1"
+ prop-types "^15.7.2"
+ react-fast-compare "^3.0.1"
+
+react-plotly.js@^2.6.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/react-plotly.js/-/react-plotly.js-2.6.0.tgz#ad6b68ee64f1b5cfa142ee92c59687f9c2c09209"
+ integrity sha512-g93xcyhAVCSt9kV1svqG1clAEdL6k3U+jjuSzfTV7owaSU9Go6Ph8bl25J+jKfKvIGAEYpe4qj++WHJuc9IaeA==
+ dependencies:
+ prop-types "^15.8.1"
+
+react-redux@^8.0.1:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-8.1.1.tgz#8e740f3fd864a4cd0de5ba9cdc8ad39cc9e7c81a"
+ integrity sha512-5W0QaKtEhj+3bC0Nj0NkqkhIv8gLADH/2kYFMTHxCVqQILiWzLv6MaLuV5wJU3BQEdHKzTfcvPN0WMS6SC1oyA==
+ dependencies:
+ "@babel/runtime" "^7.12.1"
+ "@types/hoist-non-react-statics" "^3.3.1"
+ "@types/use-sync-external-store" "^0.0.3"
+ hoist-non-react-statics "^3.3.2"
+ react-is "^18.0.0"
+ use-sync-external-store "^1.0.0"
+
+react-refresh@^0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
+ integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
+
+react-scripts@5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-5.0.1.tgz#6285dbd65a8ba6e49ca8d651ce30645a6d980003"
+ integrity sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==
+ dependencies:
+ "@babel/core" "^7.16.0"
+ "@pmmmwh/react-refresh-webpack-plugin" "^0.5.3"
+ "@svgr/webpack" "^5.5.0"
+ babel-jest "^27.4.2"
+ babel-loader "^8.2.3"
+ babel-plugin-named-asset-import "^0.3.8"
+ babel-preset-react-app "^10.0.1"
+ bfj "^7.0.2"
+ browserslist "^4.18.1"
+ camelcase "^6.2.1"
+ case-sensitive-paths-webpack-plugin "^2.4.0"
+ css-loader "^6.5.1"
+ css-minimizer-webpack-plugin "^3.2.0"
+ dotenv "^10.0.0"
+ dotenv-expand "^5.1.0"
+ eslint "^8.3.0"
+ eslint-config-react-app "^7.0.1"
+ eslint-webpack-plugin "^3.1.1"
+ file-loader "^6.2.0"
+ fs-extra "^10.0.0"
+ html-webpack-plugin "^5.5.0"
+ identity-obj-proxy "^3.0.0"
+ jest "^27.4.3"
+ jest-resolve "^27.4.2"
+ jest-watch-typeahead "^1.0.0"
+ mini-css-extract-plugin "^2.4.5"
+ postcss "^8.4.4"
+ postcss-flexbugs-fixes "^5.0.2"
+ postcss-loader "^6.2.1"
+ postcss-normalize "^10.0.1"
+ postcss-preset-env "^7.0.1"
+ prompts "^2.4.2"
+ react-app-polyfill "^3.0.0"
+ react-dev-utils "^12.0.1"
+ react-refresh "^0.11.0"
+ resolve "^1.20.0"
+ resolve-url-loader "^4.0.0"
+ sass-loader "^12.3.0"
+ semver "^7.3.5"
+ source-map-loader "^3.0.0"
+ style-loader "^3.3.1"
+ tailwindcss "^3.0.2"
+ terser-webpack-plugin "^5.2.5"
+ webpack "^5.64.4"
+ webpack-dev-server "^4.6.0"
+ webpack-manifest-plugin "^4.0.2"
+ workbox-webpack-plugin "^6.4.1"
+ optionalDependencies:
+ fsevents "^2.3.2"
+
+react-transition-group@^4.4.5:
+ version "4.4.5"
+ resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"
+ integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
+ dependencies:
+ "@babel/runtime" "^7.5.5"
+ dom-helpers "^5.0.1"
+ loose-envify "^1.4.0"
+ prop-types "^15.6.2"
+
+react@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
+ integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
+ dependencies:
+ loose-envify "^1.1.0"
+
+read-cache@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
+ integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
+ dependencies:
+ pify "^2.3.0"
+
+"readable-stream@>=1.0.33-1 <1.1.0-0":
+ version "1.0.34"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
+ integrity sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.1"
+ isarray "0.0.1"
+ string_decoder "~0.10.x"
+
+readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.2.2, readable-stream@^2.3.5, readable-stream@~2.3.6:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
+ integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
+
+readable-stream@^3.0.6:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967"
+ integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==
+ dependencies:
+ inherits "^2.0.3"
+ string_decoder "^1.1.1"
+ util-deprecate "^1.0.1"
+
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
+recursive-readdir@^2.2.2:
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz#e726f328c0d69153bcabd5c322d3195252379372"
+ integrity sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==
+ dependencies:
+ minimatch "^3.0.5"
+
+redent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
+ integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==
+ dependencies:
+ indent-string "^4.0.0"
+ strip-indent "^3.0.0"
+
+redux-thunk@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.2.tgz#b9d05d11994b99f7a91ea223e8b04cf0afa5ef3b"
+ integrity sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==
+
+redux@^4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
+ integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==
+ dependencies:
+ "@babel/runtime" "^7.9.2"
+
+regenerate-unicode-properties@^10.1.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c"
+ integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ==
+ dependencies:
+ regenerate "^1.4.2"
+
+regenerate@^1.4.2:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
+ integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
+
+regenerator-runtime@^0.13.11, regenerator-runtime@^0.13.9:
+ version "0.13.11"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
+ integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
+
+regenerator-transform@^0.15.1:
+ version "0.15.1"
+ resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56"
+ integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg==
+ dependencies:
+ "@babel/runtime" "^7.8.4"
+
+regex-parser@^2.2.11:
+ version "2.2.11"
+ resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58"
+ integrity sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==
+
+regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb"
+ integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ functions-have-names "^1.2.3"
+
+regexpu-core@^5.3.1:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b"
+ integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==
+ dependencies:
+ "@babel/regjsgen" "^0.8.0"
+ regenerate "^1.4.2"
+ regenerate-unicode-properties "^10.1.0"
+ regjsparser "^0.9.1"
+ unicode-match-property-ecmascript "^2.0.0"
+ unicode-match-property-value-ecmascript "^2.1.0"
+
+regjsparser@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709"
+ integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==
+ dependencies:
+ jsesc "~0.5.0"
+
+regl-error2d@^2.0.12:
+ version "2.0.12"
+ resolved "https://registry.yarnpkg.com/regl-error2d/-/regl-error2d-2.0.12.tgz#3b976e13fe641d5242a154fcacc80aecfa0a9881"
+ integrity sha512-r7BUprZoPO9AbyqM5qlJesrSRkl+hZnVKWKsVp7YhOl/3RIpi4UDGASGJY0puQ96u5fBYw/OlqV24IGcgJ0McA==
+ dependencies:
+ array-bounds "^1.0.1"
+ color-normalize "^1.5.0"
+ flatten-vertex-data "^1.0.2"
+ object-assign "^4.1.1"
+ pick-by-alias "^1.2.0"
+ to-float32 "^1.1.0"
+ update-diff "^1.1.0"
+
+regl-line2d@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/regl-line2d/-/regl-line2d-3.1.2.tgz#2bedef7f44c1f7fae75c90f9918258723ca84c1c"
+ integrity sha512-nmT7WWS/WxmXAQMkgaMKWXaVmwJ65KCrjbqHGOUjjqQi6shfT96YbBOvelXwO9hG7/hjvbzjtQ2UO0L3e7YaXQ==
+ dependencies:
+ array-bounds "^1.0.1"
+ array-find-index "^1.0.2"
+ array-normalize "^1.1.4"
+ color-normalize "^1.5.0"
+ earcut "^2.1.5"
+ es6-weak-map "^2.0.3"
+ flatten-vertex-data "^1.0.2"
+ glslify "^7.0.0"
+ object-assign "^4.1.1"
+ parse-rect "^1.2.0"
+ pick-by-alias "^1.2.0"
+ to-float32 "^1.1.0"
+
+regl-scatter2d@^3.2.3, regl-scatter2d@^3.2.9:
+ version "3.2.9"
+ resolved "https://registry.yarnpkg.com/regl-scatter2d/-/regl-scatter2d-3.2.9.tgz#cd27b014c355e80d96fb2f273b563fd8f1b094f0"
+ integrity sha512-PNrXs+xaCClKpiB2b3HZ2j3qXQXhC5kcTh/Nfgx9rLO0EpEhab0BSQDqAsbdbpdf+pSHSJvbgitB7ulbGeQ+Fg==
+ dependencies:
+ "@plotly/point-cluster" "^3.1.9"
+ array-range "^1.0.1"
+ array-rearrange "^2.2.2"
+ clamp "^1.0.1"
+ color-id "^1.1.0"
+ color-normalize "^1.5.0"
+ color-rgba "^2.1.1"
+ flatten-vertex-data "^1.0.2"
+ glslify "^7.0.0"
+ is-iexplorer "^1.0.0"
+ object-assign "^4.1.1"
+ parse-rect "^1.2.0"
+ pick-by-alias "^1.2.0"
+ to-float32 "^1.1.0"
+ update-diff "^1.1.0"
+
+regl-splom@^1.0.14:
+ version "1.0.14"
+ resolved "https://registry.yarnpkg.com/regl-splom/-/regl-splom-1.0.14.tgz#58800b7bbd7576aa323499a1966868a6c9ea1456"
+ integrity sha512-OiLqjmPRYbd7kDlHC6/zDf6L8lxgDC65BhC8JirhP4ykrK4x22ZyS+BnY8EUinXKDeMgmpRwCvUmk7BK4Nweuw==
+ dependencies:
+ array-bounds "^1.0.1"
+ array-range "^1.0.1"
+ color-alpha "^1.0.4"
+ flatten-vertex-data "^1.0.2"
+ parse-rect "^1.2.0"
+ pick-by-alias "^1.2.0"
+ raf "^3.4.1"
+ regl-scatter2d "^3.2.3"
+
+regl@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/regl/-/regl-2.1.0.tgz#7dae71e9ff20f29c4f42f510c70cd92ebb6b657c"
+ integrity sha512-oWUce/aVoEvW5l2V0LK7O5KJMzUSKeiOwFuJehzpSFd43dO5spP9r+sSUfhKtsky4u6MCqWJaRL+abzExynfTg==
+
+"regl@npm:@plotly/regl@^2.1.2":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/@plotly/regl/-/regl-2.1.2.tgz#fd31e3e820ed8824d59a67ab5e766bb101b810b6"
+ integrity sha512-Mdk+vUACbQvjd0m/1JJjOOafmkp/EpmHjISsopEz5Av44CBq7rPC05HHNbYGKVyNUF2zmEoBS/TT0pd0SPFFyw==
+
+relateurl@^0.2.7:
+ version "0.2.7"
+ resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
+ integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==
+
+renderkid@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a"
+ integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==
+ dependencies:
+ css-select "^4.1.3"
+ dom-converter "^0.2.0"
+ htmlparser2 "^6.1.0"
+ lodash "^4.17.21"
+ strip-ansi "^6.0.1"
+
+request-progress@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-3.0.0.tgz#4ca754081c7fec63f505e4faa825aa06cd669dbe"
+ integrity sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==
+ dependencies:
+ throttleit "^1.0.0"
+
+require-directory@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+ integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
+
+require-from-string@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+ integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+
+requires-port@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
+ integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
+
+reselect@^4.1.8:
+ version "4.1.8"
+ resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524"
+ integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==
+
+resolve-cwd@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
+ integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
+ dependencies:
+ resolve-from "^5.0.0"
+
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+resolve-from@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
+ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+
+resolve-protobuf-schema@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz#9ca9a9e69cf192bbdaf1006ec1973948aa4a3758"
+ integrity sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==
+ dependencies:
+ protocol-buffers-schema "^3.3.1"
+
+resolve-url-loader@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz#d50d4ddc746bb10468443167acf800dcd6c3ad57"
+ integrity sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==
+ dependencies:
+ adjust-sourcemap-loader "^4.0.0"
+ convert-source-map "^1.7.0"
+ loader-utils "^2.0.0"
+ postcss "^7.0.35"
+ source-map "0.6.1"
+
+resolve.exports@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.1.tgz#05cfd5b3edf641571fd46fa608b610dda9ead999"
+ integrity sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==
+
+resolve@^0.6.1:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46"
+ integrity sha512-UHBY3viPlJKf85YijDUcikKX6tmF4SokIDp518ZDVT92JNDcG5uKIthaT/owt3Sar0lwtOafsQuwrg22/v2Dwg==
+
+resolve@^1.0.0, resolve@^1.1.10, resolve@^1.1.5, resolve@^1.1.7, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.1, resolve@^1.22.2:
+ version "1.22.2"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f"
+ integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==
+ dependencies:
+ is-core-module "^2.11.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+resolve@^2.0.0-next.4:
+ version "2.0.0-next.4"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660"
+ integrity sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==
+ dependencies:
+ is-core-module "^2.9.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+restore-cursor@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
+ integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
+ dependencies:
+ onetime "^5.1.0"
+ signal-exit "^3.0.2"
+
+retry@^0.13.1:
+ version "0.13.1"
+ resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
+ integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rfdc@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b"
+ integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==
+
+right-now@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/right-now/-/right-now-1.0.0.tgz#6e89609deebd7dcdaf8daecc9aea39cf585a0918"
+ integrity sha512-DA8+YS+sMIVpbsuKgy+Z67L9Lxb1p05mNxRpDPNksPDEFir4vmBlUtuN9jkTGn9YMMdlBuK7XQgFiz6ws+yhSg==
+
+rimraf@^3.0.0, rimraf@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+ dependencies:
+ glob "^7.1.3"
+
+rollup-plugin-terser@^7.0.0:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d"
+ integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ jest-worker "^26.2.1"
+ serialize-javascript "^4.0.0"
+ terser "^5.0.0"
+
+rollup@^2.43.1:
+ version "2.79.1"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7"
+ integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+rw@^1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4"
+ integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==
+
+rxjs@^7.5.1, rxjs@^7.8.0:
+ version "7.8.1"
+ resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543"
+ integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==
+ dependencies:
+ tslib "^2.1.0"
+
+safe-array-concat@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060"
+ integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.2.0"
+ has-symbols "^1.0.3"
+ isarray "^2.0.5"
+
+safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+safe-regex-test@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295"
+ integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.3"
+ is-regex "^1.1.4"
+
+"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+ integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+sanitize.css@*:
+ version "13.0.0"
+ resolved "https://registry.yarnpkg.com/sanitize.css/-/sanitize.css-13.0.0.tgz#2675553974b27964c75562ade3bd85d79879f173"
+ integrity sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==
+
+sass-loader@^12.3.0:
+ version "12.6.0"
+ resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.6.0.tgz#5148362c8e2cdd4b950f3c63ac5d16dbfed37bcb"
+ integrity sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==
+ dependencies:
+ klona "^2.0.4"
+ neo-async "^2.6.2"
+
+sax@^1.2.4, sax@~1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+ integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
+saxes@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d"
+ integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==
+ dependencies:
+ xmlchars "^2.2.0"
+
+scheduler@^0.23.0:
+ version "0.23.0"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
+ integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
+ dependencies:
+ loose-envify "^1.1.0"
+
+schema-utils@2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7"
+ integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==
+ dependencies:
+ "@types/json-schema" "^7.0.4"
+ ajv "^6.12.2"
+ ajv-keywords "^3.4.1"
+
+schema-utils@^2.6.5:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
+ integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
+ dependencies:
+ "@types/json-schema" "^7.0.5"
+ ajv "^6.12.4"
+ ajv-keywords "^3.5.2"
+
+schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe"
+ integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==
+ dependencies:
+ "@types/json-schema" "^7.0.8"
+ ajv "^6.12.5"
+ ajv-keywords "^3.5.2"
+
+schema-utils@^4.0.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b"
+ integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ ajv "^8.9.0"
+ ajv-formats "^2.1.1"
+ ajv-keywords "^5.1.0"
+
+select-hose@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
+ integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==
+
+selfsigned@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61"
+ integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ==
+ dependencies:
+ node-forge "^1"
+
+semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
+ integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
+semver@^7.3.2, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8:
+ version "7.5.3"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e"
+ integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ==
+ dependencies:
+ lru-cache "^6.0.0"
+
+send@0.18.0:
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
+ integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
+ dependencies:
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ mime "1.6.0"
+ ms "2.1.3"
+ on-finished "2.4.1"
+ range-parser "~1.2.1"
+ statuses "2.0.1"
+
+serialize-javascript@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
+ integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==
+ dependencies:
+ randombytes "^2.1.0"
+
+serialize-javascript@^6.0.0, serialize-javascript@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.1.tgz#b206efb27c3da0b0ab6b52f48d170b7996458e5c"
+ integrity sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==
+ dependencies:
+ randombytes "^2.1.0"
+
+serve-index@^1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
+ integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==
+ dependencies:
+ accepts "~1.3.4"
+ batch "0.6.1"
+ debug "2.6.9"
+ escape-html "~1.0.3"
+ http-errors "~1.6.2"
+ mime-types "~2.1.17"
+ parseurl "~1.3.2"
+
+serve-static@1.15.0:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
+ integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
+ dependencies:
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ parseurl "~1.3.3"
+ send "0.18.0"
+
+setprototypeof@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+ integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
+
+setprototypeof@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
+ integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
+
+shallow-copy@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/shallow-copy/-/shallow-copy-0.0.1.tgz#415f42702d73d810330292cc5ee86eae1a11a170"
+ integrity sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw==
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+shell-quote@^1.7.3:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680"
+ integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==
+
+side-channel@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
+ integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
+ dependencies:
+ call-bind "^1.0.0"
+ get-intrinsic "^1.0.2"
+ object-inspect "^1.9.0"
+
+signal-exit@^3.0.2, signal-exit@^3.0.3:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
+ integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+
+signum@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/signum/-/signum-1.0.0.tgz#74a7d2bf2a20b40eba16a92b152124f1d559fa77"
+ integrity sha512-yodFGwcyt59XRh7w5W3jPcIQb3Bwi21suEfT7MAWnBX3iCdklJpgDgvGT9o04UonglZN5SNMfJFkHIR/jO8GHw==
+
+sisteransi@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
+ integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
+
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+slash@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7"
+ integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==
+
+slice-ansi@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-3.0.0.tgz#31ddc10930a1b7e0b67b08c96c2f49b77a789787"
+ integrity sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==
+ dependencies:
+ ansi-styles "^4.0.0"
+ astral-regex "^2.0.0"
+ is-fullwidth-code-point "^3.0.0"
+
+slice-ansi@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
+ integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
+ dependencies:
+ ansi-styles "^4.0.0"
+ astral-regex "^2.0.0"
+ is-fullwidth-code-point "^3.0.0"
+
+sockjs@^0.3.24:
+ version "0.3.24"
+ resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce"
+ integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==
+ dependencies:
+ faye-websocket "^0.11.3"
+ uuid "^8.3.2"
+ websocket-driver "^0.7.4"
+
+source-list-map@^2.0.0, source-list-map@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
+ integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
+
+source-map-js@^1.0.1, source-map-js@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
+ integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
+
+source-map-loader@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-3.0.2.tgz#af23192f9b344daa729f6772933194cc5fa54fee"
+ integrity sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==
+ dependencies:
+ abab "^2.0.5"
+ iconv-lite "^0.6.3"
+ source-map-js "^1.0.1"
+
+source-map-support@^0.5.6, source-map-support@~0.5.20:
+ version "0.5.21"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
+ integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+source-map@^0.5.7:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+ integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
+
+source-map@^0.7.3:
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656"
+ integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
+
+source-map@^0.8.0-beta.0:
+ version "0.8.0-beta.0"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11"
+ integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==
+ dependencies:
+ whatwg-url "^7.0.0"
+
+sourcemap-codec@^1.4.8:
+ version "1.4.8"
+ resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
+ integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
+
+spdy-transport@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31"
+ integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==
+ dependencies:
+ debug "^4.1.0"
+ detect-node "^2.0.4"
+ hpack.js "^2.1.6"
+ obuf "^1.1.2"
+ readable-stream "^3.0.6"
+ wbuf "^1.7.3"
+
+spdy@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b"
+ integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==
+ dependencies:
+ debug "^4.1.0"
+ handle-thing "^2.0.0"
+ http-deceiver "^1.2.7"
+ select-hose "^2.0.0"
+ spdy-transport "^3.0.0"
+
+split@0.3:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/split/-/split-0.3.3.tgz#cd0eea5e63a211dfff7eb0f091c4133e2d0dd28f"
+ integrity sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==
+ dependencies:
+ through "2"
+
+sprintf-js@~1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+ integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==
+
+sshpk@^1.14.1:
+ version "1.17.0"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.17.0.tgz#578082d92d4fe612b13007496e543fa0fbcbe4c5"
+ integrity sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==
+ dependencies:
+ asn1 "~0.2.3"
+ assert-plus "^1.0.0"
+ bcrypt-pbkdf "^1.0.0"
+ dashdash "^1.12.0"
+ ecc-jsbn "~0.1.1"
+ getpass "^0.1.1"
+ jsbn "~0.1.0"
+ safer-buffer "^2.0.2"
+ tweetnacl "~0.14.0"
+
+stable@^0.1.8:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
+ integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
+
+stack-trace@0.0.9:
+ version "0.0.9"
+ resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.9.tgz#a8f6eaeca90674c333e7c43953f275b451510695"
+ integrity sha512-vjUc6sfgtgY0dxCdnc40mK6Oftjo9+2K8H/NG81TMhgL392FtiPA9tn9RLyTxXmTLPJPjF3VyzFp6bsWFLisMQ==
+
+stack-utils@^2.0.3:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f"
+ integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==
+ dependencies:
+ escape-string-regexp "^2.0.0"
+
+stackframe@^1.3.4:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310"
+ integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==
+
+start-server-and-test@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/start-server-and-test/-/start-server-and-test-2.0.0.tgz#0644809d63036a8a001efb70582f3e37ebfdd33d"
+ integrity sha512-UqKLw0mJbfrsG1jcRLTUlvuRi9sjNuUiDOLI42r7R5fA9dsFoywAy9DoLXNYys9B886E4RCKb+qM1Gzu96h7DQ==
+ dependencies:
+ arg "^5.0.2"
+ bluebird "3.7.2"
+ check-more-types "2.24.0"
+ debug "4.3.4"
+ execa "5.1.1"
+ lazy-ass "1.6.0"
+ ps-tree "1.2.0"
+ wait-on "7.0.1"
+
+static-eval@^2.0.5:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/static-eval/-/static-eval-2.1.0.tgz#a16dbe54522d7fa5ef1389129d813fd47b148014"
+ integrity sha512-agtxZ/kWSsCkI5E4QifRwsaPs0P0JmZV6dkLz6ILYfFYQGn+5plctanRN+IC8dJRiFkyXHrwEE3W9Wmx67uDbw==
+ dependencies:
+ escodegen "^1.11.1"
+
+statuses@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
+ integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
+
+"statuses@>= 1.4.0 < 2":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+ integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
+
+stop-iteration-iterator@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz#6a60be0b4ee757d1ed5254858ec66b10c49285e4"
+ integrity sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==
+ dependencies:
+ internal-slot "^1.0.4"
+
+stream-combiner@~0.0.4:
+ version "0.0.4"
+ resolved "https://registry.yarnpkg.com/stream-combiner/-/stream-combiner-0.0.4.tgz#4d5e433c185261dde623ca3f44c586bcf5c4ad14"
+ integrity sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==
+ dependencies:
+ duplexer "~0.1.1"
+
+stream-parser@~0.3.1:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/stream-parser/-/stream-parser-0.3.1.tgz#1618548694420021a1182ff0af1911c129761773"
+ integrity sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==
+ dependencies:
+ debug "2"
+
+stream-shift@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d"
+ integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==
+
+string-length@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
+ integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==
+ dependencies:
+ char-regex "^1.0.2"
+ strip-ansi "^6.0.0"
+
+string-length@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/string-length/-/string-length-5.0.1.tgz#3d647f497b6e8e8d41e422f7e0b23bc536c8381e"
+ integrity sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==
+ dependencies:
+ char-regex "^2.0.0"
+ strip-ansi "^7.0.1"
+
+string-natural-compare@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
+ integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
+
+string-split-by@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/string-split-by/-/string-split-by-1.0.0.tgz#53895fb3397ebc60adab1f1e3a131f5372586812"
+ integrity sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A==
+ dependencies:
+ parenthesis "^3.1.5"
+
+string-width@^4.1.0, string-width@^4.2.0:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+string.prototype.matchall@^4.0.6, string.prototype.matchall@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.8.tgz#3bf85722021816dcd1bf38bb714915887ca79fd3"
+ integrity sha512-6zOCOcJ+RJAQshcTvXPHoxoQGONa3e/Lqx90wUA+wEzX78sg5Bo+1tQo4N0pohS0erG9qtCqJDjNCQBjeWVxyg==
+ 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"
+
+string.prototype.trim@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533"
+ integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
+string.prototype.trimend@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533"
+ integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
+string.prototype.trimstart@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4"
+ integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.4"
+
+string_decoder@^1.1.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
+ integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
+ dependencies:
+ safe-buffer "~5.2.0"
+
+string_decoder@~0.10.x:
+ version "0.10.31"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+ integrity sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==
+
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+ dependencies:
+ safe-buffer "~5.1.0"
+
+stringify-object@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629"
+ integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==
+ dependencies:
+ get-own-enumerable-property-symbols "^3.0.0"
+ is-obj "^1.0.1"
+ is-regexp "^1.0.0"
+
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+strip-ansi@^7.0.1:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
+ integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
+ dependencies:
+ ansi-regex "^6.0.1"
+
+strip-bom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+ integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
+
+strip-bom@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
+ integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
+
+strip-comments@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-2.0.1.tgz#4ad11c3fbcac177a67a40ac224ca339ca1c1ba9b"
+ integrity sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==
+
+strip-final-newline@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
+ integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
+
+strip-indent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
+ integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
+ dependencies:
+ min-indent "^1.0.0"
+
+strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+ integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+
+strongly-connected-components@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/strongly-connected-components/-/strongly-connected-components-1.0.1.tgz#0920e2b4df67c8eaee96c6b6234fe29e873dba99"
+ integrity sha512-i0TFx4wPcO0FwX+4RkLJi1MxmcTv90jNZgxMu9XRnMXMeFUY1VJlIoXpZunPUvUUqbCT1pg5PEkFqqpcaElNaA==
+
+style-loader@^3.3.1:
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.3.tgz#bba8daac19930169c0c9c96706749a597ae3acff"
+ integrity sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==
+
+stylehacks@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.1.tgz#7934a34eb59d7152149fa69d6e9e56f2fc34bcc9"
+ integrity sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==
+ dependencies:
+ browserslist "^4.21.4"
+ postcss-selector-parser "^6.0.4"
+
+stylis@4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51"
+ integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==
+
+sucrase@^3.32.0:
+ version "3.32.0"
+ resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.32.0.tgz#c4a95e0f1e18b6847127258a75cf360bc568d4a7"
+ integrity sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.2"
+ commander "^4.0.0"
+ glob "7.1.6"
+ lines-and-columns "^1.1.6"
+ mz "^2.7.0"
+ pirates "^4.0.1"
+ ts-interface-checker "^0.1.9"
+
+supercluster@^7.0.0:
+ version "7.1.5"
+ resolved "https://registry.yarnpkg.com/supercluster/-/supercluster-7.1.5.tgz#65a6ce4a037a972767740614c19051b64b8be5a3"
+ integrity sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==
+ dependencies:
+ kdbush "^3.0.0"
+
+superscript-text@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/superscript-text/-/superscript-text-1.0.0.tgz#e7cb2752567360df50beb0610ce8df3d71d8dfd8"
+ integrity sha512-gwu8l5MtRZ6koO0icVTlmN5pm7Dhh1+Xpe9O4x6ObMAsW+3jPbW14d1DsBq1F4wiI+WOFjXF35pslgec/G8yCQ==
+
+supports-color@^5.3.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+ dependencies:
+ has-flag "^3.0.0"
+
+supports-color@^7.0.0, supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-color@^8.0.0, supports-color@^8.1.1:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-hyperlinks@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz#3943544347c1ff90b15effb03fc14ae45ec10624"
+ integrity sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==
+ dependencies:
+ has-flag "^4.0.0"
+ supports-color "^7.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+svg-arc-to-cubic-bezier@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz#390c450035ae1c4a0104d90650304c3bc814abe6"
+ integrity sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==
+
+svg-parser@^2.0.2:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5"
+ integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==
+
+svg-path-bounds@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/svg-path-bounds/-/svg-path-bounds-1.0.2.tgz#00312f672b08afc432a66ddfbd06db40cec8d0d0"
+ integrity sha512-H4/uAgLWrppIC0kHsb2/dWUYSmb4GE5UqH06uqWBcg6LBjX2fu0A8+JrO2/FJPZiSsNOKZAhyFFgsLTdYUvSqQ==
+ dependencies:
+ abs-svg-path "^0.1.1"
+ is-svg-path "^1.0.1"
+ normalize-svg-path "^1.0.0"
+ parse-svg-path "^0.1.2"
+
+svg-path-sdf@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/svg-path-sdf/-/svg-path-sdf-1.1.3.tgz#92957a31784c0eaf68945472c8dc6bf9e6d126fc"
+ integrity sha512-vJJjVq/R5lSr2KLfVXVAStktfcfa1pNFjFOgyJnzZFXlO/fDZ5DmM8FpnSKKzLPfEYTVeXuVBTHF296TpxuJVg==
+ dependencies:
+ bitmap-sdf "^1.0.0"
+ draw-svg-path "^1.0.0"
+ is-svg-path "^1.0.1"
+ parse-svg-path "^0.1.2"
+ svg-path-bounds "^1.0.1"
+
+svgo@^1.2.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167"
+ integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==
+ dependencies:
+ chalk "^2.4.1"
+ coa "^2.0.2"
+ css-select "^2.0.0"
+ css-select-base-adapter "^0.1.1"
+ css-tree "1.0.0-alpha.37"
+ csso "^4.0.2"
+ js-yaml "^3.13.1"
+ mkdirp "~0.5.1"
+ object.values "^1.1.0"
+ sax "~1.2.4"
+ stable "^0.1.8"
+ unquote "~1.1.1"
+ util.promisify "~1.0.0"
+
+svgo@^2.7.0:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24"
+ integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==
+ dependencies:
+ "@trysound/sax" "0.2.0"
+ commander "^7.2.0"
+ css-select "^4.1.3"
+ css-tree "^1.1.3"
+ csso "^4.2.0"
+ picocolors "^1.0.0"
+ stable "^0.1.8"
+
+symbol-tree@^3.2.4:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
+ integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+
+tailwindcss@^3.0.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.3.2.tgz#2f9e35d715fdf0bbf674d90147a0684d7054a2d3"
+ integrity sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==
+ dependencies:
+ "@alloc/quick-lru" "^5.2.0"
+ arg "^5.0.2"
+ chokidar "^3.5.3"
+ didyoumean "^1.2.2"
+ dlv "^1.1.3"
+ fast-glob "^3.2.12"
+ glob-parent "^6.0.2"
+ is-glob "^4.0.3"
+ jiti "^1.18.2"
+ lilconfig "^2.1.0"
+ micromatch "^4.0.5"
+ normalize-path "^3.0.0"
+ object-hash "^3.0.0"
+ picocolors "^1.0.0"
+ postcss "^8.4.23"
+ postcss-import "^15.1.0"
+ postcss-js "^4.0.1"
+ postcss-load-config "^4.0.1"
+ postcss-nested "^6.0.1"
+ postcss-selector-parser "^6.0.11"
+ postcss-value-parser "^4.2.0"
+ resolve "^1.22.2"
+ sucrase "^3.32.0"
+
+tapable@^1.0.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
+ integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
+
+tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
+ integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+
+temp-dir@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e"
+ integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==
+
+tempy@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.6.0.tgz#65e2c35abc06f1124a97f387b08303442bde59f3"
+ integrity sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==
+ dependencies:
+ is-stream "^2.0.0"
+ temp-dir "^2.0.0"
+ type-fest "^0.16.0"
+ unique-string "^2.0.0"
+
+terminal-link@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994"
+ integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==
+ dependencies:
+ ansi-escapes "^4.2.1"
+ supports-hyperlinks "^2.0.0"
+
+terser-webpack-plugin@^5.2.5, terser-webpack-plugin@^5.3.7:
+ version "5.3.9"
+ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1"
+ integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.17"
+ jest-worker "^27.4.5"
+ schema-utils "^3.1.1"
+ serialize-javascript "^6.0.1"
+ terser "^5.16.8"
+
+terser@^5.0.0, terser@^5.10.0, terser@^5.16.8:
+ version "5.18.1"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-5.18.1.tgz#6d8642508ae9fb7b48768e48f16d675c89a78460"
+ integrity sha512-j1n0Ao919h/Ai5r43VAnfV/7azUYW43GPxK7qSATzrsERfW7+y2QW9Cp9ufnRF5CQUWbnLSo7UJokSWCqg4tsQ==
+ dependencies:
+ "@jridgewell/source-map" "^0.3.3"
+ acorn "^8.8.2"
+ commander "^2.20.0"
+ source-map-support "~0.5.20"
+
+test-exclude@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
+ integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==
+ dependencies:
+ "@istanbuljs/schema" "^0.1.2"
+ glob "^7.1.4"
+ minimatch "^3.0.4"
+
+text-table@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+ integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
+
+thenify-all@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
+ integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==
+ dependencies:
+ thenify ">= 3.1.0 < 4"
+
+"thenify@>= 3.1.0 < 4":
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f"
+ integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
+ dependencies:
+ any-promise "^1.0.0"
+
+throat@^6.0.1:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.2.tgz#51a3fbb5e11ae72e2cf74861ed5c8020f89f29fe"
+ integrity sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==
+
+throttleit@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c"
+ integrity sha512-rkTVqu6IjfQ/6+uNuuc3sZek4CEYxTJom3IktzgdSxcZqdARuebbA/f4QmAxMQIxqq9ZLEUkSYqvuk1I6VKq4g==
+
+through2@^0.6.3:
+ version "0.6.5"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48"
+ integrity sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==
+ dependencies:
+ readable-stream ">=1.0.33-1 <1.1.0-0"
+ xtend ">=4.0.0 <4.1.0-0"
+
+through2@^2.0.1:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd"
+ integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
+ dependencies:
+ readable-stream "~2.3.6"
+ xtend "~4.0.1"
+
+through@2, through@^2.3.8, through@~2.3, through@~2.3.1:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
+ integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==
+
+thunky@^1.0.2:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d"
+ integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==
+
+tinycolor2@^1.4.2:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e"
+ integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==
+
+tinyqueue@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-2.0.3.tgz#64d8492ebf39e7801d7bd34062e29b45b2035f08"
+ integrity sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==
+
+tmp@~0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14"
+ integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==
+ dependencies:
+ rimraf "^3.0.0"
+
+tmpl@1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
+ integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
+
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+ integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
+
+to-float32@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/to-float32/-/to-float32-1.1.0.tgz#39bd3b11eadccd490c08f5f9171da5127b6f3946"
+ integrity sha512-keDnAusn/vc+R3iEiSDw8TOF7gPiTLdK1ArvWtYbJQiVfmRg6i/CAvbKq3uIS0vWroAC7ZecN3DjQKw3aSklUg==
+
+to-px@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/to-px/-/to-px-1.0.1.tgz#5bbaed5e5d4f76445bcc903c293a2307dd324646"
+ integrity sha512-2y3LjBeIZYL19e5gczp14/uRWFDtDUErJPVN3VU9a7SJO+RjGRtYR47aMN2bZgGlxvW4ZcEz2ddUPVHXcMfuXw==
+ dependencies:
+ parse-unit "^1.0.1"
+
+to-px@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/to-px/-/to-px-1.1.0.tgz#b6b269ed5db0cc9aefc15272a4c8bcb2ca1e99ca"
+ integrity sha512-bfg3GLYrGoEzrGoE05TAL/Uw+H/qrf2ptr9V3W7U0lkjjyYnIfgxmVLUfhQ1hZpIQwin81uxhDjvUkDYsC0xWw==
+ dependencies:
+ parse-unit "^1.0.1"
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+toidentifier@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
+ integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
+
+topojson-client@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/topojson-client/-/topojson-client-3.1.0.tgz#22e8b1ed08a2b922feeb4af6f53b6ef09a467b99"
+ integrity sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==
+ dependencies:
+ commander "2"
+
+tough-cookie@^4.0.0:
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.3.tgz#97b9adb0728b42280aa3d814b6b999b2ff0318bf"
+ integrity sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==
+ dependencies:
+ psl "^1.1.33"
+ punycode "^2.1.1"
+ universalify "^0.2.0"
+ url-parse "^1.5.3"
+
+tough-cookie@~2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
+ integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==
+ dependencies:
+ psl "^1.1.28"
+ punycode "^2.1.1"
+
+tr46@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
+ integrity sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==
+ dependencies:
+ punycode "^2.1.0"
+
+tr46@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240"
+ integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==
+ dependencies:
+ punycode "^2.1.1"
+
+tryer@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
+ integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==
+
+ts-interface-checker@^0.1.9:
+ version "0.1.13"
+ resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
+ integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
+
+tsconfig-paths@^3.14.1:
+ version "3.14.2"
+ resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz#6e32f1f79412decd261f92d633a9dc1cfa99f088"
+ integrity sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==
+ dependencies:
+ "@types/json5" "^0.0.29"
+ json5 "^1.0.2"
+ minimist "^1.2.6"
+ strip-bom "^3.0.0"
+
+tslib@^1.8.1:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
+ integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+
+tslib@^2.0.3, tslib@^2.1.0:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.0.tgz#b295854684dbda164e181d259a22cd779dcd7bc3"
+ integrity sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==
+
+tsutils@^3.21.0:
+ version "3.21.0"
+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
+ integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
+ dependencies:
+ tslib "^1.8.1"
+
+tunnel-agent@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+ integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==
+ dependencies:
+ safe-buffer "^5.0.1"
+
+tweetnacl@^0.14.3, tweetnacl@~0.14.0:
+ version "0.14.5"
+ resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
+ integrity sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==
+
+type-check@^0.4.0, type-check@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+ integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+ dependencies:
+ prelude-ls "^1.2.1"
+
+type-check@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+ integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==
+ dependencies:
+ prelude-ls "~1.1.2"
+
+type-detect@4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
+ integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
+
+type-fest@^0.16.0:
+ version "0.16.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860"
+ integrity sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==
+
+type-fest@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
+ integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+
+type-fest@^0.21.3:
+ version "0.21.3"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
+ integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
+
+type-is@~1.6.18:
+ version "1.6.18"
+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
+ integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
+ dependencies:
+ media-typer "0.3.0"
+ mime-types "~2.1.24"
+
+type@^1.0.1:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"
+ integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==
+
+type@^2.7.2:
+ version "2.7.2"
+ resolved "https://registry.yarnpkg.com/type/-/type-2.7.2.tgz#2376a15a3a28b1efa0f5350dcf72d24df6ef98d0"
+ integrity sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==
+
+typed-array-length@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb"
+ integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==
+ dependencies:
+ call-bind "^1.0.2"
+ for-each "^0.3.3"
+ is-typed-array "^1.1.9"
+
+typedarray-pool@^1.1.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/typedarray-pool/-/typedarray-pool-1.2.0.tgz#e7e90720144ba02b9ed660438af6f3aacfe33ac3"
+ integrity sha512-YTSQbzX43yvtpfRtIDAYygoYtgT+Rpjuxy9iOpczrjpXLgGoyG7aS5USJXV2d3nn8uHTeb9rXDvzS27zUg5KYQ==
+ dependencies:
+ bit-twiddle "^1.0.0"
+ dup "^1.0.0"
+
+typedarray-to-buffer@^3.1.5:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
+ integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
+ dependencies:
+ is-typedarray "^1.0.0"
+
+typedarray@^0.0.6:
+ version "0.0.6"
+ resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
+ integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==
+
+typescript@^4.6.0:
+ version "4.9.5"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
+ integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
+
+unbox-primitive@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
+ integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
+ dependencies:
+ call-bind "^1.0.2"
+ has-bigints "^1.0.2"
+ has-symbols "^1.0.3"
+ which-boxed-primitive "^1.0.2"
+
+unicode-canonical-property-names-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc"
+ integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==
+
+unicode-match-property-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3"
+ integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==
+ dependencies:
+ unicode-canonical-property-names-ecmascript "^2.0.0"
+ unicode-property-aliases-ecmascript "^2.0.0"
+
+unicode-match-property-value-ecmascript@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0"
+ integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==
+
+unicode-property-aliases-ecmascript@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd"
+ integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==
+
+unique-string@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
+ integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==
+ dependencies:
+ crypto-random-string "^2.0.0"
+
+universalify@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
+ integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
+
+universalify@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
+ integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
+
+unpipe@1.0.0, unpipe@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+ integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
+
+unquote@^1.1.0, unquote@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544"
+ integrity sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==
+
+untildify@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/untildify/-/untildify-4.0.0.tgz#2bc947b953652487e4600949fb091e3ae8cd919b"
+ integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==
+
+upath@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
+ integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==
+
+update-browserslist-db@^1.0.11:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940"
+ integrity sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==
+ dependencies:
+ escalade "^3.1.1"
+ picocolors "^1.0.0"
+
+update-diff@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/update-diff/-/update-diff-1.1.0.tgz#f510182d81ee819fb82c3a6b22b62bbdeda7808f"
+ integrity sha512-rCiBPiHxZwT4+sBhEbChzpO5hYHjm91kScWgdHf4Qeafs6Ba7MBl+d9GlGv72bcTZQO0sLmtQS1pHSWoCLtN/A==
+
+uri-js@^4.2.2:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+ dependencies:
+ punycode "^2.1.0"
+
+url-parse@^1.5.3:
+ version "1.5.10"
+ resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
+ integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
+ dependencies:
+ querystringify "^2.1.1"
+ requires-port "^1.0.0"
+
+use-sync-external-store@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
+ integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
+
+util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
+
+util.promisify@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee"
+ integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==
+ dependencies:
+ define-properties "^1.1.3"
+ es-abstract "^1.17.2"
+ has-symbols "^1.0.1"
+ object.getownpropertydescriptors "^2.1.0"
+
+utila@~0.4:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
+ integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==
+
+utils-merge@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+ integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==
+
+uuid@^8.3.2:
+ version "8.3.2"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
+ integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
+
+v8-to-istanbul@^8.1.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed"
+ integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.1"
+ convert-source-map "^1.6.0"
+ source-map "^0.7.3"
+
+vary@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+ integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
+
+verror@1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
+ integrity sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==
+ dependencies:
+ assert-plus "^1.0.0"
+ core-util-is "1.0.2"
+ extsprintf "^1.2.0"
+
+vt-pbf@^3.1.1:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/vt-pbf/-/vt-pbf-3.1.3.tgz#68fd150756465e2edae1cc5c048e063916dcfaac"
+ integrity sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==
+ dependencies:
+ "@mapbox/point-geometry" "0.1.0"
+ "@mapbox/vector-tile" "^1.3.1"
+ pbf "^3.2.1"
+
+w3c-hr-time@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
+ integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==
+ dependencies:
+ browser-process-hrtime "^1.0.0"
+
+w3c-xmlserializer@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a"
+ integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==
+ dependencies:
+ xml-name-validator "^3.0.0"
+
+wait-on@7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-7.0.1.tgz#5cff9f8427e94f4deacbc2762e6b0a489b19eae9"
+ integrity sha512-9AnJE9qTjRQOlTZIldAaf/da2eW0eSRSgcqq85mXQja/DW3MriHxkpODDSUEg+Gri/rKEcXUZHe+cevvYItaog==
+ dependencies:
+ axios "^0.27.2"
+ joi "^17.7.0"
+ lodash "^4.17.21"
+ minimist "^1.2.7"
+ rxjs "^7.8.0"
+
+walker@^1.0.7:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f"
+ integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==
+ dependencies:
+ makeerror "1.0.12"
+
+watchpack@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
+ integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
+ dependencies:
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.1.2"
+
+wbuf@^1.1.0, wbuf@^1.7.3:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df"
+ integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==
+ dependencies:
+ minimalistic-assert "^1.0.0"
+
+weak-map@^1.0.5:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/weak-map/-/weak-map-1.0.8.tgz#394c18a9e8262e790544ed8b55c6a4ddad1cb1a3"
+ integrity sha512-lNR9aAefbGPpHO7AEnY0hCFjz1eTkWCXYvkTRrTHs9qv8zJp+SkVYpzfLIFXQQiG3tVvbNFQgVg2bQS8YGgxyw==
+
+web-vitals@^2.1.0:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-2.1.4.tgz#76563175a475a5e835264d373704f9dde718290c"
+ integrity sha512-sVWcwhU5mX6crfI5Vd2dC4qchyTqxV8URinzt25XqVh+bHEPGH4C3NPrNionCP7Obx59wrYEbNlw4Z8sjALzZg==
+
+webgl-context@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/webgl-context/-/webgl-context-2.2.0.tgz#8f37d7257cf6df1cd0a49e6a7b1b721b94cc86a0"
+ integrity sha512-q/fGIivtqTT7PEoF07axFIlHNk/XCPaYpq64btnepopSWvKNFkoORlQYgqDigBIuGA1ExnFd/GnSUnBNEPQY7Q==
+ dependencies:
+ get-canvas-context "^1.0.1"
+
+webidl-conversions@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
+ integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
+
+webidl-conversions@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
+ integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==
+
+webidl-conversions@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
+ integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
+
+webpack-dev-middleware@^5.3.1:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f"
+ integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==
+ dependencies:
+ colorette "^2.0.10"
+ memfs "^3.4.3"
+ mime-types "^2.1.31"
+ range-parser "^1.2.1"
+ schema-utils "^4.0.0"
+
+webpack-dev-server@^4.6.0:
+ version "4.15.1"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.15.1.tgz#8944b29c12760b3a45bdaa70799b17cb91b03df7"
+ integrity sha512-5hbAst3h3C3L8w6W4P96L5vaV0PxSmJhxZvWKYIdgxOQm8pNZ5dEOmmSLBVpP85ReeyRt6AS1QJNyo/oFFPeVA==
+ dependencies:
+ "@types/bonjour" "^3.5.9"
+ "@types/connect-history-api-fallback" "^1.3.5"
+ "@types/express" "^4.17.13"
+ "@types/serve-index" "^1.9.1"
+ "@types/serve-static" "^1.13.10"
+ "@types/sockjs" "^0.3.33"
+ "@types/ws" "^8.5.5"
+ ansi-html-community "^0.0.8"
+ bonjour-service "^1.0.11"
+ chokidar "^3.5.3"
+ colorette "^2.0.10"
+ compression "^1.7.4"
+ connect-history-api-fallback "^2.0.0"
+ default-gateway "^6.0.3"
+ express "^4.17.3"
+ graceful-fs "^4.2.6"
+ html-entities "^2.3.2"
+ http-proxy-middleware "^2.0.3"
+ ipaddr.js "^2.0.1"
+ launch-editor "^2.6.0"
+ open "^8.0.9"
+ p-retry "^4.5.0"
+ rimraf "^3.0.2"
+ schema-utils "^4.0.0"
+ selfsigned "^2.1.1"
+ serve-index "^1.9.1"
+ sockjs "^0.3.24"
+ spdy "^4.0.2"
+ webpack-dev-middleware "^5.3.1"
+ ws "^8.13.0"
+
+webpack-manifest-plugin@^4.0.2:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz#10f8dbf4714ff93a215d5a45bcc416d80506f94f"
+ integrity sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==
+ dependencies:
+ tapable "^2.0.0"
+ webpack-sources "^2.2.0"
+
+webpack-sources@^1.4.3:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
+ integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
+ dependencies:
+ source-list-map "^2.0.0"
+ source-map "~0.6.1"
+
+webpack-sources@^2.2.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd"
+ integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==
+ dependencies:
+ source-list-map "^2.0.1"
+ source-map "^0.6.1"
+
+webpack-sources@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
+ integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
+
+webpack@^5.64.4:
+ version "5.88.0"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.88.0.tgz#a07aa2f8e7a64a8f1cec0c6c2e180e3cb34440c8"
+ integrity sha512-O3jDhG5e44qIBSi/P6KpcCcH7HD+nYIHVBhdWFxcLOcIGN8zGo5nqF3BjyNCxIh4p1vFdNnreZv2h2KkoAw3lw==
+ dependencies:
+ "@types/eslint-scope" "^3.7.3"
+ "@types/estree" "^1.0.0"
+ "@webassemblyjs/ast" "^1.11.5"
+ "@webassemblyjs/wasm-edit" "^1.11.5"
+ "@webassemblyjs/wasm-parser" "^1.11.5"
+ acorn "^8.7.1"
+ acorn-import-assertions "^1.9.0"
+ browserslist "^4.14.5"
+ chrome-trace-event "^1.0.2"
+ enhanced-resolve "^5.15.0"
+ es-module-lexer "^1.2.1"
+ eslint-scope "5.1.1"
+ events "^3.2.0"
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.2.9"
+ json-parse-even-better-errors "^2.3.1"
+ loader-runner "^4.2.0"
+ mime-types "^2.1.27"
+ neo-async "^2.6.2"
+ schema-utils "^3.2.0"
+ tapable "^2.1.1"
+ terser-webpack-plugin "^5.3.7"
+ watchpack "^2.4.0"
+ webpack-sources "^3.2.3"
+
+websocket-driver@>=0.5.1, websocket-driver@^0.7.4:
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
+ integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
+ dependencies:
+ http-parser-js ">=0.5.1"
+ safe-buffer ">=5.1.0"
+ websocket-extensions ">=0.1.1"
+
+websocket-extensions@>=0.1.1:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
+ integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
+
+whatwg-encoding@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
+ integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==
+ dependencies:
+ iconv-lite "0.4.24"
+
+whatwg-fetch@^3.6.2:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
+ integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==
+
+whatwg-mimetype@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
+ integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
+
+whatwg-url@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
+ integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==
+ dependencies:
+ lodash.sortby "^4.7.0"
+ tr46 "^1.0.1"
+ webidl-conversions "^4.0.2"
+
+whatwg-url@^8.0.0, whatwg-url@^8.5.0:
+ version "8.7.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"
+ integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==
+ dependencies:
+ lodash "^4.7.0"
+ tr46 "^2.1.0"
+ webidl-conversions "^6.1.0"
+
+which-boxed-primitive@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
+ integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
+ 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"
+
+which-collection@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906"
+ integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==
+ dependencies:
+ is-map "^2.0.1"
+ is-set "^2.0.1"
+ is-weakmap "^2.0.1"
+ is-weakset "^2.0.1"
+
+which-typed-array@^1.1.9:
+ version "1.1.9"
+ resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.9.tgz#307cf898025848cf995e795e8423c7f337efbde6"
+ integrity sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==
+ 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"
+
+which@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+ integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
+ dependencies:
+ isexe "^2.0.0"
+
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+word-wrap@^1.2.3, word-wrap@~1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
+ integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+
+workbox-background-sync@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.6.1.tgz#08d603a33717ce663e718c30cc336f74909aff2f"
+ integrity sha512-trJd3ovpWCvzu4sW0E8rV3FUyIcC0W8G+AZ+VcqzzA890AsWZlUGOTSxIMmIHVusUw/FDq1HFWfy/kC/WTRqSg==
+ dependencies:
+ idb "^7.0.1"
+ workbox-core "6.6.1"
+
+workbox-broadcast-update@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-6.6.1.tgz#0fad9454cf8e4ace0c293e5617c64c75d8a8c61e"
+ integrity sha512-fBhffRdaANdeQ1V8s692R9l/gzvjjRtydBOvR6WCSB0BNE2BacA29Z4r9/RHd9KaXCPl6JTdI9q0bR25YKP8TQ==
+ dependencies:
+ workbox-core "6.6.1"
+
+workbox-build@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-6.6.1.tgz#6010e9ce550910156761448f2dbea8cfcf759cb0"
+ integrity sha512-INPgDx6aRycAugUixbKgiEQBWD0MPZqU5r0jyr24CehvNuLPSXp/wGOpdRJmts656lNiXwqV7dC2nzyrzWEDnw==
+ dependencies:
+ "@apideck/better-ajv-errors" "^0.3.1"
+ "@babel/core" "^7.11.1"
+ "@babel/preset-env" "^7.11.0"
+ "@babel/runtime" "^7.11.2"
+ "@rollup/plugin-babel" "^5.2.0"
+ "@rollup/plugin-node-resolve" "^11.2.1"
+ "@rollup/plugin-replace" "^2.4.1"
+ "@surma/rollup-plugin-off-main-thread" "^2.2.3"
+ ajv "^8.6.0"
+ common-tags "^1.8.0"
+ fast-json-stable-stringify "^2.1.0"
+ fs-extra "^9.0.1"
+ glob "^7.1.6"
+ lodash "^4.17.20"
+ pretty-bytes "^5.3.0"
+ rollup "^2.43.1"
+ rollup-plugin-terser "^7.0.0"
+ source-map "^0.8.0-beta.0"
+ stringify-object "^3.3.0"
+ strip-comments "^2.0.1"
+ tempy "^0.6.0"
+ upath "^1.2.0"
+ workbox-background-sync "6.6.1"
+ workbox-broadcast-update "6.6.1"
+ workbox-cacheable-response "6.6.1"
+ workbox-core "6.6.1"
+ workbox-expiration "6.6.1"
+ workbox-google-analytics "6.6.1"
+ workbox-navigation-preload "6.6.1"
+ workbox-precaching "6.6.1"
+ workbox-range-requests "6.6.1"
+ workbox-recipes "6.6.1"
+ workbox-routing "6.6.1"
+ workbox-strategies "6.6.1"
+ workbox-streams "6.6.1"
+ workbox-sw "6.6.1"
+ workbox-window "6.6.1"
+
+workbox-cacheable-response@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-6.6.1.tgz#284c2b86be3f4fd191970ace8c8e99797bcf58e9"
+ integrity sha512-85LY4veT2CnTCDxaVG7ft3NKaFbH6i4urZXgLiU4AiwvKqS2ChL6/eILiGRYXfZ6gAwDnh5RkuDbr/GMS4KSag==
+ dependencies:
+ workbox-core "6.6.1"
+
+workbox-core@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.6.1.tgz#7184776d4134c5ed2f086878c882728fc9084265"
+ integrity sha512-ZrGBXjjaJLqzVothoE12qTbVnOAjFrHDXpZe7coCb6q65qI/59rDLwuFMO4PcZ7jcbxY+0+NhUVztzR/CbjEFw==
+
+workbox-expiration@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.6.1.tgz#a841fa36676104426dbfb9da1ef6a630b4f93739"
+ integrity sha512-qFiNeeINndiOxaCrd2DeL1Xh1RFug3JonzjxUHc5WkvkD2u5abY3gZL1xSUNt3vZKsFFGGORItSjVTVnWAZO4A==
+ dependencies:
+ idb "^7.0.1"
+ workbox-core "6.6.1"
+
+workbox-google-analytics@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-6.6.1.tgz#a07a6655ab33d89d1b0b0a935ffa5dea88618c5d"
+ integrity sha512-1TjSvbFSLmkpqLcBsF7FuGqqeDsf+uAXO/pjiINQKg3b1GN0nBngnxLcXDYo1n/XxK4N7RaRrpRlkwjY/3ocuA==
+ dependencies:
+ workbox-background-sync "6.6.1"
+ workbox-core "6.6.1"
+ workbox-routing "6.6.1"
+ workbox-strategies "6.6.1"
+
+workbox-navigation-preload@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.6.1.tgz#61a34fe125558dd88cf09237f11bd966504ea059"
+ integrity sha512-DQCZowCecO+wRoIxJI2V6bXWK6/53ff+hEXLGlQL4Rp9ZaPDLrgV/32nxwWIP7QpWDkVEtllTAK5h6cnhxNxDA==
+ dependencies:
+ workbox-core "6.6.1"
+
+workbox-precaching@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.6.1.tgz#dedeeba10a2d163d990bf99f1c2066ac0d1a19e2"
+ integrity sha512-K4znSJ7IKxCnCYEdhNkMr7X1kNh8cz+mFgx9v5jFdz1MfI84pq8C2zG+oAoeE5kFrUf7YkT5x4uLWBNg0DVZ5A==
+ dependencies:
+ workbox-core "6.6.1"
+ workbox-routing "6.6.1"
+ workbox-strategies "6.6.1"
+
+workbox-range-requests@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-6.6.1.tgz#ddaf7e73af11d362fbb2f136a9063a4c7f507a39"
+ integrity sha512-4BDzk28govqzg2ZpX0IFkthdRmCKgAKreontYRC5YsAPB2jDtPNxqx3WtTXgHw1NZalXpcH/E4LqUa9+2xbv1g==
+ dependencies:
+ workbox-core "6.6.1"
+
+workbox-recipes@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-6.6.1.tgz#ea70d2b2b0b0bce8de0a9d94f274d4a688e69fae"
+ integrity sha512-/oy8vCSzromXokDA+X+VgpeZJvtuf8SkQ8KL0xmRivMgJZrjwM3c2tpKTJn6PZA6TsbxGs3Sc7KwMoZVamcV2g==
+ dependencies:
+ workbox-cacheable-response "6.6.1"
+ workbox-core "6.6.1"
+ workbox-expiration "6.6.1"
+ workbox-precaching "6.6.1"
+ workbox-routing "6.6.1"
+ workbox-strategies "6.6.1"
+
+workbox-routing@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.6.1.tgz#cba9a1c7e0d1ea11e24b6f8c518840efdc94f581"
+ integrity sha512-j4ohlQvfpVdoR8vDYxTY9rA9VvxTHogkIDwGdJ+rb2VRZQ5vt1CWwUUZBeD/WGFAni12jD1HlMXvJ8JS7aBWTg==
+ dependencies:
+ workbox-core "6.6.1"
+
+workbox-strategies@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.6.1.tgz#38d0f0fbdddba97bd92e0c6418d0b1a2ccd5b8bf"
+ integrity sha512-WQLXkRnsk4L81fVPkkgon1rZNxnpdO5LsO+ws7tYBC6QQQFJVI6v98klrJEjFtZwzw/mB/HT5yVp7CcX0O+mrw==
+ dependencies:
+ workbox-core "6.6.1"
+
+workbox-streams@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-6.6.1.tgz#b2f7ba7b315c27a6e3a96a476593f99c5d227d26"
+ integrity sha512-maKG65FUq9e4BLotSKWSTzeF0sgctQdYyTMq529piEN24Dlu9b6WhrAfRpHdCncRS89Zi2QVpW5V33NX8PgH3Q==
+ dependencies:
+ workbox-core "6.6.1"
+ workbox-routing "6.6.1"
+
+workbox-sw@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-6.6.1.tgz#d4c4ca3125088e8b9fd7a748ed537fa0247bd72c"
+ integrity sha512-R7whwjvU2abHH/lR6kQTTXLHDFU2izht9kJOvBRYK65FbwutT4VvnUAJIgHvfWZ/fokrOPhfoWYoPCMpSgUKHQ==
+
+workbox-webpack-plugin@^6.4.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-webpack-plugin/-/workbox-webpack-plugin-6.6.1.tgz#4f81cc1ad4e5d2cd7477a86ba83c84ee2d187531"
+ integrity sha512-zpZ+ExFj9NmiI66cFEApyjk7hGsfJ1YMOaLXGXBoZf0v7Iu6hL0ZBe+83mnDq3YYWAfA3fnyFejritjOHkFcrA==
+ dependencies:
+ fast-json-stable-stringify "^2.1.0"
+ pretty-bytes "^5.4.1"
+ upath "^1.2.0"
+ webpack-sources "^1.4.3"
+ workbox-build "6.6.1"
+
+workbox-window@6.6.1:
+ version "6.6.1"
+ resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-6.6.1.tgz#f22a394cbac36240d0dadcbdebc35f711bb7b89e"
+ integrity sha512-wil4nwOY58nTdCvif/KEZjQ2NP8uk3gGeRNy2jPBbzypU4BT4D9L8xiwbmDBpZlSgJd2xsT9FvSNU0gsxV51JQ==
+ dependencies:
+ "@types/trusted-types" "^2.0.2"
+ workbox-core "6.6.1"
+
+world-calendars@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/world-calendars/-/world-calendars-1.0.3.tgz#b25c5032ba24128ffc41d09faf4a5ec1b9c14335"
+ integrity sha512-sAjLZkBnsbHkHWVhrsCU5Sa/EVuf9QqgvrN8zyJ2L/F9FR9Oc6CvVK0674+PGAtmmmYQMH98tCUSO4QLQv3/TQ==
+ dependencies:
+ object-assign "^4.1.0"
+
+wrap-ansi@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53"
+ integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+write-file-atomic@^3.0.0:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
+ integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
+ dependencies:
+ imurmurhash "^0.1.4"
+ is-typedarray "^1.0.0"
+ signal-exit "^3.0.2"
+ typedarray-to-buffer "^3.1.5"
+
+ws@^7.4.6:
+ version "7.5.9"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
+ integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
+
+ws@^8.13.0:
+ version "8.13.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.13.0.tgz#9a9fb92f93cf41512a0735c8f4dd09b8a1211cd0"
+ integrity sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==
+
+xml-name-validator@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
+ integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
+
+xmlchars@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
+ integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
+
+"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.0, xtend@~4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
+ integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
+
+xtend@^2.1.2:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.2.0.tgz#eef6b1f198c1c8deafad8b1765a04dad4a01c5a9"
+ integrity sha512-SLt5uylT+4aoXxXuwtQp5ZnMMzhDb1Xkg4pEqc00WUJCQifPfV9Ub1VrNhp9kXkrjZD2I2Hl8WnjP37jzZLPZw==
+
+y18n@^5.0.5:
+ version "5.0.8"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
+ integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+
+yallist@^3.0.2:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
+ integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
+
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
+yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2:
+ version "1.10.2"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
+ integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+
+yaml@^2.1.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.1.tgz#02fe0975d23cd441242aa7204e09fc28ac2ac33b"
+ integrity sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==
+
+yargs-parser@^20.2.2:
+ version "20.2.9"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
+ integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
+
+yargs@^16.2.0:
+ version "16.2.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
+ integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
+ dependencies:
+ cliui "^7.0.2"
+ escalade "^3.1.1"
+ get-caller-file "^2.0.5"
+ require-directory "^2.1.1"
+ string-width "^4.2.0"
+ y18n "^5.0.5"
+ yargs-parser "^20.2.2"
+
+yauzl@^2.10.0:
+ version "2.10.0"
+ resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
+ integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==
+ dependencies:
+ buffer-crc32 "~0.2.3"
+ fd-slicer "~1.1.0"
+
+yocto-queue@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
diff --git a/frontend/.gitignore b/frontend/.gitignore
new file mode 100644
index 00000000..4d29575d
--- /dev/null
+++ b/frontend/.gitignore
@@ -0,0 +1,23 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/frontend/.prettierignore b/frontend/.prettierignore
new file mode 100644
index 00000000..1d2a37f5
--- /dev/null
+++ b/frontend/.prettierignore
@@ -0,0 +1,3 @@
+node_modules
+build
+coverage
diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json
new file mode 100644
index 00000000..0967ef42
--- /dev/null
+++ b/frontend/.prettierrc.json
@@ -0,0 +1 @@
+{}
diff --git a/frontend/README.md b/frontend/README.md
new file mode 100644
index 00000000..02aac3f6
--- /dev/null
+++ b/frontend/README.md
@@ -0,0 +1,70 @@
+# Getting Started with Create React App
+
+This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
+
+## Available Scripts
+
+In the project directory, you can run:
+
+### `yarn start`
+
+Runs the app in the development mode.\
+Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
+
+The page will reload if you make edits.\
+You will also see any lint errors in the console.
+
+### `yarn test`
+
+Launches the test runner in the interactive watch mode.\
+See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
+
+### `yarn build`
+
+Builds the app for production to the `build` folder.\
+It correctly bundles React in production mode and optimizes the build for the best performance.
+
+The build is minified and the filenames include the hashes.\
+Your app is ready to be deployed!
+
+See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
+
+### `yarn eject`
+
+**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
+
+If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
+
+Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
+
+You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
+
+## Learn More
+
+You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
+
+To learn React, check out the [React documentation](https://reactjs.org/).
+
+### Code Splitting
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
+
+### Analyzing the Bundle Size
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
+
+### Making a Progressive Web App
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
+
+### Advanced Configuration
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
+
+### Deployment
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
+
+### `yarn build` fails to minify
+
+This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 00000000..77aaff83
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,68 @@
+{
+ "name": "frontend",
+ "version": "0.1.0",
+ "private": true,
+ "dependencies": {
+ "@emotion/react": "^11.10.6",
+ "@emotion/styled": "^11.10.6",
+ "@mui/icons-material": "^5.11.11",
+ "@mui/lab": "^5.0.0-alpha.122",
+ "@mui/material": "^5.11.12",
+ "@mui/styles": "^5.11.12",
+ "@mui/system": "^5.4.1",
+ "@mui/x-date-pickers": "^6.0.0",
+ "@reduxjs/toolkit": "^1.6.0",
+ "@testing-library/jest-dom": "^5.11.4",
+ "@testing-library/react": "^11.1.0",
+ "@testing-library/user-event": "^12.1.10",
+ "chart.js": "^3.7.1",
+ "chartjs-plugin-annotation": "^1.4.0",
+ "chartjs-plugin-crosshair": "^1.2.0",
+ "classnames": "^2.3.1",
+ "color-scheme": "^1.0.1",
+ "compute-iqr": "^1.1.0",
+ "date-fns": "^2.29.3",
+ "dayjs": "^1.11.7",
+ "elkjs": "^0.7.1",
+ "http-proxy-middleware": "^2.0.0",
+ "normalizr": "^3.6.1",
+ "react": "^17.0.0",
+ "react-chartjs-2": "^3.0.4",
+ "react-dom": "^17.0.2",
+ "react-flow-renderer": "^10.1.0",
+ "react-hook-form": "^7.6.6",
+ "react-mathjax-preview": "^2.2.3",
+ "react-redux": "^7.2.4",
+ "react-router-dom": "^5.2.0",
+ "react-scripts": "^5.0.0",
+ "web-vitals": "^1.0.1",
+ "web-worker": "^1.2.0"
+ },
+ "scripts": {
+ "start": "react-scripts start",
+ "build": "react-scripts build",
+ "test": "react-scripts test",
+ "eject": "react-scripts eject"
+ },
+ "eslintConfig": {
+ "extends": [
+ "react-app",
+ "react-app/jest"
+ ]
+ },
+ "browserslist": {
+ "production": [
+ ">0.2%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 1 chrome version",
+ "last 1 firefox version",
+ "last 1 safari version"
+ ]
+ },
+ "devDependencies": {
+ "prettier": "2.5.1"
+ }
+}
diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico
new file mode 100644
index 00000000..a11777cc
Binary files /dev/null and b/frontend/public/favicon.ico differ
diff --git a/frontend/public/index.html b/frontend/public/index.html
new file mode 100644
index 00000000..d3bb490c
--- /dev/null
+++ b/frontend/public/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ PKPDApp
+
+
+ You need to enable JavaScript to run this app.
+
+
+
+
diff --git a/frontend/public/logo.svg b/frontend/public/logo.svg
new file mode 100644
index 00000000..465cf440
--- /dev/null
+++ b/frontend/public/logo.svg
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/public/logo192.png b/frontend/public/logo192.png
new file mode 100644
index 00000000..fc44b0a3
Binary files /dev/null and b/frontend/public/logo192.png differ
diff --git a/frontend/public/logo512.png b/frontend/public/logo512.png
new file mode 100644
index 00000000..a4e47a65
Binary files /dev/null and b/frontend/public/logo512.png differ
diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json
new file mode 100644
index 00000000..080d6c77
--- /dev/null
+++ b/frontend/public/manifest.json
@@ -0,0 +1,25 @@
+{
+ "short_name": "React App",
+ "name": "Create React App Sample",
+ "icons": [
+ {
+ "src": "favicon.ico",
+ "sizes": "64x64 32x32 24x24 16x16",
+ "type": "image/x-icon"
+ },
+ {
+ "src": "logo192.png",
+ "type": "image/png",
+ "sizes": "192x192"
+ },
+ {
+ "src": "logo512.png",
+ "type": "image/png",
+ "sizes": "512x512"
+ }
+ ],
+ "start_url": ".",
+ "display": "standalone",
+ "theme_color": "#000000",
+ "background_color": "#ffffff"
+}
diff --git a/frontend/public/robots.txt b/frontend/public/robots.txt
new file mode 100644
index 00000000..e9e57dc4
--- /dev/null
+++ b/frontend/public/robots.txt
@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:
diff --git a/frontend/src/Api.js b/frontend/src/Api.js
new file mode 100644
index 00000000..0ae69561
--- /dev/null
+++ b/frontend/src/Api.js
@@ -0,0 +1,102 @@
+// derived from https://jasonwatmore.com/post/2020/04/18/fetch-a-lightweight-fetch-wrapper-to-simplify-http-requests
+export const api = {
+ get,
+ post,
+ patch,
+ put,
+ putMultiPart,
+ delete: _delete,
+};
+
+function get(url, csrf) {
+ const requestOptions = {
+ method: "GET",
+ headers: {
+ "X-CSRFToken": csrf,
+ },
+ };
+ return fetch(url, requestOptions).then(handleResponse);
+}
+
+function post(url, csrf, body) {
+ let requestOptions = {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(body),
+ };
+ if (csrf) {
+ requestOptions.headers["X-CSRFToken"] = csrf;
+ }
+ return fetch(url, requestOptions).then(handleResponse);
+}
+
+function put(url, csrf, body) {
+ const requestOptions = {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ "X-CSRFToken": csrf,
+ },
+ body: JSON.stringify(body),
+ };
+ return fetch(url, requestOptions).then(handleResponse);
+}
+
+function putMultiPart(url, csrf, data) {
+ const formData = new FormData();
+
+ for (const name in data) {
+ formData.append(name, data[name]);
+ }
+ const requestOptions = {
+ method: "PUT",
+ headers: {
+ "X-CSRFToken": csrf,
+ },
+ body: formData,
+ };
+ return fetch(url, requestOptions).then(handleResponse);
+}
+
+function patch(url, csrf, body) {
+ const requestOptions = {
+ method: "PATCH",
+ headers: {
+ "Content-Type": "application/json",
+ "X-CSRFToken": csrf,
+ },
+ body: JSON.stringify(body),
+ };
+ return fetch(url, requestOptions).then(handleResponse);
+}
+
+// prefixed with underscored because delete is a reserved word in javascript
+function _delete(url, csrf) {
+ const requestOptions = {
+ method: "DELETE",
+ headers: {
+ "X-CSRFToken": csrf,
+ },
+ };
+ return fetch(url, requestOptions).then(handleResponse);
+}
+
+// helper functions
+
+function handleResponse(response) {
+ return response.text().then((text) => {
+ let data = {};
+ try {
+ data = text && JSON.parse(text);
+ } catch (e) {
+ alert(text);
+ }
+ if (!response.ok) {
+ console.log("API error:", response, response.statusText, data);
+ return Promise.reject(data);
+ }
+ return data;
+ });
+}
diff --git a/frontend/src/App.css b/frontend/src/App.css
new file mode 100644
index 00000000..74b5e053
--- /dev/null
+++ b/frontend/src/App.css
@@ -0,0 +1,38 @@
+.App {
+ text-align: center;
+}
+
+.App-logo {
+ height: 40vmin;
+ pointer-events: none;
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ .App-logo {
+ animation: App-logo-spin infinite 20s linear;
+ }
+}
+
+.App-header {
+ background-color: #282c34;
+ min-height: 100vh;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ font-size: calc(10px + 2vmin);
+ color: white;
+}
+
+.App-link {
+ color: #61dafb;
+}
+
+@keyframes App-logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
diff --git a/frontend/src/App.js b/frontend/src/App.js
new file mode 100644
index 00000000..2155d3ee
--- /dev/null
+++ b/frontend/src/App.js
@@ -0,0 +1,402 @@
+import React, { useEffect } from "react";
+import {
+ Switch,
+ Route,
+ Link,
+ matchPath,
+ Redirect,
+ useParams,
+ useLocation,
+ useHistory,
+} from "react-router-dom";
+import { useDispatch } from "react-redux";
+import { ThemeProvider, StyledEngineProvider, createTheme } from '@mui/material/styles';
+import { AdapterDayjs } from '@mui/x-date-pickers/AdapterDayjs';
+import { LocalizationProvider, DatePicker } from '@mui/x-date-pickers';
+//import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
+//import enUS from 'date-fns/locale/en-US';
+import 'dayjs/locale/en-gb';
+import dayjs from 'dayjs';
+import utc from 'dayjs/plugin/utc';
+
+
+import DateFnsUtils from "@date-io/date-fns";
+import Container from "@mui/material/Container";
+import Login from "./features/login/Login";
+import Register from "./features/login/Register";
+import RegisterSuccess from "./features/login/RegisterSuccess";
+import ActivateUser from "./features/login/ActivateUser";
+import ActivateUserSuccess from "./features/login/ActivateUserSuccess";
+import ResetPasswordRequest from "./features/login/ResetPasswordRequest";
+import ResetPasswordRequestSuccess from "./features/login/ResetPasswordRequestSuccess";
+import ResetPassword from "./features/login/ResetPassword";
+import ResetPasswordSuccess from "./features/login/ResetPasswordSuccess";
+
+import { alpha } from "@mui/material/styles";
+import makeStyles from '@mui/styles/makeStyles';
+import CssBaseline from "@mui/material/CssBaseline";
+
+import SearchIcon from "@mui/icons-material/Search";
+
+import InputBase from "@mui/material/InputBase";
+
+import clsx from "clsx";
+import Drawer from "@mui/material/Drawer";
+import AppBar from "@mui/material/AppBar";
+import Toolbar from "@mui/material/Toolbar";
+import Typography from "@mui/material/Typography";
+import Divider from "@mui/material/Divider";
+import IconButton from "@mui/material/IconButton";
+import Button from "@mui/material/Button";
+import ButtonGroup from "@mui/material/ButtonGroup";
+import MenuIcon from "@mui/icons-material/Menu";
+import ChevronLeftIcon from "@mui/icons-material/ChevronLeft";
+
+import { api } from "./Api";
+import InferenceMenu from "./features/menu/InferenceMenu";
+import Projects from "./features/projects/Projects";
+import Project from "./features/projects/Project";
+import RequireLogin from "./features/login/RequireLogin";
+
+
+import { logout, fetchSession } from "./features/login/loginSlice";
+import { fetchAlgorithms } from "./features/inference/algorithmsSlice.js";
+import { fetchUnits } from "./features/projects/unitsSlice.js";
+import { fetchUsers } from "./features/projects/usersSlice.js";
+import { fetchProjects } from "./features/projects/projectsSlice.js";
+
+dayjs.extend(utc);
+
+const drawerWidth = 240;
+
+const useStyles = makeStyles((theme) => ({
+ grow: {
+ flexGrow: 1,
+ },
+ root: {
+ display: "flex",
+ },
+ title: {
+ display: "none",
+ [theme.breakpoints.up("sm")]: {
+ display: "block",
+ },
+ },
+ search: {
+ position: "relative",
+ borderRadius: theme.shape.borderRadius,
+ backgroundColor: alpha(theme.palette.common.white, 0.15),
+ "&:hover": {
+ backgroundColor: alpha(theme.palette.common.white, 0.25),
+ },
+ marginRight: theme.spacing(2),
+ marginLeft: 0,
+ width: "100%",
+ [theme.breakpoints.up("sm")]: {
+ marginLeft: theme.spacing(3),
+ width: "auto",
+ },
+ },
+ searchIcon: {
+ padding: theme.spacing(0, 2),
+ height: "100%",
+ position: "absolute",
+ pointerEvents: "none",
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "center",
+ },
+ inputRoot: {
+ color: "inherit",
+ },
+ inputInput: {
+ padding: theme.spacing(1, 1, 1, 0),
+ // vertical padding + font size from searchIcon
+ paddingLeft: `calc(1em + ${theme.spacing(4)})`,
+ transition: theme.transitions.create("width"),
+ width: "100%",
+ [theme.breakpoints.up("md")]: {
+ width: "20ch",
+ },
+ },
+ toolbar: {
+ paddingRight: 24, // keep right padding when drawer closed
+ },
+ toolbarIcon: {
+ display: "flex",
+ alignItems: "center",
+ justifyContent: "flex-end",
+ padding: "0 8px",
+ ...theme.mixins.toolbar,
+ },
+ appBar: {
+ zIndex: theme.zIndex.drawer + 1,
+ transition: theme.transitions.create(["width", "margin"], {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ },
+ appBarShift: {
+ marginLeft: drawerWidth,
+ width: `calc(100% - ${drawerWidth}px)`,
+ transition: theme.transitions.create(["width", "margin"], {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ },
+ galvanalyserLogo: {
+ height: "40px",
+ },
+ menuButton: {
+ marginRight: 36,
+ },
+ menuButtonHidden: {
+ display: "none",
+ },
+
+ drawerPaper: {
+ position: "relative",
+ overflowX: "hidden",
+ whiteSpace: "nowrap",
+ width: drawerWidth,
+ height: "100%",
+ transition: theme.transitions.create("width", {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.enteringScreen,
+ }),
+ },
+
+ drawerPaperClose: {
+ overflowX: "hidden",
+ transition: theme.transitions.create("width", {
+ easing: theme.transitions.easing.sharp,
+ duration: theme.transitions.duration.leavingScreen,
+ }),
+ width: theme.spacing(7),
+ height: "100%",
+ [theme.breakpoints.up("sm")]: {
+ width: theme.spacing(9),
+ },
+ },
+ appBarSpacer: theme.mixins.toolbar,
+ content: {
+ flexGrow: 1,
+ overflow: "auto",
+ },
+ container: {
+ paddingTop: theme.spacing(10),
+ paddingBottom: theme.spacing(4),
+ },
+ paper: {
+ padding: theme.spacing(2),
+ display: "flex",
+ overflow: "auto",
+ flexDirection: "column",
+ },
+ fixedHeight: {
+ height: 240,
+ },
+ nested: {
+ paddingLeft: theme.spacing(4),
+ },
+ avatarPlusSmall: {
+ width: theme.spacing(3),
+ height: theme.spacing(3),
+ backgroundColor: theme.palette.primary.main,
+ },
+ avatarPlus: {
+ width: theme.spacing(5),
+ height: theme.spacing(5),
+ backgroundColor: theme.palette.primary.main,
+ },
+ colorSelected: {
+ backgroundColor: theme.palette.secondary.main,
+ },
+ avatarSmall: {
+ width: theme.spacing(3),
+ height: theme.spacing(3),
+ },
+ avatar: {
+ width: theme.spacing(5),
+ height: theme.spacing(5),
+ backgroundColor: theme.palette.secondary.main,
+ },
+ large: {
+ width: theme.spacing(7),
+ height: theme.spacing(7),
+ },
+ noPadding: {
+ margin: 0,
+ marginRight: 0,
+ marginLeft: 0,
+ padding: 0,
+ },
+}));
+
+function LoggedInApp() {
+ const classes = useStyles();
+ const [open, setOpen] = React.useState(true);
+
+ const handleDrawerOpenClose = () => {
+ setOpen((prevOpen) => !prevOpen);
+ };
+
+ const handleLogout = () => {
+ dispatch(logout());
+ }
+
+ let history = useHistory();
+ const dispatch = useDispatch();
+
+ useEffect(() => {
+ dispatch(fetchProjects());
+ dispatch(fetchUsers());
+ dispatch(fetchUnits());
+ dispatch(fetchAlgorithms());
+ //const interval = setInterval(() => {
+ // refreshHarvesters();
+ //}, 5000);
+ //return () => clearInterval(interval);
+ }, [dispatch]);
+
+ const { pathname } = useLocation();
+ const matchProject = matchPath(pathname, { path: '/:id'})
+
+ const rootPath = "/";
+ const isRootPath = !!matchPath(pathname, { path: rootPath, exact: true });
+ console.log('pathname', pathname)
+ let modellingPath = ''
+ let isModellingPath = false
+ let inferencePath = ''
+ let isInferencePath = false
+ if (matchProject) {
+ modellingPath = `/${matchProject.params.id}`;
+ isModellingPath = !!matchPath(pathname, {
+ path: modellingPath,
+ exact: true,
+ });
+ inferencePath = `/${matchProject.params.id}/inference`;
+ isInferencePath = !!matchPath(pathname, {
+ path: inferencePath,
+ });
+ }
+ return (
+
+
+
+
+
+
+
+ PKPDapp
+
+ { !isRootPath &&
+
+
+
+
+
+ Home
+
+
+ Workbench
+
+
+
+ Inferences
+
+
+
+ }
+
+
+
+ Logout
+
+
+
+ {/* A
looks through its children s and
+ renders the first one that matches the current URL. */}
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+const theme = createTheme(
+ {
+ },
+);
+
+
+export default function App() {
+ const dispatch = useDispatch();
+ React.useEffect(() => {
+ dispatch(fetchSession());
+ }, [dispatch]);
+
+ return (
+
+ ;
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/App.test.js b/frontend/src/App.test.js
new file mode 100644
index 00000000..9382b9ad
--- /dev/null
+++ b/frontend/src/App.test.js
@@ -0,0 +1,8 @@
+import { render, screen } from "@testing-library/react";
+import App from "./App";
+
+test("renders learn react link", () => {
+ render( );
+ const linkElement = screen.getByText(/learn react/i);
+ expect(linkElement).toBeInTheDocument();
+});
diff --git a/frontend/src/app/store.js b/frontend/src/app/store.js
new file mode 100644
index 00000000..bb91bee1
--- /dev/null
+++ b/frontend/src/app/store.js
@@ -0,0 +1,42 @@
+import { configureStore } from "@reduxjs/toolkit";
+import projectsReducer from "../features/projects/projectsSlice";
+import datasetsReducer from "../features/datasets/datasetsSlice";
+import subjectsReducer from "../features/datasets/subjectsSlice";
+import biomarkerTypesReducer from "../features/datasets/biomarkerTypesSlice";
+import pdModelsReducer from "../features/pdModels/pdModelsSlice";
+import pkModelsReducer from "../features/pkModels/pkModelsSlice";
+import modellingReducer from "../features/modelling/modellingSlice";
+import basePkModelsReducer from "../features/pkModels/basePkModelsSlice";
+import protocolsReducer from "../features/protocols/protocolsSlice";
+import usersReducer from "../features/projects/usersSlice";
+import unitsReducer from "../features/projects/unitsSlice";
+import variablesReducer from "../features/variables/variablesSlice";
+import inferensesReducer from "../features/inference/inferenceSlice";
+import algorithmsReducer from "../features/inference/algorithmsSlice";
+import chainsReducer from "../features/inference/chainSlice";
+import loginReducer from "../features/login/loginSlice";
+
+export default configureStore({
+ reducer: {
+ login: loginReducer,
+ projects: projectsReducer,
+ datasets: datasetsReducer,
+ biomarkerTypes: biomarkerTypesReducer,
+ subjects: subjectsReducer,
+ pkModels: pkModelsReducer,
+ basePkModels: basePkModelsReducer,
+ modelling: modellingReducer,
+ protocols: protocolsReducer,
+ pdModels: pdModelsReducer,
+ users: usersReducer,
+ units: unitsReducer,
+ variables: variablesReducer,
+ inferences: inferensesReducer,
+ algorithms: algorithmsReducer,
+ chains: chainsReducer,
+ },
+ middleware: (getDefaultMiddleware) =>
+ getDefaultMiddleware({
+ serializableCheck: false,
+ }),
+});
diff --git a/frontend/src/features/dataAnalysis/AuceChart.js b/frontend/src/features/dataAnalysis/AuceChart.js
new file mode 100644
index 00000000..0fa5b7b3
--- /dev/null
+++ b/frontend/src/features/dataAnalysis/AuceChart.js
@@ -0,0 +1,218 @@
+import React from "react";
+
+import makeStyles from '@mui/styles/makeStyles';
+
+import { Scatter } from "react-chartjs-2";
+
+import { getColor, getColorBackground } from "../modelling/ShapesAndColors";
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ position: 'relative',
+ margin: 'auto',
+ height: '29vh',
+ },
+}));
+
+let options = {
+ animation: {
+ duration: 0,
+ },
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ x: {
+ type: "linear",
+ title: {
+ text: "Time ",
+ display: true,
+ },
+ },
+ y: {
+ type: "linear",
+ position: "left",
+ title: {
+ text: "Data Variable / Model Output (units defined in detail panels)",
+ display: true,
+ },
+ },
+ },
+ plugins: {
+ legend: {
+ labels: {
+ usePointStyle: true,
+ filter: function (item, chart) {
+ if (item.text) {
+ return !item.text.includes("noLabel");
+ }
+ return false;
+ },
+ },
+ },
+ tooltip: {
+ mode: "interpolate",
+ callbacks: {
+ title: function (a, d) {
+ return a[0].element.x.toPrecision(4);
+ },
+ label: function (d) {
+ return d.dataset.label + ": " + d.element.y.toPrecision(4);
+ },
+ },
+ },
+
+ },
+};
+
+export function AuceChartDataVsTime({ auces, biomarker_type }) {
+ const classes = useStyles();
+ const renderChart = true;
+
+ const datasets = auces.map((auce, i) => {
+ const subjectsDisplay = biomarker_type.data.subjects.map((id) =>
+ auce.subject_ids.includes(id)
+ );
+ const subjectsDisplayFilter = (_, i) => subjectsDisplay[i];
+ const times = biomarker_type.data.times.filter(subjectsDisplayFilter);
+ const values = biomarker_type.data.values.filter(subjectsDisplayFilter);
+ return {
+ borderColor: getColor(i),
+ backgroundColor: getColorBackground(i),
+ label: auce.name,
+ data: values.map((y, i) => ({ x: times[i], y: y })),
+ };
+ });
+
+ const data = { datasets };
+
+ const optionsVsTime = {
+ ...options,
+ scales: {
+ x: {
+ type: "linear",
+ title: {
+ text: "Time ",
+ display: true,
+ },
+ },
+ y: {
+ type: "linear",
+ position: "left",
+ title: {
+ text: "Data Variable",
+ display: true,
+ },
+ },
+ },
+ plugins: {
+ ...options.plugins,
+ crosshair: {
+ sync: {
+ enabled: false,
+ },
+ },
+ }
+ };
+
+ return (
+
+ {renderChart && }
+
+ );
+}
+
+export function AuceChartFitsVsConcentration({ auces, biomarker_type }) {
+ const classes = useStyles();
+ const renderChart = true;
+
+ let datasets = [];
+ var i = 0;
+ for (const auce of auces) {
+ const data = auce.x ? auce.x.map((x, i) => ({ x: x, y: auce.y[i] })) : null;
+ const dataLower = auce.x
+ ? auce.x.map((x, i) => ({ x: x, y: auce.y_lower[i] }))
+ : null;
+ const dataUpper = auce.x
+ ? auce.x.map((x, i) => ({ x: x, y: auce.y_upper[i] }))
+ : null;
+ const dataPoints = auce.auce
+ ? auce.concentrations.map((x, i) => ({ x: x, y: auce.auce[i] }))
+ : null;
+ if (data) {
+ datasets.push({
+ borderColor: getColor(i),
+ backgroundColor: getColorBackground(i),
+ label: "noLabel" + auce.name + "Fit",
+ pointRadius: 0,
+ fill: false,
+ type: "line",
+ data: data,
+ });
+ }
+ if (dataLower) {
+ datasets.push({
+ borderColor: getColorBackground(i),
+ backgroundColor: getColorBackground(i),
+ type: "line",
+ pointRadius: 0,
+ fill: false,
+ label: "noLabel" + auce.name + "Lower",
+ data: dataLower,
+ });
+ }
+ if (dataUpper) {
+ datasets.push({
+ borderColor: getColorBackground(i),
+ backgroundColor: getColorBackground(i),
+ type: "line",
+ pointRadius: 0,
+ fill: "-1", // fill to previous dataset
+ //fill: false,
+ label: "noLabel" + auce.name + "Upper",
+ data: dataUpper,
+ });
+ }
+ if (dataPoints) {
+ datasets.push({
+ borderColor: getColor(i),
+ backgroundColor: getColor(i),
+ label: auce.name,
+ data: dataPoints,
+ });
+ }
+ i += 1;
+ }
+
+ const data = { datasets };
+
+ const optionsVsConcentration = {
+ ...options,
+ scales: {
+ x: {
+ type: "logarithmic",
+ title: {
+ text: "Concentration",
+ display: true,
+ },
+ },
+ y: {
+ type: "logarithmic",
+ position: "left",
+ title: {
+ text: "AUCE",
+ display: true,
+ },
+ },
+ },
+ plugins: {
+ ...options.plugins,
+ crosshair: false,
+ }
+ };
+
+ return (
+
+ {renderChart && }
+
+ );
+}
diff --git a/frontend/src/features/dataAnalysis/AuceDetail.js b/frontend/src/features/dataAnalysis/AuceDetail.js
new file mode 100644
index 00000000..7a962ea2
--- /dev/null
+++ b/frontend/src/features/dataAnalysis/AuceDetail.js
@@ -0,0 +1,101 @@
+import React, { useEffect, useState } from "react";
+import { useSelector } from "react-redux";
+import Alert from '@mui/material/Alert';
+import makeStyles from '@mui/styles/makeStyles';
+
+import Select from "@mui/material/Select";
+import InputLabel from "@mui/material/InputLabel";
+import MenuItem from "@mui/material/MenuItem";
+import FormControl from "@mui/material/FormControl";
+
+import { AuceChartDataVsTime, AuceChartFitsVsConcentration } from "./AuceChart";
+import {
+ selectBiomarkerTypesByDatasetId,
+ selectBiomarkerTypeById,
+} from "../datasets/biomarkerTypesSlice";
+
+import { api } from "../../Api";
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ marginTop: theme.spacing(2),
+ flexGrow: 1,
+ },
+ formControl: {
+ margin: theme.spacing(1),
+ minWidth: 120,
+ },
+}));
+
+export default function AuceDetail({ project, dataset }) {
+ const classes = useStyles();
+ const [auce, setAuce] = useState([]);
+ const [apiError, setApiError] = useState(null);
+ const [biomarkerTypeId, setBiomarkerTypeId] = useState(null);
+ const biomarker_type = useSelector((state) =>
+ biomarkerTypeId ? selectBiomarkerTypeById(state, biomarkerTypeId) : null
+ );
+
+ const biomarkerTypes = useSelector((state) =>
+ selectBiomarkerTypesByDatasetId(state, dataset.id)
+ );
+
+ useEffect(() => {
+ if (biomarkerTypeId != null) {
+ api
+ .post(`/api/auce/`, {
+ biomarker_type_id: biomarkerTypeId,
+ })
+ .then(setAuce)
+ .catch((data) => setApiError(data["biomarker_type_id"]));
+ }
+ }, [biomarkerTypeId]);
+
+ const handleBiomarkerTypeChange = (event) => {
+ setBiomarkerTypeId(event.target.value);
+ };
+
+ const fitErrors = auce
+ .map((x) => (x.x ? null : `Sigmoid fit failed for ${x.name}`))
+ .filter((x) => x);
+
+ return (
+
+
+ Variable
+
+ {biomarkerTypes.map((bt, i) => {
+ return (
+
+ {bt.name}
+
+ );
+ })}
+
+
+
+ {apiError &&
{apiError} }
+ {fitErrors &&
+ fitErrors.map((fitError, i) => (
+
+ {fitError}
+
+ ))}
+
+ {auce && (
+
+ )}
+
+ {auce && (
+
+ )}
+
+ );
+}
diff --git a/frontend/src/features/dataAnalysis/NcaChart.js b/frontend/src/features/dataAnalysis/NcaChart.js
new file mode 100644
index 00000000..326ccab7
--- /dev/null
+++ b/frontend/src/features/dataAnalysis/NcaChart.js
@@ -0,0 +1,295 @@
+import React from "react";
+import makeStyles from '@mui/styles/makeStyles';
+
+import { Scatter } from "react-chartjs-2";
+
+import { getColor, getColorBackground } from "../modelling/ShapesAndColors";
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ position: 'relative',
+ margin: 'auto',
+ height: '60vh',
+ },
+}));
+
+let options = {
+ animation: {
+ duration: 0,
+ },
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ x: {
+ type: "linear",
+ title: {
+ text: "Time ",
+ display: true,
+ },
+ },
+ y: {
+ position: "left",
+ title: {
+ text: "Data Variable / Model Output (units defined in detail panels)",
+ display: true,
+ },
+ },
+ },
+ plugins: {
+ legend: {
+ labels: {
+ usePointStyle: true,
+ },
+ },
+ tooltip: {
+ mode: "interpolate",
+ callbacks: {
+ label: function (context) {
+ const tooltipText = context.dataset.tooltipText;
+ if (tooltipText) {
+ return tooltipText;
+ }
+ return `(${context.parsed.x}, ${context.parsed.y})`;
+ },
+ },
+ },
+ },
+};
+
+export function NcaChart({ nca, biomarker_type, subject, mode }) {
+ const classes = useStyles();
+ const renderChart = true;
+
+ const first_point = [nca.times[0], nca.concentrations[0]];
+ const last_point = [
+ nca.times[nca.times.length - 1],
+ nca.concentrations[nca.concentrations.length - 1],
+ ];
+
+ const max_point = [nca.t_max, nca.c_max];
+
+ let before = [first_point, [0.0, nca.c_0]];
+ if (before[0][0] === 0.0) {
+ before = [before[1]];
+ }
+
+ const after = [
+ last_point,
+ [last_point[0] + 0.5 * nca.t_half, last_point[1] * 0.75],
+ [last_point[0] + nca.t_half, last_point[1] * 0.5],
+ ];
+
+ let datasets = [];
+
+ // main scatter plot
+ if (mode !== "aucm") {
+ datasets.push({
+ borderColor: getColor(0),
+ backgroundColor: getColorBackground(0),
+ fill: mode === "auc",
+ label:
+ biomarker_type.name + " Concentration for ID " + subject.id_in_dataset,
+ data: nca.concentrations.map((y, i) => ({
+ x: nca.times[i],
+ y: y,
+ })),
+ });
+ }
+
+ const rounding = 3;
+ const c0_text = "C_0 = " + nca.c_0.toPrecision(rounding);
+ const lambdaz_text = [
+ "Lambda_z = " + nca.lambda_z.toPrecision(rounding),
+ "T_half = " + nca.t_half.toPrecision(rounding),
+ "Num_points = " + nca.num_points,
+ "R2 = " + nca.r2.toPrecision(rounding),
+ ];
+ const t_half_text = "T_half = " + nca.t_half.toPrecision(rounding);
+
+ if (mode === "extrapolation") {
+ datasets.push({
+ borderColor: getColor(1),
+ backgroundColor: getColor(1),
+ label: "Extrapolation before",
+ tooltipText: c0_text,
+ data: before.map((pt, i) => ({
+ x: pt[0],
+ y: pt[1],
+ })),
+ });
+
+ datasets.push({
+ borderColor: getColor(1),
+ backgroundColor: getColor(1),
+ label: "Extrapolation after",
+ type: "line",
+ tooltipText: t_half_text,
+ lineTension: 0,
+ interpolate: true,
+ data: after.map((pt, i) => ({
+ x: pt[0],
+ y: pt[1],
+ })),
+ });
+
+ datasets.push({
+ borderColor: getColor(2),
+ backgroundColor: getColorBackground(2),
+ label: "Extrapolation",
+ tooltipText: lambdaz_text,
+ lineTension: 0,
+ interpolate: true,
+ data: [
+ { x: after[0][0], y: after[0][1] },
+ { x: after[2][0], y: after[2][1] },
+ ],
+ });
+ }
+
+ if (mode === "aucm") {
+ const first_moment_y = nca.concentrations.map((c, i) => c * nca.times[i]);
+ datasets.push({
+ borderColor: getColor(3),
+ backgroundColor: getColorBackground(3),
+ label: "First Moment",
+ fill: true,
+ lineTension: 0,
+ interpolate: true,
+ data: first_moment_y.map((fm, i) => ({
+ x: nca.times[i],
+ y: fm,
+ })),
+ });
+
+ datasets.push({
+ borderColor: getColor(4),
+ backgroundColor: getColorBackground(4),
+ label: "Extrapolation before",
+ tooltipText: c0_text,
+ lineTension: 0,
+ interpolate: true,
+ data: before.map((pt, i) => ({
+ x: pt[0],
+ y: pt[1] * pt[0],
+ })),
+ });
+
+ datasets.push({
+ borderColor: getColor(5),
+ backgroundColor: getColorBackground(5),
+ label: "Extrapolation after",
+ type: "line",
+ tooltipText: t_half_text,
+ lineTension: 0,
+ interpolate: true,
+ data: after.map((pt, i) => ({
+ x: pt[0],
+ y: pt[1] * pt[0],
+ })),
+ });
+
+ const aumcHoverPoint = [
+ 0.5 * (Math.max(...nca.times) + Math.min(...nca.times)),
+ 0.5 * Math.max(...first_moment_y),
+ ];
+ const aumcText = "AUMC_0_last = " + nca.aumc_0_last.toPrecision(rounding);
+
+ datasets.push({
+ borderColor: getColor(6),
+ backgroundColor: getColorBackground(6),
+ label: "AUMC_0_last",
+ tooltipText: aumcText,
+ data: [
+ {
+ x: aumcHoverPoint[0],
+ y: aumcHoverPoint[1],
+ },
+ ],
+ });
+
+ const aumcInfHoverPoint = [
+ last_point[0] * 1.05,
+ last_point[1] * last_point[0] * 0.5,
+ ];
+ const aumcInfText = [
+ "AUMC = " + nca.aumc.toPrecision(rounding),
+ "AUMC_extrap_percent = " + nca.aumc_extrap_percent.toPrecision(rounding),
+ ];
+
+ datasets.push({
+ borderColor: getColor(8),
+ backgroundColor: getColorBackground(8),
+ label: "AUMC",
+ tooltipText: aumcInfText,
+ data: [
+ {
+ x: aumcInfHoverPoint[0],
+ y: aumcInfHoverPoint[1],
+ },
+ ],
+ });
+ }
+
+ if (mode === "auc") {
+ const aucHoverPoint = [max_point[0], 0.5 * max_point[1]];
+ const aucText = "AUC_0_last = " + nca.auc_0_last.toPrecision(rounding);
+
+ datasets.push({
+ borderColor: getColor(6),
+ backgroundColor: getColorBackground(6),
+ label: "AUC_0_last",
+ tooltipText: aucText,
+ data: [
+ {
+ x: aucHoverPoint[0],
+ y: aucHoverPoint[1],
+ },
+ ],
+ });
+
+ const aucInfHoverPoint = [last_point[0] * 1.05, last_point[1] * 0.5];
+ const aucInfText = [
+ "AUC = " + nca.auc_infinity.toPrecision(rounding),
+ "AUC_infinity_dose = " + nca.auc_infinity_dose.toPrecision(rounding),
+ "AUC_extrap_percent = " + nca.auc_extrap_percent.toPrecision(rounding),
+ ];
+
+ datasets.push({
+ borderColor: getColor(7),
+ backgroundColor: getColorBackground(7),
+ label: "AUC",
+ tooltipText: aucInfText,
+ data: [
+ {
+ x: aucInfHoverPoint[0],
+ y: aucInfHoverPoint[1],
+ },
+ ],
+ });
+ }
+
+ if (mode === "tmax") {
+ const tmax_text = "T_max = " + max_point[0];
+ const cmax_text = "C_max = " + max_point[1];
+
+ datasets.push({
+ borderColor: getColor(8),
+ backgroundColor: getColorBackground(8),
+ label: "T_max/C_max",
+ tooltipText: [tmax_text, cmax_text],
+ data: [
+ { x: max_point[0], y: 0 },
+ { x: max_point[0], y: max_point[1] },
+ { x: 0, y: max_point[1] },
+ ],
+ });
+ }
+
+ const data = { datasets };
+
+ return (
+
+ {renderChart && }
+
+ );
+}
diff --git a/frontend/src/features/dataAnalysis/NcaDetail.js b/frontend/src/features/dataAnalysis/NcaDetail.js
new file mode 100644
index 00000000..48720351
--- /dev/null
+++ b/frontend/src/features/dataAnalysis/NcaDetail.js
@@ -0,0 +1,167 @@
+import React, { useEffect, useState } from "react";
+import { useSelector } from "react-redux";
+import makeStyles from '@mui/styles/makeStyles';
+
+import Select from "@mui/material/Select";
+import InputLabel from "@mui/material/InputLabel";
+import MenuItem from "@mui/material/MenuItem";
+import FormControl from "@mui/material/FormControl";
+
+import { NcaChart } from "./NcaChart";
+import {
+ selectProtocolById,
+} from "../protocols/protocolsSlice";
+import {
+ selectDatasetById,
+} from "../datasets/datasetsSlice";
+import {
+ selectBiomarkerTypesByDatasetId,
+ selectBiomarkerTypeById,
+} from "../datasets/biomarkerTypesSlice";
+
+import { selectSubjectById } from "../datasets/subjectsSlice";
+
+import { api } from "../../Api";
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ marginTop: theme.spacing(2),
+ flexGrow: 1,
+ },
+ formControl: {
+ margin: theme.spacing(1),
+ minWidth: 120,
+ },
+}));
+
+export default function NcaDetail({ project, dataset }) {
+ const classes = useStyles();
+ const [nca, setNca] = useState(null);
+ const [subjectId, setSubjectId] = useState(null);
+ const [mode, setMode] = useState("data");
+ const modeOptions = [
+ { key: "Data", value: "data" },
+ { key: "Maximum and Extrapolation", value: "extrapolation" },
+ { key: "Area Under the Curve", value: "auc" },
+ { key: "Area Under the First Moment", value: "aucm" },
+ ];
+
+ const [biomarkerTypeId, setBiomarkerTypeId] = useState(null);
+ const biomarker_type = useSelector((state) =>
+ biomarkerTypeId ? selectBiomarkerTypeById(state, biomarkerTypeId) : null
+ );
+
+
+ const subject = useSelector((state) =>
+ subjectId ? selectSubjectById(state, subjectId) : null
+ );
+
+ const biomarkerTypes = useSelector((state) =>
+ selectBiomarkerTypesByDatasetId(state, dataset.id)
+ );
+
+ const subjectsEntities = useSelector((state) => state.subjects.entities);
+
+ const subjectsInBiomarkerType = biomarkerTypeId
+ ? [... new Set(biomarker_type.data.subjects)]
+ : [];
+
+ const subjectOptions = subjectsInBiomarkerType.filter(s_id =>
+ (subjectsEntities[s_id].protocol)
+ ).map(s_id => ({
+ key: subjectsEntities[s_id].id_in_dataset, value: s_id
+ }))
+
+ useEffect(() => {
+ if (biomarkerTypeId != null && subjectId != null) {
+ api
+ .post(`/api/nca/`, {
+ biomarker_type_id: biomarkerTypeId,
+ subject_id: subjectId,
+ })
+ .then(setNca);
+ } else {
+ setNca(null)
+ }
+ }, [biomarkerTypeId, subjectId]);
+
+ const handleSubjectChange = (event) => {
+ setSubjectId(event.target.value);
+ };
+ const handleBiomarkerTypeChange = (event) => {
+ setBiomarkerTypeId(event.target.value);
+ setSubjectId(null);
+ };
+ const handleModeChange = (event) => {
+ setMode(event.target.value);
+ };
+
+ console.log("nca", nca);
+
+ return (
+
+
+ Variable
+
+ {biomarkerTypes.map((bt, i) => {
+ return (
+
+ {bt.name}
+
+ );
+ })}
+
+
+
+
+ Subject
+
+ {subjectOptions.map((s, i) => {
+ return (
+
+ {s.key}
+
+ );
+ })}
+
+
+
+
+ {nca && subject && (
+
+ Show
+
+ {modeOptions.map((mode, i) => {
+ return (
+
+ {mode.key}
+
+ );
+ })}
+
+
+ )}
+
+ {nca && subject && (
+
+ )}
+
+ );
+}
diff --git a/frontend/src/features/datasets/BiomarkerTypeSubform.js b/frontend/src/features/datasets/BiomarkerTypeSubform.js
new file mode 100644
index 00000000..01b08e4e
--- /dev/null
+++ b/frontend/src/features/datasets/BiomarkerTypeSubform.js
@@ -0,0 +1,136 @@
+import React, { useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import IconButton from "@mui/material/IconButton";
+import { useForm, useFormState } from "react-hook-form";
+import SaveIcon from "@mui/icons-material/Save";
+import Stack from "@mui/material/Stack";
+import Grid from "@mui/material/Grid";
+
+import {
+ FormCheckboxField,
+ FormTextField,
+ FormSelectField,
+} from "../forms/FormComponents";
+import { selectUnitById } from "../projects/unitsSlice";
+import {
+ selectBiomarkerTypeById,
+ updateBiomarkerType,
+} from "./biomarkerTypesSlice";
+
+export default function BiomarkerTypeSubform({ biomarker_id, disableSave }) {
+ const dispatch = useDispatch();
+ let biomarker_type = useSelector((state) =>
+ selectBiomarkerTypeById(state, biomarker_id)
+ );
+ if (!biomarker_type) {
+ biomarker_type = {
+ default_value: false,
+ axis: false,
+ };
+ }
+ const unit_id = biomarker_type ? biomarker_type.display_unit : 1;
+ let unit = useSelector((state) => selectUnitById(state, unit_id));
+ if (!unit) {
+ unit = {
+ symbol: "X",
+ compatible_units: [],
+ };
+ }
+ const unitOptions = unit.compatible_units.map((u) => {
+ return { key: u.symbol, value: u.id };
+ });
+
+ const time_unit_id = biomarker_type ? biomarker_type.display_time_unit : 1;
+ let time_unit = useSelector((state) => selectUnitById(state, time_unit_id));
+ if (!time_unit) {
+ time_unit = {
+ symbol: "X",
+ compatible_units: [],
+ };
+ }
+ const timeUnitOptions = time_unit.compatible_units.map((u) => {
+ return { key: u.symbol, value: u.id };
+ });
+
+ const { control, handleSubmit, reset } = useForm({
+ defaultValues: {
+ id: biomarker_type.id,
+ display: biomarker_type.display,
+ name: biomarker_type.name,
+ color: biomarker_type.color,
+ display_unit: biomarker_type.display_unit,
+ display_time_unit: biomarker_type.display_time_unit,
+ axis: biomarker_type.axis,
+ },
+ });
+
+ const { isDirty } = useFormState({ control });
+
+ useEffect(() => {
+ reset(biomarker_type);
+ }, [reset, biomarker_type]);
+
+ const onSubmit = (values) => {
+ console.log("submit biomarker_type", values);
+ dispatch(updateBiomarkerType(values));
+ };
+
+ const axisOptions = [
+ { value: false, key: "LHS" },
+ { value: true, key: "RHS" },
+ ];
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {isDirty && (
+
+
+
+ )}
+
+
+ );
+}
diff --git a/frontend/src/features/datasets/DatasetDetail.js b/frontend/src/features/datasets/DatasetDetail.js
new file mode 100644
index 00000000..8ecc46b4
--- /dev/null
+++ b/frontend/src/features/datasets/DatasetDetail.js
@@ -0,0 +1,221 @@
+import React, { useEffect } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import Button from "@mui/material/Button";
+import Grid from "@mui/material/Grid";
+import Box from "@mui/material/Box";
+import Alert from '@mui/material/Alert';
+import { useForm } from "react-hook-form";
+import makeStyles from '@mui/styles/makeStyles';
+import Typography from "@mui/material/Typography";
+import List from "@mui/material/List";
+import ListItem from "@mui/material/ListItem";
+import Dialog from "@mui/material/Dialog";
+import DialogTitle from "@mui/material/DialogTitle";
+import DialogActions from "@mui/material/DialogActions";
+import Tab from "@mui/material/Tab";
+import Tabs from "@mui/material/Tabs";
+import Stack from "@mui/material/Stack";
+
+import Accordion from "@mui/material/Accordion";
+import AccordionSummary from "@mui/material/AccordionSummary";
+import Paper from "@mui/material/Paper";
+import AccordionDetails from "@mui/material/AccordionDetails";
+import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
+
+import Header from "../modelling/Header";
+import Footer from "../modelling/Footer";
+import SubjectsTable from "./SubjectsTable";
+import BiomarkerTypeSubform from "./BiomarkerTypeSubform";
+
+import AuceDetail from "../dataAnalysis/AuceDetail"
+import NcaDetail from "../dataAnalysis/NcaDetail"
+
+import { userHasReadOnlyAccess } from "../projects/projectsSlice";
+
+import {
+ updateDataset,
+ uploadDatasetCsv,
+ deleteDataset,
+} from "../datasets/datasetsSlice";
+import { FormTextField, FormDateTimeField } from "../forms/FormComponents";
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ width: "100%",
+ padding: theme.spacing(2),
+ maxHeight: '75vh', overflow: 'auto'
+ },
+ rootTab: {
+ width: "100%",
+ padding: theme.spacing(2),
+ height: '75vh', overflow: 'auto'
+ },
+ paper: {
+ padding: theme.spacing(2)
+ },
+ tabs: {
+ backgroundColor: theme.palette.primary.main,
+ color: theme.palette.primary.contrastText,
+ borderBottom: 1,
+ borderColor: 'divider',
+ },
+ dialogFooter: {
+ }
+}));
+
+function TabPanel(props) {
+ const { children, value, index, ...other } = props;
+
+ return (
+
+ {value === index && (
+
+ {children}
+
+ )}
+
+ );
+}
+
+function a11yProps(index: number) {
+ return {
+ id: `simple-tab-${index}`,
+ 'aria-controls': `simple-tabpanel-${index}`,
+ };
+}
+
+function DataAnalysisDialog({ project, onClose, dataset, open }) {
+ const classes = useStyles();
+ const [value, setValue] = React.useState(0);
+ const handleClose = () => {
+ onClose();
+ };
+
+ const handleChange = (event, newValue) => {
+ setValue(newValue);
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Close
+
+
+
+ );
+}
+
+
+export default function DatasetDetail({ project, dataset }) {
+ const { control, handleSubmit, reset } = useForm();
+ const dispatch = useDispatch();
+
+ const [openDataAnalysis, setOpenDataAnalysis] = React.useState(false);
+ const handleDataAnalysis = () => {
+ setOpenDataAnalysis(true);
+ };
+ const handleCloseDataAnalysis = () => {
+ setOpenDataAnalysis(false);
+ };
+
+ useEffect(() => {
+ reset(dataset);
+ }, [reset, dataset]);
+
+
+ const handleDatasetDelete = () => {
+ dispatch(deleteDataset(dataset.id));
+ };
+
+ const handleFileUpload = (event) => {
+ console.log(event)
+ const files = Array.from(event.target.files);
+ const [file] = files;
+ dispatch(uploadDatasetCsv({ id: dataset.id, csv: file }));
+ };
+
+ const onSubmit = (values) => {
+ dispatch(updateDataset(values));
+ };
+
+ const disableSave = useSelector(state => userHasReadOnlyAccess(state, project));
+
+ return (
+
+
+
+ );
+}
diff --git a/frontend/src/features/datasets/SubjectSubform.js b/frontend/src/features/datasets/SubjectSubform.js
new file mode 100644
index 00000000..933a909e
--- /dev/null
+++ b/frontend/src/features/datasets/SubjectSubform.js
@@ -0,0 +1,78 @@
+import React,{ useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import IconButton from "@mui/material/IconButton";
+import { useForm, useFormState } from "react-hook-form";
+import SaveIcon from "@mui/icons-material/Save";
+import AddIcon from "@mui/icons-material/Add";
+import DoneIcon from "@mui/icons-material/Done";
+import TableCell from "@mui/material/TableCell";
+import TableRow from "@mui/material/TableRow";
+
+import { FormCheckboxField, FormTextField } from "../forms/FormComponents";
+import { selectSubjectById, updateSubject } from "./subjectsSlice";
+import { selectDatasetProtocolById } from "../protocols/DatasetProtocols";
+
+export default function SubjectSubform({ subject, disableSave, dataset }) {
+ const dispatch = useDispatch();
+
+ const { control, handleSubmit, reset } = useForm({
+ defaultValues: {
+ id: subject.id,
+ display: subject.display,
+ name: subject.name,
+ shape: subject.shape,
+ },
+ });
+
+
+ const { isDirty } = useFormState({ control });
+
+ const onSubmit = (values) => {
+ console.log("submit subject", values);
+ dispatch(updateSubject(values));
+ };
+
+ useEffect(() => {
+ reset(subject);
+ }, [reset, subject]);
+
+ const protocol = dataset.protocols.find(p => p.id === subject.protocol)
+
+ return (
+
+
+ {subject.id_in_dataset}
+
+
+ {protocol?.name}
+
+
+
+
+
+
+
+
+ {isDirty && (
+
+
+
+ )}
+
+
+ );
+}
diff --git a/frontend/src/features/datasets/SubjectsTable.js b/frontend/src/features/datasets/SubjectsTable.js
new file mode 100644
index 00000000..e8a7ac20
--- /dev/null
+++ b/frontend/src/features/datasets/SubjectsTable.js
@@ -0,0 +1,80 @@
+import React, { useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import Paper from "@mui/material/Paper";
+import Button from "@mui/material/Button";
+import IconButton from "@mui/material/IconButton";
+import { useForm, useFieldArray } from "react-hook-form";
+import makeStyles from '@mui/styles/makeStyles';
+import DeleteIcon from "@mui/icons-material/Delete";
+import AddIcon from "@mui/icons-material/Add";
+import Typography from "@mui/material/Typography";
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableContainer from "@mui/material/TableContainer";
+import TableHead from "@mui/material/TableHead";
+import TableRow from "@mui/material/TableRow";
+
+import { selectUnitById } from "../projects/unitsSlice";
+import { FormTextField, FormSelectField } from "../forms/FormComponents";
+import SubjectSubform from "./SubjectSubform";
+
+import { userHasReadOnlyAccess } from "../projects/projectsSlice";
+
+import { updateProtocol, deleteProtocol } from "../protocols/protocolsSlice.js";
+import { selectSubjectsByDataset } from "../datasets/subjectsSlice";
+
+const useStyles = makeStyles((theme) => ({
+ table: {
+ width: "100%",
+ },
+ tableCell: {
+ width: "100pt",
+ },
+ controls: {
+ display: "flex",
+ alignItems: "center",
+ paddingLeft: theme.spacing(1),
+ paddingBottom: theme.spacing(1),
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ },
+}));
+
+
+export default function SubjectsTable ({ dataset, disableSave }) {
+
+ const classes = useStyles();
+ const subjects = useSelector((state) => selectSubjectsByDataset(state, dataset));
+
+ return (
+
+ Subjects
+
+
+
+
+ Id
+ Protocol
+ Display
+ Shape
+ Actions
+
+
+
+ {subjects.map((subject, index) => (
+
+ ))}
+
+
+
+
+ )
+}
+
diff --git a/frontend/src/features/datasets/biomarkerTypesSlice.js b/frontend/src/features/datasets/biomarkerTypesSlice.js
new file mode 100644
index 00000000..1e8eb7ac
--- /dev/null
+++ b/frontend/src/features/datasets/biomarkerTypesSlice.js
@@ -0,0 +1,104 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+
+const biomarkerTypesAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = biomarkerTypesAdapter.getInitialState({
+ status: "idle",
+ error: null,
+});
+
+export const fetchBiomarkerType = createAsyncThunk(
+ "biomarkerTypes/fetchBiomarkerType",
+ async (biomarkerTypeId, { getState }) => {
+ const response = await api.get(`/api/biomarker_type/${biomarkerTypeId}/`, getState().login.csrf);
+ return response;
+ }
+);
+
+export const fetchBiomarkerTypesByProject = createAsyncThunk(
+ "biomarkerTypes/fetchBiomarkerTypesByProject",
+ async (project_id, { getState }) => {
+ const response = await api.get(
+ `/api/biomarker_type/?project_id=${project_id}`, getState().login.csrf
+ );
+ return response;
+ }
+);
+
+export const fetchBiomarkerTypesByDataset = createAsyncThunk(
+ "subjects/fetchBiomarkerTypeByDataset",
+ async (dataset, { getState }) => {
+ const response = await api.get(
+ `/api/biomarker_type/`, getState().login.csrf,
+ dataset.biomarker_types
+ );
+ return response;
+ }
+);
+
+export const updateBiomarkerType = createAsyncThunk(
+ "biomarkerTypes/updateBiomarkerType",
+ async (biomarker_type, { getState }) => {
+ const response = await api.put(
+ `/api/biomarker_type/${biomarker_type.id}/`, getState().login.csrf,
+ biomarker_type
+ );
+ return response;
+ }
+);
+
+export const biomarkerTypesSlice = createSlice({
+ name: "biomarkerTypes",
+ initialState,
+ reducers: {
+ updateOne: biomarkerTypesAdapter.updateOne,
+ },
+ extraReducers: {
+ [fetchBiomarkerType.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchBiomarkerType.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [fetchBiomarkerType.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ biomarkerTypesAdapter.addOne(state, action.payload);
+ },
+ [fetchBiomarkerTypesByProject.fulfilled]: biomarkerTypesAdapter.upsertMany,
+ [fetchBiomarkerTypesByDataset.fulfilled]: biomarkerTypesAdapter.upsertMany,
+ [updateBiomarkerType.fulfilled]: biomarkerTypesAdapter.upsertOne,
+ },
+});
+
+export const { updateOne: updateBiomarkerTypeById } =
+ biomarkerTypesSlice.actions;
+
+export default biomarkerTypesSlice.reducer;
+
+export const {
+ selectAll: selectAllBiomarkerTypes,
+ selectById: selectBiomarkerTypeById,
+ selectIds: selectBiomarkerTypeIds,
+} = biomarkerTypesAdapter.getSelectors((state) => state.biomarkerTypes);
+
+export const selectBiomarkerTypesByDatasetId = (state, id) => {
+ return selectAllBiomarkerTypes(state).filter((bd) => bd.dataset === id);
+};
+
+export const selectBiomarkerTypesByDatasetIds = (state, ids) => {
+ const datas = selectAllBiomarkerTypes(state).filter((bd) =>
+ ids.includes(bd.dataset)
+ );
+ return ids.reduce((sum, id) => {
+ sum[id] = datas.filter((bd) => bd.dataset === id);
+ return sum;
+ }, {});
+};
diff --git a/frontend/src/features/datasets/datasetsSlice.js b/frontend/src/features/datasets/datasetsSlice.js
new file mode 100644
index 00000000..8253927c
--- /dev/null
+++ b/frontend/src/features/datasets/datasetsSlice.js
@@ -0,0 +1,185 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { fetchBiomarkerTypesByProject, fetchBiomarkerTypesByDataset } from "./biomarkerTypesSlice";
+import { fetchSubjectByProject, fetchSubjectByDataset } from "./subjectsSlice";
+import { setSelected } from "../modelling/modellingSlice";
+import { api } from "../../Api";
+
+const datasetsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = datasetsAdapter.getInitialState({
+ status: "idle",
+ error: null,
+});
+
+export const fetchDatasets = createAsyncThunk(
+ "datasets/fetchDatasets",
+ async (project_id, { dispatch, getState }) => {
+ const response = await api.get(`/api/dataset/?project_id=${project_id}`, getState().login.csrf);
+
+ dispatch(fetchBiomarkerTypesByProject(project_id));
+ dispatch(fetchSubjectByProject(project_id));
+
+ return response;
+ }
+);
+
+export const fetchDatasetById = createAsyncThunk(
+ "datasets/fetchDatasetById",
+ async (datasetId, { dispatch, getState }) => {
+ dispatch(fetchBiomarkerTypesByDataset(datasetId));
+ dispatch(fetchSubjectByDataset(datasetId));
+ const response = await api.get(`/api/dataset/${datasetId}/`, getState().login.csrf);
+ return response;
+ }
+);
+
+export const deleteDataset = createAsyncThunk(
+ "datasets/deleteDataset",
+ async (datasetId, { dispatch, getState }) => {
+ let { modelling } = getState()
+ if (modelling.selectedType === 'dataset' && modelling.selectedId === datasetId) {
+ await dispatch(setSelected({id: null, type: null}))
+ }
+ await api.delete(`/api/dataset/${datasetId}`, getState().login.csrf);
+ return datasetId;
+ }
+);
+
+export const addNewDataset = createAsyncThunk(
+ "datasets/addNewDataset",
+ async (project, { dispatch, getState }) => {
+ const initialDataset = {
+ name: "new",
+ project: project.id,
+ };
+ let dataset = await api.post("/api/dataset/", getState().login.csrf, initialDataset);
+ return dataset;
+ }
+);
+
+export const uploadDatasetCsv = createAsyncThunk(
+ "datasets/uploadDatasetCsv",
+ async ({ id, csv }, { dispatch, rejectWithValue, getState }) => {
+ try {
+ const dataset = await api
+ .putMultiPart(`/api/dataset/${id}/csv/`, getState().login.csrf, { csv })
+ await dispatch(fetchBiomarkerTypesByProject(dataset.project));
+ await dispatch(fetchSubjectByDataset(dataset));
+ return dataset;
+ } catch (err) {
+ return rejectWithValue(err)
+ }
+ }
+);
+
+export const updateDataset = createAsyncThunk(
+ "datasets/updateDataset",
+ async (dataset, { getState }) => {
+ const response = await api.put(`/api/dataset/${dataset.id}/`, getState().login.csrf, dataset);
+ return response;
+ }
+);
+
+export const datasetsSlice = createSlice({
+ name: "datasets",
+ initialState,
+ reducers: {
+ toggleDataset(state, action) {
+ let dataset = state.entities[action.payload.id];
+ dataset.chosen = !dataset.chosen;
+ },
+ setSelectDataset(state, action) {
+ console.log("setSelectDataset", action.payload)
+ let dataset = state.entities[action.payload.id];
+ dataset.selected = action.payload.select;
+ },
+ toggleProtocol(state, action) {
+ const dataset_id = action.payload.dataset
+ let dataset = state.entities[dataset_id];
+ let protocol = dataset.protocols.find(p => p.id === action.payload.id)
+ protocol.chosen = !protocol.chosen;
+ },
+ setSelectDatasetProtocol(state, action) {
+ const dataset_id = action.payload.dataset
+ let dataset = state.entities[dataset_id];
+ let protocol = dataset.protocols.find(p => p.id === action.payload.id)
+ protocol.select = action.payload.select;
+ },
+ toggleDisplayGroup(state, action) {
+ const group = action.payload.group;
+ const id = action.payload.id;
+ const displayGroups = state.entities[id].displayGroups;
+ console.log("toggleDisplayGroup", group, id, displayGroups);
+
+ let newDisplayGroups = displayGroups.filter((x) => x !== group);
+ if (newDisplayGroups.length === displayGroups.length) {
+ newDisplayGroups.push(group);
+ }
+ const changes = { displayGroups: newDisplayGroups };
+ datasetsAdapter.updateOne(state, { id, changes });
+ },
+ },
+ extraReducers: {
+ [fetchDatasets.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchDatasets.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [fetchDatasets.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ datasetsAdapter.setAll(state, action.payload);
+ },
+ [fetchDatasetById.fulfilled]: datasetsAdapter.upsertOne,
+ [deleteDataset.fulfilled]: datasetsAdapter.removeOne,
+ [addNewDataset.fulfilled]: datasetsAdapter.addOne,
+ [updateDataset.fulfilled]: datasetsAdapter.upsertOne,
+ [uploadDatasetCsv.pending]: (state, action) => {
+ console.log("uploadcsv pending", action);
+ state.entities[action.meta.arg.id].status = "loading";
+ state.entities[action.meta.arg.id].errors = [];
+ },
+ [uploadDatasetCsv.rejected]: (state, action) => {
+ console.log("upload csv rejected", action);
+ state.entities[action.meta.arg.id].status = "rejected";
+ state.entities[action.meta.arg.id].errors = action.payload.csv;
+ },
+ [uploadDatasetCsv.fulfilled]: (state, action) => {
+ console.log("uploadcsv fulfilled", action);
+ state.entities[action.meta.arg.id].status = "succeeded";
+ datasetsAdapter.upsertOne(state, action);
+ },
+ },
+});
+
+export const { toggleDataset, toggleProtocol, setSelectDataset, toggleDisplayGroup: toggleDatasetDisplayGroup } =
+ datasetsSlice.actions;
+
+export default datasetsSlice.reducer;
+
+export const {
+ selectAll: selectAllDatasets,
+ selectById: selectDatasetById,
+ selectIds: selectDatasetIds,
+} = datasetsAdapter.getSelectors((state) => state.datasets);
+
+export const selectChosenDatasets = (state) =>
+ selectAllDatasets(state).filter((dataset) => dataset.chosen);
+
+
+export const selectChosenDatasetProtocols = (state) =>
+ selectAllDatasets(state).reduce((sum, dataset) => {
+ return sum.concat(dataset.protocols.filter(p => p.chosen))
+ }, []);
+
+export const selectAllProtocols = (state) =>
+ selectAllDatasets(state).reduce((sum, dataset) => {
+ return sum.concat(dataset.protocols)
+ }, []);
diff --git a/frontend/src/features/datasets/subjectsSlice.js b/frontend/src/features/datasets/subjectsSlice.js
new file mode 100644
index 00000000..6757aacf
--- /dev/null
+++ b/frontend/src/features/datasets/subjectsSlice.js
@@ -0,0 +1,94 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+
+const subjectsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = subjectsAdapter.getInitialState({
+ status: "idle",
+ error: null,
+});
+
+export const fetchSubject = createAsyncThunk(
+ "subjects/fetchSubject",
+ async (subjectId, { getState }) => {
+ console.log("fetchSubject", subjectId);
+ const response = await api.get(`/api/subject/${subjectId}/`, getState().login.csrf);
+ return response;
+ }
+);
+
+export const updateSubject = createAsyncThunk(
+ "subjects/updateSubject",
+ async (subject, {dispatch, getState}) => {
+ const response = await api.put(`/api/subject/${subject.id}/`, getState().login.csrf, subject);
+ return response;
+ }
+);
+
+export const fetchSubjectByProject = createAsyncThunk(
+ "subjects/fetchSubjectByProject",
+ async (project_id, { getState }) => {
+ const response = await api.get(`/api/subject/?project_id=${project_id}`, getState().login.csrf);
+ return response;
+ }
+);
+
+export const fetchSubjectByDataset = createAsyncThunk(
+ "subjects/fetchSubjectByDataset",
+ async (dataset, { getState }) => {
+ const response = await api.get(`/api/subject/`, dataset.subjects);
+ return response;
+ }
+);
+
+export const subjectsSlice = createSlice({
+ name: "subjects",
+ initialState,
+ reducers: {},
+ extraReducers: {
+ [fetchSubject.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchSubject.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [fetchSubject.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ subjectsAdapter.addOne(state, action.payload);
+ },
+ [fetchSubjectByProject.fulfilled]: subjectsAdapter.upsertMany,
+ [fetchSubjectByDataset.fulfilled]: subjectsAdapter.upsertMany,
+ [updateSubject.fulfilled]: subjectsAdapter.upsertOne,
+ },
+});
+
+export const {
+ setDisplayGroups: setSubjectDisplayGroups,
+ toggleDisplayGroup: toggleSubjectDisplayGroup,
+} = subjectsSlice.actions;
+
+export default subjectsSlice.reducer;
+
+export const {
+ selectAll: selectAllSubjects,
+ selectById: selectSubjectById,
+ selectIds: selectSubjectIds,
+} = subjectsAdapter.getSelectors((state) => state.subjects);
+
+export const selectSubjectDisplayGroups = (state) => {
+ return state.subjects.displayGroups;
+};
+
+export const selectSubjectsByDataset = (state, dataset) => {
+ return selectAllSubjects(state).filter((subject) => subject.dataset === dataset.id);
+};
+export const selectSubjectsByIds = (state, ids) => {
+ return ids.map(id => state.subjects.entities[id])
+}
diff --git a/frontend/src/features/forms/ComponentForm.js b/frontend/src/features/forms/ComponentForm.js
new file mode 100644
index 00000000..99f8bb54
--- /dev/null
+++ b/frontend/src/features/forms/ComponentForm.js
@@ -0,0 +1,67 @@
+import React from "react";
+import Grid from "@mui/material/Grid";
+import Typography from "@mui/material/Typography";
+import makeStyles from '@mui/styles/makeStyles';
+import List from "@mui/material/List";
+import ListItem from "@mui/material/ListItem";
+
+import MathJaxPreview from "react-mathjax-preview";
+
+import VariableSubform from "../variables/VariableSubform";
+import OutputSubform from "../variables/OutputSubform";
+
+export default function ComponentForm({ control, component, disableSave }) {
+
+ const mathjaxConfig = {
+ CommonHTML: { linebreaks: { automatic: true } },
+ SVG: { linebreaks: { automatic: true } },
+ "HTML-CSS": { linebreaks: { automatic: true } },
+ };
+ const sortedVariables = [...component.variables].sort();
+ const sortedStates = [...component.states].sort();
+ const sortedOutputs = [...component.outputs].sort();
+
+ return (
+
+
+
+ Variables
+
+ {sortedVariables.map((variable, index) => {
+ return (
+
+
+
+ );
+ })}
+
+
+
+ Initial Conditions
+
+ {sortedStates.map((state, index) => {
+ return (
+
+
+
+ );
+ })}
+
+
+
+ Outputs
+
+ {sortedOutputs.map((output, index) => {
+ return (
+
+
+
+ );
+ })}
+
+
+ );
+}
diff --git a/frontend/src/features/forms/FormComponents.js b/frontend/src/features/forms/FormComponents.js
new file mode 100644
index 00000000..6f09539e
--- /dev/null
+++ b/frontend/src/features/forms/FormComponents.js
@@ -0,0 +1,467 @@
+import React from "react";
+import TextField from "@mui/material/TextField";
+
+import makeStyles from '@mui/styles/makeStyles';
+import InputLabel from "@mui/material/InputLabel";
+import Tooltip from "@mui/material/Tooltip";
+import MenuItem from "@mui/material/MenuItem";
+import Typography from "@mui/material/Typography";
+import FormControl from "@mui/material/FormControl";
+import FormHelperText from "@mui/material/FormHelperText";
+import Slider from "@mui/material/Slider";
+import ListSubheader from "@mui/material/ListSubheader";
+import Button from "@mui/material/Button";
+import Select from "@mui/material/Select";
+import { Controller } from "react-hook-form";
+import { DateTimePicker } from "@mui/x-date-pickers/DateTimePicker";
+
+import OutlinedInput from "@mui/material/OutlinedInput";
+import Stack from "@mui/material/Stack";
+import Chip from "@mui/material/Chip";
+import Checkbox from "@mui/material/Checkbox";
+import FormControlLabel from "@mui/material/FormControlLabel";
+import Box from "@mui/material/Box";
+
+import dayjs from 'dayjs';
+import utc from 'dayjs/plugin/utc';
+
+dayjs.extend(utc);
+
+const useStyles = makeStyles((theme) => ({
+ container: {
+ paddingTop: theme.spacing(4),
+ paddingBottom: theme.spacing(4),
+ height: "100%",
+ },
+ formInput: {
+ display: "flex",
+ margin: theme.spacing(1),
+ },
+ chips: {
+ display: "flex",
+ flexWrap: "wrap",
+ },
+ chip: {
+ margin: 2,
+ },
+ fileFieldBox: {
+ margin: theme.spacing(1),
+ width: "200pt",
+ display: "inline-block",
+ },
+ fileFieldField: {
+ "& .MuiFormLabel-root.Mui-disabled": {
+ color: theme.palette.text.secondary,
+ },
+ },
+ fileFieldButton: {
+ width: "100%",
+ height: "100%",
+ overflow: "hidden",
+ },
+}));
+
+export function FormCheckboxField({
+ control,
+ name,
+ defaultValue,
+ label,
+ ...rest
+}) {
+ return (
+
+ (
+ {
+ onChange(e);
+ }}
+ checked={value}
+ inputRef={ref}
+ {...rest}
+ />
+ }
+ label={label}
+ />
+ )}
+ />
+
+ );
+}
+
+export function FormSliderField({
+ control,
+ name,
+ defaultValue,
+ min,
+ label_min,
+ label_max,
+ max,
+ log,
+ label,
+ tooltip,
+}) {
+ const roundNumber = (x) => {
+ if (x === 0 || x === 0.0) {
+ return x;
+ } else if (Math.abs(x) < 0.01 || Math.abs(x) >= 1000.0) {
+ const [coefficient, exponent] = x
+ .toExponential()
+ .split("e")
+ .map((item) => Number(item));
+ return `${Math.round(coefficient)}e^${exponent}`;
+ } else if (Math.abs(x) >= 100.0) {
+ return x.toFixed(0);
+ } else if (Math.abs(x) >= 10.0) {
+ return x.toFixed(1);
+ } else {
+ return x.toFixed(2);
+ }
+ };
+
+
+ let calculateValue = (value) => value;
+ if (log) {
+ calculateValue = (value) => Math.exp(value);
+ }
+
+ const marks = [
+ label_min ? {
+ value: min,
+ label: label_min,
+ } :
+ {
+ value: min,
+ },
+ label_max ? {
+ value: max,
+ label: label_max,
+ } :
+ {
+ value: max,
+ },
+
+ ]
+
+ const internalMin = log ? Math.log(min) : min;
+ const internalMax = log ? Math.log(max) : max;
+ const internalStep = log ? (Math.log(max) - Math.log(min)) / 100.0 : (max - min) / 100.0;
+
+ return (
+
+ {label && (
+
+
+ {label}
+
+
+ )}
+ {
+ return (
+ {
+ e.target.name = name;
+ e.target.value = v;
+ onChange(e);
+ }}
+ onBlur={(e, v) => {
+ e.target.name = name;
+ e.target.value = v;
+ onBlur(e);
+ }}
+ aria-labelledby={`input-slider-${name}`}
+ />
+ );
+ }}
+ />
+
+ );
+}
+
+export function FormDateTimeField({
+ control,
+ name,
+ defaultValue,
+ label,
+ ...rest
+}) {
+ return (
+ (
+
+ )}
+ />
+ );
+}
+
+export function FormFileField({
+ control,
+ name,
+ defaultValue,
+ label,
+ clearErrors,
+ ...rest
+}) {
+
+ return (
+ {
+ const handleChange = (event) => {
+ clearErrors(name);
+ const files = Array.from(event.target.files);
+ const [file] = files;
+ if (!!onChange) onChange({ target: { value: file } });
+ };
+ return (
+
+
+
+
+
+
+
+
+
+ );
+ }}
+ />
+ );
+}
+
+export function FormTextField({ control, name, defaultValue, label, ...rest }) {
+ return (
+
+ (
+
+ )}
+ />
+
+ );
+}
+
+export function FormMultiSelectField({
+ control,
+ name,
+ defaultValue,
+ label,
+ options,
+ ...rest
+}) {
+ return (
+
+
+ {label}
+ (
+ }
+ renderValue={(selected) => (
+
+ {selected.map((value) => {
+ const option_list = options.filter((x) => x.value === value);
+ let option = {
+ key: "user not found",
+ value: 0,
+ };
+ if (option_list.length > 0) {
+ option = option_list[0];
+ }
+ return (
+
+ );
+ })}
+
+ )}
+ {...rest}
+ {...field}
+ >
+ {options.map((option) => {
+ return (
+
+ {option.key}
+
+ );
+ })}
+
+ )}
+ />
+
+
+ );
+}
+
+export function FormSelectField({
+ control,
+ name,
+ defaultValue,
+ label,
+ options,
+ displayEmpty,
+ useGroups,
+ onChangeUser,
+ ...rest
+}) {
+ let groups = {};
+ if (useGroups) {
+ for (const option of options) {
+ if (!(option.group in groups)) {
+ groups[option.group] = [];
+ }
+ groups[option.group].push(option);
+ }
+ }
+ return (
+
+
+ {label}
+ {
+ const inputEl = document.querySelector(`input[name="${name}"]`);
+ inputEl.focus();
+ }}
+ render={({
+ field: { onChange, onBlur, value, name, ref },
+ fieldState: { invalid, isTouched, isDirty, error },
+ formState,
+ }) => {
+ console.log("error in select", error);
+ return (
+
+ }
+ checked={value}
+ displayEmpty
+ inputRef={ref}
+ onChange={(value) => {
+ if (onChangeUser) {
+ onChangeUser(value);
+ }
+ return onChange(value);
+ }}
+ {...rest}
+ >
+ {useGroups
+ ? Object.keys(groups).map((group, i) => [
+ {group} ,
+ groups[group].map((option, j) => {
+ return (
+
+ {option.key}
+
+ );
+ }),
+ ])
+ : options.map((option, i) => (
+
+ {option.key}
+
+ ))}
+
+ {error?.message &&
+ {error?.message}
+ }
+
+ )
+ }
+ }
+ />
+
+
+ );
+}
diff --git a/frontend/src/features/inference/DraftInferences.js b/frontend/src/features/inference/DraftInferences.js
new file mode 100644
index 00000000..4a4a1ad0
--- /dev/null
+++ b/frontend/src/features/inference/DraftInferences.js
@@ -0,0 +1,31 @@
+import React from "react";
+import { useSelector, useDispatch } from "react-redux";
+
+import TableChartIcon from "@mui/icons-material/TableChart";
+
+import ExpandableListItem from "../menu/ExpandableListItem";
+
+import {
+ selectAllDraftInferences,
+ toggleInference,
+ addNewInference,
+} from "../inference/inferenceSlice.js";
+
+export default function Inferences({ project, disableSave }) {
+ const inferences = useSelector(selectAllDraftInferences);
+ const dispatch = useDispatch();
+ const handleClickItem = (item) => dispatch(toggleInference(item));
+ const handleNewItem = () => dispatch(addNewInference(project));
+
+ return (
+
+ );
+}
diff --git a/frontend/src/features/inference/Inference.js b/frontend/src/features/inference/Inference.js
new file mode 100644
index 00000000..87e36485
--- /dev/null
+++ b/frontend/src/features/inference/Inference.js
@@ -0,0 +1,72 @@
+import React, { useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import {
+ useParams,
+ useHistory,
+} from "react-router-dom";
+
+import PropTypes from "prop-types";
+import Grid from "@mui/material/Grid";
+import InferenceDetail from "./InferenceDetail";
+import InferenceChart from "./InferenceChart";
+import Paper from "@mui/material/Paper";
+import Toolbar from '@mui/material/Toolbar';
+import AccordionSummary from "@mui/material/AccordionSummary";
+import Drawer from "@mui/material/Drawer";
+import AccordionDetails from "@mui/material/AccordionDetails";
+import CircularProgress from "@mui/material/CircularProgress";
+import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
+import Typography from "@mui/material/Typography";
+import Box from "@mui/material/Box";
+import Inferences from "../inference/Inferences";
+import List from "@mui/material/List";
+import Stack from "@mui/material/Stack";
+
+import LinearProgressWithLabel from '../menu/LinearProgressWithLabel'
+
+import makeStyles from '@mui/styles/makeStyles';
+
+
+import { selectChosenProject, userHasReadOnlyAccess } from "../projects/projectsSlice.js";
+
+import { selectChosenInferences, fetchInferences, selectInferenceById } from "./inferenceSlice.js";
+
+import ExpandableListItem from "../menu/ExpandableListItem"
+
+const drawerWidth = 200;
+
+export default function Inference({project}) {
+ let { id } = useParams();
+ const inference = useSelector((state) => selectInferenceById(state, id));
+ const dispatch = useDispatch();
+
+ if (!inference) {
+ return ( )
+ }
+
+ const progress = (100 * inference.number_of_iterations) /
+ inference.max_number_of_iterations;
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
diff --git a/frontend/src/features/inference/InferenceChart.js b/frontend/src/features/inference/InferenceChart.js
new file mode 100644
index 00000000..6544dc98
--- /dev/null
+++ b/frontend/src/features/inference/InferenceChart.js
@@ -0,0 +1,163 @@
+import React, { useState, useEffect } from "react";
+import PropTypes from 'prop-types';
+import Tab from '@mui/material/Tab';
+import Typography from '@mui/material/Typography';
+import Tabs from '@mui/material/Tabs';
+import Box from '@mui/material/Box';
+import Button from '@mui/material/Button';
+import Alert from '@mui/material/Alert';
+import Stack from '@mui/material/Stack';
+import { useSelector, useDispatch } from "react-redux";
+import InferenceChartOptimisationResults from './InferenceChartOptimisationResults'
+import InferenceChartSamplingResults from './InferenceChartSamplingResults'
+import InferenceChartTraces from './InferenceChartTraces'
+import InferenceChartFits from './InferenceChartFits'
+import { fetchChainsByInferenceId } from "../inference/chainSlice";
+import { fetchInferenceById } from "../inference/inferenceSlice";
+
+import {selectChainsByInferenceId} from './chainSlice'
+import {selectAlgorithmById} from './algorithmsSlice'
+
+
+import {
+ selectVariablesByPdModel,
+ selectVariablesByDosedPkModel,
+} from "../variables/variablesSlice";
+
+
+function TabPanel(props) {
+ const { children, value, index, ...other } = props;
+
+ return (
+
+ {value === index && (
+
+ {children}
+
+ )}
+
+ );
+}
+
+TabPanel.propTypes = {
+ children: PropTypes.node,
+ index: PropTypes.number.isRequired,
+ value: PropTypes.number.isRequired,
+};
+
+export default function InferenceChart({inference}) {
+ const [value, setValue] = useState(0);
+ const dispatch = useDispatch();
+
+ const chains = useSelector((state) =>
+ selectChainsByInferenceId(state, inference.id)
+ );
+
+
+ const priorsWithChainValues = inference.log_likelihoods.filter(
+ ll => ll.is_a_prior
+ ).map(ll => ({
+ ...ll,
+ chains: chains.map(chain => chain.data.chain[ll.id] || {
+ iterations: [], values: [],
+ }),
+ kdes: chains.map(chain => chain.data.kde[ll.id] || {
+ densities: [], values: [],
+ }),
+ }));
+
+ const observedWithChainValues = inference.log_likelihoods.filter(
+ ll => ll.observed
+ ).map(ll => {
+ const model_loglikelihoods = inference.log_likelihoods.filter(cll =>
+ ll.children.includes(cll.id)
+ )
+ return {
+ ...ll,
+ model_loglikelihoods,
+ outputs: chains.map(chain => chain.outputs[ll.id] || {
+ times: [], datas: [], percentile_mins: [], percentile_maxs: [],
+ medians: [], subjects: [],
+ })
+ }
+ });
+ console.log('chains', chains)
+
+ const algorithm = useSelector((state) =>
+ selectAlgorithmById(state, inference.algorithm)
+ )
+
+ const isSampling = algorithm.category === "SA"
+
+ const optimisationTabs = [
+ //{ label: 'Fit', component: InferenceChartFit },
+ { label: 'Traces', component: InferenceChartTraces },
+ { label: 'Fits', component: InferenceChartFits },
+ { label: 'Results', component: InferenceChartOptimisationResults },
+ ]
+ const samplingTabs = [
+ //{ label: 'PosteriorPredictive', component: InferenceChartPosteriorPredictive },
+ //{ label: 'Biplot', component: InferenceChartBiplot},
+ { label: 'Traces', component: InferenceChartTraces },
+ { label: 'Fits', component: InferenceChartFits },
+ { label: 'Results', component: InferenceChartSamplingResults },
+ ]
+ const tabs = isSampling ? samplingTabs : optimisationTabs
+
+ const handleChange = (event, newValue) => {
+ setValue(newValue);
+ };
+
+ const handleRefresh = () => {
+ dispatch(fetchChainsByInferenceId(inference.id));
+ dispatch(fetchInferenceById(inference.id));
+ }
+
+ const noData = chains.length === 0
+
+ return (
+
+
+
+ Refresh
+
+
+ { noData &&
+ No data, refresh to get chain data
+ }
+
+
+
+ { tabs.map(tab => (
+
+ ))}
+
+
+ { tabs.map((tab, index) => (
+
+
+
+ ))}
+
+
+ )
+}
diff --git a/frontend/src/features/inference/InferenceChartFits.js b/frontend/src/features/inference/InferenceChartFits.js
new file mode 100644
index 00000000..2b948ba1
--- /dev/null
+++ b/frontend/src/features/inference/InferenceChartFits.js
@@ -0,0 +1,283 @@
+import React from "react";
+import { useSelector } from "react-redux";
+import Grid from "@mui/material/Grid";
+
+import makeStyles from '@mui/styles/makeStyles';
+import iqr from 'compute-iqr'
+
+import { Scatter } from "react-chartjs-2";
+
+import FormControl from "@mui/material/FormControl";
+import MenuItem from "@mui/material/MenuItem";
+import InputLabel from "@mui/material/InputLabel";
+import Select from "@mui/material/Select";
+
+import { Chart, registerables, Interaction } from "chart.js";
+import { CrosshairPlugin, Interpolate } from "chartjs-plugin-crosshair";
+import { getColor, getColorBackground } from "../modelling/ShapesAndColors";
+import { selectSubjectsByIds } from "../datasets/subjectsSlice";
+import {
+ selectVariableById,
+} from "../variables/variablesSlice";
+import {
+ selectUnitById,
+} from "../projects/unitsSlice";
+
+
+Chart.register(...registerables, CrosshairPlugin);
+Interaction.modes.interpolate = Interpolate;
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ width: "100%",
+ },
+ plot: {
+ height: "40vh",
+ width: "100%",
+ },
+}));
+
+
+
+function InferenceChartFits({ inference, observed }) {
+ // TODO: assumes a single log likelihood
+ //
+ const classes = useStyles();
+
+ const has_distribution = true
+ const times = observed.outputs ? observed.outputs[0].times : []
+ const datas = observed.outputs ? observed.outputs[0].datas : []
+
+ const outputVariable = useSelector((state) => {
+ return selectVariableById(state, observed.parameters[0].variable);
+ });
+ const timeVariable = useSelector((state) => {
+ return selectVariableById(state, observed.model_loglikelihoods[0].time_variable);
+ });
+ const outputUnit = useSelector((state) => {
+ if (outputVariable) {
+ return selectUnitById(state, outputVariable.unit)
+ }
+ });
+ const timeUnit = useSelector((state) => {
+ if (timeVariable) {
+ return selectUnitById(state, timeVariable.unit)
+ }
+ });
+
+ const yLabelUnit = outputUnit ? outputUnit.symbol : ''
+ const yLabelName = outputVariable ? outputVariable.name : ''
+ const xLabelUnit = timeUnit ? timeUnit.symbol : ''
+ const xLabelName = timeVariable ? timeVariable.name : ''
+ const yLabel = `${yLabelName} [${yLabelUnit}]`
+ const xLabel = `${xLabelName} [${xLabelUnit}]`
+
+ // TODO: assume single output
+ let data = {
+ }
+ if (has_distribution) {
+ data['datasets'] = observed.outputs.map((outputs, i) => {
+ const color = getColor(i);
+ const backgroundColor = getColorBackground(i);
+ return [
+ {
+ type: "line",
+ label: `chain ${i}: 10% percentile`,
+ fill: false,
+ borderColor: color,
+ borderWidth: 0,
+ pointRadius: 0,
+ backgroundColor: backgroundColor,
+ lineTension: 0,
+ interpolate: true,
+ data: outputs.percentile_mins.map((y, i) => ({ x: times[i], y: y }))
+ },
+ {
+ type: "line",
+ label: `chain ${i}: 90% percentile`,
+ borderColor: color,
+ borderWidth: 0,
+ backgroundColor: backgroundColor,
+ pointRadius: 0,
+ fill: '-1',
+ lineTension: 0,
+ interpolate: true,
+ data: outputs.percentile_maxs.map((y, i) => ({ x: times[i], y: y }))
+ },
+ {
+ type: "line",
+ label: `chain ${i}: median`,
+ borderColor: color,
+ borderWidth: 2.5,
+ pointRadius: 0,
+ backgroundColor: backgroundColor,
+ fill: false,
+ lineTension: 0,
+ interpolate: true,
+ data: outputs.medians.map((y, i) => ({ x: times[i], y: y }))
+ },
+ ]
+ }).concat([
+ {
+ type: "line",
+ label: 'data',
+ borderColor: 'black',
+ borderWidth: 2.5,
+ backgroundColor: 'black',
+ showLine: false,
+ data: datas.map((y, i) => ({ x: times[i], y: y }))
+ },
+ ]).flat()
+
+ } else {
+ data['datasets'] = observed.outputs.map((outputs, i) => {
+ const color = getColor(i);
+ const backgroundColor = getColorBackground(i);
+ return {
+ type: "line",
+ label: `chain ${i}: final fit`,
+ borderColor: color,
+ borderWidth: 2.5,
+ pointRadius: 0,
+ backgroundColor: backgroundColor,
+ lineTension: 0,
+ interpolate: true,
+ data: outputs.medians.map((y, i) => ({ x: times[i], y: y }))
+ }
+ }).concat([
+ {
+ type: "line",
+ label: 'data',
+ borderColor: 'black',
+ backgroundColor: 'black',
+ borderWidth: 2.5,
+ showLine: false,
+ data: datas.map((y, i) => ({ x: times[i], y: y }))
+ },
+ ])
+ }
+
+ let options = {
+ animation: {
+ duration: 0,
+ },
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ x: {
+ type: "linear",
+ title: {
+ text: xLabel,
+ display: true,
+ },
+ },
+ y: {
+ position: "left",
+ title: {
+ text: yLabel,
+ display: true,
+ },
+ },
+ },
+ plugins: {
+ legend: {
+ labels: {
+ boxHeight: 1
+ },
+ },
+ title: {
+ display: true,
+ text: observed.name,
+ },
+ tooltip: {
+ mode: "interpolate",
+ intersect: false,
+ callbacks: {
+ title: function (a, d) {
+ return a[0].element.x.toPrecision(4);
+ },
+ label: function (d) {
+ return d.dataset.label + ": " + d.element.y.toPrecision(4);
+ },
+ },
+ },
+ crosshair: {
+ sync: {
+ enabled: false,
+ },
+ },
+ },
+ };
+
+ return (
+
+
+
+ );
+}
+
+
+function InferenceChartTracesObserved({ inference, observed}) {
+
+ const subjectIds = observed.outputs ? observed.outputs[0].subjects : []
+ const uniqueSubjectsIds = [...new Set(subjectIds)]
+ const [subjectIndex, setSubjectIndex] = React.useState(0);
+ const subjects = useSelector((state) => selectSubjectsByIds(state, uniqueSubjectsIds));
+ const multiple_subjects = uniqueSubjectsIds.length > 1
+ const subjectOptions = multiple_subjects ?
+ subjects.map((s, i) => ({label: s.id_in_dataset, value: i})) : []
+ const observedFiltered = multiple_subjects ? {
+ ...observed,
+ outputs: observed.outputs.map(outputs => ({
+ ...outputs,
+ percentile_mins: outputs.percentile_mins.filter((_, i) => subjectIds[i] === uniqueSubjectsIds[subjectIndex]),
+ percentile_maxs: outputs.percentile_maxs.filter((_, i) => subjectIds[i] === uniqueSubjectsIds[subjectIndex]),
+ medians: outputs.medians.filter((_, i) => subjectIds[i] === uniqueSubjectsIds[subjectIndex]),
+ datas: outputs.datas.filter((_, i) => subjectIds[i] === uniqueSubjectsIds[subjectIndex]),
+ times: outputs.times.filter((_, i) => subjectIds[i] === uniqueSubjectsIds[subjectIndex]),
+ }))
+ } : observed
+
+ const handleSubjectChange = (event) => {
+ setSubjectIndex(event.target.value);
+ };
+
+ return (
+
+ { multiple_subjects &&
+
+ Subject
+
+ {subjectOptions.map(so => (
+ {so.label}
+ ))}
+
+
+ }
+
+
+
+
+ )
+}
+
+
+export default function InferenceChartTraces({ inference, observedWithChainValues}) {
+ const classes = useStyles();
+
+ return (
+
+
+ {observedWithChainValues.map(observed => (
+
+ ))}
+
+
+ )
+}
diff --git a/frontend/src/features/inference/InferenceChartOptimisationResults.js b/frontend/src/features/inference/InferenceChartOptimisationResults.js
new file mode 100644
index 00000000..18d31da5
--- /dev/null
+++ b/frontend/src/features/inference/InferenceChartOptimisationResults.js
@@ -0,0 +1,74 @@
+import React from "react";
+import { useSelector } from "react-redux";
+import makeStyles from '@mui/styles/makeStyles';
+import Typography from "@mui/material/Typography";
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableContainer from "@mui/material/TableContainer";
+import TableHead from "@mui/material/TableHead";
+import TableRow from "@mui/material/TableRow";
+
+import {
+ selectVariablesByPdModel,
+ selectVariablesByDosedPkModel,
+} from "../variables/variablesSlice";
+
+
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ height: "85vh",
+ width: "100%",
+ },
+}));
+
+export default function InferenceChartOptimisationResults({ inference, priorsWithChainValues }) {
+ const classes = useStyles();
+
+ const rows = priorsWithChainValues.map(prior => {
+ const final_values = prior.chains.map(chain => chain.values[chain.values.length - 1].toFixed(2))
+ return {
+ name: prior.name,
+ final_values,
+ }
+ });
+
+ return (
+
+
+ Number of iterations: {inference.number_of_iterations} / {inference.max_number_of_iterations}
+
+
+ Number of function evaluations: {inference.number_of_function_evals}
+
+
+
+
+
+ Variable
+ { Array(inference.number_of_chains).fill().map((_, i) => (
+ {`Final ${i}`}
+ ))}
+
+
+
+ {rows.map((row) => (
+
+
+ {row.name}
+
+ { Array(inference.number_of_chains).fill().map((_, i) => (
+ {row.final_values[i]}
+ ))}
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/frontend/src/features/inference/InferenceChartSamplingResults.js b/frontend/src/features/inference/InferenceChartSamplingResults.js
new file mode 100644
index 00000000..27dec86f
--- /dev/null
+++ b/frontend/src/features/inference/InferenceChartSamplingResults.js
@@ -0,0 +1,91 @@
+import React from "react";
+import { useSelector } from "react-redux";
+import makeStyles from '@mui/styles/makeStyles';
+import Typography from "@mui/material/Typography";
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableContainer from "@mui/material/TableContainer";
+import TableHead from "@mui/material/TableHead";
+import TableRow from "@mui/material/TableRow";
+
+import {
+ selectVariablesByPdModel,
+ selectVariablesByDosedPkModel,
+} from "../variables/variablesSlice";
+
+
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ height: "85vh",
+ width: "100%",
+ },
+}));
+
+export default function InferenceChartSamplingResults({ inference, priorsWithChainValues }) {
+ const classes = useStyles();
+
+
+ const rows = priorsWithChainValues.map(prior => {
+ const number_of_samples = prior.chains.map(
+ c => c.values.length
+ ).reduce((sum, x) => sum + x, 0)
+ const mean = (
+ prior.chains.reduce((sum, chain) => sum + chain.values.reduce((sum, x) => sum + x, 0), 0) / number_of_samples
+ ).toFixed(2)
+ const stddev = Math.sqrt(prior.chains.reduce((sum, chain) =>
+ sum + chain.values.map(x => (x - mean)**2).reduce((sum, x) => sum + x, 0)
+ , 0
+ ) / number_of_samples
+ ).toFixed(2)
+ return {
+ name: prior.name,
+ number_of_samples,
+ mean,
+ stddev
+ }
+ });
+
+ return (
+
+
+ Number of iterations: {inference.number_of_iterations} / {inference.max_number_of_iterations}
+
+
+ Number of function evaluations: {inference.number_of_function_evals}
+
+
+ Number of chains: {inference.number_of_chains}
+
+
+
+
+
+
+ Variable
+ Samples
+ Mean
+ Std Dev
+
+
+
+ {rows.map((row) => (
+
+
+ {row.name}
+
+ {row.number_of_samples}
+ {row.mean}
+ {row.stddev}
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/frontend/src/features/inference/InferenceChartTraces.js b/frontend/src/features/inference/InferenceChartTraces.js
new file mode 100644
index 00000000..4041883a
--- /dev/null
+++ b/frontend/src/features/inference/InferenceChartTraces.js
@@ -0,0 +1,337 @@
+import React from "react";
+import { useSelector } from "react-redux";
+import Grid from "@mui/material/Grid";
+
+import makeStyles from '@mui/styles/makeStyles';
+import iqr from 'compute-iqr'
+
+import { Scatter } from "react-chartjs-2";
+import FormControl from "@mui/material/FormControl";
+import MenuItem from "@mui/material/MenuItem";
+import InputLabel from "@mui/material/InputLabel";
+import Select from "@mui/material/Select";
+
+import { Chart, registerables, Interaction } from "chart.js";
+import { CrosshairPlugin, Interpolate } from "chartjs-plugin-crosshair";
+import { getColor, getColorBackground } from "../modelling/ShapesAndColors";
+import annotationPlugin from 'chartjs-plugin-annotation';
+import { selectSubjectsByIds } from "../datasets/subjectsSlice";
+
+
+
+Chart.register(...registerables, CrosshairPlugin, annotationPlugin);
+Interaction.modes.interpolate = Interpolate;
+
+const useStyles = makeStyles((theme) => ({
+ root: {
+ width: "100%",
+ },
+ plot: {
+ height: "120vh",
+ width: "100%",
+ },
+}));
+
+
+function InferenceChartDistribution({ prior }) {
+ const classes = useStyles();
+
+ const data = {
+ datasets: prior.kdes.map((kde, index) => {
+ const color = getColor(prior.id);
+ const backgroundColor = getColorBackground(prior.id);
+ const data = kde ?
+ kde.densities.map((y, i) => ({ x: kde.values[i], y: y })) :
+ { x: null, y: null }
+ return {
+ type: "line",
+ label: `Chain ${index}`,
+ borderColor: color,
+ backgroundColor: backgroundColor,
+ showLine: true,
+ pointRadius: 0,
+ fill: true,
+ borderWidth: 2.5,
+ data: data,
+ };
+ })
+ }
+ let options = {
+
+ animation: {
+ duration: 0,
+ },
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ x: {
+ type: "linear",
+ title: {
+ text: prior.name,
+ display: true,
+ },
+ },
+ y: {
+ position: "left",
+ title: {
+ text: "count",
+ display: true,
+ },
+ },
+ },
+ plugins: {
+ crosshair: false,
+ decimation: {
+ enabled: true,
+ algorithm: 'lttb',
+ },
+ legend: {
+ display: false,
+ labels: {
+ boxHeight: 1
+ },
+ },
+
+ },
+ };
+
+ return (
+
+
+
+ );
+}
+
+function InferenceChartTrace({ prior }) {
+ const classes = useStyles();
+
+ const data = {
+ datasets: prior.chains.map((chain, index) => {
+ const color = getColor(prior.id);
+ const data = chain ?
+ chain.values.map((y, i) => ({ x: chain.iterations[i], y: y })) :
+ { x : null, y: null }
+ return {
+ type: "line",
+ label: `Chain ${index}`,
+ borderColor: color,
+ backgroundColor: color,
+ showLine: true,
+ pointRadius: 0,
+ fill: false,
+ borderWidth: 1.5,
+ lineTension: 0,
+ interpolate: true,
+ data: data,
+ };
+ })
+ }
+ let options = {
+ animation: {
+ duration: 0,
+ },
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ x: {
+ type: "linear",
+ title: {
+ text: "Iteration",
+ display: true,
+ },
+ },
+ y: {
+ position: "left",
+ title: {
+ text: prior.name,
+ display: true,
+ },
+ },
+ },
+ plugins: {
+ decimation: {
+ enabled: true,
+ algorithm: 'lttb',
+ },
+ legend: {
+ labels: {
+ boxHeight: 1
+ },
+ },
+ tooltip: {
+ mode: "interpolate",
+ callbacks: {
+ title: function (a, d) {
+ return a[0].element.x.toPrecision(4);
+ },
+ label: function (d) {
+ return d.dataset.label + ": " + d.element.y.toPrecision(4);
+ },
+ },
+ },
+ crosshair: false,
+ },
+ };
+
+ return (
+
+
+
+ );
+}
+
+function InferenceChartFunction({ chains }) {
+ const classes = useStyles();
+
+ const data = {
+ datasets: chains.map((chain, index) => {
+ const color = getColor(index);
+ const data = chain ?
+ chain.data.function.values.map((y, i) => ({ x: chain.data.function.iterations[i], y: y })) :
+ { x : null, y: null }
+ return {
+ type: "line",
+ label: `Chain ${index}`,
+ borderColor: color,
+ backgroundColor: color,
+ showLine: true,
+ pointRadius: 0,
+ fill: false,
+ borderWidth: 1.5,
+ lineTension: 0,
+ interpolate: true,
+ data: data,
+ };
+ })
+ }
+ let options = {
+ animation: {
+ duration: 0,
+ },
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ x: {
+ type: "linear",
+ title: {
+ text: "Iteration",
+ display: true,
+ },
+ },
+ y: {
+ position: "left",
+ title: {
+ text: "Log-likelihood",
+ display: true,
+ },
+ },
+ },
+ plugins: {
+ decimation: {
+ enabled: true,
+ algorithm: 'lttb',
+ },
+ legend: {
+ labels: {
+ boxHeight: 1
+ },
+ },
+ tooltip: {
+ mode: "interpolate",
+ callbacks: {
+ title: function (a, d) {
+ return a[0].element.x.toPrecision(4);
+ },
+ label: function (d) {
+ return d.dataset.label + ": " + d.element.y.toPrecision(4);
+ },
+ },
+ },
+ crosshair: false,
+ },
+ };
+
+ return (
+
+
+
+ );
+}
+
+
+function InferenceChartTracesPrior({ prior }) {
+ console.log('prior', prior)
+ const multiple_subjects = prior.chains.length !== 0 && !('values' in prior.chains[0])
+ const subjectIds = multiple_subjects ? Object.keys(prior.chains[0]) : []
+ const subjects = useSelector((state) => selectSubjectsByIds(state, subjectIds));
+ const [subjectIndex, setSubjectIndex] = React.useState(0);
+ const subjectOptions = subjects.map((s, i) => ({label: s.id_in_dataset, value: i}))
+ const chosenSubject = subjects && subjectIndex ? subjects[subjectIndex] : null
+ console.log('subjects', multiple_subjects, subjectIds, subjects, chosenSubject)
+ let priorForSubject = prior
+ if (multiple_subjects) {
+ if (chosenSubject) {
+ priorForSubject = {
+ ...prior,
+ chains: prior.chains.map(chain => chain[chosenSubject.id]) ,
+ kdes: prior.kdes.map(kde => kde[chosenSubject.id]),
+ }
+ } else {
+ const firstKey = Object.keys(prior.chains[0])[0]
+ priorForSubject = {
+ ...prior,
+ chains: prior.chains.map(chain => chain[firstKey]) ,
+ kdes: prior.kdes.map(kde => kde[firstKey]),
+ }
+ }
+ }
+
+ const handleSubjectChange = (event) => {
+ setSubjectIndex(event.target.value);
+ };
+
+ return (
+
+
+ {multiple_subjects &&
+
+ Subject
+
+ {subjectOptions.map(so => (
+ {so.label}
+ ))}
+
+
+ }
+
+
+
+
+
+
+
+ )
+}
+
+export default function InferenceChartTraces({ inference, priorsWithChainValues, chains }) {
+ const classes = useStyles();
+
+ return (
+
+
+
+
+
+ {priorsWithChainValues.map(prior => (
+
+ ))}
+
+
+ )
+}
diff --git a/frontend/src/features/inference/InferenceDetail.js b/frontend/src/features/inference/InferenceDetail.js
new file mode 100644
index 00000000..6c59e533
--- /dev/null
+++ b/frontend/src/features/inference/InferenceDetail.js
@@ -0,0 +1,422 @@
+import React, { useEffect, useState, useMemo, useCallback } from "react";
+import { useSelector } from "react-redux";
+import { useDispatch } from "react-redux";
+import Divider from '@mui/material/Divider';
+import Button from "@mui/material/Button";
+
+import { useHistory } from "react-router-dom";
+import Grid from "@mui/material/Grid";
+import Paper from "@mui/material/Paper";
+
+import FormControl from "@mui/material/FormControl";
+import ReactFlow, { MarkerType, applyEdgeChanges, applyNodeChanges } from 'react-flow-renderer';
+import Stack from "@mui/material/Stack";
+import * as ELK from 'elkjs';
+import InputLabel from "@mui/material/InputLabel";
+import Alert from '@mui/material/Alert';
+import { useForm, useFieldArray } from "react-hook-form";
+import makeStyles from '@mui/styles/makeStyles';
+import Typography from "@mui/material/Typography";
+import List from "@mui/material/List";
+import ListItem from "@mui/material/ListItem";
+import Tooltip from "@mui/material/Tooltip";
+import Select from "@mui/material/Select";
+import IconButton from "@mui/material/IconButton";
+import MenuItem from "@mui/material/MenuItem";
+import AddIcon from "@mui/icons-material/Add";
+import DeleteIcon from "@mui/icons-material/Delete";
+
+
+import InferenceDialog from "./InferenceDialog";
+
+import { selectWritablePkModels, selectReadOnlyPkModels } from "../pkModels/pkModelsSlice";
+import { selectWritablePdModels, selectReadOnlyPdModels } from "../pdModels/pdModelsSlice";
+import { selectAllAlgorithms } from "../inference/algorithmsSlice";
+
+import {
+ selectBiomarkerTypesByDatasetId,
+ selectBiomarkerTypeById,
+} from "../datasets/biomarkerTypesSlice";
+
+import {
+ selectVariablesByPdModel,
+ selectVariablesByDosedPkModel,
+ selectVariableById,
+} from "../variables/variablesSlice";
+
+import { selectAllDatasets } from "../datasets/datasetsSlice";
+
+import { updateInference, deleteInference, selectAllInferences } from "../inference/inferenceSlice";
+import { runInference, stopInference } from "./inferenceSlice";
+import { FormTextField, FormSelectField, FormSliderField } from "../forms/FormComponents";
+import { userHasReadOnlyAccess } from "../projects/projectsSlice";
+
+const elk = new ELK()
+
+export default function InferenceDetail({ project, inference }) {
+ const dispatch = useDispatch();
+ let history = useHistory();
+ const [openDialog, setOpenDialog] = React.useState(false);
+ const handleCloseDialog = () => {
+ setOpenDialog(false);
+ };
+ const handleEdit = () => {
+ setOpenDialog(true);
+ };
+
+ let logLikelihoodNodes = inference.log_likelihoods.map(ll => {
+ let label = (<>{ll.name}>)
+ let border = 'solid';
+ let width = 140;
+ let height = 40;
+ let type = 'default';
+ let observed = '';
+ if (ll.observed) {
+ observed = 'Observed '
+ type = 'input'
+ }
+ if (ll.form === 'F') {
+ type = 'output'
+ }
+ if (ll.form === 'M') {
+ label = (<>Model: {ll.name}>);
+ border = '5px double';
+ height = 2 * height;
+ } else if (ll.form === 'N') {
+ label = (<>{observed}Normal >);
+ } else if (ll.form === 'LN') {
+ label = (<>{observed}LogNormal >);
+ } else if (ll.form === 'U') {
+ label = (<>{observed}Uniform >);
+ } else if (ll.form === 'F') {
+ label = `${ll.value}`
+ width = 0.6 * width;
+ }
+ return {
+ id: `${ll.id}`,
+ data: { label },
+ position: { x: 0, y: 0 },
+ type,
+ style: {
+ background: '#D6D5E6',
+ color: '#333',
+ border,
+ width,
+ height,
+ },
+ }
+ });
+
+ const parameterEdges = inference.log_likelihoods.reduce((sum, ll) =>
+ sum.concat(ll.parameters.map(p => ({
+ id: `e-${p.id}`,
+ source: `${p.parent}`,
+ target: `${p.child}`,
+ label: p.length ? `${p.name} (${p.length},)` : `${p.name}`,
+ type: 'default',
+ animated: false,
+ style: {
+ 'stroke-width': p.length ? '3px' : '1px',
+ }
+ }))), []);
+
+ const [nodes, setNodes] = useState(null);
+ const [edges, setEdges] = useState(parameterEdges);
+
+ const onNodesChange = useCallback(
+ (changes) => setNodes((nds) => applyNodeChanges(changes, nds)),
+ [setNodes]
+ );
+ const onEdgesChange = useCallback(
+ (changes) => setEdges((eds) => applyEdgeChanges(changes, eds)),
+ [setEdges]
+ );
+
+ useEffect(() => {
+ const graph = {
+ id: "root",
+ layoutOptions: {
+ 'elk.algorithm': 'layered',
+ 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
+ 'elk.direction': 'DOWN',
+ 'elk.spacing.nodeNode': 20,
+ 'elk.layered.spacing.nodeNodeBetweenLayers': 90,
+ 'elk.aspectRatio': 1.0,
+ },
+ children: logLikelihoodNodes.map(n => (
+ { id: n.id, width: n.style.width, height: n.style.height}
+ )),
+ edges: parameterEdges.map(e => (
+ { id: e.id, sources: [e.source], targets: [e.target] }
+ )),
+ }
+
+ elk.layout(graph).then(graph => {
+ const newNodes = logLikelihoodNodes.map((n, i) => {
+ n.position.x = graph.children[i].x
+ n.position.y = graph.children[i].y
+ return n;
+ })
+ setNodes(newNodes)
+ setEdges(parameterEdges)
+ })
+
+ }, [JSON.stringify(inference.metadata)]);
+
+ const logLikelihoodsNoNull = inference.log_likelihoods.map(ll =>
+ Object.keys(ll).reduce((sum, key) => {
+ sum[key] = ll[key] || ""
+ return sum
+ }, {}))
+ const { control, handleSubmit, watch, setValue } = useForm({
+ defaultValues: {
+ ...inference,
+ initialization_inference: inference.initialization_inference || "",
+ log_likelihoods: logLikelihoodsNoNull
+ },
+ });
+
+ const datasets = useSelector(selectAllDatasets);
+ const dataset_options = datasets.map((dataset) => ({
+ key: dataset.name,
+ value: dataset.id,
+ })).concat([
+ { key: 'Use simulated data', value: '' }
+ ]);
+
+ const inferences = useSelector(selectAllInferences);
+ const inference_options = inferences.map((inference) => ({
+ key: inference.name,
+ value: inference.id,
+ })).concat([
+ { key: "None", value: "" }
+ ]);
+
+ const {
+ fields: logLikelihoods,
+ append: logLikelihoodsAppend,
+ remove: logLikelihoodsRemove,
+ } = useFieldArray({
+ control,
+ name: "log_likelihoods",
+ });
+
+
+ const handleDelete = () => {
+ dispatch(deleteInference(inference.id));
+ history.push(`/${project.id}/inference`);
+ };
+
+
+ const handleStop= () => {
+ dispatch(stopInference(inference.id));
+ };
+
+ const handleNewLoglikelihood = () =>
+ logLikelihoodsAppend({
+ form: "N",
+ variable: "",
+ priors: [],
+ parameters: [],
+ biomarker_type: "",
+ });
+
+ const max_number_of_iterations = watch(
+ "max_number_of_iterations",
+ inference.max_number_of_iterations
+ )
+
+
+ const onSubmit = (values) => {
+ values.log_likelihoods = values.log_likelihoods.map(ll =>
+ Object.keys(ll).reduce((sum, key) => {
+ let value = ll[key]
+ if (value === '') {
+ value = null
+ }
+ sum[key] = value
+ return sum
+ }, {})
+ )
+ dispatch(updateInference(values));
+ };
+
+ const readOnly = useSelector(state => userHasReadOnlyAccess(state, project)) || inference.read_only;
+
+ const algorithms = useSelector(selectAllAlgorithms);
+ const algorithm_options = algorithms
+ ? algorithms.map((algorithm) => ({
+ key: algorithm.name,
+ value: algorithm.id,
+ group: algorithm.category === "SA" ? "Sampling" : "Optimisation",
+ }))
+ : [{ key: "Loading...", value: null, group: null }];
+
+ const initialization_options = [
+ { key: "NA", value: "" },
+ { key: "Random from prior", value: "R" },
+ { key: "Default values of model", value: "D" },
+ { key: "From another inference", value: "F" },
+ ]
+
+
+
+ return (
+
+ );
+}
diff --git a/frontend/src/features/inference/InferenceDialog.js b/frontend/src/features/inference/InferenceDialog.js
new file mode 100644
index 00000000..0e4c98df
--- /dev/null
+++ b/frontend/src/features/inference/InferenceDialog.js
@@ -0,0 +1,784 @@
+import React, { useEffect, useState, useMemo } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import { useForm, useFieldArray } from "react-hook-form";
+import Dialog from '@mui/material/Dialog';
+import DialogActions from '@mui/material/DialogActions';
+import makeStyles from '@mui/styles/makeStyles';
+import DialogContent from '@mui/material/DialogContent';
+import Container from "@mui/material/Container";
+import DialogContentText from '@mui/material/DialogContentText';
+import DialogTitle from '@mui/material//DialogTitle';
+import Button from '@mui/material/Button';
+import Popover from '@mui/material/Popover';
+import Alert from '@mui/material/Alert';
+import AlertTitle from '@mui/material/AlertTitle';
+import List from "@mui/material/List";
+import IconButton from "@mui/material/IconButton";
+import Tooltip from "@mui/material/Tooltip";
+import AddIcon from "@mui/icons-material/Add";
+import HelpIcon from "@mui/icons-material/Help";
+import DeleteIcon from "@mui/icons-material/Delete";
+import ListItem from "@mui/material/ListItem";
+import Grid from "@mui/material/Grid";
+import Stepper from '@mui/material/Stepper';
+import Step from '@mui/material/Step';
+import StepLabel from '@mui/material/StepLabel';
+import Typography from '@mui/material/Typography';
+import Divider from '@mui/material/Divider';
+import Paper from '@mui/material/Paper';
+
+import ModellingChart from '../modelling/Chart';
+import { FormTextField, FormSelectField, FormSliderField } from "../forms/FormComponents";
+import { selectAllAlgorithms } from "../inference/algorithmsSlice";
+import { selectAllDatasets } from "../datasets/datasetsSlice";
+import { runInferenceWizard, selectAllInferences } from "../inference/inferenceSlice";
+import { selectWritablePkModels, selectReadOnlyPkModels } from "../pkModels/pkModelsSlice";
+import { selectWritablePdModels, selectReadOnlyPdModels } from "../pdModels/pdModelsSlice";
+import {
+ selectBiomarkerTypesByDatasetId,
+ selectBiomarkerTypeById,
+} from "../datasets/biomarkerTypesSlice";
+import {
+ selectVariablesByPdModel,
+ selectVariablesByDosedPkModel,
+ selectVariableById,
+} from "../variables/variablesSlice";
+
+
+function variableGetDefaultValue(variable) {
+ if (variable.is_log) {
+ return Math.exp(variable.default_value)
+ } else {
+ return variable.default_value
+ }
+}
+
+const useStyles = makeStyles(() => ({
+ dialogPaper: {
+ minHeight: '500px',
+ maxHeight: '80vh',
+ },
+ listPaper: {
+ display: 'flex',
+ width: "100%",
+ },
+ chart: {
+ height: "50vh",
+ width: "100%",
+ },
+}));
+
+function HelpPopover() {
+ const [anchorEl, setAnchorEl] = React.useState(null);
+
+ const handleClick = (event) => {
+ setAnchorEl(event.currentTarget);
+ };
+
+ const handleClose = () => {
+ setAnchorEl(null);
+ };
+
+ const open = Boolean(anchorEl);
+ const id = open ? 'simple-popover' : undefined;
+
+ const helpText = 'Value can be a number (e.g. 1.0), or an expression in Python syntax ' +
+ '(e.g. 1.0 + parameter[central.clearence]^2). You can refer to other ' +
+ 'parameters using the syntax "parameter[]". You can ' +
+ 'refer to a biomarker in the chosen dataset using "biomarker[]"' +
+ '(e.g. 24.0 if biomarker[body weight] < 100 else 12.0). If there are more ' +
+ 'than one biomarker measurement for that subject / subject group then only the ' +
+ 'first measurement is used.';
+
+ return (
+
+
+
+
+
+
+
+ Help on defining parameter values
+ {helpText}
+
+
+
+
+ );
+}
+
+export default function InferenceDialog({ project, open, handleCloseDialog, defaultValues }) {
+ const dispatch = useDispatch();
+
+ const classes = useStyles();
+
+ const [activeStep, setActiveStep] = React.useState(0);
+
+ const steps = [
+ 'Model and dataset',
+ 'Observables',
+ 'Parameters',
+ 'Inference options',
+ ];
+
+ const handleNext = () => {
+ setActiveStep((prevActiveStep) => prevActiveStep + 1);
+ };
+
+ const handleBack = () => {
+ setActiveStep((prevActiveStep) => prevActiveStep - 1);
+ };
+
+ const algorithms = useSelector(selectAllAlgorithms);
+ const algorithm_options = algorithms
+ ? algorithms.map((algorithm) => ({
+ key: algorithm.name,
+ value: algorithm.id,
+ group: algorithm.category === "SA" ? "Sampling" : "Optimisation",
+ }))
+ : [{ key: "Loading...", value: null, group: null }];
+
+
+ const initialization_options = [
+ { key: "NA", value: "" },
+ { key: "Random from prior", value: "R" },
+ { key: "Default values of model", value: "D" },
+ { key: "From another inference", value: "F" },
+ ]
+
+ const pd_models = useSelector(state => selectWritablePdModels(state));
+ const dosed_pk_models = useSelector(state => selectWritablePkModels(state));
+ const model_options = pd_models.map((model) => ({
+ key: model.name,
+ value: JSON.stringify({id: model.id, form: 'PD'}),
+ group: 'Pharmacodynamic',
+ })).concat(dosed_pk_models.map((model) => ({
+ key: model.name,
+ value: JSON.stringify({id: model.id, form: 'PK'}),
+ group: 'Pharmacokinetic',
+ })));
+ const grouping_options = [
+ { key: 'by subject', value: 'subject' },
+ { key: 'by protocol', value: 'protocol' },
+ ]
+
+ if (defaultValues) {
+ defaultValues = {
+ ...defaultValues,
+ model: JSON.stringify(defaultValues.model),
+ }
+ } else if (!defaultValues) {
+ defaultValues = {
+ name: '',
+ grouping: 'protocol',
+ description: '',
+ project: project.id,
+ algorithm: 1,
+ initialization_strategy: 'R',
+ initialization_inference: '',
+ number_of_chains: 4,
+ max_number_of_iterations: 1000,
+ burn_in: 0,
+ model: '',
+ dataset: '',
+ }
+ }
+
+ const { control, handleSubmit, watch, setValue, reset } = useForm({
+ defaultValues
+ });
+
+ const handleClose= () => {
+ handleCloseDialog();
+ setActiveStep(0);
+ reset();
+ };
+
+ const {
+ fields: observations,
+ append: observationsAppend,
+ remove: observationsRemove,
+ replace: observationsReplace,
+ } = useFieldArray({
+ control,
+ name: "observations",
+ });
+
+ const {
+ fields: parameters,
+ replace: parametersReplace,
+ append: parametersAppend,
+ remove: parametersRemove,
+ } = useFieldArray({
+ control,
+ name: "parameters",
+ });
+
+ const modelId = watch("model")
+ const modelIdParse = modelId ? JSON.parse(modelId) : {id: null, form: null}
+ const datasetId = watch("dataset")
+
+ const chosenPkModel = dosed_pk_models.find(m => m.id === modelIdParse.id && modelIdParse.form === 'PK')
+ console.log('chosenPkModel', chosenPkModel)
+ console.log('defaultValues', defaultValues)
+ const chosenPdModel = pd_models.find(m => m.id === modelIdParse.id && modelIdParse.form === 'PD')
+
+ const variablesAll = useSelector((state) => {
+ if (modelId) {
+ if (modelIdParse.form === 'PD') {
+ return selectVariablesByPdModel(state, modelIdParse.id);
+ } else if (modelIdParse.form === 'PK') {
+ return selectVariablesByDosedPkModel(state, modelIdParse.id);
+ }
+ } else {
+ return [];
+ }
+ });
+ const variables = useMemo(
+ () => {
+ return variablesAll.filter(variable => variable.name !== "time")
+ },
+ [JSON.stringify(variablesAll)]
+ );
+
+ const biomarker_types = useSelector((state) =>
+ datasetId ? selectBiomarkerTypesByDatasetId(state, datasetId) : []
+ );
+ const biomarker_type_options = biomarker_types.map((biomarker_type) => ({
+ key: biomarker_type.name,
+ value: biomarker_type.name,
+ }));
+
+ const observedVariables = observations.map(obs => obs.model)
+ const variablesRemain = variables.filter(v => (
+ !v.constant && !observedVariables.includes(v.qname)
+ ))
+ const handleNewObservation = () => {
+ observationsAppend({
+ model: variablesRemain[0].qname,
+ biomarker: '',
+ noise_form: 'N',
+ noise_param_form: 'F',
+ parameters: [variableGetDefaultValue(variablesRemain[0])],
+ })
+ };
+ const handleDeleteObservation = (index) => () => {
+ observationsRemove(index)
+ };
+
+ useEffect(() => {
+ let model_observations = observations.filter(o => {
+ const variable = variables.find(v => v.qname === o.model)
+ if (variable) {
+ return true
+ }
+ return false
+ }).map( o => ({
+ ...o,
+ parameters: [...o.parameters]
+ }))
+ if (model_observations.length === 0 && variablesRemain.length > 0) {
+ model_observations = [
+ {
+ model: variablesRemain[0].qname,
+ biomarker: '',
+ noise_form: 'N',
+ noise_param_form: 'F',
+ parameters: [variableGetDefaultValue(variablesRemain[0])],
+ }
+ ]
+ }
+
+ const model_params = variables.filter(variable =>
+ variable.constant || variable.state
+ ).map(variable => {
+ const existing_param = parameters.find(p => p.name === variable.qname)
+ if (existing_param) {
+ return {
+ name: existing_param.name,
+ form: existing_param.form,
+ pooled: existing_param.pooled,
+ userDefined: existing_param.userDefined,
+ parameters: [...existing_param.parameters],
+ }
+ }
+ return {
+ name: variable.qname,
+ form: 'F',
+ pooled: true,
+ userDefined: false,
+ parameters: [variableGetDefaultValue(variable)],
+ }
+ })
+ parametersReplace(model_params)
+ observationsReplace(model_observations)
+ }
+ , [JSON.stringify(variables)]);
+
+ const handleNewParameter= () => {
+ parametersAppend({
+ name: 'New',
+ form: 'F',
+ pooled: true,
+ userDefined: true,
+ parameters: ['0.0'],
+ })
+ };
+ const handleDeleteParameter = (index) => () => {
+ parametersRemove(index)
+ };
+
+ const model_output_options = variables.filter(variable =>
+ !variable.constant
+ ).map(variable => ({
+ key: variable.qname, value: variable.qname
+ }))
+
+ const datasets = useSelector(selectAllDatasets);
+ const dataset_options = datasets.map((dataset) => ({
+ key: dataset.name,
+ value: dataset.id,
+ }));
+ const chosenDataset = datasets.find(d => d.id === datasetId)
+
+ const inferences = useSelector(selectAllInferences);
+ const inference_options = inferences.map((inference) => ({
+ key: inference.name,
+ value: inference.id,
+ })).concat([
+ { key: "None", value: "" }
+ ]);
+
+ const form_options = [
+ { key: "Normal", value: "N" },
+ { key: "LogNormal", value: "LN" },
+ { key: "Uniform", value: "U" },
+ { key: "Fixed", value: "F" },
+ ];
+
+ const obs_form_options = [
+ { key: "Normal", value: "N" },
+ { key: "LogNormal", value: "LN" },
+ ];
+
+ const handleFormChange = (baseName, variable, forObs) => (event) => {
+ const newForm = event.target.value;
+ if (variable) {
+ if (newForm === "F") {
+ const value = variableGetDefaultValue(variable)
+ setValue(`${baseName}.parameters[0]`, value);
+ } else if (newForm === "N" || newForm === 'LN') {
+ const mean = forObs ? 0 : variableGetDefaultValue(variable)
+ const standardDeviation = Math.sqrt(
+ Math.pow(variable.upper_bound - variable.lower_bound, 2) / 12
+ );
+ setValue(`${baseName}.parameters[0]`, mean);
+ setValue(`${baseName}.parameters[1]`, standardDeviation);
+ } else if (newForm === "U") {
+ const lower = variable.lower_bound
+ const upper = variable.upper_bound
+ setValue(`${baseName}.parameters[0]`, lower);
+ setValue(`${baseName}.parameters[1]`, upper);
+ }
+ }
+ };
+
+ const onSubmit = (values) => {
+ values = Object.keys(values).reduce((sum, key) => {
+ let value = values[key]
+ if (value === '') {
+ value = null
+ }
+ if (key === 'model') {
+ value = JSON.parse(value)
+ }
+ sum[key] = value
+ return sum
+ }, {})
+ dispatch(runInferenceWizard(values));
+ handleClose()
+ };
+
+ const max_number_of_iterations = watch(
+ "max_number_of_iterations"
+ )
+
+ const pooled_options = [
+ { value: true, key: 'Yes'},
+ { value: false, key: 'No'},
+ ]
+
+
+ const prior_parameter_render = (baseName, watchForm, showPooled) => {
+ const pooled = (
+
+
+
+ )
+ if (watchForm === 'F') {
+ return (
+
+ {showPooled && pooled}
+
+
+
+
+ )
+ } else if ((watchForm === 'N' || watchForm === 'LN')) {
+ return (
+
+ {showPooled && pooled}
+
+
+
+
+
+
+
+ )
+ } else if (watchForm === 'U') {
+ return (
+
+ {showPooled && pooled}
+
+
+
+
+
+
+
+ )
+ }
+ };
+
+ const stepRenders = [
+ (
+
+
+
+
+
+
+
+
+ {chosenPkModel && chosenDataset &&
+
+
+ Note: there are {chosenDataset.protocols.length} dosing protocols
+ and {chosenDataset.subjects.length} subjects in this dataset. The
+ inference will use generate one model per protocol
+
+
+ }
+
+
+
+
+ ),
+ (
+
+ {observations.map((obs, index) => {
+ const baseName = `observations[${index}]`
+ const watchForm = watch(`observations[${index}].noise_param_form`)
+ const variable = variables.find(v => v.qname === obs.model)
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {prior_parameter_render(baseName, watchForm, false)}
+
+
+
+
+
+
+ )
+ })}
+
+
+
+
+
+
+ ),
+ (
+
+ {parameters.map((param, index) => {
+ const baseName = `parameters[${index}]`
+ const watchForm = watch(`parameters[${index}].form`)
+ const variable = variables.find(v => v.qname === param.name)
+ return (
+
+
+
+
+
+ {prior_parameter_render(baseName, watchForm, true)}
+
+
+
+
+
+ )
+ })}
+
+
+
+
+
+
+
+
+ ),
+ (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ),
+
+ ]
+
+ return (
+
+
+
+ )
+}
diff --git a/frontend/src/features/inference/InferenceListDialog.js b/frontend/src/features/inference/InferenceListDialog.js
new file mode 100644
index 00000000..b8e598d3
--- /dev/null
+++ b/frontend/src/features/inference/InferenceListDialog.js
@@ -0,0 +1,142 @@
+import React, { useEffect } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import Button from "@mui/material/Button";
+import Dialog from '@mui/material/Dialog';
+import DialogContent from '@mui/material/DialogContent';
+import makeStyles from '@mui/styles/makeStyles';
+import { selectAllInferences } from "../inference/inferenceSlice";
+import Table from '@mui/material/Table';
+import TableCell from '@mui/material/TableCell';
+import Tooltip from "@mui/material/Tooltip";
+import TableContainer from '@mui/material/TableContainer';
+import TableBody from '@mui/material/TableBody';
+import TableRow from '@mui/material/TableRow';
+import TableHead from '@mui/material/TableHead';
+
+import Typography from "@mui/material/Typography";
+import DialogActions from "@mui/material/DialogActions";
+
+import LinearProgressWithLabel from '../menu/LinearProgressWithLabel'
+
+const useStyles = makeStyles((theme) => ({
+ container: {
+ },
+ paper: {
+ padding: theme.spacing(2),
+ textAlign: "left",
+ },
+ controlsRoot: {
+ display: "flex",
+ alignItems: "center",
+ },
+ controls: {
+ margin: theme.spacing(1),
+ },
+}));
+
+
+
+export default function InferenceListDialog({ project, onClose, model_type, model, open }) {
+ const classes = useStyles();
+ const [value, setValue] = React.useState(0);
+ const handleClose = () => {
+ onClose();
+ };
+
+ let items = useSelector(selectAllInferences);
+ const pd_models = useSelector(state => state.pdModels.entities);
+ const pk_models = useSelector(state => state.pkModels.entities);
+ const datasets = useSelector(state => state.datasets.entities);
+ // fetch model and dataset name
+ if (items) {
+ items = items.map(item => {
+ const model_id = item.metadata.model.id;
+ const dataset_id = item.metadata.dataset;
+ const dataset = datasets[dataset_id];
+ const model_type = item.metadata.model.form;
+ let model = null
+ if (model_type === 'PK') {
+ model = pk_models[model_id]
+ }
+ if (model_type === 'PD') {
+ model = pd_models[model_id]
+ }
+ console.log(item, model, dataset)
+ return {...item, model, dataset}
+ })
+ }
+
+ const handleRowClick = (item) => {
+ onClose(item);
+ }
+
+ const column_headings = [
+ {label: 'Name', help: 'Name'},
+ {label: 'Description', help: 'Description'},
+ {label: 'Model', help: 'Model'},
+ {label: 'Dataset', help: 'Dataset'},
+ {label: 'Progress', help: 'Progress'},
+ ]
+
+ console.log('inference', items)
+
+ return (
+
+
+
+ Choose an inference
+
+
+
+
+
+ {column_headings.map(heading => (
+
+
+
+ {heading.label}
+
+
+
+
+ ))
+ }
+
+
+
+ {items.map((item) => {
+ const progress =
+ (100 * item.number_of_iterations) /
+ item.max_number_of_iterations;
+ return (
+
+ handleRowClick(item)}>
+
+ {item.name}
+
+
+ {item.description}
+
+
+ {item.model?.name}
+
+
+ {item.dataset.name}
+
+
+
+
+
+
+ )
+ })}
+
+
+
+
+
+ Close
+
+
+ );
+}
diff --git a/frontend/src/features/inference/Inferences.js b/frontend/src/features/inference/Inferences.js
new file mode 100644
index 00000000..447f4e6f
--- /dev/null
+++ b/frontend/src/features/inference/Inferences.js
@@ -0,0 +1,154 @@
+import React, { useEffect } from "react";
+import { useSelector } from "react-redux";
+import Paper from "@mui/material/Paper";
+import Grid from "@mui/material/Grid";
+import Table from '@mui/material/Table';
+import { useHistory, useParams } from "react-router-dom";
+import Typography from '@mui/material/Typography';
+import Container from '@mui/material/Container';
+import LinearProgress from "@mui/material/LinearProgress";
+import TableBody from '@mui/material/TableBody';
+import ProjectDetail from "../projects/ProjectDetail";
+import Tooltip from "@mui/material/Tooltip";
+import { useTheme } from "@mui/material/styles";
+import Box from "@mui/material/Box";
+import { useDispatch } from "react-redux";
+import TableCell from '@mui/material/TableCell';
+import SaveIcon from '@mui/icons-material/Save';
+import TableContainer from '@mui/material/TableContainer';
+import TableHead from '@mui/material/TableHead';
+import DeleteIcon from '@mui/icons-material/Delete';
+import TableRow from '@mui/material/TableRow';
+
+import AddIcon from "@mui/icons-material/Add";
+
+import IconButton from "@mui/material/IconButton";
+import makeStyles from '@mui/styles/makeStyles';
+
+import LinearProgressWithLabel from '../menu/LinearProgressWithLabel'
+import InferenceDialog from './InferenceDialog'
+
+import {
+ addNewInference,
+ selectAllInferences,
+ deleteInference,
+} from "./inferenceSlice.js";
+
+const useStyles = makeStyles((theme) => ({
+ container: {
+ },
+ paper: {
+ padding: theme.spacing(2),
+ textAlign: "left",
+ },
+ controlsRoot: {
+ display: "flex",
+ alignItems: "center",
+ },
+ controls: {
+ margin: theme.spacing(1),
+ },
+}));
+
+
+
+export default function Inferences({ project }) {
+ const classes = useStyles();
+ const theme = useTheme();
+ const dispatch = useDispatch();
+ const history = useHistory();
+
+ const [openDialog, setOpenDialog] = React.useState(false);
+ const handleCloseDialog = () => {
+ setOpenDialog(false);
+ };
+
+ const handleNewRow = () => {
+ setOpenDialog(true);
+ };
+ const items = useSelector(selectAllInferences);
+
+ const handleRowClick = (item) => {
+ history.push(`/${project.id}/inference/${item.id}/`);
+ }
+
+ const handleDelete = (id) => (event) => {
+ event.stopPropagation()
+ dispatch(deleteInference(id));
+ }
+
+ const column_headings = [
+ {label: 'Name', help: 'Name'},
+ {label: 'Description', help: 'Description'},
+ {label: 'Progress', help: 'Progress'},
+ {label: 'Actions', help: 'Click icon to perform actions'},
+ ]
+
+ return (
+
+
+ My Inferences
+
+
+
+
+
+ {column_headings.map(heading => (
+
+
+
+ {heading.label}
+
+
+
+
+ ))
+ }
+
+
+
+ {items.map((item) => {
+ const progress =
+ (100 * item.number_of_iterations) /
+ item.max_number_of_iterations;
+ return (
+
+ handleRowClick(item)}>
+
+ {item.name}
+
+
+ {item.description}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+ })}
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
diff --git a/frontend/src/features/inference/algorithmsSlice.js b/frontend/src/features/inference/algorithmsSlice.js
new file mode 100644
index 00000000..85487f51
--- /dev/null
+++ b/frontend/src/features/inference/algorithmsSlice.js
@@ -0,0 +1,76 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+
+const algorithmsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = algorithmsAdapter.getInitialState({
+ status: "idle",
+ error: null,
+});
+
+export const fetchAlgorithms = createAsyncThunk(
+ "algorithms/fetchAlgorithms",
+ async (project, { getState }) => {
+ const response = await api.get(`/api/algorithm/`, getState().login.csrf);
+ return response;
+ }
+);
+
+export const addNewAlgorithm = createAsyncThunk(
+ "algorithms/addNewAlgorithm",
+ async (_, { getState }) => {
+ const initialAlgorithm = {
+ name: "new",
+ };
+ const algorithm = await api.post("/api/algorithm/", getState().login.csrf, initialAlgorithm);
+ return algorithm;
+ }
+);
+
+export const updateAlgorithm = createAsyncThunk(
+ "algorithms/updateAlgorithm",
+ async (algorithm, {getState}) => {
+ const response = await api.put(
+ `/api/algorithm/${algorithm.id}/`, getState().login.csrf,
+ algorithm
+ );
+ return response;
+ }
+);
+
+export const algorithmsSlice = createSlice({
+ name: "algorithms",
+ initialState,
+ reducers: {},
+ extraReducers: {
+ [fetchAlgorithms.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchAlgorithms.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [fetchAlgorithms.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ algorithmsAdapter.setAll(state, action.payload);
+ },
+ [addNewAlgorithm.fulfilled]: algorithmsAdapter.addOne,
+ [updateAlgorithm.fulfilled]: algorithmsAdapter.upsertOne,
+ },
+});
+
+// export const {} = algorithmsSlice.actions
+
+export default algorithmsSlice.reducer;
+
+export const {
+ selectAll: selectAllAlgorithms,
+ selectById: selectAlgorithmById,
+ selectIds: selectAlgorithmIds,
+} = algorithmsAdapter.getSelectors((state) => state.algorithms);
diff --git a/frontend/src/features/inference/chainSlice.js b/frontend/src/features/inference/chainSlice.js
new file mode 100644
index 00000000..3d09247b
--- /dev/null
+++ b/frontend/src/features/inference/chainSlice.js
@@ -0,0 +1,93 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+
+const chainsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = chainsAdapter.getInitialState({
+ status: "idle",
+ errorFetch: null,
+});
+
+export const fetchChains = createAsyncThunk(
+ "chains/fetchChains",
+ async (project, { dispatch }) => {
+ let response = await api.get(
+ `/api/inference_chain/?project_id=${project.id}`
+ );
+ return response;
+ }
+);
+
+export const fetchChainById = createAsyncThunk(
+ "chains/fetchChainById",
+ async (model_id, { dispatch }) => {
+ let response = await api.get(`/api/inference_chain/${model_id}/`);
+ return response;
+ }
+);
+
+export const fetchChainsByInferenceId = createAsyncThunk(
+ "chains/fetchChainByInference",
+ async (inferenceId, { dispatch, getState }) => {
+ let response = await api.get(
+ `/api/inference_chain/?inference_id=${inferenceId}`
+ );
+
+ const state = getState()
+ const responseIds = response.map(chain => chain.id)
+ const existingChains = selectChainsByInferenceId(state, inferenceId)
+ const deletedChains = existingChains.filter(chain => responseIds.indexOf(chain.id) == -1)
+ return {
+ chains: response,
+ deletedChains
+ };
+ }
+);
+
+export const chainsSlice = createSlice({
+ name: "chains",
+ initialState,
+ reducers: {
+ },
+ extraReducers: {
+ [fetchChains.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchChains.rejected]: (state, action) => {
+ state.status = "failed";
+ state.errorFetch = action.error.message;
+ },
+ [fetchChains.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ chainsAdapter.setAll(state, action.payload);
+ },
+ [fetchChainsByInferenceId.fulfilled]: (state, action) => {
+ if (action.payload.deletedChains.length > 0) {
+ chainsAdapter.removeMany(state, action.payload.deletedChains.map(c => c.id))
+ }
+ chainsAdapter.upsertMany(state, action.payload.chains)
+ },
+ [fetchChainById.fulfilled]: chainsAdapter.upsertOne,
+ },
+});
+
+export const { toggleChain } = chainsSlice.actions;
+
+export default chainsSlice.reducer;
+
+export const {
+ selectAll: selectAllChains,
+ selectById: selectChainById,
+ selectIds: selectChainIds,
+} = chainsAdapter.getSelectors((state) => state.chains);
+
+
+export const selectChainsByInferenceId = (state, id) => {
+ return selectAllChains(state).filter((chain) => chain.inference === id);
+};
diff --git a/frontend/src/features/inference/inferenceSlice.js b/frontend/src/features/inference/inferenceSlice.js
new file mode 100644
index 00000000..37405aa9
--- /dev/null
+++ b/frontend/src/features/inference/inferenceSlice.js
@@ -0,0 +1,216 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+import { normalize, schema } from "normalizr";
+import { fetchPdModelById} from '../pdModels/pdModelsSlice'
+import { fetchPkModelById} from '../pkModels/pkModelsSlice'
+import {
+ fetchVariablesByPkModel,
+ fetchVariablesByPdModel
+} from '../variables/variablesSlice'
+
+const inferencesAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = inferencesAdapter.getInitialState({
+ status: "idle",
+ errorFetch: null,
+ selectedId: null,
+});
+
+const variable = new schema.Entity("variables");
+const pd_model = new schema.Entity("pd_models");
+const dosed_pk_model = new schema.Entity("dosed_pk_models");
+const inference = new schema.Entity("inferences", {
+ variables: [variable],
+ pd_model_detail: pd_model,
+ dosed_pk_model_detail: dosed_pk_model,
+});
+
+export const fetchInferences = createAsyncThunk(
+ "inferences/fetchInferences",
+ async (project_id, { dispatch, getState }) => {
+ let response = await api.get(`/api/inference/?project_id=${project_id}`, getState().login.csrf);
+ //const normalized = normalize(response, [inference]);
+ //console.log("fetchInferences got", response, normalized);
+
+ return response;
+ }
+);
+
+export const fetchInferenceById = createAsyncThunk(
+ "inferences/fetchInferenceById",
+ async (inferenceId, { dispatch, getState }) => {
+ let inference = await api.get(`/api/inference/${inferenceId}/`, getState().login.csrf);
+ return inference;
+ }
+);
+
+export const addNewInference = createAsyncThunk(
+ "inferences/addNewInference",
+ async (project, { dispatch, getState }) => {
+ const initialInference = {
+ name: "new",
+ project: project.id,
+ log_likelihoods: [],
+ };
+ let inference = await api.post("/api/inference/", getState().login.csrf, initialInference);
+ inference.chosen = true;
+
+ return inference;
+ }
+);
+
+export const updateInference = createAsyncThunk(
+ "inferences/updateInference",
+ async (inference, { dispatch, getState }) => {
+ const response = await api.put(
+ `/api/inference/${inference.id}/`, getState().login.csrf,
+ inference
+ );
+ return response;
+ }
+);
+
+export const runInferenceWizard = createAsyncThunk(
+ "inferences/runInferenceWizard",
+ async (inference, { dispatch, getState }) => {
+ const newInference = await api.post(`/api/inference/wizard`, getState().login.csrf, inference);
+ for (const log_likelihood of newInference.log_likelihoods) {
+ if (log_likelihood.model && log_likelihood.model[0] === 'pkpdapp_pharmacodynamicmodel') {
+ dispatch(fetchPdModelById(log_likelihood.model[1]))
+ dispatch(fetchVariablesByPdModel(log_likelihood.model[1]))
+ }
+ if (log_likelihood.model && log_likelihood.model[0] === 'pkpdapp_dosedpharmacokineticmodel') {
+ dispatch(fetchPkModelById(log_likelihood.model[1]))
+ dispatch(fetchVariablesByPkModel(log_likelihood.model[1]))
+ }
+ }
+ return {
+ newInference,
+ inference,
+ }
+ }
+);
+
+export const runInference = createAsyncThunk(
+ "inferences/runInference",
+ async (inferenceId, { dispatch, getState }) => {
+ const newInference = await api.post(`/api/inference/${inferenceId}/run`, getState().login.csrf);
+ //const normalized = normalize(newInference, inference);
+ for (const log_likelihood of newInference.log_likelihoods) {
+ if (log_likelihood.pd_model) {
+ dispatch(fetchPdModelById(log_likelihood.pd_model))
+ dispatch(fetchVariablesByPdModel(log_likelihood.pd_model))
+ }
+ if (log_likelihood.dosed_pk_model){
+ dispatch(fetchPkModelById(log_likelihood.dosed_pk_model))
+ dispatch(fetchVariablesByPkModel(log_likelihood.dosed_pk_model))
+ }
+ }
+ return newInference;
+ }
+);
+
+export const stopInference = createAsyncThunk(
+ "inferences/stopInference",
+ async (inferenceId, { dispatch, getState }) => {
+ const newInference = await api.post(`/api/inference/${inferenceId}/stop`, getState().login.csrf);
+ //const normalized = normalize(newInference, inference);
+ return newInference;
+ }
+);
+
+export const deleteInference = createAsyncThunk(
+ "inferences/deleteInference",
+ async (inferenceId, { dispatch, getState }) => {
+ await api.delete(`/api/inference/${inferenceId}/`, getState().login.csrf);
+ return inferenceId;
+ }
+);
+
+export const inferencesSlice = createSlice({
+ name: "inferences",
+ initialState,
+ reducers: {
+ toggleInference(state, action) {
+ for (let inference of Object.values(state.entities)) {
+ if (inference.id === action.payload.id) {
+ inference.chosen = true
+ } else {
+ inference.chosen = false
+ }
+ }
+ },
+ setInferenceError(state, action) {
+ let inference = state.entities[action.payload.id];
+ inference.error = action.payload.error;
+ },
+ },
+ extraReducers: {
+ [fetchInferences.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchInferences.rejected]: (state, action) => {
+ state.status = "failed";
+ state.errorFetch = action.error.message;
+ },
+ [fetchInferences.fulfilled]: (state, action) => {
+ inferencesAdapter.upsertMany(state, action.payload);
+ state.status = "succeeded";
+ },
+ [fetchInferenceById.fulfilled]: inferencesAdapter.upsertOne,
+ [runInference.fulfilled]: (state, action) => {
+ inferencesAdapter.upsertOne(state, action.payload);
+ },
+ [runInferenceWizard.fulfilled]: (state, action) => {
+ if (action.payload.inference.id) {
+ inferencesAdapter.removeOne(state, action.payload.inference.id);
+ }
+ for (let inference of Object.values(state.entities)) {
+ inference.chosen = false
+ }
+ action.payload.newInference.chosen = true
+ inferencesAdapter.upsertOne(state, action.payload.newInference);
+ },
+ [stopInference.fulfilled]: (state, action) => {
+ inferencesAdapter.upsertOne(state, action.payload);
+ },
+ [addNewInference.fulfilled]: inferencesAdapter.addOne,
+ [updateInference.fulfilled]: inferencesAdapter.upsertOne,
+ [deleteInference.fulfilled]: inferencesAdapter.removeOne,
+ },
+});
+
+export const { toggleInference } = inferencesSlice.actions;
+
+export default inferencesSlice.reducer;
+
+export const {
+ selectAll: selectAllInferences,
+ selectById: selectInferenceById,
+ selectIds: selectInferenceIds,
+} = inferencesAdapter.getSelectors((state) => state.inferences);
+
+export const selectChosenInferences = (state) =>
+ selectAllInferences(state).filter((inference) => inference.chosen);
+
+export const selectChosenRunningInferences = (state) =>
+ selectAllInferences(state).filter(
+ (inference) => inference.chosen && inference.read_only
+ );
+
+export const selectChosenDraftInferences = (state) =>
+ selectAllInferences(state).filter(
+ (inference) => inference.chosen && !inference.read_only
+ );
+
+export const selectAllDraftInferences = (state) =>
+ selectAllInferences(state).filter((inference) => !inference.read_only);
+
+export const selectAllRunningInferences = (state) =>
+ selectAllInferences(state).filter((inference) => inference.read_only);
diff --git a/frontend/src/features/inference/objectiveFunctionsSlice.js b/frontend/src/features/inference/objectiveFunctionsSlice.js
new file mode 100644
index 00000000..985d291b
--- /dev/null
+++ b/frontend/src/features/inference/objectiveFunctionsSlice.js
@@ -0,0 +1,99 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+
+const objectiveFunctionsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = objectiveFunctionsAdapter.getInitialState({
+ status: "idle",
+ errorFetch: null,
+});
+
+export const fetchObjectiveFunctionsByInference = createAsyncThunk(
+ "objectiveFunctions/fetchObjectiveFunctions",
+ async (inference, { dispatch }) => {
+ let response = await api.get(
+ `/api/objective_function/?inference_id=${inference.id}`
+ );
+ return response;
+ }
+);
+
+export const fetchObjectiveFunctionById = createAsyncThunk(
+ "objectiveFunctions/fetchObjectiveFunctionById",
+ async (objectiveFunctionId, { dispatch }) => {
+ let objectiveFunction = await api.get(
+ `/api/objective_function/${objectiveFunctionId}/`
+ );
+ return objectiveFunction;
+ }
+);
+
+export const addNewObjectiveFunction = createAsyncThunk(
+ "objectiveFunctions/addNewObjectiveFunction",
+ async (project, { dispatch }) => {
+ const initialObjectiveFunction = {
+ name: "new",
+ project: project.id,
+ };
+ let objectiveFunction = await api.post(
+ "/api/objective_function/",
+ initialObjectiveFunction
+ );
+
+ return objectiveFunction;
+ }
+);
+
+export const updateObjectiveFunction = createAsyncThunk(
+ "objectiveFunctions/updateObjectiveFunction",
+ async (objectiveFunction, { getState }) => {
+ const response = await api.put(
+ `/api/objective_function/${objectiveFunction.id}/`,
+ objectiveFunction
+ );
+ return response;
+ }
+);
+
+export const deleteObjectiveFunction = createAsyncThunk(
+ "objectiveFunctions/deleteObjectiveFunction",
+ async (objectiveFunctionId, { dispatch }) => {
+ await api.delete(`/api/objective_function/${objectiveFunctionId}`);
+ return objectiveFunctionId;
+ }
+);
+
+export const objectiveFunctionsSlice = createSlice({
+ name: "objectiveFunctions",
+ initialState,
+ reducers: {},
+ extraReducers: {
+ [fetchObjectiveFunctionById.fulfilled]: objectiveFunctionsAdapter.upsertOne,
+ [fetchObjectiveFunctionsByInference.fulfilled]:
+ objectiveFunctionsAdapter.upsertMany,
+ [addNewObjectiveFunction.fulfilled]: objectiveFunctionsAdapter.addOne,
+ [updateObjectiveFunction.fulfilled]: objectiveFunctionsAdapter.upsertOne,
+ [deleteObjectiveFunction.fulfilled]: objectiveFunctionsAdapter.removeOne,
+ },
+});
+
+export const { toggleObjectiveFunction } = objectiveFunctionsSlice.actions;
+
+export default objectiveFunctionsSlice.reducer;
+
+export const {
+ selectAll: selectAllObjectiveFunctions,
+ selectById: selectObjectiveFunctionById,
+ selectIds: selectObjectiveFunctionIds,
+} = objectiveFunctionsAdapter.getSelectors((state) => state.objectiveFunctions);
+
+export const selectObjectiveFunctionsByInference = (state, inference) =>
+ selectAllObjectiveFunctions(state).filter(
+ (objectiveFunction) => objectiveFunction.inference === inference.id
+ );
diff --git a/frontend/src/features/inference/priorsSlice.js b/frontend/src/features/inference/priorsSlice.js
new file mode 100644
index 00000000..707fd8c1
--- /dev/null
+++ b/frontend/src/features/inference/priorsSlice.js
@@ -0,0 +1,86 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+
+const priorsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = priorsAdapter.getInitialState({
+ status: "idle",
+ errorFetch: null,
+});
+
+export const fetchPriorsByInference = createAsyncThunk(
+ "priors/fetchPriors",
+ async (inference, { dispatch }) => {
+ let response = await api.get(`/api/prior/?inference_id=${inference.id}`);
+ return response;
+ }
+);
+
+export const fetchPriorById = createAsyncThunk(
+ "priors/fetchPriorById",
+ async (priorId, { dispatch }) => {
+ let prior = await api.get(`/api/prior/${priorId}/`);
+ return prior;
+ }
+);
+
+export const addNewPrior = createAsyncThunk(
+ "priors/addNewPrior",
+ async (project, { dispatch }) => {
+ const initialPrior = {
+ name: "new",
+ project: project.id,
+ };
+ let prior = await api.post("/api/prior/", initialPrior);
+
+ return prior;
+ }
+);
+
+export const updatePrior = createAsyncThunk(
+ "priors/updatePrior",
+ async (prior, { getState }) => {
+ const response = await api.put(`/api/prior/${prior.id}/`, prior);
+ return response;
+ }
+);
+
+export const deletePrior = createAsyncThunk(
+ "priors/deletePrior",
+ async (priorId, { dispatch }) => {
+ await api.delete(`/api/prior/${priorId}`);
+ return priorId;
+ }
+);
+
+export const priorsSlice = createSlice({
+ name: "priors",
+ initialState,
+ reducers: {},
+ extraReducers: {
+ [fetchPriorById.fulfilled]: priorsAdapter.upsertOne,
+ [fetchPriorsByInference.fulfilled]: priorsAdapter.upsertMany,
+ [addNewPrior.fulfilled]: priorsAdapter.addOne,
+ [updatePrior.fulfilled]: priorsAdapter.upsertOne,
+ [deletePrior.fulfilled]: priorsAdapter.removeOne,
+ },
+});
+
+export const { togglePrior } = priorsSlice.actions;
+
+export default priorsSlice.reducer;
+
+export const {
+ selectAll: selectAllPriors,
+ selectById: selectPriorById,
+ selectIds: selectPriorIds,
+} = priorsAdapter.getSelectors((state) => state.priors);
+
+export const selectPriorsByInference = (state, inference) =>
+ selectAllPriors(state).filter((prior) => prior.inference === inference.id);
diff --git a/frontend/src/features/login/ActivateUser.js b/frontend/src/features/login/ActivateUser.js
new file mode 100644
index 00000000..58848581
--- /dev/null
+++ b/frontend/src/features/login/ActivateUser.js
@@ -0,0 +1,54 @@
+import makeStyles from '@mui/styles/makeStyles';
+import React, { useEffect } from "react";
+import { Link } from "react-router-dom";
+import Typography from "@mui/material/Typography";
+import { useHistory, useParams } from "react-router-dom";
+import Container from "@mui/material/Container";
+import { ReactComponent as PkpdAppIcon } from "../../logo_pkpdapp_with_text.svg";
+import { api } from "../../Api";
+
+const useStyles = makeStyles((theme) => ({
+ paper: {
+ marginTop: theme.spacing(8),
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ },
+ icon: {
+ margin: theme.spacing(3),
+ width: theme.spacing(20),
+ height: theme.spacing(8),
+ },
+ links: {
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ },
+}));
+
+export default function ActivateUser() {
+ const classes = useStyles();
+
+ let { uid, token } = useParams();
+ const history = useHistory();
+
+ useEffect(() => {
+ api.post("/auth/users/activation/", { uid, token }, false).then((data) => {
+ history.push("/activate-success");
+ });
+ });
+
+ return (
+
+
+
+
+ Activating User
+
+
+ Login
+
+
+
+ );
+}
diff --git a/frontend/src/features/login/ActivateUserSuccess.js b/frontend/src/features/login/ActivateUserSuccess.js
new file mode 100644
index 00000000..b43513cb
--- /dev/null
+++ b/frontend/src/features/login/ActivateUserSuccess.js
@@ -0,0 +1,7 @@
+import React from "react";
+import Success from "./Success";
+
+export default function ActivateUserSuccess() {
+ const text = "You have successfully activated your account";
+ return ;
+}
diff --git a/frontend/src/features/login/Login.js b/frontend/src/features/login/Login.js
new file mode 100644
index 00000000..832e9930
--- /dev/null
+++ b/frontend/src/features/login/Login.js
@@ -0,0 +1,88 @@
+import { api } from "../../Api";
+import makeStyles from '@mui/styles/makeStyles';
+import { useSelector, useDispatch } from "react-redux";
+import React from "react";
+import { Link, useLocation, Redirect } from "react-router-dom";
+import Button from "@mui/material/Button";
+import Box from "@mui/material/Box";
+import Stack from "@mui/material/Stack";
+import CssBaseline from "@mui/material/CssBaseline";
+import Alert from '@mui/material/Alert';
+import { useForm } from "react-hook-form";
+import Typography from "@mui/material/Typography";
+import Container from "@mui/material/Container";
+import { useHistory } from "react-router-dom";
+import { FormTextField } from "../forms/FormComponents";
+import { ReactComponent as PkpdAppIcon } from "../../logo_pkpdapp_with_text.svg";
+import { isAuthenticated, loginError, setCredentials, login } from "../login/loginSlice"
+
+export default function Login() {
+ const dispatch = useDispatch();
+ const { control, handleSubmit } = useForm();
+
+ const navigateBack = useSelector(isAuthenticated);
+ const location = useLocation();
+ const error = useSelector(loginError);
+ const history = useHistory();
+ const from = location.state?.referrer || "/";
+
+ if (navigateBack) {
+ return
+ }
+
+
+ const onSubmit = ({ username, password }) => {
+ dispatch(login({ username, password }))
+ };
+
+ return (
+
+
+
+
+ );
+}
diff --git a/frontend/src/features/login/Register.js b/frontend/src/features/login/Register.js
new file mode 100644
index 00000000..037baa5a
--- /dev/null
+++ b/frontend/src/features/login/Register.js
@@ -0,0 +1,128 @@
+import { api } from "../../Api";
+import makeStyles from '@mui/styles/makeStyles';
+import React from "react";
+import { Link } from "react-router-dom";
+import Button from "@mui/material/Button";
+import { useForm } from "react-hook-form";
+import Typography from "@mui/material/Typography";
+import Container from "@mui/material/Container";
+import { useHistory } from "react-router-dom";
+import { FormTextField } from "../forms/FormComponents";
+import { ReactComponent as PkpdAppIcon } from "../../logo_pkpdapp_with_text.svg";
+
+const useStyles = makeStyles((theme) => ({
+ paper: {
+ marginTop: theme.spacing(8),
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ },
+ icon: {
+ margin: theme.spacing(3),
+ width: theme.spacing(20),
+ height: theme.spacing(8),
+ },
+ form: {
+ width: "100%", // Fix IE 11 issue.
+ marginTop: theme.spacing(1),
+ },
+ submit: {
+ margin: theme.spacing(3, 1, 2),
+ },
+ links: {
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ },
+}));
+
+export default function Register() {
+ const classes = useStyles();
+ const { control, handleSubmit } = useForm();
+
+ const history = useHistory();
+
+ const onSubmit = (values) => {
+ api.post("/auth/users/", values, false).then((data) => {
+ history.push("/register-success");
+ });
+ };
+
+ return (
+
+
+
+
+ Register new user
+
+
+
+ Back to login
+
+
+
+ );
+}
diff --git a/frontend/src/features/login/RegisterSuccess.js b/frontend/src/features/login/RegisterSuccess.js
new file mode 100644
index 00000000..2cfb3ede
--- /dev/null
+++ b/frontend/src/features/login/RegisterSuccess.js
@@ -0,0 +1,8 @@
+import React from "react";
+import Success from "./Success";
+
+export default function RegisterSuccess() {
+ const text =
+ "You have successfully created a new user, please check your email for a link to activate this account";
+ return ;
+}
diff --git a/frontend/src/features/login/RequireLogin.jsx b/frontend/src/features/login/RequireLogin.jsx
new file mode 100644
index 00000000..646b97b8
--- /dev/null
+++ b/frontend/src/features/login/RequireLogin.jsx
@@ -0,0 +1,28 @@
+import * as React from 'react';
+import { useLocation, Redirect } from "react-router-dom";
+import { useSelector } from "react-redux";
+import { isAuthenticated } from "./loginSlice"
+
+
+export default function RequireAuth({ children }) {
+ let location = useLocation();
+ const gotoLogin = !useSelector(isAuthenticated);
+
+
+ if (gotoLogin) {
+ // Redirect them to the /login page, but save the current location they were
+ // trying to go to when they were redirected. This allows us to send them
+ // along to that page after they login, which is a nicer user experience
+ // than dropping them off on the home page.
+ return (
+
+ );
+ }
+
+ return children;
+}
diff --git a/frontend/src/features/login/ResetPassword.js b/frontend/src/features/login/ResetPassword.js
new file mode 100644
index 00000000..41c57f77
--- /dev/null
+++ b/frontend/src/features/login/ResetPassword.js
@@ -0,0 +1,99 @@
+import { api } from "../../Api";
+import makeStyles from '@mui/styles/makeStyles';
+import React from "react";
+import { Link } from "react-router-dom";
+import Button from "@mui/material/Button";
+import { useForm } from "react-hook-form";
+import Typography from "@mui/material/Typography";
+import Container from "@mui/material/Container";
+import { useHistory, useParams } from "react-router-dom";
+import { FormTextField } from "../forms/FormComponents";
+import { ReactComponent as PkpdAppIcon } from "../../logo_pkpdapp_with_text.svg";
+
+const useStyles = makeStyles((theme) => ({
+ paper: {
+ marginTop: theme.spacing(8),
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ },
+ icon: {
+ margin: theme.spacing(3),
+ width: theme.spacing(20),
+ height: theme.spacing(8),
+ },
+ form: {
+ width: "100%", // Fix IE 11 issue.
+ marginTop: theme.spacing(1),
+ },
+ submit: {
+ margin: theme.spacing(3, 1, 2),
+ },
+ links: {
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ },
+}));
+
+export default function ResetPassword() {
+ const classes = useStyles();
+ const { control, handleSubmit } = useForm();
+
+ let { uid, token } = useParams();
+ const history = useHistory();
+
+ const onSubmit = (values) => {
+ values = {
+ uid,
+ token,
+ ...values,
+ };
+ api
+ .post("/auth/users/reset_password_confirm/", values, false)
+ .then((data) => {
+ history.push("/reset-password-success");
+ });
+ };
+
+ return (
+
+
+
+
+ Register new user
+
+
+
+ Back to login
+
+
+
+ );
+}
diff --git a/frontend/src/features/login/ResetPasswordRequest.js b/frontend/src/features/login/ResetPasswordRequest.js
new file mode 100644
index 00000000..29b95ba1
--- /dev/null
+++ b/frontend/src/features/login/ResetPasswordRequest.js
@@ -0,0 +1,83 @@
+import { api } from "../../Api";
+import makeStyles from '@mui/styles/makeStyles';
+import React from "react";
+import { Link } from "react-router-dom";
+import Button from "@mui/material/Button";
+import { useForm } from "react-hook-form";
+import Typography from "@mui/material/Typography";
+import Container from "@mui/material/Container";
+import { useHistory } from "react-router-dom";
+import { FormTextField } from "../forms/FormComponents";
+import { ReactComponent as PkpdAppIcon } from "../../logo_pkpdapp_with_text.svg";
+
+const useStyles = makeStyles((theme) => ({
+ paper: {
+ marginTop: theme.spacing(8),
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ },
+ icon: {
+ margin: theme.spacing(3),
+ width: theme.spacing(20),
+ height: theme.spacing(8),
+ },
+ form: {
+ width: "100%", // Fix IE 11 issue.
+ marginTop: theme.spacing(1),
+ },
+ submit: {
+ margin: theme.spacing(3, 1, 2),
+ },
+ links: {
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ },
+}));
+
+export default function ResetPasswordRequest() {
+ const classes = useStyles();
+ const { control, handleSubmit } = useForm();
+
+ const history = useHistory();
+
+ const onSubmit = (values) => {
+ api.post("/auth/users/reset_password/", values, false).then((data) => {
+ history.push("/reset-password-request-success");
+ });
+ };
+
+ return (
+
+
+
+
+ Password Reset Request
+
+
+
+ Back to login
+
+
+
+ );
+}
diff --git a/frontend/src/features/login/ResetPasswordRequestSuccess.js b/frontend/src/features/login/ResetPasswordRequestSuccess.js
new file mode 100644
index 00000000..5fdc6f71
--- /dev/null
+++ b/frontend/src/features/login/ResetPasswordRequestSuccess.js
@@ -0,0 +1,8 @@
+import React from "react";
+import Success from "./Success";
+
+export default function ResetPasswordRequestSuccess() {
+ const text =
+ "Request submitted, please check your email for a link to complete the password reset";
+ return ;
+}
diff --git a/frontend/src/features/login/ResetPasswordSuccess.js b/frontend/src/features/login/ResetPasswordSuccess.js
new file mode 100644
index 00000000..d3ad1e17
--- /dev/null
+++ b/frontend/src/features/login/ResetPasswordSuccess.js
@@ -0,0 +1,7 @@
+import React from "react";
+import Success from "./Success";
+
+export default function ResetPasswordSuccess() {
+ const text = "Password successfully changed";
+ return ;
+}
diff --git a/frontend/src/features/login/Success.js b/frontend/src/features/login/Success.js
new file mode 100644
index 00000000..2c987e5d
--- /dev/null
+++ b/frontend/src/features/login/Success.js
@@ -0,0 +1,44 @@
+import makeStyles from '@mui/styles/makeStyles';
+import React from "react";
+import { Link } from "react-router-dom";
+import Typography from "@mui/material/Typography";
+import Container from "@mui/material/Container";
+import { ReactComponent as PkpdAppIcon } from "../../logo_pkpdapp_with_text.svg";
+
+const useStyles = makeStyles((theme) => ({
+ paper: {
+ marginTop: theme.spacing(8),
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ },
+ icon: {
+ margin: theme.spacing(3),
+ width: theme.spacing(20),
+ height: theme.spacing(8),
+ },
+ links: {
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ },
+}));
+
+export default function Success({ text }) {
+ const classes = useStyles();
+
+ return (
+
+
+
+
+ Success
+
+
{text}
+
+ Login
+
+
+
+ );
+}
diff --git a/frontend/src/features/login/loginSlice.js b/frontend/src/features/login/loginSlice.js
new file mode 100644
index 00000000..fa7447f2
--- /dev/null
+++ b/frontend/src/features/login/loginSlice.js
@@ -0,0 +1,136 @@
+import { createSlice, PayloadAction, createAsyncThunk } from "@reduxjs/toolkit";
+
+import { api } from "../../Api";
+
+
+export const fetchCsrf = createAsyncThunk(
+ "login/fetchCsrf",
+ async (project, { dispatch }) => {
+ const response = await fetch("/api/csrf/", {
+ method: "GET",
+ credentials: "include",
+ }).then(response => response.json());
+ localStorage.setItem("csrf", response['X-CSRFToken']);
+ return response['X-CSRFToken'];
+ }
+);
+
+export const fetchSession = createAsyncThunk(
+ "login/fetchSession",
+ async (_, { dispatch }) => {
+ const { isAuthenticated, user } = await fetch("/api/session/", {
+ method: "GET",
+ credentials: "include",
+ }).then((response) => {
+ dispatch(fetchCsrf());
+ return isResponseOk(response)
+ }).then(data =>
+ ({ isAuthenticated: true, user: data.user })
+ ).catch((err) =>
+ ({ isAuthenticated: false, user: null })
+ );
+ console.log('fetchSession', isAuthenticated, user)
+ return { isAuthenticated, user };
+ }
+);
+
+function isResponseOk(response) {
+ if (response.status >= 200 && response.status <= 299) {
+ return response.json();
+ } else {
+ throw Error(response.statusText);
+ }
+}
+
+
+
+export const login = createAsyncThunk(
+ "login/login",
+ async ({username, password}, { getState, dispatch }) => {
+ const csrf = getState().login.csrf;
+ const response = fetch("/api/login/", {
+ method: "POST",
+ credentials: "include",
+ headers: {
+ "Content-Type": "application/json",
+ "X-CSRFToken": csrf,
+ },
+ body: JSON.stringify({username: username, password: password}),
+ })
+ .then(isResponseOk)
+ .then((data) => {
+ //dispatch(fetchCsrf());
+ return {isAuthenticated: true, user: data.user, error: null}
+ })
+ .catch((err) => {
+ return {isAuthenticated: false, user: null, error: "Wrong usename or password"}
+ });
+ return response;
+ }
+);
+
+export const logout = createAsyncThunk(
+ "login/logout",
+ async (_, { dispatch }) => {
+ const response = await fetch("/api/logout/", {
+ method: "GET",
+ credentials: "include",
+ })
+ .then(isResponseOk)
+ .then((data) => {
+ dispatch(fetchCsrf());
+ return {isAuthenticated: false}
+ });
+ return response;
+ }
+);
+
+const slice = createSlice({
+
+ name: "login",
+ initialState: { user: null, csrf: null, isAuthenticated: false, error: null },
+ reducers: {
+ setCredentials: (state, action) => {
+ const user = action.payload.user;
+ const csrf = action.payload.csrf;
+ console.log('setCredentials', user)
+ state.user = user;
+ state.csrf = csrf;
+ }
+ },
+ extraReducers: {
+ [fetchCsrf.fulfilled]: (state, action) => {
+ state.csrf = action.payload
+ },
+ [fetchSession.fulfilled]: (state, action) => {
+ state.isAuthenticated = action.payload.isAuthenticated
+ state.user = action.payload.user
+ },
+ [login.fulfilled]: (state, action) => {
+ console.log('login.fulfilled', action.payload)
+ state.isAuthenticated = action.payload.isAuthenticated;
+ state.user = action.payload.user;
+ state.error = action.payload.error;
+ },
+ [logout.fulfilled]: (state, action) => {
+ state.isAuthenticated = action.payload.isAuthenticated;
+ },
+ }
+});
+
+export const { setCredentials } = slice.actions;
+
+export default slice.reducer;
+
+export const selectCurrentUser = (state) => state.login.user;
+export const selectCsrf = (state) => state.login.csrf;
+export const selectAuthHeaders = (state) => {
+ let headers = {}
+ const csrf = state.login.csrf;
+ if (csrf) {
+ headers["X-CSRFToken"] = csrf;
+ }
+ return headers
+}
+export const isAuthenticated = (state) => state.login.isAuthenticated;
+export const loginError = (state) => state.login.error;
diff --git a/frontend/src/features/menu/AvatarListItem.js b/frontend/src/features/menu/AvatarListItem.js
new file mode 100644
index 00000000..df09523d
--- /dev/null
+++ b/frontend/src/features/menu/AvatarListItem.js
@@ -0,0 +1,78 @@
+import React from "react";
+
+import ListItem from "@mui/material/ListItem";
+import ListItemSecondaryAction from "@mui/material/ListItemSecondaryAction";
+import ListItemIcon from "@mui/material/ListItemIcon";
+import ListItemText from "@mui/material/ListItemText";
+import Checkbox from "@mui/material/Checkbox";
+import Box from "@mui/material/Box";
+import classNames from "classnames";
+import Tooltip from "@mui/material/Tooltip";
+import CircularProgress from "@mui/material/CircularProgress";
+import ListItemAvatar from "@mui/material/ListItemAvatar";
+import Avatar from "@mui/material/Avatar";
+import makeStyles from '@mui/styles/makeStyles';
+
+const useStyles = makeStyles((theme) => ({
+ nested: {
+ paddingLeft: theme.spacing(4),
+ },
+ colorSelected: {
+ backgroundColor: theme.palette.secondary.main,
+ },
+ avatarSmall: {
+ width: theme.spacing(3),
+ height: theme.spacing(3),
+ },
+}));
+
+export default function AvatarListItem({
+ nested,
+ item,
+ selected,
+ handleClick,
+ handleToggle,
+ small,
+ checked,
+ loading,
+}) {
+ const classes = useStyles();
+ const avatarClassName = classNames(
+ small ? classes.avatarSmall : null,
+ selected ? classes.colorSelected : null
+ );
+ const itemClassName = classNames(nested ? classes.nested : null);
+
+ const marginAdjust = -2;
+
+ let avatar = (
+
+ {item.name[0]}
+
+ );
+ if (loading) {
+ avatar = (
+
+
+
+ );
+ }
+
+ return (
+
+
+ {avatar}
+
+ {handleToggle &&
+
+
+
+ }
+
+
+ );
+}
diff --git a/frontend/src/features/menu/ExpandableListItem.js b/frontend/src/features/menu/ExpandableListItem.js
new file mode 100644
index 00000000..c1981bc1
--- /dev/null
+++ b/frontend/src/features/menu/ExpandableListItem.js
@@ -0,0 +1,168 @@
+import React from "react";
+import { useDispatch } from "react-redux";
+import makeStyles from '@mui/styles/makeStyles';
+import { useSelector } from "react-redux";
+
+import List from "@mui/material/List";
+import ListItem from "@mui/material/ListItem";
+import ListItemIcon from "@mui/material/ListItemIcon";
+import ListItemText from "@mui/material/ListItemText";
+
+import TableChartIcon from "@mui/icons-material/TableChart";
+import AccessibilityIcon from "@mui/icons-material/Accessibility";
+import FunctionsIcon from "@mui/icons-material/Functions";
+
+import CircularProgress from "@mui/material/CircularProgress";
+import Tooltip from "@mui/material/Tooltip";
+
+import Collapse from "@mui/material/Collapse";
+import ExpandLess from "@mui/icons-material/ExpandLess";
+import ExpandMore from "@mui/icons-material/ExpandMore";
+
+import Avatar from "@mui/material/Avatar";
+import ListItemAvatar from "@mui/material/ListItemAvatar";
+import AddIcon from "@mui/icons-material/Add";
+
+import AvatarListItem from "./AvatarListItem";
+
+import { selectItem as selectModellingItem } from "../modelling/modellingSlice"
+import { addNewDataset, selectDatasetById, selectDatasetIds, toggleDataset } from "../datasets/datasetsSlice.js";
+import { addNewPkModel, selectPkModelById, selectPkModelIds, selectWritablePkModelIds, togglePkModel } from "../pkModels/pkModelsSlice.js";
+import { addNewPdModel, selectPdModelById, selectPdModelIds, selectWritablePdModelIds, togglePdModel } from "../pdModels/pdModelsSlice.js";
+import { addNewProtocol, selectProtocolById, selectProtocolIds, toggleProtocol } from "../protocols/protocolsSlice.js";
+import { addNewInference, selectInferenceById, selectInferenceIds, toggleInference } from "../inference/inferenceSlice";
+
+const useStyles = makeStyles((theme) => ({
+ avatarPlusSmall: {
+ width: theme.spacing(3),
+ height: theme.spacing(3),
+ backgroundColor: theme.palette.primary.main,
+ },
+}));
+
+function GenericListItem({id, type, selector, handleToggle, handleClickItem}) {
+ const item = useSelector((state) => selector(state, id))
+ if (!item) {
+ return (null)
+ }
+ const loading = item.status ? item.status === "loading" : false;
+ const simulateLoading = item.simulate
+ ? item.simulate.status === "loading"
+ : false;
+
+ return (
+ handleToggle(item) : null}
+ handleClick={() => handleClickItem(item)}
+ />
+ );
+}
+
+
+export default function ExpandableListItem({
+ text,
+ type,
+ project,
+ disableSave,
+}) {
+ const dispatch = useDispatch();
+ const classes = useStyles();
+ const [open, setOpen] = React.useState(true);
+
+ const handleClick = () => {
+ setOpen(!open);
+ };
+
+ let selectorById = null
+ let selector = null
+ let Icon = null
+ let toggle = null
+ let addNew = null
+ let selectItem = selectModellingItem
+ if (type == 'dataset') {
+ selectorById = selectDatasetById
+ selector = selectDatasetIds
+ Icon = TableChartIcon
+ toggle = toggleDataset
+ addNew = addNewDataset
+ }
+ if (type == 'pk_model') {
+ selectorById = selectPkModelById
+ selector = selectWritablePkModelIds
+ Icon = AccessibilityIcon
+ toggle = togglePkModel
+ addNew = addNewPkModel
+ }
+ if (type == 'pd_model') {
+ selectorById = selectPdModelById
+ selector = selectWritablePdModelIds
+ Icon = FunctionsIcon
+ toggle = togglePdModel
+ addNew = addNewPdModel
+ }
+ if (type == 'protocol') {
+ selector = selectProtocolIds
+ selectorById = selectProtocolById
+ Icon = AccessibilityIcon
+ toggle = toggleProtocol
+ addNew = addNewProtocol
+ }
+ if (type == 'inference') {
+ selector = selectInferenceIds
+ selectorById = selectInferenceById
+ Icon = AccessibilityIcon
+ toggle = null
+ addNew = addNewInference
+ }
+
+ const ids = useSelector(selector);
+ const handleToggle = toggle ? (item) => dispatch(toggle(item)) : null
+ const handleClickItem = (item) => {
+ dispatch(selectItem({type: type, id: item.id}));
+ }
+ const handleNewItem = () => dispatch(addNew(project)).then((arg) => dispatch(selectItem({id: arg.payload.id, type: type})));
+
+ return (
+
+
+
+
+
+
+ {open ? : }
+
+
+
+ {ids && ids.map((id) => (
+
+ ))}
+
+ {handleNewItem && (
+
+
+
+
+
+
+
+
+
+ )}
+
+
+
+ );
+}
diff --git a/frontend/src/features/menu/InferenceMenu.js b/frontend/src/features/menu/InferenceMenu.js
new file mode 100644
index 00000000..0f05db86
--- /dev/null
+++ b/frontend/src/features/menu/InferenceMenu.js
@@ -0,0 +1,45 @@
+import React from "react";
+
+import { useSelector } from "react-redux";
+import AccountTreeIcon from "@mui/icons-material/AccountTree";
+
+import List from "@mui/material/List";
+import ListItem from "@mui/material/ListItem";
+import ListItemIcon from "@mui/material/ListItemIcon";
+import ListItemText from "@mui/material/ListItemText";
+
+import Divider from "@mui/material/Divider";
+
+import Inferences from "../inference/Inferences";
+import DraftInferences from "../inference/DraftInferences";
+
+import {
+ selectChosenProject,
+ userHasReadOnlyAccess,
+} from "../projects/projectsSlice.js";
+
+export default function ProjectMenu() {
+ const project = useSelector(selectChosenProject);
+ console.log("got project", project);
+
+ const disableSave = project ? userHasReadOnlyAccess(project) : true;
+
+ const projectName = project ? project.name : "None";
+
+ return (
+
+
+
+
+
+
+
+ {project && (
+
+
+
+
+ )}
+
+ );
+}
diff --git a/frontend/src/features/menu/LinearProgressWithLabel.js b/frontend/src/features/menu/LinearProgressWithLabel.js
new file mode 100644
index 00000000..a8ab97b4
--- /dev/null
+++ b/frontend/src/features/menu/LinearProgressWithLabel.js
@@ -0,0 +1,19 @@
+import React from "react";
+import Box from "@mui/material/Box";
+import LinearProgress from "@mui/material/LinearProgress";
+import Typography from '@mui/material/Typography';
+
+
+export default function LinearProgressWithLabel(props) {
+ return (
+
+ {`${props.value}%`}
+
+
+
+
+ );
+}
diff --git a/frontend/src/features/modelling/Chart.js b/frontend/src/features/modelling/Chart.js
new file mode 100644
index 00000000..a03b8eb4
--- /dev/null
+++ b/frontend/src/features/modelling/Chart.js
@@ -0,0 +1,383 @@
+import React from "react";
+import { useSelector } from "react-redux";
+
+import makeStyles from '@mui/styles/makeStyles';
+import List from "@mui/material/List";
+import Alert from '@mui/material/Alert';
+import Box from "@mui/material/Box";
+import Tooltip from "@mui/material/Tooltip";
+import Grid from "@mui/material/Grid";
+import ListItem from "@mui/material/ListItem";
+import ListItemIcon from "@mui/material/ListItemIcon";
+import ListItemText from "@mui/material/ListItemText";
+
+
+
+import { Scatter } from "react-chartjs-2";
+import Header from "../modelling/Header";
+
+import { Chart, registerables, Interaction } from "chart.js";
+import { CrosshairPlugin, Interpolate } from "chartjs-plugin-crosshair";
+import { getColor, getShape } from "./ShapesAndColors";
+import {Typography} from "@mui/material";
+
+Chart.register(...registerables, CrosshairPlugin);
+Interaction.modes.interpolate = Interpolate;
+
+
+export default function ModellingChart({ datasets, pkModels, pdModels, visualHeight }) {
+ let renderChart = true;
+
+ let showRhsAxis = false;
+
+ const biomarkers = useSelector((state) => state.biomarkerTypes.entities);
+ const subjects = useSelector((state) => state.subjects.entities);
+ const variables = useSelector((state) => state.variables.entities);
+ const units = useSelector((state) => state.units.entities);
+
+ let labelsShown = {}
+
+ let xLimits = [0, 0];
+ let updateXLimits = (data) => {
+ xLimits[0] = Math.min(xLimits[0], Math.min(...data));
+ xLimits[1] = Math.max(xLimits[1], Math.max(...data));
+ };
+
+ const getChartData = (model) => {
+ console.log("getChartData");
+ if (!model.simulate) {
+ return {};
+ }
+ let model_simulate = { ...model.simulate };
+ delete model_simulate.status;
+ const have_all_variables =
+ Object.keys(model_simulate).filter((id) => id in variables).length ===
+ Object.keys(model_simulate).length;
+ if (!have_all_variables) {
+ return {};
+ }
+ const time_id = Object.keys(model_simulate).filter(
+ (id) => variables[id].binding === "time"
+ )[0];
+ const time_variable = variables[time_id]
+ const time_unit = time_variable ? units[time_variable.unit] : null;
+
+ return Object.entries(model_simulate)
+ .map(([variable_id, data]) => {
+ const variable = variables[variable_id];
+ const unit = units[variable.unit];
+ console.log("doing variable", variable, variable_id);
+ const color = getColor(variable.color);
+ if (!variable.display) {
+ return null;
+ }
+ const yAxisID = variable.axis ? "yRhs" : "yLhs";
+ if (variable.axis) {
+ showRhsAxis = true;
+ }
+ // chartjs crashes if there are identical labels
+ let label = `${variable.qname} [${unit ? unit.symbol : ''}]`;
+ if (label in labelsShown) {
+ label = `${label}${labelsShown[label]}`
+ labelsShown[label] += 1
+ } else {
+ labelsShown[label] = 1
+ }
+ updateXLimits(model_simulate[time_id]);
+ return {
+ yAxisID: yAxisID,
+ type: "line",
+ label: label,
+ borderColor: color,
+ backgroundColor: color,
+ showLine: true,
+ fill: false,
+ lineTension: 0,
+ interpolate: true,
+ myMetadata: {
+ ylabel: label,
+ xlabel: `${model.name}.time [${time_unit ? time_unit.symbol : ''}]`,
+ yunit: unit,
+ xunit: time_unit,
+ },
+ data: data.map((y, i) => ({ x: model_simulate[time_id][i], y: y })),
+ };
+ })
+ .filter((x) => x);
+ };
+
+ const getChartDataDataset = (dataset) => {
+ return dataset.biomarker_types
+ .map((id) => {
+ const biomarker = biomarkers[id];
+ if (!biomarker) {
+ return null;
+ }
+ const display_unit = units[biomarker.display_unit];
+ const display_time_unit = units[biomarker.display_time_unit];
+ const subjectsDisplay = biomarker.data.subjects.map((id) =>
+ subjects[id] ? subjects[id].display : false
+ );
+ const subjectsDisplayFilter = (_, i) => subjectsDisplay[i];
+ const times = biomarker.data.times.filter(subjectsDisplayFilter);
+ const values = biomarker.data.values.filter(subjectsDisplayFilter);
+ const color = getColor(biomarker.color);
+ const pointStyle = biomarker.data.subjects
+ .filter(subjectsDisplayFilter)
+ .map((id) => getShape(subjects[id].shape));
+ if (!biomarker.display) {
+ return null;
+ }
+ if (values.length === 0) {
+ return null;
+ }
+ const yAxisID = biomarker.axis ? "yRhs" : "yLhs";
+ if (biomarker.axis) {
+ showRhsAxis = true;
+ }
+ const label = `${dataset.name}.${biomarker.name} [${display_unit ? display_unit.symbol : ''}]`;
+ updateXLimits(times);
+ return {
+ yAxisID: yAxisID,
+ label: label,
+ pointStyle: pointStyle,
+ borderColor: color,
+ backgroundColor: color,
+ myMetadata: {
+ ylabel: label,
+ xlabel: `${dataset.name}.time [${display_time_unit ? display_time_unit.symbol : ''}]`,
+ yunit: display_unit,
+ xunit: display_time_unit,
+ },
+ data: values.map((y, i) => ({ x: times[i], y: y })),
+ };
+ })
+ .filter((x) => x);
+ };
+
+ const getChartDataProtocol = (dataset) => {
+ return dataset.protocols
+ .map((protocol, index) => {
+ const display_unit = units[protocol.amount_unit];
+ const display_time_unit = units[protocol.time_unit];
+ const subjectsDisplay = protocol.subjects.map(id => subjects[id] ? subjects[id].display : false)
+ console.log("subjectsDisplay", subjectsDisplay)
+ const protocolDisplay = subjectsDisplay.some((x) => x);
+ if (!protocolDisplay) {
+ return null;
+ }
+ let times = protocol.doses.map(dose => [dose.start_time, dose.start_time, dose.start_time + dose.duration, dose.start_time + dose.duration]).flat();
+ let values = protocol.doses.map(dose => [0, dose.amount, dose.amount, 0]).flat();
+ times.unshift(xLimits[0]);
+ times.push(xLimits[1]);
+ values.unshift(0);
+ values.push(0);
+ console.log("times", times)
+ console.log("values", values)
+ const color = getColor(index);
+ if (values.length === 0) {
+ return null;
+ }
+ const yAxisID = "yLhs";
+ const label = `${protocol.name} [${display_unit ? display_unit.symbol : ''}]`;
+ return {
+ yAxisID: yAxisID,
+ label: label,
+ type: "line",
+ fill: true,
+ lineTension: 0,
+ interpolate: true,
+ borderColor: color,
+ backgroundColor: color,
+ myMetadata: {
+ ylabel: label,
+ xlabel: `${protocol.name}.time [${display_time_unit ? display_time_unit.symbol : ''}]`,
+ yunit: display_unit,
+ xunit: display_time_unit,
+ },
+ data: values.map((y, i) => ({ x: times[i], y: y })),
+ };
+ })
+ .filter((x) => x);
+ };
+
+ const data = {
+ datasets: [
+ ...datasets
+ .map((d) => getChartDataDataset(d))
+ .flat()
+ .flat(),
+ ...pkModels.map((m) => getChartData(m)).flat(),
+ ...pdModels.map((m) => getChartData(m)).flat(),
+ ],
+ };
+
+ const data_protocols = {
+ datasets: [
+ ...datasets.map((d) => getChartDataProtocol(d)).flat().flat(),
+ ]
+ }
+
+ const showProtocols = datasets.length > 0;
+
+ const y_unit_symbols = data.datasets.reduce((sum, dataset) => {
+ if (!dataset?.myMetadata) {
+ return sum;
+ }
+ const unit = dataset.myMetadata.yunit;
+ sum.add(unit ? unit.symbol : '');
+ return sum;
+ }, new Set());
+
+ const y_amount_unit_symbols = data_protocols.datasets.reduce((sum, dataset) => {
+ if (!dataset?.myMetadata) {
+ return sum;
+ }
+ const unit = dataset.myMetadata.yunit;
+ sum.add(unit ? unit.symbol : '');
+ return sum;
+ }, new Set());
+
+ const x_unit_symbols = data.datasets.reduce((sum, dataset) => {
+ if (!dataset?.myMetadata) {
+ return sum;
+ }
+ const unit = dataset.myMetadata.xunit;
+ sum.add(unit ? unit.symbol : '');
+ return sum;
+ }, new Set());
+
+ const incompatible_y_unit = y_unit_symbols.size > 1;
+ const incompatible_x_unit = x_unit_symbols.size > 1;
+
+ const list_of_y_unit = new Array(...y_unit_symbols).join(', ');
+ const list_of_y_amount_unit = new Array(...y_amount_unit_symbols).join(', ');
+ const list_of_x_unit = new Array(...x_unit_symbols).join(', ');
+
+ let crosshair = {
+ line: {
+ color: '#F66', // crosshair line color
+ width: 1 // crosshair line width
+ },
+ sync: {
+ enabled: true, // enable trace line syncing with other charts
+ suppressTooltips: false // suppress tooltips when showing a synced tracer
+ },
+ zoom: {
+ enabled: true, // enable zooming
+ zoomboxBackgroundColor: 'rgba(66,133,244,0.2)', // background color of zoom box
+ zoomboxBorderColor: '#48F', // border color of zoom box
+ zoomButtonText: 'Reset Zoom', // reset zoom button text
+ zoomButtonClass: 'reset-zoom', // reset zoom button class
+ },
+ }
+
+ let plugins = {
+ legend: {
+ labels: {
+ usePointStyle: true,
+ },
+ },
+ tooltip: {
+ mode: "interpolate",
+ callbacks: {
+ title: function (a, d) {
+ return a[0].element.x.toPrecision(4);
+ },
+ label: function (d) {
+ return d.dataset.label + ": " + d.element.y.toPrecision(4);
+ },
+ },
+ },
+ crosshair,
+ };
+
+ let options_protocols = {
+ animation: {
+ duration: 0,
+ },
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ x: {
+ type: "linear",
+ title: {
+ text: `Time [${list_of_x_unit}]`,
+ display: false,
+ },
+ },
+ yLhs: {
+ position: "left",
+ title: {
+ text: `Dose Amount [${list_of_y_amount_unit}]`,
+ display: true,
+ }
+ }
+ },
+ plugins,
+ }
+
+ let options = {
+ animation: {
+ duration: 0,
+ },
+ responsive: true,
+ maintainAspectRatio: false,
+ scales: {
+ x: {
+ type: "linear",
+ title: {
+ text: `Time [${list_of_x_unit}]`,
+ display: true,
+ },
+ },
+ yLhs: {
+ position: "left",
+ title: {
+ text: `Data Variable / Model Output [${list_of_y_unit}]`,
+ display: true,
+ },
+ },
+ },
+ plugins,
+ };
+
+ if (showRhsAxis) {
+ options.scales["yRhs"] = {
+ position: "right",
+ title: {
+ text: "Data Variable / Model Output (units defined above)",
+ display: true,
+ },
+ };
+ }
+
+ const chartVisualHeight = visualHeight * 3.0 / 4.0;
+ const chartVisualHeightStr = `${chartVisualHeight}vh}`;
+ const protocolVisualHeight = visualHeight * 1.0 / 4.0;
+ const protocolVisualHeightStr = `${protocolVisualHeight}vh}`;
+
+ console.log('data', data, options, renderChart)
+ return (
+
+
+ {renderChart && }
+
+ {showProtocols &&
+
+ {renderChart && }
+
+ }
+ {incompatible_y_unit &&
+
+ Different units on y-axis
+
+ }
+ {incompatible_x_unit &&
+
+ Different units on x-axis
+
+ }
+
+ );
+}
diff --git a/frontend/src/features/modelling/ChartController.js b/frontend/src/features/modelling/ChartController.js
new file mode 100644
index 00000000..b1513307
--- /dev/null
+++ b/frontend/src/features/modelling/ChartController.js
@@ -0,0 +1,3 @@
+export default function ChartController() {
+ return null;
+}
diff --git a/frontend/src/features/modelling/Footer.js b/frontend/src/features/modelling/Footer.js
new file mode 100644
index 00000000..78b47bfb
--- /dev/null
+++ b/frontend/src/features/modelling/Footer.js
@@ -0,0 +1,66 @@
+import React, { useEffect } from "react";
+import Paper from "@mui/material/Paper";
+import makeStyles from '@mui/styles/makeStyles';
+import Button from "@mui/material/Button";
+import Toolbar from "@mui/material/Toolbar";
+import Typography from "@mui/material/Typography";
+
+const useStyles = makeStyles((theme) => ({
+ controls: {
+ justifyContent: 'center',
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ },
+ toolbar: {
+ marginTop: theme.spacing(1),
+ backgroundColor: theme.palette.primary.main,
+ position: 'sticky',
+ bottom: 0,
+ borderRadius: '0 0 5px 5px',
+ }
+}));
+
+export default function Footer({ buttons, disableSave, variant }) {
+ const classes = useStyles();
+ const button = null
+ const createButton = (button, i) => {
+ if (button.variant == 'fileUpload') {
+ return (
+
+ {button.label}
+
+
+ )
+ } else {
+ return(
+
+ {button.label}
+
+
+ )
+ }
+ };
+
+ return (
+
+
+ {buttons.map(createButton)}
+
+
+ )
+}
diff --git a/frontend/src/features/modelling/Header.js b/frontend/src/features/modelling/Header.js
new file mode 100644
index 00000000..cc17b990
--- /dev/null
+++ b/frontend/src/features/modelling/Header.js
@@ -0,0 +1,31 @@
+import React, { useEffect } from "react";
+import Paper from "@mui/material/Paper";
+import makeStyles from '@mui/styles/makeStyles';
+import Toolbar from "@mui/material/Toolbar";
+import Typography from "@mui/material/Typography";
+
+const useStyles = makeStyles((theme) => ({
+ topToolbar: {
+ backgroundColor: theme.palette.primary.main,
+ position: 'sticky',
+ top: 0,
+ borderRadius: '5px 5px 0 0',
+ zIndex: 10,
+ marginBottom: theme.spacing(1),
+ },
+ header: {
+ fontWeight:'bold',
+ color: theme.palette.primary.contrastText,
+ },
+}));
+
+export default function Header({ title }) {
+ const classes = useStyles();
+ return (
+
+
+ {title}
+
+
+ )
+}
diff --git a/frontend/src/features/modelling/Modelling.js b/frontend/src/features/modelling/Modelling.js
new file mode 100644
index 00000000..cb9f554a
--- /dev/null
+++ b/frontend/src/features/modelling/Modelling.js
@@ -0,0 +1,277 @@
+import React from "react";
+import { useDispatch, useSelector } from "react-redux";
+import Paper from "@mui/material/Paper";
+import Grid from "@mui/material/Grid";
+import PkDetail from "../pkModels/PkDetail";
+import AccountTreeIcon from "@mui/icons-material/AccountTree";
+import PdDetail from "../pdModels/PdDetail";
+import Toolbar from '@mui/material/Toolbar';
+import ProtocolDetail from "../protocols/ProtocolDetail";
+import DatasetDetail from "../datasets/DatasetDetail";
+import Chart from "./Chart";
+import Drawer from "@mui/material/Drawer";
+import Accordion from "@mui/material/Accordion";
+import AccordionSummary from "@mui/material/AccordionSummary";
+import AccordionDetails from "@mui/material/AccordionDetails";
+import Box from "@mui/material/Box";
+import CircularProgress from "@mui/material/CircularProgress";
+import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
+import Typography from "@mui/material/Typography";
+import List from "@mui/material/List";
+import ListItem from "@mui/material/ListItem";
+import ListItemIcon from "@mui/material/ListItemIcon";
+import ListItemText from "@mui/material/ListItemText";
+
+import makeStyles from '@mui/styles/makeStyles';
+
+import Header from "../modelling/Header";
+import Footer from "../modelling/Footer";
+import { selectChosenProject, userHasReadOnlyAccess } from "../projects/projectsSlice.js";
+
+import { selectChosenDatasets, selectChosenDatasetProtocols, selectDatasetById } from "../datasets/datasetsSlice.js";
+
+import { selectChosenPdModels, selectPdModelById } from "../pdModels/pdModelsSlice.js";
+
+import { selectChosenPkModels, selectPkModelById } from "../pkModels/pkModelsSlice.js";
+
+import { selectChosenProtocols, selectProtocolById } from "../protocols/protocolsSlice.js";
+
+import { clearSelectItem } from "./modellingSlice"
+
+import DatasetProtocols from "../protocols/DatasetProtocols";
+import ProjectDetail from "../projects/ProjectDetail";
+import ExpandableListItem from "../menu/ExpandableListItem";
+
+const drawerWidth = 250;
+
+const useStyles = makeStyles((theme) => ({
+ drawer: {
+ width: drawerWidth,
+ flexShrink: 0,
+ '& .MuiDrawer-paper': {
+ width: drawerWidth,
+ boxSizing: 'border-box',
+ },
+ },
+ main: {
+ marginLeft: drawerWidth,
+ flexGrow: 1,
+ },
+ paperChart: {
+ padding: theme.spacing(2),
+ maxHeight: '90vh', overflow: 'auto'
+ },
+ chart: {
+ height: "50vh",
+ width: "100%",
+ },
+ protocolChart: {
+ height: "40vh",
+ width: "100%",
+ marginTop: theme.spacing(2),
+ },
+ mmt_box: {
+ width: "100%",
+ padding: theme.spacing(2),
+ maxHeight: '23vh', overflow: 'auto'
+ },
+ mmt: {
+ whiteSpace: 'pre-wrap'
+ },
+}));
+
+function Mmt({ item, project }) {
+ const classes = useStyles();
+ console.log('mmt', item.mmt)
+ return (
+
+
+
+
+ {item.mmt}
+
+
+
+
+ )
+}
+
+function ModellingMenu({ project }) {
+ const readOnly = useSelector((state) => userHasReadOnlyAccess(state, project));
+ const disableSave = project ? readOnly : true;
+ const dispatch = useDispatch();
+ const handleProjectClick = () => dispatch(clearSelectItem());
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function ModellingChart({ project }) {
+ const classes = useStyles();
+ const chosenDatasets = useSelector(selectChosenDatasets);
+ const chosenPkModels = useSelector(selectChosenPkModels);
+ const chosenPdModels = useSelector(selectChosenPdModels);
+ const chosenDatasetProtocols = useSelector(selectChosenDatasetProtocols);
+
+ let showChart = true;
+ if (
+ !chosenDatasets ||
+ !chosenPkModels ||
+ !chosenPdModels
+ ) {
+ showChart = false;
+ }
+ if (
+ chosenDatasets.length === 0 &&
+ chosenPkModels.length === 0 &&
+ chosenPdModels.length === 0
+ ) {
+ showChart = false;
+ }
+
+ if (!showChart) {
+ return (
+ Choose a dataset or model to visualise
+ )
+ }
+
+ console.log('Chosendatasets', chosenDatasets)
+ console.log('chosenPkModels', chosenPkModels)
+ console.log('chosenPdModels', chosenPdModels)
+
+ return (
+
+ );
+}
+
+function SelectedItem({ project }) {
+ const id = useSelector((state) => state.modelling.selectedId);
+ const type = useSelector((state) => state.modelling.selectedType);
+ let selector = null;
+ if (type == 'dataset') {
+ selector = selectDatasetById
+ }
+ if (type == 'pk_model') {
+ selector = selectPkModelById
+ }
+ if (type == 'pd_model') {
+ selector = selectPdModelById
+ }
+ if (type == 'protocol') {
+ selector = selectProtocolById
+ }
+ const item = useSelector((state) => selector ? selector(state, id) : null)
+
+ if (type && !item) {
+ return (
+
+ )
+ }
+ let itemDetail = null
+ if (type === 'dataset') {
+ itemDetail = (
+
+ )
+ } else if (type === 'pk_model') {
+ itemDetail = (
+
+ )
+ } else if (type === 'pd_model') {
+ itemDetail = (
+
+ )
+ } else if (type === 'protocol') {
+ itemDetail = (
+
+ )
+ } else {
+ itemDetail = (
+
+ )
+ }
+ return itemDetail;
+}
+
+function SelectedItemSecondary({ project }) {
+ const id = useSelector((state) => state.modelling.selectedId);
+ const type = useSelector((state) => state.modelling.selectedType);
+ let selector = null;
+
+ if (type === 'pk_model') {
+ selector = selectPkModelById
+ }
+ if (type === 'pd_model') {
+ selector = selectPdModelById
+ }
+ const item = useSelector((state) => selector ? selector(state, id) : null)
+
+ if (type !== 'pk_model' && type !== 'pd_model' ) {
+ return (null)
+ }
+
+ if (type && !item) {
+ return (
+
+ )
+ }
+ let itemDetail = null
+ if (type === 'pk_model') {
+ itemDetail = (
+
+ )
+ } else if (type === 'pd_model') {
+ itemDetail = (
+
+ )
+ } else {
+ itemDetail = (null)
+ }
+ return itemDetail;
+}
+
+export default function Modelling({project}) {
+ const classes = useStyles();
+ return (
+
+ );
+}
diff --git a/frontend/src/features/modelling/SelectedItem.js b/frontend/src/features/modelling/SelectedItem.js
new file mode 100644
index 00000000..e69de29b
diff --git a/frontend/src/features/modelling/ShapesAndColors.js b/frontend/src/features/modelling/ShapesAndColors.js
new file mode 100644
index 00000000..cc4961b9
--- /dev/null
+++ b/frontend/src/features/modelling/ShapesAndColors.js
@@ -0,0 +1,56 @@
+import ColorScheme from "color-scheme";
+
+var scheme = new ColorScheme();
+scheme.from_hue(21).scheme("tetrade").variation("hard");
+
+const colors = scheme.colors().map(hexToRGB);
+const colorsBackground = scheme.colors().map((c) => hexToRGB(c, 0.2));
+
+const shapes = [
+ "cross",
+ "triangle",
+ "star",
+ "crossRot",
+ "dash",
+ "line",
+ "rect",
+ "rectRounded",
+ "rectRot",
+ "circle",
+];
+
+export function getShape(i) {
+ const index = i % shapes.length;
+ return shapes[index];
+}
+
+export function getColor(i) {
+ const index = i % colors.length;
+ return colors[index];
+}
+
+export function getColorBackground(i) {
+ const index = i % colors.length;
+ return colorsBackground[index];
+}
+
+export function numShapes() {
+ return shapes.length;
+}
+
+export function numColors() {
+ return shapes.colors;
+}
+
+// https://stackoverflow.com/questions/21646738/convert-hex-to-rgba
+function hexToRGB(hex, alpha) {
+ var r = parseInt(hex.slice(1, 3), 16),
+ g = parseInt(hex.slice(3, 5), 16),
+ b = parseInt(hex.slice(5, 7), 16);
+
+ if (alpha) {
+ return "rgba(" + r + ", " + g + ", " + b + ", " + alpha + ")";
+ } else {
+ return "rgb(" + r + ", " + g + ", " + b + ")";
+ }
+}
diff --git a/frontend/src/features/modelling/modellingSlice.js b/frontend/src/features/modelling/modellingSlice.js
new file mode 100644
index 00000000..a9417693
--- /dev/null
+++ b/frontend/src/features/modelling/modellingSlice.js
@@ -0,0 +1,105 @@
+import {
+ createSlice,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { setSelectDataset, setSelectDatasetProtocol } from '../datasets/datasetsSlice'
+import { setSelectPkModel } from '../pkModels/pkModelsSlice'
+import { setSelectPdModel } from '../pdModels/pdModelsSlice'
+import { setSelectProtocol } from '../protocols/protocolsSlice'
+
+
+export const selectItem = createAsyncThunk(
+ "modelling/selectItem",
+ async ({id, type}, { dispatch, getState }) => {
+ console.log('selectItem', id, type)
+ const { modelling } = getState();
+ // turn off old select
+ if (modelling.selectedType == 'dataset') {
+ dispatch(setSelectDataset({id: modelling.selectedId, select: false}))
+ }
+ if (modelling.selectedType == 'pk_model') {
+ dispatch(setSelectPkModel({id: modelling.selectedId, select: false}))
+ }
+ if (modelling.selectedType == 'pd_model') {
+ dispatch(setSelectPdModel({id: modelling.selectedId, select: false}))
+ }
+ if (modelling.selectedType == 'protocol') {
+ dispatch(setSelectProtocol({id: modelling.selectedId, select: false}))
+ }
+ // turn on new select
+ if (type == 'dataset') {
+ dispatch(setSelectDataset({id: id, select: true}))
+ }
+ if (type == 'pk_model') {
+ dispatch(setSelectPkModel({id: id, select: true}))
+ }
+ if (type == 'pd_model') {
+ dispatch(setSelectPdModel({id: id, select: true}))
+ }
+ if (type == 'protocol') {
+ dispatch(setSelectProtocol({id: id, select: true}))
+ }
+
+ return {id: id, type: type}
+ }
+);
+
+export const clearSelectItem = createAsyncThunk(
+ "modelling/clearSelectItem",
+ async (arg, { dispatch, getState }) => {
+ console.log('clearSelectItem')
+ const { modelling } = getState();
+ // turn off old select
+ if (modelling.selectedType == 'dataset') {
+ dispatch(setSelectDataset({id: modelling.selectedId, select: false}))
+ }
+ if (modelling.selectedType == 'pk_model') {
+ dispatch(setSelectPkModel({id: modelling.selectedId, select: false}))
+ }
+ if (modelling.selectedType == 'pd_model') {
+ dispatch(setSelectPdModel({id: modelling.selectedId, select: false}))
+ }
+ if (modelling.selectedType == 'protocol') {
+ dispatch(setSelectProtocol({id: modelling.selectedId, select: false}))
+ }
+ return {id: null, type: null}
+ }
+);
+
+export const modellingSlice = createSlice({
+ name: 'modelling',
+ initialState: {
+ selectedType: null,
+ selectedId: null,
+ },
+ reducers: {
+ setSelected(state, action) {
+ state.selectedType = action.payload.type
+ state.selectedId = action.payload.id
+ },
+ },
+ extraReducers: {
+ [selectItem.fulfilled]: (state, action) => {
+ state.selectedType = action.payload.type
+ state.selectedId = action.payload.id
+ },
+ [clearSelectItem.fulfilled]: (state, action) => {
+ state.selectedType = null
+ state.selectedId = null
+ },
+ },
+})
+
+// Action creators are generated for each case reducer function
+export const { setSelected } = modellingSlice.actions
+
+export function selectSelected(state, type) {
+ // turn off old selection
+ if (type == state.modelling.selectedType) {
+ return state.modelling.selectedId;
+ } else {
+ return null
+ }
+}
+
+export default modellingSlice.reducer
diff --git a/frontend/src/features/pdModels/PdDetail.js b/frontend/src/features/pdModels/PdDetail.js
new file mode 100644
index 00000000..efb665e0
--- /dev/null
+++ b/frontend/src/features/pdModels/PdDetail.js
@@ -0,0 +1,165 @@
+import React, { useEffect, useState } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import Alert from '@mui/material/Alert';
+import Box from "@mui/material/Box";
+import Grid from "@mui/material/Grid";
+import { useForm } from "react-hook-form";
+import makeStyles from '@mui/styles/makeStyles';
+import Typography from "@mui/material/Typography";
+import Paper from "@mui/material/Paper";
+import Stack from "@mui/material/Stack";
+
+import Header from "../modelling/Header";
+import Footer from "../modelling/Footer";
+import ComponentForm from "../forms/ComponentForm";
+import {
+ updatePdModel,
+ uploadPdSbml,
+ uploadPdMmt,
+ deletePdModel,
+ setPdVariablesByInference,
+} from "../pdModels/pdModelsSlice";
+import { FormTextField } from "../forms/FormComponents";
+import { userHasReadOnlyAccess } from "../projects/projectsSlice";
+import InferenceListDialog from "../inference/InferenceListDialog";
+
+
+export default function PdDetail({ project, pd_model }) {
+ const { control, handleSubmit, reset } = useForm();
+ const dispatch = useDispatch();
+ const [openInferenceDialog, setOpenInferenceDialog] = useState(false);
+
+ const handleCloseInferenceDialog = (inference) => {
+ if (inference) {
+ dispatch(setPdVariablesByInference({id: pd_model.id, inference_id: inference.id}));
+ }
+ setOpenInferenceDialog(false)
+ }
+
+ const handlePdDelete = () => {
+ dispatch(deletePdModel(pd_model.id));
+ };
+
+ const handleSetVariablesFromInference = () => {
+ setOpenInferenceDialog(true);
+ };
+
+ const handleSbmlFileUpload = (event) => {
+ console.log('handleSbmlFileUpload', event)
+ const files = Array.from(event.target.files);
+ const [file] = files;
+ let reader = new FileReader();
+
+ reader.onload = function () {
+ dispatch(uploadPdSbml({ id: pd_model.id, sbml: reader.result }));
+ };
+
+ reader.onerror = function () {
+ console.log(reader.error);
+ };
+
+ reader.readAsText(file);
+ };
+
+ const handleMmtFileUpload = (event) => {
+ console.log('handleMmtFileUpload', event)
+ const files = Array.from(event.target.files);
+ const [file] = files;
+ let reader = new FileReader();
+
+ reader.onload = function () {
+ dispatch(uploadPdMmt({ id: pd_model.id, mmt: reader.result }));
+ };
+
+ reader.onerror = function () {
+ console.log(reader.error);
+ };
+
+ reader.readAsText(file);
+ };
+
+ useEffect(() => {
+ reset(pd_model);
+ }, [reset, pd_model]);
+
+ const onSubmit = (values) => {
+ dispatch(updatePdModel(values));
+ };
+
+ const disableSave = useSelector(state => userHasReadOnlyAccess(state, project));
+
+ return (
+
+
+
+
+ );
+}
diff --git a/frontend/src/features/pdModels/pdModelsSlice.js b/frontend/src/features/pdModels/pdModelsSlice.js
new file mode 100644
index 00000000..0bda2443
--- /dev/null
+++ b/frontend/src/features/pdModels/pdModelsSlice.js
@@ -0,0 +1,250 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+import { fetchVariablesByPdModel } from "../variables/variablesSlice";
+import { setSelected } from "../modelling/modellingSlice";
+import { fetchUnitsByPdModel } from "../projects/unitsSlice";
+
+const pdModelsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = pdModelsAdapter.getInitialState({
+ status: "idle",
+ errorFetch: null,
+});
+
+export const fetchPdModels = createAsyncThunk(
+ "pdModels/fetchPdModels",
+ async (project_id, { dispatch, getState }) => {
+ let response = await api.get(
+ `/api/pharmacodynamic/?project_id=${project_id}`, getState().login.csrf
+ );
+ for (var i = 0; i < response.length; i++) {
+ if (!response[i].read_only) {
+ dispatch(fetchPdModelSimulateById(response[i].id));
+ }
+ }
+ return response;
+ }
+);
+
+export const fetchPdModelById = createAsyncThunk(
+ "pdModels/fetchPdModelById",
+ async (model_id, { dispatch, getState }) => {
+ let response = await api.get(`/api/pharmacodynamic/${model_id}/`, getState().login.csrf);
+ dispatch(fetchVariablesByPdModel(response.id));
+ dispatch(fetchUnitsByPdModel(response.id));
+ dispatch(fetchPdModelSimulateById(response.id));
+ return response;
+ }
+);
+
+export const fetchPdModelSimulateById = createAsyncThunk(
+ "pdModels/fetchPdModelSimulateById",
+ async (model_id, {getState}) => {
+ const response = await api.post(
+ `/api/pharmacodynamic/${model_id}/simulate`, getState().login.csrf, {}
+ );
+ return response;
+ }
+);
+
+export const addNewPdModel = createAsyncThunk(
+ "pdModels/addNewPdModel",
+ async (project, { dispatch, getState }) => {
+ const initialPdModel = {
+ name: "new",
+ project: project.id,
+ };
+ let pdModel = await api.post("/api/pharmacodynamic/", getState().login.csrf, initialPdModel);
+
+ dispatch(fetchVariablesByPdModel(pdModel.id));
+ dispatch(fetchUnitsByPdModel(pdModel.id));
+ dispatch(fetchPdModelSimulateById(pdModel.id));
+
+ return pdModel;
+ }
+);
+
+export const deletePdModel = createAsyncThunk(
+ "pdModels/deletePdModel",
+ async (pdModelId, { dispatch, getState }) => {
+ let { modelling } = getState()
+ if (modelling.selectedType === 'pd_model' && modelling.selectedId === pdModelId) {
+ dispatch(setSelected({id: null, type: null}))
+ }
+ await api.delete(`/api/pharmacodynamic/${pdModelId}`, getState().login.csrf);
+ return pdModelId;
+ }
+);
+
+export const uploadPdSbml = createAsyncThunk(
+ "pdModels/uploadPdSbml",
+ async ({ id, sbml }, { rejectWithValue, dispatch, getState }) => {
+ try {
+ await api.putMultiPart(`/api/pharmacodynamic/${id}/sbml/`, getState().login.csrf, { sbml });
+ } catch (error) {
+ return rejectWithValue(error);
+ }
+ let pdModel = await api.get(`/api/pharmacodynamic/${id}`, getState().login.csrf);
+ dispatch(fetchVariablesByPdModel(pdModel.id));
+ dispatch(fetchUnitsByPdModel(pdModel.id));
+ dispatch(fetchPdModelSimulateById(pdModel.id));
+ return pdModel;
+ }
+);
+
+export const uploadPdMmt = createAsyncThunk(
+ "pdModels/uploadPdMmt",
+ async ({ id, mmt }, { rejectWithValue, dispatch, getState }) => {
+ try {
+ await api.putMultiPart(`/api/pharmacodynamic/${id}/mmt/`, getState().login.csrf, { mmt });
+ } catch (error) {
+ return rejectWithValue(error);
+ }
+ let pdModel = await api.get(`/api/pharmacodynamic/${id}`, getState().login.csrf);
+ console.log('pdModel', pdModel)
+ dispatch(fetchVariablesByPdModel(pdModel.id));
+ dispatch(fetchUnitsByPdModel(pdModel.id));
+ dispatch(fetchPdModelSimulateById(pdModel.id));
+ return pdModel;
+ }
+);
+
+export const setPdVariablesByInference = createAsyncThunk(
+ "pdModels/setVariablesByInference",
+ async ({ id, inference_id }, { rejectWithValue, dispatch, getState }) => {
+ const pdModel = await api.put(`/api/pharmacodynamic/${id}/set_variables_from_inference/`, getState().login.csrf, { inference_id});
+ dispatch(fetchVariablesByPdModel(pdModel.id));
+ dispatch(fetchPdModelSimulateById(pdModel.id));
+ return pdModel;
+ }
+);
+
+export const updatePdModel = createAsyncThunk(
+ "pdModels/updatePdModel",
+ async (pdModel, { dispatch, getState }) => {
+ let newPdModel = await api.put(
+ `/api/pharmacodynamic/${pdModel.id}/`, getState().login.csrf,
+ pdModel
+ );
+ dispatch(fetchPdModelSimulateById(newPdModel.id));
+ return newPdModel;
+ }
+);
+
+export const pdModelsSlice = createSlice({
+ name: "pdModels",
+ initialState,
+ reducers: {
+ togglePdModel(state, action) {
+ let pdModel = state.entities[action.payload.id];
+ pdModel.chosen = !pdModel.chosen;
+ },
+ setSelectPdModel(state, action) {
+ let pdModel = state.entities[action.payload.id];
+ pdModel.selected = action.payload.select;
+ },
+ setPdModelError(state, action) {
+ let pdModel = state.entities[action.payload.id];
+ pdModel.error = action.payload.error;
+ },
+ addPdModels: pdModelsAdapter.upsertMany,
+ },
+ extraReducers: {
+ [fetchPdModels.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchPdModels.rejected]: (state, action) => {
+ state.status = "failed";
+ state.errorFetch = action.error.message;
+ },
+ [fetchPdModels.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ pdModelsAdapter.setAll(state, action.payload);
+ },
+
+
+ [fetchPdModelById.fulfilled]: pdModelsAdapter.upsertOne,
+ [fetchPdModelSimulateById.fulfilled]: pdModelsAdapter.upsertOne,
+ [fetchPdModelSimulateById.pending]: (state, action) => {
+ if (state.ids.includes(action.meta.arg)) {
+ state.entities[action.meta.arg]["simulate"] = {
+ status: "loading",
+ };
+ }
+ },
+ [fetchPdModelSimulateById.fulfilled]: (state, action) => {
+ if (state.ids.includes(action.meta.arg)) {
+ state.entities[action.meta.arg].simulate = {
+ ...action.payload,
+ status: "succeeded",
+ };
+ }
+ },
+ [fetchPdModelSimulateById.rejected]: (state, action) => {
+ if (state.ids.includes(action.meta.arg)) {
+ state.entities[action.meta.arg].simulate = {
+ status: "failed",
+ };
+ }
+ },
+ [addNewPdModel.fulfilled]: pdModelsAdapter.addOne,
+ [updatePdModel.fulfilled]: pdModelsAdapter.upsertOne,
+ [setPdVariablesByInference.fulfilled]: pdModelsAdapter.upsertOne,
+ [deletePdModel.fulfilled]: pdModelsAdapter.removeOne,
+ [uploadPdSbml.pending]: (state, action) => {
+ state.entities[action.meta.arg.id].status = "loading";
+ state.entities[action.meta.arg.id].errors = [];
+ },
+ [uploadPdSbml.rejected]: (state, action) => {
+ state.entities[action.meta.arg.id].status = "failed";
+ state.entities[action.meta.arg.id].errors = action.payload.sbml;
+ },
+ [uploadPdSbml.fulfilled]: (state, action) => {
+ state.entities[action.meta.arg.id].status = "failed";
+ pdModelsAdapter.upsertOne(state, action);
+ },
+ [uploadPdMmt.pending]: (state, action) => {
+ state.entities[action.meta.arg.id].status = "loading";
+ state.entities[action.meta.arg.id].status = "failed";
+ state.entities[action.meta.arg.id].errors = [];
+ },
+ [uploadPdMmt.rejected]: (state, action) => {
+ state.entities[action.meta.arg.id].status = "failed";
+ console.log('rejected', action)
+ state.entities[action.meta.arg.id].errors = action.payload.mmt;
+ },
+ [uploadPdMmt.fulfilled]: (state, action) => {
+ state.entities[action.meta.arg.id].status = "failed";
+ pdModelsAdapter.upsertOne(state, action);
+ },
+ },
+});
+
+export const { togglePdModel, setSelectPdModel, addPdModels } = pdModelsSlice.actions;
+
+export default pdModelsSlice.reducer;
+
+export const {
+ selectAll: selectAllPdModels,
+ selectById: selectPdModelById,
+ selectIds: selectPdModelIds,
+} = pdModelsAdapter.getSelectors((state) => state.pdModels);
+
+export const selectChosenPdModels = (state) =>
+ selectAllPdModels(state).filter((pdModel) => pdModel.chosen);
+
+
+export const selectWritablePdModels = (state) =>
+ selectAllPdModels(state).filter((pdModel) => !pdModel.read_only);
+
+export const selectWritablePdModelIds = (state) =>
+ selectAllPdModels(state).filter((pdModel) => !pdModel.read_only).map(pdModel => pdModel.id);
+
+export const selectReadOnlyPdModels = (state) =>
+ selectAllPdModels(state).filter((pdModel) => pdModel.read_only);
diff --git a/frontend/src/features/pkModels/PkDetail.js b/frontend/src/features/pkModels/PkDetail.js
new file mode 100644
index 00000000..2bfa5669
--- /dev/null
+++ b/frontend/src/features/pkModels/PkDetail.js
@@ -0,0 +1,305 @@
+import React, { useEffect, useState } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import Button from "@mui/material/Button";
+import List from "@mui/material/List";
+import Box from "@mui/material/Box";
+import IconButton from "@mui/material/IconButton";
+import Grid from "@mui/material/Grid";
+import ListItem from "@mui/material/ListItem";
+import Accordion from "@mui/material/Accordion";
+import AccordionSummary from "@mui/material/AccordionSummary";
+import AccordionDetails from "@mui/material/AccordionDetails";
+import Paper from "@mui/material/Paper";
+import ExpandMoreIcon from "@mui/icons-material/ExpandMore";
+import AddIcon from "@mui/icons-material/Add";
+import AppBar from "@mui/material/AppBar";
+import BottomNavigation from "@mui/material/BottomNavigation";
+import BottomNavigationAction from "@mui/material/BottomNavigationAction";
+import Toolbar from "@mui/material/Toolbar";
+import DeleteIcon from "@mui/icons-material/Delete";
+
+import { useForm, useFieldArray } from "react-hook-form";
+import makeStyles from '@mui/styles/makeStyles';
+import Typography from "@mui/material/Typography";
+
+
+import InferenceListDialog from "../inference/InferenceListDialog";
+import ComponentForm from "../forms/ComponentForm";
+import Header from "../modelling/Header";
+import Footer from "../modelling/Footer";
+import { FormTextField, FormSelectField } from "../forms/FormComponents";
+
+import { selectAllBasePkModels } from "../pkModels/basePkModelsSlice.js";
+
+import { selectAllDatasets } from "../datasets/datasetsSlice.js";
+
+import { selectAllProtocols } from "../protocols/protocolsSlice.js";
+
+import { updatePkModel, deletePkModel, setPkVariablesByInference } from "../pkModels/pkModelsSlice.js";
+
+import { selectAllPdModels } from "../pdModels/pdModelsSlice.js";
+
+import { userHasReadOnlyAccess } from "../projects/projectsSlice";
+
+import {
+ selectVariablesByDosedPkModel,
+} from "../variables/variablesSlice.js";
+
+
+export default function PkDetail({ project, pk_model }) {
+ const mappings_no_null = pk_model.mappings.map(m =>
+ Object.keys(m).reduce((sum, key) => {
+ sum[key] = m[key] || ""
+ return sum
+ }, {}))
+
+ const pk_model_no_null = Object.keys(pk_model).reduce((sum, key) => {
+ if (key === 'mappings') {
+ sum[key] = mappings_no_null
+ } else if (key === 'datetime') {
+ sum[key] = pk_model[key]
+ } else if (pk_model[key] === null) {
+ sum[key] = ""
+ } else {
+ sum[key] = pk_model[key]
+ }
+ return sum
+ }, {})
+ console.log('pk_model_no_null', pk_model_no_null)
+ const { control, handleSubmit, reset } = useForm({
+ defaultValues: pk_model_no_null,
+ });
+ const dispatch = useDispatch();
+
+ const {
+ fields: mappings,
+ append: mappingsAppend,
+ remove: mappingsRemove,
+ } = useFieldArray({
+ control,
+ name: `mappings`,
+ });
+
+ const handleNewMapping = () => mappingsAppend(
+ { pkpd_model: pk_model.id, pk_variable: '', pd_variable: '' }
+ )
+
+ const basePkModels = useSelector(selectAllBasePkModels);
+ const protocols = useSelector(selectAllProtocols);
+ const datasets = useSelector(selectAllDatasets);
+ const pdModels = useSelector(selectAllPdModels);
+ const pd_model_options = pdModels.map((pd_model) => ({
+ key: pd_model.name,
+ value: pd_model.id,
+ })).concat([{key: 'None', value: ''}]);
+
+ const variables = useSelector((state) => {
+ return selectVariablesByDosedPkModel(state, pk_model.id);
+ });
+ const variablesOptions = variables?.map(v => ({
+ key: v.qname, value: v.id
+ }))
+
+ useEffect(() => {
+ reset(pk_model_no_null);
+ }, [reset, pk_model]);
+
+ const handlePkDelete = () => {
+ dispatch(deletePkModel(pk_model.id));
+ };
+
+
+ const [openInferenceDialog, setOpenInferenceDialog] = useState(false);
+
+ const handleCloseInferenceDialog = (inference) => {
+ if (inference) {
+ dispatch(setPkVariablesByInference({id: pk_model.id, inference_id: inference.id}));
+ }
+ setOpenInferenceDialog(false)
+ }
+
+ const handleSetVariablesFromInference = () => {
+ setOpenInferenceDialog(true);
+ };
+
+ const onSubmit = (values) => {
+ console.log('submit', values)
+ dispatch(updatePkModel(values));
+ };
+
+ const base_pk_model_options = basePkModels.filter(pk => !pk.read_only).map((pk) => ({
+ key: pk.name,
+ value: pk.id,
+ }));
+
+ let protocol_options = [];
+ protocol_options = protocol_options.concat(
+ protocols.map((protocol) => ({ key: protocol.name, value: protocol.id }))
+ );
+ console.log('pk_model', pk_model)
+ for (let i = 0; i < datasets.length; i++) {
+ const dataset_protocols = datasets[i].protocols.map((protocol) => ({
+ key: protocol.name,
+ value: protocol.id,
+ }));
+ protocol_options = protocol_options.concat(dataset_protocols);
+ }
+
+ const dose_compartment_options = pk_model.components.map(c => (
+ { key: c.name, value: c.name }
+ ));
+
+ const disableSave = useSelector(state => userHasReadOnlyAccess(state, project));
+
+ return (
+
+
+
+
+ );
+}
diff --git a/frontend/src/features/pkModels/basePkModelsSlice.js b/frontend/src/features/pkModels/basePkModelsSlice.js
new file mode 100644
index 00000000..52a5083c
--- /dev/null
+++ b/frontend/src/features/pkModels/basePkModelsSlice.js
@@ -0,0 +1,53 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+
+import { api } from "../../Api";
+
+const basePkModelsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = basePkModelsAdapter.getInitialState({
+ status: "idle",
+ error: null,
+});
+
+export const fetchBasePkModels = createAsyncThunk(
+ "basePkModels/fetchBasePkModels",
+ async () => {
+ const response = await api.get(`/api/pharmacokinetic/`);
+ return response;
+ }
+);
+
+export const basePkModelsSlice = createSlice({
+ name: "basePkModels",
+ initialState,
+ reducers: {},
+ extraReducers: {
+ [fetchBasePkModels.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchBasePkModels.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [fetchBasePkModels.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ basePkModelsAdapter.setAll(state, action.payload);
+ },
+ },
+});
+
+// export const {} = basePkModelsSlice.actions
+
+export default basePkModelsSlice.reducer;
+
+export const {
+ selectAll: selectAllBasePkModels,
+ selectById: selectBasePkModelById,
+ selectIds: selectBasePkModelIds,
+} = basePkModelsAdapter.getSelectors((state) => state.basePkModels);
diff --git a/frontend/src/features/pkModels/pkModelsSlice.js b/frontend/src/features/pkModels/pkModelsSlice.js
new file mode 100644
index 00000000..327cf895
--- /dev/null
+++ b/frontend/src/features/pkModels/pkModelsSlice.js
@@ -0,0 +1,199 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+
+import { api } from "../../Api";
+import { fetchVariablesByPkModel } from "../variables/variablesSlice";
+import { setSelected } from "../modelling/modellingSlice";
+import { fetchUnitsByPkModel } from "../projects/unitsSlice";
+
+export const pkModelsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = pkModelsAdapter.getInitialState({
+ status: "idle",
+ error: null,
+});
+
+export const fetchPkModels = createAsyncThunk(
+ "pkModels/fetchPkModels",
+ async (project_id, { dispatch, getState }) => {
+ const response = await api.get(
+ `/api/dosed_pharmacokinetic/?project_id=${project_id}`, getState().login.csrf
+ );
+ for (var i = 0; i < response.length; i++) {
+ if (!response[i].read_only) {
+ dispatch(fetchPkModelSimulateById(response[i].id));
+ }
+ }
+ return response;
+ }
+);
+
+export const fetchPkModelById = createAsyncThunk(
+ "pkModels/fetchPkModelById",
+ async (model_id, { dispatch, getState }) => {
+ let response = await api.get(`/api/dosed_pharmacokinetic/${model_id}/`, getState().login.csrf);
+ dispatch(fetchVariablesByPkModel(response.id));
+ dispatch(fetchUnitsByPkModel(response.id));
+ dispatch(fetchPkModelSimulateById(response.id));
+ return response;
+ }
+);
+
+export const fetchPkModelSimulateById = createAsyncThunk(
+ "pkModels/fetchPkModelSimulateById",
+ async (model_id, { dispatch, getState }) => {
+ const response = await api.post(
+ `/api/dosed_pharmacokinetic/${model_id}/simulate`, getState().login.csrf
+ );
+ return response;
+ }
+);
+
+export const setPkVariablesByInference = createAsyncThunk(
+ "pkModels/setVariablesByInference",
+ async ({ id, inference_id}, { rejectWithValue, dispatch, getState }) => {
+ const pkModel = await api.put(`/api/dosed_pharmacokinetic/${id}/set_variables_from_inference/`, getState().login.csrf, { inference_id });
+ dispatch(fetchVariablesByPkModel(pkModel.id));
+ dispatch(fetchPkModelSimulateById(pkModel.id));
+ return pkModel;
+ }
+);
+
+export const deletePkModel = createAsyncThunk(
+ "pkModels/deletePkModel",
+ async (pkModelId, { dispatch, getState }) => {
+ let { modelling } = getState()
+ if (modelling.selectedType === 'pk_model' && modelling.selectedId === pkModelId) {
+ await dispatch(setSelected({id: null, type: null}))
+ }
+ await api.delete(`/api/dosed_pharmacokinetic/${pkModelId}`, getState().login.csrf);
+ return pkModelId;
+ }
+);
+
+export const addNewPkModel = createAsyncThunk(
+ "pkModels/addNewPkModel",
+ async (project, { dispatch, getState }) => {
+ const initialPkModel = {
+ name: "new",
+ project: project.id,
+ mappings: [],
+ };
+ let pkModel = await api.post("/api/dosed_pharmacokinetic/", getState().login.csrf, initialPkModel);
+ dispatch(fetchVariablesByPkModel(pkModel.id));
+ dispatch(fetchUnitsByPkModel(pkModel.id));
+ dispatch(fetchPkModelSimulateById(pkModel.id));
+ return pkModel;
+ }
+);
+
+export const updatePkModel = createAsyncThunk(
+ "pkModels/updatePkModel",
+ async (pkModel, { dispatch, getState }) => {
+ let newPkModel = await api.put(
+ `/api/dosed_pharmacokinetic/${pkModel.id}/`, getState().login.csrf,
+ pkModel
+ );
+ // an update could create new variables
+ dispatch(fetchVariablesByPkModel(newPkModel.id));
+ dispatch(fetchUnitsByPkModel(newPkModel.id));
+ dispatch(fetchPkModelSimulateById(newPkModel.id));
+ //const simulateData = {
+ // outputs: pkModel.outputs.filter(x => x.default_value).map(x => x.name),
+ // initial_conditions: pkModel.outputs.reduce((o, x) => ({...o, x.name: x.default_value}), {}),
+ // variables: pkModel.variables.reduce((o, x) => ({...o, x.name: x.default_value}), {}),
+ //}
+ //const result = await api.post(
+ // `/api/dosed_pharmacokinetic/${pkModel.id}/simulate`, simulateData
+ //)
+ //return { ...newPkModel, simulate: result }
+ return newPkModel;
+ }
+);
+
+export const pkModelsSlice = createSlice({
+ name: "pkModels",
+ initialState,
+ reducers: {
+ togglePkModel(state, action) {
+ let pkModel = state.entities[action.payload.id];
+ pkModel.chosen = !pkModel.chosen;
+ },
+ setSelectPkModel(state, action) {
+ let pkModel = state.entities[action.payload.id];
+ pkModel.selected = action.payload.select;
+ },
+ addPkModels: pkModelsAdapter.upsertMany,
+ },
+ extraReducers: {
+
+ [fetchPkModels.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchPkModels.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [fetchPkModels.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ pkModelsAdapter.setAll(state, action.payload);
+ },
+ [deletePkModel.fulfilled]: pkModelsAdapter.removeOne,
+ [fetchPkModelById.fulfilled]: pkModelsAdapter.upsertOne,
+ [fetchPkModelSimulateById.pending]: (state, action) => {
+ if (state.ids.includes(action.meta.arg)) {
+ state.entities[action.meta.arg].simulate = {
+ status: "loading",
+ };
+ }
+ },
+ [fetchPkModelSimulateById.fulfilled]: (state, action) => {
+ if (state.ids.includes(action.meta.arg)) {
+ state.entities[action.meta.arg].simulate = {
+ ...action.payload,
+ status: "succeeded",
+ };
+ }
+ },
+ [fetchPkModelSimulateById.rejected]: (state, action) => {
+ if (state.ids.includes(action.meta.arg)) {
+ state.entities[action.meta.arg].simulate = {
+ status: "failed",
+ };
+ }
+ },
+ [addNewPkModel.rejected]: (state, action) =>
+ console.log(action.error.message),
+ [addNewPkModel.fulfilled]: pkModelsAdapter.addOne,
+ [updatePkModel.fulfilled]: pkModelsAdapter.upsertOne,
+ [setPkVariablesByInference.fulfilled]: pkModelsAdapter.upsertOne,
+ },
+});
+
+export const { togglePkModel, setSelectPkModel, addPkModels } = pkModelsSlice.actions;
+
+export default pkModelsSlice.reducer;
+
+export const {
+ selectAll: selectAllPkModels,
+ selectById: selectPkModelById,
+ selectIds: selectPkModelIds,
+} = pkModelsAdapter.getSelectors((state) => state.pkModels);
+
+export const selectChosenPkModels = (state) =>
+ selectAllPkModels(state).filter((pkModel) => pkModel.chosen);
+
+export const selectWritablePkModels = (state) =>
+ selectAllPkModels(state).filter((pkModel) => !pkModel.read_only);
+
+export const selectWritablePkModelIds = (state) =>
+ selectAllPkModels(state).filter((pkModel) => !pkModel.read_only).map(pkModel => pkModel.id);
+
+export const selectReadOnlyPkModels = (state) =>
+ selectAllPkModels(state).filter((pkModel) => pkModel.read_only);
+
diff --git a/frontend/src/features/projects/ImportMonolixDialog.js b/frontend/src/features/projects/ImportMonolixDialog.js
new file mode 100644
index 00000000..fd132ab8
--- /dev/null
+++ b/frontend/src/features/projects/ImportMonolixDialog.js
@@ -0,0 +1,312 @@
+import React, { useEffect, useState } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import Button from "@mui/material/Button";
+import Card from "@mui/material/Card";
+import CardContent from "@mui/material/CardContent";
+import CardMedia from "@mui/material/CardMedia";
+import CardActions from "@mui/material/CardActions";
+import Divider from "@mui/material/Divider";
+import TextField from "@mui/material/TextField";
+import { useForm, useFieldArray } from "react-hook-form";
+import Dialog from '@mui/material/Dialog';
+import DialogContent from '@mui/material/DialogContent';
+import Box from "@mui/material/Box";
+import Stack from "@mui/material/Stack";
+import makeStyles from '@mui/styles/makeStyles';
+import { selectAllInferences } from "../inference/inferenceSlice";
+import Table from '@mui/material/Table';
+import TableCell from '@mui/material/TableCell';
+import Tooltip from "@mui/material/Tooltip";
+import TableContainer from '@mui/material/TableContainer';
+import TableBody from '@mui/material/TableBody';
+import TableRow from '@mui/material/TableRow';
+import TableHead from '@mui/material/TableHead';
+
+import Typography from "@mui/material/Typography";
+import DialogActions from "@mui/material/DialogActions";
+
+import LinearProgressWithLabel from '../menu/LinearProgressWithLabel'
+import { FormSelectField } from "../forms/FormComponents";
+import { CardActionArea } from "@mui/material";
+import { importMonolix, importMonolixStatus, importMonolixErrors } from "./projectsSlice";
+
+const useStyles = makeStyles((theme) => ({
+ fileCard: {
+ marginTop: theme.spacing(1),
+ marginBottom: theme.spacing(1),
+ paddingTop: theme.spacing(1),
+ paddingBottom: theme.spacing(1),
+ },
+ fileCardContent: {
+ display: "flex",
+ flexDirection: "column",
+ },
+ paper: {
+ padding: theme.spacing(2),
+ textAlign: "left",
+ },
+ controlsRoot: {
+ display: "flex",
+ alignItems: "center",
+ },
+ controls: {
+ margin: theme.spacing(1),
+ minWidth: 120,
+ },
+ dialogPaper: {
+ "& > *": {
+ margin: theme.spacing(1),
+ },
+ },
+ content: {
+ marginTop: theme.spacing(2),
+ maxHeight: 100,
+ overflow: "auto",
+ }
+}));
+
+function FileCard({ index, file, control, api_errors, errors, clearErrors }) {
+ const classes = useStyles();
+ const [content, setContent] = useState(null);
+ const filename = file.file.name;
+ const filetype = file.type;
+
+ useEffect(() => {
+ const reader = new FileReader();
+ reader.onload = function() {
+ setContent(reader.result);
+ };
+ reader.onerror = function() {
+ setContent("Error: could not read file");
+ };
+ reader.readAsText(file.file);
+ }, [file.file])
+
+ const current_type = file.monolix_type;
+ let error = null;
+ if (api_errors && api_errors[current_type]) {
+ error = api_errors[current_type]
+ }
+
+ console.log('errors', errors, 'index', index)
+
+ const handleOnChange = (e) => {
+ console.log('e', e)
+ clearErrors(`files[${index}].monolix_type`);
+ if (e.target.value === 'project_mlxtran') {
+ clearErrors('project_mlxtran');
+ }
+ if (e.target.value === 'model_txt') {
+ clearErrors('model_txt');
+ }
+ if (e.target.value === 'data_csv') {
+ clearErrors('data_csv');
+ }
+ return e;
+ }
+
+ return (
+
+
+
+
+ {file.file.name}
+
+
+ {content &&
+
+
+ {content}
+
+
+ }
+
+ {error &&
+ {error.replace(/\n/g, " ")}
+ }
+
+
+
+
+
+
+
+ );
+}
+
+
+
+export default function ImportMonolixDialog({ project, onClose, open }) {
+ const classes = useStyles();
+ const dispatch = useDispatch();
+ const [fileList, setFileList] = useState(null);
+ const uploadStatus = useSelector(state => importMonolixStatus(state, project));
+ const uploadErrors = useSelector(state => importMonolixErrors(state, project));
+ const { handleSubmit, control, register, reset, setError, formState: { errors }, clearErrors, watch } = useForm();
+ const { fields, append, prepend, remove, swap, move, insert, replace } = useFieldArray({
+ control,
+ name: "files",
+ });
+ console.log('errors', errors);
+
+ const handleFileChange = (e) => {
+ const fileList = e.target.files;
+ const files = fileList ? [...fileList] : [];
+ const files_with_type = files.map(file => {
+ if (file.name.endsWith('.mlxtran')) {
+ return { file, monolix_type: 'project_mlxtran'}
+ } else if (file.name.endsWith('.csv')) {
+ return { file, monolix_type: 'data_csv'}
+ } else if (file.name.endsWith('.txt')) {
+ return { file, monolix_type: 'model_txt' }
+ } else {
+ return { file, monolix_type: ''}
+ }
+ });
+ reset({ files: files_with_type });
+ };
+
+ useEffect(() => {
+ validateFiles(fields);
+ }, [JSON.stringify(fields)]);
+
+ const validateFiles = (files) => {
+ console.log('validateFiles', files)
+ if (!files) {
+ return;
+ }
+ const project_indices = files.map(
+ (file, index) => ({index, type: file.monolix_type})
+ ).filter(({index, type}) => type === 'project_mlxtran')
+ .map(({index, type}) => index);
+ const data_indices = files.map(
+ (file, index) => ({index, type: file.monolix_type})
+ ).filter(({index, type}) => type === 'data_csv')
+ .map(({index, type}) => index);
+ const model_indices = files.map(
+ (file, index) => ({index, type: file.monolix_type})
+ ).filter(({index, type}) => type === 'model_txt')
+ .map(({index, type}) => index);
+
+ let errored = false;
+ if (project_indices.length !== 1) {
+ if (project_indices.length === 0) {
+ setError(`project_mlxtran`, { type: 'custom', message: 'A project file is required' });
+ }
+ for (const index of project_indices) {
+ setError(`files[ ${index}].monolix_type`, { type: 'custom', message: 'Only one project file is allowed' });
+ }
+ errored = true;
+ }
+ if (data_indices.length !== 1) {
+ if (data_indices.length === 0) {
+ setError(`data_csv`, { type: 'custom', message: 'A data file is required' });
+ }
+ for (const index of data_indices) {
+ setError(`files[${index}].monolix_type`, { type: 'custom', message: 'Only one data file is allowed' });
+ }
+ errored = true;
+ }
+ console.log('model_indices', model_indices)
+ if (model_indices.length !== 1) {
+ if (model_indices.length === 0) {
+ setError(`model_txt`, { type: 'custom', message: 'A model file is required' });
+ }
+ console.log('XXmodel_indices', model_indices)
+ for (const index of model_indices) {
+ setError(`files[${index}].monolix_type`, { type: 'custom', message: 'Only one model file is allowed' });
+ }
+ errored = true;
+ }
+ if (!errored) {
+ clearErrors();
+ }
+ return errored;
+ };
+
+ const onSubmit = (files) => {
+ console.log('uploading files', files.files)
+ const errored = validateFiles(files.files);
+ if (errored) {
+ return;
+ }
+ const data = {
+ id: project.id,
+ project_mlxtran: files.files.filter(file => file.monolix_type === 'project_mlxtran')[0].file,
+ model_txt: files.files.filter(file => file.monolix_type === 'model_txt')[0].file,
+ data_csv: files.files.filter(file => file.monolix_type === 'data_csv')[0].file,
+ }
+
+ dispatch(importMonolix(data));
+ };
+
+ const files = fileList ? [...fileList] : [];
+
+ const handleClose = () => {
+ reset({ files: [] });
+ onClose();
+ };
+
+
+ let uploadButtonColor = 'primary'
+ if (uploadStatus === 'loading') {
+ uploadButtonColor = 'secondary'
+ } else if (uploadStatus === 'success') {
+ uploadButtonColor = 'succeeded'
+ } else if (uploadStatus === 'failed') {
+ uploadButtonColor = 'error'
+ }
+
+ return (
+
+ );
+}
diff --git a/frontend/src/features/projects/Project.js b/frontend/src/features/projects/Project.js
new file mode 100644
index 00000000..78d69810
--- /dev/null
+++ b/frontend/src/features/projects/Project.js
@@ -0,0 +1,103 @@
+import React, { useEffect } from "react";
+import {
+ Switch,
+ Route,
+ useParams,
+ Link,
+ matchPath,
+ useRouteMatch,
+ Redirect,
+ useLocation,
+ useHistory,
+} from "react-router-dom";
+
+import { useSelector, useDispatch } from "react-redux";
+import Button from "@mui/material/Button";
+import Paper from "@mui/material/Paper";
+import { useForm } from "react-hook-form";
+import makeStyles from '@mui/styles/makeStyles';
+import List from "@mui/material/List";
+import CircularProgress from "@mui/material/CircularProgress";
+import ListItem from "@mui/material/ListItem";
+
+import Inferences from "../inference/Inferences";
+import Inference from "../inference/Inference";
+import Modelling from "../modelling/Modelling";
+import Header from "../modelling/Header";
+import Footer from "../modelling/Footer";
+
+import {
+ FormTextField,
+ FormMultiSelectField,
+ FormCheckboxField,
+} from "../forms/FormComponents";
+import { selectAllUsers } from "../projects/usersSlice.js";
+
+import {
+ selectProjectById,
+ updateProject,
+ chooseProject,
+ deleteProject,
+ userHasReadOnlyAccess,
+} from "../projects/projectsSlice.js";
+
+import { fetchDatasets } from "../datasets/datasetsSlice.js";
+
+import { fetchUnits} from "../projects/unitsSlice.js";
+
+import { fetchPkModels } from "../pkModels/pkModelsSlice.js";
+
+import { fetchPdModels } from "../pdModels/pdModelsSlice.js";
+
+import { fetchBasePkModels } from "../pkModels/basePkModelsSlice.js";
+
+import { fetchProtocols } from "../protocols/protocolsSlice.js";
+
+import { fetchVariables } from "../variables/variablesSlice.js";
+
+import { fetchInferences } from "../inference/inferenceSlice.js";
+
+import { fetchChains } from "../inference/chainSlice.js";
+import { clearSelectItem } from "../modelling/modellingSlice";
+
+const useStyles = makeStyles((theme) => ({
+}));
+
+
+export default function Project() {
+ let { id } = useParams();
+ let { path, url } = useRouteMatch();
+ const project = useSelector((state) => selectProjectById(state, id));
+ const classes = useStyles();
+ const dispatch = useDispatch();
+
+ useEffect(() => {
+ dispatch(fetchDatasets(id));
+ dispatch(fetchPkModels(id));
+ dispatch(fetchPdModels(id));
+ dispatch(fetchBasePkModels(id));
+ dispatch(fetchVariables(id));
+ dispatch(fetchProtocols(id));
+ dispatch(fetchUnits(id));
+ dispatch(fetchInferences(id));
+ dispatch(clearSelectItem());
+ }, [id]);
+
+ if (!project) {
+ return ( )
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/features/projects/ProjectDetail.js b/frontend/src/features/projects/ProjectDetail.js
new file mode 100644
index 00000000..c482b3ce
--- /dev/null
+++ b/frontend/src/features/projects/ProjectDetail.js
@@ -0,0 +1,134 @@
+import React, { useEffect, useState } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import Stack from "@mui/material/Stack";
+import Paper from "@mui/material/Paper";
+import { useForm } from "react-hook-form";
+import List from "@mui/material/List";
+import ListItem from "@mui/material/ListItem";
+
+import Header from "../modelling/Header";
+import Footer from "../modelling/Footer";
+import ImportMonolixDialog from "./ImportMonolixDialog";
+
+import {
+ FormTextField,
+ FormMultiSelectField,
+ FormCheckboxField,
+} from "../forms/FormComponents";
+import { selectAllUsers } from "../projects/usersSlice.js";
+
+import {
+ updateProject,
+ deleteProject,
+ userHasReadOnlyAccess,
+} from "../projects/projectsSlice.js";
+
+
+export default function ProjectDetail({ project }) {
+ const users = useSelector(selectAllUsers);
+ const userEntities = useSelector((state) => state.users.entities);
+ const dispatch = useDispatch();
+ const { control, handleSubmit, reset } = useForm();
+ const disableSave = useSelector(state => userHasReadOnlyAccess(state, project));
+ const user_options = users.map((user) => ({
+ key: user.username,
+ value: user.id,
+ }));
+
+ useEffect(() => {
+ reset(project);
+ }, [reset, project]);
+
+ const [openMonolixDialog, setOpenMonolixDialog] = useState(false);
+
+ const handleCloseMonolixDialog = (arg) => {
+ setOpenMonolixDialog(false)
+ }
+
+ const handleImportMonolix = () => {
+ setOpenMonolixDialog(true)
+ }
+
+ const handleDeleteProject = () => {
+ console.log('delete project', project)
+ dispatch(deleteProject(project.id));
+ };
+
+ const onSubmit = (values) => {
+ const users_in_project = values.user_access.map((ua) => ua.user);
+ const users_to_be_added = values.users.filter(u => !users_in_project.includes(u));
+ const users_to_be_removed = values.user_access.filter(u => !values.users.includes(u.user)).map(u => u.user);
+ let new_user_access = values.user_access.filter((ua) => !users_to_be_removed.includes(ua.user));
+ new_user_access.push(...users_to_be_added.map(u => ({user: u, read_only: true, project: project.id})));
+ values.user_access = new_user_access;
+ console.log("project detail submit", values);
+ dispatch(updateProject(values));
+ };
+ return (
+
+
+
+
+ )
+}
+
+
diff --git a/frontend/src/features/projects/Projects.js b/frontend/src/features/projects/Projects.js
new file mode 100644
index 00000000..ee67d0f7
--- /dev/null
+++ b/frontend/src/features/projects/Projects.js
@@ -0,0 +1,134 @@
+import React, { useEffect } from "react";
+import { useSelector } from "react-redux";
+import Paper from "@mui/material/Paper";
+import Grid from "@mui/material/Grid";
+import Table from '@mui/material/Table';
+import { useHistory } from "react-router-dom";
+import Typography from '@mui/material/Typography';
+import Container from '@mui/material/Container';
+import TableBody from '@mui/material/TableBody';
+import ProjectDetail from "../projects/ProjectDetail";
+import Tooltip from "@mui/material/Tooltip";
+import { useTheme } from "@mui/material/styles";
+import { useDispatch } from "react-redux";
+import TableCell from '@mui/material/TableCell';
+import SaveIcon from '@mui/icons-material/Save';
+import TableContainer from '@mui/material/TableContainer';
+import TableHead from '@mui/material/TableHead';
+import DeleteIcon from '@mui/icons-material/Delete';
+import TableRow from '@mui/material/TableRow';
+
+import AddIcon from "@mui/icons-material/Add";
+
+import IconButton from "@mui/material/IconButton";
+import makeStyles from '@mui/styles/makeStyles';
+
+
+
+
+
+import {
+ selectMyProjects,
+ selectChosenProject,
+ addNewProject,
+ deleteProject,
+} from "./projectsSlice.js";
+
+const useStyles = makeStyles((theme) => ({
+ container: {
+ },
+ paper: {
+ padding: theme.spacing(2),
+ textAlign: "left",
+ },
+ controlsRoot: {
+ display: "flex",
+ alignItems: "center",
+ },
+ controls: {
+ margin: theme.spacing(1),
+ },
+}));
+
+export default function Projects() {
+ const classes = useStyles();
+ const theme = useTheme();
+ const dispatch = useDispatch();
+ const history = useHistory();
+
+
+
+ const handleNewProject = () => {
+ dispatch(addNewProject());
+ };
+
+ const projects = useSelector(selectMyProjects);
+
+ const handleRowClick = (project) => {
+ history.push(`/${project.id}/`);
+ }
+
+ const handleDelete = (id) => (event) => {
+ event.stopPropagation()
+ dispatch(deleteProject(id));
+ }
+
+ const column_headings = [
+ {label: 'Name', help: 'Project Name'},
+ {label: 'Description', help: 'Description'},
+ {label: 'Actions', help: 'Click icon to perform actions'},
+ ]
+
+ return (
+
+
+ My Projects
+
+
+
+
+
+ {column_headings.map(heading => (
+
+
+
+ {heading.label}
+
+
+
+ ))
+ }
+
+
+
+ {projects.map((project) => (
+
+ handleRowClick(project)}>
+
+ {project.name}
+
+
+ {project.description}
+
+
+
+
+
+
+
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/features/projects/projectsSlice.js b/frontend/src/features/projects/projectsSlice.js
new file mode 100644
index 00000000..c6b84bce
--- /dev/null
+++ b/frontend/src/features/projects/projectsSlice.js
@@ -0,0 +1,158 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+
+import { api } from "../../Api";
+import { selectCurrentUser } from '../login/loginSlice'
+import { fetchPdModelById } from "../pdModels/pdModelsSlice";
+import { fetchPkModelById } from "../pkModels/pkModelsSlice";
+import { fetchDatasetById } from "../datasets/datasetsSlice";
+
+const projectsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = projectsAdapter.getInitialState({
+ status: "idle",
+ selected: null,
+ error: null,
+ monolix_errors: null,
+ monolix_status: null,
+});
+
+export const fetchProjects = createAsyncThunk(
+ "projects/fetchProjects",
+ async (_, { getState }) => {
+ return await api.get(`/api/project/`, getState().login.csrf);
+ }
+);
+
+export const addNewProject = createAsyncThunk(
+ "projects/addNewProject",
+ async (_, { getState }) => {
+ const user = selectCurrentUser(getState())
+ console.log('user is ', user)
+ const initialProject = {
+ name: "new",
+ user_access: [
+ {user: user.id, read_only: false}
+ ],
+ };
+ console.log("addNewProject", initialProject);
+ return await api.post("/api/project/", getState().login.csrf, initialProject);
+ }
+);
+
+export const deleteProject = createAsyncThunk(
+ "projects/deleteProject",
+ async (projectId, { dispatch, getState }) => {
+ await api.delete(`/api/project/${projectId}`, getState().login.csrf);
+ return projectId;
+ }
+);
+
+export const updateProject = createAsyncThunk(
+ "projects/updateProject",
+ async (project, { getState }) => {
+ const csrf = getState().login.csrf;
+ const new_project = await api.put(`/api/project/${project.id}/`, csrf, project);
+ return new_project;
+ }
+);
+
+export const importMonolix = createAsyncThunk(
+ "projects/importMonolix",
+ async ({ id, project_mlxtran, model_txt, data_csv }, { rejectWithValue, dispatch, getState }) => {
+ try {
+ let response = await api.putMultiPart(`/api/project/${id}/monolix/`, getState().login.csrf, { project_mlxtran, model_txt, data_csv });
+ console.log('response is ', response)
+ dispatch(fetchPdModelById(response.pd_model));
+ dispatch(fetchPkModelById(response.pk_model));
+ dispatch(fetchDatasetById(response.data));
+ return response;
+ } catch (error) {
+ return rejectWithValue(error);
+ }
+ }
+);
+
+export const projectsSlice = createSlice({
+ name: "projects",
+ initialState,
+ reducers: {
+ chooseProject(state, action) {
+ console.log("choose project", action);
+ state.selected = action.payload.id;
+ },
+ },
+ extraReducers: {
+ [fetchProjects.pending]: (state, action) => {
+ console.log("pending");
+ state.status = "loading";
+ },
+ [fetchProjects.rejected]: (state, action) => {
+ console.log("rejected", action.error.message);
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [fetchProjects.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ projectsAdapter.setAll(state, action.payload);
+ },
+ [deleteProject.fulfilled]: projectsAdapter.removeOne,
+ [addNewProject.fulfilled]: projectsAdapter.addOne,
+ [updateProject.fulfilled]: projectsAdapter.upsertOne,
+ [importMonolix.pending]: (state, action) => {
+ state.entities[action.meta.arg.id].monolix_status = "loading";
+ state.entities[action.meta.arg.id].monolix_errors = null;
+ },
+ [importMonolix.rejected]: (state, action) => {
+ state.entities[action.meta.arg.id].monolix_status = "failed";
+ state.entities[action.meta.arg.id].monolix_errors = action.payload;
+ },
+ [importMonolix.fulfilled]: (state, action) => {
+ state.entities[action.meta.arg.id].monolix_status = "succeeded";
+ state.entities[action.meta.arg.id].monolix_errors = null;
+ },
+
+ },
+});
+
+export const { chooseProject } = projectsSlice.actions;
+
+export default projectsSlice.reducer;
+
+export const selectChosenProject = (state) => {
+ if (!state.projects.selected) {
+ return null;
+ }
+ return state.projects.entities[state.projects.selected];
+};
+
+export const {
+ selectAll: selectAllProjects,
+ selectById: selectProjectById,
+ selectIds: selectProjectIds,
+} = projectsAdapter.getSelectors((state) => state.projects);
+
+export const selectMyProjects = (state) =>
+ selectAllProjects(state).filter((p) =>
+ p.users.includes(state.login.user.id)
+ );
+
+export const userHasReadOnlyAccess = (state, project) => {
+ const access = project.user_access.find(
+ (x) => x.user === state.login.user.id
+ );
+ return access.read_only;
+};
+
+export const importMonolixStatus = (state, project) => {
+ return state.projects.entities[project.id].monolix_status;
+}
+
+export const importMonolixErrors = (state, project) => {
+ return state.projects.entities[project.id].monolix_errors;
+}
\ No newline at end of file
diff --git a/frontend/src/features/projects/unitsSlice.js b/frontend/src/features/projects/unitsSlice.js
new file mode 100644
index 00000000..4709f320
--- /dev/null
+++ b/frontend/src/features/projects/unitsSlice.js
@@ -0,0 +1,87 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+
+const unitsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = unitsAdapter.getInitialState({
+ status: "idle",
+ error: null,
+});
+
+export const fetchUnits = createAsyncThunk(
+ "units/fetchUnits",
+ async (project, { getState }) => {
+ const response = await api.get(`/api/unit/`, getState().login.csrf);
+ return response;
+ }
+);
+
+export const fetchUnitsByPdModel = createAsyncThunk(
+ "units/fetchUnitsByPdModel",
+ async (pd_model_id, { getState }) => {
+ const response = await api.get(`/api/unit/?pd_model_id=${pd_model_id}`, getState().login.csrf);
+ return response;
+ }
+);
+
+export const fetchUnitsByPkModel = createAsyncThunk(
+ "units/fetchUnitsByPkModel",
+ async (pk_model_id, { getState }) => {
+ const response = await api.get(
+ `/api/unit/?dosed_pk_model_id=${pk_model_id}`, getState().login.csrf
+ );
+ return response;
+ }
+);
+
+export const addNewUnit = createAsyncThunk("units/addNewUnit", async (_, { getState}) => {
+ const initialUnit = {
+ name: "new",
+ };
+ const unit = await api.post("/api/unit/", getState().login.csrf, initialUnit);
+ return unit;
+});
+
+export const updateUnit = createAsyncThunk("units/updateUnit", async (unit, { getState }) => {
+ const response = await api.put(`/api/unit/${unit.id}/`, getState().login.csrf, unit);
+ return response;
+});
+
+export const unitsSlice = createSlice({
+ name: "units",
+ initialState,
+ reducers: {},
+ extraReducers: {
+ [fetchUnits.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchUnits.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [fetchUnits.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ unitsAdapter.setAll(state, action.payload);
+ },
+ [fetchUnitsByPdModel.fulfilled]: unitsAdapter.upsertMany,
+ [fetchUnitsByPkModel.fulfilled]: unitsAdapter.upsertMany,
+ [addNewUnit.fulfilled]: unitsAdapter.addOne,
+ [updateUnit.fulfilled]: unitsAdapter.upsertOne,
+ },
+});
+
+// export const {} = unitsSlice.actions
+
+export default unitsSlice.reducer;
+
+export const {
+ selectAll: selectAllUnits,
+ selectById: selectUnitById,
+ selectIds: selectUnitIds,
+} = unitsAdapter.getSelectors((state) => state.units);
diff --git a/frontend/src/features/projects/usersSlice.js b/frontend/src/features/projects/usersSlice.js
new file mode 100644
index 00000000..b587acc3
--- /dev/null
+++ b/frontend/src/features/projects/usersSlice.js
@@ -0,0 +1,67 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+
+const usersAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = usersAdapter.getInitialState({
+ status: "idle",
+ error: null,
+});
+
+export const fetchUsers = createAsyncThunk("users/fetchUsers", async (_, { getState }) => {
+ const response = await api.get(`/api/user/`, getState().login.csrf);
+ return response;
+});
+
+export const addNewUser = createAsyncThunk("users/addNewUser", async (_, { getState }) => {
+ const initialUser = {
+ name: "new",
+ };
+ const response = await api.post("/api/user/", getState().login.csrf, initialUser);
+ return response;
+});
+
+export const updateUser = createAsyncThunk("users/updateUser", async (user, { getState }) => {
+ const response = await api.put(`/api/user/${user.id}/`, getState().login.csrf, user);
+ return response;
+});
+
+export const usersSlice = createSlice({
+ name: "users",
+ initialState,
+ reducers: {},
+ extraReducers: {
+ [fetchUsers.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchUsers.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [fetchUsers.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ usersAdapter.setAll(state, action.payload);
+ },
+ [addNewUser.fulfilled]: usersAdapter.addOne,
+ [updateUser.fulfilled]: usersAdapter.upsertOne,
+ },
+});
+
+// export const { } = usersSlice.actions
+
+export default usersSlice.reducer;
+
+export const {
+ selectAll: selectAllUsers,
+ selectById: selectUserById,
+ selectIds: selectUserIds,
+} = usersAdapter.getSelectors((state) => state.users);
+
+export const selectChosenUsers = (state) =>
+ selectAllUsers(state).filter((user) => user.chosen);
diff --git a/frontend/src/features/protocols/DatasetProtocols.js b/frontend/src/features/protocols/DatasetProtocols.js
new file mode 100644
index 00000000..02d463d4
--- /dev/null
+++ b/frontend/src/features/protocols/DatasetProtocols.js
@@ -0,0 +1,36 @@
+import React from "react";
+import { useSelector, useDispatch } from "react-redux";
+
+import AccessibilityIcon from "@mui/icons-material/Accessibility";
+
+import ExpandableListItem from "../menu/ExpandableListItem";
+
+import {
+ addNewProtocol,
+} from "../protocols/protocolsSlice.js";
+
+
+import {
+ selectAllProtocols,
+ toggleProtocol,
+} from "../datasets/datasetsSlice.js";
+
+
+export default function DatasetProtocols({ project, disableSave }) {
+ const protocols = useSelector(selectAllProtocols);
+ const dispatch = useDispatch();
+ const handleClickItem = (item) => dispatch(toggleProtocol(item));
+ const handleNewItem = () => dispatch(addNewProtocol(project));
+
+ return (
+
+ );
+}
diff --git a/frontend/src/features/protocols/ProtocolDetail.js b/frontend/src/features/protocols/ProtocolDetail.js
new file mode 100644
index 00000000..c3ad0d2e
--- /dev/null
+++ b/frontend/src/features/protocols/ProtocolDetail.js
@@ -0,0 +1,191 @@
+import React, { useEffect } from "react";
+import { useSelector, useDispatch } from "react-redux";
+import Paper from "@mui/material/Paper";
+import Button from "@mui/material/Button";
+import IconButton from "@mui/material/IconButton";
+import { useForm, useFieldArray } from "react-hook-form";
+import Box from "@mui/material/Box";
+import makeStyles from '@mui/styles/makeStyles';
+import DeleteIcon from "@mui/icons-material/Delete";
+import AddIcon from "@mui/icons-material/Add";
+import Typography from "@mui/material/Typography";
+import Table from "@mui/material/Table";
+import TableBody from "@mui/material/TableBody";
+import TableCell from "@mui/material/TableCell";
+import TableContainer from "@mui/material/TableContainer";
+import TableHead from "@mui/material/TableHead";
+import TableRow from "@mui/material/TableRow";
+import Stack from "@mui/material/Stack"
+import Grid from "@mui/material/Grid";
+
+import Header from "../modelling/Header";
+import Footer from "../modelling/Footer";
+
+import { selectUnitById } from "../projects/unitsSlice";
+import { FormTextField, FormSelectField } from "../forms/FormComponents";
+
+import { userHasReadOnlyAccess } from "../projects/projectsSlice";
+
+import { updateProtocol, deleteProtocol } from "../protocols/protocolsSlice.js";
+
+
+export default function ProtocolDetail({ project, protocol }) {
+ const dispatch = useDispatch();
+ console.log("protocol", protocol);
+ const { control, handleSubmit, reset } = useForm(protocol);
+ const { fields, append, remove } = useFieldArray({
+ control,
+ name: "doses",
+ keyName: "keyId",
+ });
+
+ useEffect(() => {
+ reset(protocol);
+ }, [reset, protocol]);
+
+ const handleProtocolDelete = () => {
+ dispatch(deleteProtocol(protocol.id));
+ };
+
+ const onSubmit = (values) => {
+ dispatch(updateProtocol(values));
+ };
+
+ const amount_unit_id = protocol.amount_unit;
+ let amount_unit = useSelector((state) =>
+ selectUnitById(state, amount_unit_id)
+ );
+ if (!amount_unit) {
+ amount_unit = {
+ symbol: "X",
+ };
+ }
+ const amount_unit_options = amount_unit.compatible_units.map((u) => {
+ return { key: u.symbol, value: u.id };
+ });
+
+ const time_unit_id = protocol.time_unit;
+ let time_unit = useSelector((state) => selectUnitById(state, time_unit_id));
+ if (!time_unit) {
+ time_unit = {
+ symbol: "X",
+ };
+ }
+ const time_unit_options = time_unit.compatible_units.map((u) => {
+ return { key: u.symbol, value: u.id };
+ });
+
+ const dose_type_options = [
+ { key: "IV", value: "D" },
+ { key: "Extravascular", value: "I" },
+ ];
+
+ const dose_columns = [
+ { title: "Start Time", field: "start_time" },
+ { title: "Amount", field: "amount" },
+ { title: "Duration", field: "duration" },
+ ];
+
+ let disableSave = useSelector(state => userHasReadOnlyAccess(state, project));
+ disableSave = protocol.dataset || disableSave;
+
+
+ return (
+
+
+
+ );
+}
diff --git a/frontend/src/features/protocols/protocolsSlice.js b/frontend/src/features/protocols/protocolsSlice.js
new file mode 100644
index 00000000..24b74999
--- /dev/null
+++ b/frontend/src/features/protocols/protocolsSlice.js
@@ -0,0 +1,155 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+import { setSelected } from "../modelling/modellingSlice";
+import { fetchPkModelById } from "../pkModels/pkModelsSlice";
+
+const protocolsAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = protocolsAdapter.getInitialState({
+ status: "idle",
+ error: null,
+});
+
+export const fetchProtocols = createAsyncThunk(
+ "protocols/fetchProtocols",
+ async (project_id, { getState }) => {
+ const response = await api.get(`/api/protocol/?project_id=${project_id}`, getState().login.csrf);
+ return response;
+ }
+);
+
+export const addNewProtocol = createAsyncThunk(
+ "protocols/addNewProtocol",
+ async (project, { dispatch, getState }) => {
+ const initialProtocol = {
+ name: "new",
+ dose_ids: [],
+ project: project.id,
+ };
+ let protocol = await api.post("/api/protocol/", getState().login.csrf, initialProtocol);
+ return protocol;
+ }
+);
+
+export const deleteProtocol = createAsyncThunk(
+ "protocols/deleteProtocol",
+ async (protocolId, { dispatch, getState }) => {
+ let { modelling } = getState()
+ if (modelling.selectedType === 'protocol' && modelling.selectedId === protocolId) {
+ await dispatch(setSelected({id: null, type: null}))
+ }
+ await api.delete(`/api/protocol/${protocolId}`, getState().login.csrf);
+ return protocolId;
+ }
+);
+
+export const updateProtocol = createAsyncThunk(
+ "protocols/updateProtocol",
+ async (protocol, { getState, dispatch }) => {
+ const csrf = getState().login.csrf
+ const dosePromises = protocol.doses.map((dose) => {
+ // add or update doses
+ const data = {
+ protocol: protocol.id,
+ ...dose,
+ };
+ if (dose.id) {
+ return api.put(`/api/dose/${dose.id}/`, csrf, data);
+ } else {
+ return api.post(`/api/dose/`, csrf, data);
+ }
+ });
+ const dose_ids = await Promise.all(dosePromises).then((doses) =>
+ doses.map((x) => x.id)
+ );
+
+ // delete removed doses
+ const toDelete = getState()
+ .protocols.entities[protocol.id].doses.map((x) => x.id)
+ .filter((x) => !dose_ids.includes(x));
+ await Promise.all(
+ toDelete.map((id) => {
+ return api.delete(`api/dose/${id}/`, csrf);
+ })
+ );
+
+ console.log("have dose_ids", dose_ids, toDelete);
+ const updatedProtocol = { ...protocol, dose_ids };
+ const newProtocol = await api.put(
+ `/api/protocol/${protocol.id}/`, csrf,
+ updatedProtocol
+ );
+ console.log("got new protocol", newProtocol);
+ for (const pkModelId of newProtocol.dosed_pk_models) {
+ console.log("fetching", pkModelId);
+ dispatch(fetchPkModelById(pkModelId));
+ }
+ return newProtocol;
+ }
+);
+
+export const protocolsSlice = createSlice({
+ name: "protocols",
+ initialState,
+ reducers: {
+ toggleProtocol(state, action) {
+ let protocol = state.entities[action.payload.id];
+ protocol.chosen = !protocol.chosen;
+ },
+ setSelectProtocol(state, action) {
+ let protocol = state.entities[action.payload.id];
+ protocol.selected = action.payload.select;
+ },
+ },
+ extraReducers: {
+ [fetchProtocols.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchProtocols.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [fetchProtocols.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ protocolsAdapter.setAll(state, action.payload);
+ },
+ [deleteProtocol.fulfilled]: protocolsAdapter.removeOne,
+ [addNewProtocol.fulfilled]: protocolsAdapter.addOne,
+ [addNewProtocol.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [updateProtocol.fulfilled]: protocolsAdapter.upsertOne,
+ [updateProtocol.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ },
+});
+
+export const { toggleProtocol, setSelectProtocol } = protocolsSlice.actions;
+
+export default protocolsSlice.reducer;
+
+export const {
+ selectAll: selectAllProtocols,
+ selectById: selectProtocolById,
+ selectIds: selectProtocolIds,
+} = protocolsAdapter.getSelectors((state) => state.protocols);
+
+export const selectChosenProtocols = (state) =>
+ selectAllProtocols(state).filter((protocol) => protocol.chosen);
+
+export const selectDatasetProtocols = (state, dataset) =>
+ selectAllProtocols(state).filter(
+ (protocol) => protocol.dataset === dataset.id
+ );
+
+export const selectWritableProtocols = (state, dataset) =>
+ selectAllProtocols(state).filter((protocol) => !protocol.read_only);
diff --git a/frontend/src/features/variables/OutputSubform.js b/frontend/src/features/variables/OutputSubform.js
new file mode 100644
index 00000000..24de8338
--- /dev/null
+++ b/frontend/src/features/variables/OutputSubform.js
@@ -0,0 +1,102 @@
+import React, { useEffect } from "react";
+import { useSelector } from "react-redux";
+import {
+ FormCheckboxField,
+ FormTextField,
+ FormSelectField,
+} from "../forms/FormComponents";
+import { useForm, useFormState } from "react-hook-form";
+import SaveIcon from "@mui/icons-material/Save";
+import IconButton from "@mui/material/IconButton";
+import { useDispatch } from "react-redux";
+import { selectUnitById } from "../projects/unitsSlice";
+import { selectVariableById, updateVariable } from "./variablesSlice";
+import Stack from "@mui/material/Stack";
+
+export default function OutputSubform({ variable_id, disableSave }) {
+ const dispatch = useDispatch();
+ let variable = useSelector((state) => selectVariableById(state, variable_id));
+ if (!variable) {
+ variable = {
+ display: 0,
+ default_value: 0,
+ lower_bound: -1,
+ upper_bound: 1,
+ unit: 1,
+ color: 0,
+ axis: false,
+ };
+ }
+ const { control, handleSubmit, reset } = useForm({
+ defaultValues: {
+ id: variable.id,
+ display: variable.display,
+ color: variable.color,
+ unit: variable.unit,
+ axis: variable.axis,
+ },
+ });
+ const variableStringify = JSON.stringify(variable)
+
+ useEffect(() => {
+ reset(variable);
+ }, [variableStringify]);
+
+ const unit_id = variable ? variable.unit : 1;
+ let unit = useSelector((state) => selectUnitById(state, unit_id));
+ if (!unit) {
+ unit = {
+ symbol: "X",
+ compatible_units: [],
+ };
+ }
+ const unitOptions = unit.compatible_units.map((u) => {
+ return { key: u.symbol, value: u.id };
+ });
+ const label = `${variable.name}`;
+
+ const onSubmit = (values) => {
+ dispatch(updateVariable(values));
+ };
+
+ const { isDirty } = useFormState({ control });
+
+ const axisOptions = [
+ { value: false, key: "LHS" },
+ { value: true, key: "RHS" },
+ ];
+
+ return (
+
+
+
+
+
+
+ {isDirty && (
+
+
+
+ )}
+
+ );
+}
diff --git a/frontend/src/features/variables/VariableSubform.js b/frontend/src/features/variables/VariableSubform.js
new file mode 100644
index 00000000..6ec32503
--- /dev/null
+++ b/frontend/src/features/variables/VariableSubform.js
@@ -0,0 +1,136 @@
+import React, { useEffect } from "react";
+import { useSelector } from "react-redux";
+import { FormSliderField, FormTextField, FormCheckboxField } from "../forms/FormComponents";
+import Box from "@mui/material/Box";
+import Grid from "@mui/material/Grid";
+import { useForm, useFormState } from "react-hook-form";
+import SaveIcon from "@mui/icons-material/Save";
+import { useDispatch } from "react-redux";
+import IconButton from "@mui/material/IconButton";
+import { selectUnitById } from "../projects/unitsSlice";
+import { selectVariableById, updateVariable } from "./variablesSlice";
+
+export default function VariableSubform({ variable_id, disableSave }) {
+ const dispatch = useDispatch();
+ let variable = useSelector((state) => selectVariableById(state, variable_id));
+ if (!variable) {
+ variable = {
+ default_value: 0,
+ lower_bound: -1,
+ upper_bound: 1,
+ unit: 0,
+ };
+ }
+ const { control, handleSubmit, getValues, reset } = useForm({
+ defaultValues: {
+ id: variable.id,
+ default_value: variable.default_value,
+ lower_bound: variable.lower_bound,
+ upper_bound: variable.upper_bound,
+ is_log: variable.is_log,
+ },
+ });
+ const variableStringify = JSON.stringify(variable)
+
+ useEffect(() => {
+ console.log('useEffect variable subform', variable)
+ reset(variable);
+ }, [variableStringify]);
+
+ const unit_id = variable ? variable.unit : 1;
+ let unit = useSelector((state) => selectUnitById(state, unit_id));
+ if (!unit) {
+ unit = {
+ symbol: "",
+ };
+ }
+ const label = variable.name === 'size' ?
+ `volume [${unit.symbol}]` :
+ `${variable.name} [${unit.symbol}]`
+ ;
+ let truncatedLabel = label;
+ const maxLength = 15;
+ if (label.length > maxLength) {
+ truncatedLabel = label.slice(0, maxLength - 2) + "...";
+ }
+
+ const onSubmit = (values) => {
+ dispatch(updateVariable(values));
+ };
+
+ const { isDirty } = useFormState({ control });
+ const current_lower_bound = getValues("lower_bound");
+ const current_upper_bound = getValues("upper_bound");
+ const current_is_log = getValues("is_log");
+
+ return (
+
+
+
+
+
+
+
+
+
+ {isDirty && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/features/variables/variablesSlice.js b/frontend/src/features/variables/variablesSlice.js
new file mode 100644
index 00000000..22a75654
--- /dev/null
+++ b/frontend/src/features/variables/variablesSlice.js
@@ -0,0 +1,155 @@
+import {
+ createSlice,
+ createEntityAdapter,
+ createAsyncThunk,
+} from "@reduxjs/toolkit";
+import { api } from "../../Api";
+import { fetchPdModelById } from "../pdModels/pdModelsSlice";
+import { fetchPkModelById } from "../pkModels/pkModelsSlice";
+
+const variablesAdapter = createEntityAdapter({
+ sortComparer: (a, b) => b.id < a.id,
+});
+
+const initialState = variablesAdapter.getInitialState({
+ status: "idle",
+ error: null,
+});
+
+export const fetchVariables = createAsyncThunk(
+ "variables/fetchVariables",
+ async (project_id, { getState }) => {
+ console.log("called fetchVariables");
+ const response = await api.get(`/api/variable/?project_id=${project_id}`, getState().login.csrf);
+ return response;
+ }
+);
+
+export const fetchVariableById = createAsyncThunk(
+ "variables/fetchVariableById",
+ async (variable_id, { getState }) => {
+ const response = await api.get(`/api/variable/${variable_id}/`, getState().login.csrf);
+ return response;
+ }
+);
+
+export const fetchVariablesByPdModel = createAsyncThunk(
+ "variables/fetchVariablesByPdModel",
+ async (pd_model_id, { getState }) => {
+ const response = await api.get(`/api/variable/?pd_model_id=${pd_model_id}`, getState().login.csrf);
+ const responseIds = response.map(v => v.id)
+ const state = getState()
+ const existingVariables = selectVariablesByPdModel(state, pd_model_id)
+ const deletedVariables = existingVariables.filter(v => responseIds.indexOf(v.id) === -1)
+ return {
+ variables: response,
+ deletedVariables
+ };
+ }
+);
+
+
+export const fetchVariablesByPkModel = createAsyncThunk(
+ "variables/fetchVariablesByPkModel",
+ async (pk_model_id, { getState }) => {
+ const response = await api.get(
+ `/api/variable/?dosed_pk_model_id=${pk_model_id}`, getState().login.csrf
+ );
+ const responseIds = response.map(v => v.id)
+ const state = getState()
+ const existingVariables = selectVariablesByDosedPkModel(state, pk_model_id)
+ const deletedVariables = existingVariables.filter(v => responseIds.indexOf(v.id) === -1)
+ return {
+ variables: response,
+ deletedVariables
+ };
+ }
+);
+
+export const addNewVariable = createAsyncThunk(
+ "variables/addNewVariable",
+ async (_, { getState }) => {
+ const initialVariable = {
+ name: "new",
+ };
+ const variable = await api.post("/api/variable/", getState().login.csrf, initialVariable);
+ return variable;
+ }
+);
+
+export const updateVariable = createAsyncThunk(
+ "variables/updateVariable",
+ async (variable, { dispatch, getState }) => {
+ const response = await api.patch(`/api/variable/${variable.id}/`, getState().login.csrf, variable);
+ if (response.pd_model) {
+ dispatch(fetchPdModelById(response.pd_model));
+ }
+ if (response.dosed_pk_model) {
+ dispatch(fetchPkModelById(response.dosed_pk_model));
+ }
+ return response;
+ }
+);
+
+export const variablesSlice = createSlice({
+ name: "variables",
+ initialState,
+ reducers: {
+ addVariables: variablesAdapter.upsertMany,
+ },
+ extraReducers: {
+ [fetchVariables.pending]: (state, action) => {
+ state.status = "loading";
+ },
+ [fetchVariables.rejected]: (state, action) => {
+ state.status = "failed";
+ state.error = action.error.message;
+ },
+ [fetchVariables.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ variablesAdapter.setAll(state, action.payload);
+ },
+ [fetchVariableById.fulfilled]: variablesAdapter.upsertOne,
+ [fetchVariablesByPdModel.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ if (action.payload.deletedVariables.length > 0) {
+ variablesAdapter.removeMany(state, action.payload.deletedVariables.map(v => v.id))
+ }
+ variablesAdapter.upsertMany(state, action.payload.variables);
+ },
+ [fetchVariablesByPkModel.fulfilled]: (state, action) => {
+ state.status = "succeeded";
+ if (action.payload.deletedVariables.length > 0) {
+ variablesAdapter.removeMany(state, action.payload.deletedVariables.map(v => v.id))
+ }
+ variablesAdapter.upsertMany(state, action.payload.variables);
+ },
+ [addNewVariable.fulfilled]: variablesAdapter.addOne,
+ [updateVariable.fulfilled]: variablesAdapter.upsertOne,
+ },
+});
+
+export const { addVariables } = variablesSlice.actions;
+
+export default variablesSlice.reducer;
+
+export const {
+ selectAll: selectAllVariables,
+ selectById: selectVariableById,
+ selectIds: selectVariableIds,
+} = variablesAdapter.getSelectors((state) => state.variables);
+
+export const selectVariablesByPdModel = (state, model_id, model_type) =>
+ selectAllVariables(state).filter(
+ (variable) => variable.pd_model === model_id
+ );
+
+export const selectVariablesByDosedPkModel = (state, model_id, model_type) =>
+ selectAllVariables(state).filter(
+ (variable) => variable.dosed_pk_model === model_id
+ );
+
+export const selectVariablesByPkpdModel = (state, model_id, model_type) =>
+ selectAllVariables(state).filter(
+ (variable) => variable.pkpd_model === model_id
+ );
diff --git a/frontend/src/index.css b/frontend/src/index.css
new file mode 100644
index 00000000..4a1df4db
--- /dev/null
+++ b/frontend/src/index.css
@@ -0,0 +1,13 @@
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
+ "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
+ sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+code {
+ font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
+ monospace;
+}
diff --git a/frontend/src/index.js b/frontend/src/index.js
new file mode 100644
index 00000000..0c56bba8
--- /dev/null
+++ b/frontend/src/index.js
@@ -0,0 +1,25 @@
+import React from "react";
+import ReactDOM from "react-dom";
+import "./index.css";
+import App from "./App";
+import reportWebVitals from "./reportWebVitals";
+import { BrowserRouter as Router } from "react-router-dom";
+import store from "./app/store";
+import { Provider } from "react-redux";
+
+ReactDOM.render(
+
+
+
+
+
+ ,
+
+ ,
+ document.getElementById("root")
+);
+
+// If you want to start measuring performance in your app, pass a function
+// to log results (for example: reportWebVitals(console.log))
+// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
+reportWebVitals();
diff --git a/frontend/src/logo.svg b/frontend/src/logo.svg
new file mode 100644
index 00000000..465cf440
--- /dev/null
+++ b/frontend/src/logo.svg
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/logo_pkpdapp_with_text.svg b/frontend/src/logo_pkpdapp_with_text.svg
new file mode 100644
index 00000000..1b524776
--- /dev/null
+++ b/frontend/src/logo_pkpdapp_with_text.svg
@@ -0,0 +1 @@
+PKPD APP
\ No newline at end of file
diff --git a/frontend/src/reportWebVitals.js b/frontend/src/reportWebVitals.js
new file mode 100644
index 00000000..9ecd33f9
--- /dev/null
+++ b/frontend/src/reportWebVitals.js
@@ -0,0 +1,13 @@
+const reportWebVitals = (onPerfEntry) => {
+ if (onPerfEntry && onPerfEntry instanceof Function) {
+ import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
+ getCLS(onPerfEntry);
+ getFID(onPerfEntry);
+ getFCP(onPerfEntry);
+ getLCP(onPerfEntry);
+ getTTFB(onPerfEntry);
+ });
+ }
+};
+
+export default reportWebVitals;
diff --git a/frontend/src/setupProxy.js b/frontend/src/setupProxy.js
new file mode 100644
index 00000000..2ba69e4d
--- /dev/null
+++ b/frontend/src/setupProxy.js
@@ -0,0 +1,11 @@
+const { createProxyMiddleware } = require("http-proxy-middleware");
+
+module.exports = function (app) {
+ app.use(
+ ['/api', '/auth', '/api-auth'],
+ createProxyMiddleware({
+ target: "http://127.0.0.1:8000",
+ changeOrigin: true,
+ })
+ );
+};
diff --git a/frontend/src/setupTests.js b/frontend/src/setupTests.js
new file mode 100644
index 00000000..1dd407a6
--- /dev/null
+++ b/frontend/src/setupTests.js
@@ -0,0 +1,5 @@
+// jest-dom adds custom jest matchers for asserting on DOM nodes.
+// allows you to do things like:
+// expect(element).toHaveTextContent(/react/i)
+// learn more: https://github.com/testing-library/jest-dom
+import "@testing-library/jest-dom";
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
new file mode 100644
index 00000000..6e04856c
--- /dev/null
+++ b/frontend/yarn.lock
@@ -0,0 +1,9790 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@ampproject/remapping@^2.1.0":
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d"
+ integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.1.0"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@apideck/better-ajv-errors@^0.3.1":
+ version "0.3.4"
+ resolved "https://registry.yarnpkg.com/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.4.tgz#f89924dd4efd04a51835db7eb549a7177e0ca727"
+ integrity sha512-Ic2d8ZT6HJiSikGVQvSklaFyw1OUv4g8sDOxa0PXSlbmN/3gL5IO1WYY9DOwTDqOFmjWoqG1yaaKnPDqYCE9KA==
+ dependencies:
+ json-schema "^0.4.0"
+ jsonpointer "^5.0.0"
+ leven "^3.1.0"
+
+"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.8.3":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.7.tgz#44416b6bd7624b998f5b1af5d470856c40138789"
+ integrity sha512-iAXqUn8IIeBTNd72xsFlgaXHkMBMt6y4HJp1tIaK465CWLT/fG1aqB7ykr95gHHmlBdGbFeWWfyB4NJJ0nmeIg==
+ dependencies:
+ "@babel/highlight" "^7.16.7"
+
+"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.17.10":
+ version "7.17.10"
+ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.17.10.tgz#711dc726a492dfc8be8220028b1b92482362baab"
+ integrity sha512-GZt/TCsG70Ms19gfZO1tM4CVnXsPgEPBCpJu+Qz3L0LUDsY5nZqFZglIoPC1kIYOtNBZlrnFT+klg12vFGZXrw==
+
+"@babel/core@^7.1.0", "@babel/core@^7.11.1", "@babel/core@^7.12.3", "@babel/core@^7.16.0", "@babel/core@^7.7.2", "@babel/core@^7.8.0":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.2.tgz#87b2fcd7cce9becaa7f5acebdc4f09f3dd19d876"
+ integrity sha512-A8pri1YJiC5UnkdrWcmfZTJTV85b4UXTAfImGmCfYmax4TR9Cw8sDS0MOk++Gp2mE/BefVJ5nwy5yzqNJbP/DQ==
+ dependencies:
+ "@ampproject/remapping" "^2.1.0"
+ "@babel/code-frame" "^7.16.7"
+ "@babel/generator" "^7.18.2"
+ "@babel/helper-compilation-targets" "^7.18.2"
+ "@babel/helper-module-transforms" "^7.18.0"
+ "@babel/helpers" "^7.18.2"
+ "@babel/parser" "^7.18.0"
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.18.2"
+ "@babel/types" "^7.18.2"
+ convert-source-map "^1.7.0"
+ debug "^4.1.0"
+ gensync "^1.0.0-beta.2"
+ json5 "^2.2.1"
+ semver "^6.3.0"
+
+"@babel/eslint-parser@^7.16.3":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.18.2.tgz#e14dee36c010edfb0153cf900c2b0815e82e3245"
+ integrity sha512-oFQYkE8SuH14+uR51JVAmdqwKYXGRjEXx7s+WiagVjqQ+HPE+nnwyF2qlVG8evUsUHmPcA+6YXMEDbIhEyQc5A==
+ dependencies:
+ eslint-scope "^5.1.1"
+ eslint-visitor-keys "^2.1.0"
+ semver "^6.3.0"
+
+"@babel/generator@^7.18.2", "@babel/generator@^7.7.2":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.18.2.tgz#33873d6f89b21efe2da63fe554460f3df1c5880d"
+ integrity sha512-W1lG5vUwFvfMd8HVXqdfbuG7RuaSrTCCD8cl8fP8wOivdbtbIg2Db3IWUcgvfxKbbn6ZBGYRW/Zk1MIwK49mgw==
+ dependencies:
+ "@babel/types" "^7.18.2"
+ "@jridgewell/gen-mapping" "^0.3.0"
+ jsesc "^2.5.1"
+
+"@babel/helper-annotate-as-pure@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.7.tgz#bb2339a7534a9c128e3102024c60760a3a7f3862"
+ integrity sha512-s6t2w/IPQVTAET1HitoowRGXooX8mCgtuP5195wD/QJPV6wYjpujCGF7JuMODVX2ZAJOf1GT6DT9MHEZvLOFSw==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
+"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.7.tgz#38d138561ea207f0f69eb1626a418e4f7e6a580b"
+ integrity sha512-C6FdbRaxYjwVu/geKW4ZeQ0Q31AftgRcdSnZ5/jsH6BzCJbtvXvhpfkbkThYSuutZA7nCXpPR6AD9zd1dprMkA==
+ dependencies:
+ "@babel/helper-explode-assignable-expression" "^7.16.7"
+ "@babel/types" "^7.16.7"
+
+"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.7", "@babel/helper-compilation-targets@^7.17.10", "@babel/helper-compilation-targets@^7.18.2":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.2.tgz#67a85a10cbd5fc7f1457fec2e7f45441dc6c754b"
+ integrity sha512-s1jnPotJS9uQnzFtiZVBUxe67CuBa679oWFHpxYYnTpRL/1ffhyX44R9uYiXoa/pLXcY9H2moJta0iaanlk/rQ==
+ dependencies:
+ "@babel/compat-data" "^7.17.10"
+ "@babel/helper-validator-option" "^7.16.7"
+ browserslist "^4.20.2"
+ semver "^6.3.0"
+
+"@babel/helper-create-class-features-plugin@^7.17.12", "@babel/helper-create-class-features-plugin@^7.18.0":
+ version "7.18.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.0.tgz#fac430912606331cb075ea8d82f9a4c145a4da19"
+ integrity sha512-Kh8zTGR9de3J63e5nS0rQUdRs/kbtwoeQQ0sriS0lItjC96u8XXZN6lKpuyWd2coKSU13py/y+LTmThLuVX0Pg==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.16.7"
+ "@babel/helper-environment-visitor" "^7.16.7"
+ "@babel/helper-function-name" "^7.17.9"
+ "@babel/helper-member-expression-to-functions" "^7.17.7"
+ "@babel/helper-optimise-call-expression" "^7.16.7"
+ "@babel/helper-replace-supers" "^7.16.7"
+ "@babel/helper-split-export-declaration" "^7.16.7"
+
+"@babel/helper-create-regexp-features-plugin@^7.16.7", "@babel/helper-create-regexp-features-plugin@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.17.12.tgz#bb37ca467f9694bbe55b884ae7a5cc1e0084e4fd"
+ integrity sha512-b2aZrV4zvutr9AIa6/gA3wsZKRwTKYoDxYiFKcESS3Ug2GTXzwBEvMuuFLhCQpEnRXs1zng4ISAXSUxxKBIcxw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.16.7"
+ regexpu-core "^5.0.1"
+
+"@babel/helper-define-polyfill-provider@^0.3.1":
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.1.tgz#52411b445bdb2e676869e5a74960d2d3826d2665"
+ integrity sha512-J9hGMpJQmtWmj46B3kBHmL38UhJGhYX7eqkcq+2gsstyYt341HmPeWspihX43yVRA0mS+8GGk2Gckc7bY/HCmA==
+ dependencies:
+ "@babel/helper-compilation-targets" "^7.13.0"
+ "@babel/helper-module-imports" "^7.12.13"
+ "@babel/helper-plugin-utils" "^7.13.0"
+ "@babel/traverse" "^7.13.0"
+ debug "^4.1.1"
+ lodash.debounce "^4.0.8"
+ resolve "^1.14.2"
+ semver "^6.1.2"
+
+"@babel/helper-environment-visitor@^7.16.7", "@babel/helper-environment-visitor@^7.18.2":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.2.tgz#8a6d2dedb53f6bf248e31b4baf38739ee4a637bd"
+ integrity sha512-14GQKWkX9oJzPiQQ7/J36FTXcD4kSp8egKjO9nINlSKiHITRA9q/R74qu8S9xlc/b/yjsJItQUeeh3xnGN0voQ==
+
+"@babel/helper-explode-assignable-expression@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.7.tgz#12a6d8522fdd834f194e868af6354e8650242b7a"
+ integrity sha512-KyUenhWMC8VrxzkGP0Jizjo4/Zx+1nNZhgocs+gLzyZyB8SHidhoq9KK/8Ato4anhwsivfkBLftky7gvzbZMtQ==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
+"@babel/helper-function-name@^7.16.7", "@babel/helper-function-name@^7.17.9":
+ version "7.17.9"
+ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.17.9.tgz#136fcd54bc1da82fcb47565cf16fd8e444b1ff12"
+ integrity sha512-7cRisGlVtiVqZ0MW0/yFB4atgpGLWEHUVYnb448hZK4x+vih0YO5UoS11XIYtZYqHd0dIPMdUSv8q5K4LdMnIg==
+ dependencies:
+ "@babel/template" "^7.16.7"
+ "@babel/types" "^7.17.0"
+
+"@babel/helper-hoist-variables@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.7.tgz#86bcb19a77a509c7b77d0e22323ef588fa58c246"
+ integrity sha512-m04d/0Op34H5v7pbZw6pSKP7weA6lsMvfiIAMeIvkY/R4xQtBSMFEigu9QTZ2qB/9l22vsxtM8a+Q8CzD255fg==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
+"@babel/helper-member-expression-to-functions@^7.17.7":
+ version "7.17.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.17.7.tgz#a34013b57d8542a8c4ff8ba3f747c02452a4d8c4"
+ integrity sha512-thxXgnQ8qQ11W2wVUObIqDL4p148VMxkt5T/qpN5k2fboRyzFGFmKsTGViquyM5QHKUy48OZoca8kw4ajaDPyw==
+ dependencies:
+ "@babel/types" "^7.17.0"
+
+"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.7.tgz#25612a8091a999704461c8a222d0efec5d091437"
+ integrity sha512-LVtS6TqjJHFc+nYeITRo6VLXve70xmq7wPhWTqDJusJEgGmkAACWwMiTNrvfoQo6hEhFwAIixNkvB0jPXDL8Wg==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
+"@babel/helper-module-transforms@^7.18.0":
+ version "7.18.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.18.0.tgz#baf05dec7a5875fb9235bd34ca18bad4e21221cd"
+ integrity sha512-kclUYSUBIjlvnzN2++K9f2qzYKFgjmnmjwL4zlmU5f8ZtzgWe8s0rUPSTGy2HmK4P8T52MQsS+HTQAgZd3dMEA==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.16.7"
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/helper-simple-access" "^7.17.7"
+ "@babel/helper-split-export-declaration" "^7.16.7"
+ "@babel/helper-validator-identifier" "^7.16.7"
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.18.0"
+ "@babel/types" "^7.18.0"
+
+"@babel/helper-optimise-call-expression@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.7.tgz#a34e3560605abbd31a18546bd2aad3e6d9a174f2"
+ integrity sha512-EtgBhg7rd/JcnpZFXpBy0ze1YRfdm7BnBX4uKMBd3ixa3RGAE002JZB66FJyNH7g0F38U05pXmA5P8cBh7z+1w==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
+"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.17.12", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.17.12.tgz#86c2347da5acbf5583ba0a10aed4c9bf9da9cf96"
+ integrity sha512-JDkf04mqtN3y4iAbO1hv9U2ARpPyPL1zqyWs/2WG1pgSq9llHFjStX5jdxb84himgJm+8Ng+x0oiWF/nw/XQKA==
+
+"@babel/helper-remap-async-to-generator@^7.16.8":
+ version "7.16.8"
+ resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.8.tgz#29ffaade68a367e2ed09c90901986918d25e57e3"
+ integrity sha512-fm0gH7Flb8H51LqJHy3HJ3wnE1+qtYR2A99K06ahwrawLdOFsCEWjZOrYricXJHoPSudNKxrMBUPEIPxiIIvBw==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.16.7"
+ "@babel/helper-wrap-function" "^7.16.8"
+ "@babel/types" "^7.16.8"
+
+"@babel/helper-replace-supers@^7.16.7", "@babel/helper-replace-supers@^7.18.2":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.18.2.tgz#41fdfcc9abaf900e18ba6e5931816d9062a7b2e0"
+ integrity sha512-XzAIyxx+vFnrOxiQrToSUOzUOn0e1J2Li40ntddek1Y69AXUTXoDJ40/D5RdjFu7s7qHiaeoTiempZcbuVXh2Q==
+ dependencies:
+ "@babel/helper-environment-visitor" "^7.18.2"
+ "@babel/helper-member-expression-to-functions" "^7.17.7"
+ "@babel/helper-optimise-call-expression" "^7.16.7"
+ "@babel/traverse" "^7.18.2"
+ "@babel/types" "^7.18.2"
+
+"@babel/helper-simple-access@^7.17.7", "@babel/helper-simple-access@^7.18.2":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.18.2.tgz#4dc473c2169ac3a1c9f4a51cfcd091d1c36fcff9"
+ integrity sha512-7LIrjYzndorDY88MycupkpQLKS1AFfsVRm2k/9PtKScSy5tZq0McZTj+DiMRynboZfIqOKvo03pmhTaUgiD6fQ==
+ dependencies:
+ "@babel/types" "^7.18.2"
+
+"@babel/helper-skip-transparent-expression-wrappers@^7.16.0":
+ version "7.16.0"
+ resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09"
+ integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==
+ dependencies:
+ "@babel/types" "^7.16.0"
+
+"@babel/helper-split-export-declaration@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.7.tgz#0b648c0c42da9d3920d85ad585f2778620b8726b"
+ integrity sha512-xbWoy/PFoxSWazIToT9Sif+jJTlrMcndIsaOKvTA6u7QEo7ilkRZpjew18/W3c7nm8fXdUDXh02VXTbZ0pGDNw==
+ dependencies:
+ "@babel/types" "^7.16.7"
+
+"@babel/helper-validator-identifier@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.16.7.tgz#e8c602438c4a8195751243da9031d1607d247cad"
+ integrity sha512-hsEnFemeiW4D08A5gUAZxLBTXpZ39P+a+DGDsHw1yxqyQ/jzFEnxf5uTEGp+3bzAbNOxU1paTgYS4ECU/IgfDw==
+
+"@babel/helper-validator-option@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.16.7.tgz#b203ce62ce5fe153899b617c08957de860de4d23"
+ integrity sha512-TRtenOuRUVo9oIQGPC5G9DgK4743cdxvtOw0weQNpZXaS16SCBi5MNjZF8vba3ETURjZpTbVn7Vvcf2eAwFozQ==
+
+"@babel/helper-wrap-function@^7.16.8":
+ version "7.16.8"
+ resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.8.tgz#58afda087c4cd235de92f7ceedebca2c41274200"
+ integrity sha512-8RpyRVIAW1RcDDGTA+GpPAwV22wXCfKOoM9bet6TLkGIFTkRQSkH1nMQ5Yet4MpoXe1ZwHPVtNasc2w0uZMqnw==
+ dependencies:
+ "@babel/helper-function-name" "^7.16.7"
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.16.8"
+ "@babel/types" "^7.16.8"
+
+"@babel/helpers@^7.18.2":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.18.2.tgz#970d74f0deadc3f5a938bfa250738eb4ac889384"
+ integrity sha512-j+d+u5xT5utcQSzrh9p+PaJX94h++KN+ng9b9WEJq7pkUPAd61FGqhjuUEdfknb3E/uDBb7ruwEeKkIxNJPIrg==
+ dependencies:
+ "@babel/template" "^7.16.7"
+ "@babel/traverse" "^7.18.2"
+ "@babel/types" "^7.18.2"
+
+"@babel/highlight@^7.16.7":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.17.12.tgz#257de56ee5afbd20451ac0a75686b6b404257351"
+ integrity sha512-7yykMVF3hfZY2jsHZEEgLc+3x4o1O+fYyULu11GynEUQNwB6lua+IIQn1FiJxNucd5UlyJryrwsOh8PL9Sn8Qg==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.16.7"
+ chalk "^2.0.0"
+ js-tokens "^4.0.0"
+
+"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.16.7", "@babel/parser@^7.18.0":
+ version "7.18.4"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.18.4.tgz#6774231779dd700e0af29f6ad8d479582d7ce5ef"
+ integrity sha512-FDge0dFazETFcxGw/EXzOkN8uJp0PC7Qbm+Pe9T+av2zlBpOgunFHkQPPn+eRuClU73JF+98D531UgayY89tow==
+
+"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.17.12.tgz#1dca338caaefca368639c9ffb095afbd4d420b1e"
+ integrity sha512-xCJQXl4EeQ3J9C4yOmpTrtVGmzpm2iSzyxbkZHw7UCnZBftHpF/hpII80uWVyVrc40ytIClHjgWGTG1g/yB+aw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.17.12.tgz#0d498ec8f0374b1e2eb54b9cb2c4c78714c77753"
+ integrity sha512-/vt0hpIw0x4b6BLKUkwlvEoiGZYYLNZ96CzyHYPbtG2jZGz6LBe7/V+drYrc/d+ovrF9NBi0pmtvmNb/FsWtRQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0"
+ "@babel/plugin-proposal-optional-chaining" "^7.17.12"
+
+"@babel/plugin-proposal-async-generator-functions@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.17.12.tgz#094a417e31ce7e692d84bab06c8e2a607cbeef03"
+ integrity sha512-RWVvqD1ooLKP6IqWTA5GyFVX2isGEgC5iFxKzfYOIy/QEFdxYyCybBDtIGjipHpb9bDWHzcqGqFakf+mVmBTdQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-remap-async-to-generator" "^7.16.8"
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+
+"@babel/plugin-proposal-class-properties@^7.16.0", "@babel/plugin-proposal-class-properties@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.17.12.tgz#84f65c0cc247d46f40a6da99aadd6438315d80a4"
+ integrity sha512-U0mI9q8pW5Q9EaTHFPwSVusPMV/DV9Mm8p7csqROFLtIE9rBF5piLqyrBGigftALrBcsBGu4m38JneAe7ZDLXw==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.17.12"
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-proposal-class-static-block@^7.18.0":
+ version "7.18.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.0.tgz#7d02253156e3c3793bdb9f2faac3a1c05f0ba710"
+ integrity sha512-t+8LsRMMDE74c6sV7KShIw13sqbqd58tlqNrsWoWBTIMw7SVQ0cZ905wLNS/FBCy/3PyooRHLFFlfrUNyyz5lA==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.18.0"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/plugin-syntax-class-static-block" "^7.14.5"
+
+"@babel/plugin-proposal-decorators@^7.16.4":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.18.2.tgz#dbe4086d2d42db489399783c3aa9272e9700afd4"
+ integrity sha512-kbDISufFOxeczi0v4NQP3p5kIeW6izn/6klfWBrIIdGZZe4UpHR+QU03FAoWjGGd9SUXAwbw2pup1kaL4OQsJQ==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.18.0"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-replace-supers" "^7.18.2"
+ "@babel/helper-split-export-declaration" "^7.16.7"
+ "@babel/plugin-syntax-decorators" "^7.17.12"
+ charcodes "^0.2.0"
+
+"@babel/plugin-proposal-dynamic-import@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.7.tgz#c19c897eaa46b27634a00fee9fb7d829158704b2"
+ integrity sha512-I8SW9Ho3/8DRSdmDdH3gORdyUuYnk1m4cMxUAdu5oy4n3OfN8flDEH+d60iG7dUfi0KkYwSvoalHzzdRzpWHTg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.3"
+
+"@babel/plugin-proposal-export-namespace-from@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.17.12.tgz#b22864ccd662db9606edb2287ea5fd1709f05378"
+ integrity sha512-j7Ye5EWdwoXOpRmo5QmRyHPsDIe6+u70ZYZrd7uz+ebPYFKfRcLcNu3Ro0vOlJ5zuv8rU7xa+GttNiRzX56snQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
+
+"@babel/plugin-proposal-json-strings@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.17.12.tgz#f4642951792437233216d8c1af370bb0fbff4664"
+ integrity sha512-rKJ+rKBoXwLnIn7n6o6fulViHMrOThz99ybH+hKHcOZbnN14VuMnH9fo2eHE69C8pO4uX1Q7t2HYYIDmv8VYkg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+
+"@babel/plugin-proposal-logical-assignment-operators@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.17.12.tgz#c64a1bcb2b0a6d0ed2ff674fd120f90ee4b88a23"
+ integrity sha512-EqFo2s1Z5yy+JeJu7SFfbIUtToJTVlC61/C7WLKDntSw4Sz6JNAIfL7zQ74VvirxpjB5kz/kIx0gCcb+5OEo2Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+
+"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0", "@babel/plugin-proposal-nullish-coalescing-operator@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.17.12.tgz#1e93079bbc2cbc756f6db6a1925157c4a92b94be"
+ integrity sha512-ws/g3FSGVzv+VH86+QvgtuJL/kR67xaEIF2x0iPqdDfYW6ra6JF3lKVBkWynRLcNtIC1oCTfDRVxmm2mKzy+ag==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+
+"@babel/plugin-proposal-numeric-separator@^7.16.0", "@babel/plugin-proposal-numeric-separator@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.7.tgz#d6b69f4af63fb38b6ca2558442a7fb191236eba9"
+ integrity sha512-vQgPMknOIgiuVqbokToyXbkY/OmmjAzr/0lhSIbG/KmnzXPGwW/AdhdKpi+O4X/VkWiWjnkKOBiqJrTaC98VKw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+
+"@babel/plugin-proposal-object-rest-spread@^7.18.0":
+ version "7.18.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.0.tgz#79f2390c892ba2a68ec112eb0d895cfbd11155e8"
+ integrity sha512-nbTv371eTrFabDfHLElkn9oyf9VG+VKK6WMzhY2o4eHKaG19BToD9947zzGMO6I/Irstx9d8CwX6njPNIAR/yw==
+ dependencies:
+ "@babel/compat-data" "^7.17.10"
+ "@babel/helper-compilation-targets" "^7.17.10"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-transform-parameters" "^7.17.12"
+
+"@babel/plugin-proposal-optional-catch-binding@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.7.tgz#c623a430674ffc4ab732fd0a0ae7722b67cb74cf"
+ integrity sha512-eMOH/L4OvWSZAE1VkHbr1vckLG1WUcHGJSLqqQwl2GaUqG6QjddvrOaTUMNYiv77H5IKPMZ9U9P7EaHwvAShfA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+
+"@babel/plugin-proposal-optional-chaining@^7.16.0", "@babel/plugin-proposal-optional-chaining@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.17.12.tgz#f96949e9bacace3a9066323a5cf90cfb9de67174"
+ integrity sha512-7wigcOs/Z4YWlK7xxjkvaIw84vGhDv/P1dFGQap0nHkc8gFKY/r+hXc8Qzf5k1gY7CvGIcHqAnOagVKJJ1wVOQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+
+"@babel/plugin-proposal-private-methods@^7.16.0", "@babel/plugin-proposal-private-methods@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.17.12.tgz#c2ca3a80beb7539289938da005ad525a038a819c"
+ integrity sha512-SllXoxo19HmxhDWm3luPz+cPhtoTSKLJE9PXshsfrOzBqs60QP0r8OaJItrPhAj0d7mZMnNF0Y1UUggCDgMz1A==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.17.12"
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-proposal-private-property-in-object@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.17.12.tgz#b02efb7f106d544667d91ae97405a9fd8c93952d"
+ integrity sha512-/6BtVi57CJfrtDNKfK5b66ydK2J5pXUKBKSPD2G1whamMuEnZWgoOIfO8Vf9F/DoD4izBLD/Au4NMQfruzzykg==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.16.7"
+ "@babel/helper-create-class-features-plugin" "^7.17.12"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+
+"@babel/plugin-proposal-unicode-property-regex@^7.17.12", "@babel/plugin-proposal-unicode-property-regex@^7.4.4":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.17.12.tgz#3dbd7a67bd7f94c8238b394da112d86aaf32ad4d"
+ integrity sha512-Wb9qLjXf3ZazqXA7IvI7ozqRIXIGPtSo+L5coFmEkhTQK18ao4UDDD0zdTGAarmbLj2urpRwrc6893cu5Bfh0A==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.17.12"
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-syntax-async-generators@^7.8.4":
+ version "7.8.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d"
+ integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-bigint@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea"
+ integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-class-properties@^7.12.13", "@babel/plugin-syntax-class-properties@^7.8.3":
+ version "7.12.13"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10"
+ integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.12.13"
+
+"@babel/plugin-syntax-class-static-block@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406"
+ integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-decorators@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.17.12.tgz#02e8f678602f0af8222235271efea945cfdb018a"
+ integrity sha512-D1Hz0qtGTza8K2xGyEdVNCYLdVHukAcbQr4K3/s6r/esadyEriZovpJimQOpu8ju4/jV8dW/1xdaE0UpDroidw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-syntax-dynamic-import@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
+ integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-export-namespace-from@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a"
+ integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.3"
+
+"@babel/plugin-syntax-flow@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.17.12.tgz#23d852902acd19f42923fca9d0f196984d124e73"
+ integrity sha512-B8QIgBvkIG6G2jgsOHQUist7Sm0EBLDCx8sen072IwqNuzMegZNXrYnSv77cYzA8mLDZAfQYqsLIhimiP1s2HQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-syntax-import-assertions@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.17.12.tgz#58096a92b11b2e4e54b24c6a0cc0e5e607abcedd"
+ integrity sha512-n/loy2zkq9ZEM8tEOwON9wTQSTNDTDEz6NujPtJGLU7qObzT1N4c4YZZf8E6ATB2AjNQg/Ib2AIpO03EZaCehw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-syntax-import-meta@^7.8.3":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51"
+ integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-json-strings@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a"
+ integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-jsx@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.17.12.tgz#834035b45061983a491f60096f61a2e7c5674a47"
+ integrity sha512-spyY3E3AURfxh/RHtjx5j6hs8am5NbUBGfcZ2vB3uShSpZdQyXSf5rR5Mk76vbtlAZOelyVQ71Fg0x9SG4fsog==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699"
+ integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9"
+ integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-numeric-separator@^7.10.4", "@babel/plugin-syntax-numeric-separator@^7.8.3":
+ version "7.10.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97"
+ integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.10.4"
+
+"@babel/plugin-syntax-object-rest-spread@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871"
+ integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-optional-catch-binding@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1"
+ integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-optional-chaining@^7.8.3":
+ version "7.8.3"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a"
+ integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.8.0"
+
+"@babel/plugin-syntax-private-property-in-object@^7.14.5":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz#0dc6671ec0ea22b6e94a1114f857970cd39de1ad"
+ integrity sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-top-level-await@^7.14.5", "@babel/plugin-syntax-top-level-await@^7.8.3":
+ version "7.14.5"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c"
+ integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.14.5"
+
+"@babel/plugin-syntax-typescript@^7.17.12", "@babel/plugin-syntax-typescript@^7.7.2":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.17.12.tgz#b54fc3be6de734a56b87508f99d6428b5b605a7b"
+ integrity sha512-TYY0SXFiO31YXtNg3HtFwNJHjLsAyIIhAhNWkQ5whPPS7HWUFlg9z0Ta4qAQNjQbP1wsSt/oKkmZ/4/WWdMUpw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-arrow-functions@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.17.12.tgz#dddd783b473b1b1537ef46423e3944ff24898c45"
+ integrity sha512-PHln3CNi/49V+mza4xMwrg+WGYevSF1oaiXaC2EQfdp4HWlSjRsrDXWJiQBKpP7749u6vQ9mcry2uuFOv5CXvA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-async-to-generator@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.17.12.tgz#dbe5511e6b01eee1496c944e35cdfe3f58050832"
+ integrity sha512-J8dbrWIOO3orDzir57NRsjg4uxucvhby0L/KZuGsWDj0g7twWK3g7JhJhOrXtuXiw8MeiSdJ3E0OW9H8LYEzLQ==
+ dependencies:
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-remap-async-to-generator" "^7.16.8"
+
+"@babel/plugin-transform-block-scoped-functions@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.7.tgz#4d0d57d9632ef6062cdf354bb717102ee042a620"
+ integrity sha512-JUuzlzmF40Z9cXyytcbZEZKckgrQzChbQJw/5PuEHYeqzCsvebDx0K0jWnIIVcmmDOAVctCgnYs0pMcrYj2zJg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+
+"@babel/plugin-transform-block-scoping@^7.17.12":
+ version "7.18.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.4.tgz#7988627b3e9186a13e4d7735dc9c34a056613fb9"
+ integrity sha512-+Hq10ye+jlvLEogSOtq4mKvtk7qwcUQ1f0Mrueai866C82f844Yom2cttfJdMdqRLTxWpsbfbkIkOIfovyUQXw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-classes@^7.17.12":
+ version "7.18.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.4.tgz#51310b812a090b846c784e47087fa6457baef814"
+ integrity sha512-e42NSG2mlKWgxKUAD9EJJSkZxR67+wZqzNxLSpc51T8tRU5SLFHsPmgYR5yr7sdgX4u+iHA1C5VafJ6AyImV3A==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.16.7"
+ "@babel/helper-environment-visitor" "^7.18.2"
+ "@babel/helper-function-name" "^7.17.9"
+ "@babel/helper-optimise-call-expression" "^7.16.7"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-replace-supers" "^7.18.2"
+ "@babel/helper-split-export-declaration" "^7.16.7"
+ globals "^11.1.0"
+
+"@babel/plugin-transform-computed-properties@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.17.12.tgz#bca616a83679698f3258e892ed422546e531387f"
+ integrity sha512-a7XINeplB5cQUWMg1E/GI1tFz3LfK021IjV1rj1ypE+R7jHm+pIHmHl25VNkZxtx9uuYp7ThGk8fur1HHG7PgQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-destructuring@^7.18.0":
+ version "7.18.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.0.tgz#dc4f92587e291b4daa78aa20cc2d7a63aa11e858"
+ integrity sha512-Mo69klS79z6KEfrLg/1WkmVnB8javh75HX4pi2btjvlIoasuxilEyjtsQW6XPrubNd7AQy0MMaNIaQE4e7+PQw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-dotall-regex@^7.16.7", "@babel/plugin-transform-dotall-regex@^7.4.4":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.7.tgz#6b2d67686fab15fb6a7fd4bd895d5982cfc81241"
+ integrity sha512-Lyttaao2SjZF6Pf4vk1dVKv8YypMpomAbygW+mU5cYP3S5cWTfCJjG8xV6CFdzGFlfWK81IjL9viiTvpb6G7gQ==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.16.7"
+ "@babel/helper-plugin-utils" "^7.16.7"
+
+"@babel/plugin-transform-duplicate-keys@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.17.12.tgz#a09aa709a3310013f8e48e0e23bc7ace0f21477c"
+ integrity sha512-EA5eYFUG6xeerdabina/xIoB95jJ17mAkR8ivx6ZSu9frKShBjpOGZPn511MTDTkiCO+zXnzNczvUM69YSf3Zw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-exponentiation-operator@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.7.tgz#efa9862ef97e9e9e5f653f6ddc7b665e8536fe9b"
+ integrity sha512-8UYLSlyLgRixQvlYH3J2ekXFHDFLQutdy7FfFAMm3CPZ6q9wHCwnUyiXpQCe3gVVnQlHc5nsuiEVziteRNTXEA==
+ dependencies:
+ "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.7"
+ "@babel/helper-plugin-utils" "^7.16.7"
+
+"@babel/plugin-transform-flow-strip-types@^7.16.0":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.17.12.tgz#5e070f99a4152194bd9275de140e83a92966cab3"
+ integrity sha512-g8cSNt+cHCpG/uunPQELdq/TeV3eg1OLJYwxypwHtAWo9+nErH3lQx9CSO2uI9lF74A0mR0t4KoMjs1snSgnTw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/plugin-syntax-flow" "^7.17.12"
+
+"@babel/plugin-transform-for-of@^7.18.1":
+ version "7.18.1"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.1.tgz#ed14b657e162b72afbbb2b4cdad277bf2bb32036"
+ integrity sha512-+TTB5XwvJ5hZbO8xvl2H4XaMDOAK57zF4miuC9qQJgysPNEAZZ9Z69rdF5LJkozGdZrjBIUAIyKUWRMmebI7vg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-function-name@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.7.tgz#5ab34375c64d61d083d7d2f05c38d90b97ec65cf"
+ integrity sha512-SU/C68YVwTRxqWj5kgsbKINakGag0KTgq9f2iZEXdStoAbOzLHEBRYzImmA6yFo8YZhJVflvXmIHUO7GWHmxxA==
+ dependencies:
+ "@babel/helper-compilation-targets" "^7.16.7"
+ "@babel/helper-function-name" "^7.16.7"
+ "@babel/helper-plugin-utils" "^7.16.7"
+
+"@babel/plugin-transform-literals@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.17.12.tgz#97131fbc6bbb261487105b4b3edbf9ebf9c830ae"
+ integrity sha512-8iRkvaTjJciWycPIZ9k9duu663FT7VrBdNqNgxnVXEFwOIp55JWcZd23VBRySYbnS3PwQ3rGiabJBBBGj5APmQ==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-member-expression-literals@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.7.tgz#6e5dcf906ef8a098e630149d14c867dd28f92384"
+ integrity sha512-mBruRMbktKQwbxaJof32LT9KLy2f3gH+27a5XSuXo6h7R3vqltl0PgZ80C8ZMKw98Bf8bqt6BEVi3svOh2PzMw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+
+"@babel/plugin-transform-modules-amd@^7.18.0":
+ version "7.18.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.0.tgz#7ef1002e67e36da3155edc8bf1ac9398064c02ed"
+ integrity sha512-h8FjOlYmdZwl7Xm2Ug4iX2j7Qy63NANI+NQVWQzv6r25fqgg7k2dZl03p95kvqNclglHs4FZ+isv4p1uXMA+QA==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.18.0"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ babel-plugin-dynamic-import-node "^2.3.3"
+
+"@babel/plugin-transform-modules-commonjs@^7.18.2":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.2.tgz#1aa8efa2e2a6e818b6a7f2235fceaf09bdb31e9e"
+ integrity sha512-f5A865gFPAJAEE0K7F/+nm5CmAE3y8AWlMBG9unu5j9+tk50UQVK0QS8RNxSp7MJf0wh97uYyLWt3Zvu71zyOQ==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.18.0"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-simple-access" "^7.18.2"
+ babel-plugin-dynamic-import-node "^2.3.3"
+
+"@babel/plugin-transform-modules-systemjs@^7.18.0":
+ version "7.18.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.4.tgz#3d6fd9868c735cce8f38d6ae3a407fb7e61e6d46"
+ integrity sha512-lH2UaQaHVOAeYrUUuZ8i38o76J/FnO8vu21OE+tD1MyP9lxdZoSfz+pDbWkq46GogUrdrMz3tiz/FYGB+bVThg==
+ dependencies:
+ "@babel/helper-hoist-variables" "^7.16.7"
+ "@babel/helper-module-transforms" "^7.18.0"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-validator-identifier" "^7.16.7"
+ babel-plugin-dynamic-import-node "^2.3.3"
+
+"@babel/plugin-transform-modules-umd@^7.18.0":
+ version "7.18.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.0.tgz#56aac64a2c2a1922341129a4597d1fd5c3ff020f"
+ integrity sha512-d/zZ8I3BWli1tmROLxXLc9A6YXvGK8egMxHp+E/rRwMh1Kip0AP77VwZae3snEJ33iiWwvNv2+UIIhfalqhzZA==
+ dependencies:
+ "@babel/helper-module-transforms" "^7.18.0"
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-named-capturing-groups-regex@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.17.12.tgz#9c4a5a5966e0434d515f2675c227fd8cc8606931"
+ integrity sha512-vWoWFM5CKaTeHrdUJ/3SIOTRV+MBVGybOC9mhJkaprGNt5demMymDW24yC74avb915/mIRe3TgNb/d8idvnCRA==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.17.12"
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-new-target@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.17.12.tgz#10842cd605a620944e81ea6060e9e65c265742e3"
+ integrity sha512-CaOtzk2fDYisbjAD4Sd1MTKGVIpRtx9bWLyj24Y/k6p4s4gQ3CqDGJauFJxt8M/LEx003d0i3klVqnN73qvK3w==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-object-super@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.7.tgz#ac359cf8d32cf4354d27a46867999490b6c32a94"
+ integrity sha512-14J1feiQVWaGvRxj2WjyMuXS2jsBkgB3MdSN5HuC2G5nRspa5RK9COcs82Pwy5BuGcjb+fYaUj94mYcOj7rCvw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+ "@babel/helper-replace-supers" "^7.16.7"
+
+"@babel/plugin-transform-parameters@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.17.12.tgz#eb467cd9586ff5ff115a9880d6fdbd4a846b7766"
+ integrity sha512-6qW4rWo1cyCdq1FkYri7AHpauchbGLXpdwnYsfxFb+KtddHENfsY5JZb35xUwkK5opOLcJ3BNd2l7PhRYGlwIA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-property-literals@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.7.tgz#2dadac85155436f22c696c4827730e0fe1057a55"
+ integrity sha512-z4FGr9NMGdoIl1RqavCqGG+ZuYjfZ/hkCIeuH6Do7tXmSm0ls11nYVSJqFEUOSJbDab5wC6lRE/w6YjVcr6Hqw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+
+"@babel/plugin-transform-react-constant-elements@^7.12.1":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.17.12.tgz#cc580857696b6dd9e5e3d079e673d060a0657f37"
+ integrity sha512-maEkX2xs2STuv2Px8QuqxqjhV2LsFobT1elCgyU5704fcyTu9DyD/bJXxD/mrRiVyhpHweOQ00OJ5FKhHq9oEw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.7.tgz#7b6d40d232f4c0f550ea348593db3b21e2404340"
+ integrity sha512-qgIg8BcZgd0G/Cz916D5+9kqX0c7nPZyXaP8R2tLNN5tkyIZdG5fEwBrxwplzSnjC1jvQmyMNVwUCZPcbGY7Pg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+
+"@babel/plugin-transform-react-jsx-development@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.7.tgz#43a00724a3ed2557ed3f276a01a929e6686ac7b8"
+ integrity sha512-RMvQWvpla+xy6MlBpPlrKZCMRs2AGiHOGHY3xRwl0pEeim348dDyxeH4xBsMPbIMhujeq7ihE702eM2Ew0Wo+A==
+ dependencies:
+ "@babel/plugin-transform-react-jsx" "^7.16.7"
+
+"@babel/plugin-transform-react-jsx@^7.16.7", "@babel/plugin-transform-react-jsx@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.17.12.tgz#2aa20022709cd6a3f40b45d60603d5f269586dba"
+ integrity sha512-Lcaw8bxd1DKht3thfD4A12dqo1X16he1Lm8rIv8sTwjAYNInRS1qHa9aJoqvzpscItXvftKDCfaEQzwoVyXpEQ==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.16.7"
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/plugin-syntax-jsx" "^7.17.12"
+ "@babel/types" "^7.17.12"
+
+"@babel/plugin-transform-react-pure-annotations@^7.16.7":
+ version "7.18.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.0.tgz#ef82c8e310913f3522462c9ac967d395092f1954"
+ integrity sha512-6+0IK6ouvqDn9bmEG7mEyF/pwlJXVj5lwydybpyyH3D0A7Hftk+NCTdYjnLNZksn261xaOV5ksmp20pQEmc2RQ==
+ dependencies:
+ "@babel/helper-annotate-as-pure" "^7.16.7"
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-regenerator@^7.18.0":
+ version "7.18.0"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.0.tgz#44274d655eb3f1af3f3a574ba819d3f48caf99d5"
+ integrity sha512-C8YdRw9uzx25HSIzwA7EM7YP0FhCe5wNvJbZzjVNHHPGVcDJ3Aie+qGYYdS1oVQgn+B3eAIJbWFLrJ4Jipv7nw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ regenerator-transform "^0.15.0"
+
+"@babel/plugin-transform-reserved-words@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.17.12.tgz#7dbd349f3cdffba751e817cf40ca1386732f652f"
+ integrity sha512-1KYqwbJV3Co03NIi14uEHW8P50Md6KqFgt0FfpHdK6oyAHQVTosgPuPSiWud1HX0oYJ1hGRRlk0fP87jFpqXZA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-runtime@^7.16.4":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.18.2.tgz#04637de1e45ae8847ff14b9beead09c33d34374d"
+ integrity sha512-mr1ufuRMfS52ttq+1G1PD8OJNqgcTFjq3hwn8SZ5n1x1pBhi0E36rYMdTK0TsKtApJ4lDEdfXJwtGobQMHSMPg==
+ dependencies:
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ babel-plugin-polyfill-corejs2 "^0.3.0"
+ babel-plugin-polyfill-corejs3 "^0.5.0"
+ babel-plugin-polyfill-regenerator "^0.3.0"
+ semver "^6.3.0"
+
+"@babel/plugin-transform-shorthand-properties@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.7.tgz#e8549ae4afcf8382f711794c0c7b6b934c5fbd2a"
+ integrity sha512-hah2+FEnoRoATdIb05IOXf+4GzXYTq75TVhIn1PewihbpyrNWUt2JbudKQOETWw6QpLe+AIUpJ5MVLYTQbeeUg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+
+"@babel/plugin-transform-spread@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.17.12.tgz#c112cad3064299f03ea32afed1d659223935d1f5"
+ integrity sha512-9pgmuQAtFi3lpNUstvG9nGfk9DkrdmWNp9KeKPFmuZCpEnxRzYlS8JgwPjYj+1AWDOSvoGN0H30p1cBOmT/Svg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0"
+
+"@babel/plugin-transform-sticky-regex@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.7.tgz#c84741d4f4a38072b9a1e2e3fd56d359552e8660"
+ integrity sha512-NJa0Bd/87QV5NZZzTuZG5BPJjLYadeSZ9fO6oOUoL4iQx+9EEuw/eEM92SrsT19Yc2jgB1u1hsjqDtH02c3Drw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+
+"@babel/plugin-transform-template-literals@^7.18.2":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.2.tgz#31ed6915721864847c48b656281d0098ea1add28"
+ integrity sha512-/cmuBVw9sZBGZVOMkpAEaVLwm4JmK2GZ1dFKOGGpMzEHWFmyZZ59lUU0PdRr8YNYeQdNzTDwuxP2X2gzydTc9g==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-typeof-symbol@^7.17.12":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.17.12.tgz#0f12f57ac35e98b35b4ed34829948d42bd0e6889"
+ integrity sha512-Q8y+Jp7ZdtSPXCThB6zjQ74N3lj0f6TDh1Hnf5B+sYlzQ8i5Pjp8gW0My79iekSpT4WnI06blqP6DT0OmaXXmw==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+
+"@babel/plugin-transform-typescript@^7.17.12":
+ version "7.18.4"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.4.tgz#587eaf6a39edb8c06215e550dc939faeadd750bf"
+ integrity sha512-l4vHuSLUajptpHNEOUDEGsnpl9pfRLsN1XUoDQDD/YBuXTM+v37SHGS+c6n4jdcZy96QtuUuSvZYMLSSsjH8Mw==
+ dependencies:
+ "@babel/helper-create-class-features-plugin" "^7.18.0"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/plugin-syntax-typescript" "^7.17.12"
+
+"@babel/plugin-transform-unicode-escapes@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.7.tgz#da8717de7b3287a2c6d659750c964f302b31ece3"
+ integrity sha512-TAV5IGahIz3yZ9/Hfv35TV2xEm+kaBDaZQCn2S/hG9/CZ0DktxJv9eKfPc7yYCvOYR4JGx1h8C+jcSOvgaaI/Q==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.16.7"
+
+"@babel/plugin-transform-unicode-regex@^7.16.7":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.7.tgz#0f7aa4a501198976e25e82702574c34cfebe9ef2"
+ integrity sha512-oC5tYYKw56HO75KZVLQ+R/Nl3Hro9kf8iG0hXoaHP7tjAyCpvqBiSNe6vGrZni1Z6MggmUOC6A7VP7AVmw225Q==
+ dependencies:
+ "@babel/helper-create-regexp-features-plugin" "^7.16.7"
+ "@babel/helper-plugin-utils" "^7.16.7"
+
+"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.12.1", "@babel/preset-env@^7.16.4":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.18.2.tgz#f47d3000a098617926e674c945d95a28cb90977a"
+ integrity sha512-PfpdxotV6afmXMU47S08F9ZKIm2bJIQ0YbAAtDfIENX7G1NUAXigLREh69CWDjtgUy7dYn7bsMzkgdtAlmS68Q==
+ dependencies:
+ "@babel/compat-data" "^7.17.10"
+ "@babel/helper-compilation-targets" "^7.18.2"
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-validator-option" "^7.16.7"
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.17.12"
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.17.12"
+ "@babel/plugin-proposal-async-generator-functions" "^7.17.12"
+ "@babel/plugin-proposal-class-properties" "^7.17.12"
+ "@babel/plugin-proposal-class-static-block" "^7.18.0"
+ "@babel/plugin-proposal-dynamic-import" "^7.16.7"
+ "@babel/plugin-proposal-export-namespace-from" "^7.17.12"
+ "@babel/plugin-proposal-json-strings" "^7.17.12"
+ "@babel/plugin-proposal-logical-assignment-operators" "^7.17.12"
+ "@babel/plugin-proposal-nullish-coalescing-operator" "^7.17.12"
+ "@babel/plugin-proposal-numeric-separator" "^7.16.7"
+ "@babel/plugin-proposal-object-rest-spread" "^7.18.0"
+ "@babel/plugin-proposal-optional-catch-binding" "^7.16.7"
+ "@babel/plugin-proposal-optional-chaining" "^7.17.12"
+ "@babel/plugin-proposal-private-methods" "^7.17.12"
+ "@babel/plugin-proposal-private-property-in-object" "^7.17.12"
+ "@babel/plugin-proposal-unicode-property-regex" "^7.17.12"
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+ "@babel/plugin-syntax-class-properties" "^7.12.13"
+ "@babel/plugin-syntax-class-static-block" "^7.14.5"
+ "@babel/plugin-syntax-dynamic-import" "^7.8.3"
+ "@babel/plugin-syntax-export-namespace-from" "^7.8.3"
+ "@babel/plugin-syntax-import-assertions" "^7.17.12"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+ "@babel/plugin-syntax-numeric-separator" "^7.10.4"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+ "@babel/plugin-syntax-private-property-in-object" "^7.14.5"
+ "@babel/plugin-syntax-top-level-await" "^7.14.5"
+ "@babel/plugin-transform-arrow-functions" "^7.17.12"
+ "@babel/plugin-transform-async-to-generator" "^7.17.12"
+ "@babel/plugin-transform-block-scoped-functions" "^7.16.7"
+ "@babel/plugin-transform-block-scoping" "^7.17.12"
+ "@babel/plugin-transform-classes" "^7.17.12"
+ "@babel/plugin-transform-computed-properties" "^7.17.12"
+ "@babel/plugin-transform-destructuring" "^7.18.0"
+ "@babel/plugin-transform-dotall-regex" "^7.16.7"
+ "@babel/plugin-transform-duplicate-keys" "^7.17.12"
+ "@babel/plugin-transform-exponentiation-operator" "^7.16.7"
+ "@babel/plugin-transform-for-of" "^7.18.1"
+ "@babel/plugin-transform-function-name" "^7.16.7"
+ "@babel/plugin-transform-literals" "^7.17.12"
+ "@babel/plugin-transform-member-expression-literals" "^7.16.7"
+ "@babel/plugin-transform-modules-amd" "^7.18.0"
+ "@babel/plugin-transform-modules-commonjs" "^7.18.2"
+ "@babel/plugin-transform-modules-systemjs" "^7.18.0"
+ "@babel/plugin-transform-modules-umd" "^7.18.0"
+ "@babel/plugin-transform-named-capturing-groups-regex" "^7.17.12"
+ "@babel/plugin-transform-new-target" "^7.17.12"
+ "@babel/plugin-transform-object-super" "^7.16.7"
+ "@babel/plugin-transform-parameters" "^7.17.12"
+ "@babel/plugin-transform-property-literals" "^7.16.7"
+ "@babel/plugin-transform-regenerator" "^7.18.0"
+ "@babel/plugin-transform-reserved-words" "^7.17.12"
+ "@babel/plugin-transform-shorthand-properties" "^7.16.7"
+ "@babel/plugin-transform-spread" "^7.17.12"
+ "@babel/plugin-transform-sticky-regex" "^7.16.7"
+ "@babel/plugin-transform-template-literals" "^7.18.2"
+ "@babel/plugin-transform-typeof-symbol" "^7.17.12"
+ "@babel/plugin-transform-unicode-escapes" "^7.16.7"
+ "@babel/plugin-transform-unicode-regex" "^7.16.7"
+ "@babel/preset-modules" "^0.1.5"
+ "@babel/types" "^7.18.2"
+ babel-plugin-polyfill-corejs2 "^0.3.0"
+ babel-plugin-polyfill-corejs3 "^0.5.0"
+ babel-plugin-polyfill-regenerator "^0.3.0"
+ core-js-compat "^3.22.1"
+ semver "^6.3.0"
+
+"@babel/preset-modules@^0.1.5":
+ version "0.1.5"
+ resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.5.tgz#ef939d6e7f268827e1841638dc6ff95515e115d9"
+ integrity sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@babel/plugin-proposal-unicode-property-regex" "^7.4.4"
+ "@babel/plugin-transform-dotall-regex" "^7.4.4"
+ "@babel/types" "^7.4.4"
+ esutils "^2.0.2"
+
+"@babel/preset-react@^7.12.5", "@babel/preset-react@^7.16.0":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.17.12.tgz#62adbd2d1870c0de3893095757ed5b00b492ab3d"
+ integrity sha512-h5U+rwreXtZaRBEQhW1hOJLMq8XNJBQ/9oymXiCXTuT/0uOwpbT0gUt+sXeOqoXBgNuUKI7TaObVwoEyWkpFgA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-validator-option" "^7.16.7"
+ "@babel/plugin-transform-react-display-name" "^7.16.7"
+ "@babel/plugin-transform-react-jsx" "^7.17.12"
+ "@babel/plugin-transform-react-jsx-development" "^7.16.7"
+ "@babel/plugin-transform-react-pure-annotations" "^7.16.7"
+
+"@babel/preset-typescript@^7.16.0":
+ version "7.17.12"
+ resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.17.12.tgz#40269e0a0084d56fc5731b6c40febe1c9a4a3e8c"
+ integrity sha512-S1ViF8W2QwAKUGJXxP9NAfNaqGDdEBJKpYkxHf5Yy2C4NPPzXGeR3Lhk7G8xJaaLcFTRfNjVbtbVtm8Gb0mqvg==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.17.12"
+ "@babel/helper-validator-option" "^7.16.7"
+ "@babel/plugin-transform-typescript" "^7.17.12"
+
+"@babel/runtime-corejs3@^7.10.2":
+ version "7.18.3"
+ resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.18.3.tgz#52f0241a31e0ec61a6187530af6227c2846bd60c"
+ integrity sha512-l4ddFwrc9rnR+EJsHsh+TJ4A35YqQz/UqcjtlX2ov53hlJYG5CxtQmNZxyajwDVmCxwy++rtvGU5HazCK4W41Q==
+ dependencies:
+ core-js-pure "^3.20.2"
+ regenerator-runtime "^0.13.4"
+
+"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.15.4", "@babel/runtime@^7.16.3", "@babel/runtime@^7.18.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
+ version "7.18.3"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.3.tgz#c7b654b57f6f63cf7f8b418ac9ca04408c4579f4"
+ integrity sha512-38Y8f7YUhce/K7RMwTp7m0uCumpv9hZkitCbBClqQIow1qSbCvGkcegKOXpEWCQLfWmevgRiWokZ1GkpfhbZug==
+ dependencies:
+ regenerator-runtime "^0.13.4"
+
+"@babel/runtime@^7.18.3", "@babel/runtime@^7.20.13", "@babel/runtime@^7.21.0":
+ version "7.21.0"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
+ integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
+ dependencies:
+ regenerator-runtime "^0.13.11"
+
+"@babel/template@^7.16.7", "@babel/template@^7.3.3":
+ version "7.16.7"
+ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.7.tgz#8d126c8701fde4d66b264b3eba3d96f07666d155"
+ integrity sha512-I8j/x8kHUrbYRTUxXrrMbfCa7jxkE7tZre39x3kjr9hvI82cK1FfqLygotcWN5kdPGWcLdWMHpSBavse5tWw3w==
+ dependencies:
+ "@babel/code-frame" "^7.16.7"
+ "@babel/parser" "^7.16.7"
+ "@babel/types" "^7.16.7"
+
+"@babel/traverse@^7.13.0", "@babel/traverse@^7.16.8", "@babel/traverse@^7.18.0", "@babel/traverse@^7.18.2", "@babel/traverse@^7.7.2":
+ version "7.18.2"
+ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.18.2.tgz#b77a52604b5cc836a9e1e08dca01cba67a12d2e8"
+ integrity sha512-9eNwoeovJ6KH9zcCNnENY7DMFwTU9JdGCFtqNLfUAqtUHRCOsTOqWoffosP8vKmNYeSBUv3yVJXjfd8ucwOjUA==
+ dependencies:
+ "@babel/code-frame" "^7.16.7"
+ "@babel/generator" "^7.18.2"
+ "@babel/helper-environment-visitor" "^7.18.2"
+ "@babel/helper-function-name" "^7.17.9"
+ "@babel/helper-hoist-variables" "^7.16.7"
+ "@babel/helper-split-export-declaration" "^7.16.7"
+ "@babel/parser" "^7.18.0"
+ "@babel/types" "^7.18.2"
+ debug "^4.1.0"
+ globals "^11.1.0"
+
+"@babel/types@^7.0.0", "@babel/types@^7.12.6", "@babel/types@^7.16.0", "@babel/types@^7.16.7", "@babel/types@^7.16.8", "@babel/types@^7.17.0", "@babel/types@^7.17.12", "@babel/types@^7.18.0", "@babel/types@^7.18.2", "@babel/types@^7.3.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4":
+ version "7.18.4"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.18.4.tgz#27eae9b9fd18e9dccc3f9d6ad051336f307be354"
+ integrity sha512-ThN1mBcMq5pG/Vm2IcBmPPfyPXbd8S02rS+OBIDENdufvqC7Z/jHPCv9IcP01277aKtDI8g/2XysBN4hA8niiw==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.16.7"
+ to-fast-properties "^2.0.0"
+
+"@bcoe/v8-coverage@^0.2.3":
+ version "0.2.3"
+ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
+ integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
+
+"@csstools/normalize.css@*":
+ version "12.0.0"
+ resolved "https://registry.yarnpkg.com/@csstools/normalize.css/-/normalize.css-12.0.0.tgz#a9583a75c3f150667771f30b60d9f059473e62c4"
+ integrity sha512-M0qqxAcwCsIVfpFQSlGN5XjXWu8l5JDZN+fPt1LeW5SZexQTgnaEvgXAY+CeygRw0EeppWHi12JxESWiWrB0Sg==
+
+"@csstools/postcss-cascade-layers@^1.0.2":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.0.3.tgz#71ee4a3f00f947788097f8d67310b2e4a336aa51"
+ integrity sha512-fvXP0+dcllGtRKAjA5n5tBr57xWQalKky09hSiXAZ9qqjHn0sDuQV2Jz0Y5zHRQ6iGrAjJZOf2+xQj3yuXfLwA==
+ dependencies:
+ "@csstools/selector-specificity" "^2.0.0"
+ postcss-selector-parser "^6.0.10"
+
+"@csstools/postcss-color-function@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-color-function/-/postcss-color-function-1.1.0.tgz#229966327747f58fbe586de35daa139db3ce1e5d"
+ integrity sha512-5D5ND/mZWcQoSfYnSPsXtuiFxhzmhxt6pcjrFLJyldj+p0ZN2vvRpYNX+lahFTtMhAYOa2WmkdGINr0yP0CvGA==
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties" "^1.1.0"
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-font-format-keywords@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.0.tgz#7e7df948a83a0dfb7eb150a96e2390ac642356a1"
+ integrity sha512-oO0cZt8do8FdVBX8INftvIA4lUrKUSCcWUf9IwH9IPWOgKT22oAZFXeHLoDK7nhB2SmkNycp5brxfNMRLIhd6Q==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-hwb-function@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.1.tgz#5224db711ed09a965f85c80c18144ac1c2702fce"
+ integrity sha512-AMZwWyHbbNLBsDADWmoXT9A5yl5dsGEBeJSJRUJt8Y9n8Ziu7Wstt4MC8jtPW7xjcLecyfJwtnUTNSmOzcnWeg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-ic-unit@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.0.tgz#f484db59fc94f35a21b6d680d23b0ec69b286b7f"
+ integrity sha512-i4yps1mBp2ijrx7E96RXrQXQQHm6F4ym1TOD0D69/sjDjZvQ22tqiEvaNw7pFZTUO5b9vWRHzbHzP9+UKuw+bA==
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties" "^1.1.0"
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-is-pseudo-class@^2.0.4":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.5.tgz#60fea78776fc3916ad66d568064aa31029b9f772"
+ integrity sha512-Ek+UFI4UP2hB9u0N1cJd6KgSF1rL0J3PT4is0oSStuus8+WzbGGPyJNMOKQ0w/tyPjxiCnOI4RdSMZt3nks64g==
+ dependencies:
+ "@csstools/selector-specificity" "^2.0.0"
+ postcss-selector-parser "^6.0.10"
+
+"@csstools/postcss-normalize-display-values@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.0.tgz#ce698f688c28517447aedf15a9037987e3d2dc97"
+ integrity sha512-bX+nx5V8XTJEmGtpWTO6kywdS725t71YSLlxWt78XoHUbELWgoCXeOFymRJmL3SU1TLlKSIi7v52EWqe60vJTQ==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-oklab-function@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.0.tgz#e9a269487a292e0930760948e923e1d46b638ee6"
+ integrity sha512-e/Q5HopQzmnQgqimG9v3w2IG4VRABsBq3itOcn4bnm+j4enTgQZ0nWsaH/m9GV2otWGQ0nwccYL5vmLKyvP1ww==
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties" "^1.1.0"
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-progressive-custom-properties@^1.1.0", "@csstools/postcss-progressive-custom-properties@^1.3.0":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz#542292558384361776b45c85226b9a3a34f276fa"
+ integrity sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-stepped-value-functions@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.0.tgz#f8ffc05e163ba7bcbefc5fdcaf264ce9fd408c16"
+ integrity sha512-q8c4bs1GumAiRenmFjASBcWSLKrbzHzWl6C2HcaAxAXIiL2rUlUWbqQZUjwVG5tied0rld19j/Mm90K3qI26vw==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-trigonometric-functions@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.1.tgz#e36e61f445614193dbf6d3a8408709b0cf184a6f"
+ integrity sha512-G78CY/+GePc6dDCTUbwI6TTFQ5fs3N9POHhI6v0QzteGpf6ylARiJUNz9HrRKi4eVYBNXjae1W2766iUEFxHlw==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+"@csstools/postcss-unset-value@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.1.tgz#2cc020785db5ec82cc9444afe4cdae2a65445f89"
+ integrity sha512-f1G1WGDXEU/RN1TWAxBPQgQudtLnLQPyiWdtypkPC+mVYNKFKH/HYXSxH4MVNqwF8M0eDsoiU7HumJHCg/L/jg==
+
+"@csstools/selector-specificity@^2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.0.tgz#65b12f12db55188422070e34687bf3af09870922"
+ integrity sha512-rZ6vufeY/UjAgtyiJ4WvfF6XP6HizIyOfbZOg0RnecIwjrvH8Am3nN1BpKnnPZunYAkUcPPXDhwbxOtGop8cfQ==
+
+"@date-io/core@^2.16.0":
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/@date-io/core/-/core-2.16.0.tgz#7871bfc1d9bca9aa35ad444a239505589d0f22f6"
+ integrity sha512-DYmSzkr+jToahwWrsiRA2/pzMEtz9Bq1euJwoOuYwuwIYXnZFtHajY2E6a1VNVDc9jP8YUXK1BvnZH9mmT19Zg==
+
+"@date-io/date-fns-jalali@^2.16.0":
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/@date-io/date-fns-jalali/-/date-fns-jalali-2.16.0.tgz#0e2916c287e00d708a6f9f6d6e6c44ec377994c5"
+ integrity sha512-MNVvGYwRiBydbvY7gvZM14W2kosIG29G1Ekw5qmYWOXkIIFngh6ZvV7/uVGDCW+gqlIeSz/XitZXA9n8RO0tJw==
+ dependencies:
+ "@date-io/core" "^2.16.0"
+
+"@date-io/date-fns@^2.16.0":
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/@date-io/date-fns/-/date-fns-2.16.0.tgz#bd5e09b6ecb47ee55e593fc3a87e7b2caaa3da40"
+ integrity sha512-bfm5FJjucqlrnQcXDVU5RD+nlGmL3iWgkHTq3uAZWVIuBu6dDmGa3m8a6zo2VQQpu8ambq9H22UyUpn7590joA==
+ dependencies:
+ "@date-io/core" "^2.16.0"
+
+"@date-io/dayjs@^2.16.0":
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/@date-io/dayjs/-/dayjs-2.16.0.tgz#0d2c254ad8db1306fdc4b8eda197cb53c9af89dc"
+ integrity sha512-y5qKyX2j/HG3zMvIxTobYZRGnd1FUW2olZLS0vTj7bEkBQkjd2RO7/FEwDY03Z1geVGlXKnzIATEVBVaGzV4Iw==
+ dependencies:
+ "@date-io/core" "^2.16.0"
+
+"@date-io/hijri@^2.16.1":
+ version "2.16.1"
+ resolved "https://registry.yarnpkg.com/@date-io/hijri/-/hijri-2.16.1.tgz#a5e7e5b875e0ac8719c235eaf51d4188f21ea193"
+ integrity sha512-6BxY0mtnqj5cBiXluRs3uWN0mSJwGw0AB2ZxqtEHvBFoiSYEojW51AETnfPIWpdvDsBn+WAC7QrfBvQZnoyIkQ==
+ dependencies:
+ "@date-io/moment" "^2.16.1"
+
+"@date-io/jalaali@^2.16.1":
+ version "2.16.1"
+ resolved "https://registry.yarnpkg.com/@date-io/jalaali/-/jalaali-2.16.1.tgz#c53323fc429f8fe6ab205d36c003d6de071f17e8"
+ integrity sha512-GLw87G/WJ1DNrQHW8p/LqkqAqTUSqBSRin0H1pRPwCccB5Fh7GT64sadjzEvjW56lPJ0aq2vp5yI2eIjZajfrw==
+ dependencies:
+ "@date-io/moment" "^2.16.1"
+
+"@date-io/luxon@^2.16.1":
+ version "2.16.1"
+ resolved "https://registry.yarnpkg.com/@date-io/luxon/-/luxon-2.16.1.tgz#b08786614cb58831c729a15807753011e4acb966"
+ integrity sha512-aeYp5K9PSHV28946pC+9UKUi/xMMYoaGelrpDibZSgHu2VWHXrr7zWLEr+pMPThSs5vt8Ei365PO+84pCm37WQ==
+ dependencies:
+ "@date-io/core" "^2.16.0"
+
+"@date-io/moment@^2.16.1":
+ version "2.16.1"
+ resolved "https://registry.yarnpkg.com/@date-io/moment/-/moment-2.16.1.tgz#ec6e0daa486871e0e6412036c6f806842a0eeed4"
+ integrity sha512-JkxldQxUqZBfZtsaCcCMkm/dmytdyq5pS1RxshCQ4fHhsvP5A7gSqPD22QbVXMcJydi3d3v1Y8BQdUKEuGACZQ==
+ dependencies:
+ "@date-io/core" "^2.16.0"
+
+"@emotion/babel-plugin@^11.10.6":
+ version "11.10.6"
+ resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.10.6.tgz#a68ee4b019d661d6f37dec4b8903255766925ead"
+ integrity sha512-p2dAqtVrkhSa7xz1u/m9eHYdLi+en8NowrmXeF/dKtJpU8lCWli8RUAati7NcSl0afsBott48pdnANuD0wh9QQ==
+ dependencies:
+ "@babel/helper-module-imports" "^7.16.7"
+ "@babel/runtime" "^7.18.3"
+ "@emotion/hash" "^0.9.0"
+ "@emotion/memoize" "^0.8.0"
+ "@emotion/serialize" "^1.1.1"
+ babel-plugin-macros "^3.1.0"
+ convert-source-map "^1.5.0"
+ escape-string-regexp "^4.0.0"
+ find-root "^1.1.0"
+ source-map "^0.5.7"
+ stylis "4.1.3"
+
+"@emotion/cache@^11.10.5":
+ version "11.10.5"
+ resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.10.5.tgz#c142da9351f94e47527ed458f7bbbbe40bb13c12"
+ integrity sha512-dGYHWyzTdmK+f2+EnIGBpkz1lKc4Zbj2KHd4cX3Wi8/OWr5pKslNjc3yABKH4adRGCvSX4VDC0i04mrrq0aiRA==
+ dependencies:
+ "@emotion/memoize" "^0.8.0"
+ "@emotion/sheet" "^1.2.1"
+ "@emotion/utils" "^1.2.0"
+ "@emotion/weak-memoize" "^0.3.0"
+ stylis "4.1.3"
+
+"@emotion/hash@^0.9.0":
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.0.tgz#c5153d50401ee3c027a57a177bc269b16d889cb7"
+ integrity sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==
+
+"@emotion/is-prop-valid@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.0.tgz#7f2d35c97891669f7e276eb71c83376a5dc44c83"
+ integrity sha512-3aDpDprjM0AwaxGE09bOPkNxHpBd+kA6jty3RnaEXdweX1DF1U3VQpPYb0g1IStAuK7SVQ1cy+bNBBKp4W3Fjg==
+ dependencies:
+ "@emotion/memoize" "^0.8.0"
+
+"@emotion/memoize@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.0.tgz#f580f9beb67176fa57aae70b08ed510e1b18980f"
+ integrity sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==
+
+"@emotion/react@^11.10.6":
+ version "11.10.6"
+ resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.10.6.tgz#dbe5e650ab0f3b1d2e592e6ab1e006e75fd9ac11"
+ integrity sha512-6HT8jBmcSkfzO7mc+N1L9uwvOnlcGoix8Zn7srt+9ga0MjREo6lRpuVX0kzo6Jp6oTqDhREOFsygN6Ew4fEQbw==
+ dependencies:
+ "@babel/runtime" "^7.18.3"
+ "@emotion/babel-plugin" "^11.10.6"
+ "@emotion/cache" "^11.10.5"
+ "@emotion/serialize" "^1.1.1"
+ "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0"
+ "@emotion/utils" "^1.2.0"
+ "@emotion/weak-memoize" "^0.3.0"
+ hoist-non-react-statics "^3.3.1"
+
+"@emotion/serialize@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.1.1.tgz#0595701b1902feded8a96d293b26be3f5c1a5cf0"
+ integrity sha512-Zl/0LFggN7+L1liljxXdsVSVlg6E/Z/olVWpfxUTxOAmi8NU7YoeWeLfi1RmnB2TATHoaWwIBRoL+FvAJiTUQA==
+ dependencies:
+ "@emotion/hash" "^0.9.0"
+ "@emotion/memoize" "^0.8.0"
+ "@emotion/unitless" "^0.8.0"
+ "@emotion/utils" "^1.2.0"
+ csstype "^3.0.2"
+
+"@emotion/sheet@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.1.tgz#0767e0305230e894897cadb6c8df2c51e61a6c2c"
+ integrity sha512-zxRBwl93sHMsOj4zs+OslQKg/uhF38MB+OMKoCrVuS0nyTkqnau+BM3WGEoOptg9Oz45T/aIGs1qbVAsEFo3nA==
+
+"@emotion/styled@^11.10.6":
+ version "11.10.6"
+ resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.10.6.tgz#d886afdc51ef4d66c787ebde848f3cc8b117ebba"
+ integrity sha512-OXtBzOmDSJo5Q0AFemHCfl+bUueT8BIcPSxu0EGTpGk6DmI5dnhSzQANm1e1ze0YZL7TDyAyy6s/b/zmGOS3Og==
+ dependencies:
+ "@babel/runtime" "^7.18.3"
+ "@emotion/babel-plugin" "^11.10.6"
+ "@emotion/is-prop-valid" "^1.2.0"
+ "@emotion/serialize" "^1.1.1"
+ "@emotion/use-insertion-effect-with-fallbacks" "^1.0.0"
+ "@emotion/utils" "^1.2.0"
+
+"@emotion/unitless@^0.8.0":
+ version "0.8.0"
+ resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db"
+ integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==
+
+"@emotion/use-insertion-effect-with-fallbacks@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz#ffadaec35dbb7885bd54de3fa267ab2f860294df"
+ integrity sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==
+
+"@emotion/utils@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.0.tgz#9716eaccbc6b5ded2ea5a90d65562609aab0f561"
+ integrity sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==
+
+"@emotion/weak-memoize@^0.3.0":
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz#ea89004119dc42db2e1dba0f97d553f7372f6fcb"
+ integrity sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==
+
+"@eslint/eslintrc@^1.3.0":
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.0.tgz#29f92c30bb3e771e4a2048c95fa6855392dfac4f"
+ integrity sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==
+ dependencies:
+ ajv "^6.12.4"
+ debug "^4.3.2"
+ espree "^9.3.2"
+ globals "^13.15.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"
+
+"@humanwhocodes/config-array@^0.9.2":
+ version "0.9.5"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.9.5.tgz#2cbaf9a89460da24b5ca6531b8bbfc23e1df50c7"
+ integrity sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==
+ dependencies:
+ "@humanwhocodes/object-schema" "^1.2.1"
+ debug "^4.1.1"
+ minimatch "^3.0.4"
+
+"@humanwhocodes/object-schema@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45"
+ integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==
+
+"@istanbuljs/load-nyc-config@^1.0.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"
+ integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==
+ dependencies:
+ camelcase "^5.3.1"
+ find-up "^4.1.0"
+ get-package-type "^0.1.0"
+ js-yaml "^3.13.1"
+ resolve-from "^5.0.0"
+
+"@istanbuljs/schema@^0.1.2":
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
+ integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==
+
+"@jest/console@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/console/-/console-27.5.1.tgz#260fe7239602fe5130a94f1aa386eff54b014bba"
+ integrity sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ jest-message-util "^27.5.1"
+ jest-util "^27.5.1"
+ slash "^3.0.0"
+
+"@jest/console@^28.1.1":
+ version "28.1.1"
+ resolved "https://registry.yarnpkg.com/@jest/console/-/console-28.1.1.tgz#305f8ca50b6e70413839f54c0e002b60a0f2fd7d"
+ integrity sha512-0RiUocPVFEm3WRMOStIHbRWllG6iW6E3/gUPnf4lkrVFyXIIDeCe+vlKeYyFOMhB2EPE6FLFCNADSOOQMaqvyA==
+ dependencies:
+ "@jest/types" "^28.1.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ jest-message-util "^28.1.1"
+ jest-util "^28.1.1"
+ slash "^3.0.0"
+
+"@jest/core@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.5.1.tgz#267ac5f704e09dc52de2922cbf3af9edcd64b626"
+ integrity sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==
+ dependencies:
+ "@jest/console" "^27.5.1"
+ "@jest/reporters" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ emittery "^0.8.1"
+ exit "^0.1.2"
+ graceful-fs "^4.2.9"
+ jest-changed-files "^27.5.1"
+ jest-config "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-resolve-dependencies "^27.5.1"
+ jest-runner "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ jest-watcher "^27.5.1"
+ micromatch "^4.0.4"
+ rimraf "^3.0.0"
+ slash "^3.0.0"
+ strip-ansi "^6.0.0"
+
+"@jest/environment@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-27.5.1.tgz#d7425820511fe7158abbecc010140c3fd3be9c74"
+ integrity sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==
+ dependencies:
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ jest-mock "^27.5.1"
+
+"@jest/fake-timers@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-27.5.1.tgz#76979745ce0579c8a94a4678af7a748eda8ada74"
+ integrity sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@sinonjs/fake-timers" "^8.0.1"
+ "@types/node" "*"
+ jest-message-util "^27.5.1"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
+
+"@jest/globals@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.5.1.tgz#7ac06ce57ab966566c7963431cef458434601b2b"
+ integrity sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ expect "^27.5.1"
+
+"@jest/reporters@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.5.1.tgz#ceda7be96170b03c923c37987b64015812ffec04"
+ integrity sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==
+ dependencies:
+ "@bcoe/v8-coverage" "^0.2.3"
+ "@jest/console" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ collect-v8-coverage "^1.0.0"
+ exit "^0.1.2"
+ glob "^7.1.2"
+ graceful-fs "^4.2.9"
+ istanbul-lib-coverage "^3.0.0"
+ istanbul-lib-instrument "^5.1.0"
+ istanbul-lib-report "^3.0.0"
+ istanbul-lib-source-maps "^4.0.0"
+ istanbul-reports "^3.1.3"
+ jest-haste-map "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
+ slash "^3.0.0"
+ source-map "^0.6.0"
+ string-length "^4.0.1"
+ terminal-link "^2.0.0"
+ v8-to-istanbul "^8.1.0"
+
+"@jest/schemas@^28.0.2":
+ version "28.0.2"
+ resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-28.0.2.tgz#08c30df6a8d07eafea0aef9fb222c5e26d72e613"
+ integrity sha512-YVDJZjd4izeTDkij00vHHAymNXQ6WWsdChFRK86qck6Jpr3DCL5W3Is3vslviRlP+bLuMYRLbdp98amMvqudhA==
+ dependencies:
+ "@sinclair/typebox" "^0.23.3"
+
+"@jest/source-map@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-27.5.1.tgz#6608391e465add4205eae073b55e7f279e04e8cf"
+ integrity sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==
+ dependencies:
+ callsites "^3.0.0"
+ graceful-fs "^4.2.9"
+ source-map "^0.6.0"
+
+"@jest/test-result@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-27.5.1.tgz#56a6585fa80f7cdab72b8c5fc2e871d03832f5bb"
+ integrity sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==
+ dependencies:
+ "@jest/console" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ collect-v8-coverage "^1.0.0"
+
+"@jest/test-result@^28.1.1":
+ version "28.1.1"
+ resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-28.1.1.tgz#c6f18d1bbb01aa88925dd687872a75f8414b317a"
+ integrity sha512-hPmkugBktqL6rRzwWAtp1JtYT4VHwv8OQ+9lE5Gymj6dHzubI/oJHMUpPOt8NrdVWSrz9S7bHjJUmv2ggFoUNQ==
+ dependencies:
+ "@jest/console" "^28.1.1"
+ "@jest/types" "^28.1.1"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ collect-v8-coverage "^1.0.0"
+
+"@jest/test-sequencer@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.5.1.tgz#4057e0e9cea4439e544c6353c6affe58d095745b"
+ integrity sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==
+ dependencies:
+ "@jest/test-result" "^27.5.1"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-runtime "^27.5.1"
+
+"@jest/transform@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.5.1.tgz#6c3501dcc00c4c08915f292a600ece5ecfe1f409"
+ integrity sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==
+ dependencies:
+ "@babel/core" "^7.1.0"
+ "@jest/types" "^27.5.1"
+ babel-plugin-istanbul "^6.1.1"
+ chalk "^4.0.0"
+ convert-source-map "^1.4.0"
+ fast-json-stable-stringify "^2.0.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-util "^27.5.1"
+ micromatch "^4.0.4"
+ pirates "^4.0.4"
+ slash "^3.0.0"
+ source-map "^0.6.1"
+ write-file-atomic "^3.0.0"
+
+"@jest/types@^26.6.2":
+ version "26.6.2"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e"
+ integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^15.0.0"
+ chalk "^4.0.0"
+
+"@jest/types@^27.5.1":
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.5.1.tgz#3c79ec4a8ba61c170bf937bcf9e98a9df175ec80"
+ integrity sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^16.0.0"
+ chalk "^4.0.0"
+
+"@jest/types@^28.1.1":
+ version "28.1.1"
+ resolved "https://registry.yarnpkg.com/@jest/types/-/types-28.1.1.tgz#d059bbc80e6da6eda9f081f293299348bd78ee0b"
+ integrity sha512-vRXVqSg1VhDnB8bWcmvLzmg0Bt9CRKVgHPXqYwvWMX3TvAjeO+nRuK6+VdTKCtWOvYlmkF/HqNAL/z+N3B53Kw==
+ dependencies:
+ "@jest/schemas" "^28.0.2"
+ "@types/istanbul-lib-coverage" "^2.0.0"
+ "@types/istanbul-reports" "^3.0.0"
+ "@types/node" "*"
+ "@types/yargs" "^17.0.8"
+ chalk "^4.0.0"
+
+"@jridgewell/gen-mapping@^0.1.0":
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996"
+ integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==
+ dependencies:
+ "@jridgewell/set-array" "^1.0.0"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+
+"@jridgewell/gen-mapping@^0.3.0":
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
+ integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==
+ dependencies:
+ "@jridgewell/set-array" "^1.0.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/resolve-uri@^3.0.3":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
+ integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
+
+"@jridgewell/set-array@^1.0.0":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.1.tgz#36a6acc93987adcf0ba50c66908bd0b70de8afea"
+ integrity sha512-Ct5MqZkLGEXTVmQYbGtx9SVqD2fqwvdubdps5D3djjAkgkKwT918VNOz65pEHFaYTeWcukmJmH5SwsA9Tn2ObQ==
+
+"@jridgewell/set-array@^1.0.1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
+ integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
+
+"@jridgewell/source-map@^0.3.2":
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb"
+ integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.0"
+ "@jridgewell/trace-mapping" "^0.3.9"
+
+"@jridgewell/sourcemap-codec@^1.4.10":
+ version "1.4.14"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
+ integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
+
+"@jridgewell/trace-mapping@^0.3.7":
+ version "0.3.13"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.13.tgz#dcfe3e95f224c8fe97a87a5235defec999aa92ea"
+ integrity sha512-o1xbKhp9qnIAoHJSWd6KlCZfqslL4valSF81H8ImioOAxluWYWOpWkpyktY2vnt4tbrX9XYaxovq6cgowaJp2w==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.0.3"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+
+"@jridgewell/trace-mapping@^0.3.9":
+ version "0.3.14"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
+ integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.0.3"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+
+"@leichtgewicht/ip-codec@^2.0.1":
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"
+ integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==
+
+"@mui/base@5.0.0-alpha.119":
+ version "5.0.0-alpha.119"
+ resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-alpha.119.tgz#923e148ceb84898fdd28da069b7c42635053c128"
+ integrity sha512-XA5zhlYfXi67u613eIF0xRmktkatx6ERy3h+PwrMN5IcWFbgiL1guz8VpdXON+GWb8+G7B8t5oqTFIaCqaSAeA==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+ "@emotion/is-prop-valid" "^1.2.0"
+ "@mui/types" "^7.2.3"
+ "@mui/utils" "^5.11.11"
+ "@popperjs/core" "^2.11.6"
+ clsx "^1.2.1"
+ prop-types "^15.8.1"
+ react-is "^18.2.0"
+
+"@mui/base@5.0.0-alpha.120":
+ version "5.0.0-alpha.120"
+ resolved "https://registry.yarnpkg.com/@mui/base/-/base-5.0.0-alpha.120.tgz#d576f62af476af51a6ced948cf51a688a9ed10e8"
+ integrity sha512-UoIXLjbl8ghK7OSD1dYzHIj79sx9v5S2J7vYeuhxUS0QR0FwGZ3WLHd31TQ2CT2faPX/AXsHQeFn93wKSnjPUQ==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+ "@emotion/is-prop-valid" "^1.2.0"
+ "@mui/types" "^7.2.3"
+ "@mui/utils" "^5.11.12"
+ "@popperjs/core" "^2.11.6"
+ clsx "^1.2.1"
+ prop-types "^15.8.1"
+ react-is "^18.2.0"
+
+"@mui/core-downloads-tracker@^5.11.12":
+ version "5.11.12"
+ resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.11.12.tgz#b2ea89ba71321a79c89dfb6b2a1b1886dc7de6e4"
+ integrity sha512-LHh8HZQ5nPVcW5QnyLwkAZ40txc/S2bzKMQ3bTO+5mjuwAJ2AzQrjZINLVy1geY7ei1pHXVqO1hcWHg/QdT44w==
+
+"@mui/icons-material@^5.11.11":
+ version "5.11.11"
+ resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.11.11.tgz#d4e01bd405b0dac779f5e060586277f91f3acb6e"
+ integrity sha512-Eell3ADmQVE8HOpt/LZ3zIma8JSvPh3XgnhwZLT0k5HRqZcd6F/QDHc7xsWtgz09t+UEFvOYJXjtrwKmLdwwpw==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+
+"@mui/lab@^5.0.0-alpha.122":
+ version "5.0.0-alpha.122"
+ resolved "https://registry.yarnpkg.com/@mui/lab/-/lab-5.0.0-alpha.122.tgz#271d4edb45613c598b6a9ab2fbe356454805f90f"
+ integrity sha512-rJyu9llUWAluUQgDEmN0WrpcFxeTdJgu+XYriJtp/MchdvKl/qVTlx+vhnIhqas2bySj5N1VQnkI6qOvfXiYvQ==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+ "@mui/base" "5.0.0-alpha.120"
+ "@mui/system" "^5.11.12"
+ "@mui/types" "^7.2.3"
+ "@mui/utils" "^5.11.12"
+ clsx "^1.2.1"
+ prop-types "^15.8.1"
+ react-is "^18.2.0"
+
+"@mui/material@^5.11.12":
+ version "5.11.12"
+ resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.11.12.tgz#b113c854fb1bb0aa473686a36a92322c6c754121"
+ integrity sha512-M6BiIeJjySeEzWeiFJQ9pIjJy6mx5mHPWeMT99wjQdAmA2GxCQhE9A0fh6jQP4jMmYzxhOIhjsGcp0vSdpseXg==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+ "@mui/base" "5.0.0-alpha.119"
+ "@mui/core-downloads-tracker" "^5.11.12"
+ "@mui/system" "^5.11.12"
+ "@mui/types" "^7.2.3"
+ "@mui/utils" "^5.11.12"
+ "@types/react-transition-group" "^4.4.5"
+ clsx "^1.2.1"
+ csstype "^3.1.1"
+ prop-types "^15.8.1"
+ react-is "^18.2.0"
+ react-transition-group "^4.4.5"
+
+"@mui/private-theming@^5.11.12":
+ version "5.11.12"
+ resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-5.11.12.tgz#07c60abac0547b89cc6ac68821c2366e8fab5389"
+ integrity sha512-hnJ0svNI1TPeWZ18E6DvES8PB4NyMLwal6EyXf69rTrYqT6wZPLjB+HiCYfSOCqU/fwArhupSqIIkQpDs8CkAw==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+ "@mui/utils" "^5.11.12"
+ prop-types "^15.8.1"
+
+"@mui/styled-engine@^5.11.11":
+ version "5.11.11"
+ resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-5.11.11.tgz#9084c331fdcff2210ec33adf37f34e94d67202e4"
+ integrity sha512-wV0UgW4lN5FkDBXefN8eTYeuE9sjyQdg5h94vtwZCUamGQEzmCOtir4AakgmbWMy0x8OLjdEUESn9wnf5J9MOg==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+ "@emotion/cache" "^11.10.5"
+ csstype "^3.1.1"
+ prop-types "^15.8.1"
+
+"@mui/styles@^5.11.12":
+ version "5.11.12"
+ resolved "https://registry.yarnpkg.com/@mui/styles/-/styles-5.11.12.tgz#ae1c86b360649e661e2d0c3f15ded4dc08e758c3"
+ integrity sha512-rhymjGAVOKPYfe80p0a5qq5Anfzy8Qlnrmcfba+gRLwbnWZpF1wheasb2IeEHmV/QoPTbk0+tbb1Ej94XCA5CA==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+ "@emotion/hash" "^0.9.0"
+ "@mui/private-theming" "^5.11.12"
+ "@mui/types" "^7.2.3"
+ "@mui/utils" "^5.11.12"
+ clsx "^1.2.1"
+ csstype "^3.1.1"
+ hoist-non-react-statics "^3.3.2"
+ jss "^10.10.0"
+ jss-plugin-camel-case "^10.10.0"
+ jss-plugin-default-unit "^10.10.0"
+ jss-plugin-global "^10.10.0"
+ jss-plugin-nested "^10.10.0"
+ jss-plugin-props-sort "^10.10.0"
+ jss-plugin-rule-value-function "^10.10.0"
+ jss-plugin-vendor-prefixer "^10.10.0"
+ prop-types "^15.8.1"
+
+"@mui/system@^5.11.12", "@mui/system@^5.4.1":
+ version "5.11.12"
+ resolved "https://registry.yarnpkg.com/@mui/system/-/system-5.11.12.tgz#e7234c4e73e9af2b8e985fbed048d8b274338561"
+ integrity sha512-sYjsXkiwKpZDC3aS6O/6KTjji0jGINLQcrD5EJ5NTkIDiLf19I4HJhnufgKqlTWNfoDBlRohuTf3TzfM06c4ug==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+ "@mui/private-theming" "^5.11.12"
+ "@mui/styled-engine" "^5.11.11"
+ "@mui/types" "^7.2.3"
+ "@mui/utils" "^5.11.12"
+ clsx "^1.2.1"
+ csstype "^3.1.1"
+ prop-types "^15.8.1"
+
+"@mui/types@^7.2.3":
+ version "7.2.3"
+ resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.3.tgz#06faae1c0e2f3a31c86af6f28b3a4a42143670b9"
+ integrity sha512-tZ+CQggbe9Ol7e/Fs5RcKwg/woU+o8DCtOnccX6KmbBc7YrfqMYEYuaIcXHuhpT880QwNkZZ3wQwvtlDFA2yOw==
+
+"@mui/utils@^5.11.11", "@mui/utils@^5.11.12", "@mui/utils@^5.11.7":
+ version "5.11.12"
+ resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.11.12.tgz#627f491c0e7267398590af5e6cb14b306170d914"
+ integrity sha512-5vH9B/v8pzkpEPO2HvGM54ToXV6cFdAn8UrvdN8TMEEwpn/ycW0jLiyBcgUlPsQ+xha7hqXCPQYHaYFDIcwaiw==
+ dependencies:
+ "@babel/runtime" "^7.21.0"
+ "@types/prop-types" "^15.7.5"
+ "@types/react-is" "^16.7.1 || ^17.0.0"
+ prop-types "^15.8.1"
+ react-is "^18.2.0"
+
+"@mui/x-date-pickers@^6.0.0":
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/@mui/x-date-pickers/-/x-date-pickers-6.0.0.tgz#003a613e7addc33fee6bcb2938f3194188c68b47"
+ integrity sha512-6kraEcal5oBM/14CyJteNYcr0BqVD3qy4fX83dQrruRf2B3j8evzCVPZiT7T+Qdrx3AvbUS2wQdGP+9BcHByhA==
+ dependencies:
+ "@babel/runtime" "^7.20.13"
+ "@date-io/core" "^2.16.0"
+ "@date-io/date-fns" "^2.16.0"
+ "@date-io/date-fns-jalali" "^2.16.0"
+ "@date-io/dayjs" "^2.16.0"
+ "@date-io/hijri" "^2.16.1"
+ "@date-io/jalaali" "^2.16.1"
+ "@date-io/luxon" "^2.16.1"
+ "@date-io/moment" "^2.16.1"
+ "@mui/utils" "^5.11.7"
+ "@types/react-transition-group" "^4.4.5"
+ clsx "^1.2.1"
+ prop-types "^15.8.1"
+ react-transition-group "^4.4.5"
+
+"@nodelib/fs.scandir@2.1.5":
+ version "2.1.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
+ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==
+ dependencies:
+ "@nodelib/fs.stat" "2.0.5"
+ run-parallel "^1.1.9"
+
+"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b"
+ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
+
+"@nodelib/fs.walk@^1.2.3":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@pmmmwh/react-refresh-webpack-plugin@^0.5.3":
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz#58f8217ba70069cc6a73f5d7e05e85b458c150e2"
+ integrity sha512-bcKCAzF0DV2IIROp9ZHkRJa6O4jy7NlnHdWL3GmcUxYWNjLXkK5kfELELwEfSP5hXPfVL/qOGMAROuMQb9GG8Q==
+ dependencies:
+ ansi-html-community "^0.0.8"
+ common-path-prefix "^3.0.0"
+ core-js-pure "^3.8.1"
+ error-stack-parser "^2.0.6"
+ find-up "^5.0.0"
+ html-entities "^2.1.0"
+ loader-utils "^2.0.0"
+ schema-utils "^3.0.0"
+ source-map "^0.7.3"
+
+"@popperjs/core@^2.11.6":
+ version "2.11.6"
+ resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45"
+ integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==
+
+"@reduxjs/toolkit@^1.6.0":
+ version "1.8.2"
+ resolved "https://registry.yarnpkg.com/@reduxjs/toolkit/-/toolkit-1.8.2.tgz#352fd17bc858af51d21ce8d28183a930cab9e638"
+ integrity sha512-CtPw5TkN1pHRigMFCOS/0qg3b/yfPV5qGCsltVnIz7bx4PKTJlGHYfIxm97qskLknMzuGfjExaYdXJ77QTL0vg==
+ dependencies:
+ immer "^9.0.7"
+ redux "^4.1.2"
+ redux-thunk "^2.4.1"
+ reselect "^4.1.5"
+
+"@rollup/plugin-babel@^5.2.0":
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283"
+ integrity sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==
+ dependencies:
+ "@babel/helper-module-imports" "^7.10.4"
+ "@rollup/pluginutils" "^3.1.0"
+
+"@rollup/plugin-node-resolve@^11.2.1":
+ version "11.2.1"
+ resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60"
+ integrity sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==
+ dependencies:
+ "@rollup/pluginutils" "^3.1.0"
+ "@types/resolve" "1.17.1"
+ builtin-modules "^3.1.0"
+ deepmerge "^4.2.2"
+ is-module "^1.0.0"
+ resolve "^1.19.0"
+
+"@rollup/plugin-replace@^2.4.1":
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz#a2d539314fbc77c244858faa523012825068510a"
+ integrity sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==
+ dependencies:
+ "@rollup/pluginutils" "^3.1.0"
+ magic-string "^0.25.7"
+
+"@rollup/pluginutils@^3.1.0":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
+ integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
+ dependencies:
+ "@types/estree" "0.0.39"
+ estree-walker "^1.0.1"
+ picomatch "^2.2.2"
+
+"@rushstack/eslint-patch@^1.1.0":
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.1.3.tgz#6801033be7ff87a6b7cadaf5b337c9f366a3c4b0"
+ integrity sha512-WiBSI6JBIhC6LRIsB2Kwh8DsGTlbBU+mLRxJmAe3LjHTdkDpwIbEOZgoXBbZilk/vlfjK8i6nKRAvIRn1XaIMw==
+
+"@sinclair/typebox@^0.23.3":
+ version "0.23.5"
+ resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.23.5.tgz#93f7b9f4e3285a7a9ade7557d9a8d36809cbc47d"
+ integrity sha512-AFBVi/iT4g20DHoujvMH1aEDn8fGJh4xsRGCP6d8RpLPMqsNPvW01Jcn0QysXTsg++/xj25NmJsGyH9xug/wKg==
+
+"@sinonjs/commons@^1.7.0":
+ version "1.8.3"
+ resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d"
+ integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==
+ dependencies:
+ type-detect "4.0.8"
+
+"@sinonjs/fake-timers@^8.0.1":
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-8.1.0.tgz#3fdc2b6cb58935b21bfb8d1625eb1300484316e7"
+ integrity sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==
+ dependencies:
+ "@sinonjs/commons" "^1.7.0"
+
+"@surma/rollup-plugin-off-main-thread@^2.2.3":
+ version "2.2.3"
+ resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz#ee34985952ca21558ab0d952f00298ad2190c053"
+ integrity sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==
+ dependencies:
+ ejs "^3.1.6"
+ json5 "^2.2.0"
+ magic-string "^0.25.0"
+ string.prototype.matchall "^4.0.6"
+
+"@svgr/babel-plugin-add-jsx-attribute@^5.4.0":
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz#81ef61947bb268eb9d50523446f9c638fb355906"
+ integrity sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==
+
+"@svgr/babel-plugin-remove-jsx-attribute@^5.4.0":
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz#6b2c770c95c874654fd5e1d5ef475b78a0a962ef"
+ integrity sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==
+
+"@svgr/babel-plugin-remove-jsx-empty-expression@^5.0.1":
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz#25621a8915ed7ad70da6cea3d0a6dbc2ea933efd"
+ integrity sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==
+
+"@svgr/babel-plugin-replace-jsx-attribute-value@^5.0.1":
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz#0b221fc57f9fcd10e91fe219e2cd0dd03145a897"
+ integrity sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==
+
+"@svgr/babel-plugin-svg-dynamic-title@^5.4.0":
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz#139b546dd0c3186b6e5db4fefc26cb0baea729d7"
+ integrity sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==
+
+"@svgr/babel-plugin-svg-em-dimensions@^5.4.0":
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz#6543f69526632a133ce5cabab965deeaea2234a0"
+ integrity sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==
+
+"@svgr/babel-plugin-transform-react-native-svg@^5.4.0":
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz#00bf9a7a73f1cad3948cdab1f8dfb774750f8c80"
+ integrity sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==
+
+"@svgr/babel-plugin-transform-svg-component@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz#583a5e2a193e214da2f3afeb0b9e8d3250126b4a"
+ integrity sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==
+
+"@svgr/babel-preset@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-5.5.0.tgz#8af54f3e0a8add7b1e2b0fcd5a882c55393df327"
+ integrity sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==
+ dependencies:
+ "@svgr/babel-plugin-add-jsx-attribute" "^5.4.0"
+ "@svgr/babel-plugin-remove-jsx-attribute" "^5.4.0"
+ "@svgr/babel-plugin-remove-jsx-empty-expression" "^5.0.1"
+ "@svgr/babel-plugin-replace-jsx-attribute-value" "^5.0.1"
+ "@svgr/babel-plugin-svg-dynamic-title" "^5.4.0"
+ "@svgr/babel-plugin-svg-em-dimensions" "^5.4.0"
+ "@svgr/babel-plugin-transform-react-native-svg" "^5.4.0"
+ "@svgr/babel-plugin-transform-svg-component" "^5.5.0"
+
+"@svgr/core@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/core/-/core-5.5.0.tgz#82e826b8715d71083120fe8f2492ec7d7874a579"
+ integrity sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==
+ dependencies:
+ "@svgr/plugin-jsx" "^5.5.0"
+ camelcase "^6.2.0"
+ cosmiconfig "^7.0.0"
+
+"@svgr/hast-util-to-babel-ast@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz#5ee52a9c2533f73e63f8f22b779f93cd432a5461"
+ integrity sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==
+ dependencies:
+ "@babel/types" "^7.12.6"
+
+"@svgr/plugin-jsx@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz#1aa8cd798a1db7173ac043466d7b52236b369000"
+ integrity sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==
+ dependencies:
+ "@babel/core" "^7.12.3"
+ "@svgr/babel-preset" "^5.5.0"
+ "@svgr/hast-util-to-babel-ast" "^5.5.0"
+ svg-parser "^2.0.2"
+
+"@svgr/plugin-svgo@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz#02da55d85320549324e201c7b2e53bf431fcc246"
+ integrity sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==
+ dependencies:
+ cosmiconfig "^7.0.0"
+ deepmerge "^4.2.2"
+ svgo "^1.2.2"
+
+"@svgr/webpack@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-5.5.0.tgz#aae858ee579f5fa8ce6c3166ef56c6a1b381b640"
+ integrity sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==
+ dependencies:
+ "@babel/core" "^7.12.3"
+ "@babel/plugin-transform-react-constant-elements" "^7.12.1"
+ "@babel/preset-env" "^7.12.1"
+ "@babel/preset-react" "^7.12.5"
+ "@svgr/core" "^5.5.0"
+ "@svgr/plugin-jsx" "^5.5.0"
+ "@svgr/plugin-svgo" "^5.5.0"
+ loader-utils "^2.0.0"
+
+"@testing-library/dom@^7.28.1":
+ version "7.31.2"
+ resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.31.2.tgz#df361db38f5212b88555068ab8119f5d841a8c4a"
+ integrity sha512-3UqjCpey6HiTZT92vODYLPxTBWlM8ZOOjr3LX5F37/VRipW2M1kX6I/Cm4VXzteZqfGfagg8yXywpcOgQBlNsQ==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ "@babel/runtime" "^7.12.5"
+ "@types/aria-query" "^4.2.0"
+ aria-query "^4.2.2"
+ chalk "^4.1.0"
+ dom-accessibility-api "^0.5.6"
+ lz-string "^1.4.4"
+ pretty-format "^26.6.2"
+
+"@testing-library/jest-dom@^5.11.4":
+ version "5.16.4"
+ resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.4.tgz#938302d7b8b483963a3ae821f1c0808f872245cd"
+ integrity sha512-Gy+IoFutbMQcky0k+bqqumXZ1cTGswLsFqmNLzNdSKkU9KGV2u9oXhukCbbJ9/LRPKiqwxEE8VpV/+YZlfkPUA==
+ dependencies:
+ "@babel/runtime" "^7.9.2"
+ "@types/testing-library__jest-dom" "^5.9.1"
+ aria-query "^5.0.0"
+ chalk "^3.0.0"
+ css "^3.0.0"
+ css.escape "^1.5.1"
+ dom-accessibility-api "^0.5.6"
+ lodash "^4.17.15"
+ redent "^3.0.0"
+
+"@testing-library/react@^11.1.0":
+ version "11.2.7"
+ resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-11.2.7.tgz#b29e2e95c6765c815786c0bc1d5aed9cb2bf7818"
+ integrity sha512-tzRNp7pzd5QmbtXNG/mhdcl7Awfu/Iz1RaVHY75zTdOkmHCuzMhRL83gWHSgOAcjS3CCbyfwUHMZgRJb4kAfpA==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+ "@testing-library/dom" "^7.28.1"
+
+"@testing-library/user-event@^12.1.10":
+ version "12.8.3"
+ resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-12.8.3.tgz#1aa3ed4b9f79340a1e1836bc7f57c501e838704a"
+ integrity sha512-IR0iWbFkgd56Bu5ZI/ej8yQwrkCv8Qydx6RzwbKz9faXazR/+5tvYKsZQgyXJiwgpcva127YO6JcWy7YlCfofQ==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+
+"@tootallnate/once@1":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
+ integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==
+
+"@trysound/sax@0.2.0":
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad"
+ integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
+
+"@types/aria-query@^4.2.0":
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc"
+ integrity sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==
+
+"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.14":
+ version "7.1.19"
+ resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.19.tgz#7b497495b7d1b4812bdb9d02804d0576f43ee460"
+ integrity sha512-WEOTgRsbYkvA/KCsDwVEGkd7WAr1e3g31VHQ8zy5gul/V1qKullU/BU5I68X5v7V3GnB9eotmom4v5a5gjxorw==
+ dependencies:
+ "@babel/parser" "^7.1.0"
+ "@babel/types" "^7.0.0"
+ "@types/babel__generator" "*"
+ "@types/babel__template" "*"
+ "@types/babel__traverse" "*"
+
+"@types/babel__generator@*":
+ version "7.6.4"
+ resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.4.tgz#1f20ce4c5b1990b37900b63f050182d28c2439b7"
+ integrity sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==
+ dependencies:
+ "@babel/types" "^7.0.0"
+
+"@types/babel__template@*":
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.1.tgz#3d1a48fd9d6c0edfd56f2ff578daed48f36c8969"
+ integrity sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==
+ dependencies:
+ "@babel/parser" "^7.1.0"
+ "@babel/types" "^7.0.0"
+
+"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6":
+ version "7.17.1"
+ resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.17.1.tgz#1a0e73e8c28c7e832656db372b779bfd2ef37314"
+ integrity sha512-kVzjari1s2YVi77D3w1yuvohV2idweYXMCDzqBiVNN63TcDWrIlTVOYpqVrvbbyOE/IyzBoTKF0fdnLPEORFxA==
+ dependencies:
+ "@babel/types" "^7.3.0"
+
+"@types/body-parser@*":
+ version "1.19.2"
+ resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0"
+ integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==
+ dependencies:
+ "@types/connect" "*"
+ "@types/node" "*"
+
+"@types/bonjour@^3.5.9":
+ version "3.5.10"
+ resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275"
+ integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw==
+ dependencies:
+ "@types/node" "*"
+
+"@types/connect-history-api-fallback@^1.3.5":
+ version "1.3.5"
+ resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae"
+ integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==
+ dependencies:
+ "@types/express-serve-static-core" "*"
+ "@types/node" "*"
+
+"@types/connect@*":
+ version "3.4.35"
+ resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1"
+ integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==
+ dependencies:
+ "@types/node" "*"
+
+"@types/eslint-scope@^3.7.3":
+ version "3.7.3"
+ resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224"
+ integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==
+ dependencies:
+ "@types/eslint" "*"
+ "@types/estree" "*"
+
+"@types/eslint@*":
+ version "8.4.3"
+ resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.3.tgz#5c92815a3838b1985c90034cd85f26f59d9d0ece"
+ integrity sha512-YP1S7YJRMPs+7KZKDb9G63n8YejIwW9BALq7a5j2+H4yl6iOv9CB29edho+cuFRrvmJbbaH2yiVChKLJVysDGw==
+ dependencies:
+ "@types/estree" "*"
+ "@types/json-schema" "*"
+
+"@types/eslint@^7.28.2":
+ version "7.29.0"
+ resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.29.0.tgz#e56ddc8e542815272720bb0b4ccc2aff9c3e1c78"
+ integrity sha512-VNcvioYDH8/FxaeTKkM4/TiTwt6pBV9E3OfGmvaw8tPl0rrHCJ4Ll15HRT+pMiFAf/MLQvAzC+6RzUMEL9Ceng==
+ dependencies:
+ "@types/estree" "*"
+ "@types/json-schema" "*"
+
+"@types/estree@*", "@types/estree@^0.0.51":
+ version "0.0.51"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40"
+ integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==
+
+"@types/estree@0.0.39":
+ version "0.0.39"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
+ integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==
+
+"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18":
+ version "4.17.28"
+ resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz#c47def9f34ec81dc6328d0b1b5303d1ec98d86b8"
+ integrity sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==
+ dependencies:
+ "@types/node" "*"
+ "@types/qs" "*"
+ "@types/range-parser" "*"
+
+"@types/express@*", "@types/express@^4.17.13":
+ version "4.17.13"
+ resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034"
+ integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==
+ dependencies:
+ "@types/body-parser" "*"
+ "@types/express-serve-static-core" "^4.17.18"
+ "@types/qs" "*"
+ "@types/serve-static" "*"
+
+"@types/graceful-fs@^4.1.2":
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15"
+ integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw==
+ dependencies:
+ "@types/node" "*"
+
+"@types/hoist-non-react-statics@^3.3.0":
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f"
+ integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA==
+ dependencies:
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+
+"@types/html-minifier-terser@^6.0.0":
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35"
+ integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==
+
+"@types/http-proxy@^1.17.8":
+ version "1.17.9"
+ resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a"
+ integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw==
+ dependencies:
+ "@types/node" "*"
+
+"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1":
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44"
+ integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==
+
+"@types/istanbul-lib-report@*":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686"
+ integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==
+ dependencies:
+ "@types/istanbul-lib-coverage" "*"
+
+"@types/istanbul-reports@^3.0.0":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff"
+ integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==
+ dependencies:
+ "@types/istanbul-lib-report" "*"
+
+"@types/jest@*":
+ version "28.1.1"
+ resolved "https://registry.yarnpkg.com/@types/jest/-/jest-28.1.1.tgz#8c9ba63702a11f8c386ee211280e8b68cb093cd1"
+ integrity sha512-C2p7yqleUKtCkVjlOur9BWVA4HgUQmEj/HWCt5WzZ5mLXrWnyIfl0wGuArc+kBXsy0ZZfLp+7dywB4HtSVYGVA==
+ dependencies:
+ jest-matcher-utils "^27.0.0"
+ pretty-format "^27.0.0"
+
+"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
+ version "7.0.11"
+ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
+ integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
+
+"@types/json5@^0.0.29":
+ version "0.0.29"
+ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
+ integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
+
+"@types/mime@^1":
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
+ integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
+
+"@types/node@*":
+ version "17.0.41"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.41.tgz#1607b2fd3da014ae5d4d1b31bc792a39348dfb9b"
+ integrity sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw==
+
+"@types/parse-json@^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0"
+ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==
+
+"@types/prettier@^2.1.5":
+ version "2.6.3"
+ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.6.3.tgz#68ada76827b0010d0db071f739314fa429943d0a"
+ integrity sha512-ymZk3LEC/fsut+/Q5qejp6R9O1rMxz3XaRHDV6kX8MrGAhOSPqVARbDi+EZvInBpw+BnCX3TD240byVkOfQsHg==
+
+"@types/prop-types@*", "@types/prop-types@^15.7.5":
+ version "15.7.5"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf"
+ integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
+
+"@types/q@^1.5.1":
+ version "1.5.5"
+ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df"
+ integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==
+
+"@types/qs@*":
+ version "6.9.7"
+ resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
+ integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
+
+"@types/range-parser@*":
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
+ integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
+
+"@types/react-is@^16.7.1 || ^17.0.0":
+ version "17.0.3"
+ resolved "https://registry.yarnpkg.com/@types/react-is/-/react-is-17.0.3.tgz#2d855ba575f2fc8d17ef9861f084acc4b90a137a"
+ integrity sha512-aBTIWg1emtu95bLTLx0cpkxwGW3ueZv71nE2YFBpL8k/z5czEW8yYpOo8Dp+UUAFAtKwNaOsh/ioSeQnWlZcfw==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react-redux@^7.1.20":
+ version "7.1.24"
+ resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.24.tgz#6caaff1603aba17b27d20f8ad073e4c077e975c0"
+ integrity sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==
+ dependencies:
+ "@types/hoist-non-react-statics" "^3.3.0"
+ "@types/react" "*"
+ hoist-non-react-statics "^3.3.0"
+ redux "^4.0.0"
+
+"@types/react-transition-group@^4.4.5":
+ version "4.4.5"
+ resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416"
+ integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react@*":
+ version "18.0.12"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.12.tgz#cdaa209d0a542b3fcf69cf31a03976ec4cdd8840"
+ integrity sha512-duF1OTASSBQtcigUvhuiTB1Ya3OvSy+xORCiEf20H0P0lzx+/KeVsA99U5UjLXSbyo1DRJDlLKqTeM1ngosqtg==
+ dependencies:
+ "@types/prop-types" "*"
+ "@types/scheduler" "*"
+ csstype "^3.0.2"
+
+"@types/resolve@1.17.1":
+ version "1.17.1"
+ resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
+ integrity sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==
+ dependencies:
+ "@types/node" "*"
+
+"@types/retry@0.12.0":
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
+ integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==
+
+"@types/scheduler@*":
+ version "0.16.2"
+ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39"
+ integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==
+
+"@types/serve-index@^1.9.1":
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278"
+ integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg==
+ dependencies:
+ "@types/express" "*"
+
+"@types/serve-static@*", "@types/serve-static@^1.13.10":
+ version "1.13.10"
+ resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9"
+ integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==
+ dependencies:
+ "@types/mime" "^1"
+ "@types/node" "*"
+
+"@types/sockjs@^0.3.33":
+ version "0.3.33"
+ resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f"
+ integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw==
+ dependencies:
+ "@types/node" "*"
+
+"@types/stack-utils@^2.0.0":
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c"
+ integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw==
+
+"@types/testing-library__jest-dom@^5.9.1":
+ version "5.14.3"
+ resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.3.tgz#ee6c7ffe9f8595882ee7bda8af33ae7b8789ef17"
+ integrity sha512-oKZe+Mf4ioWlMuzVBaXQ9WDnEm1+umLx0InILg+yvZVBBDmzV5KfZyLrCvadtWcx8+916jLmHafcmqqffl+iIw==
+ dependencies:
+ "@types/jest" "*"
+
+"@types/trusted-types@^2.0.2":
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.2.tgz#fc25ad9943bcac11cceb8168db4f275e0e72e756"
+ integrity sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==
+
+"@types/ws@^8.5.1":
+ version "8.5.3"
+ resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d"
+ integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w==
+ dependencies:
+ "@types/node" "*"
+
+"@types/yargs-parser@*":
+ version "21.0.0"
+ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b"
+ integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==
+
+"@types/yargs@^15.0.0":
+ version "15.0.14"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.14.tgz#26d821ddb89e70492160b66d10a0eb6df8f6fb06"
+ integrity sha512-yEJzHoxf6SyQGhBhIYGXQDSCkJjB6HohDShto7m8vaKg9Yp0Yn8+71J9eakh2bnPg6BfsH9PRMhiRTZnd4eXGQ==
+ dependencies:
+ "@types/yargs-parser" "*"
+
+"@types/yargs@^16.0.0":
+ version "16.0.4"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz#26aad98dd2c2a38e421086ea9ad42b9e51642977"
+ integrity sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==
+ dependencies:
+ "@types/yargs-parser" "*"
+
+"@types/yargs@^17.0.8":
+ version "17.0.10"
+ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.10.tgz#591522fce85d8739bca7b8bb90d048e4478d186a"
+ integrity sha512-gmEaFwpj/7f/ROdtIlci1R1VYU1J4j95m8T+Tj3iBgiBFKg1foE/PSl93bBd5T9LDXNPo8UlNN6W0qwD8O5OaA==
+ dependencies:
+ "@types/yargs-parser" "*"
+
+"@typescript-eslint/eslint-plugin@^5.5.0":
+ version "5.27.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.27.1.tgz#fdf59c905354139046b41b3ed95d1609913d0758"
+ integrity sha512-6dM5NKT57ZduNnJfpY81Phe9nc9wolnMCnknb1im6brWi1RYv84nbMS3olJa27B6+irUVV1X/Wb+Am0FjJdGFw==
+ dependencies:
+ "@typescript-eslint/scope-manager" "5.27.1"
+ "@typescript-eslint/type-utils" "5.27.1"
+ "@typescript-eslint/utils" "5.27.1"
+ debug "^4.3.4"
+ functional-red-black-tree "^1.0.1"
+ ignore "^5.2.0"
+ regexpp "^3.2.0"
+ semver "^7.3.7"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/experimental-utils@^5.0.0":
+ version "5.27.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.27.1.tgz#c5c5121a75cf875bfae8083c50f5ae7bfde6145a"
+ integrity sha512-Vd8uewIixGP93sEnmTRIH6jHZYRQRkGPDPpapACMvitJKX8335VHNyqKTE+mZ+m3E2c5VznTZfSsSsS5IF7vUA==
+ dependencies:
+ "@typescript-eslint/utils" "5.27.1"
+
+"@typescript-eslint/parser@^5.5.0":
+ version "5.27.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.27.1.tgz#3a4dcaa67e45e0427b6ca7bb7165122c8b569639"
+ integrity sha512-7Va2ZOkHi5NP+AZwb5ReLgNF6nWLGTeUJfxdkVUAPPSaAdbWNnFZzLZ4EGGmmiCTg+AwlbE1KyUYTBglosSLHQ==
+ dependencies:
+ "@typescript-eslint/scope-manager" "5.27.1"
+ "@typescript-eslint/types" "5.27.1"
+ "@typescript-eslint/typescript-estree" "5.27.1"
+ debug "^4.3.4"
+
+"@typescript-eslint/scope-manager@5.27.1":
+ version "5.27.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.27.1.tgz#4d1504392d01fe5f76f4a5825991ec78b7b7894d"
+ integrity sha512-fQEOSa/QroWE6fAEg+bJxtRZJTH8NTskggybogHt4H9Da8zd4cJji76gA5SBlR0MgtwF7rebxTbDKB49YUCpAg==
+ dependencies:
+ "@typescript-eslint/types" "5.27.1"
+ "@typescript-eslint/visitor-keys" "5.27.1"
+
+"@typescript-eslint/type-utils@5.27.1":
+ version "5.27.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.27.1.tgz#369f695199f74c1876e395ebea202582eb1d4166"
+ integrity sha512-+UC1vVUWaDHRnC2cQrCJ4QtVjpjjCgjNFpg8b03nERmkHv9JV9X5M19D7UFMd+/G7T/sgFwX2pGmWK38rqyvXw==
+ dependencies:
+ "@typescript-eslint/utils" "5.27.1"
+ debug "^4.3.4"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/types@5.27.1":
+ version "5.27.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.27.1.tgz#34e3e629501349d38be6ae97841298c03a6ffbf1"
+ integrity sha512-LgogNVkBhCTZU/m8XgEYIWICD6m4dmEDbKXESCbqOXfKZxRKeqpiJXQIErv66sdopRKZPo5l32ymNqibYEH/xg==
+
+"@typescript-eslint/typescript-estree@5.27.1":
+ version "5.27.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.27.1.tgz#7621ee78607331821c16fffc21fc7a452d7bc808"
+ integrity sha512-DnZvvq3TAJ5ke+hk0LklvxwYsnXpRdqUY5gaVS0D4raKtbznPz71UJGnPTHEFo0GDxqLOLdMkkmVZjSpET1hFw==
+ dependencies:
+ "@typescript-eslint/types" "5.27.1"
+ "@typescript-eslint/visitor-keys" "5.27.1"
+ debug "^4.3.4"
+ globby "^11.1.0"
+ is-glob "^4.0.3"
+ semver "^7.3.7"
+ tsutils "^3.21.0"
+
+"@typescript-eslint/utils@5.27.1", "@typescript-eslint/utils@^5.13.0":
+ version "5.27.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.27.1.tgz#b4678b68a94bc3b85bf08f243812a6868ac5128f"
+ integrity sha512-mZ9WEn1ZLDaVrhRaYgzbkXBkTPghPFsup8zDbbsYTxC5OmqrFE7skkKS/sraVsLP3TcT3Ki5CSyEFBRkLH/H/w==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ "@typescript-eslint/scope-manager" "5.27.1"
+ "@typescript-eslint/types" "5.27.1"
+ "@typescript-eslint/typescript-estree" "5.27.1"
+ eslint-scope "^5.1.1"
+ eslint-utils "^3.0.0"
+
+"@typescript-eslint/visitor-keys@5.27.1":
+ version "5.27.1"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.27.1.tgz#05a62666f2a89769dac2e6baa48f74e8472983af"
+ integrity sha512-xYs6ffo01nhdJgPieyk7HAOpjhTsx7r/oB9LWEhwAXgwn33tkr+W8DI2ChboqhZlC4q3TC6geDYPoiX8ROqyOQ==
+ dependencies:
+ "@typescript-eslint/types" "5.27.1"
+ eslint-visitor-keys "^3.3.0"
+
+"@webassemblyjs/ast@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7"
+ integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==
+ dependencies:
+ "@webassemblyjs/helper-numbers" "1.11.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.1"
+
+"@webassemblyjs/floating-point-hex-parser@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f"
+ integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==
+
+"@webassemblyjs/helper-api-error@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16"
+ integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==
+
+"@webassemblyjs/helper-buffer@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5"
+ integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==
+
+"@webassemblyjs/helper-numbers@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae"
+ integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==
+ dependencies:
+ "@webassemblyjs/floating-point-hex-parser" "1.11.1"
+ "@webassemblyjs/helper-api-error" "1.11.1"
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/helper-wasm-bytecode@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1"
+ integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==
+
+"@webassemblyjs/helper-wasm-section@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a"
+ integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.1"
+ "@webassemblyjs/helper-buffer" "1.11.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.1"
+ "@webassemblyjs/wasm-gen" "1.11.1"
+
+"@webassemblyjs/ieee754@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614"
+ integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==
+ dependencies:
+ "@xtuc/ieee754" "^1.2.0"
+
+"@webassemblyjs/leb128@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5"
+ integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==
+ dependencies:
+ "@xtuc/long" "4.2.2"
+
+"@webassemblyjs/utf8@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff"
+ integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==
+
+"@webassemblyjs/wasm-edit@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6"
+ integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.1"
+ "@webassemblyjs/helper-buffer" "1.11.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.1"
+ "@webassemblyjs/helper-wasm-section" "1.11.1"
+ "@webassemblyjs/wasm-gen" "1.11.1"
+ "@webassemblyjs/wasm-opt" "1.11.1"
+ "@webassemblyjs/wasm-parser" "1.11.1"
+ "@webassemblyjs/wast-printer" "1.11.1"
+
+"@webassemblyjs/wasm-gen@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76"
+ integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.1"
+ "@webassemblyjs/ieee754" "1.11.1"
+ "@webassemblyjs/leb128" "1.11.1"
+ "@webassemblyjs/utf8" "1.11.1"
+
+"@webassemblyjs/wasm-opt@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2"
+ integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.1"
+ "@webassemblyjs/helper-buffer" "1.11.1"
+ "@webassemblyjs/wasm-gen" "1.11.1"
+ "@webassemblyjs/wasm-parser" "1.11.1"
+
+"@webassemblyjs/wasm-parser@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199"
+ integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.1"
+ "@webassemblyjs/helper-api-error" "1.11.1"
+ "@webassemblyjs/helper-wasm-bytecode" "1.11.1"
+ "@webassemblyjs/ieee754" "1.11.1"
+ "@webassemblyjs/leb128" "1.11.1"
+ "@webassemblyjs/utf8" "1.11.1"
+
+"@webassemblyjs/wast-printer@1.11.1":
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0"
+ integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==
+ dependencies:
+ "@webassemblyjs/ast" "1.11.1"
+ "@xtuc/long" "4.2.2"
+
+"@xtuc/ieee754@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790"
+ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==
+
+"@xtuc/long@4.2.2":
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
+ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
+
+abab@^2.0.3, abab@^2.0.5:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
+ integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
+
+accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
+ integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
+ dependencies:
+ mime-types "~2.1.34"
+ negotiator "0.6.3"
+
+acorn-globals@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45"
+ integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==
+ dependencies:
+ acorn "^7.1.1"
+ acorn-walk "^7.1.1"
+
+acorn-import-assertions@^1.7.6:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9"
+ integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==
+
+acorn-jsx@^5.3.2:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
+ integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
+
+acorn-node@^1.8.2:
+ version "1.8.2"
+ resolved "https://registry.yarnpkg.com/acorn-node/-/acorn-node-1.8.2.tgz#114c95d64539e53dede23de8b9d96df7c7ae2af8"
+ integrity sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==
+ dependencies:
+ acorn "^7.0.0"
+ acorn-walk "^7.0.0"
+ xtend "^4.0.2"
+
+acorn-walk@^7.0.0, acorn-walk@^7.1.1:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
+ integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
+
+acorn@^7.0.0, acorn@^7.1.1:
+ version "7.4.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
+ integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
+
+acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1:
+ version "8.7.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30"
+ integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==
+
+address@^1.0.1, address@^1.1.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/address/-/address-1.2.0.tgz#d352a62c92fee90f89a693eccd2a8b2139ab02d9"
+ integrity sha512-tNEZYz5G/zYunxFm7sfhAxkXEuLj3K6BKwv6ZURlsF6yiUQ65z0Q2wZW9L5cPUl9ocofGvXOdFYbFHp0+6MOig==
+
+adjust-sourcemap-loader@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz#fc4a0fd080f7d10471f30a7320f25560ade28c99"
+ integrity sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==
+ dependencies:
+ loader-utils "^2.0.0"
+ regex-parser "^2.2.11"
+
+agent-base@6:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
+ integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
+ dependencies:
+ debug "4"
+
+ajv-formats@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
+ integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==
+ dependencies:
+ ajv "^8.0.0"
+
+ajv-keywords@^3.4.1, ajv-keywords@^3.5.2:
+ version "3.5.2"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
+ integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==
+
+ajv-keywords@^5.0.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16"
+ integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==
+ dependencies:
+ fast-deep-equal "^3.1.3"
+
+ajv@^6.10.0, ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ 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"
+
+ajv@^8.0.0, ajv@^8.6.0, ajv@^8.8.0:
+ version "8.11.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f"
+ integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ json-schema-traverse "^1.0.0"
+ require-from-string "^2.0.2"
+ uri-js "^4.2.2"
+
+ansi-escapes@^4.2.1, ansi-escapes@^4.3.1:
+ version "4.3.2"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
+ integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
+ dependencies:
+ type-fest "^0.21.3"
+
+ansi-html-community@^0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/ansi-html-community/-/ansi-html-community-0.0.8.tgz#69fbc4d6ccbe383f9736934ae34c3f8290f1bf41"
+ integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
+
+ansi-regex@^5.0.0, ansi-regex@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+ integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
+ansi-regex@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
+ integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
+
+ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ dependencies:
+ color-convert "^1.9.0"
+
+ansi-styles@^4.0.0, ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
+ansi-styles@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
+ integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
+
+anymatch@^3.0.3, anymatch@~3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716"
+ integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+arg@^5.0.1:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
+ integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
+
+argparse@^1.0.7:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
+ integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==
+ dependencies:
+ sprintf-js "~1.0.2"
+
+argparse@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
+aria-query@^4.2.2:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b"
+ integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA==
+ dependencies:
+ "@babel/runtime" "^7.10.2"
+ "@babel/runtime-corejs3" "^7.10.2"
+
+aria-query@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.0.0.tgz#210c21aaf469613ee8c9a62c7f86525e058db52c"
+ integrity sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==
+
+array-flatten@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
+ integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==
+
+array-flatten@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099"
+ integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==
+
+array-includes@^3.1.4, array-includes@^3.1.5:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.5.tgz#2c320010db8d31031fd2a5f6b3bbd4b1aad31bdb"
+ integrity sha512-iSDYZMMyTPkiFasVqfuAQnWAYcvO/SeBSCGKePoEthjp4LEMTe4uLc7b025o4jAZpHhihh8xPo99TNWUWWkGDQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
+ get-intrinsic "^1.1.1"
+ is-string "^1.0.7"
+
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+array.prototype.flat@^1.2.5:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.0.tgz#0b0c1567bf57b38b56b4c97b8aa72ab45e4adc7b"
+ integrity sha512-12IUEkHsAhA4DY5s0FPgNXIdc8VRSqD9Zp78a5au9abH/SOBrsp082JOWFNTjkMozh8mqcdiKuaLGhPeYztxSw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.2"
+ es-shim-unscopables "^1.0.0"
+
+array.prototype.flatmap@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.0.tgz#a7e8ed4225f4788a70cd910abcf0791e76a5534f"
+ integrity sha512-PZC9/8TKAIxcWKdyeb77EzULHPrIX/tIZebLJUQOMR1OwYosT8yggdfWScfTBCDj5utONvOuPQQumYsU2ULbkg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.2"
+ es-shim-unscopables "^1.0.0"
+
+array.prototype.reduce@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz#8167e80089f78bff70a99e20bd4201d4663b0a6f"
+ integrity sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.2"
+ es-array-method-boxes-properly "^1.0.0"
+ is-string "^1.0.7"
+
+asap@~2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
+ integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
+
+ast-types-flow@^0.0.7:
+ version "0.0.7"
+ resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad"
+ integrity sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==
+
+async@^3.2.3:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
+ integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
+at-least-node@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2"
+ integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==
+
+atob@^2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
+ integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
+
+autoprefixer@^10.4.7:
+ version "10.4.7"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.7.tgz#1db8d195f41a52ca5069b7593be167618edbbedf"
+ integrity sha512-ypHju4Y2Oav95SipEcCcI5J7CGPuvz8oat7sUtYj3ClK44bldfvtvcxK6IEK++7rqB7YchDGzweZIBG+SD0ZAA==
+ dependencies:
+ browserslist "^4.20.3"
+ caniuse-lite "^1.0.30001335"
+ fraction.js "^4.2.0"
+ normalize-range "^0.1.2"
+ picocolors "^1.0.0"
+ postcss-value-parser "^4.2.0"
+
+axe-core@^4.3.5:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.4.2.tgz#dcf7fb6dea866166c3eab33d68208afe4d5f670c"
+ integrity sha512-LVAaGp/wkkgYJcjmHsoKx4juT1aQvJyPcW09MLCjVTh3V2cc6PnyempiLMNH5iMdfIX/zdbjUx2KDjMLCTdPeA==
+
+axobject-query@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be"
+ integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA==
+
+babel-jest@^27.4.2, babel-jest@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.5.1.tgz#a1bf8d61928edfefd21da27eb86a695bfd691444"
+ integrity sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==
+ dependencies:
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/babel__core" "^7.1.14"
+ babel-plugin-istanbul "^6.1.1"
+ babel-preset-jest "^27.5.1"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ slash "^3.0.0"
+
+babel-loader@^8.2.3:
+ version "8.2.5"
+ resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e"
+ integrity sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ==
+ dependencies:
+ find-cache-dir "^3.3.1"
+ loader-utils "^2.0.0"
+ make-dir "^3.1.0"
+ schema-utils "^2.6.5"
+
+babel-plugin-dynamic-import-node@^2.3.3:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3"
+ integrity sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==
+ dependencies:
+ object.assign "^4.1.0"
+
+babel-plugin-istanbul@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73"
+ integrity sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==
+ dependencies:
+ "@babel/helper-plugin-utils" "^7.0.0"
+ "@istanbuljs/load-nyc-config" "^1.0.0"
+ "@istanbuljs/schema" "^0.1.2"
+ istanbul-lib-instrument "^5.0.4"
+ test-exclude "^6.0.0"
+
+babel-plugin-jest-hoist@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-27.5.1.tgz#9be98ecf28c331eb9f5df9c72d6f89deb8181c2e"
+ integrity sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==
+ dependencies:
+ "@babel/template" "^7.3.3"
+ "@babel/types" "^7.3.3"
+ "@types/babel__core" "^7.0.0"
+ "@types/babel__traverse" "^7.0.6"
+
+babel-plugin-macros@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1"
+ integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
+ dependencies:
+ "@babel/runtime" "^7.12.5"
+ cosmiconfig "^7.0.0"
+ resolve "^1.19.0"
+
+babel-plugin-named-asset-import@^0.3.8:
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/babel-plugin-named-asset-import/-/babel-plugin-named-asset-import-0.3.8.tgz#6b7fa43c59229685368683c28bc9734f24524cc2"
+ integrity sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==
+
+babel-plugin-polyfill-corejs2@^0.3.0:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.1.tgz#440f1b70ccfaabc6b676d196239b138f8a2cfba5"
+ integrity sha512-v7/T6EQcNfVLfcN2X8Lulb7DjprieyLWJK/zOWH5DUYcAgex9sP3h25Q+DLsX9TloXe3y1O8l2q2Jv9q8UVB9w==
+ dependencies:
+ "@babel/compat-data" "^7.13.11"
+ "@babel/helper-define-polyfill-provider" "^0.3.1"
+ semver "^6.1.1"
+
+babel-plugin-polyfill-corejs3@^0.5.0:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.2.tgz#aabe4b2fa04a6e038b688c5e55d44e78cd3a5f72"
+ integrity sha512-G3uJih0XWiID451fpeFaYGVuxHEjzKTHtc9uGFEjR6hHrvNzeS/PX+LLLcetJcytsB5m4j+K3o/EpXJNb/5IEQ==
+ dependencies:
+ "@babel/helper-define-polyfill-provider" "^0.3.1"
+ core-js-compat "^3.21.0"
+
+babel-plugin-polyfill-regenerator@^0.3.0:
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.1.tgz#2c0678ea47c75c8cc2fbb1852278d8fb68233990"
+ integrity sha512-Y2B06tvgHYt1x0yz17jGkGeeMr5FeKUu+ASJ+N6nB5lQ8Dapfg42i0OVrf8PNGJ3zKL4A23snMi1IRwrqqND7A==
+ dependencies:
+ "@babel/helper-define-polyfill-provider" "^0.3.1"
+
+babel-plugin-transform-react-remove-prop-types@^0.4.24:
+ version "0.4.24"
+ resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a"
+ integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==
+
+babel-preset-current-node-syntax@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b"
+ integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==
+ dependencies:
+ "@babel/plugin-syntax-async-generators" "^7.8.4"
+ "@babel/plugin-syntax-bigint" "^7.8.3"
+ "@babel/plugin-syntax-class-properties" "^7.8.3"
+ "@babel/plugin-syntax-import-meta" "^7.8.3"
+ "@babel/plugin-syntax-json-strings" "^7.8.3"
+ "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3"
+ "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
+ "@babel/plugin-syntax-numeric-separator" "^7.8.3"
+ "@babel/plugin-syntax-object-rest-spread" "^7.8.3"
+ "@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
+ "@babel/plugin-syntax-optional-chaining" "^7.8.3"
+ "@babel/plugin-syntax-top-level-await" "^7.8.3"
+
+babel-preset-jest@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-27.5.1.tgz#91f10f58034cb7989cb4f962b69fa6eef6a6bc81"
+ integrity sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==
+ dependencies:
+ babel-plugin-jest-hoist "^27.5.1"
+ babel-preset-current-node-syntax "^1.0.0"
+
+babel-preset-react-app@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz#ed6005a20a24f2c88521809fa9aea99903751584"
+ integrity sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg==
+ dependencies:
+ "@babel/core" "^7.16.0"
+ "@babel/plugin-proposal-class-properties" "^7.16.0"
+ "@babel/plugin-proposal-decorators" "^7.16.4"
+ "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.0"
+ "@babel/plugin-proposal-numeric-separator" "^7.16.0"
+ "@babel/plugin-proposal-optional-chaining" "^7.16.0"
+ "@babel/plugin-proposal-private-methods" "^7.16.0"
+ "@babel/plugin-transform-flow-strip-types" "^7.16.0"
+ "@babel/plugin-transform-react-display-name" "^7.16.0"
+ "@babel/plugin-transform-runtime" "^7.16.4"
+ "@babel/preset-env" "^7.16.4"
+ "@babel/preset-react" "^7.16.0"
+ "@babel/preset-typescript" "^7.16.0"
+ "@babel/runtime" "^7.16.3"
+ babel-plugin-macros "^3.1.0"
+ babel-plugin-transform-react-remove-prop-types "^0.4.24"
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+batch@0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
+ integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==
+
+bfj@^7.0.2:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/bfj/-/bfj-7.0.2.tgz#1988ce76f3add9ac2913fd8ba47aad9e651bfbb2"
+ integrity sha512-+e/UqUzwmzJamNF50tBV6tZPTORow7gQ96iFow+8b562OdMpEK0BcJEq2OSPEDmAbSMBQ7PKZ87ubFkgxpYWgw==
+ dependencies:
+ bluebird "^3.5.5"
+ check-types "^11.1.1"
+ hoopy "^0.1.4"
+ tryer "^1.0.1"
+
+big.js@^5.2.2:
+ version "5.2.2"
+ resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
+ integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
+
+binary-extensions@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
+ integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
+
+bluebird@^3.5.5:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
+ integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==
+
+body-parser@1.20.0:
+ version "1.20.0"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5"
+ integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg==
+ dependencies:
+ bytes "3.1.2"
+ content-type "~1.0.4"
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ http-errors "2.0.0"
+ iconv-lite "0.4.24"
+ on-finished "2.4.1"
+ qs "6.10.3"
+ raw-body "2.5.1"
+ type-is "~1.6.18"
+ unpipe "1.0.0"
+
+bonjour-service@^1.0.11:
+ version "1.0.13"
+ resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.0.13.tgz#4ac003dc1626023252d58adf2946f57e5da450c1"
+ integrity sha512-LWKRU/7EqDUC9CTAQtuZl5HzBALoCYwtLhffW3et7vZMwv3bWLpJf8bRYlMD5OCcDpTfnPgNCV4yo9ZIaJGMiA==
+ dependencies:
+ array-flatten "^2.1.2"
+ dns-equal "^1.0.0"
+ fast-deep-equal "^3.1.3"
+ multicast-dns "^7.2.5"
+
+boolbase@^1.0.0, boolbase@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
+ integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+brace-expansion@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
+ integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
+ dependencies:
+ balanced-match "^1.0.0"
+
+braces@^3.0.2, braces@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+browser-process-hrtime@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
+ integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
+
+browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.18.1, browserslist@^4.20.2, browserslist@^4.20.3:
+ version "4.20.4"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.4.tgz#98096c9042af689ee1e0271333dbc564b8ce4477"
+ integrity sha512-ok1d+1WpnU24XYN7oC3QWgTyMhY/avPJ/r9T00xxvUOIparA/gc+UPUMaod3i+G6s+nI2nUb9xZ5k794uIwShw==
+ dependencies:
+ caniuse-lite "^1.0.30001349"
+ electron-to-chromium "^1.4.147"
+ escalade "^3.1.1"
+ node-releases "^2.0.5"
+ picocolors "^1.0.0"
+
+bser@2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05"
+ integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==
+ dependencies:
+ node-int64 "^0.4.0"
+
+buffer-from@^1.0.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
+ integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
+
+builtin-modules@^3.1.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
+ integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==
+
+bytes@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
+ integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==
+
+bytes@3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
+ integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
+
+call-bind@^1.0.0, call-bind@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
+ integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
+ dependencies:
+ function-bind "^1.1.1"
+ get-intrinsic "^1.0.2"
+
+callsites@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+ integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+camel-case@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-4.1.2.tgz#9728072a954f805228225a6deea6b38461e1bd5a"
+ integrity sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==
+ dependencies:
+ pascal-case "^3.1.2"
+ tslib "^2.0.3"
+
+camelcase-css@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
+ integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
+
+camelcase@^5.3.1:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
+ integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+
+camelcase@^6.2.0, camelcase@^6.2.1:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a"
+ integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
+
+caniuse-api@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
+ integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==
+ dependencies:
+ browserslist "^4.0.0"
+ caniuse-lite "^1.0.0"
+ lodash.memoize "^4.1.2"
+ lodash.uniq "^4.5.0"
+
+caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001335, caniuse-lite@^1.0.30001349:
+ version "1.0.30001352"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001352.tgz#cc6f5da3f983979ad1e2cdbae0505dccaa7c6a12"
+ integrity sha512-GUgH8w6YergqPQDGWhJGt8GDRnY0L/iJVQcU3eJ46GYf52R8tk0Wxp0PymuFVZboJYXGiCqwozAYZNRjVj6IcA==
+
+case-sensitive-paths-webpack-plugin@^2.4.0:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz#db64066c6422eed2e08cc14b986ca43796dbc6d4"
+ integrity sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==
+
+chalk@^2.0.0, chalk@^2.4.1:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+chalk@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
+ integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+char-regex@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
+ integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==
+
+char-regex@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-2.0.1.tgz#6dafdb25f9d3349914079f010ba8d0e6ff9cd01e"
+ integrity sha512-oSvEeo6ZUD7NepqAat3RqoucZ5SeqLJgOvVIwkafu6IP3V0pO38s/ypdVUmDDK6qIIHNlYHJAKX9E7R7HoKElw==
+
+charcodes@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/charcodes/-/charcodes-0.2.0.tgz#5208d327e6cc05f99eb80ffc814707572d1f14e4"
+ integrity sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ==
+
+chart.js@^3.7.1:
+ version "3.8.0"
+ resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.8.0.tgz#c6c14c457b9dc3ce7f1514a59e9b262afd6f1a94"
+ integrity sha512-cr8xhrXjLIXVLOBZPkBZVF6NDeiVIrPLHcMhnON7UufudL+CNeRrD+wpYanswlm8NpudMdrt3CHoLMQMxJhHRg==
+
+chartjs-plugin-annotation@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/chartjs-plugin-annotation/-/chartjs-plugin-annotation-1.4.0.tgz#4c84cec1ec838bc09712f3686237866e6c3f4798"
+ integrity sha512-OC0eGoVvdxTtGGi8mV3Dr+G1YmMhtYYQWqGMb2uWcgcnyiBslaRKPofKwAYWPbh7ABnmQNsNDQLIKPH+XiaZLA==
+
+chartjs-plugin-crosshair@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/chartjs-plugin-crosshair/-/chartjs-plugin-crosshair-1.2.0.tgz#54c8223ed40db4a5c380f17967fcf1a11cb2a284"
+ integrity sha512-yohsbME+wT1ODBdErBzWnC6xUDcn2tLeWmGjGDTykjpiT7+FMgibffajxqaCVmdzselxNPirpt76vx33EewSSQ==
+
+check-types@^11.1.1:
+ version "11.1.2"
+ resolved "https://registry.yarnpkg.com/check-types/-/check-types-11.1.2.tgz#86a7c12bf5539f6324eb0e70ca8896c0e38f3e2f"
+ integrity sha512-tzWzvgePgLORb9/3a0YenggReLKAIb2owL03H2Xdoe5pKcUyWRSEQ8xfCar8t2SIAuEDwtmx2da1YB52YuHQMQ==
+
+chokidar@^3.4.2, chokidar@^3.5.3:
+ version "3.5.3"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
+ integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
+ dependencies:
+ anymatch "~3.1.2"
+ braces "~3.0.2"
+ glob-parent "~5.1.2"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.6.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+chrome-trace-event@^1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac"
+ integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==
+
+ci-info@^3.2.0:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.3.1.tgz#58331f6f472a25fe3a50a351ae3052936c2c7f32"
+ integrity sha512-SXgeMX9VwDe7iFFaEWkA5AstuER9YKqy4EhHqr4DVqkwmD9rpVimkMKWHdjn30Ja45txyjhSn63lVX69eVCckg==
+
+cjs-module-lexer@^1.0.0:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz#9f84ba3244a512f3a54e5277e8eef4c489864e40"
+ integrity sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==
+
+classcat@^5.0.3:
+ version "5.0.3"
+ resolved "https://registry.yarnpkg.com/classcat/-/classcat-5.0.3.tgz#38eaa0ec6eb1b10faf101bbcef2afb319c23c17b"
+ integrity sha512-6dK2ke4VEJZOFx2ZfdDAl5OhEL8lvkl6EHF92IfRePfHxQTqir5NlcNVUv+2idjDqCX2NDc8m8YSAI5NI975ZQ==
+
+classnames@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
+ integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
+
+clean-css@^5.2.2:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.0.tgz#ad3d8238d5f3549e83d5f87205189494bc7cbb59"
+ integrity sha512-YYuuxv4H/iNb1Z/5IbMRoxgrzjWGhOEFfd+groZ5dMCVkpENiMZmwspdrzBo9286JjM1gZJPAyL7ZIdzuvu2AQ==
+ dependencies:
+ source-map "~0.6.0"
+
+cliui@^7.0.2:
+ version "7.0.4"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
+ integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.0"
+ wrap-ansi "^7.0.0"
+
+clsx@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
+ integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==
+
+co@^4.6.0:
+ version "4.6.0"
+ resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
+ integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==
+
+coa@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3"
+ integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==
+ dependencies:
+ "@types/q" "^1.5.1"
+ chalk "^2.4.1"
+ q "^1.1.2"
+
+collect-v8-coverage@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
+ integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==
+
+color-convert@^1.9.0:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+ dependencies:
+ color-name "1.1.3"
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+ integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
+
+color-name@^1.1.4, color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+color-scheme@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/color-scheme/-/color-scheme-1.0.1.tgz#d1de417f65e10f73c0eb2c97f7ed6c156bc6e8f5"
+ integrity sha512-4x+ya6+z6g9DaTFSfVzTZc8TSjxHuDT40NB43N3XPUkQlF6uujhwH8aeMeq8HBgoQQog/vrYgJ16mt/eVTRXwQ==
+
+colord@^2.9.1:
+ version "2.9.2"
+ resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.2.tgz#25e2bacbbaa65991422c07ea209e2089428effb1"
+ integrity sha512-Uqbg+J445nc1TKn4FoDPS6ZZqAvEDnwrH42yo8B40JSOgSLxMZ/gt3h4nmCtPLQeXhjJJkqBx7SCY35WnIixaQ==
+
+colorette@^2.0.10:
+ version "2.0.17"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.17.tgz#5dd4c0d15e2984b7433cb4a9f2ead45063b80c47"
+ integrity sha512-hJo+3Bkn0NCHybn9Tu35fIeoOKGOk5OCC32y4Hz2It+qlCO2Q3DeQ1hRn/tDDMQKRYUEzqsl7jbF6dYKjlE60g==
+
+combined-stream@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+commander@^2.20.0:
+ version "2.20.3"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
+ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
+
+commander@^7.2.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
+ integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
+
+commander@^8.3.0:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
+ integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==
+
+common-path-prefix@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/common-path-prefix/-/common-path-prefix-3.0.0.tgz#7d007a7e07c58c4b4d5f433131a19141b29f11e0"
+ integrity sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==
+
+common-tags@^1.8.0:
+ version "1.8.2"
+ resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6"
+ integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==
+
+commondir@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
+ integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
+
+compressible@~2.0.16:
+ version "2.0.18"
+ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
+ integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
+ dependencies:
+ mime-db ">= 1.43.0 < 2"
+
+compression@^1.7.4:
+ version "1.7.4"
+ resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
+ integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
+ dependencies:
+ accepts "~1.3.5"
+ bytes "3.0.0"
+ compressible "~2.0.16"
+ debug "2.6.9"
+ on-headers "~1.0.2"
+ safe-buffer "5.1.2"
+ vary "~1.1.2"
+
+compute-iqr@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/compute-iqr/-/compute-iqr-1.1.0.tgz#2eaae69dca6ff810b3fe8f05f0c646c0198cee67"
+ integrity sha512-oDAFGG4Oin5Kwkd+QB6dvBKN+3MJmFliB4EhABxdKjEgZftUdQh9zj6oKsZtY+aLvgiftK8X0Sk0Fhs71rJBHQ==
+ dependencies:
+ compute-quantile "^1.0.0"
+ validate.io-object "^1.0.0"
+
+compute-quantile@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/compute-quantile/-/compute-quantile-1.0.1.tgz#30723bac616d9cc5e27c0e0775a9d3567dfbad66"
+ integrity sha512-0o7szTa9QIs/1ZFdGwfS4gmo9df5elEGyLh+hpr1Ap1gsWQtNPHqChfJGR3Kt8swxqkgOUuUERnmVy0Zd7x2+Q==
+ dependencies:
+ validate.io-object "^1.0.0"
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+confusing-browser-globals@^1.0.11:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz#ae40e9b57cdd3915408a2805ebd3a5585608dc81"
+ integrity sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==
+
+connect-history-api-fallback@^1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc"
+ integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
+
+content-disposition@0.5.4:
+ version "0.5.4"
+ resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
+ integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
+ dependencies:
+ safe-buffer "5.2.1"
+
+content-type@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
+ integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==
+
+convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369"
+ integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==
+ dependencies:
+ safe-buffer "~5.1.1"
+
+convert-source-map@^1.5.0:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f"
+ integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
+
+cookie-signature@1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c"
+ integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==
+
+cookie@0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b"
+ integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==
+
+core-js-compat@^3.21.0, core-js-compat@^3.22.1:
+ version "3.22.8"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.22.8.tgz#46fa34ce1ddf742acd7f95f575f66bbb21e05d62"
+ integrity sha512-pQnwg4xtuvc2Bs/5zYQPaEYYSuTxsF7LBWF0SvnVhthZo/Qe+rJpcEekrdNK5DWwDJ0gv0oI9NNX5Mppdy0ctg==
+ dependencies:
+ browserslist "^4.20.3"
+ semver "7.0.0"
+
+core-js-pure@^3.20.2, core-js-pure@^3.8.1:
+ version "3.22.8"
+ resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.22.8.tgz#f2157793b58719196ccf9673cc14f3683adc0957"
+ integrity sha512-bOxbZIy9S5n4OVH63XaLVXZ49QKicjowDx/UELyJ68vxfCRpYsbyh/WNZNfEfAk+ekA8vSjt+gCDpvh672bc3w==
+
+core-js@^3.19.2:
+ version "3.22.8"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.22.8.tgz#23f860b1fe60797cc4f704d76c93fea8a2f60631"
+ integrity sha512-UoGQ/cfzGYIuiq6Z7vWL1HfkE9U9IZ4Ub+0XSiJTCzvbZzgPA69oDF2f+lgJ6dFFLEdjW5O6svvoKzXX23xFkA==
+
+core-util-is@~1.0.0:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
+ integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
+
+cosmiconfig@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982"
+ integrity sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==
+ dependencies:
+ "@types/parse-json" "^4.0.0"
+ import-fresh "^3.1.0"
+ parse-json "^5.0.0"
+ path-type "^4.0.0"
+ yaml "^1.7.2"
+
+cosmiconfig@^7.0.0:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d"
+ integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==
+ dependencies:
+ "@types/parse-json" "^4.0.0"
+ import-fresh "^3.2.1"
+ parse-json "^5.0.0"
+ path-type "^4.0.0"
+ yaml "^1.10.0"
+
+cross-spawn@^7.0.2, cross-spawn@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+ integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+crypto-random-string@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
+ integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
+
+css-blank-pseudo@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz#36523b01c12a25d812df343a32c322d2a2324561"
+ integrity sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+
+css-declaration-sorter@^6.2.2:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.3.0.tgz#72ebd995c8f4532ff0036631f7365cce9759df14"
+ integrity sha512-OGT677UGHJTAVMRhPO+HJ4oKln3wkBTwtDFH0ojbqm+MJm6xuDMHp2nkhh/ThaBqq20IbraBQSWKfSLNHQO9Og==
+
+css-has-pseudo@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz#57f6be91ca242d5c9020ee3e51bbb5b89fc7af73"
+ integrity sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+
+css-loader@^6.5.1:
+ version "6.7.1"
+ resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.1.tgz#e98106f154f6e1baf3fc3bc455cb9981c1d5fd2e"
+ integrity sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==
+ dependencies:
+ icss-utils "^5.1.0"
+ postcss "^8.4.7"
+ postcss-modules-extract-imports "^3.0.0"
+ postcss-modules-local-by-default "^4.0.0"
+ postcss-modules-scope "^3.0.0"
+ postcss-modules-values "^4.0.0"
+ postcss-value-parser "^4.2.0"
+ semver "^7.3.5"
+
+css-minimizer-webpack-plugin@^3.2.0:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz#ab78f781ced9181992fe7b6e4f3422e76429878f"
+ integrity sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==
+ dependencies:
+ cssnano "^5.0.6"
+ jest-worker "^27.0.2"
+ postcss "^8.3.5"
+ schema-utils "^4.0.0"
+ serialize-javascript "^6.0.0"
+ source-map "^0.6.1"
+
+css-prefers-color-scheme@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz#ca8a22e5992c10a5b9d315155e7caee625903349"
+ integrity sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==
+
+css-select-base-adapter@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7"
+ integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==
+
+css-select@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef"
+ integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==
+ dependencies:
+ boolbase "^1.0.0"
+ css-what "^3.2.1"
+ domutils "^1.7.0"
+ nth-check "^1.0.2"
+
+css-select@^4.1.3:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b"
+ integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==
+ dependencies:
+ boolbase "^1.0.0"
+ css-what "^6.0.1"
+ domhandler "^4.3.1"
+ domutils "^2.8.0"
+ nth-check "^2.0.1"
+
+css-tree@1.0.0-alpha.37:
+ version "1.0.0-alpha.37"
+ resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22"
+ integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==
+ dependencies:
+ mdn-data "2.0.4"
+ source-map "^0.6.1"
+
+css-tree@^1.1.2, css-tree@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d"
+ integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==
+ dependencies:
+ mdn-data "2.0.14"
+ source-map "^0.6.1"
+
+css-vendor@^2.0.8:
+ version "2.0.8"
+ resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-2.0.8.tgz#e47f91d3bd3117d49180a3c935e62e3d9f7f449d"
+ integrity sha512-x9Aq0XTInxrkuFeHKbYC7zWY8ai7qJ04Kxd9MnvbC1uO5DagxoHQjm4JvG+vCdXOoFtCjbL2XSZfxmoYa9uQVQ==
+ dependencies:
+ "@babel/runtime" "^7.8.3"
+ is-in-browser "^1.0.2"
+
+css-what@^3.2.1:
+ version "3.4.2"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.4.2.tgz#ea7026fcb01777edbde52124e21f327e7ae950e4"
+ integrity sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==
+
+css-what@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4"
+ integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==
+
+css.escape@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
+ integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==
+
+css@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d"
+ integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ==
+ dependencies:
+ inherits "^2.0.4"
+ source-map "^0.6.1"
+ source-map-resolve "^0.6.0"
+
+cssdb@^6.6.3:
+ version "6.6.3"
+ resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-6.6.3.tgz#1f331a2fab30c18d9f087301e6122a878bb1e505"
+ integrity sha512-7GDvDSmE+20+WcSMhP17Q1EVWUrLlbxxpMDqG731n8P99JhnQZHR9YvtjPvEHfjFUjvQJvdpKCjlKOX+xe4UVA==
+
+cssesc@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
+ integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+
+cssnano-preset-default@^5.2.11:
+ version "5.2.11"
+ resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.11.tgz#28350471bc1af9df14052472b61340347f453a53"
+ integrity sha512-4PadR1NtuaIK8MvLNuY7MznK4WJteldGlzCiMaaTiOUP+apeiIvUDIXykzUOoqgOOUAHrU64ncdD90NfZR3LSQ==
+ dependencies:
+ css-declaration-sorter "^6.2.2"
+ cssnano-utils "^3.1.0"
+ postcss-calc "^8.2.3"
+ postcss-colormin "^5.3.0"
+ postcss-convert-values "^5.1.2"
+ postcss-discard-comments "^5.1.2"
+ postcss-discard-duplicates "^5.1.0"
+ postcss-discard-empty "^5.1.1"
+ postcss-discard-overridden "^5.1.0"
+ postcss-merge-longhand "^5.1.5"
+ postcss-merge-rules "^5.1.2"
+ postcss-minify-font-values "^5.1.0"
+ postcss-minify-gradients "^5.1.1"
+ postcss-minify-params "^5.1.3"
+ postcss-minify-selectors "^5.2.1"
+ postcss-normalize-charset "^5.1.0"
+ postcss-normalize-display-values "^5.1.0"
+ postcss-normalize-positions "^5.1.0"
+ postcss-normalize-repeat-style "^5.1.0"
+ postcss-normalize-string "^5.1.0"
+ postcss-normalize-timing-functions "^5.1.0"
+ postcss-normalize-unicode "^5.1.0"
+ postcss-normalize-url "^5.1.0"
+ postcss-normalize-whitespace "^5.1.1"
+ postcss-ordered-values "^5.1.2"
+ postcss-reduce-initial "^5.1.0"
+ postcss-reduce-transforms "^5.1.0"
+ postcss-svgo "^5.1.0"
+ postcss-unique-selectors "^5.1.1"
+
+cssnano-utils@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861"
+ integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==
+
+cssnano@^5.0.6:
+ version "5.1.11"
+ resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.11.tgz#3bb003380718c7948ce3813493370e8946caf04b"
+ integrity sha512-2nx+O6LvewPo5EBtYrKc8762mMkZRk9cMGIOP4UlkmxHm7ObxH+zvsJJ+qLwPkUc4/yumL/qJkavYi9NlodWIQ==
+ dependencies:
+ cssnano-preset-default "^5.2.11"
+ lilconfig "^2.0.3"
+ yaml "^1.10.2"
+
+csso@^4.0.2, csso@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529"
+ integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==
+ dependencies:
+ css-tree "^1.1.2"
+
+cssom@^0.4.4:
+ version "0.4.4"
+ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10"
+ integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==
+
+cssom@~0.3.6:
+ version "0.3.8"
+ resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a"
+ integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==
+
+cssstyle@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852"
+ integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==
+ dependencies:
+ cssom "~0.3.6"
+
+csstype@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2"
+ integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==
+
+csstype@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9"
+ integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==
+
+"d3-color@1 - 3":
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2"
+ integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==
+
+"d3-dispatch@1 - 3":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e"
+ integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==
+
+"d3-drag@2 - 3", d3-drag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba"
+ integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==
+ dependencies:
+ d3-dispatch "1 - 3"
+ d3-selection "3"
+
+"d3-ease@1 - 3":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4"
+ integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==
+
+"d3-interpolate@1 - 3":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d"
+ integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==
+ dependencies:
+ d3-color "1 - 3"
+
+"d3-selection@2 - 3", d3-selection@3, d3-selection@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31"
+ integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==
+
+"d3-timer@1 - 3":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0"
+ integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==
+
+"d3-transition@2 - 3":
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f"
+ integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==
+ dependencies:
+ d3-color "1 - 3"
+ d3-dispatch "1 - 3"
+ d3-ease "1 - 3"
+ d3-interpolate "1 - 3"
+ d3-timer "1 - 3"
+
+d3-zoom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3"
+ integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==
+ dependencies:
+ d3-dispatch "1 - 3"
+ d3-drag "2 - 3"
+ d3-interpolate "1 - 3"
+ d3-selection "2 - 3"
+ d3-transition "2 - 3"
+
+damerau-levenshtein@^1.0.7:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
+ integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
+
+data-urls@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b"
+ integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==
+ dependencies:
+ abab "^2.0.3"
+ whatwg-mimetype "^2.3.0"
+ whatwg-url "^8.0.0"
+
+date-fns@^2.29.3:
+ version "2.29.3"
+ resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8"
+ integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA==
+
+dayjs@^1.11.7:
+ version "1.11.7"
+ resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.7.tgz#4b296922642f70999544d1144a2c25730fce63e2"
+ integrity sha512-+Yw9U6YO5TQohxLcIkrXBeY73WP3ejHWVvx8XCk3gxvQDCTEmS48ZrSZCKciI7Bhl/uCMyxYtE9UqRILmFphkQ==
+
+debug@2.6.9, debug@^2.6.0, debug@^2.6.9:
+ version "2.6.9"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
+ integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==
+ dependencies:
+ ms "2.0.0"
+
+debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
+debug@^3.2.7:
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+ integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+ dependencies:
+ ms "^2.1.1"
+
+decimal.js@^10.2.1:
+ version "10.3.1"
+ resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.3.1.tgz#d8c3a444a9c6774ba60ca6ad7261c3a94fd5e783"
+ integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
+
+decode-uri-component@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
+ integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==
+
+dedent@^0.7.0:
+ version "0.7.0"
+ resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
+ integrity sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==
+
+deep-is@^0.1.3, deep-is@~0.1.3:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
+ integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
+
+deepmerge@^4.2.2:
+ version "4.2.2"
+ resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
+ integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
+
+default-gateway@^6.0.3:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71"
+ integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==
+ dependencies:
+ execa "^5.0.0"
+
+define-lazy-prop@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
+ integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
+
+define-properties@^1.1.3, define-properties@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1"
+ integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==
+ dependencies:
+ has-property-descriptors "^1.0.0"
+ object-keys "^1.1.1"
+
+defined@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
+ integrity sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
+depd@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
+ integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
+
+depd@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
+ integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
+
+destroy@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015"
+ integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==
+
+detect-newline@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
+ integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
+
+detect-node@^2.0.4:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1"
+ integrity sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==
+
+detect-port-alt@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275"
+ integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==
+ dependencies:
+ address "^1.0.1"
+ debug "^2.6.0"
+
+detective@^5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/detective/-/detective-5.2.1.tgz#6af01eeda11015acb0e73f933242b70f24f91034"
+ integrity sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==
+ dependencies:
+ acorn-node "^1.8.2"
+ defined "^1.0.0"
+ minimist "^1.2.6"
+
+didyoumean@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
+ integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
+
+diff-sequences@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
+ integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==
+
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
+dlv@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
+ integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
+
+dns-equal@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
+ integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==
+
+dns-packet@^5.2.2:
+ version "5.4.0"
+ resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b"
+ integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==
+ dependencies:
+ "@leichtgewicht/ip-codec" "^2.0.1"
+
+doctrine@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
+ integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==
+ dependencies:
+ esutils "^2.0.2"
+
+doctrine@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
+ integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
+ dependencies:
+ esutils "^2.0.2"
+
+dom-accessibility-api@^0.5.6:
+ version "0.5.14"
+ resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.14.tgz#56082f71b1dc7aac69d83c4285eef39c15d93f56"
+ integrity sha512-NMt+m9zFMPZe0JcY9gN224Qvk6qLIdqex29clBvc/y75ZBX9YA9wNK3frsYvu2DI1xcCIwxwnX+TlsJ2DSOADg==
+
+dom-converter@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768"
+ integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==
+ dependencies:
+ utila "~0.4"
+
+dom-helpers@^5.0.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
+ integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
+ dependencies:
+ "@babel/runtime" "^7.8.7"
+ csstype "^3.0.2"
+
+dom-serializer@0:
+ version "0.2.2"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51"
+ integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==
+ dependencies:
+ domelementtype "^2.0.1"
+ entities "^2.0.0"
+
+dom-serializer@^1.0.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30"
+ integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==
+ dependencies:
+ domelementtype "^2.0.1"
+ domhandler "^4.2.0"
+ entities "^2.0.0"
+
+domelementtype@1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f"
+ integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==
+
+domelementtype@^2.0.1, domelementtype@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
+ integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
+
+domexception@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304"
+ integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==
+ dependencies:
+ webidl-conversions "^5.0.0"
+
+domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1:
+ version "4.3.1"
+ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c"
+ integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==
+ dependencies:
+ domelementtype "^2.2.0"
+
+dompurify@^2.0.8:
+ version "2.3.8"
+ resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.8.tgz#224fe9ae57d7ebd9a1ae1ac18c1c1ca3f532226f"
+ integrity sha512-eVhaWoVibIzqdGYjwsBWodIQIaXFSB+cKDf4cfxLMsK0xiud6SE+/WCVx/Xw/UwQsa4cS3T2eITcdtmTg2UKcw==
+
+domutils@^1.7.0:
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
+ integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==
+ dependencies:
+ dom-serializer "0"
+ domelementtype "1"
+
+domutils@^2.5.2, domutils@^2.8.0:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135"
+ integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==
+ dependencies:
+ dom-serializer "^1.0.1"
+ domelementtype "^2.2.0"
+ domhandler "^4.2.0"
+
+dot-case@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
+ integrity sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==
+ dependencies:
+ no-case "^3.0.4"
+ tslib "^2.0.3"
+
+dotenv-expand@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-5.1.0.tgz#3fbaf020bfd794884072ea26b1e9791d45a629f0"
+ integrity sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==
+
+dotenv@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81"
+ integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==
+
+duplexer@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
+ integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
+
+ee-first@1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d"
+ integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==
+
+ejs@^3.1.6:
+ version "3.1.8"
+ resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.8.tgz#758d32910c78047585c7ef1f92f9ee041c1c190b"
+ integrity sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==
+ dependencies:
+ jake "^10.8.5"
+
+electron-to-chromium@^1.4.147:
+ version "1.4.150"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.150.tgz#89f0e12505462d5df7e56c5b91aff7e1dfdd33ec"
+ integrity sha512-MP3oBer0X7ZeS9GJ0H6lmkn561UxiwOIY9TTkdxVY7lI9G6GVCKfgJaHaDcakwdKxBXA4T3ybeswH/WBIN/KTA==
+
+elkjs@^0.7.1:
+ version "0.7.1"
+ resolved "https://registry.yarnpkg.com/elkjs/-/elkjs-0.7.1.tgz#4751c5e918a4988139baf7f214e010aea22de969"
+ integrity sha512-lD86RWdh480/UuRoHhRcnv2IMkIcK6yMDEuT8TPBIbO3db4HfnVF+1lgYdQi99Ck0yb+lg5Eb46JCHI5uOsmAw==
+
+emittery@^0.10.2:
+ version "0.10.2"
+ resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.10.2.tgz#902eec8aedb8c41938c46e9385e9db7e03182933"
+ integrity sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==
+
+emittery@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860"
+ integrity sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==
+
+emoji-regex@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+ integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
+emoji-regex@^9.2.2:
+ version "9.2.2"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
+ integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
+
+emojis-list@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78"
+ integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==
+
+encodeurl@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
+ integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
+
+enhanced-resolve@^5.9.3:
+ version "5.9.3"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.9.3.tgz#44a342c012cbc473254af5cc6ae20ebd0aae5d88"
+ integrity sha512-Bq9VSor+kjvW3f9/MiiR4eE3XYgOl7/rS8lnSxbRbF3kS0B2r+Y9w5krBWxZgDxASVZbdYrn5wT4j/Wb0J9qow==
+ dependencies:
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
+
+entities@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55"
+ integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==
+
+error-ex@^1.3.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+ dependencies:
+ is-arrayish "^0.2.1"
+
+error-stack-parser@^2.0.6:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.1.4.tgz#229cb01cdbfa84440bfa91876285b94680188286"
+ integrity sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==
+ dependencies:
+ stackframe "^1.3.4"
+
+es-abstract@^1.17.2, es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.1:
+ version "1.20.1"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814"
+ integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==
+ dependencies:
+ call-bind "^1.0.2"
+ es-to-primitive "^1.2.1"
+ function-bind "^1.1.1"
+ function.prototype.name "^1.1.5"
+ get-intrinsic "^1.1.1"
+ get-symbol-description "^1.0.0"
+ has "^1.0.3"
+ has-property-descriptors "^1.0.0"
+ has-symbols "^1.0.3"
+ internal-slot "^1.0.3"
+ is-callable "^1.2.4"
+ is-negative-zero "^2.0.2"
+ is-regex "^1.1.4"
+ is-shared-array-buffer "^1.0.2"
+ is-string "^1.0.7"
+ is-weakref "^1.0.2"
+ object-inspect "^1.12.0"
+ object-keys "^1.1.1"
+ object.assign "^4.1.2"
+ regexp.prototype.flags "^1.4.3"
+ string.prototype.trimend "^1.0.5"
+ string.prototype.trimstart "^1.0.5"
+ unbox-primitive "^1.0.2"
+
+es-array-method-boxes-properly@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e"
+ integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==
+
+es-module-lexer@^0.9.0:
+ version "0.9.3"
+ resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19"
+ integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==
+
+es-shim-unscopables@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241"
+ integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==
+ dependencies:
+ has "^1.0.3"
+
+es-to-primitive@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
+ integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
+ dependencies:
+ is-callable "^1.1.4"
+ is-date-object "^1.0.1"
+ is-symbol "^1.0.2"
+
+escalade@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
+ integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+
+escape-html@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
+ integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==
+
+escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+ integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+
+escape-string-regexp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
+ integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
+
+escape-string-regexp@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
+ integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
+
+escodegen@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd"
+ integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==
+ dependencies:
+ esprima "^4.0.1"
+ estraverse "^5.2.0"
+ esutils "^2.0.2"
+ optionator "^0.8.1"
+ optionalDependencies:
+ source-map "~0.6.1"
+
+eslint-config-react-app@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-7.0.1.tgz#73ba3929978001c5c86274c017ea57eb5fa644b4"
+ integrity sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==
+ dependencies:
+ "@babel/core" "^7.16.0"
+ "@babel/eslint-parser" "^7.16.3"
+ "@rushstack/eslint-patch" "^1.1.0"
+ "@typescript-eslint/eslint-plugin" "^5.5.0"
+ "@typescript-eslint/parser" "^5.5.0"
+ babel-preset-react-app "^10.0.1"
+ confusing-browser-globals "^1.0.11"
+ eslint-plugin-flowtype "^8.0.3"
+ eslint-plugin-import "^2.25.3"
+ eslint-plugin-jest "^25.3.0"
+ eslint-plugin-jsx-a11y "^6.5.1"
+ eslint-plugin-react "^7.27.1"
+ eslint-plugin-react-hooks "^4.3.0"
+ eslint-plugin-testing-library "^5.0.1"
+
+eslint-import-resolver-node@^0.3.6:
+ version "0.3.6"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz#4048b958395da89668252001dbd9eca6b83bacbd"
+ integrity sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==
+ dependencies:
+ debug "^3.2.7"
+ resolve "^1.20.0"
+
+eslint-module-utils@^2.7.3:
+ version "2.7.3"
+ resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.7.3.tgz#ad7e3a10552fdd0642e1e55292781bd6e34876ee"
+ integrity sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==
+ dependencies:
+ debug "^3.2.7"
+ find-up "^2.1.0"
+
+eslint-plugin-flowtype@^8.0.3:
+ version "8.0.3"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-8.0.3.tgz#e1557e37118f24734aa3122e7536a038d34a4912"
+ integrity sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==
+ dependencies:
+ lodash "^4.17.21"
+ string-natural-compare "^3.0.1"
+
+eslint-plugin-import@^2.25.3:
+ version "2.26.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz#f812dc47be4f2b72b478a021605a59fc6fe8b88b"
+ integrity sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==
+ dependencies:
+ array-includes "^3.1.4"
+ array.prototype.flat "^1.2.5"
+ debug "^2.6.9"
+ doctrine "^2.1.0"
+ eslint-import-resolver-node "^0.3.6"
+ eslint-module-utils "^2.7.3"
+ has "^1.0.3"
+ is-core-module "^2.8.1"
+ is-glob "^4.0.3"
+ minimatch "^3.1.2"
+ object.values "^1.1.5"
+ resolve "^1.22.0"
+ tsconfig-paths "^3.14.1"
+
+eslint-plugin-jest@^25.3.0:
+ version "25.7.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-25.7.0.tgz#ff4ac97520b53a96187bad9c9814e7d00de09a6a"
+ integrity sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==
+ dependencies:
+ "@typescript-eslint/experimental-utils" "^5.0.0"
+
+eslint-plugin-jsx-a11y@^6.5.1:
+ version "6.5.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.5.1.tgz#cdbf2df901040ca140b6ec14715c988889c2a6d8"
+ integrity sha512-sVCFKX9fllURnXT2JwLN5Qgo24Ug5NF6dxhkmxsMEUZhXRcGg+X3e1JbJ84YePQKBl5E0ZjAH5Q4rkdcGY99+g==
+ dependencies:
+ "@babel/runtime" "^7.16.3"
+ aria-query "^4.2.2"
+ array-includes "^3.1.4"
+ ast-types-flow "^0.0.7"
+ axe-core "^4.3.5"
+ axobject-query "^2.2.0"
+ damerau-levenshtein "^1.0.7"
+ emoji-regex "^9.2.2"
+ has "^1.0.3"
+ jsx-ast-utils "^3.2.1"
+ language-tags "^1.0.5"
+ minimatch "^3.0.4"
+
+eslint-plugin-react-hooks@^4.3.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.5.0.tgz#5f762dfedf8b2cf431c689f533c9d3fa5dcf25ad"
+ integrity sha512-8k1gRt7D7h03kd+SAAlzXkQwWK22BnK6GKZG+FJA6BAGy22CFvl8kCIXKpVux0cCxMWDQUPqSok0LKaZ0aOcCw==
+
+eslint-plugin-react@^7.27.1:
+ version "7.30.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.30.0.tgz#8e7b1b2934b8426ac067a0febade1b13bd7064e3"
+ integrity sha512-RgwH7hjW48BleKsYyHK5vUAvxtE9SMPDKmcPRQgtRCYaZA0XQPt5FSkrU3nhz5ifzMZcA8opwmRJ2cmOO8tr5A==
+ dependencies:
+ array-includes "^3.1.5"
+ array.prototype.flatmap "^1.3.0"
+ 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.5"
+ object.fromentries "^2.0.5"
+ object.hasown "^1.1.1"
+ object.values "^1.1.5"
+ prop-types "^15.8.1"
+ resolve "^2.0.0-next.3"
+ semver "^6.3.0"
+ string.prototype.matchall "^4.0.7"
+
+eslint-plugin-testing-library@^5.0.1:
+ version "5.5.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-testing-library/-/eslint-plugin-testing-library-5.5.1.tgz#6fe602f9082a421b471bbae8aed692e26fe981b3"
+ integrity sha512-plLEkkbAKBjPxsLj7x4jNapcHAg2ernkQlKKrN2I8NrQwPISZHyCUNvg5Hv3EDqOQReToQb5bnqXYbkijJPE/g==
+ dependencies:
+ "@typescript-eslint/utils" "^5.13.0"
+
+eslint-scope@5.1.1, eslint-scope@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
+eslint-scope@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642"
+ integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^5.2.0"
+
+eslint-utils@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672"
+ integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==
+ dependencies:
+ eslint-visitor-keys "^2.0.0"
+
+eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303"
+ integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==
+
+eslint-visitor-keys@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826"
+ integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==
+
+eslint-webpack-plugin@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-3.1.1.tgz#83dad2395e5f572d6f4d919eedaa9cf902890fcb"
+ integrity sha512-xSucskTN9tOkfW7so4EaiFIkulWLXwCB/15H917lR6pTv0Zot6/fetFucmENRb7J5whVSFKIvwnrnsa78SG2yg==
+ dependencies:
+ "@types/eslint" "^7.28.2"
+ jest-worker "^27.3.1"
+ micromatch "^4.0.4"
+ normalize-path "^3.0.0"
+ schema-utils "^3.1.1"
+
+eslint@^8.3.0:
+ version "8.17.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.17.0.tgz#1cfc4b6b6912f77d24b874ca1506b0fe09328c21"
+ integrity sha512-gq0m0BTJfci60Fz4nczYxNAlED+sMcihltndR8t9t1evnU/azx53x3t2UHXC/uRjcbvRw/XctpaNygSTcQD+Iw==
+ dependencies:
+ "@eslint/eslintrc" "^1.3.0"
+ "@humanwhocodes/config-array" "^0.9.2"
+ 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-utils "^3.0.0"
+ eslint-visitor-keys "^3.3.0"
+ espree "^9.3.2"
+ esquery "^1.4.0"
+ esutils "^2.0.2"
+ fast-deep-equal "^3.1.3"
+ file-entry-cache "^6.0.1"
+ functional-red-black-tree "^1.0.1"
+ glob-parent "^6.0.1"
+ globals "^13.15.0"
+ ignore "^5.2.0"
+ import-fresh "^3.0.0"
+ imurmurhash "^0.1.4"
+ is-glob "^4.0.0"
+ 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"
+ regexpp "^3.2.0"
+ strip-ansi "^6.0.1"
+ strip-json-comments "^3.1.0"
+ text-table "^0.2.0"
+ v8-compile-cache "^2.0.3"
+
+espree@^9.3.2:
+ version "9.3.2"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-9.3.2.tgz#f58f77bd334731182801ced3380a8cc859091596"
+ integrity sha512-D211tC7ZwouTIuY5x9XnS0E9sWNChB7IYKX/Xp5eQj3nFXhqmiUDB9q27y76oFl8jTg3pXcQx/bpxMfs3CIZbA==
+ dependencies:
+ acorn "^8.7.1"
+ acorn-jsx "^5.3.2"
+ eslint-visitor-keys "^3.3.0"
+
+esprima@^4.0.0, esprima@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
+ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
+
+esquery@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
+ integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
+ dependencies:
+ estraverse "^5.1.0"
+
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
+estraverse@^4.1.1:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
+ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
+
+estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
+ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+estree-walker@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
+ integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
+
+esutils@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+ integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+etag@~1.8.1:
+ version "1.8.1"
+ resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
+ integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
+
+eventemitter3@^4.0.0:
+ version "4.0.7"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
+ integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+
+events@^3.2.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
+execa@^5.0.0:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
+ integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
+ dependencies:
+ cross-spawn "^7.0.3"
+ get-stream "^6.0.0"
+ human-signals "^2.1.0"
+ is-stream "^2.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^4.0.1"
+ onetime "^5.1.2"
+ signal-exit "^3.0.3"
+ strip-final-newline "^2.0.0"
+
+exit@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
+ integrity sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==
+
+expect@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/expect/-/expect-27.5.1.tgz#83ce59f1e5bdf5f9d2b94b61d2050db48f3fef74"
+ integrity sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+
+express@^4.17.3:
+ version "4.18.1"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf"
+ integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q==
+ dependencies:
+ accepts "~1.3.8"
+ array-flatten "1.1.1"
+ body-parser "1.20.0"
+ content-disposition "0.5.4"
+ content-type "~1.0.4"
+ cookie "0.5.0"
+ cookie-signature "1.0.6"
+ debug "2.6.9"
+ depd "2.0.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ finalhandler "1.2.0"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ merge-descriptors "1.0.1"
+ methods "~1.1.2"
+ on-finished "2.4.1"
+ parseurl "~1.3.3"
+ path-to-regexp "0.1.7"
+ proxy-addr "~2.0.7"
+ qs "6.10.3"
+ range-parser "~1.2.1"
+ safe-buffer "5.2.1"
+ send "0.18.0"
+ serve-static "1.15.0"
+ setprototypeof "1.2.0"
+ statuses "2.0.1"
+ type-is "~1.6.18"
+ utils-merge "1.0.1"
+ vary "~1.1.2"
+
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-glob@^3.2.11, fast-glob@^3.2.9:
+ version "3.2.11"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
+ integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
+fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+ integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
+
+fastq@^1.6.0:
+ version "1.13.0"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c"
+ integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==
+ dependencies:
+ reusify "^1.0.4"
+
+faye-websocket@^0.11.3:
+ version "0.11.4"
+ resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da"
+ integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==
+ dependencies:
+ websocket-driver ">=0.5.1"
+
+fb-watchman@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85"
+ integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg==
+ dependencies:
+ bser "2.1.1"
+
+file-entry-cache@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
+ integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
+ dependencies:
+ flat-cache "^3.0.4"
+
+file-loader@^6.2.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d"
+ integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==
+ dependencies:
+ loader-utils "^2.0.0"
+ schema-utils "^3.0.0"
+
+filelist@^1.0.1:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5"
+ integrity sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==
+ dependencies:
+ minimatch "^5.0.1"
+
+filesize@^8.0.6:
+ version "8.0.7"
+ resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8"
+ integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==
+
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+finalhandler@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32"
+ integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==
+ dependencies:
+ debug "2.6.9"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ on-finished "2.4.1"
+ parseurl "~1.3.3"
+ statuses "2.0.1"
+ unpipe "~1.0.0"
+
+find-cache-dir@^3.3.1:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b"
+ integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==
+ dependencies:
+ commondir "^1.0.1"
+ make-dir "^3.0.2"
+ pkg-dir "^4.1.0"
+
+find-root@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
+ integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
+
+find-up@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
+ integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==
+ dependencies:
+ locate-path "^2.0.0"
+
+find-up@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73"
+ integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==
+ dependencies:
+ locate-path "^3.0.0"
+
+find-up@^4.0.0, find-up@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
+find-up@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+ dependencies:
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
+
+flat-cache@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
+ integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
+ dependencies:
+ flatted "^3.1.0"
+ rimraf "^3.0.2"
+
+flatted@^3.1.0:
+ version "3.2.5"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.5.tgz#76c8584f4fc843db64702a6bd04ab7a8bd666da3"
+ integrity sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==
+
+follow-redirects@^1.0.0:
+ version "1.15.1"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5"
+ integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==
+
+fork-ts-checker-webpack-plugin@^6.5.0:
+ version "6.5.2"
+ resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz#4f67183f2f9eb8ba7df7177ce3cf3e75cdafb340"
+ integrity sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA==
+ dependencies:
+ "@babel/code-frame" "^7.8.3"
+ "@types/json-schema" "^7.0.5"
+ chalk "^4.1.0"
+ chokidar "^3.4.2"
+ cosmiconfig "^6.0.0"
+ deepmerge "^4.2.2"
+ fs-extra "^9.0.0"
+ glob "^7.1.6"
+ memfs "^3.1.2"
+ minimatch "^3.0.4"
+ schema-utils "2.7.0"
+ semver "^7.3.2"
+ tapable "^1.0.0"
+
+form-data@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f"
+ integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+forwarded@0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
+ integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
+
+fraction.js@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950"
+ integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==
+
+fresh@0.5.2:
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
+ integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==
+
+fs-extra@^10.0.0:
+ version "10.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
+ integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
+ dependencies:
+ graceful-fs "^4.2.0"
+ jsonfile "^6.0.1"
+ universalify "^2.0.0"
+
+fs-extra@^9.0.0, fs-extra@^9.0.1:
+ version "9.1.0"
+ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d"
+ integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==
+ dependencies:
+ at-least-node "^1.0.0"
+ graceful-fs "^4.2.0"
+ jsonfile "^6.0.1"
+ universalify "^2.0.0"
+
+fs-monkey@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3"
+ integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+fsevents@^2.3.2, fsevents@~2.3.2:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
+ integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
+
+function-bind@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
+ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+
+function.prototype.name@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621"
+ integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.0"
+ functions-have-names "^1.2.2"
+
+functional-red-black-tree@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327"
+ integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==
+
+functions-have-names@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
+ integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
+
+gensync@^1.0.0-beta.2:
+ version "1.0.0-beta.2"
+ resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
+ integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==
+
+get-caller-file@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
+ integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
+
+get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598"
+ integrity sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==
+ dependencies:
+ function-bind "^1.1.1"
+ has "^1.0.3"
+ has-symbols "^1.0.3"
+
+get-own-enumerable-property-symbols@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
+ integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==
+
+get-package-type@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
+ integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==
+
+get-stream@^6.0.0:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
+ integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
+
+get-symbol-description@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
+ integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.1.1"
+
+glob-parent@^5.1.2, glob-parent@~5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob-parent@^6.0.1, glob-parent@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+ dependencies:
+ is-glob "^4.0.3"
+
+glob-to-regexp@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
+ integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
+
+glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
+ version "7.2.3"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
+ integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
+ 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"
+
+global-modules@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
+ integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==
+ dependencies:
+ global-prefix "^3.0.0"
+
+global-prefix@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97"
+ integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==
+ dependencies:
+ ini "^1.3.5"
+ kind-of "^6.0.2"
+ which "^1.3.1"
+
+globals@^11.1.0:
+ version "11.12.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
+ integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==
+
+globals@^13.15.0:
+ version "13.15.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.15.0.tgz#38113218c907d2f7e98658af246cef8b77e90bac"
+ integrity sha512-bpzcOlgDhMG070Av0Vy5Owklpv1I6+j96GhUI7Rh7IzDCKLzboflLrrfqMu8NquDbiR4EOQk7XzJwqVJxicxog==
+ dependencies:
+ type-fest "^0.20.2"
+
+globby@^11.0.4, globby@^11.1.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
+graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
+ version "4.2.10"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
+ integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
+
+gzip-size@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
+ integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==
+ dependencies:
+ duplexer "^0.1.2"
+
+handle-thing@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e"
+ integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==
+
+harmony-reflect@^1.4.6:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710"
+ integrity sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==
+
+has-bigints@^1.0.1, has-bigints@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
+ integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
+
+has-flag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+ integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+has-property-descriptors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
+ integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
+ dependencies:
+ get-intrinsic "^1.1.1"
+
+has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
+ integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
+
+has-tostringtag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
+ integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
+ dependencies:
+ has-symbols "^1.0.2"
+
+has@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
+ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ dependencies:
+ function-bind "^1.1.1"
+
+he@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
+ integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
+
+history@^4.9.0:
+ version "4.10.1"
+ resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
+ integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==
+ dependencies:
+ "@babel/runtime" "^7.1.2"
+ loose-envify "^1.2.0"
+ resolve-pathname "^3.0.0"
+ tiny-invariant "^1.0.2"
+ tiny-warning "^1.0.0"
+ value-equal "^1.0.1"
+
+hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
+ integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
+ dependencies:
+ react-is "^16.7.0"
+
+hoopy@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d"
+ integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==
+
+hpack.js@^2.1.6:
+ version "2.1.6"
+ resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2"
+ integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==
+ dependencies:
+ inherits "^2.0.1"
+ obuf "^1.0.0"
+ readable-stream "^2.0.1"
+ wbuf "^1.1.0"
+
+html-encoding-sniffer@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3"
+ integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==
+ dependencies:
+ whatwg-encoding "^1.0.5"
+
+html-entities@^2.1.0, html-entities@^2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46"
+ integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==
+
+html-escaper@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453"
+ integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==
+
+html-minifier-terser@^6.0.2:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab"
+ integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==
+ dependencies:
+ camel-case "^4.1.2"
+ clean-css "^5.2.2"
+ commander "^8.3.0"
+ he "^1.2.0"
+ param-case "^3.0.4"
+ relateurl "^0.2.7"
+ terser "^5.10.0"
+
+html-webpack-plugin@^5.5.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50"
+ integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==
+ dependencies:
+ "@types/html-minifier-terser" "^6.0.0"
+ html-minifier-terser "^6.0.2"
+ lodash "^4.17.21"
+ pretty-error "^4.0.0"
+ tapable "^2.0.0"
+
+htmlparser2@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7"
+ integrity sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==
+ dependencies:
+ domelementtype "^2.0.1"
+ domhandler "^4.0.0"
+ domutils "^2.5.2"
+ entities "^2.0.0"
+
+http-deceiver@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
+ integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==
+
+http-errors@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
+ integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
+ dependencies:
+ depd "2.0.0"
+ inherits "2.0.4"
+ setprototypeof "1.2.0"
+ statuses "2.0.1"
+ toidentifier "1.0.1"
+
+http-errors@~1.6.2:
+ version "1.6.3"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d"
+ integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==
+ dependencies:
+ depd "~1.1.2"
+ inherits "2.0.3"
+ setprototypeof "1.1.0"
+ statuses ">= 1.4.0 < 2"
+
+http-parser-js@>=0.5.1:
+ version "0.5.6"
+ resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.6.tgz#2e02406ab2df8af8a7abfba62e0da01c62b95afd"
+ integrity sha512-vDlkRPDJn93swjcjqMSaGSPABbIarsr1TLAui/gLDXzV5VsJNdXNzMYDyNBLQkjWQCJ1uizu8T2oDMhmGt0PRA==
+
+http-proxy-agent@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a"
+ integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==
+ dependencies:
+ "@tootallnate/once" "1"
+ agent-base "6"
+ debug "4"
+
+http-proxy-middleware@^2.0.0, http-proxy-middleware@^2.0.3:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f"
+ integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw==
+ dependencies:
+ "@types/http-proxy" "^1.17.8"
+ http-proxy "^1.18.1"
+ is-glob "^4.0.1"
+ is-plain-obj "^3.0.0"
+ micromatch "^4.0.2"
+
+http-proxy@^1.18.1:
+ version "1.18.1"
+ resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.1.tgz#401541f0534884bbf95260334e72f88ee3976549"
+ integrity sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==
+ dependencies:
+ eventemitter3 "^4.0.0"
+ follow-redirects "^1.0.0"
+ requires-port "^1.0.0"
+
+https-proxy-agent@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6"
+ integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==
+ dependencies:
+ agent-base "6"
+ debug "4"
+
+human-signals@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
+ integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
+
+hyphenate-style-name@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d"
+ integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ==
+
+iconv-lite@0.4.24:
+ version "0.4.24"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
+ integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3"
+
+iconv-lite@^0.6.3:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
+ integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
+ dependencies:
+ safer-buffer ">= 2.1.2 < 3.0.0"
+
+icss-utils@^5.0.0, icss-utils@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae"
+ integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==
+
+idb@^6.1.4:
+ version "6.1.5"
+ resolved "https://registry.yarnpkg.com/idb/-/idb-6.1.5.tgz#dbc53e7adf1ac7c59f9b2bf56e00b4ea4fce8c7b"
+ integrity sha512-IJtugpKkiVXQn5Y+LteyBCNk1N8xpGV3wWZk9EVtZWH8DYkjBn0bX1XnGP9RkyZF0sAcywa6unHqSWKe7q4LGw==
+
+identity-obj-proxy@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14"
+ integrity sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==
+ dependencies:
+ harmony-reflect "^1.4.6"
+
+ignore@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a"
+ integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==
+
+immer@^9.0.7:
+ version "9.0.14"
+ resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.14.tgz#e05b83b63999d26382bb71676c9d827831248a48"
+ integrity sha512-ubBeqQutOSLIFCUBN03jGeOS6a3DoYlSYwYJTa+gSKEZKU5redJIqkIdZ3JVv/4RZpfcXdAWH5zCNLWPRv2WDw==
+
+import-fresh@^3.0.0, import-fresh@^3.1.0, import-fresh@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
+ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+ dependencies:
+ parent-module "^1.0.0"
+ resolve-from "^4.0.0"
+
+import-local@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4"
+ integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==
+ dependencies:
+ pkg-dir "^4.2.0"
+ resolve-cwd "^3.0.0"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+ integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
+
+indent-string@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+ integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+inherits@2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
+ integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==
+
+ini@^1.3.5:
+ version "1.3.8"
+ resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
+ integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
+
+internal-slot@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c"
+ integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==
+ dependencies:
+ get-intrinsic "^1.1.0"
+ has "^1.0.3"
+ side-channel "^1.0.4"
+
+ipaddr.js@1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3"
+ integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==
+
+ipaddr.js@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0"
+ integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+ integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
+
+is-bigint@^1.0.1:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
+ integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==
+ dependencies:
+ has-bigints "^1.0.1"
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-boolean-object@^1.1.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719"
+ integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-callable@^1.1.4, is-callable@^1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945"
+ integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==
+
+is-core-module@^2.2.0, is-core-module@^2.8.1:
+ version "2.9.0"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.9.0.tgz#e1c34429cd51c6dd9e09e0799e396e27b19a9c69"
+ integrity sha512-+5FPy5PnwmO3lvfMb0AsoPaBG+5KHUI0wYFXOtYPnVVVspTFUuMZNfNaNVRt3FZadstu2c8x23vykRW/NBoU6A==
+ dependencies:
+ has "^1.0.3"
+
+is-date-object@^1.0.1:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
+ integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-docker@^2.0.0, is-docker@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa"
+ integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-fullwidth-code-point@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+ integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
+is-generator-fn@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118"
+ integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==
+
+is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-in-browser@^1.0.2, is-in-browser@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/is-in-browser/-/is-in-browser-1.1.3.tgz#56ff4db683a078c6082eb95dad7dc62e1d04f835"
+ integrity sha512-FeXIBgG/CPGd/WUxuEyvgGTEfwiG9Z4EKGxjNMRqviiIIfsmgrpnHLffEDdwUHqNva1VEW91o3xBT/m8Elgl9g==
+
+is-module@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
+ integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==
+
+is-negative-zero@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
+ integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
+
+is-number-object@^1.0.4:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
+ integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-obj@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
+ integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==
+
+is-plain-obj@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7"
+ integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==
+
+is-potential-custom-element-name@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
+ integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
+
+is-regex@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
+ integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069"
+ integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==
+
+is-root@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c"
+ integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==
+
+is-shared-array-buffer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79"
+ integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==
+ dependencies:
+ call-bind "^1.0.2"
+
+is-stream@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
+ integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
+
+is-string@^1.0.5, is-string@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
+ integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-symbol@^1.0.2, is-symbol@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
+ integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==
+ dependencies:
+ has-symbols "^1.0.2"
+
+is-typedarray@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
+ integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==
+
+is-weakref@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
+ integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==
+ dependencies:
+ call-bind "^1.0.2"
+
+is-wsl@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271"
+ integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==
+ dependencies:
+ is-docker "^2.0.0"
+
+isarray@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
+ integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==
+
+isarray@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
+ integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3"
+ integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==
+
+istanbul-lib-instrument@^5.0.4, istanbul-lib-instrument@^5.1.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.0.tgz#31d18bdd127f825dd02ea7bfdfd906f8ab840e9f"
+ integrity sha512-6Lthe1hqXHBNsqvgDzGO6l03XNeu3CrG4RqQ1KM9+l5+jNGpEJfIELx1NS3SEHmJQA8np/u+E4EPRKRiu6m19A==
+ dependencies:
+ "@babel/core" "^7.12.3"
+ "@babel/parser" "^7.14.7"
+ "@istanbuljs/schema" "^0.1.2"
+ istanbul-lib-coverage "^3.2.0"
+ semver "^6.3.0"
+
+istanbul-lib-report@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6"
+ integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==
+ dependencies:
+ istanbul-lib-coverage "^3.0.0"
+ make-dir "^3.0.0"
+ supports-color "^7.1.0"
+
+istanbul-lib-source-maps@^4.0.0:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551"
+ integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==
+ dependencies:
+ debug "^4.1.1"
+ istanbul-lib-coverage "^3.0.0"
+ source-map "^0.6.1"
+
+istanbul-reports@^3.1.3:
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.4.tgz#1b6f068ecbc6c331040aab5741991273e609e40c"
+ integrity sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==
+ dependencies:
+ html-escaper "^2.0.0"
+ istanbul-lib-report "^3.0.0"
+
+jake@^10.8.5:
+ version "10.8.5"
+ resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.5.tgz#f2183d2c59382cb274226034543b9c03b8164c46"
+ integrity sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==
+ dependencies:
+ async "^3.2.3"
+ chalk "^4.0.2"
+ filelist "^1.0.1"
+ minimatch "^3.0.4"
+
+jest-changed-files@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-27.5.1.tgz#a348aed00ec9bf671cc58a66fcbe7c3dfd6a68f5"
+ integrity sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ execa "^5.0.0"
+ throat "^6.0.1"
+
+jest-circus@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.5.1.tgz#37a5a4459b7bf4406e53d637b49d22c65d125ecc"
+ integrity sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ co "^4.6.0"
+ dedent "^0.7.0"
+ expect "^27.5.1"
+ is-generator-fn "^2.0.0"
+ jest-each "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+ throat "^6.0.1"
+
+jest-cli@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.5.1.tgz#278794a6e6458ea8029547e6c6cbf673bd30b145"
+ integrity sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==
+ dependencies:
+ "@jest/core" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ exit "^0.1.2"
+ graceful-fs "^4.2.9"
+ import-local "^3.0.2"
+ jest-config "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ prompts "^2.0.1"
+ yargs "^16.2.0"
+
+jest-config@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.5.1.tgz#5c387de33dca3f99ad6357ddeccd91bf3a0e4a41"
+ integrity sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==
+ dependencies:
+ "@babel/core" "^7.8.0"
+ "@jest/test-sequencer" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ babel-jest "^27.5.1"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ deepmerge "^4.2.2"
+ glob "^7.1.1"
+ graceful-fs "^4.2.9"
+ jest-circus "^27.5.1"
+ jest-environment-jsdom "^27.5.1"
+ jest-environment-node "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-jasmine2 "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-runner "^27.5.1"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ micromatch "^4.0.4"
+ parse-json "^5.2.0"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ strip-json-comments "^3.1.1"
+
+jest-diff@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def"
+ integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==
+ dependencies:
+ chalk "^4.0.0"
+ diff-sequences "^27.5.1"
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-docblock@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-27.5.1.tgz#14092f364a42c6108d42c33c8cf30e058e25f6c0"
+ integrity sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==
+ dependencies:
+ detect-newline "^3.0.0"
+
+jest-each@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-27.5.1.tgz#5bc87016f45ed9507fed6e4702a5b468a5b2c44e"
+ integrity sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ jest-get-type "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-environment-jsdom@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-27.5.1.tgz#ea9ccd1fc610209655a77898f86b2b559516a546"
+ integrity sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
+ jsdom "^16.6.0"
+
+jest-environment-node@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-27.5.1.tgz#dedc2cfe52fab6b8f5714b4808aefa85357a365e"
+ integrity sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ jest-mock "^27.5.1"
+ jest-util "^27.5.1"
+
+jest-get-type@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1"
+ integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==
+
+jest-haste-map@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-27.5.1.tgz#9fd8bd7e7b4fa502d9c6164c5640512b4e811e7f"
+ integrity sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/graceful-fs" "^4.1.2"
+ "@types/node" "*"
+ anymatch "^3.0.3"
+ fb-watchman "^2.0.0"
+ graceful-fs "^4.2.9"
+ jest-regex-util "^27.5.1"
+ jest-serializer "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
+ micromatch "^4.0.4"
+ walker "^1.0.7"
+ optionalDependencies:
+ fsevents "^2.3.2"
+
+jest-jasmine2@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.5.1.tgz#a037b0034ef49a9f3d71c4375a796f3b230d1ac4"
+ integrity sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/source-map" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ co "^4.6.0"
+ expect "^27.5.1"
+ is-generator-fn "^2.0.0"
+ jest-each "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ pretty-format "^27.5.1"
+ throat "^6.0.1"
+
+jest-leak-detector@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-27.5.1.tgz#6ec9d54c3579dd6e3e66d70e3498adf80fde3fb8"
+ integrity sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==
+ dependencies:
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-matcher-utils@^27.0.0, jest-matcher-utils@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.5.1.tgz#9c0cdbda8245bc22d2331729d1091308b40cf8ab"
+ integrity sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==
+ dependencies:
+ chalk "^4.0.0"
+ jest-diff "^27.5.1"
+ jest-get-type "^27.5.1"
+ pretty-format "^27.5.1"
+
+jest-message-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-27.5.1.tgz#bdda72806da10d9ed6425e12afff38cd1458b6cf"
+ integrity sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==
+ dependencies:
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^27.5.1"
+ "@types/stack-utils" "^2.0.0"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^27.5.1"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
+jest-message-util@^28.1.1:
+ version "28.1.1"
+ resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-28.1.1.tgz#60aa0b475cfc08c8a9363ed2fb9108514dd9ab89"
+ integrity sha512-xoDOOT66fLfmTRiqkoLIU7v42mal/SqwDKvfmfiWAdJMSJiU+ozgluO7KbvoAgiwIrrGZsV7viETjc8GNrA/IQ==
+ dependencies:
+ "@babel/code-frame" "^7.12.13"
+ "@jest/types" "^28.1.1"
+ "@types/stack-utils" "^2.0.0"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ micromatch "^4.0.4"
+ pretty-format "^28.1.1"
+ slash "^3.0.0"
+ stack-utils "^2.0.3"
+
+jest-mock@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-27.5.1.tgz#19948336d49ef4d9c52021d34ac7b5f36ff967d6"
+ integrity sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+
+jest-pnp-resolver@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c"
+ integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==
+
+jest-regex-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.5.1.tgz#4da143f7e9fd1e542d4aa69617b38e4a78365b95"
+ integrity sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==
+
+jest-regex-util@^28.0.0:
+ version "28.0.2"
+ resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-28.0.2.tgz#afdc377a3b25fb6e80825adcf76c854e5bf47ead"
+ integrity sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==
+
+jest-resolve-dependencies@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.5.1.tgz#d811ecc8305e731cc86dd79741ee98fed06f1da8"
+ integrity sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-snapshot "^27.5.1"
+
+jest-resolve@^27.4.2, jest-resolve@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-27.5.1.tgz#a2f1c5a0796ec18fe9eb1536ac3814c23617b384"
+ integrity sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-pnp-resolver "^1.2.2"
+ jest-util "^27.5.1"
+ jest-validate "^27.5.1"
+ resolve "^1.20.0"
+ resolve.exports "^1.1.0"
+ slash "^3.0.0"
+
+jest-runner@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.5.1.tgz#071b27c1fa30d90540805c5645a0ec167c7b62e5"
+ integrity sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==
+ dependencies:
+ "@jest/console" "^27.5.1"
+ "@jest/environment" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ emittery "^0.8.1"
+ graceful-fs "^4.2.9"
+ jest-docblock "^27.5.1"
+ jest-environment-jsdom "^27.5.1"
+ jest-environment-node "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-leak-detector "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-runtime "^27.5.1"
+ jest-util "^27.5.1"
+ jest-worker "^27.5.1"
+ source-map-support "^0.5.6"
+ throat "^6.0.1"
+
+jest-runtime@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.5.1.tgz#4896003d7a334f7e8e4a53ba93fb9bcd3db0a1af"
+ integrity sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==
+ dependencies:
+ "@jest/environment" "^27.5.1"
+ "@jest/fake-timers" "^27.5.1"
+ "@jest/globals" "^27.5.1"
+ "@jest/source-map" "^27.5.1"
+ "@jest/test-result" "^27.5.1"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ chalk "^4.0.0"
+ cjs-module-lexer "^1.0.0"
+ collect-v8-coverage "^1.0.0"
+ execa "^5.0.0"
+ glob "^7.1.3"
+ graceful-fs "^4.2.9"
+ jest-haste-map "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-mock "^27.5.1"
+ jest-regex-util "^27.5.1"
+ jest-resolve "^27.5.1"
+ jest-snapshot "^27.5.1"
+ jest-util "^27.5.1"
+ slash "^3.0.0"
+ strip-bom "^4.0.0"
+
+jest-serializer@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-27.5.1.tgz#81438410a30ea66fd57ff730835123dea1fb1f64"
+ integrity sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==
+ dependencies:
+ "@types/node" "*"
+ graceful-fs "^4.2.9"
+
+jest-snapshot@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.5.1.tgz#b668d50d23d38054a51b42c4039cab59ae6eb6a1"
+ integrity sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==
+ dependencies:
+ "@babel/core" "^7.7.2"
+ "@babel/generator" "^7.7.2"
+ "@babel/plugin-syntax-typescript" "^7.7.2"
+ "@babel/traverse" "^7.7.2"
+ "@babel/types" "^7.0.0"
+ "@jest/transform" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/babel__traverse" "^7.0.4"
+ "@types/prettier" "^2.1.5"
+ babel-preset-current-node-syntax "^1.0.0"
+ chalk "^4.0.0"
+ expect "^27.5.1"
+ graceful-fs "^4.2.9"
+ jest-diff "^27.5.1"
+ jest-get-type "^27.5.1"
+ jest-haste-map "^27.5.1"
+ jest-matcher-utils "^27.5.1"
+ jest-message-util "^27.5.1"
+ jest-util "^27.5.1"
+ natural-compare "^1.4.0"
+ pretty-format "^27.5.1"
+ semver "^7.3.2"
+
+jest-util@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-27.5.1.tgz#3ba9771e8e31a0b85da48fe0b0891fb86c01c2f9"
+ integrity sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
+
+jest-util@^28.1.1:
+ version "28.1.1"
+ resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-28.1.1.tgz#ff39e436a1aca397c0ab998db5a51ae2b7080d05"
+ integrity sha512-FktOu7ca1DZSyhPAxgxB6hfh2+9zMoJ7aEQA759Z6p45NuO8mWcqujH+UdHlCm/V6JTWwDztM2ITCzU1ijJAfw==
+ dependencies:
+ "@jest/types" "^28.1.1"
+ "@types/node" "*"
+ chalk "^4.0.0"
+ ci-info "^3.2.0"
+ graceful-fs "^4.2.9"
+ picomatch "^2.2.3"
+
+jest-validate@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-27.5.1.tgz#9197d54dc0bdb52260b8db40b46ae668e04df067"
+ integrity sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==
+ dependencies:
+ "@jest/types" "^27.5.1"
+ camelcase "^6.2.0"
+ chalk "^4.0.0"
+ jest-get-type "^27.5.1"
+ leven "^3.1.0"
+ pretty-format "^27.5.1"
+
+jest-watch-typeahead@^1.0.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/jest-watch-typeahead/-/jest-watch-typeahead-1.1.0.tgz#b4a6826dfb9c9420da2f7bc900de59dad11266a9"
+ integrity sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==
+ dependencies:
+ ansi-escapes "^4.3.1"
+ chalk "^4.0.0"
+ jest-regex-util "^28.0.0"
+ jest-watcher "^28.0.0"
+ slash "^4.0.0"
+ string-length "^5.0.1"
+ strip-ansi "^7.0.1"
+
+jest-watcher@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-27.5.1.tgz#71bd85fb9bde3a2c2ec4dc353437971c43c642a2"
+ integrity sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==
+ dependencies:
+ "@jest/test-result" "^27.5.1"
+ "@jest/types" "^27.5.1"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ jest-util "^27.5.1"
+ string-length "^4.0.1"
+
+jest-watcher@^28.0.0:
+ version "28.1.1"
+ resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-28.1.1.tgz#533597fb3bfefd52b5cd115cd916cffd237fb60c"
+ integrity sha512-RQIpeZ8EIJMxbQrXpJQYIIlubBnB9imEHsxxE41f54ZwcqWLysL/A0ZcdMirf+XsMn3xfphVQVV4EW0/p7i7Ug==
+ dependencies:
+ "@jest/test-result" "^28.1.1"
+ "@jest/types" "^28.1.1"
+ "@types/node" "*"
+ ansi-escapes "^4.2.1"
+ chalk "^4.0.0"
+ emittery "^0.10.2"
+ jest-util "^28.1.1"
+ string-length "^4.0.1"
+
+jest-worker@^26.2.1:
+ version "26.6.2"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed"
+ integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==
+ dependencies:
+ "@types/node" "*"
+ merge-stream "^2.0.0"
+ supports-color "^7.0.0"
+
+jest-worker@^27.0.2, jest-worker@^27.3.1, jest-worker@^27.4.5, jest-worker@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0"
+ integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==
+ dependencies:
+ "@types/node" "*"
+ merge-stream "^2.0.0"
+ supports-color "^8.0.0"
+
+jest@^27.4.3:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/jest/-/jest-27.5.1.tgz#dadf33ba70a779be7a6fc33015843b51494f63fc"
+ integrity sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==
+ dependencies:
+ "@jest/core" "^27.5.1"
+ import-local "^3.0.2"
+ jest-cli "^27.5.1"
+
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-yaml@^3.13.1:
+ version "3.14.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537"
+ integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
+js-yaml@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
+jsdom@^16.6.0:
+ version "16.7.0"
+ resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.7.0.tgz#918ae71965424b197c819f8183a754e18977b710"
+ integrity sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==
+ dependencies:
+ abab "^2.0.5"
+ acorn "^8.2.4"
+ acorn-globals "^6.0.0"
+ cssom "^0.4.4"
+ cssstyle "^2.3.0"
+ data-urls "^2.0.0"
+ decimal.js "^10.2.1"
+ domexception "^2.0.1"
+ escodegen "^2.0.0"
+ form-data "^3.0.0"
+ html-encoding-sniffer "^2.0.1"
+ http-proxy-agent "^4.0.1"
+ https-proxy-agent "^5.0.0"
+ is-potential-custom-element-name "^1.0.1"
+ nwsapi "^2.2.0"
+ parse5 "6.0.1"
+ saxes "^5.0.1"
+ symbol-tree "^3.2.4"
+ tough-cookie "^4.0.0"
+ w3c-hr-time "^1.0.2"
+ w3c-xmlserializer "^2.0.0"
+ webidl-conversions "^6.1.0"
+ whatwg-encoding "^1.0.5"
+ whatwg-mimetype "^2.3.0"
+ whatwg-url "^8.5.0"
+ ws "^7.4.6"
+ xml-name-validator "^3.0.0"
+
+jsesc@^2.5.1:
+ version "2.5.2"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
+ integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
+
+jsesc@~0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+ integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
+
+json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json-schema-traverse@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+ integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+
+json-schema@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
+ integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
+
+json-stable-stringify-without-jsonify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+ integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
+
+json5@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
+ integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
+ dependencies:
+ minimist "^1.2.0"
+
+json5@^2.1.2, json5@^2.2.0, json5@^2.2.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c"
+ integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==
+
+jsonfile@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
+ integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
+ dependencies:
+ universalify "^2.0.0"
+ optionalDependencies:
+ graceful-fs "^4.1.6"
+
+jsonpointer@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.0.tgz#f802669a524ec4805fa7389eadbc9921d5dc8072"
+ integrity sha512-PNYZIdMjVIvVgDSYKTT63Y+KZ6IZvGRNNWcxwD+GNnUz1MKPfv30J8ueCjdwcN0nDx2SlshgyB7Oy0epAzVRRg==
+
+jss-plugin-camel-case@^10.10.0:
+ version "10.10.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-camel-case/-/jss-plugin-camel-case-10.10.0.tgz#27ea159bab67eb4837fa0260204eb7925d4daa1c"
+ integrity sha512-z+HETfj5IYgFxh1wJnUAU8jByI48ED+v0fuTuhKrPR+pRBYS2EDwbusU8aFOpCdYhtRc9zhN+PJ7iNE8pAWyPw==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ hyphenate-style-name "^1.0.3"
+ jss "10.10.0"
+
+jss-plugin-default-unit@^10.10.0:
+ version "10.10.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-default-unit/-/jss-plugin-default-unit-10.10.0.tgz#db3925cf6a07f8e1dd459549d9c8aadff9804293"
+ integrity sha512-SvpajxIECi4JDUbGLefvNckmI+c2VWmP43qnEy/0eiwzRUsafg5DVSIWSzZe4d2vFX1u9nRDP46WCFV/PXVBGQ==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ jss "10.10.0"
+
+jss-plugin-global@^10.10.0:
+ version "10.10.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-global/-/jss-plugin-global-10.10.0.tgz#1c55d3c35821fab67a538a38918292fc9c567efd"
+ integrity sha512-icXEYbMufiNuWfuazLeN+BNJO16Ge88OcXU5ZDC2vLqElmMybA31Wi7lZ3lf+vgufRocvPj8443irhYRgWxP+A==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ jss "10.10.0"
+
+jss-plugin-nested@^10.10.0:
+ version "10.10.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-nested/-/jss-plugin-nested-10.10.0.tgz#db872ed8925688806e77f1fc87f6e62264513219"
+ integrity sha512-9R4JHxxGgiZhurDo3q7LdIiDEgtA1bTGzAbhSPyIOWb7ZubrjQe8acwhEQ6OEKydzpl8XHMtTnEwHXCARLYqYA==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ jss "10.10.0"
+ tiny-warning "^1.0.2"
+
+jss-plugin-props-sort@^10.10.0:
+ version "10.10.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-props-sort/-/jss-plugin-props-sort-10.10.0.tgz#67f4dd4c70830c126f4ec49b4b37ccddb680a5d7"
+ integrity sha512-5VNJvQJbnq/vRfje6uZLe/FyaOpzP/IH1LP+0fr88QamVrGJa0hpRRyAa0ea4U/3LcorJfBFVyC4yN2QC73lJg==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ jss "10.10.0"
+
+jss-plugin-rule-value-function@^10.10.0:
+ version "10.10.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-rule-value-function/-/jss-plugin-rule-value-function-10.10.0.tgz#7d99e3229e78a3712f78ba50ab342e881d26a24b"
+ integrity sha512-uEFJFgaCtkXeIPgki8ICw3Y7VMkL9GEan6SqmT9tqpwM+/t+hxfMUdU4wQ0MtOiMNWhwnckBV0IebrKcZM9C0g==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ jss "10.10.0"
+ tiny-warning "^1.0.2"
+
+jss-plugin-vendor-prefixer@^10.10.0:
+ version "10.10.0"
+ resolved "https://registry.yarnpkg.com/jss-plugin-vendor-prefixer/-/jss-plugin-vendor-prefixer-10.10.0.tgz#c01428ef5a89f2b128ec0af87a314d0c767931c7"
+ integrity sha512-UY/41WumgjW8r1qMCO8l1ARg7NHnfRVWRhZ2E2m0DMYsr2DD91qIXLyNhiX83hHswR7Wm4D+oDYNC1zWCJWtqg==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ css-vendor "^2.0.8"
+ jss "10.10.0"
+
+jss@10.10.0, jss@^10.10.0:
+ version "10.10.0"
+ resolved "https://registry.yarnpkg.com/jss/-/jss-10.10.0.tgz#a75cc85b0108c7ac8c7b7d296c520a3e4fbc6ccc"
+ integrity sha512-cqsOTS7jqPsPMjtKYDUpdFC0AbhYFLTcuGRqymgmdJIeQ8cH7+AgX7YSgQy79wXloZq2VvATYxUOUQEvS1V/Zw==
+ dependencies:
+ "@babel/runtime" "^7.3.1"
+ csstype "^3.0.2"
+ is-in-browser "^1.1.3"
+ tiny-warning "^1.0.2"
+
+"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.0.tgz#e624f259143b9062c92b6413ff92a164c80d3ccb"
+ integrity sha512-XzO9luP6L0xkxwhIJMTJQpZo/eeN60K08jHdexfD569AGxeNug6UketeHXEhROoM8aR7EcUoOQmIhcJQjcuq8Q==
+ dependencies:
+ array-includes "^3.1.4"
+ object.assign "^4.1.2"
+
+kind-of@^6.0.2:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
+ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
+
+kleur@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
+ integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
+
+klona@^2.0.4, klona@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc"
+ integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ==
+
+language-subtag-registry@~0.3.2:
+ version "0.3.21"
+ resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a"
+ integrity sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg==
+
+language-tags@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a"
+ integrity sha512-qJhlO9cGXi6hBGKoxEG/sKZDAHD5Hnu9Hs4WbOY3pCWXDhw0N8x1NenNzm2EnNLkLkk7J2SdxAkDSbb6ftT+UQ==
+ dependencies:
+ language-subtag-registry "~0.3.2"
+
+leven@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
+ integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==
+
+levn@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+ integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+ dependencies:
+ prelude-ls "^1.2.1"
+ type-check "~0.4.0"
+
+levn@~0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee"
+ integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==
+ dependencies:
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+
+lilconfig@^2.0.3, lilconfig@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.5.tgz#19e57fd06ccc3848fd1891655b5a447092225b25"
+ integrity sha512-xaYmXZtTHPAw5m+xLN8ab9C+3a8YmV3asNSPOATITbtwrfbwaLJj8h66H1WMIpALCkqsIzK3h7oQ+PdX+LQ9Eg==
+
+lines-and-columns@^1.1.6:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
+ integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+
+loader-runner@^4.2.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1"
+ integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==
+
+loader-utils@^2.0.0:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129"
+ integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==
+ dependencies:
+ big.js "^5.2.2"
+ emojis-list "^3.0.0"
+ json5 "^2.1.2"
+
+loader-utils@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.0.tgz#bcecc51a7898bee7473d4bc6b845b23af8304d4f"
+ integrity sha512-HVl9ZqccQihZ7JM85dco1MvO9G+ONvxoGa9rkhzFsneGLKSUg1gJf9bWzhRhcvm2qChhWpebQhP44qxjKIUCaQ==
+
+locate-path@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
+ integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==
+ dependencies:
+ p-locate "^2.0.0"
+ path-exists "^3.0.0"
+
+locate-path@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
+ integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==
+ dependencies:
+ p-locate "^3.0.0"
+ path-exists "^3.0.0"
+
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
+
+lodash.debounce@^4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
+ integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
+
+lodash.memoize@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe"
+ integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==
+
+lodash.merge@^4.6.2:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
+ integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+
+lodash.sortby@^4.7.0:
+ version "4.7.0"
+ resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
+ integrity sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==
+
+lodash.uniq@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
+ integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==
+
+lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
+
+loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+ dependencies:
+ js-tokens "^3.0.0 || ^4.0.0"
+
+lower-case@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-2.0.2.tgz#6fa237c63dbdc4a82ca0fd882e4722dc5e634e28"
+ integrity sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==
+ dependencies:
+ tslib "^2.0.3"
+
+lru-cache@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
+ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
+ dependencies:
+ yallist "^4.0.0"
+
+lz-string@^1.4.4:
+ version "1.4.4"
+ resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26"
+ integrity sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==
+
+magic-string@^0.25.0, magic-string@^0.25.7:
+ version "0.25.9"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.9.tgz#de7f9faf91ef8a1c91d02c2e5314c8277dbcdd1c"
+ integrity sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==
+ dependencies:
+ sourcemap-codec "^1.4.8"
+
+make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
+ integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==
+ dependencies:
+ semver "^6.0.0"
+
+makeerror@1.0.12:
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
+ integrity sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==
+ dependencies:
+ tmpl "1.0.5"
+
+mdn-data@2.0.14:
+ version "2.0.14"
+ resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50"
+ integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==
+
+mdn-data@2.0.4:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b"
+ integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==
+
+media-typer@0.3.0:
+ version "0.3.0"
+ resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748"
+ integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
+
+memfs@^3.1.2, memfs@^3.4.3:
+ version "3.4.4"
+ resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.4.tgz#e8973cd8060548916adcca58a248e7805c715e89"
+ integrity sha512-W4gHNUE++1oSJVn8Y68jPXi+mkx3fXR5ITE/Ubz6EQ3xRpCN5k2CQ4AUR8094Z7211F876TyoBACGsIveqgiGA==
+ dependencies:
+ fs-monkey "1.0.3"
+
+merge-descriptors@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
+ integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
+
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
+merge2@^1.3.0, merge2@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+methods@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee"
+ integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==
+
+micromatch@^4.0.2, micromatch@^4.0.4:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+ integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+ dependencies:
+ braces "^3.0.2"
+ picomatch "^2.3.1"
+
+mime-db@1.52.0, "mime-db@>= 1.43.0 < 2":
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34:
+ version "2.1.35"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+mime@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
+ integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
+
+mimic-fn@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+ integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+min-indent@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
+ integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
+
+mini-create-react-context@^0.4.0:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e"
+ integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==
+ dependencies:
+ "@babel/runtime" "^7.12.1"
+ tiny-warning "^1.0.3"
+
+mini-css-extract-plugin@^2.4.5:
+ version "2.6.0"
+ resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.0.tgz#578aebc7fc14d32c0ad304c2c34f08af44673f5e"
+ integrity sha512-ndG8nxCEnAemsg4FSgS+yNyHKgkTB4nPKqCOgh65j3/30qqC5RaSQQXMm++Y6sb6E1zRSxPkztj9fqxhS1Eo6w==
+ dependencies:
+ schema-utils "^4.0.0"
+
+minimalistic-assert@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
+ integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
+
+minimatch@3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimatch@^5.0.1:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7"
+ integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==
+ dependencies:
+ brace-expansion "^2.0.1"
+
+minimist@^1.2.0, minimist@^1.2.6:
+ version "1.2.6"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
+ integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
+
+mkdirp@~0.5.1:
+ version "0.5.6"
+ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
+ integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
+ dependencies:
+ minimist "^1.2.6"
+
+ms@2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
+ integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==
+
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+ms@2.1.3, ms@^2.1.1:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+ integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
+multicast-dns@^7.2.5:
+ version "7.2.5"
+ resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced"
+ integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==
+ dependencies:
+ dns-packet "^5.2.2"
+ thunky "^1.0.2"
+
+nanoid@^3.3.4:
+ version "3.3.4"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab"
+ integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+ integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+
+negotiator@0.6.3:
+ version "0.6.3"
+ resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
+ integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
+
+neo-async@^2.6.2:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
+ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
+
+no-case@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/no-case/-/no-case-3.0.4.tgz#d361fd5c9800f558551a8369fc0dcd4662b6124d"
+ integrity sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==
+ dependencies:
+ lower-case "^2.0.2"
+ tslib "^2.0.3"
+
+node-forge@^1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3"
+ integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==
+
+node-int64@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b"
+ integrity sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==
+
+node-releases@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666"
+ integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+normalize-range@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+ integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
+
+normalize-url@^6.0.1:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
+ integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==
+
+normalizr@^3.6.1:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/normalizr/-/normalizr-3.6.2.tgz#ac1571207dc3008adb46e3f62311c17f11dcf083"
+ integrity sha512-30qCybsBaCBciotorvuOZTCGEg2AXrJfADMT2Kk/lvpIAcipHdK0zc33nNtwKzyfQAqIJXAcqET6YgflYUgsoQ==
+
+npm-run-path@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
+ integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
+ dependencies:
+ path-key "^3.0.0"
+
+nth-check@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
+ integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==
+ dependencies:
+ boolbase "~1.0.0"
+
+nth-check@^2.0.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
+ integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==
+ dependencies:
+ boolbase "^1.0.0"
+
+nwsapi@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
+ integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==
+
+object-assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+ integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
+
+object-hash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
+ integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
+
+object-inspect@^1.12.0, object-inspect@^1.9.0:
+ version "1.12.2"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
+ integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
+
+object-keys@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
+ integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
+
+object.assign@^4.1.0, object.assign@^4.1.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940"
+ integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==
+ dependencies:
+ call-bind "^1.0.0"
+ define-properties "^1.1.3"
+ has-symbols "^1.0.1"
+ object-keys "^1.1.1"
+
+object.entries@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861"
+ integrity sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.1"
+
+object.fromentries@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.5.tgz#7b37b205109c21e741e605727fe8b0ad5fa08251"
+ integrity sha512-CAyG5mWQRRiBU57Re4FKoTBjXfDoNwdFVH2Y1tS9PqCsfUTymAohOkEMSG3aRNKmv4lV3O7p1et7c187q6bynw==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.1"
+
+object.getownpropertydescriptors@^2.1.0:
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz#7965e6437a57278b587383831a9b829455a4bc37"
+ integrity sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ==
+ dependencies:
+ array.prototype.reduce "^1.0.4"
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.20.1"
+
+object.hasown@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.1.tgz#ad1eecc60d03f49460600430d97f23882cf592a3"
+ integrity sha512-LYLe4tivNQzq4JdaWW6WO3HMZZJWzkkH8fnI6EebWl0VZth2wL2Lovm74ep2/gZzlaTdV62JZHEqHQ2yVn8Q/A==
+ dependencies:
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
+
+object.values@^1.1.0, object.values@^1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac"
+ integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.1"
+
+obuf@^1.0.0, obuf@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
+ integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
+
+on-finished@2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
+ integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==
+ dependencies:
+ ee-first "1.1.1"
+
+on-headers@~1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
+ integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+onetime@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
+ integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
+ dependencies:
+ mimic-fn "^2.1.0"
+
+open@^8.0.9, open@^8.4.0:
+ version "8.4.0"
+ resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8"
+ integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==
+ dependencies:
+ define-lazy-prop "^2.0.0"
+ is-docker "^2.1.1"
+ is-wsl "^2.2.0"
+
+optionator@^0.8.1:
+ version "0.8.3"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
+ integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
+ dependencies:
+ deep-is "~0.1.3"
+ fast-levenshtein "~2.0.6"
+ levn "~0.3.0"
+ prelude-ls "~1.1.2"
+ type-check "~0.3.2"
+ word-wrap "~1.2.3"
+
+optionator@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
+ integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
+ 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"
+
+p-limit@^1.1.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
+ integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
+ dependencies:
+ p-try "^1.0.0"
+
+p-limit@^2.0.0, p-limit@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
+p-limit@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
+p-locate@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
+ integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==
+ dependencies:
+ p-limit "^1.1.0"
+
+p-locate@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4"
+ integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==
+ dependencies:
+ p-limit "^2.0.0"
+
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
+p-retry@^4.5.0:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16"
+ integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==
+ dependencies:
+ "@types/retry" "0.12.0"
+ retry "^0.13.1"
+
+p-try@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
+ integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==
+
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+param-case@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5"
+ integrity sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==
+ dependencies:
+ dot-case "^3.0.4"
+ tslib "^2.0.3"
+
+parent-module@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
+ integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+ dependencies:
+ callsites "^3.0.0"
+
+parse-json@^5.0.0, parse-json@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
+ integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ error-ex "^1.3.1"
+ json-parse-even-better-errors "^2.3.0"
+ lines-and-columns "^1.1.6"
+
+parse5@6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b"
+ integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==
+
+parseurl@~1.3.2, parseurl@~1.3.3:
+ version "1.3.3"
+ resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
+ integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==
+
+pascal-case@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/pascal-case/-/pascal-case-3.1.2.tgz#b48e0ef2b98e205e7c1dae747d0b1508237660eb"
+ integrity sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==
+ dependencies:
+ no-case "^3.0.4"
+ tslib "^2.0.3"
+
+path-exists@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
+ integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==
+
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-key@^3.0.0, path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-parse@^1.0.6, path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+path-to-regexp@0.1.7:
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
+ integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
+
+path-to-regexp@^1.7.0:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
+ integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
+ dependencies:
+ isarray "0.0.1"
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+performance-now@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
+ integrity sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==
+
+picocolors@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-0.2.1.tgz#570670f793646851d1ba135996962abad587859f"
+ integrity sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==
+
+picocolors@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
+ integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
+
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+ integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
+
+pirates@^4.0.4:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b"
+ integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==
+
+pkg-dir@^4.1.0, pkg-dir@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
+ integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==
+ dependencies:
+ find-up "^4.0.0"
+
+pkg-up@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-3.1.0.tgz#100ec235cc150e4fd42519412596a28512a0def5"
+ integrity sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==
+ dependencies:
+ find-up "^3.0.0"
+
+postcss-attribute-case-insensitive@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.1.tgz#86d323c77ab8896ed90500071c2c8329fba64fda"
+ integrity sha512-wrt2VndqSLJpyBRNz9OmJcgnhI9MaongeWgapdBuUMu2a/KNJ8SENesG4SdiTnQwGO9b1VKbTWYAfCPeokLqZQ==
+ dependencies:
+ postcss-selector-parser "^6.0.10"
+
+postcss-browser-comments@^4:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-browser-comments/-/postcss-browser-comments-4.0.0.tgz#bcfc86134df5807f5d3c0eefa191d42136b5e72a"
+ integrity sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==
+
+postcss-calc@^8.2.3:
+ version "8.2.4"
+ resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5"
+ integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+ postcss-value-parser "^4.2.0"
+
+postcss-clamp@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-clamp/-/postcss-clamp-4.1.0.tgz#7263e95abadd8c2ba1bd911b0b5a5c9c93e02363"
+ integrity sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-color-functional-notation@^4.2.3:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.3.tgz#23c9d73c76113b75473edcf66f443c6f1872bd0f"
+ integrity sha512-5fbr6FzFzjwHXKsVnkmEYrJYG8VNNzvD1tAXaPPWR97S6rhKI5uh2yOfV5TAzhDkZoq4h+chxEplFDc8GeyFtw==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-color-hex-alpha@^8.0.3:
+ version "8.0.3"
+ resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.3.tgz#61a0fd151d28b128aa6a8a21a2dad24eebb34d52"
+ integrity sha512-fESawWJCrBV035DcbKRPAVmy21LpoyiXdPTuHUfWJ14ZRjY7Y7PA6P4g8z6LQGYhU1WAxkTxjIjurXzoe68Glw==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-color-rebeccapurple@^7.0.2:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.0.2.tgz#5d397039424a58a9ca628762eb0b88a61a66e079"
+ integrity sha512-SFc3MaocHaQ6k3oZaFwH8io6MdypkUtEy/eXzXEB1vEQlO3S3oDc/FSZA8AsS04Z25RirQhlDlHLh3dn7XewWw==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-colormin@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz#3cee9e5ca62b2c27e84fce63affc0cfb5901956a"
+ integrity sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==
+ dependencies:
+ browserslist "^4.16.6"
+ caniuse-api "^3.0.0"
+ colord "^2.9.1"
+ postcss-value-parser "^4.2.0"
+
+postcss-convert-values@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.2.tgz#31586df4e184c2e8890e8b34a0b9355313f503ab"
+ integrity sha512-c6Hzc4GAv95B7suy4udszX9Zy4ETyMCgFPUDtWjdFTKH1SE9eFY/jEpHSwTH1QPuwxHpWslhckUQWbNRM4ho5g==
+ dependencies:
+ browserslist "^4.20.3"
+ postcss-value-parser "^4.2.0"
+
+postcss-custom-media@^8.0.1:
+ version "8.0.2"
+ resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz#c8f9637edf45fef761b014c024cee013f80529ea"
+ integrity sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-custom-properties@^12.1.7:
+ version "12.1.7"
+ resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-12.1.7.tgz#ca470fd4bbac5a87fd868636dafc084bc2a78b41"
+ integrity sha512-N/hYP5gSoFhaqxi2DPCmvto/ZcRDVjE3T1LiAMzc/bg53hvhcHOLpXOHb526LzBBp5ZlAUhkuot/bfpmpgStJg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-custom-selectors@^6.0.2:
+ version "6.0.3"
+ resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz#1ab4684d65f30fed175520f82d223db0337239d9"
+ integrity sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==
+ dependencies:
+ postcss-selector-parser "^6.0.4"
+
+postcss-dir-pseudo-class@^6.0.4:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.4.tgz#9afe49ea631f0cb36fa0076e7c2feb4e7e3f049c"
+ integrity sha512-I8epwGy5ftdzNWEYok9VjW9whC4xnelAtbajGv4adql4FIF09rnrxnA9Y8xSHN47y7gqFIv10C5+ImsLeJpKBw==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+
+postcss-discard-comments@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696"
+ integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==
+
+postcss-discard-duplicates@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848"
+ integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==
+
+postcss-discard-empty@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c"
+ integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==
+
+postcss-discard-overridden@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e"
+ integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==
+
+postcss-double-position-gradients@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.1.tgz#a12cfdb7d11fa1a99ccecc747f0c19718fb37152"
+ integrity sha512-jM+CGkTs4FcG53sMPjrrGE0rIvLDdCrqMzgDC5fLI7JHDO7o6QG8C5TQBtExb13hdBdoH9C2QVbG4jo2y9lErQ==
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties" "^1.1.0"
+ postcss-value-parser "^4.2.0"
+
+postcss-env-function@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-4.0.6.tgz#7b2d24c812f540ed6eda4c81f6090416722a8e7a"
+ integrity sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-flexbugs-fixes@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz#2028e145313074fc9abe276cb7ca14e5401eb49d"
+ integrity sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==
+
+postcss-focus-visible@^6.0.4:
+ version "6.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz#50c9ea9afa0ee657fb75635fabad25e18d76bf9e"
+ integrity sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+
+postcss-focus-within@^5.0.4:
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz#5b1d2ec603195f3344b716c0b75f61e44e8d2e20"
+ integrity sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==
+ dependencies:
+ postcss-selector-parser "^6.0.9"
+
+postcss-font-variant@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz#efd59b4b7ea8bb06127f2d031bfbb7f24d32fa66"
+ integrity sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==
+
+postcss-gap-properties@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-3.0.3.tgz#6401bb2f67d9cf255d677042928a70a915e6ba60"
+ integrity sha512-rPPZRLPmEKgLk/KlXMqRaNkYTUpE7YC+bOIQFN5xcu1Vp11Y4faIXv6/Jpft6FMnl6YRxZqDZG0qQOW80stzxQ==
+
+postcss-image-set-function@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-4.0.6.tgz#bcff2794efae778c09441498f40e0c77374870a9"
+ integrity sha512-KfdC6vg53GC+vPd2+HYzsZ6obmPqOk6HY09kttU19+Gj1nC3S3XBVEXDHxkhxTohgZqzbUb94bKXvKDnYWBm/A==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-import@^14.1.0:
+ version "14.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0"
+ integrity sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==
+ dependencies:
+ postcss-value-parser "^4.0.0"
+ read-cache "^1.0.0"
+ resolve "^1.1.7"
+
+postcss-initial@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-4.0.1.tgz#529f735f72c5724a0fb30527df6fb7ac54d7de42"
+ integrity sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==
+
+postcss-js@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00"
+ integrity sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==
+ dependencies:
+ camelcase-css "^2.0.1"
+
+postcss-lab-function@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-4.2.0.tgz#e054e662c6480202f5760887ec1ae0d153357123"
+ integrity sha512-Zb1EO9DGYfa3CP8LhINHCcTTCTLI+R3t7AX2mKsDzdgVQ/GkCpHOTgOr6HBHslP7XDdVbqgHW5vvRPMdVANQ8w==
+ dependencies:
+ "@csstools/postcss-progressive-custom-properties" "^1.1.0"
+ postcss-value-parser "^4.2.0"
+
+postcss-load-config@^3.1.4:
+ version "3.1.4"
+ resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz#1ab2571faf84bb078877e1d07905eabe9ebda855"
+ integrity sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==
+ dependencies:
+ lilconfig "^2.0.5"
+ yaml "^1.10.2"
+
+postcss-loader@^6.2.1:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.1.tgz#0895f7346b1702103d30fdc66e4d494a93c008ef"
+ integrity sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==
+ dependencies:
+ cosmiconfig "^7.0.0"
+ klona "^2.0.5"
+ semver "^7.3.5"
+
+postcss-logical@^5.0.4:
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-5.0.4.tgz#ec75b1ee54421acc04d5921576b7d8db6b0e6f73"
+ integrity sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==
+
+postcss-media-minmax@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz#7140bddec173e2d6d657edbd8554a55794e2a5b5"
+ integrity sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==
+
+postcss-merge-longhand@^5.1.5:
+ version "5.1.5"
+ resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.5.tgz#b0e03bee3b964336f5f33c4fc8eacae608e91c05"
+ integrity sha512-NOG1grw9wIO+60arKa2YYsrbgvP6tp+jqc7+ZD5/MalIw234ooH2C6KlR6FEn4yle7GqZoBxSK1mLBE9KPur6w==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+ stylehacks "^5.1.0"
+
+postcss-merge-rules@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.2.tgz#7049a14d4211045412116d79b751def4484473a5"
+ integrity sha512-zKMUlnw+zYCWoPN6yhPjtcEdlJaMUZ0WyVcxTAmw3lkkN/NDMRkOkiuctQEoWAOvH7twaxUUdvBWl0d4+hifRQ==
+ dependencies:
+ browserslist "^4.16.6"
+ caniuse-api "^3.0.0"
+ cssnano-utils "^3.1.0"
+ postcss-selector-parser "^6.0.5"
+
+postcss-minify-font-values@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b"
+ integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-minify-gradients@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c"
+ integrity sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==
+ dependencies:
+ colord "^2.9.1"
+ cssnano-utils "^3.1.0"
+ postcss-value-parser "^4.2.0"
+
+postcss-minify-params@^5.1.3:
+ version "5.1.3"
+ resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.3.tgz#ac41a6465be2db735099bbd1798d85079a6dc1f9"
+ integrity sha512-bkzpWcjykkqIujNL+EVEPOlLYi/eZ050oImVtHU7b4lFS82jPnsCb44gvC6pxaNt38Els3jWYDHTjHKf0koTgg==
+ dependencies:
+ browserslist "^4.16.6"
+ cssnano-utils "^3.1.0"
+ postcss-value-parser "^4.2.0"
+
+postcss-minify-selectors@^5.2.1:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6"
+ integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==
+ dependencies:
+ postcss-selector-parser "^6.0.5"
+
+postcss-modules-extract-imports@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz#cda1f047c0ae80c97dbe28c3e76a43b88025741d"
+ integrity sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==
+
+postcss-modules-local-by-default@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz#ebbb54fae1598eecfdf691a02b3ff3b390a5a51c"
+ integrity sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==
+ dependencies:
+ icss-utils "^5.0.0"
+ postcss-selector-parser "^6.0.2"
+ postcss-value-parser "^4.1.0"
+
+postcss-modules-scope@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz#9ef3151456d3bbfa120ca44898dfca6f2fa01f06"
+ integrity sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==
+ dependencies:
+ postcss-selector-parser "^6.0.4"
+
+postcss-modules-values@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c"
+ integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==
+ dependencies:
+ icss-utils "^5.0.0"
+
+postcss-nested@5.0.6:
+ version "5.0.6"
+ resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-5.0.6.tgz#466343f7fc8d3d46af3e7dba3fcd47d052a945bc"
+ integrity sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==
+ dependencies:
+ postcss-selector-parser "^6.0.6"
+
+postcss-nesting@^10.1.7:
+ version "10.1.8"
+ resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-10.1.8.tgz#1675542cfedc3dc9621993f3abfdafa260c3a460"
+ integrity sha512-txdb3/idHYsBbNDFo1PFY0ExCgH5nfWi8G5lO49e6iuU42TydbODTzJgF5UuL5bhgeSlnAtDgfFTDG0Cl1zaSQ==
+ dependencies:
+ "@csstools/selector-specificity" "^2.0.0"
+ postcss-selector-parser "^6.0.10"
+
+postcss-normalize-charset@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed"
+ integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==
+
+postcss-normalize-display-values@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8"
+ integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-positions@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.0.tgz#902a7cb97cf0b9e8b1b654d4a43d451e48966458"
+ integrity sha512-8gmItgA4H5xiUxgN/3TVvXRoJxkAWLW6f/KKhdsH03atg0cB8ilXnrB5PpSshwVu/dD2ZsRFQcR1OEmSBDAgcQ==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-repeat-style@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.0.tgz#f6d6fd5a54f51a741cc84a37f7459e60ef7a6398"
+ integrity sha512-IR3uBjc+7mcWGL6CtniKNQ4Rr5fTxwkaDHwMBDGGs1x9IVRkYIT/M4NelZWkAOBdV6v3Z9S46zqaKGlyzHSchw==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-string@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228"
+ integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-timing-functions@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb"
+ integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-unicode@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.0.tgz#3d23aede35e160089a285e27bf715de11dc9db75"
+ integrity sha512-J6M3MizAAZ2dOdSjy2caayJLQT8E8K9XjLce8AUQMwOrCvjCHv24aLC/Lps1R1ylOfol5VIDMaM/Lo9NGlk1SQ==
+ dependencies:
+ browserslist "^4.16.6"
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-url@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc"
+ integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==
+ dependencies:
+ normalize-url "^6.0.1"
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize-whitespace@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa"
+ integrity sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-normalize@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-normalize/-/postcss-normalize-10.0.1.tgz#464692676b52792a06b06880a176279216540dd7"
+ integrity sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==
+ dependencies:
+ "@csstools/normalize.css" "*"
+ postcss-browser-comments "^4"
+ sanitize.css "*"
+
+postcss-opacity-percentage@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.2.tgz#bd698bb3670a0a27f6d657cc16744b3ebf3b1145"
+ integrity sha512-lyUfF7miG+yewZ8EAk9XUBIlrHyUE6fijnesuz+Mj5zrIHIEw6KcIZSOk/elVMqzLvREmXB83Zi/5QpNRYd47w==
+
+postcss-ordered-values@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.2.tgz#daffacd4abf327d52d5ac570b59dfbcf4b836614"
+ integrity sha512-wr2avRbW4HS2XE2ZCqpfp4N/tDC6GZKZ+SVP8UBTOVS8QWrc4TD8MYrebJrvVVlGPKszmiSCzue43NDiVtgDmg==
+ dependencies:
+ cssnano-utils "^3.1.0"
+ postcss-value-parser "^4.2.0"
+
+postcss-overflow-shorthand@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.3.tgz#ebcfc0483a15bbf1b27fdd9b3c10125372f4cbc2"
+ integrity sha512-CxZwoWup9KXzQeeIxtgOciQ00tDtnylYIlJBBODqkgS/PU2jISuWOL/mYLHmZb9ZhZiCaNKsCRiLp22dZUtNsg==
+
+postcss-page-break@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-3.0.4.tgz#7fbf741c233621622b68d435babfb70dd8c1ee5f"
+ integrity sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==
+
+postcss-place@^7.0.4:
+ version "7.0.4"
+ resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-7.0.4.tgz#eb026650b7f769ae57ca4f938c1addd6be2f62c9"
+ integrity sha512-MrgKeiiu5OC/TETQO45kV3npRjOFxEHthsqGtkh3I1rPbZSbXGD/lZVi9j13cYh+NA8PIAPyk6sGjT9QbRyvSg==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-preset-env@^7.0.1:
+ version "7.7.1"
+ resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-7.7.1.tgz#ca416c15fd63fd44abe5dcd2890a34b0a664d2c8"
+ integrity sha512-1sx6+Nl1wMVJzaYLVaz4OAR6JodIN/Z1upmVqLwSPCLT6XyxrEoePgNMHPH08kseLe3z06i9Vfkt/32BYEKDeA==
+ dependencies:
+ "@csstools/postcss-cascade-layers" "^1.0.2"
+ "@csstools/postcss-color-function" "^1.1.0"
+ "@csstools/postcss-font-format-keywords" "^1.0.0"
+ "@csstools/postcss-hwb-function" "^1.0.1"
+ "@csstools/postcss-ic-unit" "^1.0.0"
+ "@csstools/postcss-is-pseudo-class" "^2.0.4"
+ "@csstools/postcss-normalize-display-values" "^1.0.0"
+ "@csstools/postcss-oklab-function" "^1.1.0"
+ "@csstools/postcss-progressive-custom-properties" "^1.3.0"
+ "@csstools/postcss-stepped-value-functions" "^1.0.0"
+ "@csstools/postcss-trigonometric-functions" "^1.0.1"
+ "@csstools/postcss-unset-value" "^1.0.1"
+ autoprefixer "^10.4.7"
+ browserslist "^4.20.3"
+ css-blank-pseudo "^3.0.3"
+ css-has-pseudo "^3.0.4"
+ css-prefers-color-scheme "^6.0.3"
+ cssdb "^6.6.3"
+ postcss-attribute-case-insensitive "^5.0.1"
+ postcss-clamp "^4.1.0"
+ postcss-color-functional-notation "^4.2.3"
+ postcss-color-hex-alpha "^8.0.3"
+ postcss-color-rebeccapurple "^7.0.2"
+ postcss-custom-media "^8.0.1"
+ postcss-custom-properties "^12.1.7"
+ postcss-custom-selectors "^6.0.2"
+ postcss-dir-pseudo-class "^6.0.4"
+ postcss-double-position-gradients "^3.1.1"
+ postcss-env-function "^4.0.6"
+ postcss-focus-visible "^6.0.4"
+ postcss-focus-within "^5.0.4"
+ postcss-font-variant "^5.0.0"
+ postcss-gap-properties "^3.0.3"
+ postcss-image-set-function "^4.0.6"
+ postcss-initial "^4.0.1"
+ postcss-lab-function "^4.2.0"
+ postcss-logical "^5.0.4"
+ postcss-media-minmax "^5.0.0"
+ postcss-nesting "^10.1.7"
+ postcss-opacity-percentage "^1.1.2"
+ postcss-overflow-shorthand "^3.0.3"
+ postcss-page-break "^3.0.4"
+ postcss-place "^7.0.4"
+ postcss-pseudo-class-any-link "^7.1.4"
+ postcss-replace-overflow-wrap "^4.0.0"
+ postcss-selector-not "^6.0.0"
+ postcss-value-parser "^4.2.0"
+
+postcss-pseudo-class-any-link@^7.1.4:
+ version "7.1.4"
+ resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.4.tgz#ac72aac4fe11fc4a0a368691f8fd5fe89e95aba4"
+ integrity sha512-JxRcLXm96u14N3RzFavPIE9cRPuOqLDuzKeBsqi4oRk4vt8n0A7I0plFs/VXTg7U2n7g/XkQi0OwqTO3VWBfEg==
+ dependencies:
+ postcss-selector-parser "^6.0.10"
+
+postcss-reduce-initial@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.0.tgz#fc31659ea6e85c492fb2a7b545370c215822c5d6"
+ integrity sha512-5OgTUviz0aeH6MtBjHfbr57tml13PuedK/Ecg8szzd4XRMbYxH4572JFG067z+FqBIf6Zp/d+0581glkvvWMFw==
+ dependencies:
+ browserslist "^4.16.6"
+ caniuse-api "^3.0.0"
+
+postcss-reduce-transforms@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9"
+ integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+
+postcss-replace-overflow-wrap@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz#d2df6bed10b477bf9c52fab28c568b4b29ca4319"
+ integrity sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==
+
+postcss-selector-not@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-6.0.0.tgz#d100f273d345917246762300411b4d2e24905047"
+ integrity sha512-i/HI/VNd3V9e1WOLCwJsf9nePBRXqcGtVibcJ9FsVo0agfDEfsLSlFt94aYjY35wUNcdG0KrvdyjEr7It50wLQ==
+ dependencies:
+ postcss-selector-parser "^6.0.10"
+
+postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9:
+ version "6.0.10"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
+ integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-svgo@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d"
+ integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==
+ dependencies:
+ postcss-value-parser "^4.2.0"
+ svgo "^2.7.0"
+
+postcss-unique-selectors@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6"
+ integrity sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==
+ dependencies:
+ postcss-selector-parser "^6.0.5"
+
+postcss-value-parser@^4.0.0, postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
+ integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
+
+postcss@^7.0.35:
+ version "7.0.39"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.39.tgz#9624375d965630e2e1f2c02a935c82a59cb48309"
+ integrity sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==
+ dependencies:
+ picocolors "^0.2.1"
+ source-map "^0.6.1"
+
+postcss@^8.3.5, postcss@^8.4.14, postcss@^8.4.4, postcss@^8.4.7:
+ version "8.4.14"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf"
+ integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==
+ dependencies:
+ nanoid "^3.3.4"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.2"
+
+prelude-ls@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+ integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+
+prelude-ls@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
+ integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==
+
+prettier@2.5.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.5.1.tgz#fff75fa9d519c54cf0fce328c1017d94546bc56a"
+ integrity sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==
+
+pretty-bytes@^5.3.0, pretty-bytes@^5.4.1:
+ version "5.6.0"
+ resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
+ integrity sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==
+
+pretty-error@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-4.0.0.tgz#90a703f46dd7234adb46d0f84823e9d1cb8f10d6"
+ integrity sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==
+ dependencies:
+ lodash "^4.17.20"
+ renderkid "^3.0.0"
+
+pretty-format@^26.6.2:
+ version "26.6.2"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93"
+ integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==
+ dependencies:
+ "@jest/types" "^26.6.2"
+ ansi-regex "^5.0.0"
+ ansi-styles "^4.0.0"
+ react-is "^17.0.1"
+
+pretty-format@^27.0.0, pretty-format@^27.5.1:
+ version "27.5.1"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e"
+ integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
+ dependencies:
+ ansi-regex "^5.0.1"
+ ansi-styles "^5.0.0"
+ react-is "^17.0.1"
+
+pretty-format@^28.1.1:
+ version "28.1.1"
+ resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-28.1.1.tgz#f731530394e0f7fcd95aba6b43c50e02d86b95cb"
+ integrity sha512-wwJbVTGFHeucr5Jw2bQ9P+VYHyLdAqedFLEkdQUVaBF/eiidDwH5OpilINq4mEfhbCjLnirt6HTTDhv1HaTIQw==
+ dependencies:
+ "@jest/schemas" "^28.0.2"
+ ansi-regex "^5.0.1"
+ ansi-styles "^5.0.0"
+ react-is "^18.0.0"
+
+process-nextick-args@~2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
+ integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
+
+promise@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e"
+ integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==
+ dependencies:
+ asap "~2.0.6"
+
+prompts@^2.0.1, prompts@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
+ integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
+ dependencies:
+ kleur "^3.0.3"
+ sisteransi "^1.0.5"
+
+prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
+ version "15.8.1"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
+ integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.13.1"
+
+proxy-addr@~2.0.7:
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
+ integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
+ dependencies:
+ forwarded "0.2.0"
+ ipaddr.js "1.9.1"
+
+psl@^1.1.33:
+ version "1.8.0"
+ resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
+ integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
+
+punycode@^2.1.0, punycode@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
+ integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
+
+q@^1.1.2:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
+ integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==
+
+qs@6.10.3:
+ version "6.10.3"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
+ integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==
+ dependencies:
+ side-channel "^1.0.4"
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+quick-lru@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
+ integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
+
+raf@^3.4.1:
+ version "3.4.1"
+ resolved "https://registry.yarnpkg.com/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
+ integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
+ dependencies:
+ performance-now "^2.1.0"
+
+randombytes@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a"
+ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==
+ dependencies:
+ safe-buffer "^5.1.0"
+
+range-parser@^1.2.1, range-parser@~1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
+ integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
+
+raw-body@2.5.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857"
+ integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==
+ dependencies:
+ bytes "3.1.2"
+ http-errors "2.0.0"
+ iconv-lite "0.4.24"
+ unpipe "1.0.0"
+
+react-app-polyfill@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz#95221e0a9bd259e5ca6b177c7bb1cb6768f68fd7"
+ integrity sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==
+ dependencies:
+ core-js "^3.19.2"
+ object-assign "^4.1.1"
+ promise "^8.1.0"
+ raf "^3.4.1"
+ regenerator-runtime "^0.13.9"
+ whatwg-fetch "^3.6.2"
+
+react-chartjs-2@^3.0.4:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-3.3.0.tgz#3f62681645acccc1ab27a9186c70f79d6d417f73"
+ integrity sha512-4Mt0SR2aiUbWi/4762odRBYSnbNKSs4HWc0o3IW43py5bMfmfpeZU95w6mbvtuLZH/M3GsPJMU8DvDc+5U9blQ==
+
+react-dev-utils@^12.0.1:
+ version "12.0.1"
+ resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73"
+ integrity sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==
+ dependencies:
+ "@babel/code-frame" "^7.16.0"
+ address "^1.1.2"
+ browserslist "^4.18.1"
+ chalk "^4.1.2"
+ cross-spawn "^7.0.3"
+ detect-port-alt "^1.1.6"
+ escape-string-regexp "^4.0.0"
+ filesize "^8.0.6"
+ find-up "^5.0.0"
+ fork-ts-checker-webpack-plugin "^6.5.0"
+ global-modules "^2.0.0"
+ globby "^11.0.4"
+ gzip-size "^6.0.0"
+ immer "^9.0.7"
+ is-root "^2.1.0"
+ loader-utils "^3.2.0"
+ open "^8.4.0"
+ pkg-up "^3.1.0"
+ prompts "^2.4.2"
+ react-error-overlay "^6.0.11"
+ recursive-readdir "^2.2.2"
+ shell-quote "^1.7.3"
+ strip-ansi "^6.0.1"
+ text-table "^0.2.0"
+
+react-dom@^17.0.2:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
+ integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+ scheduler "^0.20.2"
+
+react-error-overlay@^6.0.11:
+ version "6.0.11"
+ resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb"
+ integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==
+
+react-flow-renderer@^10.1.0:
+ version "10.3.6"
+ resolved "https://registry.yarnpkg.com/react-flow-renderer/-/react-flow-renderer-10.3.6.tgz#9b6a963fdb68f99800207bea835316f3339ed11f"
+ integrity sha512-pHx+QRjfY42o8wCJwgmT5gRDqrLIKq2FM9j0+BmwzUVHK/DglJC0DbAKfoM6MR6Czrz4Y2bdrBFadrwdEg62XA==
+ dependencies:
+ "@babel/runtime" "^7.18.0"
+ classcat "^5.0.3"
+ d3-drag "^3.0.0"
+ d3-selection "^3.0.0"
+ d3-zoom "^3.0.0"
+ zustand "^3.7.2"
+
+react-hook-form@^7.6.6:
+ version "7.31.3"
+ resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.31.3.tgz#b61bafb9a7435f91695351a7a9f714d8c4df0121"
+ integrity sha512-NVZdCWViIWXXXlQ3jxVQH0NuNfwPf8A/0KvuCxrM9qxtP1qYosfR2ZudarziFrVOC7eTUbWbm1T4OyYCwv9oSQ==
+
+react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0:
+ version "16.13.1"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
+ integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+
+react-is@^17.0.1, react-is@^17.0.2:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
+ integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
+
+react-is@^18.0.0:
+ version "18.1.0"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.1.0.tgz#61aaed3096d30eacf2a2127118b5b41387d32a67"
+ integrity sha512-Fl7FuabXsJnV5Q1qIOQwx/sagGF18kogb4gpfcG4gjLBWO0WDiiz1ko/ExayuxE7InyQkBLkxRFG5oxY6Uu3Kg==
+
+react-is@^18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
+ integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
+
+react-mathjax-preview@^2.2.3:
+ version "2.2.6"
+ resolved "https://registry.yarnpkg.com/react-mathjax-preview/-/react-mathjax-preview-2.2.6.tgz#adcdaf73733e45f98562105c5822d851fe3c105e"
+ integrity sha512-lS+wQ49jd/XyXu8tTWWZ38qfNJrAlxsDjkUrQoldfM1MdS6s18DxFV4dwP9xoAsq86kuSb/raXU8qJrH5dtV5w==
+ dependencies:
+ dompurify "^2.0.8"
+
+react-redux@^7.2.4:
+ version "7.2.8"
+ resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.8.tgz#a894068315e65de5b1b68899f9c6ee0923dd28de"
+ integrity sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==
+ dependencies:
+ "@babel/runtime" "^7.15.4"
+ "@types/react-redux" "^7.1.20"
+ hoist-non-react-statics "^3.3.2"
+ loose-envify "^1.4.0"
+ prop-types "^15.7.2"
+ react-is "^17.0.2"
+
+react-refresh@^0.11.0:
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.11.0.tgz#77198b944733f0f1f1a90e791de4541f9f074046"
+ integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
+
+react-router-dom@^5.2.0:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.3.tgz#8779fc28e6691d07afcaf98406d3812fe6f11199"
+ integrity sha512-Ov0tGPMBgqmbu5CDmN++tv2HQ9HlWDuWIIqn4b88gjlAN5IHI+4ZUZRcpz9Hl0azFIwihbLDYw1OiHGRo7ZIng==
+ dependencies:
+ "@babel/runtime" "^7.12.13"
+ history "^4.9.0"
+ loose-envify "^1.3.1"
+ prop-types "^15.6.2"
+ react-router "5.3.3"
+ tiny-invariant "^1.0.2"
+ tiny-warning "^1.0.0"
+
+react-router@5.3.3:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.3.tgz#8e3841f4089e728cf82a429d92cdcaa5e4a3a288"
+ integrity sha512-mzQGUvS3bM84TnbtMYR8ZjKnuPJ71IjSzR+DE6UkUqvN4czWIqEs17yLL8xkAycv4ev0AiN+IGrWu88vJs/p2w==
+ dependencies:
+ "@babel/runtime" "^7.12.13"
+ history "^4.9.0"
+ hoist-non-react-statics "^3.1.0"
+ loose-envify "^1.3.1"
+ mini-create-react-context "^0.4.0"
+ path-to-regexp "^1.7.0"
+ prop-types "^15.6.2"
+ react-is "^16.6.0"
+ tiny-invariant "^1.0.2"
+ tiny-warning "^1.0.0"
+
+react-scripts@^5.0.0:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-5.0.1.tgz#6285dbd65a8ba6e49ca8d651ce30645a6d980003"
+ integrity sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==
+ dependencies:
+ "@babel/core" "^7.16.0"
+ "@pmmmwh/react-refresh-webpack-plugin" "^0.5.3"
+ "@svgr/webpack" "^5.5.0"
+ babel-jest "^27.4.2"
+ babel-loader "^8.2.3"
+ babel-plugin-named-asset-import "^0.3.8"
+ babel-preset-react-app "^10.0.1"
+ bfj "^7.0.2"
+ browserslist "^4.18.1"
+ camelcase "^6.2.1"
+ case-sensitive-paths-webpack-plugin "^2.4.0"
+ css-loader "^6.5.1"
+ css-minimizer-webpack-plugin "^3.2.0"
+ dotenv "^10.0.0"
+ dotenv-expand "^5.1.0"
+ eslint "^8.3.0"
+ eslint-config-react-app "^7.0.1"
+ eslint-webpack-plugin "^3.1.1"
+ file-loader "^6.2.0"
+ fs-extra "^10.0.0"
+ html-webpack-plugin "^5.5.0"
+ identity-obj-proxy "^3.0.0"
+ jest "^27.4.3"
+ jest-resolve "^27.4.2"
+ jest-watch-typeahead "^1.0.0"
+ mini-css-extract-plugin "^2.4.5"
+ postcss "^8.4.4"
+ postcss-flexbugs-fixes "^5.0.2"
+ postcss-loader "^6.2.1"
+ postcss-normalize "^10.0.1"
+ postcss-preset-env "^7.0.1"
+ prompts "^2.4.2"
+ react-app-polyfill "^3.0.0"
+ react-dev-utils "^12.0.1"
+ react-refresh "^0.11.0"
+ resolve "^1.20.0"
+ resolve-url-loader "^4.0.0"
+ sass-loader "^12.3.0"
+ semver "^7.3.5"
+ source-map-loader "^3.0.0"
+ style-loader "^3.3.1"
+ tailwindcss "^3.0.2"
+ terser-webpack-plugin "^5.2.5"
+ webpack "^5.64.4"
+ webpack-dev-server "^4.6.0"
+ webpack-manifest-plugin "^4.0.2"
+ workbox-webpack-plugin "^6.4.1"
+ optionalDependencies:
+ fsevents "^2.3.2"
+
+react-transition-group@^4.4.5:
+ version "4.4.5"
+ resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"
+ integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
+ dependencies:
+ "@babel/runtime" "^7.5.5"
+ dom-helpers "^5.0.1"
+ loose-envify "^1.4.0"
+ prop-types "^15.6.2"
+
+react@^17.0.0:
+ version "17.0.2"
+ resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
+ integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+
+read-cache@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
+ integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
+ dependencies:
+ pify "^2.3.0"
+
+readable-stream@^2.0.1:
+ version "2.3.7"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
+ integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
+ dependencies:
+ core-util-is "~1.0.0"
+ inherits "~2.0.3"
+ isarray "~1.0.0"
+ process-nextick-args "~2.0.0"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.1.1"
+ util-deprecate "~1.0.1"
+
+readable-stream@^3.0.6:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
+ integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
+ dependencies:
+ inherits "^2.0.3"
+ string_decoder "^1.1.1"
+ util-deprecate "^1.0.1"
+
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
+recursive-readdir@^2.2.2:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f"
+ integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==
+ dependencies:
+ minimatch "3.0.4"
+
+redent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f"
+ integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==
+ dependencies:
+ indent-string "^4.0.0"
+ strip-indent "^3.0.0"
+
+redux-thunk@^2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.4.1.tgz#0dd8042cf47868f4b29699941de03c9301a75714"
+ integrity sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==
+
+redux@^4.0.0, redux@^4.1.2:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.0.tgz#46f10d6e29b6666df758780437651eeb2b969f13"
+ integrity sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==
+ dependencies:
+ "@babel/runtime" "^7.9.2"
+
+regenerate-unicode-properties@^10.0.1:
+ version "10.0.1"
+ resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz#7f442732aa7934a3740c779bb9b3340dccc1fb56"
+ integrity sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==
+ dependencies:
+ regenerate "^1.4.2"
+
+regenerate@^1.4.2:
+ version "1.4.2"
+ resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a"
+ integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==
+
+regenerator-runtime@^0.13.11:
+ version "0.13.11"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
+ integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==
+
+regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.9:
+ version "0.13.9"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"
+ integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==
+
+regenerator-transform@^0.15.0:
+ version "0.15.0"
+ resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537"
+ integrity sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==
+ dependencies:
+ "@babel/runtime" "^7.8.4"
+
+regex-parser@^2.2.11:
+ version "2.2.11"
+ resolved "https://registry.yarnpkg.com/regex-parser/-/regex-parser-2.2.11.tgz#3b37ec9049e19479806e878cabe7c1ca83ccfe58"
+ integrity sha512-jbD/FT0+9MBU2XAZluI7w2OBs1RBi6p9M83nkoZayQXXU9e8Robt69FcZc7wU4eJD/YFTjn1JdCk3rbMJajz8Q==
+
+regexp.prototype.flags@^1.4.1, regexp.prototype.flags@^1.4.3:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac"
+ integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ functions-have-names "^1.2.2"
+
+regexpp@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2"
+ integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
+
+regexpu-core@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.0.1.tgz#c531122a7840de743dcf9c83e923b5560323ced3"
+ integrity sha512-CriEZlrKK9VJw/xQGJpQM5rY88BtuL8DM+AEwvcThHilbxiTAy8vq4iJnd2tqq8wLmjbGZzP7ZcKFjbGkmEFrw==
+ dependencies:
+ regenerate "^1.4.2"
+ regenerate-unicode-properties "^10.0.1"
+ regjsgen "^0.6.0"
+ regjsparser "^0.8.2"
+ unicode-match-property-ecmascript "^2.0.0"
+ unicode-match-property-value-ecmascript "^2.0.0"
+
+regjsgen@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d"
+ integrity sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==
+
+regjsparser@^0.8.2:
+ version "0.8.4"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.8.4.tgz#8a14285ffcc5de78c5b95d62bbf413b6bc132d5f"
+ integrity sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==
+ dependencies:
+ jsesc "~0.5.0"
+
+relateurl@^0.2.7:
+ version "0.2.7"
+ resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9"
+ integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==
+
+renderkid@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-3.0.0.tgz#5fd823e4d6951d37358ecc9a58b1f06836b6268a"
+ integrity sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==
+ dependencies:
+ css-select "^4.1.3"
+ dom-converter "^0.2.0"
+ htmlparser2 "^6.1.0"
+ lodash "^4.17.21"
+ strip-ansi "^6.0.1"
+
+require-directory@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
+ integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
+
+require-from-string@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+ integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+
+requires-port@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
+ integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
+
+reselect@^4.1.5:
+ version "4.1.6"
+ resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.6.tgz#19ca2d3d0b35373a74dc1c98692cdaffb6602656"
+ integrity sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ==
+
+resolve-cwd@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d"
+ integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==
+ dependencies:
+ resolve-from "^5.0.0"
+
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+resolve-from@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
+ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+
+resolve-pathname@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd"
+ integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==
+
+resolve-url-loader@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz#d50d4ddc746bb10468443167acf800dcd6c3ad57"
+ integrity sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==
+ dependencies:
+ adjust-sourcemap-loader "^4.0.0"
+ convert-source-map "^1.7.0"
+ loader-utils "^2.0.0"
+ postcss "^7.0.35"
+ source-map "0.6.1"
+
+resolve.exports@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9"
+ integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ==
+
+resolve@^1.1.7, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.0:
+ version "1.22.0"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198"
+ integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==
+ dependencies:
+ is-core-module "^2.8.1"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+resolve@^2.0.0-next.3:
+ version "2.0.0-next.3"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.3.tgz#d41016293d4a8586a39ca5d9b5f15cbea1f55e46"
+ integrity sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q==
+ dependencies:
+ is-core-module "^2.2.0"
+ path-parse "^1.0.6"
+
+retry@^0.13.1:
+ version "0.13.1"
+ resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
+ integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rimraf@^3.0.0, rimraf@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+ dependencies:
+ glob "^7.1.3"
+
+rollup-plugin-terser@^7.0.0:
+ version "7.0.2"
+ resolved "https://registry.yarnpkg.com/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz#e8fbba4869981b2dc35ae7e8a502d5c6c04d324d"
+ integrity sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==
+ dependencies:
+ "@babel/code-frame" "^7.10.4"
+ jest-worker "^26.2.1"
+ serialize-javascript "^4.0.0"
+ terser "^5.0.0"
+
+rollup@^2.43.1:
+ version "2.75.6"
+ resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.75.6.tgz#ac4dc8600f95942a0180f61c7c9d6200e374b439"
+ integrity sha512-OEf0TgpC9vU6WGROJIk1JA3LR5vk/yvqlzxqdrE2CzzXnqKXNzbAwlWUXis8RS3ZPe7LAq+YUxsRa0l3r27MLA==
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
+safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0:
+ version "5.2.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
+ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+
+"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
+ integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
+
+sanitize.css@*:
+ version "13.0.0"
+ resolved "https://registry.yarnpkg.com/sanitize.css/-/sanitize.css-13.0.0.tgz#2675553974b27964c75562ade3bd85d79879f173"
+ integrity sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==
+
+sass-loader@^12.3.0:
+ version "12.6.0"
+ resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-12.6.0.tgz#5148362c8e2cdd4b950f3c63ac5d16dbfed37bcb"
+ integrity sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==
+ dependencies:
+ klona "^2.0.4"
+ neo-async "^2.6.2"
+
+sax@~1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
+ integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
+
+saxes@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d"
+ integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==
+ dependencies:
+ xmlchars "^2.2.0"
+
+scheduler@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
+ integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
+ dependencies:
+ loose-envify "^1.1.0"
+ object-assign "^4.1.1"
+
+schema-utils@2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7"
+ integrity sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==
+ dependencies:
+ "@types/json-schema" "^7.0.4"
+ ajv "^6.12.2"
+ ajv-keywords "^3.4.1"
+
+schema-utils@^2.6.5:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
+ integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==
+ dependencies:
+ "@types/json-schema" "^7.0.5"
+ ajv "^6.12.4"
+ ajv-keywords "^3.5.2"
+
+schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281"
+ integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==
+ dependencies:
+ "@types/json-schema" "^7.0.8"
+ ajv "^6.12.5"
+ ajv-keywords "^3.5.2"
+
+schema-utils@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7"
+ integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==
+ dependencies:
+ "@types/json-schema" "^7.0.9"
+ ajv "^8.8.0"
+ ajv-formats "^2.1.1"
+ ajv-keywords "^5.0.0"
+
+select-hose@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
+ integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==
+
+selfsigned@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.0.1.tgz#8b2df7fa56bf014d19b6007655fff209c0ef0a56"
+ integrity sha512-LmME957M1zOsUhG+67rAjKfiWFox3SBxE/yymatMZsAx+oMrJ0YQ8AToOnyCm7xbeg2ep37IHLxdu0o2MavQOQ==
+ dependencies:
+ node-forge "^1"
+
+semver@7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
+ integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
+
+semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
+ integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+
+semver@^7.3.2, semver@^7.3.5, semver@^7.3.7:
+ version "7.3.7"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f"
+ integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==
+ dependencies:
+ lru-cache "^6.0.0"
+
+send@0.18.0:
+ version "0.18.0"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be"
+ integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==
+ dependencies:
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ mime "1.6.0"
+ ms "2.1.3"
+ on-finished "2.4.1"
+ range-parser "~1.2.1"
+ statuses "2.0.1"
+
+serialize-javascript@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
+ integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==
+ dependencies:
+ randombytes "^2.1.0"
+
+serialize-javascript@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8"
+ integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==
+ dependencies:
+ randombytes "^2.1.0"
+
+serve-index@^1.9.1:
+ version "1.9.1"
+ resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239"
+ integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==
+ dependencies:
+ accepts "~1.3.4"
+ batch "0.6.1"
+ debug "2.6.9"
+ escape-html "~1.0.3"
+ http-errors "~1.6.2"
+ mime-types "~2.1.17"
+ parseurl "~1.3.2"
+
+serve-static@1.15.0:
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
+ integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
+ dependencies:
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ parseurl "~1.3.3"
+ send "0.18.0"
+
+setprototypeof@1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656"
+ integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==
+
+setprototypeof@1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424"
+ integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+shell-quote@^1.7.3:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123"
+ integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==
+
+side-channel@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
+ integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
+ dependencies:
+ call-bind "^1.0.0"
+ get-intrinsic "^1.0.2"
+ object-inspect "^1.9.0"
+
+signal-exit@^3.0.2, signal-exit@^3.0.3:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
+ integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+
+sisteransi@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
+ integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==
+
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+slash@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7"
+ integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==
+
+sockjs@^0.3.24:
+ version "0.3.24"
+ resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce"
+ integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==
+ dependencies:
+ faye-websocket "^0.11.3"
+ uuid "^8.3.2"
+ websocket-driver "^0.7.4"
+
+source-list-map@^2.0.0, source-list-map@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34"
+ integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==
+
+source-map-js@^1.0.1, source-map-js@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
+ integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
+
+source-map-loader@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-3.0.1.tgz#9ae5edc7c2d42570934be4c95d1ccc6352eba52d"
+ integrity sha512-Vp1UsfyPvgujKQzi4pyDiTOnE3E4H+yHvkVRN3c/9PJmQS4CQJExvcDvaX/D+RV+xQben9HJ56jMJS3CgUeWyA==
+ dependencies:
+ abab "^2.0.5"
+ iconv-lite "^0.6.3"
+ source-map-js "^1.0.1"
+
+source-map-resolve@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2"
+ integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w==
+ dependencies:
+ atob "^2.1.2"
+ decode-uri-component "^0.2.0"
+
+source-map-support@^0.5.6, source-map-support@~0.5.20:
+ version "0.5.21"
+ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
+ integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
+ dependencies:
+ buffer-from "^1.0.0"
+ source-map "^0.6.0"
+
+source-map@0.6.1, source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
+ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
+
+source-map@^0.5.7:
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
+ integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
+
+source-map@^0.7.3:
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656"
+ integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==
+
+source-map@^0.8.0-beta.0:
+ version "0.8.0-beta.0"
+ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.8.0-beta.0.tgz#d4c1bb42c3f7ee925f005927ba10709e0d1d1f11"
+ integrity sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==
+ dependencies:
+ whatwg-url "^7.0.0"
+
+sourcemap-codec@^1.4.8:
+ version "1.4.8"
+ resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
+ integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==
+
+spdy-transport@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31"
+ integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==
+ dependencies:
+ debug "^4.1.0"
+ detect-node "^2.0.4"
+ hpack.js "^2.1.6"
+ obuf "^1.1.2"
+ readable-stream "^3.0.6"
+ wbuf "^1.7.3"
+
+spdy@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.2.tgz#b74f466203a3eda452c02492b91fb9e84a27677b"
+ integrity sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==
+ dependencies:
+ debug "^4.1.0"
+ handle-thing "^2.0.0"
+ http-deceiver "^1.2.7"
+ select-hose "^2.0.0"
+ spdy-transport "^3.0.0"
+
+sprintf-js@~1.0.2:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
+ integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==
+
+stable@^0.1.8:
+ version "0.1.8"
+ resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf"
+ integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==
+
+stack-utils@^2.0.3:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.5.tgz#d25265fca995154659dbbfba3b49254778d2fdd5"
+ integrity sha512-xrQcmYhOsn/1kX+Vraq+7j4oE2j/6BFscZ0etmYg81xuM8Gq0022Pxb8+IqgOFUIaxHs0KaSb7T1+OegiNrNFA==
+ dependencies:
+ escape-string-regexp "^2.0.0"
+
+stackframe@^1.3.4:
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.3.4.tgz#b881a004c8c149a5e8efef37d51b16e412943310"
+ integrity sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==
+
+statuses@2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
+ integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
+
+"statuses@>= 1.4.0 < 2":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c"
+ integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==
+
+string-length@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
+ integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==
+ dependencies:
+ char-regex "^1.0.2"
+ strip-ansi "^6.0.0"
+
+string-length@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/string-length/-/string-length-5.0.1.tgz#3d647f497b6e8e8d41e422f7e0b23bc536c8381e"
+ integrity sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==
+ dependencies:
+ char-regex "^2.0.0"
+ strip-ansi "^7.0.1"
+
+string-natural-compare@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4"
+ integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==
+
+string-width@^4.1.0, string-width@^4.2.0:
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+string.prototype.matchall@^4.0.6, string.prototype.matchall@^4.0.7:
+ version "4.0.7"
+ resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz#8e6ecb0d8a1fb1fda470d81acecb2dba057a481d"
+ integrity sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.3"
+ es-abstract "^1.19.1"
+ get-intrinsic "^1.1.1"
+ has-symbols "^1.0.3"
+ internal-slot "^1.0.3"
+ regexp.prototype.flags "^1.4.1"
+ side-channel "^1.0.4"
+
+string.prototype.trimend@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0"
+ integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
+
+string.prototype.trimstart@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef"
+ integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.1.4"
+ es-abstract "^1.19.5"
+
+string_decoder@^1.1.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
+ integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
+ dependencies:
+ safe-buffer "~5.2.0"
+
+string_decoder@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
+ integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==
+ dependencies:
+ safe-buffer "~5.1.0"
+
+stringify-object@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629"
+ integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==
+ dependencies:
+ get-own-enumerable-property-symbols "^3.0.0"
+ is-obj "^1.0.1"
+ is-regexp "^1.0.0"
+
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+strip-ansi@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2"
+ integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==
+ dependencies:
+ ansi-regex "^6.0.1"
+
+strip-bom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+ integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
+
+strip-bom@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878"
+ integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==
+
+strip-comments@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/strip-comments/-/strip-comments-2.0.1.tgz#4ad11c3fbcac177a67a40ac224ca339ca1c1ba9b"
+ integrity sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==
+
+strip-final-newline@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
+ integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
+
+strip-indent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
+ integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
+ dependencies:
+ min-indent "^1.0.0"
+
+strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+ integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+
+style-loader@^3.3.1:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.1.tgz#057dfa6b3d4d7c7064462830f9113ed417d38575"
+ integrity sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==
+
+stylehacks@^5.1.0:
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.0.tgz#a40066490ca0caca04e96c6b02153ddc39913520"
+ integrity sha512-SzLmvHQTrIWfSgljkQCw2++C9+Ne91d/6Sp92I8c5uHTcy/PgeHamwITIbBW9wnFTY/3ZfSXR9HIL6Ikqmcu6Q==
+ dependencies:
+ browserslist "^4.16.6"
+ postcss-selector-parser "^6.0.4"
+
+stylis@4.1.3:
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.1.3.tgz#fd2fbe79f5fed17c55269e16ed8da14c84d069f7"
+ integrity sha512-GP6WDNWf+o403jrEp9c5jibKavrtLW+/qYGhFxFrG8maXhwTBI7gLLhiBb0o7uFccWN+EOS9aMO6cGHWAO07OA==
+
+supports-color@^5.3.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+ dependencies:
+ has-flag "^3.0.0"
+
+supports-color@^7.0.0, supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-color@^8.0.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c"
+ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-hyperlinks@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb"
+ integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ==
+ dependencies:
+ has-flag "^4.0.0"
+ supports-color "^7.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+svg-parser@^2.0.2:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5"
+ integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==
+
+svgo@^1.2.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167"
+ integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==
+ dependencies:
+ chalk "^2.4.1"
+ coa "^2.0.2"
+ css-select "^2.0.0"
+ css-select-base-adapter "^0.1.1"
+ css-tree "1.0.0-alpha.37"
+ csso "^4.0.2"
+ js-yaml "^3.13.1"
+ mkdirp "~0.5.1"
+ object.values "^1.1.0"
+ sax "~1.2.4"
+ stable "^0.1.8"
+ unquote "~1.1.1"
+ util.promisify "~1.0.0"
+
+svgo@^2.7.0:
+ version "2.8.0"
+ resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24"
+ integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==
+ dependencies:
+ "@trysound/sax" "0.2.0"
+ commander "^7.2.0"
+ css-select "^4.1.3"
+ css-tree "^1.1.3"
+ csso "^4.2.0"
+ picocolors "^1.0.0"
+ stable "^0.1.8"
+
+symbol-tree@^3.2.4:
+ version "3.2.4"
+ resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
+ integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
+
+tailwindcss@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.1.0.tgz#126e5abd0831dbfdaabea1474c746384c73836ab"
+ integrity sha512-XzXq31Fj6RizhlFVNLBlDqzs0dXuIEOAknuOcKx2R/IIQbEz5DnngslYY4JNN6e9JkNBjHGm1w2XDABsADg1ng==
+ dependencies:
+ arg "^5.0.1"
+ chokidar "^3.5.3"
+ color-name "^1.1.4"
+ detective "^5.2.1"
+ didyoumean "^1.2.2"
+ dlv "^1.1.3"
+ fast-glob "^3.2.11"
+ glob-parent "^6.0.2"
+ is-glob "^4.0.3"
+ lilconfig "^2.0.5"
+ normalize-path "^3.0.0"
+ object-hash "^3.0.0"
+ picocolors "^1.0.0"
+ postcss "^8.4.14"
+ postcss-import "^14.1.0"
+ postcss-js "^4.0.0"
+ postcss-load-config "^3.1.4"
+ postcss-nested "5.0.6"
+ postcss-selector-parser "^6.0.10"
+ postcss-value-parser "^4.2.0"
+ quick-lru "^5.1.1"
+ resolve "^1.22.0"
+
+tapable@^1.0.0:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2"
+ integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==
+
+tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
+ integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+
+temp-dir@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e"
+ integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==
+
+tempy@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.6.0.tgz#65e2c35abc06f1124a97f387b08303442bde59f3"
+ integrity sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==
+ dependencies:
+ is-stream "^2.0.0"
+ temp-dir "^2.0.0"
+ type-fest "^0.16.0"
+ unique-string "^2.0.0"
+
+terminal-link@^2.0.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994"
+ integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==
+ dependencies:
+ ansi-escapes "^4.2.1"
+ supports-hyperlinks "^2.0.0"
+
+terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.5:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.3.tgz#8033db876dd5875487213e87c627bca323e5ed90"
+ integrity sha512-Fx60G5HNYknNTNQnzQ1VePRuu89ZVYWfjRAeT5rITuCY/1b08s49e5kSQwHDirKZWuoKOBRFS98EUUoZ9kLEwQ==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.7"
+ jest-worker "^27.4.5"
+ schema-utils "^3.1.1"
+ serialize-javascript "^6.0.0"
+ terser "^5.7.2"
+
+terser@^5.0.0, terser@^5.10.0, terser@^5.7.2:
+ version "5.14.2"
+ resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10"
+ integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==
+ dependencies:
+ "@jridgewell/source-map" "^0.3.2"
+ acorn "^8.5.0"
+ commander "^2.20.0"
+ source-map-support "~0.5.20"
+
+test-exclude@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
+ integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==
+ dependencies:
+ "@istanbuljs/schema" "^0.1.2"
+ glob "^7.1.4"
+ minimatch "^3.0.4"
+
+text-table@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+ integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
+
+throat@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/throat/-/throat-6.0.1.tgz#d514fedad95740c12c2d7fc70ea863eb51ade375"
+ integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==
+
+thunky@^1.0.2:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d"
+ integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==
+
+tiny-invariant@^1.0.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9"
+ integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==
+
+tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
+ integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
+
+tmpl@1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
+ integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
+
+to-fast-properties@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
+ integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+toidentifier@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
+ integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
+
+tough-cookie@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
+ integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==
+ dependencies:
+ psl "^1.1.33"
+ punycode "^2.1.1"
+ universalify "^0.1.2"
+
+tr46@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09"
+ integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=
+ dependencies:
+ punycode "^2.1.0"
+
+tr46@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.1.0.tgz#fa87aa81ca5d5941da8cbf1f9b749dc969a4e240"
+ integrity sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==
+ dependencies:
+ punycode "^2.1.1"
+
+tryer@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8"
+ integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==
+
+tsconfig-paths@^3.14.1:
+ version "3.14.1"
+ resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a"
+ integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==
+ dependencies:
+ "@types/json5" "^0.0.29"
+ json5 "^1.0.1"
+ minimist "^1.2.6"
+ strip-bom "^3.0.0"
+
+tslib@^1.8.1:
+ version "1.14.1"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
+ integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
+
+tslib@^2.0.3:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
+ integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
+
+tsutils@^3.21.0:
+ version "3.21.0"
+ resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623"
+ integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==
+ dependencies:
+ tslib "^1.8.1"
+
+type-check@^0.4.0, type-check@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+ integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+ dependencies:
+ prelude-ls "^1.2.1"
+
+type-check@~0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
+ integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=
+ dependencies:
+ prelude-ls "~1.1.2"
+
+type-detect@4.0.8:
+ version "4.0.8"
+ resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
+ integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
+
+type-fest@^0.16.0:
+ version "0.16.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.16.0.tgz#3240b891a78b0deae910dbeb86553e552a148860"
+ integrity sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==
+
+type-fest@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
+ integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+
+type-fest@^0.21.3:
+ version "0.21.3"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
+ integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
+
+type-is@~1.6.18:
+ version "1.6.18"
+ resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
+ integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
+ dependencies:
+ media-typer "0.3.0"
+ mime-types "~2.1.24"
+
+typedarray-to-buffer@^3.1.5:
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080"
+ integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==
+ dependencies:
+ is-typedarray "^1.0.0"
+
+unbox-primitive@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
+ integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
+ dependencies:
+ call-bind "^1.0.2"
+ has-bigints "^1.0.2"
+ has-symbols "^1.0.3"
+ which-boxed-primitive "^1.0.2"
+
+unicode-canonical-property-names-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc"
+ integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==
+
+unicode-match-property-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz#54fd16e0ecb167cf04cf1f756bdcc92eba7976c3"
+ integrity sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==
+ dependencies:
+ unicode-canonical-property-names-ecmascript "^2.0.0"
+ unicode-property-aliases-ecmascript "^2.0.0"
+
+unicode-match-property-value-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714"
+ integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==
+
+unicode-property-aliases-ecmascript@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8"
+ integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==
+
+unique-string@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
+ integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==
+ dependencies:
+ crypto-random-string "^2.0.0"
+
+universalify@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
+ integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
+
+universalify@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
+ integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
+
+unpipe@1.0.0, unpipe@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
+ integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
+
+unquote@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544"
+ integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=
+
+upath@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894"
+ integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==
+
+uri-js@^4.2.2:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+ dependencies:
+ punycode "^2.1.0"
+
+util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
+
+util.promisify@~1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee"
+ integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==
+ dependencies:
+ define-properties "^1.1.3"
+ es-abstract "^1.17.2"
+ has-symbols "^1.0.1"
+ object.getownpropertydescriptors "^2.1.0"
+
+utila@~0.4:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c"
+ integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=
+
+utils-merge@1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"
+ integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=
+
+uuid@^8.3.2:
+ version "8.3.2"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
+ integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==
+
+v8-compile-cache@^2.0.3:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"
+ integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==
+
+v8-to-istanbul@^8.1.0:
+ version "8.1.1"
+ resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed"
+ integrity sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==
+ dependencies:
+ "@types/istanbul-lib-coverage" "^2.0.1"
+ convert-source-map "^1.6.0"
+ source-map "^0.7.3"
+
+validate.io-array@^1.0.1:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/validate.io-array/-/validate.io-array-1.0.6.tgz#5b5a2cafd8f8b85abb2f886ba153f2d93a27774d"
+ integrity sha1-W1osr9j4uFq7L4hroVPy2Tond00=
+
+validate.io-object@^1.0.0:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/validate.io-object/-/validate.io-object-1.0.4.tgz#dca01eceee390e110dbc2af843c81f7bf33a41ab"
+ integrity sha1-3KAezu45DhENvCr4Q8gfe/M6Qas=
+ dependencies:
+ validate.io-array "^1.0.1"
+
+value-equal@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c"
+ integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==
+
+vary@~1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
+ integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=
+
+w3c-hr-time@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd"
+ integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==
+ dependencies:
+ browser-process-hrtime "^1.0.0"
+
+w3c-xmlserializer@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a"
+ integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==
+ dependencies:
+ xml-name-validator "^3.0.0"
+
+walker@^1.0.7:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.8.tgz#bd498db477afe573dc04185f011d3ab8a8d7653f"
+ integrity sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==
+ dependencies:
+ makeerror "1.0.12"
+
+watchpack@^2.3.1:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
+ integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
+ dependencies:
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.1.2"
+
+wbuf@^1.1.0, wbuf@^1.7.3:
+ version "1.7.3"
+ resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df"
+ integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==
+ dependencies:
+ minimalistic-assert "^1.0.0"
+
+web-vitals@^1.0.1:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-1.1.2.tgz#06535308168986096239aa84716e68b4c6ae6d1c"
+ integrity sha512-PFMKIY+bRSXlMxVAQ+m2aw9c/ioUYfDgrYot0YUa+/xa0sakubWhSDyxAKwzymvXVdF4CZI71g06W+mqhzu6ig==
+
+web-worker@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.2.0.tgz#5d85a04a7fbc1e7db58f66595d7a3ac7c9c180da"
+ integrity sha512-PgF341avzqyx60neE9DD+XS26MMNMoUQRz9NOZwW32nPQrF6p77f1htcnjBSEV8BGMKZ16choqUG4hyI0Hx7mA==
+
+webidl-conversions@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
+ integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
+
+webidl-conversions@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
+ integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==
+
+webidl-conversions@^6.1.0:
+ version "6.1.0"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
+ integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
+
+webpack-dev-middleware@^5.3.1:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f"
+ integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA==
+ dependencies:
+ colorette "^2.0.10"
+ memfs "^3.4.3"
+ mime-types "^2.1.31"
+ range-parser "^1.2.1"
+ schema-utils "^4.0.0"
+
+webpack-dev-server@^4.6.0:
+ version "4.9.2"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.9.2.tgz#c188db28c7bff12f87deda2a5595679ebbc3c9bc"
+ integrity sha512-H95Ns95dP24ZsEzO6G9iT+PNw4Q7ltll1GfJHV4fKphuHWgKFzGHWi4alTlTnpk1SPPk41X+l2RB7rLfIhnB9Q==
+ dependencies:
+ "@types/bonjour" "^3.5.9"
+ "@types/connect-history-api-fallback" "^1.3.5"
+ "@types/express" "^4.17.13"
+ "@types/serve-index" "^1.9.1"
+ "@types/serve-static" "^1.13.10"
+ "@types/sockjs" "^0.3.33"
+ "@types/ws" "^8.5.1"
+ ansi-html-community "^0.0.8"
+ bonjour-service "^1.0.11"
+ chokidar "^3.5.3"
+ colorette "^2.0.10"
+ compression "^1.7.4"
+ connect-history-api-fallback "^1.6.0"
+ default-gateway "^6.0.3"
+ express "^4.17.3"
+ graceful-fs "^4.2.6"
+ html-entities "^2.3.2"
+ http-proxy-middleware "^2.0.3"
+ ipaddr.js "^2.0.1"
+ open "^8.0.9"
+ p-retry "^4.5.0"
+ rimraf "^3.0.2"
+ schema-utils "^4.0.0"
+ selfsigned "^2.0.1"
+ serve-index "^1.9.1"
+ sockjs "^0.3.24"
+ spdy "^4.0.2"
+ webpack-dev-middleware "^5.3.1"
+ ws "^8.4.2"
+
+webpack-manifest-plugin@^4.0.2:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/webpack-manifest-plugin/-/webpack-manifest-plugin-4.1.1.tgz#10f8dbf4714ff93a215d5a45bcc416d80506f94f"
+ integrity sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==
+ dependencies:
+ tapable "^2.0.0"
+ webpack-sources "^2.2.0"
+
+webpack-sources@^1.4.3:
+ version "1.4.3"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933"
+ integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==
+ dependencies:
+ source-list-map "^2.0.0"
+ source-map "~0.6.1"
+
+webpack-sources@^2.2.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd"
+ integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==
+ dependencies:
+ source-list-map "^2.0.1"
+ source-map "^0.6.1"
+
+webpack-sources@^3.2.3:
+ version "3.2.3"
+ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
+ integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
+
+webpack@^5.64.4:
+ version "5.73.0"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.73.0.tgz#bbd17738f8a53ee5760ea2f59dce7f3431d35d38"
+ integrity sha512-svjudQRPPa0YiOYa2lM/Gacw0r6PvxptHj4FuEKQ2kX05ZLkjbVc5MnPs6its5j7IZljnIqSVo/OsY2X0IpHGA==
+ dependencies:
+ "@types/eslint-scope" "^3.7.3"
+ "@types/estree" "^0.0.51"
+ "@webassemblyjs/ast" "1.11.1"
+ "@webassemblyjs/wasm-edit" "1.11.1"
+ "@webassemblyjs/wasm-parser" "1.11.1"
+ acorn "^8.4.1"
+ acorn-import-assertions "^1.7.6"
+ browserslist "^4.14.5"
+ chrome-trace-event "^1.0.2"
+ enhanced-resolve "^5.9.3"
+ es-module-lexer "^0.9.0"
+ eslint-scope "5.1.1"
+ events "^3.2.0"
+ glob-to-regexp "^0.4.1"
+ graceful-fs "^4.2.9"
+ json-parse-even-better-errors "^2.3.1"
+ loader-runner "^4.2.0"
+ mime-types "^2.1.27"
+ neo-async "^2.6.2"
+ schema-utils "^3.1.0"
+ tapable "^2.1.1"
+ terser-webpack-plugin "^5.1.3"
+ watchpack "^2.3.1"
+ webpack-sources "^3.2.3"
+
+websocket-driver@>=0.5.1, websocket-driver@^0.7.4:
+ version "0.7.4"
+ resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760"
+ integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==
+ dependencies:
+ http-parser-js ">=0.5.1"
+ safe-buffer ">=5.1.0"
+ websocket-extensions ">=0.1.1"
+
+websocket-extensions@>=0.1.1:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42"
+ integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==
+
+whatwg-encoding@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
+ integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==
+ dependencies:
+ iconv-lite "0.4.24"
+
+whatwg-fetch@^3.6.2:
+ version "3.6.2"
+ resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
+ integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==
+
+whatwg-mimetype@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
+ integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
+
+whatwg-url@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
+ integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==
+ dependencies:
+ lodash.sortby "^4.7.0"
+ tr46 "^1.0.1"
+ webidl-conversions "^4.0.2"
+
+whatwg-url@^8.0.0, whatwg-url@^8.5.0:
+ version "8.7.0"
+ resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"
+ integrity sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==
+ dependencies:
+ lodash "^4.7.0"
+ tr46 "^2.1.0"
+ webidl-conversions "^6.1.0"
+
+which-boxed-primitive@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
+ integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
+ 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"
+
+which@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
+ integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==
+ dependencies:
+ isexe "^2.0.0"
+
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+word-wrap@^1.2.3, word-wrap@~1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
+ integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+
+workbox-background-sync@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-6.5.3.tgz#7c66c1836aeca6f3762dc48d17a1852a33b3168c"
+ integrity sha512-0DD/V05FAcek6tWv9XYj2w5T/plxhDSpclIcAGjA/b7t/6PdaRkQ7ZgtAX6Q/L7kV7wZ8uYRJUoH11VjNipMZw==
+ dependencies:
+ idb "^6.1.4"
+ workbox-core "6.5.3"
+
+workbox-broadcast-update@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-6.5.3.tgz#fc2ad79cf507e22950cda9baf1e9a0ccc43f31bc"
+ integrity sha512-4AwCIA5DiDrYhlN+Miv/fp5T3/whNmSL+KqhTwRBTZIL6pvTgE4lVuRzAt1JltmqyMcQ3SEfCdfxczuI4kwFQg==
+ dependencies:
+ workbox-core "6.5.3"
+
+workbox-build@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-6.5.3.tgz#38e3f286d63d2745bff4d1478bb3a6ab5c8b1170"
+ integrity sha512-8JNHHS7u13nhwIYCDea9MNXBNPHXCs5KDZPKI/ZNTr3f4sMGoD7hgFGecbyjX1gw4z6e9bMpMsOEJNyH5htA/w==
+ dependencies:
+ "@apideck/better-ajv-errors" "^0.3.1"
+ "@babel/core" "^7.11.1"
+ "@babel/preset-env" "^7.11.0"
+ "@babel/runtime" "^7.11.2"
+ "@rollup/plugin-babel" "^5.2.0"
+ "@rollup/plugin-node-resolve" "^11.2.1"
+ "@rollup/plugin-replace" "^2.4.1"
+ "@surma/rollup-plugin-off-main-thread" "^2.2.3"
+ ajv "^8.6.0"
+ common-tags "^1.8.0"
+ fast-json-stable-stringify "^2.1.0"
+ fs-extra "^9.0.1"
+ glob "^7.1.6"
+ lodash "^4.17.20"
+ pretty-bytes "^5.3.0"
+ rollup "^2.43.1"
+ rollup-plugin-terser "^7.0.0"
+ source-map "^0.8.0-beta.0"
+ stringify-object "^3.3.0"
+ strip-comments "^2.0.1"
+ tempy "^0.6.0"
+ upath "^1.2.0"
+ workbox-background-sync "6.5.3"
+ workbox-broadcast-update "6.5.3"
+ workbox-cacheable-response "6.5.3"
+ workbox-core "6.5.3"
+ workbox-expiration "6.5.3"
+ workbox-google-analytics "6.5.3"
+ workbox-navigation-preload "6.5.3"
+ workbox-precaching "6.5.3"
+ workbox-range-requests "6.5.3"
+ workbox-recipes "6.5.3"
+ workbox-routing "6.5.3"
+ workbox-strategies "6.5.3"
+ workbox-streams "6.5.3"
+ workbox-sw "6.5.3"
+ workbox-window "6.5.3"
+
+workbox-cacheable-response@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-6.5.3.tgz#b1f8c2bc599a7be8f7e3c262535629c558738e47"
+ integrity sha512-6JE/Zm05hNasHzzAGKDkqqgYtZZL2H06ic2GxuRLStA4S/rHUfm2mnLFFXuHAaGR1XuuYyVCEey1M6H3PdZ7SQ==
+ dependencies:
+ workbox-core "6.5.3"
+
+workbox-core@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-6.5.3.tgz#bca038a9ef0d7a634a6db2a60f45313ed22ac249"
+ integrity sha512-Bb9ey5n/M9x+l3fBTlLpHt9ASTzgSGj6vxni7pY72ilB/Pb3XtN+cZ9yueboVhD5+9cNQrC9n/E1fSrqWsUz7Q==
+
+workbox-expiration@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-6.5.3.tgz#efc0811f371a2ede1052b9de1c4f072b71d50503"
+ integrity sha512-jzYopYR1zD04ZMdlbn/R2Ik6ixiXbi15c9iX5H8CTi6RPDz7uhvMLZPKEndZTpfgmUk8mdmT9Vx/AhbuCl5Sqw==
+ dependencies:
+ idb "^6.1.4"
+ workbox-core "6.5.3"
+
+workbox-google-analytics@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-6.5.3.tgz#cc8c3a61f449131660a4ed2f5362d9a3599b18fe"
+ integrity sha512-3GLCHotz5umoRSb4aNQeTbILETcrTVEozSfLhHSBaegHs1PnqCmN0zbIy2TjTpph2AGXiNwDrWGF0AN+UgDNTw==
+ dependencies:
+ workbox-background-sync "6.5.3"
+ workbox-core "6.5.3"
+ workbox-routing "6.5.3"
+ workbox-strategies "6.5.3"
+
+workbox-navigation-preload@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-6.5.3.tgz#81b74f598b11aa07e2cf1c21af7a826a4f0f70b3"
+ integrity sha512-bK1gDFTc5iu6lH3UQ07QVo+0ovErhRNGvJJO/1ngknT0UQ702nmOUhoN9qE5mhuQSrnK+cqu7O7xeaJ+Rd9Tmg==
+ dependencies:
+ workbox-core "6.5.3"
+
+workbox-precaching@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-6.5.3.tgz#c870312b2ef901d790ab9e48da084e776c62af47"
+ integrity sha512-sjNfgNLSsRX5zcc63H/ar/hCf+T19fRtTqvWh795gdpghWb5xsfEkecXEvZ8biEi1QD7X/ljtHphdaPvXDygMQ==
+ dependencies:
+ workbox-core "6.5.3"
+ workbox-routing "6.5.3"
+ workbox-strategies "6.5.3"
+
+workbox-range-requests@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-6.5.3.tgz#e624ac82ff266a5e4f236d055797def07949d941"
+ integrity sha512-pGCP80Bpn/0Q0MQsfETSfmtXsQcu3M2QCJwSFuJ6cDp8s2XmbUXkzbuQhCUzKR86ZH2Vex/VUjb2UaZBGamijA==
+ dependencies:
+ workbox-core "6.5.3"
+
+workbox-recipes@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-6.5.3.tgz#15beac9d8ae7a3a1c100218094a824b4dd3fd59a"
+ integrity sha512-IcgiKYmbGiDvvf3PMSEtmwqxwfQ5zwI7OZPio3GWu4PfehA8jI8JHI3KZj+PCfRiUPZhjQHJ3v1HbNs+SiSkig==
+ dependencies:
+ workbox-cacheable-response "6.5.3"
+ workbox-core "6.5.3"
+ workbox-expiration "6.5.3"
+ workbox-precaching "6.5.3"
+ workbox-routing "6.5.3"
+ workbox-strategies "6.5.3"
+
+workbox-routing@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-6.5.3.tgz#a0a699d8cc90b5692bd3df24679acbbda3913777"
+ integrity sha512-DFjxcuRAJjjt4T34RbMm3MCn+xnd36UT/2RfPRfa8VWJGItGJIn7tG+GwVTdHmvE54i/QmVTJepyAGWtoLPTmg==
+ dependencies:
+ workbox-core "6.5.3"
+
+workbox-strategies@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-6.5.3.tgz#4bea9a48fee16cf43766e0d8138296773c8a9783"
+ integrity sha512-MgmGRrDVXs7rtSCcetZgkSZyMpRGw8HqL2aguszOc3nUmzGZsT238z/NN9ZouCxSzDu3PQ3ZSKmovAacaIhu1w==
+ dependencies:
+ workbox-core "6.5.3"
+
+workbox-streams@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-6.5.3.tgz#b6860290031caa7d0e46ad7142315c94359c780b"
+ integrity sha512-vN4Qi8o+b7zj1FDVNZ+PlmAcy1sBoV7SC956uhqYvZ9Sg1fViSbOpydULOssVJ4tOyKRifH/eoi6h99d+sJ33w==
+ dependencies:
+ workbox-core "6.5.3"
+ workbox-routing "6.5.3"
+
+workbox-sw@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-6.5.3.tgz#cd2f0c086f4496acd25774ed02c48504189bebdd"
+ integrity sha512-BQBzm092w+NqdIEF2yhl32dERt9j9MDGUTa2Eaa+o3YKL4Qqw55W9yQC6f44FdAHdAJrJvp0t+HVrfh8AiGj8A==
+
+workbox-webpack-plugin@^6.4.1:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-webpack-plugin/-/workbox-webpack-plugin-6.5.3.tgz#c37bb323be4952311565c07db51054fe59c87d73"
+ integrity sha512-Es8Xr02Gi6Kc3zaUwR691ZLy61hz3vhhs5GztcklQ7kl5k2qAusPh0s6LF3wEtlpfs9ZDErnmy5SErwoll7jBA==
+ dependencies:
+ fast-json-stable-stringify "^2.1.0"
+ pretty-bytes "^5.4.1"
+ upath "^1.2.0"
+ webpack-sources "^1.4.3"
+ workbox-build "6.5.3"
+
+workbox-window@6.5.3:
+ version "6.5.3"
+ resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-6.5.3.tgz#4ade70056cb73477ef1cd8fea7cfd0ecbd825c7f"
+ integrity sha512-GnJbx1kcKXDtoJBVZs/P7ddP0Yt52NNy4nocjBpYPiRhMqTpJCNrSL+fGHZ/i/oP6p/vhE8II0sA6AZGKGnssw==
+ dependencies:
+ "@types/trusted-types" "^2.0.2"
+ workbox-core "6.5.3"
+
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
+
+write-file-atomic@^3.0.0:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8"
+ integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==
+ dependencies:
+ imurmurhash "^0.1.4"
+ is-typedarray "^1.0.0"
+ signal-exit "^3.0.2"
+ typedarray-to-buffer "^3.1.5"
+
+ws@^7.4.6:
+ version "7.5.8"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.8.tgz#ac2729881ab9e7cbaf8787fe3469a48c5c7f636a"
+ integrity sha512-ri1Id1WinAX5Jqn9HejiGb8crfRio0Qgu8+MtL36rlTA6RLsMdWt1Az/19A2Qij6uSHUMphEFaTKa4WG+UNHNw==
+
+ws@^8.4.2:
+ version "8.8.0"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-8.8.0.tgz#8e71c75e2f6348dbf8d78005107297056cb77769"
+ integrity sha512-JDAgSYQ1ksuwqfChJusw1LSJ8BizJ2e/vVu5Lxjq3YvNJNlROv1ui4i+c/kUUrPheBvQl4c5UbERhTwKa6QBJQ==
+
+xml-name-validator@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a"
+ integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==
+
+xmlchars@^2.2.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
+ integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
+
+xtend@^4.0.2:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
+ integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
+
+y18n@^5.0.5:
+ version "5.0.8"
+ resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55"
+ integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
+
+yallist@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
+ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
+
+yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2:
+ version "1.10.2"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"
+ integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==
+
+yargs-parser@^20.2.2:
+ version "20.2.9"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
+ integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
+
+yargs@^16.2.0:
+ version "16.2.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
+ integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
+ dependencies:
+ cliui "^7.0.2"
+ escalade "^3.1.1"
+ get-caller-file "^2.0.5"
+ require-directory "^2.1.1"
+ string-width "^4.2.0"
+ y18n "^5.0.5"
+ yargs-parser "^20.2.2"
+
+yocto-queue@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
+
+zustand@^3.7.2:
+ version "3.7.2"
+ resolved "https://registry.yarnpkg.com/zustand/-/zustand-3.7.2.tgz#7b44c4f4a5bfd7a8296a3957b13e1c346f42514d"
+ integrity sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==
diff --git a/heroku.yml b/heroku.yml
new file mode 100644
index 00000000..8eec25b9
--- /dev/null
+++ b/heroku.yml
@@ -0,0 +1,3 @@
+build:
+ docker:
+ web: Dockerfile
diff --git a/nginx.default.template b/nginx.default.template
new file mode 100644
index 00000000..e8e91819
--- /dev/null
+++ b/nginx.default.template
@@ -0,0 +1,74 @@
+# nginx.default
+
+upstream app_server {
+ # fail_timeout=0 means we always retry an upstream even if it failed
+ # to return a good HTTP response
+ server unix:/run/gunicorn.socket fail_timeout=0;
+}
+
+server {
+ listen $PORT;
+ server_name pkpdapp.herokuapp.com;
+
+ # javascript frontend
+ location / {
+ root /usr/share/nginx/html;
+ try_files $uri /index.html;
+ }
+
+ # fetch data from proxied server when /api is called
+ location /api {
+ proxy_pass http://app_server/api;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $remote_addr;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_redirect http://app_server/api $scheme://$http_host;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_read_timeout 20d;
+ proxy_buffering off;
+ }
+
+ # or /auth
+ location /auth {
+ proxy_pass http://app_server/auth;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $remote_addr;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_redirect http://app_server/auth $scheme://$http_host;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_read_timeout 20d;
+ proxy_buffering off;
+ }
+
+ # or /admin
+ location /admin {
+ proxy_pass http://app_server/admin;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $remote_addr;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_redirect http://app_server/admin $scheme://$http_host;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_read_timeout 20d;
+ proxy_buffering off;
+ }
+
+ # or /backend -> /static
+ location /backend {
+ proxy_pass http://app_server/static;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $remote_addr;
+ proxy_set_header Host $host;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ proxy_redirect http://app_server/static $scheme://$http_host;
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_read_timeout 20d;
+ proxy_buffering off;
+ }
+}
diff --git a/pkpdapp/.coveragerc b/pkpdapp/.coveragerc
new file mode 100644
index 00000000..eeddb421
--- /dev/null
+++ b/pkpdapp/.coveragerc
@@ -0,0 +1,8 @@
+[run]
+source = .
+omit =
+ */apps.py
+ */tests/*
+ manage.py
+ pkpdapp/asgi.py
+ pkpdapp/wsgi.py
diff --git a/pkpdapp/manage.py b/pkpdapp/manage.py
new file mode 100755
index 00000000..ebd8f394
--- /dev/null
+++ b/pkpdapp/manage.py
@@ -0,0 +1,29 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import os
+import sys
+
+
+def main():
+ """
+ This function makes Django's core app management features accessible from
+ the command line.
+ """
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pkpdapp.settings')
+ try:
+ from django.core.management import execute_from_command_line
+ except ImportError as exc:
+ raise ImportError(
+ "Couldn't import Django. Are you sure it's installed and "
+ "available on your PYTHONPATH environment variable? Did you "
+ "forget to activate a virtual environment?"
+ ) from exc
+ execute_from_command_line(sys.argv)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/pkpdapp/media/data/lxf_control_growth.csv b/pkpdapp/media/data/lxf_control_growth.csv
new file mode 100644
index 00000000..7b928854
--- /dev/null
+++ b/pkpdapp/media/data/lxf_control_growth.csv
@@ -0,0 +1,103 @@
+,#ID,TIME in day,TUMOUR VOLUME in cm^3,BODY WEIGHT in g
+0,40,0,0.191808,26.8
+1,94,0,0.07724750000000001,18.3
+2,95,0,0.1862,22.3
+59,136,0,0.1185885,25.4
+60,140,0,0.0793305,22.7
+61,155,0,0.105875,26.0
+62,169,0,0.12300799999999999,26.9
+63,170,0,0.0800565,28.3
+153,140,2,0.12685200000000002,23.6
+152,169,2,0.128774,26.8
+148,155,2,0.167706,27.3
+147,136,2,0.175071,26.2
+137,95,2,0.24642,23.0
+136,40,2,0.249158,26.1
+156,170,2,0.094221,27.7
+157,94,2,0.0884835,18.2
+123,155,4,0.35632800000000003,27.5
+127,40,4,0.33067199999999997,26.5
+145,169,4,0.1764,26.2
+112,95,4,0.4293,22.4
+140,136,4,0.22999200000000003,28.3
+154,94,4,0.125316,18.5
+155,170,4,0.10933,27.9
+151,140,4,0.146072,23.6
+150,170,7,0.158994,28.8
+149,94,7,0.165528,18.3
+141,169,7,0.20516650000000003,26.2
+135,140,7,0.261121,24.4
+101,95,7,0.62426,23.6
+97,40,7,0.6683669999999999,26.5
+130,136,7,0.30268849999999997,28.0
+99,155,7,0.6489600000000001,28.2
+96,155,9,0.692224,28.7
+131,136,9,0.30268849999999997,25.1
+93,95,9,0.7246720000000001,24.1
+84,40,9,0.915008,27.1
+144,94,9,0.189486,18.7
+146,170,9,0.176157,29.3
+139,169,9,0.2460535,27.3
+125,140,9,0.34574400000000005,25.0
+132,169,11,0.2788425,26.6
+124,140,11,0.3552,23.5
+133,94,11,0.264654,17.9
+120,136,11,0.37044,22.9
+92,155,11,0.7300800000000001,27.9
+91,95,11,0.7300800000000001,22.7
+143,170,11,0.1940785,28.6
+80,40,11,1.119258,26.0
+87,155,14,0.81648,28.6
+142,170,14,0.20416050000000002,29.5
+126,169,14,0.333036,28.0
+108,136,14,0.5341545,24.1
+83,95,14,0.9196000000000001,23.6
+76,40,14,1.470432,26.4
+134,94,14,0.264654,18.4
+114,140,14,0.41905000000000003,24.8
+138,170,16,0.246402,28.9
+122,169,16,0.356445,27.6
+128,94,16,0.306936,18.2
+72,40,16,1.6692479999999998,26.0
+98,136,16,0.651688,23.9
+79,95,16,1.131184,23.3
+75,155,16,1.494954,29.0
+109,140,16,0.480298,24.3
+69,40,18,1.752192,25.4
+129,170,18,0.3050865,26.8
+105,140,18,0.556668,23.8
+94,136,18,0.7212869999999999,23.0
+71,95,18,1.675872,23.3
+118,94,18,0.389207,18.7
+117,169,18,0.39285000000000003,26.6
+74,155,18,1.5166985,28.0
+110,169,21,0.47985900000000004,27.9
+64,95,21,2.346616,23.3
+89,136,21,0.78732,24.0
+121,170,21,0.3683265,28.7
+65,40,21,2.276736,26.2
+119,94,21,0.389207,20.0
+88,140,21,0.8089919999999999,23.3
+70,155,21,1.72405,28.9
+73,155,23,1.637784,28.5
+85,140,23,0.857304,23.7
+86,136,23,0.8529505000000001,23.7
+116,94,23,0.405769,20.2
+115,170,23,0.418176,27.3
+107,169,23,0.539055,27.4
+66,155,25,2.25108,29.6
+113,94,25,0.4264715,20.3
+100,169,25,0.6354195,28.6
+82,140,25,1.097675,24.8
+81,136,25,1.104558,24.7
+111,170,25,0.4396155,28.7
+104,170,28,0.5661554999999999,28.5
+68,140,28,1.9921440000000001,24.7
+95,169,28,0.7146180000000001,27.5
+78,136,28,1.13288,24.6
+106,94,28,0.5551309999999999,20.0
+77,136,30,1.4593425,24.2
+103,94,30,0.57624,19.2
+90,169,30,0.7469865,28.0
+67,140,30,2.1225820000000004,24.1
+102,170,30,0.6206265,27.5
diff --git a/pkpdapp/media/model/1_comp_PK_model.xml b/pkpdapp/media/model/1_comp_PK_model.xml
new file mode 100644
index 00000000..6e1ec928
--- /dev/null
+++ b/pkpdapp/media/model/1_comp_PK_model.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ka
+ Agi
+
+
+
+
+
+
+
+
+
+
+
+
+
+ k10
+ A1
+
+
+
+
+
+
+
+
+
+
diff --git a/pkpdapp/media/model/2_comp_PK_model_simple.xml b/pkpdapp/media/model/2_comp_PK_model_simple.xml
new file mode 100644
index 00000000..66649691
--- /dev/null
+++ b/pkpdapp/media/model/2_comp_PK_model_simple.xml
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ka
+ Agi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ k12
+ A1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ k21
+ A2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ k10
+ A1
+
+
+
+
+
+
+
+
+
+
diff --git a/pkpdapp/media/model/3_comp_PK_model.xml b/pkpdapp/media/model/3_comp_PK_model.xml
new file mode 100644
index 00000000..dd7265af
--- /dev/null
+++ b/pkpdapp/media/model/3_comp_PK_model.xml
@@ -0,0 +1,220 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ka
+ Agi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ k12
+ A1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ k21
+ A2
+
+
+
+
+
+
+
+
+
+
+
+
+
+ k10
+ A1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ k13
+ A1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ k21
+ A3
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pkpdapp/media/model/tumour_growth_without_treatment.xml b/pkpdapp/media/model/tumour_growth_without_treatment.xml
new file mode 100644
index 00000000..9d2c135c
--- /dev/null
+++ b/pkpdapp/media/model/tumour_growth_without_treatment.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ lambda
+ critical_volume
+ tumour_volume
+
+
+
+ tumour_volume
+ critical_volume
+
+
+
+
+
+
+
diff --git a/pkpdapp/pkpdapp/__init__.py b/pkpdapp/pkpdapp/__init__.py
new file mode 100644
index 00000000..b1c69e7a
--- /dev/null
+++ b/pkpdapp/pkpdapp/__init__.py
@@ -0,0 +1,11 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from .celery import app as celery_app
+
+default_app_config = 'pkpdapp.apps.PkpdAppConfig'
+
+__all__ = ('celery_app', 'default_app_config')
diff --git a/pkpdapp/pkpdapp/admin.py b/pkpdapp/pkpdapp/admin.py
new file mode 100644
index 00000000..7ce08081
--- /dev/null
+++ b/pkpdapp/pkpdapp/admin.py
@@ -0,0 +1,16 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.contrib import admin
+from django.apps import apps
+
+models = apps.get_models()
+
+for model in models:
+ try:
+ admin.site.register(model)
+ except admin.sites.AlreadyRegistered:
+ pass
diff --git a/pkpdapp/pkpdapp/api/__init__.py b/pkpdapp/pkpdapp/api/__init__.py
new file mode 100644
index 00000000..1b41d03c
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/__init__.py
@@ -0,0 +1,21 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+# flake8: noqa F401
+
+from .views import (
+ DatasetView, UserView, ProjectView, CompoundView,
+ PharmacokineticView, CombinedModelView,
+ PharmacodynamicView, DoseView,
+ ProtocolView, SimulateCombinedView, SimulatePdView,
+ UnitView, BiomarkerTypeView, VariableView, SubjectView,
+ ProjectAccessView, NcaView, AuceView,
+ InferenceView, InferenceChainView,
+ AlgorithmView,
+ StopInferenceView,
+ LogLikelihoodView, InferenceWizardView,
+ login_view, logout_view, get_csrf, SessionView, WhoAmIView,
+ SimulationViewSet,
+)
diff --git a/pkpdapp/pkpdapp/api/serializers/__init__.py b/pkpdapp/pkpdapp/api/serializers/__init__.py
new file mode 100644
index 00000000..1b540956
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/__init__.py
@@ -0,0 +1,50 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+# flake8: noqa F401
+
+
+from .polymorphicserializer import PolymorphicSerializer
+
+from .validators import (
+ ValidSbml, ValidMmt
+)
+from .monolix import MonolixSerializer
+from .auce import AuceSerializer
+from .biomarker_type import BiomarkerTypeSerializer
+from .dose import DoseSerializer
+from .efficacy_experiment import EfficacySerializer
+from .compound import CompoundSerializer
+from .models import (
+ PharmacokineticSerializer,
+ CombinedModelSerializer,
+ PharmacodynamicSerializer,
+ PharmacodynamicSbmlSerializer,
+)
+from .variables import VariableSerializer
+from .likelihoods import (
+ LogLikelihoodSerializer,
+ LogLikelihoodParameterSerializer,
+)
+from .inference import (
+ InferenceSerializer,
+ InferenceChainSerializer,
+ AlgorithmSerializer,
+)
+from .nca import NcaSerializer
+from .project import ProjectSerializer, ProjectAccessSerializer
+from .protocol import ProtocolSerializer
+from .dataset import DatasetSerializer, DatasetCsvSerializer
+from .subject import SubjectSerializer
+from .unit import UnitSerializer
+from .user import UserSerializer
+from .simulation import (
+ SimulationSerializer,
+ SimulationYAxisSerializer,
+ SimulationCxLineSerializer,
+ SimulationSliderSerializer,
+)
+
+
diff --git a/pkpdapp/pkpdapp/api/serializers/auce.py b/pkpdapp/pkpdapp/api/serializers/auce.py
new file mode 100644
index 00000000..e3bf81b2
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/auce.py
@@ -0,0 +1,39 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import serializers
+
+
+class AuceSerializer(serializers.Serializer):
+ name = serializers.CharField()
+ fit_type = serializers.CharField()
+ subject_ids = serializers.ListField(
+ child=serializers.IntegerField()
+ )
+ concentrations = serializers.ListField(
+ child=serializers.FloatField()
+ )
+ auce = serializers.ListField(
+ child=serializers.FloatField()
+ )
+
+ x = serializers.ListField(
+ child=serializers.FloatField()
+ )
+ y = serializers.ListField(
+ child=serializers.FloatField()
+ )
+ y_upper = serializers.ListField(
+ child=serializers.FloatField()
+ )
+ y_lower = serializers.ListField(
+ child=serializers.FloatField()
+ )
+ fit_EC50 = serializers.FloatField()
+ sigma_EC50 = serializers.FloatField()
+ fit_top = serializers.FloatField()
+ sigma_top = serializers.FloatField()
+ fit_bottom = serializers.FloatField()
+ sigma_bottom = serializers.FloatField()
diff --git a/pkpdapp/pkpdapp/api/serializers/biomarker_type.py b/pkpdapp/pkpdapp/api/serializers/biomarker_type.py
new file mode 100644
index 00000000..7a862fea
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/biomarker_type.py
@@ -0,0 +1,30 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from typing import Dict, List
+from rest_framework import serializers
+from pkpdapp.models import (
+ BiomarkerType
+)
+
+
+class BiomarkerTypeSerializer(serializers.ModelSerializer):
+ data = serializers.SerializerMethodField('get_data')
+ is_continuous = serializers.SerializerMethodField('get_is_continuous')
+ is_categorical = serializers.SerializerMethodField('get_is_categorical')
+
+ class Meta:
+ model = BiomarkerType
+ fields = '__all__'
+
+ def get_data(self, bt) -> Dict[str, List] | None:
+ return bt.data().to_dict(orient='list')
+
+ def get_is_categorical(self, bt) -> bool:
+ return bt.is_categorical()
+
+ def get_is_continuous(self, bt) -> bool:
+ return bt.is_continuous()
diff --git a/pkpdapp/pkpdapp/api/serializers/compound.py b/pkpdapp/pkpdapp/api/serializers/compound.py
new file mode 100644
index 00000000..2de12fb6
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/compound.py
@@ -0,0 +1,64 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from rest_framework import serializers
+from pkpdapp.models import (
+ Compound
+)
+from pkpdapp.api.serializers import EfficacySerializer
+
+
+class BaseCompoundSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Compound
+ fields = '__all__'
+
+
+class CompoundSerializer(serializers.ModelSerializer):
+ efficacy_experiments = EfficacySerializer(many=True)
+
+ class Meta:
+ model = Compound
+ fields = '__all__'
+
+ def create(self, validated_data):
+ # save method of log_likelihood will create its own parameters,
+ # so ignore any parameters that are given
+ experiments = validated_data.pop('efficacy_experiments')
+ compound = BaseCompoundSerializer().create(
+ validated_data
+ )
+ for exp in experiments:
+ exp['compound'] = compound
+ serializer = EfficacySerializer()
+ serializer.create(exp)
+ return compound
+
+ def update(self, instance, validated_data):
+ experiments = validated_data.pop('efficacy_experiments')
+ old_experiments = list(instance.efficacy_experiments.all())
+ project = BaseCompoundSerializer().update(
+ instance, validated_data
+ )
+ for exp in experiments:
+ exp['compound'] = instance
+ serializer = EfficacySerializer()
+ try:
+ old_experiment = old_experiments.pop(0)
+ new_exp = serializer.update(
+ old_experiment, exp
+ )
+ new_exp.save()
+ except IndexError:
+ new_exp = serializer.create(exp)
+
+ # delete any old accesses
+ for old_exp in old_experiments:
+ old_exp.delete()
+
+ project.refresh_from_db()
+
+ return project
diff --git a/pkpdapp/pkpdapp/api/serializers/dataset.py b/pkpdapp/pkpdapp/api/serializers/dataset.py
new file mode 100644
index 00000000..5dc9baec
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/dataset.py
@@ -0,0 +1,64 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from pkpdapp.utils import DataParser
+from rest_framework import serializers
+from drf_spectacular.utils import extend_schema_field
+import codecs
+from pkpdapp.models import (
+ Dataset, Protocol,
+)
+from pkpdapp.api.serializers import ProtocolSerializer
+
+
+class DatasetSerializer(serializers.ModelSerializer):
+ biomarker_types = serializers.PrimaryKeyRelatedField(
+ many=True, read_only=True
+ )
+ subjects = serializers.PrimaryKeyRelatedField(
+ many=True, read_only=True
+ )
+ protocols = serializers.SerializerMethodField('get_protocols')
+
+ class Meta:
+ model = Dataset
+ fields = '__all__'
+
+ @extend_schema_field(ProtocolSerializer(many=True))
+ def get_protocols(self, dataset):
+ protocols = [
+ Protocol.objects.get(pk=p['protocol'])
+ for p in dataset.subjects.values('protocol').distinct()
+ if p['protocol'] is not None
+ ]
+ return ProtocolSerializer(protocols, many=True).data
+
+
+class DatasetCsvSerializer(serializers.ModelSerializer):
+ csv = serializers.FileField()
+
+ class Meta:
+ model = Dataset
+ fields = ['csv']
+
+ def validate_csv(self, csv):
+ utf8_file = codecs.EncodedFile(csv.open(), "utf-8")
+ parser = DataParser()
+
+ # error in columns
+ try:
+ data = parser.parse_from_stream(utf8_file)
+ except RuntimeError as err:
+ raise serializers.ValidationError(str(err))
+ except UnicodeDecodeError as err:
+ raise serializers.ValidationError(str(err))
+
+ return data
+
+ def update(self, instance, validated_data):
+ data = validated_data['csv']
+ instance.replace_data(data)
+ return instance
diff --git a/pkpdapp/pkpdapp/api/serializers/dose.py b/pkpdapp/pkpdapp/api/serializers/dose.py
new file mode 100644
index 00000000..cf96a79a
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/dose.py
@@ -0,0 +1,16 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from rest_framework import serializers
+from pkpdapp.models import (
+ Dose
+)
+
+
+class DoseSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Dose
+ exclude = ['protocol']
diff --git a/pkpdapp/pkpdapp/api/serializers/efficacy_experiment.py b/pkpdapp/pkpdapp/api/serializers/efficacy_experiment.py
new file mode 100644
index 00000000..d9657d33
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/efficacy_experiment.py
@@ -0,0 +1,16 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from rest_framework import serializers
+from pkpdapp.models import (
+ EfficacyExperiment
+)
+
+
+class EfficacySerializer(serializers.ModelSerializer):
+ class Meta:
+ model = EfficacyExperiment
+ fields = '__all__'
diff --git a/pkpdapp/pkpdapp/api/serializers/inference.py b/pkpdapp/pkpdapp/api/serializers/inference.py
new file mode 100644
index 00000000..4d0517eb
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/inference.py
@@ -0,0 +1,200 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import serializers
+from pkpdapp.models import (
+ Inference, InferenceChain, Algorithm,
+ InferenceOutputResult,
+)
+import scipy.stats
+import numpy as np
+from pkpdapp.api.serializers import (
+ LogLikelihoodSerializer,
+)
+
+
+class InferenceOutputResultSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = InferenceOutputResult
+ fields = '__all__'
+
+
+class AlgorithmSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Algorithm
+ fields = '__all__'
+
+
+class BaseInferenceSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Inference
+ fields = '__all__'
+
+
+class InferenceSerializer(serializers.ModelSerializer):
+
+ log_likelihoods = LogLikelihoodSerializer(
+ many=True
+ )
+
+ class Meta:
+ model = Inference
+ fields = '__all__'
+
+ def validate_log_likelihoods(self, value):
+ """
+ Check that the blog post is about Django.
+ """
+ names = [v['name'] for v in value]
+ if len(set(names)) < len(names):
+ raise serializers.ValidationError(
+ "all log_likelihoods in an inference must have unique names"
+ )
+ return value
+
+ def create(self, validated_data):
+ log_likelihood_data = validated_data.pop('log_likelihoods')
+ new_inference = BaseInferenceSerializer().create(
+ validated_data
+ )
+ for field_datas, Serializer in [
+ (log_likelihood_data, LogLikelihoodSerializer),
+ ]:
+ for field_data in field_datas:
+ serializer = Serializer()
+ field_data['inference'] = new_inference
+ serializer.create(field_data)
+
+ return new_inference
+
+ def update(self, instance, validated_data):
+ log_likelihood_data = validated_data.pop('log_likelihoods')
+ old_log_likelihoods = list((instance.log_likelihoods).all())
+
+ # if read_only only update name, description and burnin
+ if instance.read_only:
+ validated_data = {
+ key: validated_data[key]
+ for key in ['name', 'description', 'burn_in']
+ if key in validated_data
+ }
+
+ new_inference = BaseInferenceSerializer().update(
+ instance, validated_data
+ )
+
+ # don't update log_likelihoods if read_only
+ if not instance.read_only:
+ for field_datas, old_models, Serializer in [
+ (log_likelihood_data,
+ old_log_likelihoods, LogLikelihoodSerializer)
+ ]:
+ for field_data in field_datas:
+ serializer = Serializer()
+ try:
+ old_model = old_models.pop(0)
+ new_model = serializer.update(
+ old_model, field_data
+ )
+ except IndexError:
+ field_data['inference'] = new_inference
+ new_model = serializer.create(field_data)
+ new_model.save()
+
+ return new_inference
+
+
+class InferenceChainSerializer(serializers.ModelSerializer):
+ data = serializers.SerializerMethodField('get_data')
+ outputs = serializers.SerializerMethodField('get_outputs')
+
+ class Meta:
+ model = InferenceChain
+ fields = '__all__'
+
+ def get_outputs(self, inference_chain):
+ outputs = {
+ ll.id: inference_chain.outputs_for(ll).to_dict(orient='list')
+ for ll in inference_chain.inference.log_likelihoods.all()
+ if ll.has_data()
+ }
+ return outputs
+
+ def get_data(self, inference_chain):
+ chain = inference_chain.as_pandas()
+ function_values = inference_chain.function_as_pandas()
+ by_priors = chain.groupby(['priors', 'subjects'], dropna=False)
+
+ chain = {}
+ kde = {}
+
+ for (prior, subject), frame in by_priors:
+ values = frame['values']
+
+ # get kde density of chains
+ min_value = values.min()
+ max_value = values.max()
+ kde_values = np.linspace(min_value, max_value, 100)
+ try:
+ kde_densities = scipy.stats.gaussian_kde(values)(kde_values)
+ except np.linalg.LinAlgError:
+ kde[int(prior)] = {
+ 'values': [],
+ 'densities': [],
+ }
+ continue
+
+ if np.isnan(subject):
+ kde[int(prior)] = {
+ 'values': kde_values.tolist(),
+ 'densities': kde_densities.tolist(),
+ }
+ else:
+ if prior not in kde:
+ kde[int(prior)] = {}
+ kde[int(prior)][int(subject)] = {
+ 'values': kde_values.tolist(),
+ 'densities': kde_densities.tolist(),
+ }
+
+ # reduce to max 500 values for each prior
+ sample_n = 500
+ for (prior, subject), frame in by_priors:
+ if frame['values'].count() > sample_n:
+ sampled_frame = frame.sample(n=sample_n).sort_index()
+ else:
+ sampled_frame = frame
+ values = sampled_frame['values']
+ iterations = sampled_frame['iterations']
+ if np.isnan(subject):
+ chain[int(prior)] = {
+ 'values': values.tolist(),
+ 'iterations': iterations.tolist()
+ }
+ else:
+ if prior not in chain:
+ chain[int(prior)] = {}
+ chain[int(prior)][int(subject)] = {
+ 'values': values.tolist(),
+ 'iterations': iterations.tolist()
+ }
+
+ if len(function_values.index) > sample_n:
+ function_values = function_values.sample(n=sample_n).sort_index()
+
+ # inf & nan values not serializable
+ function_values.replace([np.inf, -np.inf], np.nan, inplace=True)
+ function_values.fillna('', inplace=True)
+
+ function_values = {
+ 'values': function_values['values'].tolist(),
+ 'iterations': function_values['iterations'],
+ }
+
+ return {
+ 'kde': kde,
+ 'chain': chain,
+ 'function': function_values,
+ }
diff --git a/pkpdapp/pkpdapp/api/serializers/likelihoods.py b/pkpdapp/pkpdapp/api/serializers/likelihoods.py
new file mode 100644
index 00000000..7e19bc88
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/likelihoods.py
@@ -0,0 +1,90 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from django.db.models import Q
+from typing import Tuple
+from rest_framework import serializers
+from pkpdapp.models import (
+ LogLikelihood, LogLikelihoodParameter,
+)
+
+
+class LogLikelihoodParameterSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = LogLikelihoodParameter
+ fields = '__all__'
+ read_only_fields = ("parent", )
+
+
+class BaseLogLikelihoodSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = LogLikelihood
+ fields = '__all__'
+
+
+class LogLikelihoodSerializer(serializers.ModelSerializer):
+ parameters = LogLikelihoodParameterSerializer(
+ many=True
+ )
+ model = serializers.SerializerMethodField('get_model')
+ dataset = serializers.SerializerMethodField('get_dataset')
+ time_variable = serializers.SerializerMethodField('get_time_variable')
+ is_a_prior = serializers.SerializerMethodField('get_is_a_prior')
+
+ class Meta:
+ model = LogLikelihood
+ fields = '__all__'
+ read_only_fields = ("inference", )
+
+ def get_time_variable(self, instance) -> int | None:
+ model = instance.get_model()
+ if model is not None:
+ time_variable = model.variables.get(
+ Q(name='time') | Q(name='t')
+ )
+ return time_variable.id
+
+ def get_is_a_prior(self, instance) -> bool:
+ return instance.is_a_prior()
+
+ def get_model(self, instance) -> Tuple[str, int] | None:
+ model = instance.get_model()
+ if model is not None:
+ return (model._meta.db_table, model.id)
+
+ def get_dataset(self, instance) -> int | None:
+ if instance.biomarker_type:
+ return instance.biomarker_type.dataset.id
+
+ def create(self, validated_data):
+ # save method of log_likelihood will create its own parameters,
+ # so ignore any parameters that are given
+ validated_data.pop('parameters')
+ new_log_likelihood = BaseLogLikelihoodSerializer().create(
+ validated_data
+ )
+ return new_log_likelihood
+
+ def update(self, instance, validated_data):
+ parameters_data = validated_data.pop('parameters')
+ old_parameters = list((instance.parameters).all())
+ new_log_likelihood = BaseLogLikelihoodSerializer().update(
+ instance, validated_data
+ )
+
+ # update params with new info
+ for field_datas, old_models, Serializer in [
+ (parameters_data, old_parameters,
+ LogLikelihoodParameterSerializer),
+ ]:
+ for field_data in field_datas:
+ serializer = Serializer()
+ old_model = old_parameters.pop(0)
+ new_model = serializer.update(
+ old_model, field_data
+ )
+ new_model.save()
+
+ return new_log_likelihood
diff --git a/pkpdapp/pkpdapp/api/serializers/models.py b/pkpdapp/pkpdapp/api/serializers/models.py
new file mode 100644
index 00000000..66558668
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/models.py
@@ -0,0 +1,220 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import serializers
+from pkpdapp.models import (
+ PharmacokineticModel,
+ CombinedModel,
+ PharmacodynamicModel,
+ PkpdMapping,
+ MyokitModelMixin,
+ DerivedVariable,
+ Variable,
+)
+from pkpdapp.api.serializers import ValidSbml, ValidMmt
+
+
+class PkpdMappingSerializer(serializers.ModelSerializer):
+ datetime = serializers.DateField(read_only=True, required=False)
+ read_only = serializers.BooleanField(read_only=True, required=False)
+
+ class Meta:
+ model = PkpdMapping
+ fields = "__all__"
+
+
+class DerivedVariableSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = DerivedVariable
+ fields = "__all__"
+
+
+class BaseDosedPharmacokineticSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = CombinedModel
+ fields = "__all__"
+
+
+class CombinedModelSerializer(serializers.ModelSerializer):
+ mappings = PkpdMappingSerializer(many=True)
+ derived_variables = DerivedVariableSerializer(many=True)
+ components = serializers.SerializerMethodField("get_components")
+ variables = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
+ mmt = serializers.SerializerMethodField("get_mmt", read_only=True)
+ time_unit = serializers.SerializerMethodField("get_time_unit")
+ is_library_model = serializers.SerializerMethodField("get_is_library_model")
+
+ class Meta:
+ model = CombinedModel
+ fields = "__all__"
+
+ def get_is_library_model(self, m) -> bool:
+ return m.is_library_model
+
+ def get_mmt(self, m) -> str:
+ return m.get_mmt()
+
+ def get_time_unit(self, m) -> int:
+ unit = m.get_time_unit()
+ if unit is None:
+ return -1
+ else:
+ return unit.id
+
+ def get_components(self, m):
+ model = m.get_myokit_model()
+ return [_serialize_component(m, c, model) for c in model.components(sort=True)]
+
+ def create(self, validated_data):
+ mappings_data = validated_data.pop("mappings", [])
+ derived_variables_data = validated_data.pop("derived_variables", [])
+ new_pkpd_model = BaseDosedPharmacokineticSerializer().create(validated_data)
+ for field_datas, Serializer in [
+ (mappings_data, PkpdMappingSerializer),
+ (derived_variables_data, DerivedVariableSerializer),
+ ]:
+ for field_data in field_datas:
+ serializer = Serializer()
+ field_data["pkpd_model"] = new_pkpd_model
+ serializer.create(field_data)
+
+ return new_pkpd_model
+
+ def update(self, instance, validated_data):
+ mappings_data = validated_data.pop("mappings", [])
+ derived_var_data = validated_data.pop("derived_variables", [])
+ old_mappings = list((instance.mappings).all())
+ old_derived_vars = list((instance.derived_variables).all())
+
+ pk_model_changed = False
+ if "pk_model" in validated_data:
+ pk_model_changed = instance.pk_model != validated_data.get("pk_model")
+ pd_model_changed = False
+ if "pd_model" in validated_data:
+ pd_model_changed = instance.pd_model != validated_data.get("pd_model")
+
+ new_pkpd_model = BaseDosedPharmacokineticSerializer().update(
+ instance, validated_data
+ )
+
+ # if pd model has changed, update effect variable
+ if pd_model_changed:
+ for mapping in mappings_data:
+ try:
+ mapping["pd_variable"] = new_pkpd_model.variables.get(
+ qname=mapping["pd_variable"].qname
+ )
+ except Variable.DoesNotExist:
+ mapping["pd_variable"] = None
+
+ mappings_data = [m for m in mappings_data if m["pd_variable"] is not None]
+
+ # don't update mappings if read_only
+ # don't update mapping or derived variables if pk model has changed
+ if not (instance.read_only or pk_model_changed):
+ for derived_var in derived_var_data:
+ serializer = DerivedVariableSerializer()
+ try:
+ old_model = old_derived_vars.pop(0)
+ new_model = serializer.update(old_model, derived_var)
+ new_model.save()
+ except IndexError:
+ derived_var["pkpd_model"] = new_pkpd_model
+ new_model = serializer.create(derived_var)
+
+ for mapping in mappings_data:
+ serializer = PkpdMappingSerializer()
+ try:
+ old_model = old_mappings.pop(0)
+ new_model = serializer.update(old_model, mapping)
+ new_model.save()
+ except IndexError:
+ mapping["pkpd_model"] = new_pkpd_model
+ new_model = serializer.create(mapping)
+
+ # delete any remaining old mappings and derived variables
+ for old_model in old_mappings:
+ old_model.delete()
+ for old_model in old_derived_vars:
+ old_model.delete()
+
+ # update model since mappings might have changed
+ new_pkpd_model.update_model()
+
+ return new_pkpd_model
+
+
+class PharmacokineticSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = PharmacokineticModel
+ fields = "__all__"
+
+
+def _serialize_component(model, component, myokit_model):
+ states = [
+ v.pk
+ for v in model.variables.filter(state=True)
+ if v.qname.startswith(component.name())
+ ]
+
+ variables = [
+ v.pk
+ for v in model.variables.filter(constant=True)
+ if v.qname.startswith(component.name())
+ ]
+
+ outputs = [
+ v.pk
+ for v in model.variables.filter(constant=False)
+ if v.qname.startswith(component.name())
+ ]
+
+ equations = [
+ MyokitModelMixin._serialise_equation(e)
+ for e in component.equations(bound=False, const=False)
+ ]
+ return {
+ "name": component.name(),
+ "states": states,
+ "variables": variables,
+ "outputs": outputs,
+ "equations": equations,
+ }
+
+
+class PharmacodynamicSerializer(serializers.ModelSerializer):
+ components = serializers.SerializerMethodField("get_components")
+ variables = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
+ mmt = serializers.CharField(validators=[ValidMmt()], required=False)
+
+ def get_components(self, m):
+ model = m.get_myokit_model()
+ return [_serialize_component(m, c, model) for c in model.components(sort=True)]
+
+ class Meta:
+ model = PharmacodynamicModel
+ fields = "__all__"
+
+
+class PharmacodynamicSbmlSerializer(serializers.ModelSerializer):
+ sbml = serializers.CharField(validators=[ValidSbml()], write_only=True)
+
+ class Meta:
+ model = PharmacodynamicModel
+ fields = ["sbml"]
+ extra_kwargs = {"sbml": {"write_only": True}}
+
+ def create(self, validated_data):
+ sbml = validated_data.pop("sbml")
+ mmt = MyokitModelMixin.sbml_string_to_mmt(sbml)
+ validated_data["mmt"] = mmt
+ return PharmacodynamicModel(**validated_data)
+
+ def update(self, instance, validated_data):
+ sbml = validated_data.get("sbml")
+ mmt = MyokitModelMixin.sbml_string_to_mmt(sbml)
+ instance.mmt = mmt
+ instance.save()
+ return instance
diff --git a/pkpdapp/pkpdapp/api/serializers/monolix.py b/pkpdapp/pkpdapp/api/serializers/monolix.py
new file mode 100644
index 00000000..67013ab0
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/monolix.py
@@ -0,0 +1,100 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from pkpdapp.utils import (
+ MonolixModelParser,
+ monolix_import,
+)
+from rest_framework import serializers
+import codecs
+from pkpdapp.models import (
+ Project,
+)
+
+
+class MonolixSerializer(serializers.ModelSerializer):
+ data_csv = serializers.FileField(write_only=True)
+ model_txt = serializers.FileField(write_only=True)
+ project_mlxtran = serializers.FileField(write_only=True)
+ data = serializers.PrimaryKeyRelatedField(read_only=True)
+ pd_model = serializers.PrimaryKeyRelatedField(read_only=True)
+ pk_model = serializers.PrimaryKeyRelatedField(read_only=True)
+
+ class Meta:
+ model = Project
+ fields = ['data_csv', 'model_txt', 'project_mlxtran',
+ 'data', 'pd_model', 'pk_model']
+
+ def validate_data_csv(self, data_csv):
+ utf8_file = codecs.EncodedFile(data_csv.open(), "utf-8")
+ # error in columns
+ try:
+ utf8_str = codecs.decode(utf8_file.read(), 'utf-8')
+ except RuntimeError as err:
+ raise serializers.ValidationError(str(err))
+ except UnicodeDecodeError as err:
+ raise serializers.ValidationError(str(err))
+
+ return utf8_str
+
+ def validate_model_txt(self, model_txt):
+ utf8_file = codecs.EncodedFile(model_txt.open(), "utf-8")
+ parser = MonolixModelParser()
+
+ # error in columns
+ try:
+ utf8_str = codecs.decode(utf8_file.read(), 'utf-8')
+ parser.parse(utf8_str)
+ except RuntimeError as err:
+ raise serializers.ValidationError(str(err))
+ except UnicodeDecodeError as err:
+ raise serializers.ValidationError(str(err))
+
+ return utf8_str
+
+ def validate_project_mlxtran(self, project_mlxtran):
+ utf8_file = codecs.EncodedFile(project_mlxtran.open(), "utf-8")
+ # error in columns
+ try:
+ utf8_str = codecs.decode(utf8_file.read(), 'utf-8')
+ except RuntimeError as err:
+ raise serializers.ValidationError(str(err))
+ except UnicodeDecodeError as err:
+ raise serializers.ValidationError(str(err))
+
+ return utf8_str
+
+ def validate(self, data):
+ instance = getattr(self, 'instance', None)
+ if instance is None:
+ raise serializers.ValidationError('project instance must exist')
+ try:
+ monolix_import(instance, data['project_mlxtran'],
+ data['model_txt'], data['data_csv'], validate=True)
+ except RuntimeError as err:
+ raise serializers.ValidationError(str(err))
+ except UnicodeDecodeError as err:
+ raise serializers.ValidationError(str(err))
+ return data
+
+ def update(self, instance, validated_data):
+ result = monolix_import(
+ instance, validated_data['project_mlxtran'],
+ validated_data['model_txt'], validated_data['data_csv'],
+ validate=False
+ )
+ if result is None:
+ return None
+ result_dict = {
+ 'data_csv': validated_data['data_csv'],
+ 'model_txt': validated_data['model_txt'],
+ 'project_mlxtran': validated_data['project_mlxtran'],
+ 'pd_model': result[0],
+ 'pk_model': result[1],
+ 'data': result[2],
+ }
+ print('result_dict: ', result_dict)
+ return result_dict
diff --git a/pkpdapp/pkpdapp/api/serializers/nca.py b/pkpdapp/pkpdapp/api/serializers/nca.py
new file mode 100644
index 00000000..c4b3a477
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/nca.py
@@ -0,0 +1,37 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import serializers
+
+
+class NcaSerializer(serializers.Serializer):
+ times = serializers.ListField(
+ child=serializers.FloatField()
+ )
+ concentrations = serializers.ListField(
+ child=serializers.FloatField()
+ )
+ dose_amount = serializers.FloatField()
+ administration_route = serializers.CharField()
+ c_0 = serializers.FloatField()
+ auc_0_last = serializers.FloatField()
+ aumc_0_last = serializers.FloatField()
+ lambda_z = serializers.FloatField()
+ r2 = serializers.FloatField()
+ num_points = serializers.IntegerField(min_value=0)
+ auc_infinity = serializers.FloatField()
+ auc_infinity_dose = serializers.FloatField()
+ auc_extrap_percent = serializers.FloatField()
+ cl = serializers.FloatField()
+ c_max = serializers.FloatField()
+ t_max = serializers.FloatField()
+ c_max_dose = serializers.FloatField()
+ aumc = serializers.FloatField()
+ aumc_extrap_percent = serializers.FloatField()
+ mrt = serializers.FloatField()
+ tlast = serializers.FloatField()
+ t_half = serializers.FloatField()
+ v_ss = serializers.FloatField()
+ v_z = serializers.FloatField()
diff --git a/pkpdapp/pkpdapp/api/serializers/polymorphicserializer.py b/pkpdapp/pkpdapp/api/serializers/polymorphicserializer.py
new file mode 100644
index 00000000..320cce27
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/polymorphicserializer.py
@@ -0,0 +1,102 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+# This code was derived from
+# https://stackoverflow.com/questions/48911345/drf-how-to-serialize-models-inheritance-read-write
+
+from enum import Enum
+
+from rest_framework import serializers
+
+
+class PolymorphicSerializer(serializers.Serializer):
+ """
+ Serializer to handle multiple subclasses of another class
+
+ - For serialized dict representations, a 'type' key with the class name as
+ the value is expected: ex. {'type': 'Decimal', ... }
+ - This type information is used in tandem with get_serializer_map(...) to
+ manage serializers for multiple subclasses
+
+ """
+
+ def get_serializer_map(self):
+ """
+ Return a dict to map class names to their respective serializer classes
+
+ To be implemented by all PolymorphicSerializer subclasses
+ """
+ raise NotImplementedError
+
+ def to_representation(self, obj):
+ """
+ Translate object to internal data representation
+
+ Override to allow polymorphism
+ """
+ if hasattr(obj, 'get_type'):
+ type_ = obj.get_type()
+ if isinstance(type_, Enum):
+ type_str = type_.value
+ else:
+ type_str = type_.__name__
+
+ else:
+ type_str = obj.__class__.__name__
+
+ try:
+ serializer = self.get_serializer_map()[type_str]
+ except KeyError:
+ raise ValueError(
+ 'Serializer for "{}" does not exist'.format(type_str),
+ )
+
+ data = serializer(obj, context=self.context).to_representation(obj)
+ data['type'] = type_str
+ return data
+
+ def to_internal_value(self, data):
+ """
+ Validate data and initialize primitive types
+
+ Override to allow polymorphism
+ """
+ try:
+ type_str = data['type']
+ except KeyError:
+ raise serializers.ValidationError({
+ 'type': 'This field is required',
+ })
+
+ try:
+ serializer = self.get_serializer_map()[type_str]
+ except KeyError:
+ raise serializers.ValidationError({
+ 'type': 'Serializer for "{}" does not exist'.format(type_str),
+ })
+
+ validated_data = serializer(
+ context=self.context
+ ).to_internal_value(data)
+ validated_data['type'] = type_str
+ return validated_data
+
+ def create(self, validated_data):
+ """
+ Translate validated data representation to object
+
+ Override to allow polymorphism
+ """
+ serializer = self.get_serializer_map()[validated_data['type']]
+ validated_data.pop('type')
+ return serializer(context=self.context).create(validated_data)
+
+ def update(self, instance, validated_data):
+ serializer = self.get_serializer_map()[validated_data['type']]
+ validated_data.pop('type')
+
+ return serializer(context=self.context).update(
+ instance, validated_data
+ )
diff --git a/pkpdapp/pkpdapp/api/serializers/project.py b/pkpdapp/pkpdapp/api/serializers/project.py
new file mode 100644
index 00000000..0c388e3b
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/project.py
@@ -0,0 +1,78 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import serializers
+from pkpdapp.models import (
+ ProjectAccess, Project
+)
+
+
+class ProjectAccessSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = ProjectAccess
+ fields = '__all__'
+ read_only_fields = ("project", )
+
+
+class BaseProjectSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Project
+ fields = '__all__'
+
+
+class ProjectSerializer(serializers.ModelSerializer):
+ user_access = ProjectAccessSerializer(
+ source='projectaccess_set', many=True
+ )
+ protocols = serializers.PrimaryKeyRelatedField(
+ many=True, read_only=True
+ )
+
+ class Meta:
+ model = Project
+ fields = '__all__'
+ read_only_fields = ("created", )
+
+ def create(self, validated_data):
+ # save method of log_likelihood will create its own parameters,
+ # so ignore any parameters that are given
+ users = validated_data.pop('projectaccess_set')
+ project = BaseProjectSerializer().create(
+ validated_data
+ )
+ for user in users:
+ user['project'] = project
+ serializer = ProjectAccessSerializer()
+ serializer.create(user)
+ return project
+
+ def update(self, instance, validated_data):
+ print('project update', validated_data)
+ users = validated_data.pop('projectaccess_set')
+ old_accesses = list(instance.projectaccess_set.all())
+ project = BaseProjectSerializer().update(
+ instance, validated_data
+ )
+ for user in users:
+ user['project_id'] = instance.id
+ serializer = ProjectAccessSerializer()
+ old_access = [
+ i for i, a in enumerate(old_accesses) if a.user == user['user']
+ ]
+ if not old_access:
+ new_access = serializer.create(user)
+ else:
+ new_access = serializer.update(
+ old_accesses.pop(old_access[0]), user
+ )
+ new_access.save()
+
+ # delete any old accesses
+ for old_access in old_accesses:
+ old_access.delete()
+
+ project.refresh_from_db()
+
+ return project
diff --git a/pkpdapp/pkpdapp/api/serializers/protocol.py b/pkpdapp/pkpdapp/api/serializers/protocol.py
new file mode 100644
index 00000000..fc02a9dc
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/protocol.py
@@ -0,0 +1,45 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import serializers
+from pkpdapp.models import (
+ Dose, Protocol
+)
+from pkpdapp.api.serializers import DoseSerializer
+
+
+class ProtocolSerializer(serializers.ModelSerializer):
+ doses = DoseSerializer(
+ many=True
+ )
+ dataset = serializers.SerializerMethodField('get_dataset')
+ variables = serializers.PrimaryKeyRelatedField(
+ many=True, read_only=True
+ )
+ subjects = serializers.PrimaryKeyRelatedField(
+ many=True, read_only=True
+ )
+
+ class Meta:
+ model = Protocol
+ fields = '__all__'
+
+ def get_dataset(self, protocol):
+ return protocol.get_dataset()
+
+ def create(self, validated_data):
+ doses = validated_data.pop('doses')
+ protocol = Protocol.objects.create(**validated_data)
+ for dose in doses:
+ Dose.objects.create(protocol=protocol, **dose)
+ return protocol
+
+ def update(self, instance, validated_data):
+ doses = validated_data.pop('doses')
+ Dose.objects.filter(protocol=instance).delete()
+ for dose in doses:
+ dose['protocol'] = instance
+ DoseSerializer.create(DoseSerializer(), dose)
+ return super().update(instance, validated_data)
diff --git a/pkpdapp/pkpdapp/api/serializers/simulation.py b/pkpdapp/pkpdapp/api/serializers/simulation.py
new file mode 100644
index 00000000..c2ea3624
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/simulation.py
@@ -0,0 +1,100 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from rest_framework import serializers
+from pkpdapp.models import (
+ Simulation, SimulationYAxis, SimulationSlider,
+ SimulationCxLine, SimulationPlot
+)
+
+
+class SimulationYAxisSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = SimulationYAxis
+ exclude = ['plot']
+
+
+class SimulationSliderSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = SimulationSlider
+ exclude = ['simulation']
+
+
+class SimulationCxLineSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = SimulationCxLine
+ exclude = ['plot']
+
+
+class SimulationPlotSerializer(serializers.ModelSerializer):
+ y_axes = SimulationYAxisSerializer(
+ many=True
+ )
+ cx_lines = SimulationCxLineSerializer(
+ many=True
+ )
+
+ class Meta:
+ model = SimulationPlot
+ # fields = '__all__'
+ exclude = ['simulation']
+
+ def create(self, validated_data):
+ y_axes_data = validated_data.pop('y_axes')
+ cx_lines_data = validated_data.pop('cx_lines')
+ plot = SimulationPlot.objects.create(**validated_data)
+ for y_axis in y_axes_data:
+ SimulationYAxis.objects.create(plot=plot, **y_axis)
+ for cx_line in cx_lines_data:
+ SimulationCxLine.objects.create(plot=plot, **cx_line)
+ return plot
+
+ def update(self, instance, validated_data):
+ y_axes_data = validated_data.pop('y_axes')
+ cx_lines_data = validated_data.pop('cx_lines')
+ SimulationYAxis.objects.filter(plot=instance).delete()
+ SimulationCxLine.objects.filter(plot=instance).delete()
+ for y_axis in y_axes_data:
+ SimulationYAxis.objects.create(plot=instance, **y_axis)
+ for cx_line in cx_lines_data:
+ SimulationCxLine.objects.create(plot=instance, **cx_line)
+ return super().update(instance, validated_data)
+
+
+class SimulationSerializer(serializers.ModelSerializer):
+ sliders = SimulationSliderSerializer(
+ many=True
+ )
+ plots = SimulationPlotSerializer(
+ many=True
+ )
+
+ class Meta:
+ model = Simulation
+ fields = '__all__'
+
+ def create(self, validated_data):
+ slider_data = validated_data.pop('sliders')
+ plot_data = validated_data.pop('plots')
+ simulation = Simulation.objects.create(**validated_data)
+ for slider in slider_data:
+ SimulationSlider.objects.create(simulation=simulation, **slider)
+ for plot in plot_data:
+ plot['simulation'] = simulation
+ SimulationPlotSerializer.create(SimulationPlotSerializer(), plot)
+ return simulation
+
+ def update(self, instance, validated_data):
+ slider_data = validated_data.pop('sliders')
+ plot_data = validated_data.pop('plots')
+ SimulationSlider.objects.filter(simulation=instance).delete()
+ SimulationPlot.objects.filter(simulation=instance).delete()
+ for slider in slider_data:
+ SimulationSlider.objects.create(simulation=instance, **slider)
+ for plot in plot_data:
+ plot['simulation'] = instance
+ SimulationPlotSerializer.create(SimulationPlotSerializer(), plot)
+ return super().update(instance, validated_data)
diff --git a/pkpdapp/pkpdapp/api/serializers/subject.py b/pkpdapp/pkpdapp/api/serializers/subject.py
new file mode 100644
index 00000000..c2a62bdb
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/subject.py
@@ -0,0 +1,15 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import serializers
+from pkpdapp.models import (
+ Subject,
+)
+
+
+class SubjectSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Subject
+ fields = '__all__'
diff --git a/pkpdapp/pkpdapp/api/serializers/unit.py b/pkpdapp/pkpdapp/api/serializers/unit.py
new file mode 100644
index 00000000..f131ce3e
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/unit.py
@@ -0,0 +1,44 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from pkpdapp.models import Unit
+from rest_framework.schemas.openapi import AutoSchema
+from rest_framework import serializers
+from typing import Dict, List
+import logging
+
+logger = logging.getLogger(__name__)
+
+
+class UnitSchema(AutoSchema):
+ """
+ AutoSchema subclass that knows how to use extra_info.
+ """
+
+ ...
+
+
+class UnitSerializer(serializers.ModelSerializer):
+ compatible_units = serializers.SerializerMethodField("get_compatible_units")
+
+ class Meta:
+ model = Unit
+ fields = "__all__"
+
+ def get_compatible_units(self, unit) -> List[Dict[str, str]]:
+ compound = self.context.get("compound")
+ return [
+ {
+ "id": u.id,
+ "symbol": u.symbol,
+ "conversion_factor": unit.convert_to(
+ u, compound=compound, is_target=False
+ ),
+ "target_conversion_factor": unit.convert_to(
+ u, compound=compound, is_target=True
+ ),
+ }
+ for u in unit.get_compatible_units(compound=compound)
+ ]
diff --git a/pkpdapp/pkpdapp/api/serializers/user.py b/pkpdapp/pkpdapp/api/serializers/user.py
new file mode 100644
index 00000000..2e7a4bff
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/user.py
@@ -0,0 +1,31 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import serializers
+from django.contrib.auth.models import User
+from pkpdapp.models import (
+ Profile
+)
+
+
+class ProfileSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Profile
+ fields = '__all__'
+
+
+class UserSerializer(serializers.ModelSerializer):
+ profile = ProfileSerializer(read_only=True)
+ project_set = serializers.PrimaryKeyRelatedField(
+ many=True, read_only=True,
+ )
+
+ class Meta:
+ model = User
+ fields = '__all__'
+ fields = (
+ 'id', 'username', 'first_name',
+ 'last_name', 'email', 'profile', 'project_set'
+ )
diff --git a/pkpdapp/pkpdapp/api/serializers/validators.py b/pkpdapp/pkpdapp/api/serializers/validators.py
new file mode 100644
index 00000000..3e398045
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/validators.py
@@ -0,0 +1,25 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import serializers
+from pkpdapp.models.mechanistic_model import MyokitModelMixin
+from myokit.formats.sbml import SBMLParsingError
+import myokit
+
+
+class ValidSbml:
+ def __call__(self, value):
+ try:
+ MyokitModelMixin.parse_sbml_string(value)
+ except SBMLParsingError as e:
+ raise serializers.ValidationError(e)
+
+
+class ValidMmt:
+ def __call__(self, value):
+ try:
+ MyokitModelMixin.parse_mmt_string(value)
+ except myokit.ParseError as e:
+ raise serializers.ValidationError(e)
diff --git a/pkpdapp/pkpdapp/api/serializers/variables.py b/pkpdapp/pkpdapp/api/serializers/variables.py
new file mode 100644
index 00000000..59fc4be0
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/serializers/variables.py
@@ -0,0 +1,25 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import serializers
+from pkpdapp.models import (
+ Variable,
+)
+
+
+class VariableSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Variable
+ fields = "__all__"
+
+ def to_internal_value(self, data):
+ optional_fields = [
+ "lower_bound",
+ "upper_bound",
+ ]
+ for field in optional_fields:
+ if data.get(field, None) == "":
+ data[field] = None
+ return super(VariableSerializer, self).to_internal_value(data)
diff --git a/pkpdapp/pkpdapp/api/views/__init__.py b/pkpdapp/pkpdapp/api/views/__init__.py
new file mode 100644
index 00000000..f51fe248
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/__init__.py
@@ -0,0 +1,51 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+# flake8: noqa F401
+
+
+from .login import (login_view, logout_view, get_csrf, SessionView, WhoAmIView)
+from .filters import (
+ UserAccessFilter,
+ DosedPkModelFilter,
+ PdModelFilter,
+ ProjectFilter,
+ InferenceFilter
+)
+from .permissions import (
+ NotADatasetDose,
+ NotADatasetProtocol,
+ CheckAccessToProject,
+)
+from .simulation import (
+ SimulationViewSet,
+)
+from .auce import AuceView
+from .biomarker_type import BiomarkerTypeView
+from .dataset import DatasetView
+from .dose import DoseView
+from .compound import CompoundView
+
+from .models import (
+ PharmacokineticView,
+ PharmacodynamicView,
+ CombinedModelView,
+)
+from .nca import NcaView
+from .project import ProjectView, ProjectAccessView
+from .protocol import ProtocolView
+from .inference import (
+ InferenceView, InferenceChainView, AlgorithmView,
+ StopInferenceView, InferenceWizardView,
+)
+from .simulate import (
+ SimulateCombinedView,
+ SimulatePdView,
+)
+from .subject import SubjectView
+from .unit import UnitView
+from .user import UserView
+from .variable import VariableView
+from .likelihoods import LogLikelihoodView
diff --git a/pkpdapp/pkpdapp/api/views/auce.py b/pkpdapp/pkpdapp/api/views/auce.py
new file mode 100644
index 00000000..985765f1
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/auce.py
@@ -0,0 +1,117 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import (
+ views, status
+)
+from rest_framework.response import Response
+from pkpdapp.models import (
+ BiomarkerType,
+)
+from pkpdapp.api.serializers import AuceSerializer
+from pkpdapp.utils import Auce
+
+
+class AuceView(views.APIView):
+ def post(self, request, format=None):
+ errors = {
+ }
+
+ biomarker_type_id = request.data.get('biomarker_type_id', None)
+ if biomarker_type_id is None:
+ errors['biomarker_type_id'] = "This field is required"
+ else:
+ try:
+ biomarker_type = \
+ BiomarkerType.objects.get(id=biomarker_type_id)
+ except BiomarkerType.DoesNotExist:
+ errors['biomarker_type_id'] = (
+ "BiomarkerType id {} not found"
+ .format(biomarker_type_id)
+ )
+
+ group_type_id = request.data.get('group_type_id', None)
+ if group_type_id is None:
+ errors['group_type_id'] = "This field is required"
+ else:
+ try:
+ group_type = \
+ BiomarkerType.objects.get(id=group_type_id)
+ except BiomarkerType.DoesNotExist:
+ errors['group_type_id'] = (
+ "BiomarkerType id {} not found"
+ .format(biomarker_type_id)
+ )
+
+ concentration_type_id = request.data.get('concentration_type_id', None)
+ if concentration_type_id is None:
+ errors['concentration_type_id'] = "This field is required"
+ else:
+ try:
+ concentration_type = \
+ BiomarkerType.objects.get(id=concentration_type_id)
+ except BiomarkerType.DoesNotExist:
+ errors['group_type_id'] = (
+ "BiomarkerType id {} not found"
+ .format(concentration_type_id)
+ )
+
+ if errors:
+ return Response(
+ errors, status=status.HTTP_400_BAD_REQUEST
+ )
+
+ group_data = group_type.data(first_time_only=True)
+ groups = list(group_data['values'].unique()) + [None]
+ obs_data = biomarker_type.data()
+ concentration_data = concentration_type.data(first_time_only=True)
+
+ auces = []
+ for group in groups:
+ if group is None:
+ group_subjects = group_data['subjects'].unique()
+ else:
+ group_subjects = group_data.loc[
+ group_data['values'] == group
+ ]['subjects']
+ group_concentrations = concentration_data[
+ concentration_data['subjects'].isin(group_subjects)
+ ]
+ group_obs_data = obs_data[
+ obs_data['subjects'].isin(group_subjects)
+ ]
+
+ subject_times = []
+ subject_data = []
+ concentrations = []
+ subject_ids = []
+ for subject in group_subjects:
+ times = group_obs_data.loc[
+ group_obs_data['subjects'] == subject
+ ]['times']
+ values = group_obs_data.loc[
+ group_obs_data['subjects'] == subject
+ ]['values']
+ concentration = group_concentrations.loc[
+ group_concentrations['subjects'] == subject
+ ]['values'].iloc[0]
+ concentrations.append(concentration)
+ subject_times.append(times)
+ subject_data.append(values)
+ subject_ids.append(subject)
+ auces.append(Auce(
+ group if group is not None else 'All',
+ subject_ids, concentrations,
+ subject_times, subject_data
+ ))
+
+ serializers = [AuceSerializer(auce) for auce in auces]
+
+ if errors:
+ return Response(
+ errors, status=status.HTTP_400_BAD_REQUEST
+ )
+
+ return Response([serializer.data for serializer in serializers])
diff --git a/pkpdapp/pkpdapp/api/views/biomarker_type.py b/pkpdapp/pkpdapp/api/views/biomarker_type.py
new file mode 100644
index 00000000..0ac378d4
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/biomarker_type.py
@@ -0,0 +1,21 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import viewsets
+from rest_framework.permissions import IsAuthenticated
+
+from pkpdapp.api.serializers import BiomarkerTypeSerializer
+from pkpdapp.api.views import ProjectFilter
+from pkpdapp.api.views import CheckAccessToProject
+from pkpdapp.models import BiomarkerType
+
+
+class BiomarkerTypeView(viewsets.ModelViewSet):
+ queryset = BiomarkerType.objects.all()
+ serializer_class = BiomarkerTypeSerializer
+ filter_backends = [ProjectFilter]
+ permission_classes = [
+ IsAuthenticated & CheckAccessToProject
+ ]
diff --git a/pkpdapp/pkpdapp/api/views/compound.py b/pkpdapp/pkpdapp/api/views/compound.py
new file mode 100644
index 00000000..b9b2cfac
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/compound.py
@@ -0,0 +1,20 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import viewsets
+from pkpdapp.api.serializers import CompoundSerializer
+from pkpdapp.models import Compound
+from pkpdapp.api.views import (
+ CheckAccessToProject
+)
+from rest_framework.permissions import IsAuthenticated
+
+
+class CompoundView(viewsets.ModelViewSet):
+ queryset = Compound.objects.all()
+ serializer_class = CompoundSerializer
+ permission_classes = [
+ IsAuthenticated & CheckAccessToProject
+ ]
diff --git a/pkpdapp/pkpdapp/api/views/dataset.py b/pkpdapp/pkpdapp/api/views/dataset.py
new file mode 100644
index 00000000..74b31e9c
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/dataset.py
@@ -0,0 +1,38 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import (
+ viewsets, decorators, parsers, response, status
+)
+from pkpdapp.api.views import (
+ ProjectFilter,
+)
+from pkpdapp.api.serializers import (
+ DatasetSerializer, DatasetCsvSerializer
+)
+from pkpdapp.models import Dataset
+
+
+class DatasetView(viewsets.ModelViewSet):
+ queryset = Dataset.objects.all()
+ serializer_class = DatasetSerializer
+ filter_backends = [ProjectFilter]
+
+ @decorators.action(
+ detail=True,
+ serializer_class=DatasetCsvSerializer,
+ methods=['PUT'],
+ parser_classes=[parsers.MultiPartParser],
+ )
+ def csv(self, request, pk):
+ obj = self.get_object()
+ serializer = self.serializer_class(obj, data=request.data,
+ partial=True)
+ if serializer.is_valid():
+ serializer.save()
+ dataset_serializer = DatasetSerializer(obj)
+ return response.Response(dataset_serializer.data)
+ return response.Response(serializer.errors,
+ status.HTTP_400_BAD_REQUEST)
diff --git a/pkpdapp/pkpdapp/api/views/dose.py b/pkpdapp/pkpdapp/api/views/dose.py
new file mode 100644
index 00000000..8d7a774e
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/dose.py
@@ -0,0 +1,21 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import viewsets
+from rest_framework.permissions import IsAuthenticated
+from pkpdapp.api.views import (
+ NotADatasetDose,
+ CheckAccessToProject,
+)
+from pkpdapp.api.serializers import DoseSerializer
+from pkpdapp.models import Dose
+
+
+class DoseView(viewsets.ModelViewSet):
+ queryset = Dose.objects.all()
+ serializer_class = DoseSerializer
+ permission_classes = [
+ IsAuthenticated & NotADatasetDose & CheckAccessToProject
+ ]
diff --git a/pkpdapp/pkpdapp/api/views/efficacy_experiment.py b/pkpdapp/pkpdapp/api/views/efficacy_experiment.py
new file mode 100644
index 00000000..9b89074c
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/efficacy_experiment.py
@@ -0,0 +1,21 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import viewsets
+from rest_framework.permissions import IsAuthenticated
+from pkpdapp.api.views import (
+ NotADatasetDose,
+ CheckAccessToProject,
+)
+from pkpdapp.api.serializers import EfficacySerializer
+from pkpdapp.models import EfficacyExperiment
+
+
+class DoseView(viewsets.ModelViewSet):
+ queryset = EfficacyExperiment.objects.all()
+ serializer_class = EfficacySerializer
+ permission_classes = [
+ IsAuthenticated & NotADatasetDose & CheckAccessToProject
+ ]
diff --git a/pkpdapp/pkpdapp/api/views/filters.py b/pkpdapp/pkpdapp/api/views/filters.py
new file mode 100644
index 00000000..1d6193a5
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/filters.py
@@ -0,0 +1,178 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import (
+ filters
+)
+from django.db.models import Q
+
+from pkpdapp.models import (
+ Dataset, Project,
+ PharmacodynamicModel,
+ CombinedModel,
+ Protocol,
+ Unit,
+ BiomarkerType,
+ Variable,
+ Subject,
+ Inference, InferenceChain,
+ LogLikelihood,
+ Simulation,
+)
+
+
+class UserAccessFilter(filters.BaseFilterBackend):
+ """
+ Filter that allows filtering by user.
+ """
+
+ def filter_queryset(self, request, queryset, view):
+ if request.user.is_superuser:
+ return queryset
+
+ user = request.user
+ if queryset.model == Project:
+ queryset = queryset.filter(users=user)
+ else:
+ raise RuntimeError('queryset model {} not recognised')
+ return queryset
+
+
+class DosedPkModelFilter(filters.BaseFilterBackend):
+ """
+ Filter that only allows users to filter by dosed_pk_model.
+ """
+
+ def filter_queryset(self, request, queryset, view):
+ dosed_pk_model_id = \
+ request.query_params.get('dosed_pk_model_id')
+ if dosed_pk_model_id is not None:
+ try:
+ dosed_pk_model = CombinedModel.objects.get(
+ id=dosed_pk_model_id
+ )
+ if queryset.model == Variable:
+ queryset = dosed_pk_model.variables.all()
+ elif queryset.model == Unit:
+ unit_ids = (
+ dosed_pk_model.variables
+ .values_list('unit', flat=True)
+ )
+ queryset = Unit.objects.filter(id__in=unit_ids)
+ else:
+ raise RuntimeError('queryset model {} not recognised')
+ except CombinedModel.DoesNotExist:
+ queryset = queryset.model.objects.none()
+
+ return queryset
+
+
+class PdModelFilter(filters.BaseFilterBackend):
+ """
+ Filter that only allows users to filter by dosed_pk_model.
+ """
+
+ def filter_queryset(self, request, queryset, view):
+ pd_model_id = \
+ request.query_params.get('pd_model_id')
+ if pd_model_id is not None:
+ try:
+ pd_model = PharmacodynamicModel.objects.get(
+ id=pd_model_id
+ )
+ if queryset.model == Variable:
+ queryset = pd_model.variables.all()
+ elif queryset.model == Unit:
+ unit_ids = (
+ pd_model.variables
+ .values_list('unit', flat=True)
+ )
+ queryset = Unit.objects.filter(id__in=unit_ids)
+ else:
+ raise RuntimeError('queryset model {} not recognised')
+ except PharmacodynamicModel.DoesNotExist:
+ queryset = queryset.model.objects.none()
+
+ return queryset
+
+
+class InferenceFilter(filters.BaseFilterBackend):
+ """
+ Filter that only allows users to filter by inference.
+ """
+
+ def filter_queryset(self, request, queryset, view):
+ inference_id = \
+ request.query_params.get('inference_id')
+ if inference_id is not None:
+ try:
+ inference = Inference.objects.get(
+ id=inference_id
+ )
+ if queryset.model == Variable:
+ model = inference.get_model()
+ if model:
+ queryset = model.variables.all()
+ else:
+ queryset = queryset.model.objects.none()
+ elif queryset.model == InferenceChain:
+ queryset = inference.chains.all()
+ elif queryset.model == LogLikelihood:
+ queryset = inference.log_likelihoods.all()
+ else:
+ raise RuntimeError('queryset model {} not recognised')
+ except Inference.DoesNotExist:
+ queryset = queryset.model.objects.none()
+
+ return queryset
+
+
+class ProjectFilter(filters.BaseFilterBackend):
+ """
+ Filter that only allows users to filter by project.
+ """
+
+ def filter_queryset(self, request, queryset, view):
+ project_id = request.query_params.get('project_id')
+ if project_id is not None:
+ try:
+ project = Project.objects.get(
+ id=project_id
+ )
+ if queryset.model == Dataset:
+ queryset = project.datasets
+ elif queryset.model == Simulation:
+ queryset = project.simulations
+ elif queryset.model == PharmacodynamicModel:
+ queryset = project.pd_models
+ elif queryset.model == CombinedModel:
+ queryset = project.pk_models
+ elif queryset.model == Protocol:
+ queryset = project.protocols
+ elif queryset.model == Inference:
+ queryset = project.inference_set
+ elif queryset.model == InferenceChain:
+ queryset = InferenceChain.objects.filter(
+ inference__in=project.inference_set.all()
+ )
+ elif queryset.model == BiomarkerType:
+ queryset = BiomarkerType.objects.filter(
+ dataset__project=project
+ )
+ elif queryset.model == Subject:
+ queryset = Subject.objects.filter(
+ dataset__project=project
+ )
+ elif queryset.model == Variable:
+ queryset = queryset.filter(
+ Q(pd_model__project=project) |
+ Q(dosed_pk_model__project=project)
+ )
+ else:
+ raise RuntimeError('queryset model {} not recognised')
+ except Project.DoesNotExist:
+ queryset = queryset.model.objects.none()
+
+ return queryset
diff --git a/pkpdapp/pkpdapp/api/views/inference.py b/pkpdapp/pkpdapp/api/views/inference.py
new file mode 100644
index 00000000..ea4e16bd
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/inference.py
@@ -0,0 +1,731 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import numbers
+import re
+
+from pyparsing import ParseException
+from rest_framework import status, views, viewsets
+from rest_framework.response import Response
+from rest_framework.permissions import IsAuthenticated
+
+from pkpdapp.api.serializers import (
+ AlgorithmSerializer,
+ InferenceChainSerializer,
+ InferenceSerializer,
+)
+from pkpdapp.api.views import (
+ InferenceFilter, ProjectFilter,
+ CheckAccessToProject
+)
+from pkpdapp.models import (
+ Algorithm,
+ BiomarkerType,
+ Dataset,
+ CombinedModel,
+ Inference,
+ InferenceChain,
+ LogLikelihood,
+ LogLikelihoodParameter,
+ Project,
+ Protocol,
+)
+from pkpdapp.utils import ExpressionParser
+
+
+class AlgorithmView(viewsets.ModelViewSet):
+ queryset = Algorithm.objects.all()
+ serializer_class = AlgorithmSerializer
+
+
+class InferenceView(viewsets.ModelViewSet):
+ queryset = Inference.objects.all()
+ serializer_class = InferenceSerializer
+ filter_backends = [ProjectFilter]
+ permission_classes = [
+ IsAuthenticated & CheckAccessToProject
+ ]
+
+ def delete(self, request, pk, format=None):
+ print('delete inference', pk)
+ inference = self.get_object(pk)
+ print('got inference', inference)
+ inference.delete()
+ print('deleted it')
+ return Response(status=status.HTTP_204_NO_CONTENT)
+
+ def destroy(self, request, *args, **kwargs):
+ print('destroy inference')
+ instance = self.get_object()
+ print('got inference', instance)
+ self.perform_destroy(instance)
+ print('deleted it')
+ return Response(status=status.HTTP_204_NO_CONTENT)
+
+
+class InferenceWizardView(views.APIView):
+ """
+ expecting data in the form:
+ {
+
+ # Inference parameters
+ 'id': 1
+ 'name': "my inference run",
+ 'project': 1,
+ 'algorithm': 2,
+ 'initialization_strategy': 'R',
+ 'initialization_inference': 2,
+ 'number_of_chains': 4,
+ 'max_number_of_iterations': 3000,
+ 'burn_in': 0,
+
+ # Model
+ 'model': {
+ 'form': 'PK',
+ 'id': 5
+ }
+ 'dataset': 3,
+
+ # Model parameters
+ 'parameters': [
+ {
+ 'name': 'myokit.parameter1'
+ 'form': 'N',
+ 'pooled': False,
+ 'parameters': [
+ '2 * biomarker[subject_weight]',
+ 'parameter[parameter1_variance]'
+ ]
+ },
+ {
+ 'name': 'parameter1_variance'
+ 'form': 'N',
+ 'parameters': [0, 1]
+ },
+ {
+ 'name': 'myokit.parameter2'
+ 'form': 'U',
+ 'parameters': [-1, 1]
+ },
+ {
+ 'name': 'myokit.parameter3'
+ 'form': 'F',
+ 'parameters': [123.5]
+ },
+ ]
+
+ # output
+ 'observations': [
+ {
+ 'model': 'myokit.plasma_concentration',
+ 'biomarker': 'concentration,
+ 'noise_form': 'N',
+ 'noise_param_form': 'N',
+ 'parameters': [0, 1]
+ },
+ {
+ 'model': 'myokit.bacteria_count',
+ 'biomarker': 'bacteria,
+ 'noise_form': 'LN',
+ 'noise_param_form': 'F'
+ 'parameters': [123.3]
+ },
+ ]
+ }
+
+ Uses model as the base model. If it is a PK or PKPD model, creates a model
+ for each protocol used in the dataset, replacing the protocol of the model
+ with each new one.
+
+ This set of models has a set of parameters. If pooled is True or not given,
+ then parameters of the same qname are assumed to be identical, if pooled is
+ False, then the value of this parameter is different across each subject.
+ All Variable fields from the original model are copied over to the new
+ models. Priors and fixed values for each parameter in this set are provided
+ in 'parameters'. Distribution parameters for each prior can be provided
+ using a python expression, or a number. If a python expression is used, the
+ keywords Parameter[] are used to refer to other parameters in
+ the list. Additional parameters can be added to the list (parameters not in
+ the model) to contruct hierarchical inference. You can refer to biomarkers
+ in the expression using the keyword Biomarker[].
+
+ The 'observations' field maps model output variables with biomarkers in the
+ dataset
+
+
+ """
+
+ @staticmethod
+ def _create_dosed_model(model, protocol, rename_model=False):
+ if model.pd_model is None:
+ stored_pd_model = None
+ else:
+ stored_pd_model = model.pd_model.create_stored_model()
+ stored_model = model.create_stored_model(
+ new_pd_model=stored_pd_model
+ )
+ if rename_model:
+ stored_model.name = model.name + '_' + protocol.name
+ stored_model.protocol = protocol
+
+ # make the model updatable in case protocol change results
+ # in new variables (i.e. D <-> I)
+ stored_model.read_only = False
+ stored_model.save()
+
+ # make it non-updatable again
+ stored_model.read_only = True
+ stored_model.save()
+
+ return stored_model
+
+ @staticmethod
+ def _create_subject_model(model, subject):
+ model_copy = type(model).objects.get(id=model.id)
+ original_name = model_copy.name
+ model_copy.id = None
+ model_copy.pk = None
+ model_copy.name = (
+ '{}_Subject{}'.format(original_name, subject.id_in_dataset)
+ )
+ model_copy.protocol = subject.protocol
+ model_copy.save()
+ stored_model = model_copy.create_stored_model()
+ model_copy.delete()
+ return stored_model
+
+ @staticmethod
+ def _set_observed_loglikelihoods(
+ obs, models, dataset, inference, protocols,
+ ):
+ # create noise param models
+ sigma_models = []
+ for ob in obs:
+ # create model
+ sigma_form = ob['noise_param_form']
+ parameters = ob['parameters']
+ name = 'sigma for {}'.format(
+ ob['model']
+ )
+ if sigma_form == LogLikelihood.Form.FIXED:
+ ll = LogLikelihood.objects.create(
+ inference=inference,
+ name=name,
+ form=sigma_form,
+ value=parameters[0]
+ )
+ else:
+ ll = LogLikelihood.objects.create(
+ inference=inference,
+ name=name,
+ form=sigma_form,
+ )
+ for p, v in zip(
+ ll.get_noise_log_likelihoods(),
+ parameters
+ ):
+ p.value = v
+ p.save()
+
+ sigma_models.append(ll)
+
+ output_names = [ob['model'] for ob in obs]
+ output_forms = [ob['noise_form'] for ob in obs]
+ biomarkers = []
+ for ob in obs:
+ try:
+ biomarker = BiomarkerType.objects.get(
+ name=ob['biomarker'], dataset=dataset
+ )
+ except BiomarkerType.DoesNotExist:
+ biomarker = None
+ biomarkers.append(biomarker)
+
+ print('found biomarkers', biomarkers)
+
+ for model, protocol in zip(models, protocols):
+ # remove all outputs (and their parameters)
+ # except those in output_names
+ # and set the right biomarkers and protocol
+ for output in model.outputs.all():
+ try:
+ index = output_names.index(output.variable.qname)
+ except ValueError:
+ index = None
+ if index is not None:
+ parent = output.parent
+ if protocol is not None:
+ parent.name = '{} ({})'.format(
+ parent.name, protocol.name
+ )
+ parent.biomarker_type = biomarkers[index]
+ print('setting biomarker', biomarkers[index],
+ biomarkers[index].name)
+ parent.observed = True
+ parent.protocol_filter = protocol
+ parent.form = output_forms[index]
+ parent.save()
+
+ # check there is actually data for this output
+ values, _, _ = parent.get_data()
+ if values is None:
+ # no data, delete this output as well
+ for param in parent.parameters.all():
+ if param != output:
+ param.child.delete()
+ parent.delete()
+ else:
+ # remove sigma param and replace it with generated one
+ parent.get_noise_log_likelihoods()[1].delete()
+ param = LogLikelihoodParameter.objects.create(
+ parent=parent, child=sigma_models[index],
+ parent_index=1,
+ name='sigma for ' + output.variable.qname
+ )
+ else:
+ for param in output.parent.parameters.all():
+ if param != output:
+ param.child.delete()
+ output.parent.delete()
+ return biomarkers
+
+ @staticmethod
+ def _set_parameters(
+ params, models, inference, dataset, observed_biomarkers
+ ):
+ created_params = {}
+ params_names = [p['name'] for p in params]
+ parser = ExpressionParser()
+ for model in models:
+ for model_param in model.parameters.all():
+ # if we've already done this param, use the child
+ if model_param.name in created_params:
+ # in pooled_params
+ old_child = model_param.child
+ model_param.child = created_params[model_param.name]
+ model_param.save()
+ old_child.delete()
+ continue
+
+ # else we'll deal with it now
+ # if the user has set a form for this param use it,
+ # otherwise use the default
+ try:
+ param_index = params_names.index(model_param.name)
+ except ValueError:
+ param_index = None
+ child = model_param.child
+ if param_index is not None:
+ param_info = params[param_index]
+
+ InferenceWizardView.param_info_to_log_likelihood(
+ child, param_info, params, parser, dataset, inference,
+ observed_biomarkers
+ )
+
+ created_params[model_param.name] = child
+
+ @staticmethod
+ def param_info_to_log_likelihood(
+ log_likelihood, param_info, params_info, parser, dataset, inference,
+ observed_biomarkers
+ ):
+ # deal with possible equations in noise params
+ # if form is fixed and there is an equation, the child form
+ # will be an equation
+ # if form is a distribution, then the child form will be
+ # that distribution, but if a parameter is given by an
+ # equation its child will be an equation
+ noise_params = param_info['parameters']
+ param_form = param_info['form']
+ pooled = param_info.get('pooled', True)
+ log_likelihood.form = param_form
+ log_likelihood.pooled = pooled
+
+ biomarker_type = None
+ if param_form == 'F' and isinstance(noise_params[0], str):
+ try:
+ log_likelihood.value = float(noise_params[0])
+ except ValueError:
+ biomarker_type = \
+ InferenceWizardView.to_equation_log_likelihood(
+ log_likelihood, noise_params[0], params_info,
+ parser, dataset, inference, observed_biomarkers
+ )
+ elif param_form == 'F':
+ log_likelihood.value = noise_params[0]
+ else:
+ log_likelihood.value = None
+
+ # if we're not pooled then need to give a biomarker_type to get list of
+ # subjects if there is a biomarker covariate in the children use that,
+ # otherwise use the list of subjects in the measured data
+ if not pooled:
+ if biomarker_type is None and observed_biomarkers:
+ if len(observed_biomarkers) == 0:
+ raise RuntimeError('no observed biomakers found')
+
+ # TODO: assumes that multiple observed biomarkers have
+ # identical subjects
+ log_likelihood.biomarker_type = observed_biomarkers[0]
+ log_likelihood.time_independent_data = True
+ else:
+ log_likelihood.biomarker_type = biomarker_type
+ log_likelihood.time_independent_data = True
+
+ log_likelihood.save()
+
+ # set length of output appropriately if not pooled
+ if not pooled:
+ _, _, subjects = log_likelihood.get_data()
+ output = log_likelihood.outputs.first()
+ output.length = len(subjects)
+ output.save()
+
+ for i, p in enumerate(log_likelihood.parameters.all()):
+ param_index = p.parent_index
+ if isinstance(noise_params[param_index], str):
+ try:
+ p.child.value = float(noise_params[param_index])
+ except ValueError:
+ InferenceWizardView.to_equation_log_likelihood(
+ p.child, noise_params[param_index], params_info,
+ parser, dataset, inference, observed_biomarkers
+ )
+ else:
+ p.child.value = noise_params[param_index]
+ p.child.save()
+
+ @staticmethod
+ def to_equation_log_likelihood(
+ log_likelihood, eqn_str, params_info, parser, dataset, inference,
+ observed_biomarkers
+ ):
+ # set form to equation and remove existing children
+ log_likelihood.children.clear()
+ log_likelihood.form = LogLikelihood.Form.EQUATION
+
+ params_in_eqn_str = parser.get_params(eqn_str)
+
+ # replace parameters and biomarkers in equation string
+ # with arg1, arg2 etc
+ escape_regex = re.compile(r'/[.*+?^${}()|[\]\\]/g')
+ for i, param in enumerate(params_in_eqn_str):
+ param1_escaped = escape_regex.sub(r'\\$&', param[1])
+ eqn_str = re.sub(
+ r'{}\s*\(\s*"{}"\s*\)'.format(param[0], param1_escaped),
+ r'arg{}'.format(i),
+ eqn_str
+ )
+ log_likelihood.description = eqn_str
+ log_likelihood.save()
+
+ # create children using parameters and biomarkers
+ biomarker_type = None
+ for i, param in enumerate(params_in_eqn_str):
+ if param[0] == 'parameter':
+ param_info = [
+ p for p in params_info
+ if p['name'] == param[1]
+ ][0]
+ new_child = LogLikelihood.objects.create(
+ name=param_info['name'],
+ form=LogLikelihood.Form.FIXED,
+ inference=inference,
+ value=0.0
+ )
+ InferenceWizardView.param_info_to_log_likelihood(
+ new_child, param_info, params_info, parser,
+ dataset, inference,
+ observed_biomarkers
+ )
+
+ elif param[0] == 'biomarker':
+ biomarker_type = BiomarkerType.objects.get(
+ name=param[1], dataset=dataset
+ )
+ new_child = LogLikelihood.objects.create(
+ name=param[1],
+ form=LogLikelihood.Form.FIXED,
+ biomarker_type=biomarker_type,
+ inference=inference,
+ )
+ LogLikelihoodParameter.objects.create(
+ parent=log_likelihood,
+ child=new_child,
+ parent_index=i,
+ name=param[1]
+ )
+ return biomarker_type
+
+ def post(self, request, format=None):
+ errors = {}
+ data = request.data
+ print('got data', data)
+
+ if 'project' in data:
+ try:
+ project = Project.objects.get(id=data['project'])
+ except Project.DoesNotExist:
+ errors['project'] = 'id {} not found'.format(data['project'])
+ else:
+ errors['project'] = 'field required'
+
+ if 'algorithm' in data:
+ try:
+ algorithm = Algorithm.objects.get(id=data['algorithm'])
+ except Algorithm.DoesNotExist:
+ errors['algorithm'] = 'id {} not found'.format(
+ data['algorithm'])
+ else:
+ algorithm = None
+
+ if 'dataset' in data:
+ try:
+ dataset = Dataset.objects.get(id=data['dataset'])
+ except Dataset.DoesNotExist:
+ errors['dataset'] = 'id {} not found'.format(data['dataset'])
+ else:
+ errors['dataset'] = 'field required'
+
+ model_table = None
+ model_id = None
+ if 'model' in data:
+ if 'form' in data['model']:
+ model_table = CombinedModel
+ else:
+ errors.get('model', {})['form'] = 'field required'
+ if 'id' in data['model']:
+ model_id = data['model']['id']
+ else:
+ errors.get('model', {})['id'] = 'field required'
+ else:
+ errors['model'] = 'field required'
+
+ if (
+ model_table is not None and
+ model_id is not None
+ ):
+ try:
+ model = model_table.objects.get(id=model_id)
+ except model_table.DoesNotExist:
+ model = None
+ errors['model'] = '{} id {} not found'.format(
+ model_table, model_id
+ )
+
+ parameter_errors = []
+ if 'parameters' in data:
+ parser = ExpressionParser()
+ param_names = [p['name'] for p in data['parameters']]
+ for i, param in enumerate(data['parameters']):
+ for j, dist_param in enumerate(param['parameters']):
+ if not isinstance(dist_param, (numbers.Number, str)):
+ parameter_errors.append((
+ (i, 'parameters', j),
+ 'should be str or number'
+ ))
+ elif isinstance(dist_param, str):
+ try:
+ parser.parse(dist_param)
+ params = parser.get_params(dist_param)
+ for param in params:
+ if (
+ param[0] == 'parameter' and
+ param[1] not in param_names
+ ):
+ parameter_errors.append((
+ (i, 'parameters', j),
+ '{} not in list of parameters'
+ .format(param[1])
+ ))
+ elif (
+ param[0] == 'biomarker' and
+ dataset.biomarker_types.filter(
+ name=param[1]
+ ).count() == 0
+ ):
+ parameter_errors.append((
+ (i, 'parameters', j),
+ '{} not in list of biomarkers'
+ .format(param[1])
+ ))
+ except ParseException as pe:
+ parameter_errors.append((
+ (i, 'parameters', j), str(pe)
+ ))
+ else:
+ errors['parameters'] = 'field required'
+
+ # fill out the errors with the parameter errors
+ for p in parameter_errors:
+ this_error = errors.get('parameters')
+ if this_error is None:
+ errors['parameters'] = {}
+ this_error = errors['parameters']
+ for index in p[0][:-1]:
+ new_error = this_error.get(index)
+ if new_error is None:
+ this_error[index] = {}
+ this_error = this_error[index]
+ else:
+ this_error = new_error
+ this_error[p[0][-1]] = p[1]
+
+ if 'observations' in data:
+ for i, obs in enumerate(data['observations']):
+ model_var = obs['model']
+ biomarker = obs['biomarker']
+ if dataset is not None and biomarker:
+ if dataset.biomarker_types.filter(
+ name=biomarker
+ ).count() == 0:
+ base_error = errors.get('observations', None)
+ if base_error is None:
+ errors['observations'] = {}
+ base_error = errors['observations']
+ error = base_error.get(i, None)
+ if error is None:
+ base_error[i] = {}
+ error = base_error[i]
+ error['biomarker'] = 'not found in dataset'
+ if model is not None:
+ if model.variables.filter(qname=model_var).count() == 0:
+ base_error = errors.get('observations', None)
+ if base_error is None:
+ errors['observations'] = {}
+ base_error = errors['observations']
+ error = base_error.get(i, None)
+ if error is None:
+ base_error[i] = {}
+ error = base_error[i]
+ error['model'] = 'not found in model'
+ else:
+ errors['observations'] = 'field required'
+
+ if errors:
+ return Response(errors, status=status.HTTP_400_BAD_REQUEST)
+
+ # create necessary models, one for each protocol
+ protocols = [
+ Protocol.objects.get(pk=p['protocol'])
+ for p in dataset.subjects.values('protocol').distinct()
+ if p['protocol'] is not None
+ ]
+ rename_models = len(protocols) > 1
+ if len(protocols) == 0 or data['model']['form'] == 'PD':
+ models = [model.create_stored_model()]
+ protocols = [None]
+ else:
+ models = [
+ self._create_dosed_model(
+ model, p, rename_model=rename_models)
+ for p in protocols
+ ]
+
+ # start creating inference object
+ initialization_inference = data.get('initialization_inference')
+ if initialization_inference is not None:
+ initialization_inference = Inference.objects.get(
+ id=initialization_inference
+ )
+
+ if 'id' in data:
+ inference = Inference.objects.get(id=data['id'])
+ inference.reset()
+ inference.name = data.get('name')
+ inference.project = project
+ inference.algorithm = algorithm
+ inference.initialization_strategy = \
+ data.get('initialization_strategy')
+ inference.initialization_inference = initialization_inference
+ inference.number_of_chains = data.get('number_of_chains')
+ inference.max_number_of_iterations = \
+ data.get('max_number_of_iterations')
+ inference.burn_in = data.get('burn_in')
+ inference.read_only = True
+ else:
+ inference = Inference.objects.create(
+ name=data.get('name'),
+ project=project,
+ algorithm=algorithm,
+ initialization_strategy=data.get('initialization_strategy'),
+ initialization_inference=initialization_inference,
+ number_of_chains=data.get('number_of_chains'),
+ max_number_of_iterations=data.get('max_number_of_iterations'),
+ burn_in=data.get('burn_in'),
+ read_only=True
+ )
+ data['id'] = inference.id
+
+ inference.metadata = data
+ inference.save()
+
+ model_loglikelihoods = [
+ LogLikelihood.objects.create(
+ variable=m.variables.first(),
+ inference=inference,
+ form=LogLikelihood.Form.MODEL
+ ) for m in models
+ ]
+
+ biomarkers = self._set_observed_loglikelihoods(
+ data['observations'], model_loglikelihoods,
+ dataset, inference, protocols
+ )
+
+ self._set_parameters(
+ data['parameters'], model_loglikelihoods, inference, dataset,
+ biomarkers
+ )
+
+ inference.run_inference()
+
+ return Response(InferenceSerializer(inference).data)
+
+
+class InferenceOperationView(views.APIView):
+ def op(self, inference):
+ raise NotImplementedError
+
+ def post(self, request, pk, format=None):
+ try:
+ inference = Inference.objects.get(pk=pk)
+ except Inference.DoesNotExist:
+ return Response(status=status.HTTP_404_NOT_FOUND)
+
+ errors = {}
+ if inference.log_likelihoods.count() == 0:
+ errors['log_likelihoods'] = (
+ 'Inference must have at least one log_likelihood'
+ )
+ ll_names = [
+ ll.name for ll in inference.log_likelihoods.all()
+ ]
+ if len(set(ll_names)) < len(ll_names):
+ errors['log_likelihoods'] = (
+ 'inference has log-likelihoods '
+ 'with identical names! {}'
+ ).format(ll_names)
+
+ if errors:
+ return Response(
+ errors, status=status.HTTP_400_BAD_REQUEST
+ )
+
+ self.op(inference)
+
+ return Response(InferenceSerializer(inference).data)
+
+
+class StopInferenceView(InferenceOperationView):
+ def op(self, inference):
+ return inference.stop_inference()
+
+
+class InferenceChainView(viewsets.ModelViewSet):
+ queryset = InferenceChain.objects.all()
+ serializer_class = InferenceChainSerializer
+ filter_backends = [ProjectFilter, InferenceFilter]
diff --git a/pkpdapp/pkpdapp/api/views/likelihoods.py b/pkpdapp/pkpdapp/api/views/likelihoods.py
new file mode 100644
index 00000000..4aeffa1c
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/likelihoods.py
@@ -0,0 +1,39 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import viewsets
+from rest_framework.permissions import IsAuthenticated
+from pkpdapp.api.views import (
+ InferenceFilter,
+ CheckAccessToProject,
+)
+from pkpdapp.api.serializers import (
+ LogLikelihoodParameterSerializer, LogLikelihoodSerializer
+)
+from pkpdapp.models import (
+ LogLikelihood, LogLikelihoodParameter
+)
+
+
+class LogLikelihoodView(viewsets.ModelViewSet):
+ queryset = LogLikelihood.objects.all()
+ serializer_class = LogLikelihoodSerializer
+ filter_backends = [
+ InferenceFilter
+ ]
+ permission_classes = [
+ IsAuthenticated & CheckAccessToProject
+ ]
+
+
+class LogLikelihoodParameterView(viewsets.ModelViewSet):
+ queryset = LogLikelihoodParameter.objects.all()
+ serializer_class = LogLikelihoodParameterSerializer
+ filter_backends = [
+ InferenceFilter
+ ]
+ permission_classes = [
+ IsAuthenticated & CheckAccessToProject
+ ]
diff --git a/pkpdapp/pkpdapp/api/views/login.py b/pkpdapp/pkpdapp/api/views/login.py
new file mode 100644
index 00000000..99e25299
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/login.py
@@ -0,0 +1,77 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import json
+
+from django.contrib.auth import authenticate, login, logout
+from django.http import JsonResponse
+from django.middleware.csrf import get_token
+from django.views.decorators.csrf import ensure_csrf_cookie
+from django.views.decorators.http import require_POST
+from rest_framework.authentication import (
+ SessionAuthentication, BasicAuthentication
+)
+from rest_framework.permissions import IsAuthenticated
+from rest_framework.views import APIView
+from pkpdapp.api.serializers import UserSerializer
+
+
+def get_csrf(request):
+ response = JsonResponse({
+ 'X-CSRFToken': get_token(request),
+ 'detail': 'CSRF cookie set'
+ })
+ return response
+
+
+@ensure_csrf_cookie
+@require_POST
+def login_view(request):
+ data = json.loads(request.body)
+ username = data.get('username')
+ password = data.get('password')
+ if username is None or password is None:
+ return JsonResponse({
+ 'detail': 'Please provide username and password.'
+ }, status=400)
+
+ user = authenticate(username=username, password=password)
+ if user is None:
+ return JsonResponse({'detail': 'Invalid credentials.'}, status=400)
+
+ login(request, user)
+
+ return JsonResponse({
+ 'user': UserSerializer(user).data,
+ 'detail': 'Successfully logged in.'
+ })
+
+
+@ensure_csrf_cookie
+def logout_view(request):
+ if not request.user.is_authenticated:
+ return JsonResponse({'detail': 'You\'re not logged in.'}, status=400)
+
+ logout(request)
+ return JsonResponse({'detail': 'Successfully logged out.'})
+
+
+class SessionView(APIView):
+ authentication_classes = [SessionAuthentication, BasicAuthentication]
+ permission_classes = [IsAuthenticated]
+
+ @staticmethod
+ def get(request, format=None):
+ return JsonResponse({'isAuthenticated': True, 'user':
+ UserSerializer(request.user).data})
+
+
+class WhoAmIView(APIView):
+ authentication_classes = [SessionAuthentication, BasicAuthentication]
+ permission_classes = [IsAuthenticated]
+
+ @staticmethod
+ def get(request, format=None):
+ return JsonResponse({'user': request.user})
diff --git a/pkpdapp/pkpdapp/api/views/models.py b/pkpdapp/pkpdapp/api/views/models.py
new file mode 100644
index 00000000..41600985
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/models.py
@@ -0,0 +1,145 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import viewsets, response, parsers, status, decorators
+from drf_spectacular.utils import extend_schema, OpenApiParameter
+from drf_spectacular.types import OpenApiTypes
+from rest_framework.permissions import IsAuthenticated
+
+from pkpdapp.api.serializers import (
+ PharmacokineticSerializer,
+ PharmacodynamicSerializer,
+ CombinedModelSerializer,
+ PharmacodynamicSbmlSerializer,
+)
+from pkpdapp.api.views import ProjectFilter, CheckAccessToProject
+from pkpdapp.models import (
+ PharmacokineticModel,
+ PharmacodynamicModel,
+ CombinedModel,
+ Inference,
+)
+
+
+class PharmacokineticView(viewsets.ModelViewSet):
+ queryset = PharmacokineticModel.objects.all()
+ serializer_class = PharmacokineticSerializer
+ permission_classes = [IsAuthenticated & CheckAccessToProject]
+
+
+class CombinedModelView(viewsets.ModelViewSet):
+ queryset = CombinedModel.objects.all()
+ serializer_class = CombinedModelSerializer
+ filter_backends = [ProjectFilter]
+ permission_classes = [IsAuthenticated & CheckAccessToProject]
+
+ @extend_schema(
+ parameters=[
+ OpenApiParameter(
+ name="project_id",
+ description="Filter results by project ID",
+ required=False,
+ type=OpenApiTypes.INT,
+ location=OpenApiParameter.QUERY,
+ ),
+ ],
+ )
+ def list(self, request, *args, **kwargs):
+ return super().list(request, *args, **kwargs)
+
+ @decorators.action(
+ detail=True,
+ methods=["PUT"],
+ serializer_class=CombinedModelSerializer,
+ )
+ def set_variables_from_inference(self, request, pk):
+ obj = self.get_object()
+ try:
+ inference = Inference.objects.get(id=request.data["inference_id"])
+ except Inference.DoesNotExist:
+ return response.Response(
+ {"inference_id": "inference not found"}, status.HTTP_400_BAD_REQUEST
+ )
+
+ obj.set_variables_from_inference(inference)
+ serializer = self.serializer_class(obj)
+ return response.Response(serializer.data)
+
+ @decorators.action(
+ detail=True,
+ methods=["PUT"],
+ serializer_class=CombinedModelSerializer,
+ )
+ def set_params_to_defaults(self, request, pk):
+ obj = self.get_object()
+ project = obj.get_project()
+ if project is None:
+ return response.Response(
+ {"project": "project not found"}, status.HTTP_400_BAD_REQUEST
+ )
+ compound = project.compound
+ if compound is None:
+ return response.Response(
+ {"compound": "compound not found"}, status.HTTP_400_BAD_REQUEST
+ )
+ print("setting params to defaults", project.species, compound.compound_type)
+ obj.reset_params_to_defaults(project.species, compound.compound_type)
+ serializer = self.serializer_class(obj)
+ return response.Response(serializer.data)
+
+
+class PharmacodynamicView(viewsets.ModelViewSet):
+ queryset = PharmacodynamicModel.objects.all()
+ serializer_class = PharmacodynamicSerializer
+ filter_backends = [ProjectFilter]
+ permission_classes = [IsAuthenticated & CheckAccessToProject]
+
+ @decorators.action(
+ detail=True,
+ methods=["PUT"],
+ serializer_class=PharmacodynamicSbmlSerializer,
+ parser_classes=[parsers.MultiPartParser],
+ )
+ def sbml(self, request, pk):
+ obj = self.get_object()
+ serializer = self.serializer_class(obj, data=request.data, partial=True)
+ if serializer.is_valid():
+ serializer.save()
+ return response.Response(serializer.data)
+ print("xXXXXXx", serializer.errors)
+ return response.Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
+
+ @decorators.action(
+ detail=True,
+ methods=["PUT"],
+ serializer_class=PharmacodynamicSerializer,
+ parser_classes=[parsers.MultiPartParser],
+ )
+ def mmt(self, request, pk):
+ obj = self.get_object()
+ serializer = self.serializer_class(obj, data=request.data, partial=True)
+ if serializer.is_valid():
+ serializer.save()
+ return response.Response(serializer.data)
+ return response.Response(serializer.errors, status.HTTP_400_BAD_REQUEST)
+
+ @decorators.action(
+ detail=True,
+ methods=["PUT"],
+ serializer_class=PharmacodynamicSerializer,
+ )
+ def set_variables_from_inference(self, request, pk):
+ obj = self.get_object()
+ try:
+ print("got request", request.data)
+ inference = Inference.objects.get(id=request.data["inference_id"])
+ except Inference.DoesNotExist:
+ return response.Response(
+ {"inference_id": "inference not found"}, status.HTTP_400_BAD_REQUEST
+ )
+
+ obj.set_variables_from_inference(inference)
+ serializer = self.serializer_class(obj)
+ return response.Response(serializer.data)
diff --git a/pkpdapp/pkpdapp/api/views/nca.py b/pkpdapp/pkpdapp/api/views/nca.py
new file mode 100644
index 00000000..3c786f97
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/nca.py
@@ -0,0 +1,92 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import (
+ views, status
+)
+from rest_framework.response import Response
+from pkpdapp.models import (
+ BiomarkerType,
+ Subject,
+ Dose,
+)
+from pkpdapp.api.serializers import NcaSerializer
+from pkpdapp.utils import NCA
+
+
+class NcaView(views.APIView):
+ def post(self, request, format=None):
+ errors = {
+ }
+ subject_id = request.data.get('subject_id', None)
+ if subject_id is None:
+ errors['subject_id'] = "This field is required"
+ else:
+ try:
+ subject = Subject.objects.get(id=subject_id)
+ except Subject.DoesNotExist:
+ errors['subject_id'] = \
+ "Subject id {} not found".format(subject_id)
+ if not subject.protocol:
+ errors['subject_id'] = (
+ "Subject id {} does not have a protocol"
+ .format(subject_id)
+ )
+ if subject.protocol.dose_type != subject.protocol.DoseType.DIRECT:
+ errors['subject_id'] = \
+ "Subject dosing protocol is required to be type IV"
+
+ biomarker_type_id = request.data.get('biomarker_type_id', None)
+ if biomarker_type_id is None:
+ errors['biomarker_type_id'] = "This field is required"
+ else:
+ try:
+ biomarker_type = \
+ BiomarkerType.objects.get(id=biomarker_type_id)
+ except BiomarkerType.DoesNotExist:
+ errors['biomarker_type_id'] = (
+ "BiomarkerType id {} not found"
+ .format(biomarker_type_id)
+ )
+
+ if errors:
+ return Response(
+ errors, status=status.HTTP_400_BAD_REQUEST
+ )
+ protocol = subject.protocol
+ df = biomarker_type.data()
+ df = df.loc[df['subjects'] == subject.id]
+
+ if df.shape[0] == 0:
+ errors['biomarker_type'] = (
+ "BiomarkerType {} does not have measurements "
+ "for subject id {}."
+ .format(biomarker_type.id, subject.id)
+ )
+
+ doses = Dose.objects.filter(
+ protocol=protocol
+ ).all()
+
+ if len(doses) != 1:
+ errors['protocol_id'] = (
+ "Protocol id {} has {} doses, only a single dose. "
+ "Please choose a protocol with only one dose."
+ .format(protocol.id, len(doses))
+ )
+
+ if errors:
+ return Response(
+ errors, status=status.HTTP_400_BAD_REQUEST
+ )
+
+ times = df['times'].tolist()
+ concentrations = df['values'].tolist()
+ dose_amount = doses[0].amount
+
+ nca = NCA(times, concentrations, dose_amount)
+ nca.calculate_nca()
+ serializer = NcaSerializer(nca)
+ return Response(serializer.data)
diff --git a/pkpdapp/pkpdapp/api/views/permissions.py b/pkpdapp/pkpdapp/api/views/permissions.py
new file mode 100644
index 00000000..600f45ed
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/permissions.py
@@ -0,0 +1,93 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework.permissions import (
+ BasePermission
+)
+
+
+from pkpdapp.models import (
+ Project, ProjectAccess
+)
+
+
+class NotADatasetDose(BasePermission):
+ def has_object_permission(self, request, view, obj):
+ is_update_method = request.method == 'PUT' or request.method == 'PATCH'
+ if is_update_method and obj.protocol.get_dataset():
+ return False
+ return True
+
+
+class NotADatasetProtocol(BasePermission):
+ def has_object_permission(self, request, view, obj):
+ is_update_method = \
+ request.method == 'PUT' or request.method == 'PATCH'
+ if is_update_method and obj.get_dataset():
+ return False
+ return True
+
+
+class CheckAccessToProject(BasePermission):
+ def has_permission(self, request, view):
+ if request.user.is_superuser:
+ return True
+
+ is_create_method = (
+ request.method == 'POST'
+ )
+
+ if isinstance(request.data, list):
+ project_id = request.data[0].get('project', None)
+ else:
+ project_id = request.data.get('project', None)
+
+ if project_id is None:
+ return True
+
+ project = Project.objects.get(id=project_id)
+
+ if project is None:
+ return True
+
+ try:
+ access = ProjectAccess.objects.get(
+ project=project,
+ user=request.user,
+ )
+ except ProjectAccess.DoesNotExist:
+ return False
+
+ if is_create_method:
+ return not access.read_only
+
+ return True
+
+ def has_object_permission(self, request, view, obj):
+ if request.user.is_superuser:
+ return True
+
+ is_update_method = (
+ request.method == 'PUT' or
+ request.method == 'PATCH'
+ )
+
+ project = obj.get_project()
+
+ if project is None:
+ return True
+
+ try:
+ access = ProjectAccess.objects.get(
+ project=project,
+ user=request.user,
+ )
+ except ProjectAccess.DoesNotExist:
+ return False
+
+ if is_update_method:
+ return not access.read_only
+
+ return True
diff --git a/pkpdapp/pkpdapp/api/views/project.py b/pkpdapp/pkpdapp/api/views/project.py
new file mode 100644
index 00000000..503ca0b4
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/project.py
@@ -0,0 +1,61 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import (
+ viewsets, response, parsers, status, decorators
+)
+from rest_framework.permissions import IsAuthenticated
+
+from pkpdapp.api.serializers import (
+ ProjectSerializer,
+ ProjectAccessSerializer,
+ MonolixSerializer
+)
+from pkpdapp.api.views import (
+ UserAccessFilter,
+ CheckAccessToProject
+)
+from pkpdapp.models import (
+ Project,
+ ProjectAccess
+)
+
+
+class EnablePartialUpdateMixin:
+ """Enable partial updates"""
+
+ def update(self, request, *args, **kwargs):
+ kwargs['partial'] = True
+ return super().update(request, *args, **kwargs)
+
+
+class ProjectView(EnablePartialUpdateMixin, viewsets.ModelViewSet):
+ queryset = Project.objects.all()
+ serializer_class = ProjectSerializer
+ filter_backends = [UserAccessFilter]
+
+ @decorators.action(
+ detail=True,
+ methods=['PUT'],
+ serializer_class=MonolixSerializer,
+ parser_classes=[parsers.MultiPartParser],
+ )
+ def monolix(self, request, pk):
+ obj = self.get_object()
+ serializer = self.serializer_class(obj, data=request.data,
+ partial=True)
+ if serializer.is_valid():
+ serializer.save()
+ return response.Response(serializer.data)
+ return response.Response(serializer.errors,
+ status.HTTP_400_BAD_REQUEST)
+
+
+class ProjectAccessView(viewsets.ModelViewSet):
+ queryset = ProjectAccess.objects.all()
+ serializer_class = ProjectAccessSerializer
+ permission_classes = [
+ IsAuthenticated & CheckAccessToProject
+ ]
diff --git a/pkpdapp/pkpdapp/api/views/protocol.py b/pkpdapp/pkpdapp/api/views/protocol.py
new file mode 100644
index 00000000..4ed3b826
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/protocol.py
@@ -0,0 +1,39 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import viewsets
+from rest_framework.permissions import IsAuthenticated
+from drf_spectacular.utils import extend_schema, OpenApiParameter
+from drf_spectacular.types import OpenApiTypes
+from pkpdapp.api.serializers import ProtocolSerializer
+from pkpdapp.api.views import (
+ ProjectFilter,
+ NotADatasetProtocol,
+ CheckAccessToProject
+)
+from pkpdapp.models import Protocol
+
+
+class ProtocolView(viewsets.ModelViewSet):
+ queryset = Protocol.objects.all()
+ serializer_class = ProtocolSerializer
+ filter_backends = [ProjectFilter]
+ permission_classes = [
+ IsAuthenticated & NotADatasetProtocol & CheckAccessToProject
+ ]
+
+ @extend_schema(
+ parameters=[
+ OpenApiParameter(
+ name='project_id',
+ description='Filter results by project ID',
+ required=False,
+ type=OpenApiTypes.INT,
+ location=OpenApiParameter.QUERY
+ ),
+ ],
+ )
+ def list(self, request, *args, **kwargs):
+ return super().list(request, *args, **kwargs)
diff --git a/pkpdapp/pkpdapp/api/views/simulate.py b/pkpdapp/pkpdapp/api/views/simulate.py
new file mode 100644
index 00000000..716dc1c7
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/simulate.py
@@ -0,0 +1,79 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import views, status
+from rest_framework.response import Response
+from rest_framework import serializers
+from drf_spectacular.utils import extend_schema
+import myokit
+from pkpdapp.models import (
+ CombinedModel, PharmacodynamicModel, Variable
+)
+
+
+class SimulateSerializer(serializers.Serializer):
+ outputs = serializers.ListField(child=serializers.CharField())
+ variables = serializers.DictField(child=serializers.FloatField())
+ time_max = serializers.FloatField(required=False)
+
+
+class SimulateResponseSerializer(serializers.Serializer):
+ time = serializers.ListField(child=serializers.FloatField())
+ outputs = serializers.DictField(
+ child=serializers.ListField(child=serializers.FloatField()))
+
+ def to_representation(self, instance):
+ outputs = {}
+ times = []
+ for var_id, values in instance.items():
+ variable = Variable.objects.get(pk=var_id)
+ if variable.name == 'time' or variable.name == 't':
+ times = values
+ outputs[var_id] = values
+ return {
+ 'outputs': outputs,
+ 'time': times,
+ }
+
+
+class ErrorResponseSerializer(serializers.Serializer):
+ error = serializers.CharField()
+
+
+@extend_schema(
+ request=SimulateSerializer,
+ responses={
+ 200: SimulateResponseSerializer,
+ 400: ErrorResponseSerializer,
+ 404: None,
+ },
+
+)
+class SimulateBaseView(views.APIView):
+ def post(self, request, pk, format=None):
+ try:
+ m = self.model.objects.get(pk=pk)
+ except self.model.DoesNotExist:
+ return Response(status=status.HTTP_404_NOT_FOUND)
+ outputs = request.data.get('outputs', None)
+ variables = request.data.get('variables', None)
+ time_max = request.data.get('time_max', None)
+ try:
+ result = m.simulate(outputs, variables, time_max)
+ except myokit.SimulationError as e:
+ serialized_result = ErrorResponseSerializer({'error': str(e)})
+ return Response(
+ serialized_result.data, status=status.HTTP_400_BAD_REQUEST
+ )
+ serialized_result = SimulateResponseSerializer(result)
+ return Response(serialized_result.data)
+
+
+class SimulateCombinedView(SimulateBaseView):
+ model = CombinedModel
+
+
+class SimulatePdView(SimulateBaseView):
+ model = PharmacodynamicModel
diff --git a/pkpdapp/pkpdapp/api/views/simulation.py b/pkpdapp/pkpdapp/api/views/simulation.py
new file mode 100644
index 00000000..6e3bb7f4
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/simulation.py
@@ -0,0 +1,42 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from rest_framework import viewsets
+from rest_framework.permissions import IsAuthenticated
+
+from drf_spectacular.utils import extend_schema, OpenApiParameter
+from drf_spectacular.types import OpenApiTypes
+from pkpdapp.models import Simulation
+from pkpdapp.api.serializers import (
+ SimulationSerializer
+)
+from pkpdapp.api.views import (
+ ProjectFilter,
+ CheckAccessToProject
+)
+
+
+class SimulationViewSet(viewsets.ModelViewSet):
+ queryset = Simulation.objects.all()
+ serializer_class = SimulationSerializer
+ filter_backends = [ProjectFilter]
+ permission_classes = [
+ IsAuthenticated & CheckAccessToProject
+ ]
+
+ @extend_schema(
+ parameters=[
+ OpenApiParameter(
+ name='project_id',
+ description='Filter results by project ID',
+ required=False,
+ type=OpenApiTypes.INT,
+ location=OpenApiParameter.QUERY
+ ),
+ ],
+ )
+ def list(self, request, *args, **kwargs):
+ return super().list(request, *args, **kwargs)
diff --git a/pkpdapp/pkpdapp/api/views/subject.py b/pkpdapp/pkpdapp/api/views/subject.py
new file mode 100644
index 00000000..f7c0ce8c
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/subject.py
@@ -0,0 +1,17 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import viewsets
+from pkpdapp.api.views import (
+ ProjectFilter,
+)
+from pkpdapp.api.serializers import SubjectSerializer
+from pkpdapp.models import Subject
+
+
+class SubjectView(viewsets.ModelViewSet):
+ queryset = Subject.objects.all()
+ serializer_class = SubjectSerializer
+ filter_backends = [ProjectFilter]
diff --git a/pkpdapp/pkpdapp/api/views/unit.py b/pkpdapp/pkpdapp/api/views/unit.py
new file mode 100644
index 00000000..af101503
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/unit.py
@@ -0,0 +1,69 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import viewsets
+from pkpdapp.api.views import (
+ DosedPkModelFilter,
+ PdModelFilter,
+)
+from pkpdapp.api.serializers import UnitSerializer
+from pkpdapp.models import Unit, Compound
+from drf_spectacular.utils import extend_schema, OpenApiParameter
+from drf_spectacular.types import OpenApiTypes
+
+
+class UnitView(viewsets.ModelViewSet):
+ queryset = Unit.objects.all()
+ serializer_class = UnitSerializer
+ filter_backends = [DosedPkModelFilter, PdModelFilter]
+
+ def get_serializer_context(self):
+ context = super().get_serializer_context()
+
+ request = self.request
+ compound_id = None
+ compound = None
+
+ if request is not None:
+ compound_id = self.request.query_params.get("compound_id")
+
+ if compound_id is not None:
+ try:
+ compound = Compound.objects.get(pk=compound_id)
+ except Compound.DoesNotExist:
+ pass
+
+ if compound is not None:
+ context["compound"] = compound
+
+ return context
+
+ @extend_schema(
+ parameters=[
+ OpenApiParameter(
+ name="compound_id",
+ description="Enable conversions based on compound information",
+ required=False,
+ type=OpenApiTypes.INT,
+ location=OpenApiParameter.QUERY,
+ ),
+ ],
+ )
+ def list(self, request, *args, **kwargs):
+ return super().list(request, *args, **kwargs)
+
+ @extend_schema(
+ parameters=[
+ OpenApiParameter(
+ name="compound_id",
+ description="Enable conversions based on compound information",
+ required=False,
+ type=OpenApiTypes.INT,
+ location=OpenApiParameter.QUERY,
+ ),
+ ],
+ )
+ def retrieve(self, request, *args, **kwargs):
+ return super().retrieve(request, *args, **kwargs)
diff --git a/pkpdapp/pkpdapp/api/views/user.py b/pkpdapp/pkpdapp/api/views/user.py
new file mode 100644
index 00000000..20b9124f
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/user.py
@@ -0,0 +1,13 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import viewsets
+from django.contrib.auth.models import User
+from pkpdapp.api.serializers import UserSerializer
+
+
+class UserView(viewsets.ModelViewSet):
+ queryset = User.objects.all()
+ serializer_class = UserSerializer
diff --git a/pkpdapp/pkpdapp/api/views/variable.py b/pkpdapp/pkpdapp/api/views/variable.py
new file mode 100644
index 00000000..f6a989cd
--- /dev/null
+++ b/pkpdapp/pkpdapp/api/views/variable.py
@@ -0,0 +1,58 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import viewsets
+from rest_framework.permissions import IsAuthenticated
+from drf_spectacular.utils import extend_schema, OpenApiParameter
+from drf_spectacular.types import OpenApiTypes
+from pkpdapp.api.views import (
+ ProjectFilter,
+ CheckAccessToProject,
+ DosedPkModelFilter,
+ PdModelFilter,
+)
+from pkpdapp.api.serializers import (
+ VariableSerializer
+)
+from pkpdapp.models import Variable
+
+
+class VariableView(viewsets.ModelViewSet):
+ queryset = Variable.objects.all()
+ serializer_class = VariableSerializer
+ filter_backends = [
+ ProjectFilter, DosedPkModelFilter, PdModelFilter
+ ]
+ permission_classes = [
+ IsAuthenticated & CheckAccessToProject
+ ]
+
+ @extend_schema(
+ parameters=[
+ OpenApiParameter(
+ name='project_id',
+ description='Filter results by project ID',
+ required=False,
+ type=OpenApiTypes.INT,
+ location=OpenApiParameter.QUERY
+ ),
+ OpenApiParameter(
+ name='dosed_pk_model_id',
+ description='Filter results by dosed_pk_model ID',
+ required=False,
+ type=OpenApiTypes.INT,
+ location=OpenApiParameter.QUERY
+ ),
+ OpenApiParameter(
+ name='pd_model_id',
+ description='Filter results by pd_model ID',
+ required=False,
+ type=OpenApiTypes.INT,
+ location=OpenApiParameter.QUERY
+ ),
+ ],
+ )
+ def list(self, request, *args, **kwargs):
+ return super().list(request, *args, **kwargs)
diff --git a/pkpdapp/pkpdapp/apps.py b/pkpdapp/pkpdapp/apps.py
new file mode 100644
index 00000000..a82f7331
--- /dev/null
+++ b/pkpdapp/pkpdapp/apps.py
@@ -0,0 +1,17 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.apps import AppConfig
+
+
+class PkpdAppConfig(AppConfig):
+ name = 'pkpdapp'
+
+ def ready(self):
+ from django.contrib.auth.models import User
+ from .signals import add_profile_on_user_save
+ from django.db.models.signals import post_save
+ post_save.connect(add_profile_on_user_save, sender=User)
diff --git a/pkpdapp/pkpdapp/asgi.py b/pkpdapp/pkpdapp/asgi.py
new file mode 100644
index 00000000..7f1ccf70
--- /dev/null
+++ b/pkpdapp/pkpdapp/asgi.py
@@ -0,0 +1,22 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+"""
+ASGI config for pkpdapp project.
+
+It exposes the ASGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/.
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pkpdapp.settings')
+
+application = get_asgi_application()
diff --git a/pkpdapp/pkpdapp/celery.py b/pkpdapp/pkpdapp/celery.py
new file mode 100644
index 00000000..5b5eb8ad
--- /dev/null
+++ b/pkpdapp/pkpdapp/celery.py
@@ -0,0 +1,28 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import os
+
+from celery import Celery
+
+# Set the default Django settings module for the 'celery' program.
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pkpdapp.settings')
+
+app = Celery('pkpdapp', backend='rpc://', broker='pyamqp://')
+
+# Using a string here means the worker doesn't have to serialize
+# the configuration object to child processes.
+# - namespace='CELERY' means all celery-related configuration keys
+# should have a `CELERY_` prefix.
+app.config_from_object('django.conf:settings', namespace='CELERY')
+
+# Load task modules from all registered Django apps.
+app.autodiscover_tasks()
+
+
+@app.task(bind=True)
+def debug_task(self):
+ print(f'Request: {self.request!r}')
diff --git a/pkpdapp/pkpdapp/dash_apps/auce_app.py b/pkpdapp/pkpdapp/dash_apps/auce_app.py
new file mode 100644
index 00000000..dd71d173
--- /dev/null
+++ b/pkpdapp/pkpdapp/dash_apps/auce_app.py
@@ -0,0 +1,189 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import dash_core_components as dcc
+import dash_html_components as html
+import dash_bootstrap_components as dbc
+from dash.dependencies import Input, Output
+import plotly.graph_objects as go
+from .auce_figure import AuceFigure
+import pandas as pd
+import django_plotly_dash as dpd
+import json
+
+# Create data view
+app = dpd.DjangoDash(
+ name='auce_view',
+ add_bootstrap_links=True
+)
+
+# Create dash app
+app.layout = dbc.Container([
+ dbc.Row(children=[
+ dbc.Col(width=5, children=[
+ html.Label("Select datasets to use:"),
+ dcc.Dropdown(
+ id='dataset-dropdown',
+ ),
+ ])
+ ]),
+ dbc.Row([
+ dbc.Col(
+ children=[
+ html.P(children=(
+ 'Note: AUCE app requries Dosing Groups corresponding to '
+ 'numerical concentrations '
+ )),
+ dbc.Col(width=3, children=[
+ html.Label("Choose variable:"),
+ dcc.Dropdown(
+ id='auce-biomarker-dropdown',
+ ),
+ ]),
+ dcc.Graph(
+ id='initial-doses-dashboard',
+ figure=go.Figure(),
+ style={'width': '100%'}
+ ),
+ dcc.Graph(
+ id='auce-dashboard',
+ figure=go.Figure(),
+ style={'width': '100%'}
+ )
+ ],
+ ),
+ ]),
+])
+
+
+def rehydrate_state(session_state):
+ if session_state is None:
+ raise NotImplementedError("Cannot handle a missing session state")
+
+ state = session_state.get('auce_view', None)
+
+ if state is None:
+ raise NotImplementedError('AuceState missing in session state')
+
+ return AuceState.from_json(state)
+
+
+@app.callback(
+ [
+ Output('dataset-dropdown', 'options'),
+ Output('dataset-dropdown', 'value'),
+ ],
+ [Input('auce-dashboard', 'style')],
+)
+def update_datasets(_, session_state=None):
+ state = rehydrate_state(session_state)
+ return state._dataset_options, state._selected_dataset
+
+
+@app.callback(
+ [
+ Output('auce-biomarker-dropdown', 'options'),
+ Output('auce-biomarker-dropdown', 'value'),
+ ],
+ [
+ Input('dataset-dropdown', 'value'),
+ ]
+)
+def update_nca_auce_options(dataset_dropdown, session_state=None):
+ state = rehydrate_state(session_state)
+ state._selected_dataset = dataset_dropdown
+ biomarkers = state._get_biomarkers()
+ return biomarkers, biomarkers[0]['value']
+
+
+@app.callback(
+ [
+ Output('initial-doses-dashboard', 'figure'),
+ Output('auce-dashboard', 'figure'),
+ ],
+ [
+ Input('auce-biomarker-dropdown', 'value'),
+ Input('dataset-dropdown', 'value'),
+ ],
+)
+def update_auce(auce_biomarker_dropdown, dataset_dropdown,
+ session_state=None):
+ state = rehydrate_state(session_state)
+ state._selected_dataset = dataset_dropdown
+ return state.generate_auce_figures(auce_biomarker_dropdown)
+
+
+class AuceState:
+ """
+ """
+ _id_key = 'ID'
+ _biomarker_key = 'Biomarker'
+ _compound_key = 'Compound'
+
+ def __init__(self):
+ self._selected_dataset = []
+ self._datasets = []
+ self._dataset_options = []
+ self._auce_biomarker = None
+
+ def add_datasets(self, datasets, dataset_names):
+ # handle empty datasets
+ if not datasets:
+ return
+
+ # by default show last datset
+ self._selected_dataset = 0
+ self._datasets = datasets
+ for dataset, dataset_name in zip(self._datasets, dataset_names):
+ dataset['Dataset'] = dataset_name
+ self._dataset_options = [
+ {'label': name, 'value': i} for i, name in enumerate(dataset_names)
+ ]
+
+ # by default use first biomarker
+ self._auce_biomarker = self._datasets[
+ self._selected_dataset
+ ][self._biomarker_key][0]
+
+ def to_json(self):
+ state_dict = {
+ '_selected_dataset': self._selected_dataset,
+ '_datasets': [d.to_dict() for d in self._datasets],
+ '_dataset_options': self._dataset_options,
+ '_auce_biomarker': self._auce_biomarker,
+ }
+ return json.dumps(state_dict)
+
+ @classmethod
+ def from_json(cls, j):
+ data_dict = json.loads(j)
+ o = cls()
+ o._selected_dataset = data_dict['_selected_dataset']
+ o._datasets = [
+ pd.DataFrame.from_dict(d) for d in data_dict['_datasets']
+ ]
+
+ o._dataset_options = data_dict['_dataset_options']
+ o._auce_biomarker = data_dict['_auce_biomarker']
+ return o
+
+ def generate_auce_figures(self, new_biomarker=None):
+ if not self._datasets:
+ return go.Figure(), go.Figure()
+ if new_biomarker:
+ self._auce_biomarker = new_biomarker
+ self._auce_figure = AuceFigure(
+ self._datasets[self._selected_dataset],
+ self._auce_biomarker
+ )
+ return self._auce_figure.figures()
+
+ def _get_biomarkers(self):
+ biomarkers = set()
+ biomarkers = self._datasets[self._selected_dataset][
+ self._biomarker_key
+ ].unique().tolist()
+ return [{'label': str(i), 'value': i} for i in biomarkers]
diff --git a/pkpdapp/pkpdapp/dash_apps/auce_figure.py b/pkpdapp/pkpdapp/dash_apps/auce_figure.py
new file mode 100644
index 00000000..3a63d8bd
--- /dev/null
+++ b/pkpdapp/pkpdapp/dash_apps/auce_figure.py
@@ -0,0 +1,430 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+'''
+Temporary demo.
+'''
+
+import numpy as np
+import plotly
+import plotly.colors
+import plotly.graph_objects as go
+from plotly.validators.scatter.marker import SymbolValidator
+from scipy.optimize import curve_fit
+
+
+colors = plotly.colors.qualitative.Plotly[:1000]
+symbols = SymbolValidator().values
+
+
+class modeling_class:
+ def __init__(self):
+ self.series = ""
+ self.auce = 0
+
+
+class AuceFigure():
+ """
+ """
+
+ def __init__(self, dataset, biomarker):
+
+ self._id_key = 'ID'
+ self._time_key = 'Time'
+ self._obs_type_key = 'Biomarker'
+ self._obs_key = 'Measurement'
+ self._dose_group_key = 'DoseGroup'
+ self._group_key = 'Group'
+
+ self._fig = go.Figure()
+ self._auce_vs_concentration_fig = go.Figure()
+ self._dataset = dataset
+ self._auce_fit_type = 'Sigmoid'
+ self._class1_selection = 'Biomarker'
+ self._class2_selection = 'Group'
+ self._class3_selection = None
+ self._class1_plot_selection = biomarker
+ self._class2_plot_selection = None
+ self._class3_plot_selection = None
+ self._concentration_plot_selection = None
+
+ self._auce_vs_concentration_fig = compute_auce_vs_concentration(
+ self._dataset, self._auce_vs_concentration_fig,
+ self._time_key, self._auce_fit_type, self._obs_key,
+ self._class1_selection,
+ self._dose_group_key, self._class2_selection,
+ self._class3_selection, self._class1_plot_selection,
+ self._class2_plot_selection, self._class3_plot_selection)
+
+ self._fig = update_figure(
+ self._dataset, self._fig,
+ self._time_key, self._obs_key, self._class1_selection,
+ self._dose_group_key, self._class2_selection,
+ self._class3_selection, self._class1_plot_selection,
+ self._concentration_plot_selection, self._class2_plot_selection,
+ self._class3_plot_selection
+ )
+
+ def figures(self):
+ return self._fig, self._auce_vs_concentration_fig
+
+
+def fsigmoid(concentration, top, bottom, EC50):
+ # this function simulates Emax-EC50 curve for a given concentration range
+ return bottom + concentration * (top - bottom) / (EC50 + concentration)
+
+
+def update_figure(dataset, fig, time_selection, y_selection, class1_selection,
+ concentration_selection, class2_selection,
+ class3_selection, class1_plot_selection,
+ concentration_plot_selection, class2_plot_selection,
+ class3_plot_selection):
+ fig.data = []
+
+ data = dataset.loc[dataset[class1_selection] == class1_plot_selection]
+
+ if concentration_plot_selection:
+ concentration = [concentration_plot_selection]
+ else:
+ concentration = data[concentration_selection].unique()
+
+ for index_concentration, concentration_selected in \
+ enumerate(concentration):
+
+ concentration_data = data.loc[
+ data[concentration_selection] == concentration_selected
+ ]
+ if class2_plot_selection:
+ class2 = [class2_plot_selection]
+ else:
+ class2 = concentration_data[class2_selection].unique()
+
+ for index_class2, class2_selected in enumerate(class2):
+
+ class2_data = concentration_data.loc[
+ concentration_data[class2_selection] == class2_selected
+ ]
+
+ if class3_plot_selection:
+ class3 = class2_data[class3_selection].unique()
+
+ for index_class3, class3_selected in enumerate(class3):
+ class3_data = class2_data.loc[
+ class2_data[class3_selection] == class3_selected
+ ]
+
+ fig.add_trace(go.Scatter(
+ x=class3_data[time_selection],
+ y=class3_data[y_selection],
+ name="%s : %s, %s : %s, %s : %s" % (
+ concentration_selection, concentration_selected,
+ class2_selection, class2_selected,
+ class3_selection, class3_selected
+ ),
+ showlegend=True,
+ visible=True,
+ hovertemplate=(
+ "Measurement " +
+ "%s : %s " % (
+ class1_selection,
+ class1_plot_selection
+ ) +
+ "%s : %s " % (
+ concentration_selection,
+ concentration_selected
+ ) +
+ "%s : %s " % (
+ class2_selection,
+ class2_selected
+ ) +
+ "X : %{x:} " +
+ "Y: %{y:} " +
+ " "),
+ mode="markers",
+ marker=dict(
+ symbol=symbols[index_concentration * 8],
+ opacity=0.7,
+ line=dict(color='black', width=1),
+ color=colors[index_class2]
+ )
+ ))
+ else:
+ fig.add_trace(go.Scatter(
+ x=class2_data[time_selection],
+ y=class2_data[y_selection],
+ name="%s : %s, %s : %s" % (
+ concentration_selection, concentration_selected,
+ class2_selection, class2_selected
+ ),
+ showlegend=True,
+ visible=True,
+ hovertemplate=(
+ "Measurement " +
+ "%s : %s " % (
+ class1_selection,
+ class1_plot_selection
+ ) +
+ "%s : %s " % (
+ concentration_selection,
+ concentration_selected
+ ) +
+ "%s : %s " % (class2_selection, class2_selected) +
+ "X : %{x:} " +
+ "Y: %{y:} " +
+ " "),
+ mode="markers",
+ marker=dict(
+ symbol=symbols[index_concentration * 8],
+ opacity=0.7,
+ line=dict(color='black', width=1),
+ color=colors[index_class2]
+ )
+ ))
+ fig.update_layout(
+ # Button for linear versus log scale
+ updatemenus=[
+ dict(
+ type="buttons",
+ direction="right",
+ pad={"r": 10, "t": 10},
+ showactive=True,
+ x=0.13,
+ xanchor="left",
+ y=1.21,
+ yanchor="top",
+ buttons=list([
+ dict(
+ args=[{"yaxis.type": "linear"}],
+ label="Linear y-scale",
+ method="relayout"
+ ),
+ dict(
+ args=[{"yaxis.type": "log"}],
+ label="Log y-scale",
+ method="relayout"
+ ),
+ dict(
+ args=[{"xaxis.type": "linear"}],
+ label="Linear x-scale",
+ method="relayout"
+ ),
+ dict(
+ args=[{"xaxis.type": "log"}],
+ label="Log x-scale",
+ method="relayout"
+ )
+ ]),
+ )
+ ],
+ autosize=True,
+ xaxis_title='Time in hours',
+ yaxis_title=class1_plot_selection,
+ template="plotly_white",
+ ),
+
+ return fig
+
+
+def compute_auce_vs_concentration(dataset,
+ auce_vs_concentration_fig, time_selection,
+ auce_conc_fit_type,
+ y_selection,
+ class1_selection,
+ concentration_selection, class2_selection,
+ class3_selection, class1_plot_selection,
+ class2_plot_selection,
+ class3_plot_selection):
+
+ auce_vs_concentration_fig.data = []
+ auce_vs_concentration_fig.layout = {}
+ data = dataset.loc[dataset[class1_selection] == class1_plot_selection]
+
+ if class2_plot_selection:
+ class2 = [class2_plot_selection]
+ else:
+ class2 = data[class2_selection].unique()
+
+ for index_class2, class2_selected in enumerate(class2):
+
+ class2_data = data.loc[data[class2_selection] == class2_selected]
+ concentrations = class2_data[concentration_selection].unique()
+ auce_vs_concentration_data = np.zeros(len(concentrations))
+
+ for index_concentration, concentration_selected in \
+ enumerate(concentrations):
+
+ concentration_data = class2_data.loc[
+ class2_data[concentration_selection] == concentration_selected
+ ]
+
+ auce_vs_concentration_data[index_concentration] = np.trapz(
+ concentration_data[y_selection],
+ concentration_data[time_selection]
+ )
+
+ if not (auce_conc_fit_type == 'None'):
+ auce_fit(auce_vs_concentration_fig, auce_conc_fit_type,
+ class2_selection,
+ class2_selected, index_class2, concentrations,
+ auce_vs_concentration_data)
+
+ auce_vs_concentration_fig.add_trace(go.Scatter(
+ x=concentrations,
+ y=auce_vs_concentration_data,
+ name="%s, %s" % (class2_selection, class2_selected),
+ showlegend=True,
+ visible=True,
+ hovertemplate=(
+ "Measurement " +
+ "%s : %s " % (class1_selection, class1_plot_selection) +
+ "%s : %s " % (class2_selection, class2_selected) +
+ "X : %{x:} " +
+ "Y: %{y:} " +
+ " "),
+ mode="markers",
+ marker=dict(
+ opacity=0.7,
+ line=dict(color='black', width=1),
+ color=colors[index_class2]
+ )
+ ))
+
+ auce_vs_concentration_fig.update_layout(
+ updatemenus=[
+ dict(
+ type="buttons",
+ direction="right",
+ pad={"r": 10, "t": 10},
+ showactive=True,
+ x=0.13,
+ xanchor="left",
+ y=1.21,
+ yanchor="top",
+ buttons=list([
+ dict(
+ args=[{"yaxis.type": "linear"}],
+ label="Linear y-scale",
+ method="relayout"
+ ),
+ dict(
+ args=[{"yaxis.type": "log"}],
+ label="Log y-scale",
+ method="relayout"
+ ),
+ dict(
+ args=[{"xaxis.type": "linear"}],
+ label="Linear x-scale",
+ method="relayout"
+ ),
+ dict(
+ args=[{"xaxis.type": "log"}],
+ label="Log x-scale",
+ method="relayout"
+ )
+ ]),
+ )
+ ],
+ autosize=True,
+ xaxis_title='Concentration',
+ xaxis_type='log',
+ yaxis_title='AUCE',
+ yaxis_type='log',
+ template="plotly_white",
+ )
+ return auce_vs_concentration_fig
+
+
+def auce_fit(auce_vs_concentration_fig, auce_conc_fit_type,
+ class2_selection, class2_selected,
+ index_class2, concentrations, auce_vs_concentration_data):
+
+ if auce_conc_fit_type == 'Sigmoid' and len(concentrations) >= 4:
+ p0 = [
+ max(auce_vs_concentration_data),
+ min(auce_vs_concentration_data),
+ 1000
+ ]
+ fitted_params, covariates = curve_fit(
+ fsigmoid, concentrations, auce_vs_concentration_data, p0=p0)
+ fit_top, fit_bottom, fit_EC50 = fitted_params
+
+ sigma_top, sigma_bottom, sigma_EC50 = np.sqrt(np.diag(covariates))
+
+ if min(concentrations):
+ x = np.geomspace(min(concentrations), max(concentrations), 500)
+ else:
+ x = np.geomspace(0.1, max(concentrations), 500)
+
+ y = fsigmoid(x, *fitted_params)
+
+ y_upper = fsigmoid(x, fit_top + abs(sigma_top), fit_bottom +
+ abs(sigma_bottom), fit_EC50 - abs(sigma_EC50))
+ y_lower = fsigmoid(x, fit_top - abs(sigma_top), fit_bottom -
+ abs(sigma_bottom), fit_EC50 + abs(sigma_EC50))
+
+ if (fit_EC50 > 0 and sigma_bottom and sigma_EC50 and
+ sigma_top and (fit_EC50 - abs(sigma_EC50)) > 0):
+ auce_vs_concentration_fig.add_trace(go.Scatter(
+ x=[fit_EC50, fit_EC50],
+ y=[0, fsigmoid(fit_EC50, *fitted_params)],
+ line=dict(width=1, color=colors[index_class2], dash='dot'),
+ mode='lines',
+ hovertemplate=(
+ "EC50 : %f +/- %f " % (fit_EC50, sigma_EC50) +
+ " "),
+ showlegend=False
+ ))
+ auce_vs_concentration_fig.add_trace(go.Scatter(
+ x=x,
+ y=y,
+ name="FIT %s, %s" % (class2_selection, class2_selected),
+ showlegend=True,
+ visible=True,
+ hovertemplate=(
+ "Fit " +
+ "Parameters : " +
+ "Top : %f +/- %f " % (fit_top, sigma_top) +
+ "Bottom : %f +/- %f " % (fit_bottom, sigma_bottom) +
+ "EC50 : %f +/- %f " % (fit_EC50, sigma_EC50) +
+ "X : %{x:} " +
+ "Y: %{y:} " +
+ " "),
+ mode="lines",
+ line=dict(color=colors[index_class2])
+ ))
+ auce_vs_concentration_fig.add_trace(go.Scatter(
+ x=x,
+ y=y_upper,
+ mode='lines',
+ line=dict(width=0.3, color=colors[index_class2]),
+ showlegend=False,
+ hoverinfo='skip'
+ ))
+ auce_vs_concentration_fig.add_trace(go.Scatter(
+ x=x,
+ y=y_lower,
+ line=dict(width=0.3, color=colors[index_class2]),
+ mode='lines',
+ showlegend=False,
+ hoverinfo='skip'
+ ))
+ # auce_vs_concentration_fig.update_layout(
+ # autosize=True,
+ # xaxis_title='Concentration',
+ # yaxis_title='AUCE',
+ # template="plotly_white",
+ # )
+ else:
+ auce_vs_concentration_fig.add_annotation(
+ text=(
+ "Could not fit %s %s " % (
+ class2_selection, class2_selected
+ )
+ ),
+ xref='paper', yref='paper',
+ x=0.05, y=1 - index_class2 * 0.1,
+ showarrow=False, font=dict(color=colors[index_class2])
+ )
diff --git a/pkpdapp/pkpdapp/migrations/0001_initial.py b/pkpdapp/pkpdapp/migrations/0001_initial.py
new file mode 100644
index 00000000..19eaf324
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/0001_initial.py
@@ -0,0 +1,670 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+# Generated by Django 3.0.7 on 2021-01-12 17:55
+# flake8: noqa
+
+
+
+from django.conf import settings
+import django.core.validators
+from django.db import migrations, models
+import django.db.models.deletion
+import jsonfield.fields
+import pkpdapp.models.compound
+import pkpdapp.models.dose
+import pkpdapp.models.inference
+import pkpdapp.models.myokit_model_mixin
+import pkpdapp.models.protocol
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Algorithm',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(help_text='name of the algorithm', max_length=100)),
+ ('category', models.CharField(choices=[('SA', 'Sampling'), ('OP', 'Optimisation'), ('OT', 'Optimisation')], max_length=10)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Biomarker',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('time', models.FloatField(help_text='time point of measurement, in hours.')),
+ ('value', models.FloatField(help_text='value of the measurement')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='BiomarkerType',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(help_text='name of the biomarker type', max_length=100)),
+ ('description', models.TextField(blank=True, help_text='short description of the biomarker type', null=True)),
+ ('display', models.BooleanField(default=True, help_text='True if this biomarker type will be displayed in the frontend, False otherwise')),
+ ('color', models.IntegerField(default=0, help_text='Color index associated with this biomarker type. For plotting purposes in the frontend')),
+ ('axis', models.BooleanField(default=False, help_text='True/False if biomarker type displayed on LHS/RHS axis')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='CategoricalBiomarker',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('time', models.FloatField(help_text='time point of measurement, in hours.')),
+ ('value', models.CharField(help_text='category name', max_length=100)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='CombinedModel',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('read_only', models.BooleanField(default=False, help_text='true if object has been stored')),
+ ('datetime', models.DateTimeField(blank=True, help_text='datetime the object was stored.', null=True)),
+ ('name', models.CharField(help_text='name of the model', max_length=100)),
+ ('species', models.CharField(choices=[('H', 'human'), ('R', 'rat'), ('N', 'non-human primate'), ('M', 'mouse')], default='H', help_text='species', max_length=1)),
+ ('has_saturation', models.BooleanField(default=False, help_text='whether the pk model has saturation')),
+ ('has_effect', models.BooleanField(default=False, help_text='whether the pk model has effect compartment')),
+ ('has_lag', models.BooleanField(default=False, help_text='whether the pk model has lag')),
+ ('has_bioavailability', models.BooleanField(default=False, help_text='whether the pk model has bioavailability')),
+ ('has_hill_coefficient', models.BooleanField(default=False, help_text='whether the pd model has hill coefficient')),
+ ('time_max', models.FloatField(default=30, help_text='suggested time to simulate after the last dose (in the time units specified by the mmt model)')),
+ ],
+ options={
+ 'abstract': False,
+ },
+ bases=(pkpdapp.models.myokit_model_mixin.MyokitModelMixin, models.Model),
+ ),
+ migrations.CreateModel(
+ name='Compound',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(help_text='name of the compound', max_length=100)),
+ ('description', models.TextField(blank=True, default='', help_text='short description of the compound')),
+ ('molecular_mass', models.FloatField(default=500.0, help_text='molecular mass for compound for conversion from mol to grams')),
+ ('compound_type', models.CharField(choices=[('SM', 'Small Molecule'), ('LM', 'Large Molecule')], default='SM', max_length=2)),
+ ('fraction_unbound_plasma', models.FloatField(blank=True, default=0.02, help_text='fraction unbound plasma (unitless)', null=True)),
+ ('blood_to_plasma_ratio', models.FloatField(blank=True, default=1.0, help_text='blood to plasma ratio (unitless)', null=True)),
+ ('intrinsic_clearance', models.FloatField(blank=True, help_text='intrinsic clearance', null=True)),
+ ('intrinsic_clearance_assay', models.CharField(choices=[('MS', 'Microsomes'), ('HC', 'Hepatocytes')], default='MS', max_length=2)),
+ ('fraction_unbound_including_cells', models.FloatField(blank=True, default=1.0, help_text='fraction unbound in plasma and red blood cells (unitless)', null=True)),
+ ('target_molecular_mass', models.FloatField(default=25000.0, help_text='molecular mass for target for conversion from mol to grams')),
+ ('target_concentration', models.FloatField(blank=True, default=1.0, help_text='target concentration', null=True)),
+ ('dissociation_constant', models.FloatField(blank=True, help_text='dissociation constant', null=True)),
+ ('is_soluble', models.BooleanField(default=True, help_text='is the compound target soluble')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Dataset',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(help_text='name of the dataset', max_length=100)),
+ ('datetime', models.DateTimeField(blank=True, help_text='date/time the experiment was conducted. All time measurements are relative to this date/time, which is in YYYY-MM-DD HH:MM:SS format. For example, 2020-07-18 14:30:59', null=True)),
+ ('description', models.TextField(blank=True, default='', help_text='short description of the dataset')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='DerivedVariable',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('read_only', models.BooleanField(default=False, help_text='true if object has been stored')),
+ ('datetime', models.DateTimeField(blank=True, help_text='datetime the object was stored.', null=True)),
+ ('type', models.CharField(choices=[('RO', 'receptor occupancy'), ('FUP', 'faction unbound plasma'), ('BPR', 'blood plasma ratio')], help_text='type of derived variable', max_length=3)),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='DoseBase',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('start_time', models.FloatField(help_text='starting time point of dose, see protocol for units')),
+ ('amount', models.FloatField(help_text='amount of compound administered over the duration, see protocol for units. Rate of administration is assumed constant')),
+ ('duration', models.FloatField(default=1.0, help_text='Duration of dose administration, see protocol for units. Duration must be greater than 0.', validators=[pkpdapp.models.dose.validate_duration])),
+ ('repeats', models.IntegerField(default=1, help_text='Number of times to repeat the dose. ')),
+ ('repeat_interval', models.FloatField(default=1.0, help_text='Interval between repeated doses. See protocol for units. ')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Inference',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('read_only', models.BooleanField(default=False, help_text='true if object has been stored')),
+ ('datetime', models.DateTimeField(blank=True, help_text='datetime the object was stored.', null=True)),
+ ('name', models.CharField(help_text='name of the dataset', max_length=100)),
+ ('description', models.TextField(blank=True, default='', help_text='short description of what this inference does')),
+ ('initialization_strategy', models.CharField(choices=[('D', 'Default Value of model'), ('R', 'Random from prior'), ('F', 'From other inference')], default='R', max_length=1)),
+ ('number_of_chains', models.IntegerField(default=4, help_text='number of chains')),
+ ('max_number_of_iterations', models.IntegerField(default=1000, help_text='maximum number of iterations')),
+ ('burn_in', models.IntegerField(default=0, help_text='final iteration of burn-in')),
+ ('number_of_iterations', models.IntegerField(default=0, help_text='number of iterations calculated')),
+ ('time_elapsed', models.IntegerField(default=0, help_text='Elapsed run time for inference in seconds')),
+ ('number_of_function_evals', models.IntegerField(default=0, help_text='number of function evaluations')),
+ ('task_id', models.CharField(blank=True, help_text='If executing, this is the celery task id', max_length=40, null=True)),
+ ('metadata', models.JSONField(default=dict, help_text='metadata for inference')),
+ ('algorithm', models.ForeignKey(default=pkpdapp.models.inference.get_default_optimisation_algorithm, help_text='algorithm used to perform the inference', on_delete=django.db.models.deletion.PROTECT, to='pkpdapp.algorithm')),
+ ('initialization_inference', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='pkpdapp.inference')),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='InferenceChain',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('inference', models.ForeignKey(help_text='inference for this chain', on_delete=django.db.models.deletion.CASCADE, related_name='chains', to='pkpdapp.inference')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='LogLikelihood',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(help_text='name of log_likelihood.', max_length=100)),
+ ('description', models.TextField(blank=True, help_text='description of log_likelihood. For equations will be the code of that equation using Python syntax: arg1 * arg2^arg3', null=True)),
+ ('value', models.FloatField(blank=True, help_text='set if a fixed value is required', null=True)),
+ ('time_independent_data', models.BooleanField(default=True, help_text='True if biomarker_type refers to time-independent data. If there are multiple timepoints in biomarker_type then only the first is taken ')),
+ ('observed', models.BooleanField(default=False, help_text='True if this log_likelihood is observed ')),
+ ('form', models.CharField(choices=[('N', 'Normal'), ('U', 'Uniform'), ('LN', 'Log-Normal'), ('F', 'Fixed'), ('S', 'Sum'), ('E', 'Equation'), ('M', 'Model')], default='F', max_length=2)),
+ ('biomarker_type', models.ForeignKey(blank=True, help_text='data associated with this log_likelihood. This is used for measurement data (observed=True) or for covariates (observed=False). The random variable associated with this log_likelihood has the same shape as this data. For covariates the subject ids in the data correspond to the values of the random variable at that location.', null=True, on_delete=django.db.models.deletion.PROTECT, to='pkpdapp.biomarkertype')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='PharmacodynamicModel',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('read_only', models.BooleanField(default=False, help_text='true if object has been stored')),
+ ('datetime', models.DateTimeField(blank=True, help_text='datetime the object was stored.', null=True)),
+ ('name', models.CharField(help_text='name of the model', max_length=100)),
+ ('description', models.TextField(blank=True, default='', help_text='short description of the model')),
+ ('mmt', models.TextField(default='[[model]]\n\n[myokit]\ntime = 0 bind time', help_text='the model represented using mmt (see https://myokit.readthedocs)')),
+ ('time_max', models.FloatField(default=30, help_text='suggested maximum time to simulate for this model (in the time units specified by the mmt model)')),
+ ('is_library_model', models.BooleanField(default=False, help_text='whether this model is a library model (i.e. it is not an uploaded user model)')),
+ ],
+ options={
+ 'abstract': False,
+ },
+ bases=(models.Model, pkpdapp.models.myokit_model_mixin.MyokitModelMixin),
+ ),
+ migrations.CreateModel(
+ name='PharmacokineticModel',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('read_only', models.BooleanField(default=False, help_text='true if object has been stored')),
+ ('datetime', models.DateTimeField(blank=True, help_text='datetime the object was stored.', null=True)),
+ ('name', models.CharField(help_text='name of the model', max_length=100)),
+ ('description', models.TextField(blank=True, default='', help_text='short description of the model')),
+ ('mmt', models.TextField(default='[[model]]\n\n[myokit]\ntime = 0 bind time', help_text='the model represented using mmt (see https://myokit.readthedocs)')),
+ ('time_max', models.FloatField(default=30, help_text='suggested maximum time to simulate for this model (in the time units specified by the mmt model)')),
+ ('is_library_model', models.BooleanField(default=False, help_text='whether this model is a library model (i.e. it is not an uploaded user model)')),
+ ],
+ options={
+ 'abstract': False,
+ },
+ bases=(models.Model, pkpdapp.models.myokit_model_mixin.MyokitModelMixin),
+ ),
+ migrations.CreateModel(
+ name='Project',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(help_text='name of the project', max_length=100)),
+ ('description', models.TextField(blank=True, default='', help_text='short description of the project')),
+ ('created', models.DateTimeField(auto_now_add=True)),
+ ('species', models.CharField(choices=[('M', 'Mouse'), ('R', 'Rat'), ('H', 'Human'), ('K', 'Monkey'), ('O', 'Other')], default='O', help_text='subject species', max_length=1)),
+ ('compound', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='pkpdapp.compound')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Protocol',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('read_only', models.BooleanField(default=False, help_text='true if object has been stored')),
+ ('datetime', models.DateTimeField(blank=True, help_text='datetime the object was stored.', null=True)),
+ ('name', models.CharField(help_text='name of the protocol', max_length=100)),
+ ('dose_type', models.CharField(choices=[('D', 'IV'), ('I', 'Extravascular')], default='D', max_length=1)),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ migrations.CreateModel(
+ name='Simulation',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(help_text='name of the simulation', max_length=100)),
+ ('nrows', models.IntegerField(default=1, help_text='number of subplot rows')),
+ ('ncols', models.IntegerField(default=1, help_text='number of subplot columns')),
+ ('time_max', models.FloatField(default=30, help_text='maximum time for the simulation', validators=[django.core.validators.MinValueValidator(0)])),
+ ('abs_tolerance', models.FloatField(default=1e-06, help_text='absolute tolerance for the simulation', validators=[django.core.validators.MinValueValidator(0)])),
+ ('rel_tolerance', models.FloatField(default=1e-06, help_text='relative tolerance for the simulation', validators=[django.core.validators.MinValueValidator(0)])),
+ ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='simulations', to='pkpdapp.project')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='SimulationPlot',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('index', models.IntegerField(help_text='index of the plot in the simulation')),
+ ('x_scale', models.CharField(choices=[('lin', 'Linear'), ('lg2', 'Log2'), ('lg10', 'Log10'), ('ln', 'Ln')], default='lin', help_text='scale for x axis', max_length=4)),
+ ('y_scale', models.CharField(choices=[('lin', 'Linear'), ('lg2', 'Log2'), ('lg10', 'Log10'), ('ln', 'Ln')], default='lin', help_text='scale for y axis', max_length=4)),
+ ('y2_scale', models.CharField(choices=[('lin', 'Linear'), ('lg2', 'Log2'), ('lg10', 'Log10'), ('ln', 'Ln')], default='lin', help_text='scale for rhs y axis', max_length=4)),
+ ('min', models.FloatField(blank=True, help_text='lower bound for the y axis', null=True)),
+ ('max', models.FloatField(blank=True, help_text='upper bound for the y axis', null=True)),
+ ('min2', models.FloatField(blank=True, help_text='lower bound for the rhs y axis', null=True)),
+ ('max2', models.FloatField(blank=True, help_text='upper bound for the rhs y axis', null=True)),
+ ('simulation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='plots', to='pkpdapp.simulation')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Unit',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('symbol', models.CharField(help_text='symbol for unit display', max_length=50)),
+ ('g', models.FloatField(default=0, help_text='grams exponent')),
+ ('m', models.FloatField(default=0, help_text='meters exponent')),
+ ('s', models.FloatField(default=0, help_text='seconds exponent')),
+ ('A', models.FloatField(default=0, help_text='ampere exponent')),
+ ('K', models.FloatField(default=0, help_text='kelvin exponent')),
+ ('cd', models.FloatField(default=0, help_text='candela exponent')),
+ ('mol', models.FloatField(default=0, help_text='mole exponent')),
+ ('multiplier', models.FloatField(default=0, help_text='multiplier in powers of 10')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Dose',
+ fields=[
+ ('dosebase_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='pkpdapp.dosebase')),
+ ('read_only', models.BooleanField(default=False, help_text='true if object has been stored')),
+ ('datetime', models.DateTimeField(blank=True, help_text='datetime the object was stored.', null=True)),
+ ],
+ options={
+ 'abstract': False,
+ },
+ bases=('pkpdapp.dosebase', models.Model),
+ ),
+ migrations.CreateModel(
+ name='Variable',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('read_only', models.BooleanField(default=False, help_text='true if object has been stored')),
+ ('datetime', models.DateTimeField(blank=True, help_text='datetime the object was stored.', null=True)),
+ ('is_public', models.BooleanField(default=False)),
+ ('lower_bound', models.FloatField(blank=True, help_text='lowest possible value for this variable', null=True)),
+ ('upper_bound', models.FloatField(blank=True, help_text='largest possible value for this variable', null=True)),
+ ('default_value', models.FloatField(default=1, help_text='default value for this variable')),
+ ('is_log', models.BooleanField(default=False, help_text='True if default_value is stored as the log of this value')),
+ ('name', models.CharField(help_text='name of the variable', max_length=100)),
+ ('description', models.TextField(blank=True, help_text='description of the variable', null=True)),
+ ('binding', models.CharField(blank=True, help_text='myokit binding of the variable (e.g. time)', max_length=100, null=True)),
+ ('qname', models.CharField(help_text='fully qualitifed name of the variable', max_length=200)),
+ ('unit_symbol', models.CharField(blank=True, help_text='if unit is None then this is the unit of this variable as a string', max_length=20, null=True)),
+ ('constant', models.BooleanField(default=True, help_text='True for a constant variable of the model, i.e. a parameter. False if non-constant, i.e. an output of the model (default is True)')),
+ ('state', models.BooleanField(default=False, help_text='True if it is a state variable of the model and has an initial condition parameter (default is False)')),
+ ('color', models.IntegerField(default=0, help_text='Color index associated with this variable. For display purposes in the frontend')),
+ ('display', models.BooleanField(default=True, help_text='True if this variable will be displayed in the frontend, False otherwise')),
+ ('axis', models.BooleanField(default=False, help_text='False/True if biomarker type displayed on LHS/RHS axis')),
+ ('dosed_pk_model', models.ForeignKey(blank=True, help_text='dosed pharmacokinetic model', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='variables', to='pkpdapp.combinedmodel')),
+ ('pd_model', models.ForeignKey(blank=True, help_text='pharmacodynamic model', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='variables', to='pkpdapp.pharmacodynamicmodel')),
+ ('pk_model', models.ForeignKey(blank=True, help_text='pharmacokinetic model', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='variables', to='pkpdapp.pharmacokineticmodel')),
+ ('protocol', models.ForeignKey(blank=True, help_text='dosing protocol', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='variables', to='pkpdapp.protocol')),
+ ('unit', models.ForeignKey(blank=True, help_text='variable values are in this unit (note this might be different from the unit in the stored sbml)', null=True, on_delete=django.db.models.deletion.PROTECT, to='pkpdapp.unit')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Subject',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('id_in_dataset', models.IntegerField(help_text='unique id in the dataset')),
+ ('shape', models.IntegerField(default=0, help_text='Shape index associated with this subject. For plotting purposes in the frontend')),
+ ('display', models.BooleanField(default=True, help_text='True if this subject will be displayed in the frontend, False otherwise')),
+ ('metadata', jsonfield.fields.JSONField(default=dict, help_text='subject metadata')),
+ ('dataset', models.ForeignKey(help_text='dataset containing this subject', on_delete=django.db.models.deletion.CASCADE, related_name='subjects', to='pkpdapp.dataset')),
+ ('protocol', models.ForeignKey(blank=True, help_text='dosing protocol for this subject.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='subjects', to='pkpdapp.protocol')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='SimulationYAxis',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('right', models.BooleanField(default=False, help_text='True if the variable is plotted on the right y axis')),
+ ('plot', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='y_axes', to='pkpdapp.simulationplot')),
+ ('variable', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='y_axes', to='pkpdapp.variable')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='SimulationSlider',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('simulation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sliders', to='pkpdapp.simulation')),
+ ('variable', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sliders', to='pkpdapp.variable')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='simulationplot',
+ name='x_unit',
+ field=models.ForeignKey(help_text='unit for x axis', on_delete=django.db.models.deletion.PROTECT, related_name='simulation_plots', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='simulationplot',
+ name='y_unit',
+ field=models.ForeignKey(blank=True, help_text='unit for y axis', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='simulation_plots_y', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='simulationplot',
+ name='y_unit2',
+ field=models.ForeignKey(blank=True, help_text='unit for rhs y axis', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='simulation_plots_y2', to='pkpdapp.unit'),
+ ),
+ migrations.CreateModel(
+ name='SimulationCxLine',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('value', models.FloatField(help_text='value of the line')),
+ ('plot', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cx_lines', to='pkpdapp.simulationplot')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='simulation',
+ name='time_max_unit',
+ field=models.ForeignKey(help_text='unit for maximum time', on_delete=django.db.models.deletion.PROTECT, related_name='simulation_time_max', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='protocol',
+ name='amount_unit',
+ field=models.ForeignKey(blank=True, default=pkpdapp.models.protocol.get_mg_unit, help_text='unit for the amount value stored in each dose', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='protocols_amount', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='protocol',
+ name='compound',
+ field=models.ForeignKey(blank=True, help_text='drug compound', null=True, on_delete=django.db.models.deletion.PROTECT, to='pkpdapp.compound'),
+ ),
+ migrations.AddField(
+ model_name='protocol',
+ name='project',
+ field=models.ForeignKey(blank=True, help_text='Project that "owns" this protocol.', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='protocols', to='pkpdapp.project'),
+ ),
+ migrations.AddField(
+ model_name='protocol',
+ name='time_unit',
+ field=models.ForeignKey(blank=True, default=pkpdapp.models.protocol.get_h_unit, help_text='unit for the start_time and duration values stored in each dose', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='protocols_time', to='pkpdapp.unit'),
+ ),
+ migrations.CreateModel(
+ name='ProjectAccess',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('read_only', models.BooleanField(default=False, help_text='True if user has read access only')),
+ ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pkpdapp.project')),
+ ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ migrations.AddField(
+ model_name='project',
+ name='users',
+ field=models.ManyToManyField(help_text='users with access to this project', through='pkpdapp.ProjectAccess', to=settings.AUTH_USER_MODEL),
+ ),
+ migrations.CreateModel(
+ name='Profile',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='PkpdMapping',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('read_only', models.BooleanField(default=False, help_text='true if object has been stored')),
+ ('datetime', models.DateTimeField(blank=True, help_text='datetime the object was stored.', null=True)),
+ ('pd_variable', models.ForeignKey(help_text='variable in PD part of model', on_delete=django.db.models.deletion.CASCADE, related_name='pd_mappings', to='pkpdapp.variable')),
+ ('pk_variable', models.ForeignKey(help_text='variable in PK part of model', on_delete=django.db.models.deletion.CASCADE, related_name='pk_mappings', to='pkpdapp.variable')),
+ ('pkpd_model', models.ForeignKey(help_text='PKPD model that this mapping is for', on_delete=django.db.models.deletion.CASCADE, related_name='mappings', to='pkpdapp.combinedmodel')),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ migrations.AddField(
+ model_name='pharmacodynamicmodel',
+ name='project',
+ field=models.ForeignKey(blank=True, help_text='Project that "owns" this model', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pd_models', to='pkpdapp.project'),
+ ),
+ migrations.CreateModel(
+ name='LogLikelihoodParameter',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(help_text='name of log_likelihood parameter.', max_length=100)),
+ ('parent_index', models.IntegerField(blank=True, help_text='parameter index for distribution and equation parameters. blank for models (variable is used instead)', null=True)),
+ ('child_index', models.IntegerField(default=0, help_text='output index for all log_likelihoods. ')),
+ ('length', models.IntegerField(blank=True, help_text='length of array representing parameter. null for scalar', null=True)),
+ ('child', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='outputs', to='pkpdapp.loglikelihood')),
+ ('parent', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='parameters', to='pkpdapp.loglikelihood')),
+ ('variable', models.ForeignKey(blank=True, help_text='input model variable for this parameter.', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='log_likelihood_parameters', to='pkpdapp.variable')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='loglikelihood',
+ name='children',
+ field=models.ManyToManyField(related_name='parents', through='pkpdapp.LogLikelihoodParameter', to='pkpdapp.LogLikelihood'),
+ ),
+ migrations.AddField(
+ model_name='loglikelihood',
+ name='inference',
+ field=models.ForeignKey(help_text='Log_likelihood belongs to this inference object. ', on_delete=django.db.models.deletion.CASCADE, related_name='log_likelihoods', to='pkpdapp.inference'),
+ ),
+ migrations.AddField(
+ model_name='loglikelihood',
+ name='protocol_filter',
+ field=models.ForeignKey(blank=True, help_text='filter subject data on this protocol(null implies all subjects)', null=True, on_delete=django.db.models.deletion.PROTECT, to='pkpdapp.protocol'),
+ ),
+ migrations.AddField(
+ model_name='loglikelihood',
+ name='variable',
+ field=models.ForeignKey(blank=True, help_text='If form=MODEL, a variable (any) in the deterministic model. ', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='log_likelihoods', to='pkpdapp.variable'),
+ ),
+ migrations.CreateModel(
+ name='InferenceResult',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('iteration', models.IntegerField(help_text='Iteration')),
+ ('value', models.FloatField(help_text='estimated parameter value')),
+ ('chain', models.ForeignKey(help_text='Chain related to the row', on_delete=django.db.models.deletion.CASCADE, related_name='inference_results', to='pkpdapp.inferencechain')),
+ ('log_likelihood', models.ForeignKey(help_text='log_likelihood related to this result', on_delete=django.db.models.deletion.CASCADE, related_name='inference_results', to='pkpdapp.loglikelihood')),
+ ('subject', models.ForeignKey(blank=True, help_text='subject related to this result', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inference_results', to='pkpdapp.subject')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='InferenceOutputResult',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('median', models.FloatField(help_text='median of output distribution')),
+ ('percentile_min', models.FloatField(blank=True, help_text='10th percentile of output distribution', null=True)),
+ ('percentile_max', models.FloatField(blank=True, help_text='90th percentile of output distribution', null=True)),
+ ('data', models.FloatField(help_text='data value for comparison')),
+ ('time', models.FloatField(help_text='time of output value')),
+ ('chain', models.ForeignKey(help_text='Chain related to the output result', on_delete=django.db.models.deletion.CASCADE, related_name='inference_output_results', to='pkpdapp.inferencechain')),
+ ('log_likelihood', models.ForeignKey(help_text='log_likelihood related to the output result', on_delete=django.db.models.deletion.CASCADE, related_name='inference_output_results', to='pkpdapp.loglikelihood')),
+ ('subject', models.ForeignKey(blank=True, help_text='subject of output value', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='inference_outputs', to='pkpdapp.subject')),
+ ],
+ ),
+ migrations.CreateModel(
+ name='InferenceFunctionResult',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('iteration', models.IntegerField(help_text='Iteration')),
+ ('value', models.FloatField(help_text='estimated parameter value')),
+ ('chain', models.ForeignKey(help_text='Chain related to the row', on_delete=django.db.models.deletion.CASCADE, related_name='inference_function_results', to='pkpdapp.inferencechain')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='inference',
+ name='project',
+ field=models.ForeignKey(help_text='Project that "owns" this inference object', on_delete=django.db.models.deletion.CASCADE, to='pkpdapp.project'),
+ ),
+ migrations.CreateModel(
+ name='EfficacyExperiment',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(blank=True, default='', help_text='name of the experiment', max_length=100)),
+ ('c50', models.FloatField(help_text='half maximal effective concentration')),
+ ('hill_coefficient', models.FloatField(default=1.0, help_text='Hill coefficient measure of binding')),
+ ('c50_unit', models.ForeignKey(help_text='unit for c50', on_delete=django.db.models.deletion.PROTECT, related_name='efficacy_experiments', to='pkpdapp.unit')),
+ ('compound', models.ForeignKey(help_text='compound for efficacy experiment', on_delete=django.db.models.deletion.CASCADE, related_name='efficacy_experiments', to='pkpdapp.compound')),
+ ],
+ ),
+ migrations.AddConstraint(
+ model_name='dosebase',
+ constraint=models.CheckConstraint(check=models.Q(('duration__gt', 0)), name='Duration must be greater than 0'),
+ ),
+ migrations.AddField(
+ model_name='derivedvariable',
+ name='pk_variable',
+ field=models.ForeignKey(help_text='base variable in PK part of model', on_delete=django.db.models.deletion.CASCADE, related_name='derived_variables', to='pkpdapp.variable'),
+ ),
+ migrations.AddField(
+ model_name='derivedvariable',
+ name='pkpd_model',
+ field=models.ForeignKey(help_text='PKPD model that this derived variable is for', on_delete=django.db.models.deletion.CASCADE, related_name='derived_variables', to='pkpdapp.combinedmodel'),
+ ),
+ migrations.AddField(
+ model_name='dataset',
+ name='project',
+ field=models.ForeignKey(blank=True, help_text='Project that "owns" this model', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='datasets', to='pkpdapp.project'),
+ ),
+ migrations.AddField(
+ model_name='compound',
+ name='dissociation_unit',
+ field=models.ForeignKey(default=pkpdapp.models.compound.get_dissociation_constant_unit, help_text='unit for dissociation constant', on_delete=django.db.models.deletion.PROTECT, related_name='compounds_kd', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='compound',
+ name='intrinsic_clearance_unit',
+ field=models.ForeignKey(default=pkpdapp.models.compound.get_intrinsic_clearence_unit, help_text='unit for intrinsic clearance', on_delete=django.db.models.deletion.PROTECT, related_name='compounds_clint', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='compound',
+ name='molecular_mass_unit',
+ field=models.ForeignKey(default=pkpdapp.models.compound.get_mol_mass_unit, help_text='unit for molecular mass (e.g. g/mol)', on_delete=django.db.models.deletion.PROTECT, related_name='compound_mol_mass', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='compound',
+ name='target_concentration_unit',
+ field=models.ForeignKey(default=pkpdapp.models.compound.get_target_concentration_unit, help_text='unit for target concentration', on_delete=django.db.models.deletion.PROTECT, related_name='compounds_target_conc', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='compound',
+ name='target_molecular_mass_unit',
+ field=models.ForeignKey(default=pkpdapp.models.compound.get_mol_mass_unit, help_text='unit for target molecular mass (e.g. g/mol)', on_delete=django.db.models.deletion.PROTECT, related_name='compounds_target_mol_mass', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='compound',
+ name='use_efficacy',
+ field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='compound_using', to='pkpdapp.efficacyexperiment'),
+ ),
+ migrations.AddField(
+ model_name='combinedmodel',
+ name='pd_model',
+ field=models.ForeignKey(blank=True, help_text='PD part of model', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='pkpd_models', to='pkpdapp.pharmacodynamicmodel'),
+ ),
+ migrations.AddField(
+ model_name='combinedmodel',
+ name='pd_model2',
+ field=models.ForeignKey(blank=True, help_text='second PD part of model', null=True, on_delete=django.db.models.deletion.PROTECT, related_name='pkpd_models2', to='pkpdapp.pharmacodynamicmodel'),
+ ),
+ migrations.AddField(
+ model_name='combinedmodel',
+ name='pk_model',
+ field=models.ForeignKey(blank=True, help_text='model', null=True, on_delete=django.db.models.deletion.PROTECT, to='pkpdapp.pharmacokineticmodel'),
+ ),
+ migrations.AddField(
+ model_name='combinedmodel',
+ name='project',
+ field=models.ForeignKey(blank=True, help_text='Project that "owns" this model', null=True, on_delete=django.db.models.deletion.CASCADE, related_name='pk_models', to='pkpdapp.project'),
+ ),
+ migrations.AddField(
+ model_name='categoricalbiomarker',
+ name='biomarker_type',
+ field=models.ForeignKey(help_text='biomarker type, for example "weight in kg"', on_delete=django.db.models.deletion.CASCADE, related_name='categorical_biomarkers', to='pkpdapp.biomarkertype'),
+ ),
+ migrations.AddField(
+ model_name='categoricalbiomarker',
+ name='subject',
+ field=models.ForeignKey(help_text='subject associated with this biomarker', on_delete=django.db.models.deletion.CASCADE, related_name='categorical_biomarkers', to='pkpdapp.subject'),
+ ),
+ migrations.AddField(
+ model_name='biomarkertype',
+ name='dataset',
+ field=models.ForeignKey(help_text='dataset containing this biomarker measurement', on_delete=django.db.models.deletion.CASCADE, related_name='biomarker_types', to='pkpdapp.dataset'),
+ ),
+ migrations.AddField(
+ model_name='biomarkertype',
+ name='display_time_unit',
+ field=models.ForeignKey(help_text='unit to use when sending or displaying time values', on_delete=django.db.models.deletion.PROTECT, related_name='biomarker_types_time_display', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='biomarkertype',
+ name='display_unit',
+ field=models.ForeignKey(help_text='unit to use when sending or displaying biomarker values', on_delete=django.db.models.deletion.PROTECT, related_name='biomarker_types_display', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='biomarkertype',
+ name='stored_time_unit',
+ field=models.ForeignKey(help_text='unit for the time values stored in :model:`pkpdapp.Biomarker`', on_delete=django.db.models.deletion.PROTECT, related_name='biomarker_types_time_stored', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='biomarkertype',
+ name='stored_unit',
+ field=models.ForeignKey(help_text='unit for the value stored in :model:`pkpdapp.Biomarker`', on_delete=django.db.models.deletion.PROTECT, related_name='biomarker_types_stored', to='pkpdapp.unit'),
+ ),
+ migrations.AddField(
+ model_name='biomarker',
+ name='biomarker_type',
+ field=models.ForeignKey(help_text='biomarker type, for example "concentration in mg"', on_delete=django.db.models.deletion.CASCADE, related_name='biomarkers', to='pkpdapp.biomarkertype'),
+ ),
+ migrations.AddField(
+ model_name='biomarker',
+ name='subject',
+ field=models.ForeignKey(help_text='subject associated with this biomarker', on_delete=django.db.models.deletion.CASCADE, related_name='biomarkers', to='pkpdapp.subject'),
+ ),
+ migrations.AddConstraint(
+ model_name='variable',
+ constraint=models.CheckConstraint(check=models.Q(models.Q(('is_log', True), ('lower_bound__gt', 0)), ('is_log', False), _connector='OR'), name='variable: log scale must have a lower bound greater than zero'),
+ ),
+ migrations.AddConstraint(
+ model_name='variable',
+ constraint=models.CheckConstraint(check=models.Q(models.Q(('pk_model__isnull', True), ('dosed_pk_model__isnull', True), ('pd_model__isnull', False)), models.Q(('pk_model__isnull', False), ('dosed_pk_model__isnull', True), ('pd_model__isnull', True)), models.Q(('pk_model__isnull', True), ('dosed_pk_model__isnull', False), ('pd_model__isnull', True)), _connector='OR'), name='variable: variable must belong to a model'),
+ ),
+ migrations.AddConstraint(
+ model_name='subject',
+ constraint=models.UniqueConstraint(fields=('id_in_dataset', 'dataset'), name='subject_dataset_unique'),
+ ),
+ migrations.AlterUniqueTogether(
+ name='projectaccess',
+ unique_together={('user', 'project')},
+ ),
+ migrations.AddConstraint(
+ model_name='loglikelihood',
+ constraint=models.CheckConstraint(check=models.Q(('form', 'F'), ('value__isnull', True), ('biomarker_type__isnull', True), _negated=True), name='loglikelihood: fixed log_likelihood must have a value or biomarker_type'),
+ ),
+ migrations.AddConstraint(
+ model_name='loglikelihood',
+ constraint=models.CheckConstraint(check=models.Q(('form', 'M'), ('variable__isnull', True), _negated=True), name='loglikelihood: model log_likelihood must have a variable'),
+ ),
+ migrations.AddConstraint(
+ model_name='loglikelihood',
+ constraint=models.CheckConstraint(check=models.Q(models.Q(('form', 'F'), ('form', 'S'), ('form', 'M'), _connector='OR'), ('biomarker_type__isnull', False), ('protocol_filter', False), _negated=True), name='loglikelihood: deterministic log_likelihoods cannot have data'),
+ ),
+ migrations.AddField(
+ model_name='dose',
+ name='protocol',
+ field=models.ForeignKey(help_text='protocol containing this dose', on_delete=django.db.models.deletion.CASCADE, related_name='doses', to='pkpdapp.protocol'),
+ ),
+ ]
diff --git a/pkpdapp/pkpdapp/migrations/0003_initial_users_and_projects.py b/pkpdapp/pkpdapp/migrations/0003_initial_users_and_projects.py
new file mode 100644
index 00000000..4799f84c
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/0003_initial_users_and_projects.py
@@ -0,0 +1,121 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import migrations
+from django.contrib.auth.hashers import make_password
+
+
+def load_users_and_projects(apps, schema_editor):
+ compound = {
+ 'name': 'demoCompound',
+ 'description': '''This is an example compound demonstrating
+ some of the capabilities of pkpdapp''',
+ 'molecular_mass': 100,
+ 'molecular_mass_unit': 'g/mol',
+ 'compound_type': 'SM',
+ 'intrinsic_clearance_unit': 'µL/min/mg',
+ 'intrinsic_clearance_assay': 'MS',
+ 'fraction_unbound_plasma': 1.0,
+ 'fraction_unbound_including_cells': 1.0,
+ 'target_molecular_mass': 100,
+ 'target_molecular_mass_unit': 'g/mol',
+ 'target_concentration': 1e-9,
+ 'target_concentration_unit': 'nmol/L',
+ 'dissociation_constant_unit': 'nmol/L',
+ 'is_soluble': True,
+ }
+ users = [
+ {
+ 'username': 'demo',
+ 'password': '12345',
+ 'projects': [
+ {
+ 'name': 'demo',
+ 'description': '''This is an example project demonstrating
+ some of the capabilities of pkpdapp''',
+ 'read_only': False,
+ },
+ ]
+ },
+ {
+ 'username': 'demo2',
+ 'password': '12345',
+ 'projects': [
+ {
+ 'name': 'demo',
+ 'description': '''This is an example project demonstrating
+ some of the capabilities of pkpdapp''',
+ 'read_only': True,
+ },
+ ]
+ }
+ ]
+
+ Project = apps.get_model("pkpdapp", "Project")
+ Profile = apps.get_model("pkpdapp", "Profile")
+ Unit = apps.get_model("pkpdapp", "Unit")
+ User = apps.get_model("auth", "User")
+ Compound = apps.get_model("pkpdapp", "Compound")
+ compound = Compound.objects.create(
+ name=compound['name'],
+ description=compound['description'],
+ molecular_mass=compound['molecular_mass'],
+ compound_type=compound['compound_type'],
+ molecular_mass_unit=Unit.objects.get(
+ symbol=compound['molecular_mass_unit']),
+ intrinsic_clearance_unit=Unit.objects.get(
+ symbol=compound['intrinsic_clearance_unit']),
+ intrinsic_clearance_assay='MS',
+ fraction_unbound_plasma=1.0,
+ fraction_unbound_including_cells=1.0,
+ target_molecular_mass=100,
+ target_molecular_mass_unit=Unit.objects.get(
+ symbol=compound['target_molecular_mass_unit']),
+ target_concentration=1e-9,
+ target_concentration_unit=Unit.objects.get(
+ symbol=compound['target_concentration_unit']),
+ dissociation_unit=Unit.objects.get(
+ symbol=compound['dissociation_constant_unit']),
+ is_soluble=True,
+ )
+ for u in users:
+ user = User.objects.create(
+ username=u['username'],
+ password=make_password(u['password']),
+ )
+
+ for p in u['projects']:
+ try:
+ project = Project.objects.get(
+ name=p['name']
+ )
+ except Project.DoesNotExist:
+ project = Project.objects.create(
+ name=p['name'],
+ description=p['description'],
+ compound=compound,
+ )
+
+ project.users.add(
+ user,
+ through_defaults={'read_only': p['read_only']}
+ )
+
+ profile = Profile(
+ user=user,
+ )
+ profile.save()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('pkpdapp', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.RunPython(load_users_and_projects),
+ ]
diff --git a/pkpdapp/pkpdapp/migrations/0004_merge_initial_data.py b/pkpdapp/pkpdapp/migrations/0004_merge_initial_data.py
new file mode 100644
index 00000000..2b91c518
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/0004_merge_initial_data.py
@@ -0,0 +1,20 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('pkpdapp', '0003_initial_users_and_projects'),
+ ('pkpdapp', '0006_initial_pkpd_models'),
+ ('pkpdapp', '0005_initial_datasets'),
+ ('pkpdapp', '0008_initial_algorithms'),
+ ]
+
+ operations = [
+ ]
diff --git a/pkpdapp/pkpdapp/migrations/0005_initial_datasets.py b/pkpdapp/pkpdapp/migrations/0005_initial_datasets.py
new file mode 100644
index 00000000..ee7826e5
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/0005_initial_datasets.py
@@ -0,0 +1,559 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import migrations
+import urllib.request
+import csv
+import codecs
+from datetime import datetime
+from django.utils.timezone import make_aware
+import myokit
+
+datafile_urls = [
+ 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/datasets/lxf_control_growth.csv', # noqa: E501
+ 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/datasets/lxf_medium_erlotinib_dose.csv', # noqa: E501
+ 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/datasets/demo_pk_data_upload.csv', # noqa: E501
+ 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/datasets/TCB4dataset.csv', # noqa: E501
+ 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/usecase0/usecase0.csv', # noqa: E501
+ 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/usecase1/usecase1.csv', # noqa: E501
+]
+
+datafile_urls = []
+
+datafile_names = [
+ 'lxf_control_growth',
+ 'lxf_medium_erlotinib_dose',
+ 'demo_pk_data',
+ 'TCB4dataset',
+ 'usecase0',
+ 'usecase1',
+]
+
+protocol_units = [
+ {
+ 'time': None,
+ 'amount': None,
+ },
+ {
+ 'time': None,
+ 'amount': None,
+ },
+ {
+ 'time': myokit.Unit.parse_simple('h'),
+ 'amount': myokit.Unit.parse_simple('mg'),
+ },
+ {
+ 'time': None,
+ 'amount': myokit.Unit.parse_simple('ng'),
+ },
+ {
+ 'time': myokit.Unit.parse_simple('h'),
+ 'amount': myokit.Unit.parse_simple('ng'),
+ },
+ {
+ 'time': myokit.Unit.parse_simple('h'),
+ 'amount': myokit.Unit.parse_simple('ng'),
+ },
+]
+
+datafile_descriptions = [
+ '''
+The dataset from [1] contains the time series data of 8 mice with
+patient-derived lung cancer implants. The tumour volume of each
+mouse was monitored over a period of 30 days and measured a
+couple times a week.
+
+References
+----------
+.. [1] Eigenmann, M. J. et al., Combining Nonclinical Experiments with
+ Translational PKPD Modeling to Differentiate Erlotinib and
+ Gefitinib, Mol Cancer Ther. 2016; 15(12):3110-3119.
+''', # noqa: W605
+ '''
+Returns the medium erlotinib dose lung cancer treatment group data
+published in [1]_ as a :class:`pandas.DataFrame`.
+
+The dataset contains the time series data of 8 mice with patient-derived lung
+cancer implants. Each mouse was treated with an oral dose of erlotinib of
+\(25\, \\text{mg}\) per \(\\text{g}\) body weight. The dose was administered
+daily from day 3 to day 16.
+
+The blood plasma concentration of erlotinib was measured on day 10 and 16,
+while the tumour volume of each mouse was monitored over a period of 30 days
+and measured a couple times a week.
+''', # noqa: W605
+ '''
+Demo PK data
+''', # noqa: W605
+ '''
+TCB4 dataset
+''', # noqa: W605
+ '''
+usecase0 dataset
+''', # noqa: W605
+ '''
+usecase1 dataset
+''', # noqa: W605
+]
+
+
+biomarkers_for_datasets = [
+ [
+ {
+ 'name': 'Tumour volume',
+ 'unit': 'cm^3',
+ 'time': 'd',
+ },
+ {
+ 'name': 'Body weight',
+ 'unit': 'g',
+ 'time': 'd',
+ },
+ ],
+ [
+ {
+ 'name': 'Tumour volume',
+ 'unit': 'cm^3',
+ 'time': 'd',
+ },
+ {
+ 'name': 'Body weight',
+ 'unit': 'g',
+ 'time': 'd',
+ },
+ {
+ 'name': 'Plasma concentration',
+ 'unit': 'ng/mL',
+ 'time': 'd',
+ },
+ ],
+ [
+ {
+ 'name': 'Docetaxel',
+ 'unit': 'ng/mL',
+ 'time': 'h',
+ },
+ {
+ 'name': 'Red blood cells',
+ 'unit': '10^6/mcL',
+ 'time': 'h',
+ },
+ {
+ 'name': 'Hemoglobin',
+ 'unit': 'g/dL',
+ 'time': 'h',
+ },
+ {
+ 'name': 'Platelets ',
+ 'unit': '10^3/mcL',
+ 'time': 'h',
+ },
+ {
+ 'name': 'White blood cells',
+ 'unit': '10^3/mcL',
+ 'time': 'h',
+ },
+ ],
+ [
+ {
+ 'name': 'IL2',
+ 'unit': 'ng/mL',
+ 'time': 'h',
+ },
+ {
+ 'name': 'IL10',
+ 'unit': 'ng/mL',
+ 'time': 'h',
+ },
+ {
+ 'name': 'IL6',
+ 'unit': 'ng/mL',
+ 'time': 'h',
+ },
+ {
+ 'name': 'IFNg',
+ 'unit': 'ng/mL',
+ 'time': 'h',
+ },
+ {
+ 'name': 'TNFa',
+ 'unit': 'ng/mL',
+ 'time': 'h',
+ },
+ {
+ 'name': 'Cells',
+ 'unit': 'ng/mL',
+ 'time': 'h',
+ },
+ ],
+ [
+ {
+ 'name': 'DemoDrug Concentration',
+ 'unit': 'ng/mL',
+ 'time': 'h',
+ },
+ ],
+ [
+ {
+ 'name': 'DemoDrug Concentration',
+ 'unit': 'ng/mL',
+ 'time': 'h',
+ },
+ ]
+]
+
+
+def protocol_is_same_as(my_protocol, my_doses, protocol, other_doses):
+ if my_protocol.project != protocol.project:
+ return False
+ if my_protocol.compound != protocol.compound:
+ return False
+ if my_protocol.dose_type != protocol.dose_type:
+ return False
+ if my_protocol.time_unit != protocol.time_unit:
+ return False
+ if my_protocol.time_unit != protocol.time_unit:
+ return False
+ if my_protocol.amount_unit != protocol.amount_unit:
+ return False
+
+ for my_dose, other_dose in zip(my_doses, other_doses):
+ if my_dose.start_time != other_dose.start_time:
+ return False
+ if my_dose.amount != other_dose.amount:
+ return False
+ if my_dose.duration != other_dose.duration:
+ return False
+
+ return True
+
+
+def load_datasets(apps, schema_editor):
+ Dataset = apps.get_model("pkpdapp", "Dataset")
+ Subject = apps.get_model("pkpdapp", "Subject")
+ Biomarker = apps.get_model("pkpdapp", "Biomarker")
+ CategoricalBiomarker = apps.get_model("pkpdapp", "CategoricalBiomarker")
+ BiomarkerType = apps.get_model("pkpdapp", "BiomarkerType")
+ Project = apps.get_model("pkpdapp", "Project")
+ Compound = apps.get_model("pkpdapp", "Compound")
+ Dose = apps.get_model("pkpdapp", "Dose")
+ Unit = apps.get_model("pkpdapp", "Unit")
+ Protocol = apps.get_model("pkpdapp", "Protocol")
+
+ demo_project = Project.objects.get(name='demo')
+ for (datafile_name, datafile_url, datafile_description,
+ biomarkers, protocol_unit) \
+ in zip(datafile_names, datafile_urls, datafile_descriptions,
+ biomarkers_for_datasets, protocol_units):
+
+ with urllib.request.urlopen(datafile_url) as f:
+ # create all the biomarker measurements for that dataset
+ # create the dataset
+ dataset = Dataset(
+ name=datafile_name,
+ description=datafile_description,
+ datetime=make_aware(datetime.today()),
+ project=demo_project
+ )
+ dataset.save()
+
+ # find the index of the biomarker type, so we don't have to keep
+ # looking it up
+ biomarker_index = {}
+ for i, b in enumerate(biomarkers):
+ biomarker_index[b['name']] = i
+
+ # create all the biomarker types for that dataset
+ biomarker_types = [
+ BiomarkerType.objects.create(
+ name=b['name'],
+ description=b['name'],
+ stored_unit=Unit.objects.get(
+ symbol=b['unit']
+ ),
+ display_unit=Unit.objects.get(
+ symbol=b['unit']
+ ),
+ stored_time_unit=Unit.objects.get(
+ symbol=b['time'] if b['time'] != 'd' else 'day'
+ ),
+ display_time_unit=Unit.objects.get(
+ symbol=b['time'] if b['time'] != 'd' else 'day'
+ ),
+ dataset=dataset,
+ color=i,
+ ) for i, b in enumerate(biomarkers)
+ ]
+
+ # parse as csv file
+ data_reader = csv.reader(codecs.iterdecode(f, 'utf-8'))
+
+ # skip the header
+ next(data_reader)
+
+ # create entries
+ if datafile_name == 'TCB4dataset':
+ TIME_COLUMN = 0
+ TIME_UNIT_COLUMN = 10
+ VALUE_COLUMN = 1
+ TINF_COLUMN = None
+ UNIT_COLUMN = 11
+ BIOMARKER_TYPE_COLUMN = 2
+ SUBJECT_ID_COLUMN = 8
+ DOSE_COLUMN = None
+ DOSE_GROUP_COLUMN = 4
+ COMPOUND_COLUMN = None
+ SUBJECT_GROUP_COLUMN = 3
+ ROUTE_COLUMN = None
+ elif datafile_name == 'demo_pk_data':
+ TIME_COLUMN = 4
+ TIME_UNIT_COLUMN = 5
+ TINF_COLUMN = 9
+ VALUE_COLUMN = 3
+ UNIT_COLUMN = 11
+ BIOMARKER_TYPE_COLUMN = 13
+ SUBJECT_ID_COLUMN = 2
+ DOSE_GROUP_COLUMN = None
+ DOSE_COLUMN = 8
+ COMPOUND_COLUMN = 0
+ SUBJECT_GROUP_COLUMN = None
+ ROUTE_COLUMN = None
+ elif datafile_name in ['usecase0', 'usecase1']:
+ TIME_COLUMN = 4
+ TIME_UNIT_COLUMN = 5
+ TINF_COLUMN = 9
+ VALUE_COLUMN = 3
+ UNIT_COLUMN = 11
+ BIOMARKER_TYPE_COLUMN = 13
+ SUBJECT_ID_COLUMN = 2
+ DOSE_GROUP_COLUMN = None
+ DOSE_COLUMN = 8
+ COMPOUND_COLUMN = 0
+ SUBJECT_GROUP_COLUMN = 18
+ ROUTE_COLUMN = 21
+ else:
+ TIME_COLUMN = 1
+ TIME_UNIT_COLUMN = 2
+ TINF_COLUMN = None
+ VALUE_COLUMN = 4
+ UNIT_COLUMN = 5
+ BIOMARKER_TYPE_COLUMN = 3
+ DOSE_GROUP_COLUMN = None
+ SUBJECT_ID_COLUMN = 0
+ DOSE_COLUMN = None
+ COMPOUND_COLUMN = None
+ SUBJECT_GROUP_COLUMN = None
+ ROUTE_COLUMN = None
+ subject_index = 0
+ protocols = {}
+ doses = {}
+ dimensionless_unit = Unit.objects.get(symbol='')
+ for row in data_reader:
+ biomarker_type_str = row[BIOMARKER_TYPE_COLUMN]
+ if not biomarker_type_str:
+ continue
+ if biomarker_type_str not in biomarker_index:
+ continue
+ index = biomarker_index[biomarker_type_str]
+ bt = biomarker_types[index]
+ value = row[VALUE_COLUMN]
+
+ if TIME_UNIT_COLUMN is None:
+ time_unit = Unit.objects.get(symbol='h')
+ else:
+ time_unit = Unit.objects.get(symbol=row[TIME_UNIT_COLUMN] if row[TIME_UNIT_COLUMN] != 'd' else 'day') # noqa: E501
+
+ subject_id = row[SUBJECT_ID_COLUMN]
+ try:
+ subject = Subject.objects.get(
+ id_in_dataset=subject_id,
+ dataset=dataset,
+ )
+ except Subject.DoesNotExist:
+ subject = Subject.objects.create(
+ id_in_dataset=subject_id,
+ dataset=dataset,
+ shape=subject_index,
+ )
+ if SUBJECT_GROUP_COLUMN:
+ group_str = row[SUBJECT_GROUP_COLUMN]
+ if group_str != '' and group_str != '.':
+ try:
+ group_bt = BiomarkerType.objects.get(
+ name='group',
+ dataset=dataset
+ )
+ except BiomarkerType.DoesNotExist:
+ group_bt = BiomarkerType.objects.create(
+ name='group',
+ description='group',
+ stored_unit=dimensionless_unit,
+ display_unit=dimensionless_unit,
+ stored_time_unit=time_unit,
+ display_time_unit=time_unit,
+ dataset=dataset,
+ )
+ try:
+ CategoricalBiomarker.objects.get(
+ biomarker_type=group_bt,
+ subject=subject,
+ )
+ except CategoricalBiomarker.DoesNotExist:
+ CategoricalBiomarker.objects.create(
+ value=group_str,
+ biomarker_type=group_bt,
+ subject=subject,
+ time=0,
+ )
+
+ if DOSE_GROUP_COLUMN:
+ dose_group_amount = row[DOSE_GROUP_COLUMN]
+ dose_group_unit = Unit.objects.get(symbol='')
+ try:
+ dose_bt = BiomarkerType.objects.get(
+ name='dose',
+ dataset=dataset
+ )
+ except BiomarkerType.DoesNotExist:
+ dose_bt = BiomarkerType.objects.create(
+ name='dose',
+ description='dose',
+ stored_unit=dose_group_unit,
+ display_unit=dose_group_unit,
+ stored_time_unit=time_unit,
+ display_time_unit=time_unit,
+ dataset=dataset,
+ color=0,
+ )
+ try:
+ dose = Biomarker.objects.get(
+ biomarker_type=dose_bt,
+ subject=subject,
+ )
+ except Biomarker.DoesNotExist:
+ dose = Biomarker.objects.create(
+ value=float(dose_group_amount),
+ biomarker_type=dose_bt,
+ subject=subject,
+ time=0,
+ )
+ subject_index += 1
+ if UNIT_COLUMN is None:
+ unit = Unit.objects.get(symbol='')
+ else:
+ unit = Unit.objects.get(symbol=row[UNIT_COLUMN])
+ unit == bt.stored_unit
+
+ try:
+ value = float(value)
+ is_number = True
+ except ValueError:
+ is_number = False
+ if is_number:
+ Biomarker.objects.create(
+ time=row[TIME_COLUMN],
+ subject=subject,
+ value=value,
+ biomarker_type=bt
+ )
+ elif (
+ DOSE_COLUMN and
+ row[VALUE_COLUMN] == '.' and
+ row[DOSE_COLUMN] != '.'
+ ):
+ compound_str = row[COMPOUND_COLUMN]
+ try:
+ compound = Compound.objects.get(name=compound_str)
+ except Compound.DoesNotExist:
+ compound = Compound.objects.create(
+ name=compound_str,
+ # TODO how to get molecular_mass?
+ molecular_mass=100,
+ compound_type='SM',
+ molecular_mass_unit=Unit.objects.get(symbol='g/mol'), # noqa: E501
+ intrinsic_clearance_unit=Unit.objects.get(symbol='µL/min/mg'), # noqa: E501
+ intrinsic_clearance_assay='MS',
+ fraction_unbound_plasma=1.0,
+ fraction_unbound_including_cells=1.0,
+ target_molecular_mass=100,
+ target_molecular_mass_unit=Unit.objects.get(symbol='g/mol'), # noqa: E501
+ target_concentration=1e-9,
+ target_concentration_unit=Unit.objects.get(symbol='nmol/L'), # noqa: E501
+ dissociation_unit=Unit.objects.get(symbol='nmol/L'), # noqa: E501
+ is_soluble=True,
+ )
+ if subject.id in protocols:
+ protocol = protocols[subject.id]
+ else:
+ if ROUTE_COLUMN is None or row[ROUTE_COLUMN] == 'IV':
+ route = 'D'
+ else:
+ route = 'I'
+ protocol = Protocol(
+ name='{}-{}-{}'.format(
+ dataset.name,
+ compound.name,
+ subject_id
+ ),
+ compound=compound,
+ time_unit=time_unit,
+ amount_unit=unit,
+ read_only=True,
+ dose_type=route,
+ )
+ protocols[subject.id] = protocol
+ doses[protocol.name] = []
+
+ doses[protocol.name].append(Dose(
+ start_time=row[TIME_COLUMN],
+ amount=row[DOSE_COLUMN],
+ duration=row[TINF_COLUMN],
+ protocol=protocol,
+ ))
+
+ unique_protocols = []
+ protocol_subjects = []
+ for subject_id, protocol in protocols.items():
+ index = None
+ for i in range(len(unique_protocols)):
+ if protocol_is_same_as(
+ unique_protocols[i],
+ doses[unique_protocols[i].name],
+ protocol,
+ doses[protocol.name],
+ ):
+ index = i
+ break
+ if index is None:
+ unique_protocols.append(protocol)
+ protocol_subjects.append(
+ [Subject.objects.get(id=subject_id)]
+ )
+ else:
+ protocol_subjects[index].append(
+ Subject.objects.get(id=subject_id)
+ )
+ for protocol, subjects in zip(unique_protocols, protocol_subjects):
+ the_doses = doses[protocol.name]
+ protocol.save()
+ for dose in the_doses:
+ dose.protocol = protocol
+ dose.save()
+ for subject in subjects:
+ subject.protocol = protocol
+ subject.save()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('pkpdapp', '0003_initial_users_and_projects'),
+ ('pkpdapp', '0007_initial_units'),
+ ]
+
+ operations = [
+ migrations.RunPython(load_datasets),
+ ]
diff --git a/pkpdapp/pkpdapp/migrations/0006_initial_pkpd_models.py b/pkpdapp/pkpdapp/migrations/0006_initial_pkpd_models.py
new file mode 100644
index 00000000..2f711768
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/0006_initial_pkpd_models.py
@@ -0,0 +1,556 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import migrations
+import urllib.request
+import codecs
+from myokit.formats.sbml import SBMLParser
+import myokit
+from pkpdapp.models import MyokitModelMixin
+
+
+def load_pkpd_models(apps, schema_editor):
+ models_pd = [
+ {
+ 'name':
+ 'tumour_growth_inhibition_model_koch',
+ 'description':
+ '''
+Tumour growth inhibition pharmacodynamic model introduced by Koch et al. in
+[1]. In this model the tumour growth inhibition is modelled by an empirical
+model of the tumour volume \(V_T\) over time
+
+$$
+ \\frac{\\text{d}V_T}{\\text{d}t} =
+ \\frac{2\\lambda_0\\lambda_1 V_T}
+ {2\\lambda_0V_T + \\lambda_1} - \\kappa C V_T.
+$$
+
+Here, the tumour growth in absence of the drug is assumed to grow
+exponentially at rate \(2\\lambda_0\) for tumour volumes below some
+critical volume \(V_{\\text{crit}}\). For volumes beyond
+\(V_{\\text{crit}}\) the growth dynamics is assumed to slow down
+and transition to a linear growth at rate \(\\lambda_0\). The tumour
+growth inhibitory effect of the compound is modelled proportionally to
+its concentration \(C\) and the current tumour volume. The
+proportionality factor \(\\kappa\) can be interpreted as the potency
+of the drug.
+Note that the critical tumour volume \(V_{\\text{crit}}\) at which
+the growth dynamics transitions from exponential to linear growth is
+given by the two growth rates
+
+$$
+ V_{\\text{crit}} = \\frac{\\lambda _1}{2\\lambda _0}.
+$$
+
+**References**
+
+[1] Koch, G. et al. Modeling of tumor growth and anticancer effects
+ of combination therapy. J Pharmacokinet Pharmacodyn 36, 179–197
+ (2009).''', # noqa: W605
+ 'sbml_url':
+ 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/models/tgi_Koch_2009.xml' # noqa: E501
+ },
+ {
+ 'name':
+ 'tumour_growth_inhibition_model_koch_reparametrised',
+ 'description':
+ """
+Returns the absolute path to a SBML file, specifying the tumour growth
+inhibition pharmacodynamic model introduced by Koch et al. in [1]_ with
+modified parametrisation.
+
+In this model the tumour growth inhibition is modelled by an empirical
+model of the tumour volume \(V_T\) over time
+
+$$
+ \\frac{\\text{d}V_T}{\\text{d}t} =
+ \\frac{\lambda V_T}
+ {V_T / V_{\\text{crit}} + 1} - \\kappa C V_T.
+$$
+
+Here, the tumour growth in absence of the drug is assumed to grow
+exponentially at rate \(\\lambda\) for tumour volumes below some
+critical volume \(V_{\\text{crit}}\). For volumes beyond
+\(V_{\\text{crit}}\) the growth dynamics is assumed to slow down
+and transition to a linear growth at rate
+\(\\lambda V_{\\text{crit}}\). The tumour growth inhibitory effect
+of the compound is modelled proportionally to its concentration
+\(C\) and the current tumour volume. The proportionality factor
+\(\\kappa\) can be interpreted as the potency of the drug.
+
+Note that this parameterisation of the model is related to the original
+parametersation in [1]_ by
+
+$$
+ V_{\\text{crit}} = \\frac{\\lambda _1}{2\\lambda _0} \\quad \\text{and}
+ \\quad \\lambda = 2\\lambda _1 .
+$$
+""", # noqa: W605
+ 'sbml_url':
+ 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/models/tgi_Koch_2009_reparametrised.xml' # noqa: E501
+ },
+ ]
+ models_pd = []
+ models_pd_mmt = [
+ {
+ 'name': 'indirect_effects_stimulation_elimination',
+ 'description': 'Indirect effects model with stimulation and elimination', # noqa: E501
+ 'mmt_filename': 'pkpdapp/migrations/models/IE_StimulationElimination_Emax.mmt' # noqa: E501
+ },
+ {
+ 'name': 'indirect_effects_inhibition_elimination',
+ 'description': 'Indirect effects model with inhibition and elimination', # noqa: E501
+ 'mmt_filename': 'pkpdapp/migrations/models/IE_InhibitionElimination_Imax.mmt' # noqa: E501
+ },
+ {
+ 'name': 'indirect_effects_stimulation_production',
+ 'description': 'Indirect effects model with stimulation and production', # noqa: E501
+ 'mmt_filename': 'pkpdapp/migrations/models/IE_StimulationProduction_Emax.mmt' # noqa: E501
+ },
+ {
+ 'name': 'indirect_effects_inhibition_production',
+ 'description': 'Indirect effects model with inhibition and production', # noqa: E501
+ 'mmt_filename': 'pkpdapp/migrations/models/IE_InhibitionProduction_Imax.mmt' # noqa: E501
+ },
+ {
+ 'name': 'indirect_effects_precursor_inhibition_production',
+ 'description': 'Indirect effects precursor model with inhibition and production', # noqa: E501
+ 'mmt_filename': 'pkpdapp/migrations/models/IE_Precursor_InhibitionElimination_Emax.mmt' # noqa: E501
+ },
+ {
+ 'name': 'indirect_effects_precursor_stimulation_production',
+ 'description': 'Indirect effects precursor model with stimulatino and production', # noqa: E501
+ 'mmt_filename': 'pkpdapp/migrations/models/IE_Precursor_StimulationElimination_Emax.mmt' # noqa: E501
+ },
+ {
+ 'name': 'direct_effects_emax',
+ 'description': 'Direct effects model with Emax',
+ 'mmt_filename': 'pkpdapp/migrations/models/DE_Emax.mmt' # noqa: E501
+ },
+ {
+ 'name': 'direct_effects_imax',
+ 'description': 'Direct effects model with Imax',
+ 'mmt_filename': 'pkpdapp/migrations/models/DE_Imax.mmt' # noqa: E501
+ },
+ {
+ 'name': 'tumour_growth_gompertz',
+ 'description': '',
+ 'mmt_filename': 'pkpdapp/migrations/models/TG_Gompertz_PDModel.mmt' # noqa: E501
+ },
+ {
+ 'name': 'tumour_growth_simeoni_logistic',
+ 'description': '',
+ 'mmt_filename': 'pkpdapp/migrations/models/TG_Simeoni_logistic_PDModel.mmt' # noqa: E501
+ },
+ {
+ 'name': 'tumour_growth_simeoni',
+ 'description': '',
+ 'mmt_filename': 'pkpdapp/migrations/models/TG_Simeoni_PDModel.mmt' # noqa: E501
+ },
+ {
+ 'name': 'tumour_growth_inhibition_delay_cell_distribution_conc_prop_kill', # noqa: E501
+ 'description': '',
+ 'mmt_filename': 'pkpdapp/migrations/models/TGI_Delay_CellDistribution_ConcPropKill_PDModel.mmt' # noqa: E501
+ },
+ {
+ 'name': 'tumour_growth_inhibition_delay_cell_distribution_emax_kill', # noqa: E501
+ 'description': '',
+ 'mmt_filename': 'pkpdapp/migrations/models/TGI_Delay_CellDistribution_EmaxKill_PDModel.mmt' # noqa: E501
+ },
+ {
+ 'name': 'tumour_growth_inhibition_delay_cell_distribution_exp_conc_kill', # noqa: E501
+ 'description': '',
+ 'mmt_filename': 'pkpdapp/migrations/models/TGI_Delay_CellDistribution_expConcPropKill_PDModel.mmt' # noqa: E501
+ },
+
+ {
+ 'name': 'tumour_growth_inhibition_delay_signal_distribution_conc_prop_kill', # noqa: E501
+ 'description': '',
+ 'mmt_filename': 'pkpdapp/migrations/models/TGI_Delay_SignalDistribution_ConcPropKill_PDModel.mmt' # noqa: E501
+ },
+ {
+ 'name': 'tumour_growth_inhibition_delay_signal_distribution_emax_kill', # noqa: E501
+ 'description': '',
+ 'mmt_filename': 'pkpdapp/migrations/models/TGI_Delay_SignalDistribution_EmaxKill_PDModel.mmt' # noqa: E501
+ },
+ {
+ 'name': 'tumour_growth_inhibition_delay_signal_distribution_exp_conc_kill', # noqa: E501
+ 'description': '',
+ 'mmt_filename': 'pkpdapp/migrations/models/TGI_Delay_SignalDistribution_expConcPropKill_PDModel.mmt' # noqa: E501
+ },
+ ]
+
+ models_pk = [
+ {
+ 'name':
+ 'one_compartment_clinical',
+ 'description':
+ """
+Description of a clinical one compartment PK model here.
+""", # noqa: W605
+ 'mmt_filename':
+ 'pkpdapp/migrations/models/1cmpt_PK_Model_Clinical.mmt' # noqa: E501
+ },
+ {
+ 'name':
+ 'one_compartment_preclinical',
+ 'description':
+ """
+Description of a preclinical one compartment PK model here.
+""", # noqa: W605
+ 'mmt_filename':
+ 'pkpdapp/migrations/models/1cmpt_PK_Model_Preclinical.mmt' # noqa: E501
+ },
+ {
+ 'name':
+ 'two_compartment_clinical',
+ 'description':
+ """
+Description of a clinical two compartment PK model here.
+""", # noqa: W605
+ 'mmt_filename':
+ 'pkpdapp/migrations/models/2cmpt_PK_Model_Clinical.mmt' # noqa: E501
+ },
+ {
+ 'name':
+ 'two_compartment_preclinical',
+ 'description':
+ """
+Description of a preclinical two compartment PK model here.
+""", # noqa: W605
+ 'mmt_filename':
+ 'pkpdapp/migrations/models/2cmpt_PK_Model_Preclinical.mmt' # noqa: E501
+ },
+ {
+ 'name':
+ 'three_compartment_clinical',
+ 'description':
+ """
+Description of a clinical three compartment PK model here.
+""", # noqa: W605
+ 'mmt_filename':
+ 'pkpdapp/migrations/models/3cmpt_PK_Model_Clinical.mmt' # noqa: E501
+ },
+ {
+ 'name':
+ 'three_compartment_preclinical',
+ 'description':
+ """
+Description of a preclinical three compartment PK model here.
+""", # noqa: W605
+ 'mmt_filename':
+ 'pkpdapp/migrations/models/3cmpt_PK_Model_Preclinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'one_compartment_tmdd_full_clinical',
+ 'description':
+ """
+Description of a clinical one compartment TMDD model here.
+""", # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_Full_1cmpt_PK_Model_Clinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'one_compartment_tmdd_full_preclinical',
+ 'description':
+ """
+Description of a clinical one compartment TMDD model here.
+""", # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_Full_1cmpt_PK_Model_Preclinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'one_compartment_tmdd_QSS_clinical',
+ 'description':
+ """
+Description of a clinical one compartment TMDD model here.
+""", # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_QSS_1cmpt_PK_Model_Clinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'one_compartment_tmdd_QSS_preclinical',
+ 'description':
+ """
+Description of a clinical two compartment TMDD model here.
+""", # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_QSS_1cmpt_PK_Model_Preclinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'two_compartment_tmdd_full_clinical',
+ 'description':
+ """
+Description of a clinical two compartment TMDD model here.
+""", # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_Full_2cmpt_PK_Model_Clinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'two_compartment_tmdd_full_preclinical',
+ 'description':
+ """
+Description of a clinical two compartment TMDD model here.
+""", # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_Full_2cmpt_PK_Model_Preclinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'two_compartment_tmdd_QSS_clinical',
+ 'description':
+ """
+Description of a clinical two compartment TMDD model here.
+""", # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_QSS_2cmpt_PK_Model_Clinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'two_compartment_tmdd_QSS_preclinical',
+ 'description':
+ """
+Description of a clinical two compartment TMDD model here.
+""", # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_QSS_2cmpt_PK_Model_Preclinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'one_compartment_tmdd_full_constant_target_clinical',
+ 'description':
+ """
+ Description of a clinical one compartment TMDD model here.
+ """, # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_Full_ConstTarget_1cmpt_PK_Model_Clinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'two_compartment_tmdd_full_constant_target_clinical',
+ 'description':
+ """
+ Description of a clinical two compartment TMDD model here.
+ """, # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_Full_ConstTarget_2cmpt_PK_Model_clinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'one_compartment_tmdd_full_constant_target_preclinical',
+ 'description':
+ """
+ Description of a preclinical one compartment TMDD model here.
+ """, # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_Full_ConstTarget_1cmpt_PK_Model_Preclinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'two_compartment_tmdd_full_constant_target_preclinical',
+ 'description':
+ """
+ Description of a preclinical two compartment TMDD model here.
+ """, # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_Full_ConstTarget_2cmpt_PK_Model_preclinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'one_compartment_tmdd_qss_constant_target_clinical',
+ 'description':
+ """
+ Description of a clinical one compartment TMDD model here.
+ """, # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_QSS_ConstTarget_1cmpt_PK_Model_Clinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'two_compartment_tmdd_qss_constant_target_clinical',
+ 'description':
+ """
+ Description of a clinical two compartment TMDD model here.
+ """, # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_QSS_ConstTarget_2cmpt_PK_Model_clinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'one_compartment_tmdd_qss_constant_target_preclinical',
+ 'description':
+ """
+ Description of a preclinical one compartment TMDD model here.
+ """, # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_QSS_ConstTarget_1cmpt_PK_Model_Preclinical.mmt' # noqa: E501
+ },
+ {
+ 'name': 'two_compartment_tmdd_qss_constant_target_preclinical',
+ 'description':
+ """
+ Description of a preclinical two compartment TMDD model here.
+ """, # noqa: W605
+ 'mmt_filename': 'pkpdapp/migrations/models/TMDD_QSS_ConstTarget_2cmpt_PK_Model_preclinical.mmt' # noqa: E501
+ },
+ ]
+
+ PharmacodynamicModel = apps.get_model("pkpdapp", "PharmacodynamicModel")
+ PharmacokineticModel = apps.get_model("pkpdapp", "PharmacokineticModel")
+ CombinedModel = apps.get_model("pkpdapp", "CombinedModel")
+ Unit = apps.get_model("pkpdapp", "Unit")
+ Variable = apps.get_model("pkpdapp", "Variable")
+ Project = apps.get_model("pkpdapp", "Project")
+ demo_project = Project.objects.get(name='demo')
+ for m in models_pd:
+ try:
+ with urllib.request.urlopen(m['sbml_url'], timeout=5) as f:
+ sbml_string = codecs.decode(f.read(), 'utf-8')
+ model = PharmacodynamicModel.objects.create(
+ name=m['name'],
+ description=m['description'],
+ mmt=MyokitModelMixin.sbml_string_to_mmt(sbml_string),
+ project=demo_project,
+ is_library_model=True,
+ )
+
+ myokit_model = SBMLParser().parse_string(
+ str.encode(sbml_string)
+ ).myokit_model()
+
+ for i, v in enumerate(myokit_model.variables()):
+ unit = v.unit()
+ exponents = unit.exponents()
+ multiplier = unit.multiplier_log_10()
+ close_enough = 1e-9
+ close_enough_units = Unit.objects.filter(
+ g__range=(
+ exponents[0] - close_enough,
+ exponents[0] + close_enough,
+ ),
+ m__range=(
+ exponents[1] - close_enough,
+ exponents[1] + close_enough,
+ ),
+ s__range=(
+ exponents[2] - close_enough,
+ exponents[2] + close_enough,
+ ),
+ A__range=(
+ exponents[3] - close_enough,
+ exponents[3] + close_enough,
+ ),
+ K__range=(
+ exponents[4] - close_enough,
+ exponents[4] + close_enough,
+ ),
+ cd__range=(
+ exponents[5] - close_enough,
+ exponents[5] + close_enough,
+ ),
+ mol__range=(
+ exponents[6] - close_enough,
+ exponents[6] + close_enough,
+ ),
+ multiplier__range=(
+ multiplier - close_enough,
+ multiplier + close_enough,
+ ),
+ )
+ if close_enough_units.count() > 0:
+ stored_unit = close_enough_units[0]
+ else:
+ raise RuntimeError(
+ 'Unit {} {} ({}) does not exist'.format(
+ unit, unit.exponents(),
+ unit.multiplier_log_10()
+ )
+ )
+
+ Variable.objects.create(
+ name=v.name(),
+ qname=v.qname(),
+ constant=v.is_constant(),
+ state=v.is_state(),
+ binding=v.binding(),
+ unit=stored_unit,
+ pd_model=model,
+ color=i,
+ display=v.name() != 'time',
+ )
+
+ except urllib.error.URLError:
+ print('WARNING: urlopen timed-out, no data loaded')
+
+ for m in models_pd_mmt:
+ try:
+ # check myokit can parse the model
+ mmt_string = open(m['mmt_filename'], 'r').read()
+ myokit_model = myokit.parse(mmt_string)[0]
+ print('loading', m['mmt_filename'], myokit_model.meta['name'])
+ myokit_model.validate()
+ model = PharmacodynamicModel.objects.create(
+ name=m['name'],
+ description=myokit_model.meta['name'],
+ mmt=mmt_string,
+ )
+ except urllib.error.URLError:
+ print('WARNING: urlopen timed-out, no data loaded')
+
+ for m in models_pk:
+ try:
+ # check myokit can parse the model
+ mmt_string = open(m['mmt_filename'], 'r').read()
+ myokit_model = myokit.parse(mmt_string)[0]
+ print('loading', m['mmt_filename'], myokit_model.meta['name'])
+ myokit_model.validate()
+ model = PharmacokineticModel.objects.create(
+ name=m['name'],
+ description=myokit_model.meta['name'],
+ mmt=mmt_string,
+ is_library_model=True,
+ )
+ except urllib.error.URLError:
+ print('WARNING: urlopen timed-out, no data loaded')
+
+ model = CombinedModel.objects.create(
+ name='demo',
+ project=demo_project,
+ )
+
+ # three_comp_model = PharmacokineticModel.objects.get(
+ # name='three_compartment_pk_model'
+ # )
+ # usecase0_model = DosedPharmacokineticModel.objects.create(
+ # name='usecase0',
+ # project=demo_project,
+ # pk_model=three_comp_model,
+ # dose_compartment='central',
+ # protocol=(
+ # Dataset.objects.get(name='usecase0')
+ # .subjects.first().protocol
+ # )
+ # )
+ # for variable in usecase0_model.variables.all():
+ # if variable.qname == 'myokit.drug_c_scale':
+ # continue
+ # if variable.state and variable.qname != 'myokit.drug_c_concentration':
+ # variable.display = False
+ # variable.lower_bound = 0
+ # variable.upper_bound = 0.1
+ # variable.default_value = 0.05
+ # variable.save()
+
+ # usecase1_model = DosedPharmacokineticModel.objects.create(
+ # name='usecase1',
+ # project=demo_project,
+ # pk_model=three_comp_model,
+ # dose_compartment='central',
+ # protocol=(
+ # Dataset.objects.get(name='usecase1')
+ # .subjects.first().protocol
+ # )
+ # )
+ # for variable in usecase1_model.variables.all():
+ # if variable.qname == 'myokit.drug_c_scale':
+ # continue
+ # if variable.state and variable.qname != 'myokit.drug_c_concentration':
+ # variable.display = False
+
+ # variable.lower_bound = 0
+ # variable.upper_bound = 0.1
+ # variable.default_value = 0.05
+ # variable.save()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('pkpdapp', '0003_initial_users_and_projects'),
+ ('pkpdapp', '0005_initial_datasets'),
+ ('pkpdapp', '0007_initial_units'),
+ ]
+
+ operations = [
+ migrations.RunPython(load_pkpd_models),
+ ]
diff --git a/pkpdapp/pkpdapp/migrations/0007_initial_units.py b/pkpdapp/pkpdapp/migrations/0007_initial_units.py
new file mode 100644
index 00000000..57e55c4c
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/0007_initial_units.py
@@ -0,0 +1,324 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import migrations
+import myokit
+
+
+def load_units(apps, schema_editor):
+ Unit = apps.get_model("pkpdapp", "Unit")
+ L = myokit.Unit.parse_simple("L")
+ cL = myokit.Unit.parse_simple("cL")
+ h = myokit.Unit.parse_simple("h")
+ g = myokit.Unit.parse_simple("g")
+ mol = myokit.Unit.parse_simple("mol")
+ dimensionless = myokit.Unit()
+
+ units = [
+ {
+ "symbol": "nmol/L",
+ "unit": 1e-9 * mol / L,
+ },
+ {
+ "symbol": "mol",
+ "unit": mol,
+ },
+ {
+ "symbol": "nmol",
+ "unit": 1e-9 * mol,
+ },
+ {
+ "symbol": "pmol",
+ "unit": 1e-12 * mol,
+ },
+ {
+ "symbol": "µmol",
+ "unit": 1e-6 * mol,
+ },
+ {
+ "symbol": "pmol/L",
+ "unit": 1e-12 * mol / L,
+ },
+ {
+ "symbol": "µmol/L",
+ "unit": 1e-6 * mol / L,
+ },
+ {
+ "symbol": "nmol/L",
+ "unit": 1e-9 * mol / L,
+ },
+ {
+ "symbol": "µL/min/mg",
+ "unit": 1e-6 * L / (60 * h * 1e-3 * g),
+ },
+ {
+ "symbol": "h",
+ "unit": h,
+ },
+ {
+ "symbol": "1/h",
+ "unit": 1 / h,
+ },
+ {
+ "symbol": "mg",
+ "unit": 1e-3 * g,
+ },
+ {
+ "symbol": "day",
+ "unit": 24 * h,
+ },
+ {
+ "symbol": "1/day",
+ "unit": 1 / (24 * h),
+ },
+ {
+ "symbol": "week",
+ "unit": 7 * 24 * h,
+ },
+ {
+ "symbol": "1/week",
+ "unit": 1 / (7 * 24 * h),
+ },
+ {
+ "symbol": "min",
+ "unit": h / 60,
+ },
+ {
+ "symbol": "s",
+ "unit": h / 3600,
+ },
+ {
+ "symbol": "L/mg/day",
+ "unit": L / (1e-3 * g * 24 * h),
+ },
+ {
+ "symbol": "L/h/kg",
+ "unit": L / (h * 1e3 * g),
+ },
+ {
+ "symbol": "mL/h/kg",
+ "unit": 1e-3 * L / (h * 1e3 * g),
+ },
+ {
+ "symbol": "L/day/kg",
+ "unit": L / (24 * h * 1e3 * g),
+ },
+ {
+ "symbol": "mL/day/kg",
+ "unit": 1e-3 * L / (24 * h * 1e3 * g),
+ },
+ {
+ "symbol": "L/h/pmol",
+ "unit": L / (h * 1e-12 * mol),
+ },
+ {
+ "symbol": "L/day/pmol",
+ "unit": L / (24 * h * 1e-12 * mol),
+ },
+ {
+ "symbol": "mL/day/pmol",
+ "unit": 1e-3 * L / (24 * h * 1e-12 * mol),
+ },
+ {
+ "symbol": "L/h/nmol",
+ "unit": L / (h * 1e-9 * mol),
+ },
+ {
+ "symbol": "L/day/nmol",
+ "unit": L / (24 * h * 1e-9 * mol),
+ },
+ {
+ "symbol": "mL/day/nmol",
+ "unit": 1e-3 * L / (24 * h * 1e-9 * mol),
+ },
+ {
+ "symbol": "L/h/µmol",
+ "unit": L / (h * 1e-6 * mol),
+ },
+ {
+ "symbol": "L/day/µmol",
+ "unit": L / (24 * h * 1e-6 * mol),
+ },
+ {
+ "symbol": "mL/day/µmol",
+ "unit": 1e-3 * L / (24 * h * 1e-6 * mol),
+ },
+ {"symbol": "L", "unit": L},
+ {"symbol": "mL", "unit": 1e-3 * L},
+ {"symbol": "L/kg", "unit": L / (1e3 * g)},
+ {"symbol": "L/h", "unit": L / h},
+ {"symbol": "L/day", "unit": L / (24 * h)},
+ {"symbol": "mL/day", "unit": 1e-3 * L / (24 * h)},
+ {"symbol": "mL/h", "unit": 1e-3 * L / h},
+ {"symbol": "µL/h", "unit": 1e-6 * L / h},
+ {"symbol": "1/L", "unit": 1 / L},
+ {
+ "symbol": "kg",
+ "unit": 1e3 * g,
+ },
+ {
+ "symbol": "g",
+ "unit": g,
+ },
+ {
+ "symbol": "ng",
+ "unit": 1e-9 * g,
+ },
+ {
+ "symbol": "ng/mL",
+ "unit": 1e-9 * g / (1e-3 * L),
+ },
+ {
+ "symbol": "mg/L",
+ "unit": 1e-3 * g / L,
+ },
+ {
+ "symbol": "ng/L",
+ "unit": 1e-9 * g / L,
+ },
+ {
+ "symbol": "g/L",
+ "unit": g / L,
+ },
+ {
+ "symbol": "pg/mL",
+ "unit": 1e-12 * g / (1e-3 * L),
+ },
+ {
+ "symbol": "ng/mL",
+ "unit": 1e-9 * g / (1e-3 * L),
+ },
+ {
+ "symbol": "µg/mL",
+ "unit": 1e-6 * g / (1e-3 * L),
+ },
+ {
+ "symbol": "10^6/mcL",
+ "unit": 1e6 / (1e-3 * cL),
+ },
+ {
+ "symbol": "10^3/mcL",
+ "unit": 1e3 / (1e-3 * cL),
+ },
+ {
+ "symbol": "g/dL",
+ "unit": g / (10 * cL),
+ },
+ {
+ "symbol": "",
+ "unit": dimensionless,
+ },
+ {
+ "symbol": "g/mol",
+ "unit": g / mol,
+ },
+ {
+ "symbol": "g/nmol",
+ "unit": g / (1e-6 * mol),
+ },
+ {
+ "symbol": "h*pmol/L",
+ "unit": h * 1e-12 * mol / L,
+ },
+ {
+ "symbol": "h*nmol/L",
+ "unit": h * 1e-9 * mol / L,
+ },
+ {
+ "symbol": "h*µmol/L",
+ "unit": h * 1e-6 * mol / L,
+ },
+ {
+ "symbol": "h*ng/mL",
+ "unit": h * 1e-9 * g / (1e-3 * L),
+ },
+ {
+ "symbol": "h*µg/mL",
+ "unit": h * 1e-6 * g / (1e-3 * L),
+ },
+ {
+ "symbol": "day*pmol/L",
+ "unit": 24 * h * 1e-12 * mol / L,
+ },
+ {
+ "symbol": "day*nmol/L",
+ "unit": 24 * h * 1e-9 * mol / L,
+ },
+ {
+ "symbol": "day*µmol/L",
+ "unit": 24 * h * 1e-6 * mol / L,
+ },
+ {
+ "symbol": "day*ng/mL",
+ "unit": 24 * h * 1e-9 * g / (1e-3 * L),
+ },
+ {
+ "symbol": "day*µg/mL",
+ "unit": 24 * h * 1e-6 * g / (1e-3 * L),
+ },
+ {
+ "symbol": "mg/kg",
+ "unit": 1e-3 * g / (1e3 * g),
+ },
+ {
+ "symbol": "pg/kg",
+ "unit": 1e-12 * g / (1e3 * g),
+ },
+ {
+ "symbol": "ng/kg",
+ "unit": 1e-9 * g / (1e3 * g),
+ },
+ {
+ "symbol": "µg/kg",
+ "unit": 1e-6 * g / (1e3 * g),
+ },
+ {
+ "symbol": "pmol/kg",
+ "unit": 1e-12 * mol / (1e3 * g),
+ },
+ {
+ "symbol": "nmol/kg",
+ "unit": 1e-9 * mol / (1e3 * g),
+ },
+ {
+ "symbol": "µmol/kg",
+ "unit": 1e-6 * mol / (1e3 * g),
+ },
+ {
+ "symbol": "mL/kg",
+ "unit": 1e-3 * L / (1e3 * g),
+ },
+ {
+ "symbol": "L/kg",
+ "unit": L / (1e3 * g),
+ },
+ ]
+
+ for u in units:
+ try:
+ Unit.objects.get(symbol=u["symbol"])
+ except Unit.DoesNotExist:
+ Unit.objects.create(
+ symbol=u["symbol"],
+ g=u["unit"].exponents()[0],
+ m=u["unit"].exponents()[1],
+ s=u["unit"].exponents()[2],
+ A=u["unit"].exponents()[3],
+ K=u["unit"].exponents()[4],
+ cd=u["unit"].exponents()[5],
+ mol=u["unit"].exponents()[6],
+ multiplier=u["unit"].multiplier_log_10(),
+ )
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("pkpdapp", "0001_initial"),
+ ]
+
+ operations = [
+ migrations.RunPython(load_units),
+ ]
diff --git a/pkpdapp/pkpdapp/migrations/0008_initial_algorithms.py b/pkpdapp/pkpdapp/migrations/0008_initial_algorithms.py
new file mode 100644
index 00000000..50742858
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/0008_initial_algorithms.py
@@ -0,0 +1,73 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import migrations
+
+
+def load_algorithms(apps, schema_editor):
+ Algorithm = apps.get_model("pkpdapp", "Algorithm")
+
+ algorithms = [
+ {
+ 'name': 'Haario-Bardenet',
+ 'category': 'SA',
+ },
+ {
+ 'name': 'Differential evolution',
+ 'category': 'SA',
+ },
+ {
+ 'name': 'DREAM',
+ 'category': 'SA',
+ },
+ {
+ 'name': 'Population MCMC',
+ 'category': 'SA',
+ },
+ {
+ 'name': 'CMAES',
+ 'category': 'OP',
+ },
+ {
+ 'name': 'XNES',
+ 'category': 'OP',
+ },
+ {
+ 'name': 'SNES',
+ 'category': 'OP',
+ },
+ {
+ 'name': 'PSO',
+ 'category': 'OP',
+ },
+ {
+ 'name': 'Nelder-Mead',
+ 'category': 'OP',
+ },
+ {
+ 'name': 'Parameter Sweep',
+ 'category': 'OT',
+ },
+
+
+ ]
+
+ for algorithm in algorithms:
+ Algorithm.objects.create(
+ name=algorithm['name'],
+ category=algorithm['category'],
+ )
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('pkpdapp', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.RunPython(load_algorithms),
+ ]
diff --git a/pkpdapp/pkpdapp/migrations/__init__.py b/pkpdapp/pkpdapp/migrations/__init__.py
new file mode 100644
index 00000000..d0505307
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/__init__.py
@@ -0,0 +1,5 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
diff --git a/pkpdapp/pkpdapp/migrations/models/1cmpt_PK_Model_Clinical.mmt b/pkpdapp/pkpdapp/migrations/models/1cmpt_PK_Model_Clinical.mmt
new file mode 100644
index 00000000..3e252ba8
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/1cmpt_PK_Model_Clinical.mmt
@@ -0,0 +1,64 @@
+[[model]]
+name: 1-compartment PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1 = 0
+PKCompartment.AUC1 = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 0 in [h]
+ desc: Absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: First order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: Fraction absorbed/ bioavailability
+
+V1 = 1 in [L]
+ desc: Volume of the central compartment
+
+CL = 1 in [L/h]
+ desc: Linear clearance from central compartment
+
+CLmax = 0 in [L/h]
+ desc: Maximum nonlinear Michaelis-Menten clearance; CLmax = Vmax/Km
+
+Km = 1 in [pmol/L]
+ desc: Michaelis-Menten constant
+
+ke0 = 1 in [1/h]
+ desc: Equilibration rate constant effect compartment
+
+Kpu = 1 in [dimensionless]
+ desc: Unbound effect compartment to total plasma partitioning coefficient
+
+C1= A1/V1 in [pmol/L]
+ desc: Concentration of drug in the central compartment
+
+CL_t = CL+CLmax*(1/(1+(C1/Km))) in [L/h]
+ desc: Total clearance as a function of time
+
+dot(Aa) = -ka*Aa in [pmol]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1) = ka*Aa*F -CL*C1 -CLmax*(1/(1+(C1/Km)))*C1 in [pmol]
+ desc: Amount of drug in central compartment
+
+dot(Ce) = ke0*(C1*Kpu - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1) = C1 in [pmol/L*h]
+ desc: AUC of drug in the central compartment
+
+dot(AUCe) = Ce in [pmol/L*h]
+ desc: AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/1cmpt_PK_Model_Preclinical.mmt b/pkpdapp/pkpdapp/migrations/models/1cmpt_PK_Model_Preclinical.mmt
new file mode 100644
index 00000000..6a827872
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/1cmpt_PK_Model_Preclinical.mmt
@@ -0,0 +1,64 @@
+[[model]]
+name: 1-compartment PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1 = 0
+PKCompartment.AUC1 = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 0 in [h]
+ desc: Absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: First order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: Fraction absorbed/ bioavailability
+
+V1 = 1 in [L/kg]
+ desc: Volume of the central compartment
+
+CL = 1 in [L/h/kg]
+ desc: Linear clearance from central compartment
+
+CLmax = 0 in [L/h/kg]
+ desc: Maximum nonlinear Michaelis-Menten clearance; CLmax = Vmax/Km
+
+Km = 1 in [pmol/L]
+ desc: Michaelis-Menten constant
+
+ke0 = 1 in [1/h]
+ desc: Equilibration rate constant effect compartment
+
+Kpu = 1 in [dimensionless]
+ desc: Unbound effect compartment to total plasma partitioning coefficient
+
+C1= A1/V1 in [pmol/L]
+ desc: Concentration of drug in the central compartment
+
+CL_t = CL+CLmax*(1/(1+(C1/Km))) in [L/h/kg]
+ desc: Total clearance as a function of time
+
+dot(Aa) = -ka*Aa in [pmol/kg]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1) = ka*Aa*F -CL*C1 -CLmax*(1/(1+(C1/Km)))*C1 in [pmol/kg]
+ desc: Amount of drug in central compartment
+
+dot(Ce) = ke0*(C1*Kpu - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1) = C1 in [pmol/L*h]
+ desc: AUC of drug in the central compartment
+
+dot(AUCe) = Ce in [pmol/L*h]
+ desc: AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/2cmpt_PK_Model_Clinical.mmt b/pkpdapp/pkpdapp/migrations/models/2cmpt_PK_Model_Clinical.mmt
new file mode 100644
index 00000000..588b925e
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/2cmpt_PK_Model_Clinical.mmt
@@ -0,0 +1,77 @@
+[[model]]
+name: 2-compartment PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1 = 0
+PKCompartment.A2 = 0
+PKCompartment.AUC1 = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 0 in [h]
+ desc: Absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: First order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: Fraction absorbed/ bioavailability
+
+V1 = 1 in [L]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L]
+ desc: Volume of the first peripheral compartment
+
+CL = 1 in [L/h]
+ desc: Linear clearance from central compartment
+
+Q1 = 1 in [L/h]
+ desc: Intercompartmental clearance between central compartment and first peripheral compartment
+
+CLmax = 0 in [L/h]
+ desc: Maximum nonlinear Michaelis-Menten clearance; CLmax = Vmax/Km
+
+Km = 1 in [pmol/L]
+ desc: Michaelis-Menten constant
+
+ke0 = 1 in [1/h]
+ desc: Equilibration rate constant effect compartment
+
+Kpu = 1 in [dimensionless]
+ desc: Unbound effect compartment to total plasma partitioning coefficient
+
+C1= A1/V1 in [pmol/L]
+ desc: Concentration of drug in the central compartment
+
+C2= A2/V2 in [pmol/L]
+ desc: Concentration of drug in the 1st peripheral compartment
+
+CL_t = CL+CLmax*(1/(1+(C1/Km))) in [L/h]
+ desc: Total clearance as a function of time
+
+dot(Aa) = -ka*Aa in [pmol]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1) = ka*Aa*F - Q1*(C1 - C2) -CL*C1 -CLmax*(1/(1+(C1/Km)))*C1 in [pmol]
+ desc: Amount of drug in central compartment
+
+dot(A2) = Q1*(C1 - C2) in [pmol]
+ desc: Amount of drug in first peripheral compartment
+
+dot(Ce) = ke0*(C1*Kpu - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1) = C1 in [pmol/L*h]
+ desc: AUC of drug in the central compartment
+
+dot(AUCe) = Ce in [pmol/L*h]
+ desc: AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/2cmpt_PK_Model_Preclinical.mmt b/pkpdapp/pkpdapp/migrations/models/2cmpt_PK_Model_Preclinical.mmt
new file mode 100644
index 00000000..4768ff2d
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/2cmpt_PK_Model_Preclinical.mmt
@@ -0,0 +1,77 @@
+[[model]]
+name: 2-compartment PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1 = 0
+PKCompartment.A2 = 0
+PKCompartment.AUC1 = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 0 in [h]
+ desc: Absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: First order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: Fraction absorbed/ bioavailability
+
+V1 = 1 in [L/kg]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L/kg]
+ desc: Volume of the first peripheral compartment
+
+CL = 1 in [L/h/kg]
+ desc: Linear clearance from central compartment
+
+Q1 = 1 in [L/h/kg]
+ desc: Intercompartmental clearance between central compartment and first peripheral compartment
+
+CLmax = 0 in [L/h/kg]
+ desc: Maximum nonlinear Michaelis-Menten clearance; CLmax = Vmax/Km
+
+Km = 1 in [pmol/L]
+ desc: Michaelis-Menten constant
+
+ke0 = 1 in [1/h]
+ desc: Equilibration rate constant effect compartment
+
+Kpu = 1 in [dimensionless]
+ desc: Unbound effect compartment to total plasma partitioning coefficient
+
+C1= A1/V1 in [pmol/L]
+ desc: Concentration of drug in the central compartment
+
+C2= A2/V2 in [pmol/L]
+ desc: Concentration of drug in the 1st peripheral compartment
+
+CL_t = CL+CLmax*(1/(1+(C1/Km))) in [L/h/kg]
+ desc: Total clearance as a function of time
+
+dot(Aa) = -ka*Aa in [pmol/kg]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1) = ka*Aa*F - Q1*(C1 - C2) -CL*C1 -CLmax*(1/(1+(C1/Km)))*C1 in [pmol/kg]
+ desc: Amount of drug in central compartment
+
+dot(A2) = Q1*(C1 - C2) in [pmol/kg]
+ desc: Amount of drug in first peripheral compartment
+
+dot(Ce) = ke0*(C1*Kpu - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1) = C1 in [pmol/L*h]
+ desc: AUC of drug in the central compartment
+
+dot(AUCe) = Ce in [pmol/L*h]
+ desc: AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/3cmpt_PK_Model_Clinical.mmt b/pkpdapp/pkpdapp/migrations/models/3cmpt_PK_Model_Clinical.mmt
new file mode 100644
index 00000000..150b13b4
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/3cmpt_PK_Model_Clinical.mmt
@@ -0,0 +1,90 @@
+[[model]]
+name: 3-compartment PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1 = 0
+PKCompartment.A2 = 0
+PKCompartment.A3 = 0
+PKCompartment.AUC1 = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 0 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: Fraction absorbed/ bioavailability
+
+V1 = 1 in [L]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L]
+ desc: Volume of the first peripheral compartment
+
+V3 = 1 in [L]
+ desc: Volume of the second peripheral compartment
+
+CL = 1 in [L/h]
+ desc: Linear clearance from central compartment
+
+Q1 = 1 in [L/h]
+ desc: Intercompartmental clearance between central compartment and first peripheral compartment
+
+Q2 = 1 in [L/h]
+ desc: Intercompartmental clearance between central compartment and second peripheral compartment
+
+CLmax = 0 in [L/h]
+ desc: Maximum nonlinear Michaelis-Menten clearance; CLmax = Vmax/Km
+
+Km = 1 in [pmol/L]
+ desc: Michaelis-Menten constant
+
+ke0 = 1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kpu = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+C1= A1/V1 in [pmol/L]
+ desc: Concentration of drug in the central compartment
+
+C2= A2/V2 in [pmol/L]
+ desc: Concentration of drug in the 1st peripheral compartment
+
+C3= A3/V3 in [pmol/L]
+ desc: Concentration of drug in the 2nd peripheral compartment
+
+CL_t = CL+CLmax*(1/(1+(C1/Km))) in [L/h/kg]
+ desc: total clearance as function of time
+
+dot(Aa) = -ka*Aa in [pmol]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1) = ka*Aa*F -Q1*(C1 - C2) -Q2*(C1 - C3) -CL*C1 -CLmax*(1/(1+(C1/Km)))*C1 in [pmol]
+ desc: Amount of drug in central compartment
+
+dot(A2) = Q1*(C1 - C2) in [pmol]
+ desc: Amount of drug in first peripheral compartment
+
+dot(A3) = Q2*(C1 - C3) in [pmol]
+ desc: Amount of drug in second peripheral compartment
+
+dot(Ce) = ke0*(C1*Kpu - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1)= C1 in [pmol/L*h]
+ desc: AUC of the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: AUC of the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/3cmpt_PK_Model_Preclinical.mmt b/pkpdapp/pkpdapp/migrations/models/3cmpt_PK_Model_Preclinical.mmt
new file mode 100644
index 00000000..2f58ffcd
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/3cmpt_PK_Model_Preclinical.mmt
@@ -0,0 +1,90 @@
+[[model]]
+name: 3-compartment PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1 = 0
+PKCompartment.A2 = 0
+PKCompartment.A3 = 0
+PKCompartment.AUC1 = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 0 in [h]
+ desc: Absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: First order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: Fraction absorbed/ bioavailability
+
+V1 = 1 in [L/kg]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L/kg]
+ desc: Volume of the first peripheral compartment
+
+V3 = 1 in [L/kg]
+ desc: Volume of the second peripheral compartment
+
+CL = 1 in [L/h/kg]
+ desc: Linear clearance from central compartment
+
+Q1 = 1 in [L/h/kg]
+ desc: Intercompartmental clearance between central compartment and first peripheral compartment
+
+Q2 = 1 in [L/h/kg]
+ desc: Intercompartmental clearance between central compartment and second peripheral compartment
+
+CLmax = 0 in [L/h/kg]
+ desc: Maximum nonlinear Michaelis-Menten clearance; CLmax = Vmax/Km
+
+Km = 1 in [pmol/L]
+ desc: Michaelis-Menten constant
+
+ke0 = 1 in [1/h]
+ desc: Equilibration rate constant effect compartment
+
+Kpu = 1 in [dimensionless]
+ desc: Effect compartment to plasma partitioning coefficient
+
+C1= A1/V1 in [pmol/L]
+ desc: Concentration of drug in the central compartment
+
+C2= A2/V2 in [pmol/L]
+ desc: Concentration of drug in the 1st peripheral compartment
+
+C3= A3/V3 in [pmol/L]
+ desc: Concentration of drug in the 2nd peripheral compartment
+
+CL_t = CL+CLmax*(1/(1+(C1/Km))) in [L/h/kg]
+ desc: Total clearance as a function of time
+
+dot(Aa) = -ka*Aa in [pmol/kg]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1) = ka*Aa*F -Q1*(C1 - C2) -Q2*(C1 - C3) -CL*C1 -CLmax*(1/(1+(C1/Km)))*C1 in [pmol/kg]
+ desc: Amount of drug in central compartment
+
+dot(A2) = Q1*(C1 - C2) in [pmol/kg]
+ desc: Amount of drug in first peripheral compartment
+
+dot(A3) = Q2*(C1 - C3) in [pmol/kg]
+ desc: Amount of drug in second peripheral compartment
+
+dot(Ce) = ke0*(C1*Kpu - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1)= C1 in [pmol/L*h]
+ desc: AUC of drug in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/DE_Emax.mmt b/pkpdapp/pkpdapp/migrations/models/DE_Emax.mmt
new file mode 100644
index 00000000..1bdbed8a
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/DE_Emax.mmt
@@ -0,0 +1,32 @@
+[[model]]
+name: Stimulatory direct effects model (symmetrical Emax model)
+author: Michael Gertz
+
+# Initial values:
+
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PDCompartment]
+
+E0 = 100 in [dimensionless]
+ desc: baseline effect
+
+Emax = 5 in [dimensionless]
+ desc: maximal fold change from baseline (value range: 1 (no effect) to inf)
+
+C50 = 100000 in [pmol/L]
+ desc: concentration that produces half-maximal effects
+
+HC = 1 in [dimensionless]
+ desc: Hill coefficient
+
+C_Drug = 1 in [pmol/L]
+
+STIM = C_Drug^HC/(C_Drug^HC+C50^HC) in [dimensionless]
+
+E = if(E0 <= 0 ,
+ +Emax*STIM ,
+ E0 * (1+(Emax-1)*STIM)) in [dimensionless]
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/DE_Imax.mmt b/pkpdapp/pkpdapp/migrations/models/DE_Imax.mmt
new file mode 100644
index 00000000..24e32294
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/DE_Imax.mmt
@@ -0,0 +1,32 @@
+[[model]]
+name: Inhibitory direct effects model (symmetrical Imax model)
+author: Michael Gertz
+
+# Initial values:
+
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PDCompartment]
+
+E0 = 100 in [dimensionless]
+ desc: baseline effect
+
+Imax = 0.80 in [dimensionless]
+ desc: maximal fold change from baseline (value range: 0 (no effect) to 1 (complete inhibition))
+
+C50 = 100000 in [pmol/L]
+ desc: concentration that produces half-maximal effects
+
+HC = 1 in [dimensionless]
+ desc: Hill coefficient
+
+C_Drug = 1 in [pmol/L]
+
+INH = C_Drug^HC/(C_Drug^HC+C50^HC) in [dimensionless]
+
+E = if(E0 <= 0 ,
+ -Imax*INH ,
+ E0 * (1-Imax*INH)) in [dimensionless]
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/IE_InhibitionElimination_Imax.mmt b/pkpdapp/pkpdapp/migrations/models/IE_InhibitionElimination_Imax.mmt
new file mode 100644
index 00000000..375f1635
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/IE_InhibitionElimination_Imax.mmt
@@ -0,0 +1,36 @@
+[[model]]
+name: Indirect effects model - inhibition of elimination
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.E = PDCompartment.E0
+
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PDCompartment]
+
+kdeg = 0.05 in [1/h]
+ desc: degradation rate constant of the effect
+
+E0 = 100 in [dimensionless]
+ desc: baseline effect
+
+Imax = 0.80 in [dimensionless]
+ desc: maximal fold change from baseline (value range: 0 (no effect) to 1 (complete inhibition))
+
+C50 = 100000 in [pmol/L]
+ desc: concentration that produces half-maximal effects
+
+HC = 1 in [dimensionless]
+ desc: Hill coefficient
+
+C_Drug = 1 in [pmol/L]
+
+INH = C_Drug^HC/(C_Drug^HC+C50^HC) in [dimensionless]
+ desc: Inhibition
+
+dot(E) = kdeg*(E0-E*(1-Imax*INH)) in [dimensionless]
+ desc: PD effect
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/IE_InhibitionProduction_Imax.mmt b/pkpdapp/pkpdapp/migrations/models/IE_InhibitionProduction_Imax.mmt
new file mode 100644
index 00000000..a35227c4
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/IE_InhibitionProduction_Imax.mmt
@@ -0,0 +1,36 @@
+[[model]]
+name: Indirect effects model - inhibition of production
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.E = PDCompartment.E0
+
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PDCompartment]
+
+kdeg = 0.05 in [1/h]
+ desc: degradation rate constant of the effect
+
+E0 = 100 in [dimensionless]
+ desc: baseline effect
+
+Imax = 0.80 in [dimensionless]
+ desc: maximal fold change from baseline (value range: 0 (no effect) to 1 (complete inhibition))
+
+C50 = 100000 in [pmol/L]
+ desc: concentration that produces half-maximal effects
+
+HC = 1 in [dimensionless]
+ desc: Hill coefficient
+
+C_Drug = 1 in [pmol/L]
+
+INH = C_Drug^HC/(C_Drug^HC+C50^HC) in [dimensionless]
+ desc: Inhibition
+
+dot(E) = kdeg*(E0*(1-Imax*INH)-E) in [dimensionless]
+ desc: PD effect
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/IE_Precursor_InhibitionElimination_Emax.mmt b/pkpdapp/pkpdapp/migrations/models/IE_Precursor_InhibitionElimination_Emax.mmt
new file mode 100644
index 00000000..d387c0ec
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/IE_Precursor_InhibitionElimination_Emax.mmt
@@ -0,0 +1,50 @@
+[[model]]
+name: Indirect effects model with precursor (for rebound/ tolerance) - inhibition of precursor elimination
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.P = PDCompartment.E0*PDCompartment.kdeg/(PDCompartment.kdegP*PDCompartment.FE)
+PDCompartment.E = PDCompartment.E0
+
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PDCompartment]
+
+kdegP = 0.1 in [1/h]
+ desc: degradation rate constant of precursor
+
+FE = 1 in [dimensionless]
+ desc: fraction of precursor that is converted to effect
+
+kdeg = 2 in [1/h]
+ desc: degradation rate constant of the effect
+
+E0 = 100 in [dimensionless]
+ desc: baseline effect
+
+Imax = 0.80 in [dimensionless]
+ desc: maximal fold change from baseline (value range: 0 (no effect) to 1 (complete inhibition))
+
+C50 = 100000 in [pmol/L]
+ desc: concentration that produces half-maximal effects
+
+HC = 1 in [dimensionless]
+ desc: Hill coefficient
+
+C_Drug = 1 in [pmol/L]
+ desc: drug concentration driving the PD effect
+
+P0 = E0*kdeg/(kdegP*FE) in [dimensionless]
+ desc: baseline of precursor
+
+INH = C_Drug^HC/(C_Drug^HC+C50^HC) in [dimensionless]
+ desc: Inhibition
+
+dot(P) = kdegP*P0 - kdegP*P*(FE*(1-Imax*INH) + (1-FE)) in [dimensionless]
+ desc: Precursor
+
+dot(E) = kdegP*P*(FE*(1-Imax*INH)) -kdeg*E in [dimensionless]
+ desc: PD effect
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/IE_Precursor_StimulationElimination_Emax.mmt b/pkpdapp/pkpdapp/migrations/models/IE_Precursor_StimulationElimination_Emax.mmt
new file mode 100644
index 00000000..bcb5e056
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/IE_Precursor_StimulationElimination_Emax.mmt
@@ -0,0 +1,50 @@
+[[model]]
+name: Indirect effects model with precursor (for rebound/ tolerance) - stimulation of precursor elimination
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.P = PDCompartment.E0*PDCompartment.kdeg/(PDCompartment.kdegP*PDCompartment.FE)
+PDCompartment.E = PDCompartment.E0
+
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PDCompartment]
+
+kdegP = 0.1 in [1/h]
+ desc: degradation rate constant of precursor
+
+FE = 1 in [dimensionless]
+ desc: fraction of precursor that is converted to effect
+
+kdeg = 2 in [1/h]
+ desc: degradation rate constant of the effect
+
+E0 = 100 in [dimensionless]
+ desc: baseline effect
+
+Emax = 5 in [dimensionless]
+ desc: maximal fold change from baseline (value range: 1 (no effect) to infinity)
+
+C50 = 100000 in [pmol/L]
+ desc: concentration that produces half-maximal effects
+
+HC = 1 in [dimensionless]
+ desc: Hill coefficient
+
+C_Drug = 1 in [pmol/L]
+ desc: drug concentration driving the PD effect
+
+P0 = E0*kdeg/(kdegP*FE) in [dimensionless]
+ desc: baseline of precursor
+
+STIM = C_Drug^HC/(C_Drug^HC+C50^HC) in [dimensionless]
+ desc: Stimulation
+
+dot(P) = kdegP*P0 - kdegP*P*(FE*(1+(Emax-1)*STIM) + (1-FE)) in [dimensionless]
+ desc: Precursor
+
+dot(E) = kdegP*P*(FE*(1+(Emax-1)*STIM)) -kdeg*E in [dimensionless]
+ desc: PD effect
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/IE_StimulationElimination_Emax.mmt b/pkpdapp/pkpdapp/migrations/models/IE_StimulationElimination_Emax.mmt
new file mode 100644
index 00000000..2d79ab0c
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/IE_StimulationElimination_Emax.mmt
@@ -0,0 +1,36 @@
+[[model]]
+name: Indirect effects model - stimulation of elimination
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.E = PDCompartment.E0
+
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PDCompartment]
+
+kdeg = 0.05 in [1/h]
+ desc: degradation rate constant of the effect
+
+E0 = 100 in [dimensionless]
+ desc: baseline effect
+
+Emax = 5 in [dimensionless]
+ desc: maximal fold change from baseline (value range: 1 (no effect) to infinity)
+
+C50 = 100000 in [pmol/L]
+ desc: concentration that produces half-maximal effects
+
+HC = 1 in [dimensionless]
+ desc: Hill coefficient
+
+C_Drug = 1 in [pmol/L]
+
+STIM = C_Drug^HC/(C_Drug^HC+C50^HC) in [dimensionless]
+ desc: Stimulation
+
+dot(E) = kdeg*(E0-E*(1+(Emax-1)*STIM)) in [dimensionless]
+ desc: PD effect
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/IE_StimulationProduction_Emax.mmt b/pkpdapp/pkpdapp/migrations/models/IE_StimulationProduction_Emax.mmt
new file mode 100644
index 00000000..8df025ee
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/IE_StimulationProduction_Emax.mmt
@@ -0,0 +1,36 @@
+[[model]]
+name: Indirect effects model - stimulation of production
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.E = PDCompartment.E0
+
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PDCompartment]
+
+kdeg = 0.05 in [1/h]
+ desc: degradation rate constant of the effect
+
+E0 = 100 in [dimensionless]
+ desc: baseline effect
+
+Emax = 5 in [dimensionless]
+ desc: maximal fold change from baseline (value range: 1 (no effect) to infinity)
+
+C50 = 100000 in [pmol/L]
+ desc: concentration that produces half-maximal effects
+
+HC = 1 in [dimensionless]
+ desc: Hill coefficient
+
+C_Drug = 1 in [pmol/L]
+
+STIM = C_Drug^HC/(C_Drug^HC+C50^HC) in [dimensionless]
+ desc: Stimulation
+
+dot(E) = kdeg*(E0*(1+(Emax-1)*STIM)-E) in [dimensionless]
+ desc: PD effect
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/ParametersValue_Species.xlsx b/pkpdapp/pkpdapp/migrations/models/ParametersValue_Species.xlsx
new file mode 100644
index 00000000..3919d993
Binary files /dev/null and b/pkpdapp/pkpdapp/migrations/models/ParametersValue_Species.xlsx differ
diff --git a/pkpdapp/pkpdapp/migrations/models/TGI_Delay_CellDistribution_ConcPropKill_PDModel.mmt b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_CellDistribution_ConcPropKill_PDModel.mmt
new file mode 100644
index 00000000..2488603c
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_CellDistribution_ConcPropKill_PDModel.mmt
@@ -0,0 +1,46 @@
+[[model]]
+name: Tumor growth inhbition model: growth-independent, delayed response (Cell Distribution Model), proportional to concentration
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.TS = PDCompartment.TS0
+PDCompartment.TS1 = 0
+PDCompartment.TS2 = 0
+PDCompartment.TS3 = 0
+
+
+[environment]
+t = 0 bind time
+
+
+[PDCompartment]
+
+TS0 = 0.1 in [mL]
+ desc: initial tumor size
+
+kKill = 0.00000001 in [1/h*L/pmol]
+ desc: kill rate constant
+
+Mtt = 72 in [h]
+ desc: average life span
+
+tau = Mtt/3 in [h]
+
+C_Drug = 1 in [pmol/L]
+
+Kill = kKill * C_Drug in [1/h]
+
+dot(TS) = -Kill*TS in [mL]
+ desc: Tumor volume
+
+dot(TS1) = Kill*TS-TS1/tau in [mL]
+ desc: Transit compartment 1 (delay due to cell distribution > dying cells)
+
+dot(TS2) = (TS1-TS2)/tau in [mL]
+ desc: Transit compartment 2 (delay due to cell distribution > dying cells)
+
+dot(TS3) = (TS2-TS3)/tau in [mL]
+ desc: Transit compartment 3 (delay due to cell distribution > dying cells)
+
+TSTotal = TS1 + TS2 + TS3 + TS in [mL]
+ desc: Total tumor volume
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TGI_Delay_CellDistribution_EmaxKill_PDModel.mmt b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_CellDistribution_EmaxKill_PDModel.mmt
new file mode 100644
index 00000000..4aaa7396
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_CellDistribution_EmaxKill_PDModel.mmt
@@ -0,0 +1,52 @@
+[[model]]
+name: Tumor growth inhbition model: growth-independent, delayed response (Cell Distribution Model), Kmax model
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.TS = PDCompartment.TS0
+PDCompartment.TS1 = 0
+PDCompartment.TS2 = 0
+PDCompartment.TS3 = 0
+
+
+[environment]
+t = 0 bind time
+
+
+[PDCompartment]
+
+TS0 = 0.1 in [mL]
+ desc: initial tumor size
+
+kmax = 0.05 in [1/h]
+ desc: maximal kill rate constant
+
+C50 = 1000000 in [pmol/L]
+ desc: concentration of half-maximal effect
+
+HC = 1 in [dimensionless]
+ desc: Hill coefficient
+
+Mtt = 72 in [h]
+ desc: average life span
+
+tau = Mtt/3 in [h]
+
+C_Drug = 1 in [pmol/L]
+
+Kill = kmax * C_Drug^HC / (C50^HC + C_Drug^HC) in [1/h]
+
+dot(TS) = -Kill*TS in [mL]
+ desc: Tumor volume
+
+dot(TS1) = Kill*TS-TS1/tau in [mL]
+ desc: Transit compartment 1 (delay due to cell distribution)
+
+dot(TS2) = (TS1-TS2)/tau in [mL]
+ desc: Transit compartment 2 (delay due to cell distribution)
+
+dot(TS3) = (TS2-TS3)/tau in [mL]
+ desc: Transit compartment 3 (delay due to cell distribution)
+
+TSTotal = TS1 + TS2 + TS3 + TS in [mL]
+ desc: Total tumor volume
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TGI_Delay_CellDistribution_expConcPropKill_PDModel.mmt b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_CellDistribution_expConcPropKill_PDModel.mmt
new file mode 100644
index 00000000..5616eefa
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_CellDistribution_expConcPropKill_PDModel.mmt
@@ -0,0 +1,49 @@
+[[model]]
+name: Tumor growth inhbition model: growth-independent, delayed response (Cell Distribution Model), proportional to exp(concentration)
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.TS = PDCompartment.TS0
+PDCompartment.TS1 = 0
+PDCompartment.TS2 = 0
+PDCompartment.TS3 = 0
+
+
+[environment]
+t = 0 bind time
+
+
+[PDCompartment]
+
+TS0 = 0.1 in [mL]
+ desc: initial tumor size
+
+kmax = 0.015 in [1/h]
+ desc: maximal kill rate constant
+
+C50 = 1000000 in [pmol/L]
+ desc: concentration of half-maximal effect
+
+Mtt = 72 in [h]
+ desc: average life span
+
+tau = Mtt/3 in [h]
+
+C_Drug = 1 in [pmol/L]
+
+Kill = kmax * (1 - exp(-log(2)/C50 * C_Drug)) in [1/h]
+
+dot(TS) = -Kill*TS in [mL]
+ desc: Tumor volume
+
+dot(TS1) = Kill*TS-TS1/tau in [mL]
+ desc: Transit compartment 1 (delay due to cell distribution)
+
+dot(TS2) = (TS1-TS2)/tau in [mL]
+ desc: Transit compartment 2 (delay due to cell distribution)
+
+dot(TS3) = (TS2-TS3)/tau in [mL]
+ desc: Transit compartment 3 (delay due to cell distribution)
+
+TSTotal = TS1 + TS2 + TS3 + TS in [mL]
+ desc: Total tumor volume
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TGI_Delay_SignalDistribution_ConcPropKill_PDModel.mmt b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_SignalDistribution_ConcPropKill_PDModel.mmt
new file mode 100644
index 00000000..ac9ec4c0
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_SignalDistribution_ConcPropKill_PDModel.mmt
@@ -0,0 +1,43 @@
+[[model]]
+name: Tumor growth inhbition model: growth-independent, proportional to concentration
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.TS = PDCompartment.TS0
+PDCompartment.K1 = 0
+PDCompartment.K2 = 0
+PDCompartment.K3 = 0
+
+
+[environment]
+t = 0 bind time
+
+
+[PDCompartment]
+
+TS0 = 0.1 in [mL]
+ desc: initial tumor size
+
+kKill = 0.00000001 in [1/h*L/pmol]
+ desc: kill rate constant
+
+Mtt = 72 in [h]
+ desc: average life span
+
+tau = Mtt/3 in [h]
+
+C_Drug = 1 in [pmol/L]
+
+Kill = kKill * C_Drug in [1/h]
+
+dot(TS) = -K3*TS in [mL]
+ desc: Tumor volume
+
+dot(K1) = (Kill-K1)/tau in [1/h]
+ desc: Transit compartment 1 (delay due to signal transduction)
+
+dot(K2) = (K1-K2)/tau in [1/h]
+ desc: Transit compartment 2 (delay due to signal transduction)
+
+dot(K3) = (K2-K3)/tau in [1/h]
+ desc: Transit compartment 3 (delay due to signal transduction)
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TGI_Delay_SignalDistribution_EmaxKill_PDModel.mmt b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_SignalDistribution_EmaxKill_PDModel.mmt
new file mode 100644
index 00000000..8d96b898
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_SignalDistribution_EmaxKill_PDModel.mmt
@@ -0,0 +1,49 @@
+[[model]]
+name: Tumor growth inhbition model: growth-independent, delayed response (Signal Distribution Model), Kmax model
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.TS = PDCompartment.TS0
+PDCompartment.K1 = 0
+PDCompartment.K2 = 0
+PDCompartment.K3 = 0
+
+
+[environment]
+t = 0 bind time
+
+
+[PDCompartment]
+
+TS0 = 0.1 in [mL]
+ desc: initial tumor size
+
+kmax = 0.05 in [1/h]
+ desc: maximal kill rate constant
+
+C50 = 1000000 in [pmol/L]
+ desc: concentration of half-maximal effect
+
+HC = 1 in [dimensionless]
+ desc: Hill coefficient
+
+Mtt = 72 in [h]
+ desc: average duration of transduction
+
+tau = Mtt/3 in [h]
+
+C_Drug = 1 in [pmol/L]
+
+Kill = kmax * C_Drug^HC / (C50^HC + C_Drug^HC) in [1/h]
+
+dot(TS) = -K3*TS in [mL]
+ desc: Tumor volume
+
+dot(K1) = (Kill-K1)/tau in [1/h]
+ desc: Transit compartment 1 (delay due to signal distribution)
+
+dot(K2) = (K1-K2)/tau in [1/h]
+ desc: Transit compartment 2 (delay due to signal distribution)
+
+dot(K3) = (K2-K3)/tau in [1/h]
+ desc: Transit compartment 3 (delay due to signal distribution)
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TGI_Delay_SignalDistribution_expConcPropKill_PDModel.mmt b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_SignalDistribution_expConcPropKill_PDModel.mmt
new file mode 100644
index 00000000..a473902b
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TGI_Delay_SignalDistribution_expConcPropKill_PDModel.mmt
@@ -0,0 +1,46 @@
+[[model]]
+name: Tumor growth inhibition model: growth-independent, delayed response (Signal Distribution Model), proportional to exp(concentration)
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.TS = PDCompartment.TS0
+PDCompartment.K1 = 0
+PDCompartment.K2 = 0
+PDCompartment.K3 = 0
+
+
+[environment]
+t = 0 bind time
+
+
+[PDCompartment]
+
+TS0 = 0.1 in [mL]
+ desc: initial tumor size
+
+kmax = 0.015 in [1/h]
+ desc: maximal kill rate constant
+
+C50 = 1000000 in [pmol/L]
+ desc: concentration of half-maximal effect
+
+Mtt = 72 in [h]
+ desc: average duration of transduction
+
+tau = Mtt/3 in [h]
+
+C_Drug = 1 in [pmol/L]
+
+Kill = kmax * (1 - exp(-log(2)/C50 * C_Drug)) in [1/h]
+
+dot(TS) = -K3*TS in [mL]
+ desc: Tumor size
+
+dot(K1) = (Kill-K1)/tau in [1/h]
+ desc: Transit compartment 1 (delay due to signal distribution)
+
+dot(K2) = (K1-K2)/tau in [1/h]
+ desc: Transit compartment 2 (delay due to signal distribution)
+
+dot(K3) = (K2-K3)/tau in [1/h]
+ desc: Transit compartment 3 (delay due to signal distribution)
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TG_Gompertz_PDModel.mmt b/pkpdapp/pkpdapp/migrations/models/TG_Gompertz_PDModel.mmt
new file mode 100644
index 00000000..85a76d81
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TG_Gompertz_PDModel.mmt
@@ -0,0 +1,29 @@
+[[model]]
+name: Tumor growth model - exponential/ linear w/ saturation (Gompertz-logistic)
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.TS = PDCompartment.TS0
+
+
+[environment]
+t = 0 bind time
+
+
+[PDCompartment]
+
+TS0 = 0.1 in [mL]
+ desc: initial tumor size
+
+TSmax = 10 in [mL]
+ desc: maximal tumor size
+
+beta = 0.002 in [1/h]
+ desc: growth rate constant
+
+Growth = if(TS > 1e12,
+ 0,
+ TS*beta*log(TSmax/TS))
+
+dot(TS) = Growth in [mL]
+ desc: Tumor size
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TG_Simeoni_PDModel.mmt b/pkpdapp/pkpdapp/migrations/models/TG_Simeoni_PDModel.mmt
new file mode 100644
index 00000000..184e5fdc
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TG_Simeoni_PDModel.mmt
@@ -0,0 +1,32 @@
+[[model]]
+name: Tumor growth model - exponential/ linear w/o saturation (Simeoni)
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.TS = PDCompartment.TS0
+
+
+[environment]
+t = 0 bind time
+
+
+[PDCompartment]
+
+TS0 = 0.1 in [mL]
+ desc: initial tumor size
+
+kgl = 0.01 in [mL/h]
+ desc: growth rate constant linear
+
+kge = 0.005 in [1/h]
+ desc: growth rate constant exponential
+
+psi = 20 [dimensionless]
+ desc: set to a value of 20 for a rapid switch between exponential and linear phase
+
+Growth = if(TS > 1e12,
+ 0,
+ kge*TS/((1+(kge/kgl*TS)^psi)^(1/psi)))
+
+dot(TS) = Growth in [mL]
+ desc: Tumor size
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TG_Simeoni_logistic_PDModel.mmt b/pkpdapp/pkpdapp/migrations/models/TG_Simeoni_logistic_PDModel.mmt
new file mode 100644
index 00000000..188b212d
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TG_Simeoni_logistic_PDModel.mmt
@@ -0,0 +1,35 @@
+[[model]]
+name: Tumor growth model - exponential/ linear w/ saturation (Simeoni-logistic)
+author: Michael Gertz
+
+# Initial values:
+PDCompartment.TS = PDCompartment.TS0
+
+
+[environment]
+t = 0 bind time
+
+
+[PDCompartment]
+
+TS0 = 0.10 in [mL]
+ desc: initial tumor size
+
+TSmax = 10 in [mL]
+ desc: maximal tumor size
+
+kgl = 0.01 in [mL/h]
+ desc: growth rate constant linear
+
+kge = 0.005 in [1/h]
+ desc: growth rate constant exponential
+
+psi = 20 in [dimensionless]
+ desc: set to a value of 20 for a rapid switch between exponential and linear phase
+
+Growth = if(TS > 1e12,
+ 0,
+ kge*TS*(1-TS/TSmax)/((1+(kge/kgl*TS)^psi)^(1/psi)))
+
+dot(TS) = Growth in [mL]
+ desc: Tumor size
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_Full_1cmpt_PK_Model_Clinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_1cmpt_PK_Model_Clinical.mmt
new file mode 100644
index 00000000..1e83bcda
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_1cmpt_PK_Model_Clinical.mmt
@@ -0,0 +1,126 @@
+[[model]]
+name: 1-compartment Full TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_f = 0
+PKCompartment.AT1_f = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.ADT1 = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L]
+ desc: Volume of the central compartment
+
+CL = 1 in [L/h]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 100 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KD = 1000 in [pmol/L]
+ desc: Dissociation constant
+
+koff = 1 in [1/h]
+ desc: dissociation rate constant
+
+kdeg = 0.05 in [1/h]
+ desc: target degradation rate constant
+
+kint = 0.05 in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 0.10 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kon = koff/KD in [1/h*L/pmol]
+ desc: secondary parameter associate rate constant (2nd order)
+
+C1_f = A1_f/V1 in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C1_b = ADT1/V1 in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+C1_t = (A1_f + ADT1)/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+CT1_f = AT1_f/V1 in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+CT1_b = ADT1/V1 in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_t = (AT1_f + ADT1)/V1 in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy unit %
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+
+dot(Aa) = -ka*Aa in [pmol]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_f) = ka*Aa*F -CL*C1_f -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol]
+ desc: Amount of free drug in central compartment
+
+dot(AT1_f) = kdeg*V1*(CT1_0 - CT1_f) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol]
+ desc: Amount of free target in central compartment
+
+dot(ADT1) = kon*C1_f*CT1_f*V1 -(koff+kint)*ADT1 in [pmol]
+ desc: Amount of bound drug/ target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment unit
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_Full_1cmpt_PK_Model_Preclinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_1cmpt_PK_Model_Preclinical.mmt
new file mode 100644
index 00000000..fedc9cc4
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_1cmpt_PK_Model_Preclinical.mmt
@@ -0,0 +1,126 @@
+[[model]]
+name: 1-compartment Full TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_f = 0
+PKCompartment.AT1_f = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.ADT1 = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 0 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L/kg]
+ desc: Volume of the central compartment
+
+CL = 1 in [L/h/kg]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 100 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KD = 1000 in [pmol/L]
+ desc: Dissociation constant
+
+koff = 1 in [1/h]
+ desc: dissociation rate constant
+
+kdeg = 0.05 in [1/h]
+ desc: target degradation rate constant
+
+kint = 0.05 in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 0.10 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kon = koff/KD in [1/h*L/pmol]
+ desc: secondary parameter associate rate constant (2nd order)
+
+C1_f = A1_f/V1 in [pmol/L]
+ desc: Concentration of FREE drug in the central compartment
+
+C1_b = ADT1/V1 in [pmol/L]
+ desc: Concentration of BOUND drug in the central compartment
+
+C1_t = (A1_f + ADT1)/V1 in [pmol/L]
+ desc: Concentration of TOTAL drug in the central compartment
+
+CT1_f = AT1_f/V1 in [pmol/L]
+ desc: Concentration of FREE target in the central compartment
+
+CT1_b = ADT1/V1 in [pmol/L]
+ desc: Concentration of BOUND target in the central compartment
+
+CT1_t = (AT1_f + ADT1)/V1 in [pmol/L]
+ desc: Concentration of TOTAL target in the central compartment
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to TOTAL target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state concentrations of target
+
+
+dot(Aa) = -ka*Aa in [pmol/kg]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_f) = ka*Aa*F -CL*C1_f -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol/kg]
+ desc: Amount of FREE drug in central compartment
+
+dot(AT1_f) = kdeg*V1*(CT1_0 - CT1_f) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol/kg]
+ desc: Amount of FREE target in central compartment
+
+dot(ADT1) = kon*C1_f*CT1_f*V1 -(koff+kint)*ADT1 in [pmol/kg]
+ desc: Amount of BOUND drug/ target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of FREE drug in effect compartment unit
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: AUC of FREE drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: AUC of BOUND drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: AUC of TOTAL drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: AUC of FREE target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: AUC of BOUND target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: AUC of TOTAL target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: AUC of FREE drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_Full_2cmpt_PK_Model_Clinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_2cmpt_PK_Model_Clinical.mmt
new file mode 100644
index 00000000..7ed1b137
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_2cmpt_PK_Model_Clinical.mmt
@@ -0,0 +1,139 @@
+[[model]]
+name: 2-compartment Full TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_f = 0
+PKCompartment.A2 = 0
+PKCompartment.AT1_f = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.ADT1 = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L]
+ desc: Volume of the peripheral compartment
+
+Q1 = 1 in [L/h]
+ desc: intercompartmental clearance between central and peripheral compartment
+
+CL = 1 in [L/h]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 1 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KD = 1 in [pmol/L]
+ desc: Dissociation constant
+
+koff = 1 in [1/h]
+ desc: dissociation rate constant
+
+kdeg = 1 in [1/h]
+ desc: target degradation rate constant
+
+kint = 1 in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kon = koff/KD in [1/h*L/pmol]
+ desc: secondary parameter associate rate constant (2nd order)
+
+C1_f = A1_f/V1 in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C1_b = ADT1/V1 in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+C1_t = (A1_f + ADT1)/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+C2 = A2/V2 in [pmol/L]
+ desc: free concentration of drug in the peripheral compartment
+
+CT1_f = AT1_f/V1 in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+CT1_b = ADT1/V1 in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_t = (AT1_f + ADT1)/V1 in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+
+dot(Aa) = -ka*Aa in [pmol]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_f) = ka*Aa*F -CL*C1_f -Q1*(C1_f - C2) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol]
+ desc: Amount of free drug in central compartment
+
+dot(A2) = Q1*(C1_f - C2) in [pmol]
+ desc: Amount of free drug in the peripheral compartment
+
+dot(AT1_f) = kdeg*V1*(CT1_0 - CT1_f) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol]
+ desc: Amount of free target in central compartment
+
+dot(ADT1) = kon*C1_f*CT1_f*V1 -(koff+kint)*ADT1 in [pmol]
+ desc: Amount of bound drug/ target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_Full_2cmpt_PK_Model_Preclinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_2cmpt_PK_Model_Preclinical.mmt
new file mode 100644
index 00000000..eb8fc75f
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_2cmpt_PK_Model_Preclinical.mmt
@@ -0,0 +1,139 @@
+[[model]]
+name: 2-compartment Full TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_f = 0
+PKCompartment.A2 = 0
+PKCompartment.AT1_f = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.ADT1 = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L/kg]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L/kg]
+ desc: Volume of the peripheral compartment
+
+Q1 = 1 in [L/h/kg]
+ desc: intercompartmental clearance between central and peripheral compartment
+
+CL = 1 in [L/h/kg]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 1 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KD = 1 in [pmol/L]
+ desc: Dissociation constant
+
+koff = 1 in [1/h]
+ desc: dissociation rate constant
+
+kdeg = 1 in [1/h]
+ desc: target degradation rate constant
+
+kint = 1 in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kon = koff/KD in [1/h*L/pmol]
+ desc: secondary parameter associate rate constant (2nd order)
+
+C1_f = A1_f/V1 in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C1_b = ADT1/V1 in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+C1_t = (A1_f + ADT1)/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+C2 = A2/V2 in [pmol/L]
+ desc: free concentration of drug in the peripheral compartment
+
+CT1_f = AT1_f/V1 in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+CT1_b = ADT1/V1 in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_t = (AT1_f + ADT1)/V1 in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+
+dot(Aa) = -ka*Aa in [pmol/kg]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_f) = ka*Aa*F -CL*C1_f -Q1*(C1_f - C2) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol/kg]
+ desc: Amount of free drug in central compartment
+
+dot(A2) = Q1*(C1_f - C2) in [pmol/kg]
+ desc: Amount of free drug in the peripheral compartment
+
+dot(AT1_f) = kdeg*V1*(CT1_0 - CT1_f) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol/kg]
+ desc: Amount of free target in central compartment
+
+dot(ADT1) = kon*C1_f*CT1_f*V1 -(koff+kint)*ADT1 in [pmol/kg]
+ desc: Amount of bound drug/ target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_1cmpt_PK_Model_Clinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_1cmpt_PK_Model_Clinical.mmt
new file mode 100644
index 00000000..c67c17ee
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_1cmpt_PK_Model_Clinical.mmt
@@ -0,0 +1,126 @@
+[[model]]
+name: 1-compartment Full TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_f = 0
+PKCompartment.AT1_f = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.ADT1 = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 0 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L]
+ desc: Volume of the central compartment
+
+CL = 1 in [L/h]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 100 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KD = 1000 in [pmol/L]
+ desc: Dissociation constant
+
+koff = 1 in [1/h]
+ desc: dissociation rate constant
+
+kdeg = 0.05 in [1/h]
+ desc: target degradation rate constant
+
+kint = kdeg in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 0.10 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kon = koff/KD in [1/h*L/pmol]
+ desc: secondary parameter associate rate constant (2nd order)
+
+C1_f = A1_f/V1 in [pmol/L]
+ desc: Concentration of FREE drug in the central compartment
+
+C1_b = ADT1/V1 in [pmol/L]
+ desc: Concentration of BOUND drug in the central compartment
+
+C1_t = (A1_f + ADT1)/V1 in [pmol/L]
+ desc: Concentration of TOTAL drug in the central compartment
+
+CT1_f = AT1_f/V1 in [pmol/L]
+ desc: Concentration of FREE target in the central compartment
+
+CT1_b = ADT1/V1 in [pmol/L]
+ desc: Concentration of BOUND target in the central compartment
+
+CT1_t = (AT1_f + ADT1)/V1 in [pmol/L]
+ desc: Concentration of TOTAL target in the central compartment
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to TOTAL target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state concentrations of target
+
+
+dot(Aa) = -ka*Aa in [pmol]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_f) = ka*Aa*F -CL*C1_f -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol]
+ desc: Amount of FREE drug in central compartment
+
+dot(AT1_f) = kdeg*V1*(CT1_0 - CT1_f) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol]
+ desc: Amount of FREE target in central compartment
+
+dot(ADT1) = kon*C1_f*CT1_f*V1 -(koff+kint)*ADT1 in [pmol]
+ desc: Amount of BOUND drug/ target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of FREE drug in effect compartment unit
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: AUC of FREE drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: AUC of BOUND drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: AUC of TOTAL drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: AUC of FREE target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: AUC of BOUND target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: AUC of TOTAL target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: AUC of FREE drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_1cmpt_PK_Model_Preclinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_1cmpt_PK_Model_Preclinical.mmt
new file mode 100644
index 00000000..204b5a72
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_1cmpt_PK_Model_Preclinical.mmt
@@ -0,0 +1,126 @@
+[[model]]
+name: 1-compartment Full TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_f = 0
+PKCompartment.AT1_f = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.ADT1 = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 0 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L/kg]
+ desc: Volume of the central compartment
+
+CL = 1 in [L/h/kg]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 100 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KD = 1000 in [pmol/L]
+ desc: Dissociation constant
+
+koff = 1 in [1/h]
+ desc: dissociation rate constant
+
+kdeg = 0.05 in [1/h]
+ desc: target degradation rate constant
+
+kint = kdeg in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 0.10 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kon = koff/KD in [1/h*L/pmol]
+ desc: secondary parameter associate rate constant (2nd order)
+
+C1_f = A1_f/V1 in [pmol/L]
+ desc: Concentration of FREE drug in the central compartment
+
+C1_b = ADT1/V1 in [pmol/L]
+ desc: Concentration of BOUND drug in the central compartment
+
+C1_t = (A1_f + ADT1)/V1 in [pmol/L]
+ desc: Concentration of TOTAL drug in the central compartment
+
+CT1_f = AT1_f/V1 in [pmol/L]
+ desc: Concentration of FREE target in the central compartment
+
+CT1_b = ADT1/V1 in [pmol/L]
+ desc: Concentration of BOUND target in the central compartment
+
+CT1_t = (AT1_f + ADT1)/V1 in [pmol/L]
+ desc: Concentration of TOTAL target in the central compartment
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to TOTAL target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state concentrations of target
+
+
+dot(Aa) = -ka*Aa in [pmol/kg]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_f) = ka*Aa*F -CL*C1_f -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol/kg]
+ desc: Amount of FREE drug in central compartment
+
+dot(AT1_f) = kdeg*V1*(CT1_0 - CT1_f) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol/kg]
+ desc: Amount of FREE target in central compartment
+
+dot(ADT1) = kon*C1_f*CT1_f*V1 -(koff+kint)*ADT1 in [pmol/kg]
+ desc: Amount of BOUND drug/ target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of FREE drug in effect compartment unit
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: AUC of FREE drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: AUC of BOUND drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: AUC of TOTAL drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: AUC of FREE target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: AUC of BOUND target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: AUC of TOTAL target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: AUC of FREE drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_2cmpt_PK_Model_clinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_2cmpt_PK_Model_clinical.mmt
new file mode 100644
index 00000000..0610333d
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_2cmpt_PK_Model_clinical.mmt
@@ -0,0 +1,139 @@
+[[model]]
+name: 2-compartment Full TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_f = 0
+PKCompartment.A2 = 0
+PKCompartment.AT1_f = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.ADT1 = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L]
+ desc: Volume of the peripheral compartment
+
+Q1 = 1 in [L/h]
+ desc: intercompartmental clearance between central and peripheral compartment
+
+CL = 1 in [L/h]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 1 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KD = 1 in [pmol/L]
+ desc: Dissociation constant
+
+koff = 1 in [1/h]
+ desc: dissociation rate constant
+
+kdeg = 1 in [1/h]
+ desc: target degradation rate constant
+
+kint = kdeg in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kon = koff/KD in [1/h*L/pmol]
+ desc: secondary parameter associate rate constant (2nd order)
+
+C1_f = A1_f/V1 in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C1_b = ADT1/V1 in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+C1_t = (A1_f + ADT1)/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+C2 = A2/V2 in [pmol/L]
+ desc: free concentration of drug in the peripheral compartment
+
+CT1_f = AT1_f/V1 in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+CT1_b = ADT1/V1 in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_t = (AT1_f + ADT1)/V1 in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+
+dot(Aa) = -ka*Aa in [pmol]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_f) = ka*Aa*F -CL*C1_f -Q1*(C1_f - C2) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol]
+ desc: Amount of free drug in central compartment
+
+dot(A2) = Q1*(C1_f - C2) in [pmol]
+ desc: Amount of free drug in the peripheral compartment
+
+dot(AT1_f) = kdeg*V1*(CT1_0 - CT1_f) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol]
+ desc: Amount of free target in central compartment
+
+dot(ADT1) = kon*C1_f*CT1_f*V1 -(koff+kint)*ADT1 in [pmol]
+ desc: Amount of bound drug/ target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_2cmpt_PK_Model_preclinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_2cmpt_PK_Model_preclinical.mmt
new file mode 100644
index 00000000..f7e0da78
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_Full_ConstTarget_2cmpt_PK_Model_preclinical.mmt
@@ -0,0 +1,139 @@
+[[model]]
+name: 2-compartment Full TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_f = 0
+PKCompartment.A2 = 0
+PKCompartment.AT1_f = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.ADT1 = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L/kg]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L/kg]
+ desc: Volume of the peripheral compartment
+
+Q1 = 1 in [L/h/kg]
+ desc: intercompartmental clearance between central and peripheral compartment
+
+CL = 1 in [L/h/kg]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 1 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KD = 1 in [pmol/L]
+ desc: Dissociation constant
+
+koff = 1 in [1/h]
+ desc: dissociation rate constant
+
+kdeg = 1 in [1/h]
+ desc: target degradation rate constant
+
+kint = kdeg in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kon = koff/KD in [1/h*L/pmol]
+ desc: secondary parameter associate rate constant (2nd order)
+
+C1_f = A1_f/V1 in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C1_b = ADT1/V1 in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+C1_t = (A1_f + ADT1)/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+C2 = A2/V2 in [pmol/L]
+ desc: free concentration of drug in the peripheral compartment
+
+CT1_f = AT1_f/V1 in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+CT1_b = ADT1/V1 in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_t = (AT1_f + ADT1)/V1 in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+
+dot(Aa) = -ka*Aa in [pmol/kg]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_f) = ka*Aa*F -CL*C1_f -Q1*(C1_f - C2) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol/kg]
+ desc: Amount of free drug in central compartment
+
+dot(A2) = Q1*(C1_f - C2) in [pmol/kg]
+ desc: Amount of free drug in the peripheral compartment
+
+dot(AT1_f) = kdeg*V1*(CT1_0 - CT1_f) -kon*C1_f*CT1_f*V1 +koff*ADT1 in [pmol/kg]
+ desc: Amount of free target in central compartment
+
+dot(ADT1) = kon*C1_f*CT1_f*V1 -(koff+kint)*ADT1 in [pmol/kg]
+ desc: Amount of bound drug/ target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_1cmpt_PK_Model_Clinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_1cmpt_PK_Model_Clinical.mmt
new file mode 100644
index 00000000..3b59e7cd
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_1cmpt_PK_Model_Clinical.mmt
@@ -0,0 +1,123 @@
+[[model]]
+name: 1-compartment QSS TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_t = 0
+PKCompartment.AT1_t = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment (implementation tbd)
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L]
+ desc: Volume of the central compartment
+
+CL = 1 in [L/h]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 100 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KSS = 1000 in [pmol/L]
+ desc: Apparent dissociation constant [KSS = (kint+koff)/kon], if kint << koff KSS ~= KD and if kint >> koff KSS > KD
+
+kdeg = 0.05 in [1/h]
+ desc: target degradation rate constant
+
+kint = 0.05 in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 0.1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+
+b_term = C1_t - KSS - CT1_t in [pmol/L]
+ desc: b term of quadratic equation
+
+c_term = C1_t * KSS in [pmol/L*pmol/L]
+ desc: c term of quadratic equation
+
+C1_t = A1_t/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+CT1_t = AT1_t/V1 in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+C1_f = 0.5 * (b_term + (b_term^2+4*c_term)^0.5) in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C1_b = C1_t-C1_f in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+CT1_b = C1_b in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_f = CT1_t-CT1_b in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+dot(Aa) = -ka*Aa in [pmol]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_t) = ka*Aa*F -CL*C1_f -kint*CT1_b*V1 in [pmol]
+ desc: Amount of free drug in central compartment
+
+dot(AT1_t) = kdeg*V1*(CT1_0 - CT1_f) -kint*CT1_b*V1 in [pmol]
+ desc: Amount of free target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_1cmpt_PK_Model_Preclinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_1cmpt_PK_Model_Preclinical.mmt
new file mode 100644
index 00000000..5b6dd026
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_1cmpt_PK_Model_Preclinical.mmt
@@ -0,0 +1,123 @@
+[[model]]
+name: 1-compartment QSS TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_t = 0
+PKCompartment.AT1_t = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment (implementation tbd)
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L/kg]
+ desc: Volume of the central compartment
+
+CL = 1 in [L/h/kg]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 100 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KSS = 1000 in [pmol/L]
+ desc: Apparent dissociation constant [KSS = (kint+koff)/kon], if kint << koff KSS ~= KD and if kint >> koff KSS > KD
+
+kdeg = 0.05 in [1/h]
+ desc: target degradation rate constant
+
+kint = 0.05 in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 0.1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+
+b_term = C1_t - KSS - CT1_t in [pmol/L]
+ desc: b term of quadratic equation
+
+c_term = C1_t * KSS in [pmol/L*pmol/L]
+ desc: c term of quadratic equation
+
+C1_t = A1_t/V1 in [pmol/L]
+ desc: Concentration of TOTAL drug in the central compartment
+
+CT1_t = AT1_t/V1 in [pmol/L]
+ desc: Concentration of TOTAL target in the central compartment
+
+C1_f = 0.5 * (b_term + (b_term^2+4*c_term)^0.5) in [pmol/L]
+ desc: Concentration of FREE drug in the central compartment
+
+C1_b = C1_t-C1_f in [pmol/L]
+ desc: Concentration of BOUND drug in the central compartment
+
+CT1_b = C1_b in [pmol/L]
+ desc: Concentration of BOUND target in the central compartment
+
+CT1_f = CT1_t-CT1_b in [pmol/L]
+ desc: Concentration of FREE target in the central compartment
+
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy from TMDD model
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to TOTAL target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state concentrations of target
+
+dot(Aa) = -ka*Aa in [pmol/kg]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_t) = ka*Aa*F -CL*C1_f -kint*CT1_b*V1 in [pmol/kg]
+ desc: Amount of TOTAL drug in central compartment
+
+dot(AT1_t) = kdeg*V1*(CT1_0 - CT1_f) -kint*CT1_b*V1 in [pmol/kg]
+ desc: Amount of TOTAL target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of FREE drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: AUC of FREE drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: AUC of BOUND drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: AUC of TOTAL drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: AUC of FREE target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: AUC of BOUND target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: AUC of TOTAL target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: AUC of FREE drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_2cmpt_PK_Model_Clinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_2cmpt_PK_Model_Clinical.mmt
new file mode 100644
index 00000000..e61e8db1
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_2cmpt_PK_Model_Clinical.mmt
@@ -0,0 +1,136 @@
+[[model]]
+name: 2-compartment QSS TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_t = 0
+PKCompartment.A2 = 0
+PKCompartment.AT1_t = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L]
+ desc: Volume of the peripheral compartment
+
+Q1 = 1 in [L/h]
+ desc: intercompartmental clearance between central and peripheral compartment
+
+CL = 1 in [L/h]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 1 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KSS = 1 in [pmol/L]
+ desc: Apparent dissociation constant [KSS = (kint+koff)/kon], if kint << koff KSS ~= KD and if kint >> koff KSS > KD
+
+kdeg = 1 in [1/h]
+ desc: target degradation rate constant
+
+kint = 1 in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+
+b_term = C1_t - KSS - CT1_t in [pmol/L]
+ desc: b term of quadratic equation
+
+c_term = C1_t * KSS in [pmol/L*pmol/L]
+ desc: c term of quadratic equation
+
+C1_t = A1_t/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+CT1_t = AT1_t/V1 in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+C1_f = 0.5 * (b_term + (b_term^2+4*c_term)^0.5) in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C2 = A2/V2 in [pmol/L]
+ desc: free concentration of drug in the peripheral compartment
+
+C1_b = C1_t-C1_f in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+CT1_b = C1_b in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_f = CT1_t-CT1_b in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+dot(Aa) = -ka*Aa in [pmol]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_t) = ka*Aa*F -CL*C1_f -Q1*(C1_f - C2) -kint*CT1_b*V1 in [pmol]
+ desc: Amount of free drug in central compartment
+
+dot(A2) = Q1*(C1_f - C2) in [pmol]
+ desc: Amount of free drug in the peripheral compartment
+
+dot(AT1_t) = kdeg*V1*(CT1_0 - CT1_f) -kint*CT1_b*V1 in [pmol]
+ desc: Amount of free target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_2cmpt_PK_Model_Preclinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_2cmpt_PK_Model_Preclinical.mmt
new file mode 100644
index 00000000..ccab14ad
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_2cmpt_PK_Model_Preclinical.mmt
@@ -0,0 +1,136 @@
+[[model]]
+name: 2-compartment QSS TMDD PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_t = 0
+PKCompartment.A2 = 0
+PKCompartment.AT1_t = PKCompartment.CT1_0*PKCompartment.V1
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L/kg]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L/kg]
+ desc: Volume of the peripheral compartment
+
+Q1 = 1 in [L/h/kg]
+ desc: intercompartmental clearance between central and peripheral compartment
+
+CL = 1 in [L/h/kg]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 1 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KSS = 1 in [pmol/L]
+ desc: Apparent dissociation constant [KSS = (kint+koff)/kon], if kint << koff KSS ~= KD and if kint >> koff KSS > KD
+
+kdeg = 1 in [1/h]
+ desc: target degradation rate constant
+
+kint = 1 in [1/h]
+ desc: complex internalization rate constant
+
+ke0 = 1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+
+b_term = C1_t - KSS - CT1_t in [pmol/L]
+ desc: b term of quadratic equation
+
+c_term = C1_t * KSS in [pmol/L*pmol/L]
+ desc: c term of quadratic equation
+
+C1_t = A1_t/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+CT1_t = AT1_t/V1 in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+C1_f = 0.5 * (b_term + (b_term^2+4*c_term)^0.5) in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C2 = A2/V2 in [pmol/L]
+ desc: free concentration of drug in the peripheral compartment
+
+C1_b = C1_t-C1_f in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+CT1_b = C1_b in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_f = CT1_t-CT1_b in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+dot(Aa) = -ka*Aa in [pmol/kg]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_t) = ka*Aa*F -CL*C1_f -Q1*(C1_f - C2) -kint*CT1_b*V1 in [pmol/kg]
+ desc: Amount of free drug in central compartment
+
+dot(A2) = Q1*(C1_f - C2) in [pmol/kg]
+ desc: Amount of free drug in the peripheral compartment
+
+dot(AT1_t) = kdeg*V1*(CT1_0 - CT1_f) -kint*CT1_b*V1 in [pmol/kg]
+ desc: Amount of free target in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_1cmpt_PK_Model_Clinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_1cmpt_PK_Model_Clinical.mmt
new file mode 100644
index 00000000..b064b492
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_1cmpt_PK_Model_Clinical.mmt
@@ -0,0 +1,118 @@
+[[model]]
+name: 1-compartment QSS Constant Target Concentration (Wagner) PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_t = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L]
+ desc: Volume of the central compartment
+
+CL = 1 in [L/h]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 100 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KSS = 1000 in [pmol/L]
+ desc: Apparent dissociation constant [KSS = (kint+koff)/kon], if kint << koff KSS ~= KD and if kint >> koff KSS > KD
+
+kdeg = 0.05 in [1/h]
+ desc: target degradation rate constant
+
+ke0 = 0.1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kint = kdeg in [1/h]
+ desc: complex internalization rate constant
+
+
+b_term = C1_t - KSS - CT1_0 in [pmol/L]
+ desc: b term of quadratic equation
+
+c_term = C1_t * KSS in [pmol/L*pmol/L]
+ desc: c term of quadratic equation
+
+C1_t = A1_t/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+CT1_t = CT1_b + CT1_f in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+C1_f = 0.5 * (b_term + (b_term^2+4*c_term)^0.5) in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C1_b = C1_t-C1_f in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+CT1_b = C1_b in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_f = CT1_0-CT1_b in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+dot(Aa) = -ka*Aa in [pmol]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_t) = ka*Aa*F -CL*C1_f -kint*CT1_b*V1 in [pmol]
+ desc: Amount of free drug in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_1cmpt_PK_Model_Preclinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_1cmpt_PK_Model_Preclinical.mmt
new file mode 100644
index 00000000..50260312
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_1cmpt_PK_Model_Preclinical.mmt
@@ -0,0 +1,119 @@
+[[model]]
+name: 1-compartment QSS Constant Target Concentration (Wagner) PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_t = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L/kg]
+ desc: Volume of the central compartment
+
+CL = 1 in [L/h/kg]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 100 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KSS = 1000 in [pmol/L]
+ desc: Apparent dissociation constant [KSS = (kint+koff)/kon], if kint << koff KSS ~= KD and if kint >> koff KSS > KD
+
+kdeg = 0.05 in [1/h]
+ desc: target degradation rate constant
+
+ke0 = 0.1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kint = kdeg in [1/h]
+ desc: complex internalization rate constant
+
+
+b_term = C1_t - KSS - CT1_0 in [pmol/L]
+ desc: b term of quadratic equation
+
+c_term = C1_t * KSS in [pmol/L*pmol/L]
+ desc: c term of quadratic equation
+
+C1_t = A1_t/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+CT1_t = CT1_b + CT1_f in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+C1_f = 0.5 * (b_term + (b_term^2+4*c_term)^0.5) in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C1_b = C1_t-C1_f in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+CT1_b = C1_b in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_f = CT1_0-CT1_b in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+dot(Aa) = -ka*Aa in [pmol/kg]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_t) = ka*Aa*F -CL*C1_f -kint*CT1_b*V1 in [pmol/kg]
+ desc: Amount of free drug in central compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_2cmpt_PK_Model_clinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_2cmpt_PK_Model_clinical.mmt
new file mode 100644
index 00000000..a5487519
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_2cmpt_PK_Model_clinical.mmt
@@ -0,0 +1,132 @@
+[[model]]
+name: 1-compartment QSS Constant Target Concentration (Wagner) PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_t = 0
+PKCompartment.A2 = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L]
+ desc: Volume of the peripheral compartment
+
+Q1 = 1 in [L/h]
+ desc: intercompartmental clearance between central and peripheral compartment
+
+CL = 1 in [L/h]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 1 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KSS = 1 in [pmol/L]
+ desc: Apparent dissociation constant [KSS = (kint+koff)/kon], if kint << koff KSS ~= KD and if kint >> koff KSS > KD
+
+kdeg = 1 in [1/h]
+ desc: target degradation rate constant
+
+ke0 = 1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kint = kdeg in [1/h]
+ desc: complex internalization rate constant
+
+
+b_term = C1_t - KSS - CT1_0 in [pmol/L]
+ desc: b term of quadratic equation
+
+c_term = C1_t * KSS in [pmol/L * pmol/L]
+ desc: c term of quadratic equation
+
+C1_t = A1_t/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+CT1_t = CT1_b + CT1_f in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+C1_f = 0.5 * (b_term + (b_term^2+4*c_term)^0.5) in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C1_b = C1_t-C1_f in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+C2 = A2/V2 in [pmol/L]
+ desc: free concentration of drug in the peripheral compartment
+
+CT1_b = C1_b in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_f = CT1_0-CT1_b in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+dot(Aa) = -ka*Aa in [pmol]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_t) = ka*Aa*F -CL*C1_f -Q1*(C1_f - C2) -kint*CT1_b*V1 in [pmol]
+ desc: Amount of free drug in central compartment
+
+dot(A2) = Q1*(C1_f - C2) in [pmol]
+ desc: Amount of free drug in the peripheral compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_2cmpt_PK_Model_preclinical.mmt b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_2cmpt_PK_Model_preclinical.mmt
new file mode 100644
index 00000000..d60d7996
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/TMDD_QSS_ConstTarget_2cmpt_PK_Model_preclinical.mmt
@@ -0,0 +1,132 @@
+[[model]]
+name: 1-compartment QSS Constant Target Concentration (Wagner) PK Model + effect compartment
+author: Michael Gertz
+
+# Initial values:
+PKCompartment.Aa = 0
+PKCompartment.A1_t = 0
+PKCompartment.A2 = 0
+PKCompartment.AUC1_f = 0
+PKCompartment.AUC1_b = 0
+PKCompartment.AUC1_t = 0
+PKCompartment.AUCT1_f = 0
+PKCompartment.AUCT1_b = 0
+PKCompartment.AUCT1_t = 0
+PKCompartment.AUCe = 0
+PKCompartment.Ce = 0
+
+[environment]
+t = 0 in [h] bind time
+
+
+[PKCompartment]
+
+tlag = 1 in [h]
+ desc: absorption lag time from extravasc compartment
+
+ka = 1 in [1/h]
+ desc: first order absorption rate constant
+
+F = 1 in [dimensionless]
+ desc: fraction absorbed
+
+V1 = 1 in [L/kg]
+ desc: Volume of the central compartment
+
+V2 = 1 in [L/kg]
+ desc: Volume of the peripheral compartment
+
+Q1 = 1 in [L/h/kg]
+ desc: intercompartmental clearance between central and peripheral compartment
+
+CL = 1 in [L/h/kg]
+ desc: Linear clearance from central compartment
+
+CT1_0 = 1 in [pmol/L]
+ desc: baseline concentration of the target in the central compartment
+
+KSS = 1 in [pmol/L]
+ desc: Apparent dissociation constant [KSS = (kint+koff)/kon], if kint << koff KSS ~= KD and if kint >> koff KSS > KD
+
+kdeg = 1 in [1/h]
+ desc: target degradation rate constant
+
+ke0 = 1 in [1/h]
+ desc: equilibration rate constant effect compartment
+
+Kp = 1 in [dimensionless]
+ desc: effect compartment to plasma partitioning coefficient
+
+kint = kdeg in [1/h]
+ desc: complex internalization rate constant
+
+
+b_term = C1_t - KSS - CT1_0 in [pmol/L]
+ desc: b term of quadratic equation
+
+c_term = C1_t * KSS in [pmol/L * pmol/L]
+ desc: c term of quadratic equation
+
+C1_t = A1_t/V1 in [pmol/L]
+ desc: Total concentration of drug in the central compartment
+
+CT1_t = CT1_b + CT1_f in [pmol/L]
+ desc: Total concentration of target in the central compartment
+
+C1_f = 0.5 * (b_term + (b_term^2+4*c_term)^0.5) in [pmol/L]
+ desc: Free concentration of drug in the central compartment
+
+C1_b = C1_t-C1_f in [pmol/L]
+ desc: Bound concentration of drug in the central compartment
+
+C2 = A2/V2 in [pmol/L]
+ desc: free concentration of drug in the peripheral compartment
+
+CT1_b = C1_b in [pmol/L]
+ desc: Bound concentration of target in the central compartment
+
+CT1_f = CT1_0-CT1_b in [pmol/L]
+ desc: Free concentration of target in the central compartment
+
+
+RO_Model = CT1_b/CT1_t*100 in [dimensionless]
+ desc: Receptor (Target) occupancy
+
+PerInh = (1-CT1_f/CT1_t)*100 in [dimensionless]
+ desc: Percent inhbition relative to total target
+
+PerInh_Baseline = (1-CT1_f/CT1_0)*100 in [dimensionless]
+ desc: Percent inhibition relative to the initial steady-state level of target
+
+dot(Aa) = -ka*Aa in [pmol/kg]
+ desc: Amount of drug in 'depo' compartment
+
+dot(A1_t) = ka*Aa*F -CL*C1_f -Q1*(C1_f - C2) -kint*CT1_b*V1 in [pmol/kg]
+ desc: Amount of free drug in central compartment
+
+dot(A2) = Q1*(C1_f - C2) in [pmol/kg]
+ desc: Amount of free drug in the peripheral compartment
+
+dot(Ce) = ke0*(C1_f*Kp - Ce) in [pmol/L]
+ desc: Concentration of drug in effect compartment
+
+dot(AUC1_f)= C1_f in [pmol/L*h]
+ desc: Free AUC of drug in central the compartment
+
+dot(AUC1_b)= C1_b in [pmol/L*h]
+ desc: Bound AUC of drug in the central compartment
+
+dot(AUC1_t)= C1_t in [pmol/L*h]
+ desc: Total AUC of drug in central the central compartment
+
+dot(AUCT1_f)= CT1_f in [pmol/L*h]
+ desc: Free AUC of the target in the central compartment
+
+dot(AUCT1_b)= CT1_b in [pmol/L*h]
+ desc: Bound AUC of the target in the central compartment
+
+dot(AUCT1_t)= CT1_t in [pmol/L*h]
+ desc: Total AUC of the target in the central compartment
+
+dot(AUCe)= Ce in [pmol/L*h]
+ desc: Free AUC of drug in the effect compartment
\ No newline at end of file
diff --git a/pkpdapp/pkpdapp/migrations/models/readParamFile.py b/pkpdapp/pkpdapp/migrations/models/readParamFile.py
new file mode 100644
index 00000000..fa33e486
--- /dev/null
+++ b/pkpdapp/pkpdapp/migrations/models/readParamFile.py
@@ -0,0 +1,67 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import openpyxl
+
+
+# Load the workbook
+workbook = openpyxl.load_workbook(
+ 'pkpdapp/migrations/models/ParametersValue_Species.xlsx', data_only=True)
+
+sheet_names = ['1cmpt_PK_Model', '2cmpt_PK_Model',
+ '3cmpt_PK_Model', '1cmpt_TMDD_Model',
+ '2cmpt_TMDD_Model']
+model_names = ['one_compartment', 'two_compartment',
+ 'three_compartment', 'one_compartment_tmdd',
+ 'two_compartment_tmdd']
+species_list = ['M', 'R', 'K', 'H']
+compound_type = ['SM', 'LM']
+clinical = [False, False, False, True]
+
+entry = ''
+for sheet_name, model_name in zip(sheet_names, model_names):
+ worksheet = workbook[sheet_name]
+
+ model_entry = ''
+ for row in worksheet.iter_rows():
+ parameter = row[0].value
+ if parameter is None:
+ continue
+ param_entry = ''
+ for i, species in enumerate(species_list):
+ species_entry = ''
+ for j, ctype in enumerate(compound_type):
+ rowi = i * 4 + j * 2 + 1
+ value = row[rowi].value
+ unit = row[rowi + 1].value
+ if_clinical = clinical[i]
+ species_entry += f"""{ctype}: {{
+ value: {value},
+ unit: '{unit}',
+ }},"""
+ if j != len(compound_type) - 1:
+ species_entry += """
+ """
+ param_entry += f"""{species}: {{
+ {species_entry}
+ }},
+ """
+ model_entry += f"""{parameter}: {{
+ {param_entry}
+ }},
+ """
+ entry += f"""
+ {model_name}: {{
+ {model_entry}
+ }},"""
+type = '{[key: string]: {[key: string]: {[key: string]: {[key: string]: { value: number, unit: string}}}}}' # noqa: E501
+final_entry = f"""export const param_default: {type} = {{{entry}
+}};"""
+
+# save entry to param_default.ts
+with open('pkpdapp/migrations/models/param_default.ts', 'w') as f:
+ f.write(final_entry)
+
+print(final_entry)
diff --git a/pkpdapp/pkpdapp/models/__init__.py b/pkpdapp/pkpdapp/models/__init__.py
new file mode 100644
index 00000000..67e991b0
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/__init__.py
@@ -0,0 +1,60 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+# flake8: noqa f401
+
+from .stored import StoredModel
+from .units import Unit
+from .compound import Compound
+from .efficacy_experiment import EfficacyExperiment
+from .project import Project, ProjectAccess
+from .protocol import Protocol
+from .dose import Dose
+from .subject import Subject
+from .biomarker_type import BiomarkerType
+from .biomarker import Biomarker
+from .categorical_biomarker import CategoricalBiomarker
+from .myokit_model_mixin import MyokitModelMixin
+from .mechanistic_model import MechanisticModel
+from .pharmacodynamic_model import (
+ PharmacodynamicModel,
+)
+from .pharmacokinetic_model import (
+ PharmacokineticModel,
+)
+from .combined_model import (
+ CombinedModel,
+ PkpdMapping,
+ DerivedVariable
+)
+from .dataset import Dataset
+from .variable import Variable
+from .profile import Profile
+from .myokit_forward_model import MyokitForwardModel
+from .likelihoods import (
+ LogLikelihood,
+ LogLikelihoodParameter,
+)
+from .inference_results import (
+ InferenceChain,
+ InferenceResult,
+ InferenceFunctionResult,
+ InferenceOutputResult,
+)
+from .simulation import (
+ Simulation,
+ SimulationYAxis,
+ SimulationCxLine,
+ SimulationSlider,
+ SimulationPlot,
+)
+from .inference import (
+ Inference,
+ Algorithm,
+)
+
+
+
+from .inference_mixin import InferenceMixin
diff --git a/pkpdapp/pkpdapp/models/biomarker.py b/pkpdapp/pkpdapp/models/biomarker.py
new file mode 100644
index 00000000..0a092432
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/biomarker.py
@@ -0,0 +1,46 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from pkpdapp.models import BiomarkerType, Subject
+
+
+class Biomarker(models.Model):
+ """
+ A single biomarker measurement value stored in a :model:`pkpdapp.Dataset`.
+ Each biomarker is assigned a type stored in :model:`pkpdapp.BiomarkerType`.
+
+ For observations, there will be multiple biomarker measurements for each
+ subject at each measurement time.
+
+ For covariates, there will be only a single biomarker measurement for each
+ subject. The time point is arbitrary as the value is piecewise constant
+ over time
+
+ For regressors, there will be multiple biomarker measurements for each
+ subject. For time values between measurements the predicted effect is
+ piecewise constant over time.
+
+ Note for categorical covariates the :model:`pkpdapp.CategoricalBiomarker`
+ is used instead.
+ """
+ time = models.FloatField(
+ help_text='time point of measurement, in hours.'
+ )
+ subject = models.ForeignKey(
+ Subject, on_delete=models.CASCADE,
+ related_name='biomarkers',
+ help_text='subject associated with this biomarker'
+ )
+ biomarker_type = models.ForeignKey(
+ BiomarkerType, on_delete=models.CASCADE,
+ related_name='biomarkers',
+ help_text='biomarker type, for example "concentration in mg"'
+ )
+ value = models.FloatField(help_text='value of the measurement')
+
+ def get_project(self):
+ return self.biomarker_type.get_project()
diff --git a/pkpdapp/pkpdapp/models/biomarker_type.py b/pkpdapp/pkpdapp/models/biomarker_type.py
new file mode 100644
index 00000000..23f3e331
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/biomarker_type.py
@@ -0,0 +1,140 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from django.db.models import OuterRef, Subquery
+from pkpdapp.models import Unit
+import pandas as pd
+
+
+class BiomarkerType(models.Model):
+ """
+ A type of biomarker measurement associated with a particular dataset, for
+ example "concentration in mg", or "tumor volume in cm^3".
+ """
+
+ name = models.CharField(
+ max_length=100, help_text='name of the biomarker type'
+ )
+ stored_unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ related_name='biomarker_types_stored',
+ help_text='unit for the value stored in :model:`pkpdapp.Biomarker`'
+ )
+ description = models.TextField(
+ help_text='short description of the biomarker type',
+ blank=True, null=True
+ )
+ dataset = models.ForeignKey(
+ 'Dataset', on_delete=models.CASCADE,
+ related_name='biomarker_types',
+ help_text='dataset containing this biomarker measurement'
+ )
+ display = models.BooleanField(
+ default=True,
+ help_text=(
+ 'True if this biomarker type will be displayed in the '
+ 'frontend, False otherwise'
+ )
+ )
+ display_unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ related_name='biomarker_types_display',
+ help_text='unit to use when sending or displaying biomarker values'
+ )
+ stored_time_unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ related_name='biomarker_types_time_stored',
+ help_text=(
+ 'unit for the time values stored in '
+ ':model:`pkpdapp.Biomarker`'
+ )
+ )
+ display_time_unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ related_name='biomarker_types_time_display',
+ help_text='unit to use when sending or displaying time values'
+ )
+ color = models.IntegerField(
+ default=0,
+ help_text=(
+ 'Color index associated with this biomarker type. '
+ 'For plotting purposes in the frontend'
+ )
+ )
+ axis = models.BooleanField(
+ default=False,
+ help_text=(
+ 'True/False if biomarker type displayed on LHS/RHS axis'
+ )
+ )
+
+ def get_project(self):
+ return self.dataset.get_project()
+
+ def is_categorical(self):
+ return self.categorical_biomarkers.exists()
+
+ def is_continuous(self):
+ return self.biomarkers.exists()
+
+ def data(self, first_time_only=False):
+ """
+ if first_time_only then ordered by subject
+ if not first_time_only then ordered by time
+ """
+ is_continuous = self.is_continuous()
+ is_categorical = self.is_categorical()
+ if is_continuous:
+ biomarkers = self.biomarkers
+ elif is_categorical:
+ biomarkers = self.categorical_biomarkers
+ else:
+ return pd.DataFrame.from_dict({
+ 'times': [],
+ 'subjects': [],
+ 'values': [],
+ })
+ if first_time_only:
+ earliest = biomarkers.filter(
+ subject=OuterRef('subject')).order_by('time')
+ times_subjects_values = biomarkers.filter(
+ time=Subquery(earliest.values('time')[:1])
+ ).order_by('subject').values_list(
+ 'time', 'subject__id', 'value'
+ )
+ else:
+ times_subjects_values = biomarkers.order_by(
+ 'time'
+ ).values_list(
+ 'time', 'subject__id', 'value'
+ )
+
+ if not times_subjects_values:
+ return None
+
+ times, subjects, values = list(zip(*times_subjects_values))
+ df = pd.DataFrame.from_dict({
+ 'times': times,
+ 'subjects': subjects,
+ 'values': values,
+ })
+
+ time_conversion_factor = self.stored_time_unit.convert_to(
+ self.display_time_unit
+ )
+ df['times'] *= time_conversion_factor
+
+ if is_continuous:
+ conversion_factor = self.stored_unit.convert_to(
+ self.display_unit
+ )
+ df['values'] *= conversion_factor
+
+ return df
+
+ def __str__(self):
+ return str(self.name)
diff --git a/pkpdapp/pkpdapp/models/categorical_biomarker.py b/pkpdapp/pkpdapp/models/categorical_biomarker.py
new file mode 100644
index 00000000..72c1f2d1
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/categorical_biomarker.py
@@ -0,0 +1,46 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from pkpdapp.models import BiomarkerType, Subject
+
+
+class CategoricalBiomarker(models.Model):
+ """
+ A single categorical biomarker state stored in a :model:`pkpdapp.Dataset`.
+ Each biomarker is assigned a type stored in :model:`pkpdapp.BiomarkerType`.
+
+ For categorical covariates, there will be only a single biomarker state for
+ each subject. The time point is arbitrary as the value is piecewise
+ constant over time
+
+ For categorical regressors, there will be multiple biomarker state for each
+ subject. For time values between measurements the state is piecewise
+ constant over time.
+
+ Note for continuous covariates the :model:`pkpdapp.Biomarker`
+ is used instead.
+ """
+ time = models.FloatField(
+ help_text='time point of measurement, in hours.'
+ )
+ subject = models.ForeignKey(
+ Subject, on_delete=models.CASCADE,
+ related_name='categorical_biomarkers',
+ help_text='subject associated with this biomarker'
+ )
+ biomarker_type = models.ForeignKey(
+ BiomarkerType, on_delete=models.CASCADE,
+ related_name='categorical_biomarkers',
+ help_text='biomarker type, for example "weight in kg"'
+ )
+ value = models.CharField(
+ max_length=100,
+ help_text='category name'
+ )
+
+ def get_project(self):
+ return self.biomarker_type.get_project()
diff --git a/pkpdapp/pkpdapp/models/combined_model.py b/pkpdapp/pkpdapp/models/combined_model.py
new file mode 100644
index 00000000..1e972f3e
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/combined_model.py
@@ -0,0 +1,703 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from pkpdapp.models import (
+ MyokitModelMixin,
+ Project,
+ StoredModel,
+ PharmacodynamicModel,
+ PharmacokineticModel,
+ Unit,
+)
+import myokit
+from django.db import models
+from django.urls import reverse
+import logging
+from pkpdapp.utils.default_params import defaults
+
+logger = logging.getLogger(__name__)
+
+
+class CombinedModel(MyokitModelMixin, StoredModel):
+ """
+ PK model plus dosing and protocol information
+ """
+
+ name = models.CharField(max_length=100, help_text="name of the model")
+ project = models.ForeignKey(
+ Project,
+ on_delete=models.CASCADE,
+ related_name="pk_models",
+ blank=True,
+ null=True,
+ help_text='Project that "owns" this model',
+ )
+
+ class SpeciesType(models.TextChoices):
+ HUMAN = "H", "human"
+ RAT = "R", "rat"
+ NHP = "N", "non-human primate"
+ MOUSE = "M", "mouse"
+
+ species = models.CharField(
+ max_length=1,
+ choices=SpeciesType.choices,
+ default=SpeciesType.HUMAN,
+ help_text="species",
+ )
+
+ pk_model = models.ForeignKey(
+ PharmacokineticModel,
+ on_delete=models.PROTECT,
+ blank=True,
+ null=True,
+ help_text="model",
+ )
+
+ has_saturation = models.BooleanField(
+ default=False, help_text="whether the pk model has saturation"
+ )
+ has_effect = models.BooleanField(
+ default=False, help_text="whether the pk model has effect compartment"
+ )
+ has_lag = models.BooleanField(
+ default=False, help_text="whether the pk model has lag"
+ )
+
+ has_bioavailability = models.BooleanField(
+ default=False, help_text="whether the pk model has bioavailability"
+ )
+
+ pd_model = models.ForeignKey(
+ PharmacodynamicModel,
+ on_delete=models.PROTECT,
+ related_name="pkpd_models",
+ blank=True,
+ null=True,
+ help_text="PD part of model",
+ )
+
+ has_hill_coefficient = models.BooleanField(
+ default=False, help_text="whether the pd model has hill coefficient"
+ )
+
+ pd_model2 = models.ForeignKey(
+ PharmacodynamicModel,
+ on_delete=models.PROTECT,
+ related_name="pkpd_models2",
+ blank=True,
+ null=True,
+ help_text="second PD part of model",
+ )
+
+ time_max = models.FloatField(
+ default=30,
+ help_text=(
+ "suggested time to simulate after the last dose (in the time "
+ "units specified by the mmt model)"
+ ),
+ )
+ __original_pk_model = None
+ __original_pd_model = None
+ __original_pd_model2 = None
+ __original_species = None
+ __original_has_saturation = None
+ __original_has_effect = None
+ __original_has_lag = None
+ __original_has_hill_coefficient = None
+ __original_has_bioavailability = None
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ @classmethod
+ def from_db(cls, db, field_names, values):
+ instance = super().from_db(db, field_names, values)
+ # fix for infinite recursion when deleting project
+ if "pk_model_id" in field_names:
+ instance.__original_pk_model = instance.pk_model
+ if "pd_model_id" in field_names:
+ instance.__original_pd_model = instance.pd_model
+ if "pd_model2_id" in field_names:
+ instance.__original_pd_model2 = instance.pd_model2
+ if "species" in field_names:
+ instance.__original_species = instance.species
+ if "has_saturation" in field_names:
+ instance.__original_has_saturation = instance.has_saturation
+ if "has_effect" in field_names:
+ instance.__original_has_effect = instance.has_effect
+ if "has_lag" in field_names:
+ instance.__original_has_lag = instance.has_lag
+ if "has_bioavailability" in field_names:
+ instance.__original_has_bioavailability = instance.has_bioavailability
+ if "has_hill_coefficient" in field_names:
+ instance.__original_has_hill_coefficient = instance.has_hill_coefficient
+ return instance
+
+ def get_project(self):
+ return self.project
+
+ @property
+ def is_library_model(self):
+ is_library_model = False
+ if self.pk_model:
+ is_library_model = self.pk_model.is_library_model
+ return is_library_model
+
+ def get_time_max(self):
+ time_max = self.time_max
+ if self.pd_model:
+ time_max = max(time_max, self.pd_model.time_max)
+ return time_max
+
+ def get_time_unit(self):
+ from pkpdapp.models import Variable
+
+ try:
+ time_var = self.variables.get(binding="time")
+ return time_var.unit
+ except Variable.DoesNotExist:
+ return None
+
+ def get_mmt(self):
+ myokit_model = self.get_myokit_model()
+ return myokit_model.code()
+
+ def create_stored_model(self):
+ stored_model_kwargs = {
+ "name": self.name,
+ "project": self.project,
+ "pk_model": self.pk_model,
+ "pd_model": self.pd_model,
+ "time_max": self.time_max,
+ "read_only": True,
+ }
+ stored_model = CombinedModel.objects.create(**stored_model_kwargs)
+
+ new_variables = {}
+ for variable in self.variables.all():
+ new_variable = variable.create_stored_variable(stored_model)
+ new_variables[new_variable.qname] = new_variable
+
+ for mapping in self.mappings.all():
+ mapping.create_stored_mapping(stored_model, new_variables)
+
+ return stored_model
+
+ def create_myokit_model(self):
+ if self.pk_model is None:
+ pk_model = myokit.Model()
+ else:
+ pk_model = self.pk_model.create_myokit_model()
+ if self.pd_model is None:
+ pd_model = myokit.Model()
+ else:
+ pd_model = self.pd_model.create_myokit_model()
+ if self.pd_model2 is None:
+ pd_model2 = myokit.Model()
+ else:
+ pd_model2 = self.pd_model2.create_myokit_model()
+
+ have_both_models = self.pk_model is not None and self.pd_model is not None
+ have_no_models = self.pk_model is None and self.pd_model is None
+
+ # combine the two pd models. If any constants overlap prefer the
+ # pd_model (remove the constant from pd_model2) If any state variables
+ # overlap then add the rhs terms
+
+ if self.pd_model2 is not None:
+ pd2_time_var = pd_model2.binding("time")
+ pd2_time_var.set_binding(None)
+ pd2_time_component = pd2_time_var.parent()
+ pd2_time_component.remove_variable(pd2_time_var)
+ if pd2_time_component.count_variables() == 0:
+ pd_model2.remove_component(pd2_time_component)
+
+ pd2_components = list(pd_model2.components())
+ pd2_names = [
+ c.name().replace("PDCompartment", "PDCompartment2")
+ for c in pd2_components
+ ]
+ pd_model.import_component(
+ pd2_components,
+ new_name=pd2_names,
+ )
+
+ # deal with any state variables that overlap
+ for old_pd2_var in pd_model2.variables(state=True):
+ if pd_model.has_variable(old_pd2_var.qname()):
+ pd_var = pd_model.get(old_pd2_var.qname())
+ pd2_var = pd_model.get(
+ pd_var.qname().replace("PDCompartment", "PDCompartment2")
+ )
+ pd_var.set_rhs(
+ myokit.Plus(
+ pd_var.rhs(),
+ pd2_var.rhs().clone(
+ {myokit.Name(pd2_var): myokit.Name(pd_var)}
+ ),
+ )
+ )
+ for eqn in pd_model.get("PDCompartment2").equations():
+ if eqn.rhs.depends_on(myokit.Name(pd2_var)):
+ lhs_var = eqn.lhs.var()
+ lhs_var.set_rhs(
+ eqn.rhs.clone(
+ {myokit.Name(pd2_var): myokit.Name(pd_var)}
+ )
+ )
+ pd2_var.parent().remove_variable(pd2_var)
+
+ # deal with any constants that overlap
+ for old_pd2_var in pd_model2.variables(const=True):
+ if pd_model.has_variable(old_pd2_var.qname()):
+ pd2_var = pd_model.get(
+ old_pd2_var.qname().replace("PDCompartment", "PDCompartment2")
+ )
+ pd2_var.parent().remove_variable(pd2_var)
+
+ # use pk model as the base and import the pd model
+ pkpd_model = pk_model
+
+ # default model is one with just time
+ if have_no_models:
+ pkpd_model = myokit.parse_model(
+ """
+ [[model]]
+ [myokit]
+ time = 0 [s] bind time
+ in [s]
+ """
+ )
+
+ # remove time binding and variable from pd model
+ if have_both_models:
+ time_var = pd_model.binding("time")
+ time_var.set_binding(None)
+ time_component = time_var.parent()
+ time_component.remove_variable(time_var)
+ if time_component.count_variables() == 0:
+ pd_model.remove_component(time_component)
+
+ pd_components = list(pd_model.components())
+ pd_names = [c.name().replace("myokit", "PD") for c in pd_components]
+
+ if pd_components:
+ pkpd_model.import_component(
+ pd_components,
+ new_name=pd_names,
+ )
+
+ # do derived variables
+ for derived_variable in self.derived_variables.all():
+ try:
+ myokit_var = pkpd_model.get(derived_variable.pk_variable.qname)
+ except KeyError:
+ continue
+ myokit_compartment = myokit_var.parent()
+ var_name = derived_variable.pk_variable.name
+ if (
+ derived_variable.type == DerivedVariable.Type.RECEPTOR_OCCUPANCY
+ ): # noqa: E501
+ new_names = [f"calc_{var_name}_RO"]
+ has_name = any(
+ [
+ myokit_compartment.has_variable(new_name)
+ for new_name in new_names
+ ]
+ ) # noqa: E501
+ if has_name:
+ continue
+ var = myokit_compartment.add_variable(new_names[0])
+ var.meta[
+ "desc"
+ ] = f'Receptor occupancy for {myokit_var.meta["desc"]}' # noqa: E501
+ kd_name = "KD_ud"
+ if myokit_compartment.has_variable(kd_name):
+ kd = myokit_compartment.get(kd_name)
+ else:
+ kd = myokit_compartment.add_variable(kd_name)
+ kd.meta[
+ "desc"
+ ] = "User-defined Dissociation Constant (Drug Target Tab) used to calculate Receptor occupancy" # noqa: E501
+ target_conc_name = "CT1_0_ud"
+ if myokit_compartment.has_variable(target_conc_name):
+ target_conc = myokit_compartment.get(target_conc_name)
+ else:
+ target_conc = myokit_compartment.add_variable(target_conc_name)
+ target_conc.meta[
+ "desc"
+ ] = "User-defined Target Concentration (Drug Target Tab) used to calculate Receptor occupancy" # noqa: E501
+ var.set_unit(myokit.Unit())
+ kd_unit = myokit_var.unit()
+ compound = self.project.compound
+ kd_unit_conversion_factor = compound.dissociation_unit.convert_to(
+ kd_unit, compound=compound
+ )
+ kd.set_rhs(compound.dissociation_constant * kd_unit_conversion_factor)
+ kd.set_unit(kd_unit)
+ target_conc_unit = myokit_var.unit()
+ target_conc_unit_conversion_factor = (
+ compound.target_concentration_unit.convert_to(
+ target_conc_unit, compound=compound, is_target=True
+ )
+ )
+ target_conc.set_rhs(
+ compound.target_concentration * target_conc_unit_conversion_factor
+ )
+ target_conc.set_unit(target_conc_unit)
+
+ b = var.add_variable("b")
+ b.set_rhs(
+ myokit.Plus(
+ myokit.Plus(myokit.Name(kd), myokit.Name(target_conc)),
+ myokit.Name(myokit_var),
+ )
+ )
+ c = var.add_variable("c")
+ c.set_rhs(
+ myokit.Multiply(
+ myokit.Multiply(myokit.Number(4), myokit.Name(target_conc)),
+ myokit.Name(myokit_var),
+ )
+ )
+
+ var.set_rhs(
+ myokit.Multiply(
+ myokit.Number(100),
+ myokit.Divide(
+ myokit.Minus(
+ myokit.Name(b),
+ myokit.Sqrt(
+ myokit.Minus(
+ myokit.Power(myokit.Name(b), myokit.Number(2)),
+ myokit.Name(c),
+ )
+ ),
+ ),
+ myokit.Multiply(myokit.Number(2), myokit.Name(target_conc)),
+ ),
+ )
+ )
+ elif (
+ derived_variable.type == DerivedVariable.Type.FRACTION_UNBOUND_PLASMA
+ ): # noqa: E501
+ new_names = [f"calc_{var_name}_f", "FUP_ud"]
+ has_name = any(
+ [
+ myokit_compartment.has_variable(new_name)
+ for new_name in new_names
+ ]
+ ) # noqa: E501
+ if has_name:
+ continue
+ var = myokit_compartment.add_variable(new_names[0])
+ var.meta[
+ "desc"
+ ] = f'Unbound Concentration for {myokit_var.meta["desc"]}' # noqa: E501
+ fup = myokit_compartment.add_variable(new_names[1])
+ fup.meta[
+ "desc"
+ ] = "User-defined Fraction Unbound Plasma (Drug Target Tab)" # noqa: E501
+ var.set_unit(myokit_var.unit())
+ fup.set_rhs(self.project.compound.fraction_unbound_plasma)
+ fup.set_unit(myokit.units.dimensionless)
+ var.set_rhs(myokit.Multiply(myokit.Name(fup), myokit.Name(myokit_var)))
+ elif (
+ derived_variable.type == DerivedVariable.Type.BLOOD_PLASMA_RATIO
+ ): # noqa: E501
+ new_names = [f"calc_{var_name}_bl", "BP_ud"]
+ has_name = any(
+ [
+ myokit_compartment.has_variable(new_name)
+ for new_name in new_names
+ ]
+ ) # noqa: E501
+ if has_name:
+ continue
+ var = myokit_compartment.add_variable(new_names[0])
+ bpr = myokit_compartment.add_variable(new_names[1])
+ bpr.meta[
+ "desc"
+ ] = "User-defined Blood to Plasma Ratio (Drug Target Tab)" # noqa: E501
+ var.meta["desc"] = f'Blood Concentration for {myokit_var.meta["desc"]}'
+ var.set_unit(myokit_var.unit())
+ bpr.set_rhs(self.project.compound.blood_to_plasma_ratio)
+ bpr.set_unit(myokit.units.dimensionless)
+ var.set_rhs(myokit.Multiply(myokit.Name(bpr), myokit.Name(myokit_var)))
+ elif derived_variable.type == DerivedVariable.Type.TLAG: # noqa: E501
+ new_names = [f"{var_name}_tlag_ud"]
+ has_name = any(
+ [
+ myokit_compartment.has_variable(new_name)
+ for new_name in new_names
+ ]
+ ) # noqa: E501
+ if has_name:
+ continue
+ var = myokit_compartment.add_variable(new_names[0])
+ var.meta[
+ "desc"
+ ] = "User-defined absorption lag time from specified compartment"
+ time_var = pkpd_model.binding("time")
+ var.set_unit(time_var.unit())
+ var.set_rhs(myokit.Number(0))
+ else:
+ raise ValueError(
+ f"Unknown derived variable type {derived_variable.type}"
+ )
+
+ # do mappings
+ for mapping in self.mappings.all():
+ try:
+ pd_var = pkpd_model.get(
+ mapping.pd_variable.qname.replace("myokit", "PD")
+ )
+ pk_var = pkpd_model.get(mapping.pk_variable.qname)
+ except KeyError:
+ continue
+
+ pk_to_pd_conversion_multiplier = Unit.convert_between_myokit_units(
+ pk_var.unit(), pd_var.unit(), compound=self.project.compound
+ )
+ pd_to_pk_conversion_multiplier = Unit.convert_between_myokit_units(
+ pk_var.unit(), pd_var.unit(), compound=self.project.compound
+ )
+
+ # pd var will be an intermediary variable driven by pk_var
+ if pd_var.is_state():
+ # add pd_var rate equation to pk_var
+ pk_var.set_rhs(
+ myokit.Plus(
+ pk_var.rhs(),
+ myokit.Multiply(
+ myokit.Number(pd_to_pk_conversion_multiplier), pd_var.rhs()
+ ),
+ )
+ )
+
+ # demote pd_var to an intermediary variable
+ pd_var.demote()
+
+ pd_var.set_rhs(
+ myokit.Multiply(
+ myokit.Number(pk_to_pd_conversion_multiplier), myokit.Name(pk_var)
+ )
+ )
+
+ pkpd_model.validate()
+ return pkpd_model
+
+ def get_absolute_url(self):
+ return reverse("dosed_pk_model-detail", kwargs={"pk": self.pk})
+
+ def save(self, force_insert=False, force_update=False, *args, **kwargs):
+ created = not self.pk
+
+ super().save(force_insert, force_update, *args, **kwargs)
+
+ # don't update a stored model
+ if self.read_only:
+ return
+
+ # if the pk or pd models have changed then remove the mappings and
+ # derived variables
+ if (
+ self.pk_model != self.__original_pk_model
+ or self.pd_model != self.__original_pd_model
+ or self.pd_model2 != self.__original_pd_model2
+ ):
+ self.mappings.all().delete()
+ self.derived_variables.all().delete()
+
+ if (
+ created
+ or self.pk_model != self.__original_pk_model
+ or self.pd_model != self.__original_pd_model
+ or self.pd_model2 != self.__original_pd_model2
+ or self.has_saturation != self.__original_has_saturation
+ or self.has_effect != self.__original_has_effect
+ or self.has_lag != self.__original_has_lag
+ or self.has_bioavailability != self.__original_has_bioavailability
+ or self.has_hill_coefficient != self.__original_has_hill_coefficient
+ ):
+ self.update_model()
+
+ self.__original_pd_model = self.pd_model
+ self.__original_pd_model2 = self.pd_model2
+ self.__original_pk_model = self.pk_model
+ self.__original_species = self.species
+ self.__original_has_saturation = self.has_saturation
+ self.__original_has_effect = self.has_effect
+ self.__original_has_lag = self.has_lag
+ self.__original_has_hill_coefficient = self.has_hill_coefficient
+ self.__original_has_bioavailability = self.has_bioavailability
+
+ def reset_params_to_defaults(self, species, compoundType, variables=None):
+ if self.is_library_model:
+ model_name = (
+ self.pk_model.name.replace("_clinical", "")
+ .replace("_preclinical", "")
+ .replace("tmdd_full_constant_target", "tmdd")
+ .replace("tmdd_qss_constant_target", "tmdd")
+ .replace("tmdd_full", "tmdd")
+ .replace("tmdd_QSS", "tmdd")
+ .replace("production", "")
+ .replace("elimination", "")
+ )
+ print(
+ "resetting params to defaults",
+ model_name,
+ species,
+ compoundType,
+ self.pk_model.name,
+ )
+ if variables is None:
+ variables = self.variables.all()
+ for v in variables:
+ varName = v.name
+ defaultVal = (
+ defaults.get(model_name, {})
+ .get(varName, {})
+ .get(species, {})
+ .get(compoundType, None)
+ )
+ if defaultVal is None:
+ continue
+ if defaultVal.get("unit", "") == "dimensionless":
+ defaultVal["unit"] = ""
+ unit = Unit.objects.filter(symbol=defaultVal.get("unit", "")).first()
+ value = defaultVal.get("value", None)
+ if value is None or unit is None:
+ continue
+ v.default_value = value
+ v.unit = unit
+ v.save()
+
+
+class PkpdMapping(StoredModel):
+ pkpd_model = models.ForeignKey(
+ CombinedModel,
+ on_delete=models.CASCADE,
+ related_name="mappings",
+ help_text="PKPD model that this mapping is for",
+ )
+ pk_variable = models.ForeignKey(
+ "Variable",
+ on_delete=models.CASCADE,
+ related_name="pk_mappings",
+ help_text="variable in PK part of model",
+ )
+ pd_variable = models.ForeignKey(
+ "Variable",
+ on_delete=models.CASCADE,
+ related_name="pd_mappings",
+ help_text="variable in PD part of model",
+ )
+
+ __original_pk_variable = None
+ __original_pd_variable = None
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.__original_pk_variable = self.pk_variable
+ self.__original_pd_variable = self.pd_variable
+
+ def save(self, force_insert=False, force_update=False, *args, **kwargs):
+ created = not self.pk
+
+ super().save(force_insert, force_update, *args, **kwargs)
+
+ # don't update a stored model
+ if self.read_only:
+ return
+
+ if (
+ created
+ or self.pk_variable != self.__original_pk_variable
+ or self.pd_variable != self.__original_pd_variable
+ ):
+ self.pkpd_model.update_model()
+
+ self.__original_pk_variable = self.pk_variable
+ self.__original_pd_variable = self.pd_variable
+
+ def delete(self):
+ pkpd_model = self.pkpd_model
+ super().delete()
+ pkpd_model.update_model()
+
+ def create_stored_mapping(self, new_pkpd_model, new_variables):
+ new_pk_variable = new_variables[self.pk_variable.qname]
+ new_pd_variable = new_variables[self.pd_variable.qname]
+ stored_kwargs = {
+ "pkpd_model": new_pkpd_model,
+ "pk_variable": new_pk_variable,
+ "pd_variable": new_pd_variable,
+ "read_only": True,
+ }
+ stored_mapping = PkpdMapping.objects.create(**stored_kwargs)
+ return stored_mapping
+
+
+class DerivedVariable(StoredModel):
+ pkpd_model = models.ForeignKey(
+ CombinedModel,
+ on_delete=models.CASCADE,
+ related_name="derived_variables",
+ help_text="PKPD model that this derived variable is for",
+ )
+ pk_variable = models.ForeignKey(
+ "Variable",
+ on_delete=models.CASCADE,
+ related_name="derived_variables",
+ help_text="base variable in PK part of model",
+ )
+
+ class Type(models.TextChoices):
+ RECEPTOR_OCCUPANCY = "RO", "receptor occupancy"
+ FRACTION_UNBOUND_PLASMA = "FUP", "faction unbound plasma"
+ BLOOD_PLASMA_RATIO = "BPR", "blood plasma ratio"
+ TLAG = "TLG", "dosing lag time"
+
+ type = models.CharField(
+ max_length=3, choices=Type.choices, help_text="type of derived variable"
+ )
+
+ __original_pk_variable = None
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.__original_pk_variable = self.pk_variable
+
+ def save(self, force_insert=False, force_update=False, *args, **kwargs):
+ created = not self.pk
+
+ super().save(force_insert, force_update, *args, **kwargs)
+
+ # don't update a stored model
+ if self.read_only:
+ return
+
+ if created or self.pk_variable != self.__original_pk_variable:
+ self.pkpd_model.update_model()
+
+ self.__original_pk_variable = self.pk_variable
+
+ def delete(self):
+ pkpd_model = self.pkpd_model
+ super().delete()
+ pkpd_model.update_model()
+
+ def create_stored_mapping(self, new_pkpd_model, new_variables):
+ new_pk_variable = new_variables[self.pk_variable.qname]
+ stored_kwargs = {
+ "pkpd_model": new_pkpd_model,
+ "pk_variable": new_pk_variable,
+ "read_only": True,
+ }
+ stored_mapping = DerivedVariable.objects.create(**stored_kwargs)
+ return stored_mapping
diff --git a/pkpdapp/pkpdapp/models/compound.py b/pkpdapp/pkpdapp/models/compound.py
new file mode 100644
index 00000000..19bb3d01
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/compound.py
@@ -0,0 +1,172 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from pkpdapp.models import (
+ Unit,
+)
+
+
+def get_mol_mass_unit():
+ try:
+ return Unit.objects.get(symbol='g/mol')
+ except Unit.DoesNotExist:
+ return None
+
+
+def get_intrinsic_clearence_unit():
+ try:
+ return Unit.objects.get(symbol='µL/min/mg')
+ except Unit.DoesNotExist:
+ return None
+
+
+def get_target_concentration_unit():
+ try:
+ return Unit.objects.get(symbol='nmol/L')
+ except Unit.DoesNotExist:
+ return None
+
+
+def get_dissociation_constant_unit():
+ try:
+ return Unit.objects.get(symbol='nmol/L')
+ except Unit.DoesNotExist:
+ return None
+
+
+class Compound(models.Model):
+ """
+ """
+
+ name = models.CharField(
+ max_length=100, help_text='name of the compound'
+ )
+ description = models.TextField(
+ help_text='short description of the compound',
+ blank=True, default=''
+ )
+ use_efficacy = models.ForeignKey(
+ 'EfficacyExperiment', on_delete=models.SET_NULL,
+ null=True,
+ related_name='compound_using',
+ )
+ molecular_mass = models.FloatField(
+ default=500.0,
+ help_text=(
+ 'molecular mass for compound for conversion from mol to grams'
+ )
+ )
+ molecular_mass_unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ default=get_mol_mass_unit,
+ related_name='compound_mol_mass',
+ help_text='unit for molecular mass (e.g. g/mol)'
+ )
+
+ class CompoundType(models.TextChoices):
+ SMALL_MOLECULE = 'SM', 'Small Molecule'
+ LARGE_MOLECULE = 'LM', 'Large Molecule'
+
+ compound_type = models.CharField(
+ max_length=2,
+ choices=CompoundType.choices,
+ default=CompoundType.SMALL_MOLECULE,
+ )
+
+ fraction_unbound_plasma = models.FloatField(
+ default=0.02,
+ blank=True, null=True,
+ help_text='fraction unbound plasma (unitless)'
+ )
+
+ blood_to_plasma_ratio = models.FloatField(
+ default=1.0,
+ blank=True, null=True,
+ help_text='blood to plasma ratio (unitless)'
+ )
+
+ intrinsic_clearance = models.FloatField(
+ blank=True, null=True,
+ help_text='intrinsic clearance'
+ )
+
+ intrinsic_clearance_unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ default=get_intrinsic_clearence_unit,
+ related_name='compounds_clint',
+ help_text='unit for intrinsic clearance'
+ )
+
+ class AssayType(models.TextChoices):
+ MICROSOMES = 'MS', 'Microsomes'
+ HEPATOCYTES = 'HC', 'Hepatocytes'
+
+ intrinsic_clearance_assay = models.CharField(
+ max_length=2,
+ choices=AssayType.choices,
+ default=AssayType.MICROSOMES,
+ )
+
+ fraction_unbound_including_cells = models.FloatField(
+ default=1.0,
+ blank=True, null=True,
+ help_text='fraction unbound in plasma and red blood cells (unitless)'
+ )
+
+ # -------
+ # Target
+ # -------
+
+ target_molecular_mass = models.FloatField(
+ default=25000.0,
+ help_text=(
+ 'molecular mass for target for conversion from mol to grams'
+ ),
+ )
+
+ target_molecular_mass_unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ default=get_mol_mass_unit,
+ related_name='compounds_target_mol_mass',
+ help_text='unit for target molecular mass (e.g. g/mol)'
+ )
+
+ target_concentration = models.FloatField(
+ default=1.0,
+ blank=True, null=True,
+ help_text='target concentration'
+ )
+
+ target_concentration_unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ default=get_target_concentration_unit,
+ related_name='compounds_target_conc',
+ help_text='unit for target concentration'
+ )
+
+ dissociation_constant = models.FloatField(
+ blank=True, null=True,
+ help_text='dissociation constant'
+ )
+
+ dissociation_unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ related_name='compounds_kd',
+ default=get_dissociation_constant_unit,
+ help_text='unit for dissociation constant'
+ )
+
+ is_soluble = models.BooleanField(
+ default=True,
+ help_text='is the compound target soluble'
+ )
+
+ def get_project(self):
+ return self.project
+
+ def __str__(self):
+ return str(self.name)
diff --git a/pkpdapp/pkpdapp/models/dataset.py b/pkpdapp/pkpdapp/models/dataset.py
new file mode 100644
index 00000000..96429278
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/dataset.py
@@ -0,0 +1,223 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pandas as pd
+from django.db import models
+from pkpdapp.models import Project
+from pkpdapp.models import (
+ Dose, Biomarker, BiomarkerType, Subject, Protocol, Unit,
+ CategoricalBiomarker,
+)
+from pkpdapp.utils import DataParser
+
+
+class Dataset(models.Model):
+ """
+ A PKPD dataset containing one or more :model:`pkpdapp.Biomarker`.
+ """
+ name = models.CharField(
+ max_length=100,
+ help_text='name of the dataset'
+ )
+ datetime = models.DateTimeField(
+ help_text=(
+ 'date/time the experiment was conducted. '
+ 'All time measurements are relative to this date/time, ' +
+ 'which is in YYYY-MM-DD HH:MM:SS format. For example, ' +
+ '2020-07-18 14:30:59'
+ ),
+ null=True, blank=True
+ )
+ description = models.TextField(
+ help_text='short description of the dataset',
+ blank=True, default=''
+ )
+ project = models.ForeignKey(
+ Project, on_delete=models.CASCADE,
+ related_name='datasets',
+ blank=True, null=True,
+ help_text='Project that "owns" this model'
+ )
+
+ def __str__(self):
+ return self.name
+
+ def get_project(self):
+ return self.project
+
+ def replace_data(self, data: pd.DataFrame):
+ # remove existing dataset
+ BiomarkerType.objects.filter(dataset=self).delete()
+ Subject.objects.filter(dataset=self).delete()
+
+ data_without_dose = data.query('OBSERVATION != "."')
+
+ time_unit = Unit.objects.get(symbol=data["TIME_UNIT"].iloc[0])
+
+ # create biomarker types
+ # assume AMOUNT_UNIT and TIME_UNIT are constant for each bt
+ bts_unique = data_without_dose[
+ ['OBSERVATION_NAME', 'OBSERVATION_UNIT', 'TIME_UNIT']
+ ].drop_duplicates()
+ biomarker_types = {}
+ for i, row in bts_unique.iterrows():
+ unit = Unit.objects.get(symbol=row['OBSERVATION_UNIT'])
+ observation_name = row['OBSERVATION_NAME']
+ biomarker_types[observation_name] = BiomarkerType.objects.create(
+ name=observation_name,
+ description="",
+ stored_unit=unit,
+ display_unit=unit,
+ stored_time_unit=time_unit,
+ display_time_unit=time_unit,
+ dataset=self,
+ color=i,
+ )
+
+ # create subjects
+ subjects = {}
+ for i, row in data[['SUBJECT_ID']].drop_duplicates().iterrows():
+ subject_id = row['SUBJECT_ID']
+
+ subjects[subject_id] = Subject.objects.create(
+ id_in_dataset=subject_id,
+ dataset=self,
+ shape=i,
+ )
+
+ # create subject protocol
+ for i, row in data[
+ ['SUBJECT_ID', 'ROUTE', "AMOUNT_UNIT"]
+ ].drop_duplicates().iterrows():
+ subject_id = row['SUBJECT_ID']
+ route = row['ROUTE']
+ amount_unit = Unit.objects.get(symbol=row['AMOUNT_UNIT'])
+ subject = subjects[subject_id]
+ if route == 'IV':
+ route = Protocol.DoseType.DIRECT
+ else:
+ route = Protocol.DoseType.INDIRECT
+ if not subject.protocol:
+ subject.protocol = Protocol.objects.create(
+ name='{}-{}'.format(
+ self.name,
+ subject
+ ),
+ time_unit=time_unit,
+ amount_unit=amount_unit,
+ dose_type=route
+ )
+ subject.save()
+
+ # insert covariate columns as categorical for now
+ covariates = {}
+ last_covariate_value = {}
+ parser = DataParser()
+ for covariate_name in data.columns:
+ if parser.is_covariate_column(covariate_name):
+ dimensionless_unit = Unit.objects.get(symbol='')
+ covariates[covariate_name] = BiomarkerType.objects.create(
+ name=covariate_name,
+ description="",
+ stored_unit=dimensionless_unit,
+ display_unit=dimensionless_unit,
+ stored_time_unit=time_unit,
+ display_time_unit=time_unit,
+ display=False,
+ dataset=self,
+ color=len(covariates),
+ )
+ last_covariate_value[covariate_name] = None
+
+ for i, row in data.iterrows():
+ subject_id = row["SUBJECT_ID"]
+ time = row["TIME"]
+ amount = row["AMOUNT"]
+ amount_unit = row["AMOUNT_UNIT"]
+ observation = row["OBSERVATION"]
+ observation_name = row["OBSERVATION_NAME"]
+ route = row['ROUTE']
+ infusion_time = row['INFUSION_TIME']
+
+ amount_unit = Unit.objects.get(symbol=amount_unit)
+
+ subject = subjects[subject_id]
+
+ if observation != ".": # measurement observation
+ Biomarker.objects.create(
+ time=time,
+ subject=subject,
+ value=observation,
+ biomarker_type=biomarker_types[observation_name]
+ )
+ try:
+ float(amount)
+ amount_convertable_to_float = True
+ except ValueError:
+ amount_convertable_to_float = False
+ if amount_convertable_to_float and float(amount) > 0.0:
+ # dose observation
+ if route == 'IV':
+ route = Protocol.DoseType.DIRECT
+ else:
+ route = Protocol.DoseType.INDIRECT
+
+ protocol = subject.protocol
+ start_time = float(time)
+ amount = float(amount)
+ infusion_time = float(infusion_time)
+ Dose.objects.create(
+ start_time=start_time,
+ amount=amount,
+ duration=infusion_time,
+ protocol=protocol,
+ )
+
+ # insert covariate columns as categorical for now
+ for covariate_name in covariates.keys():
+ covariate_value = row[covariate_name]
+ if covariate_value != ".":
+ # only insert if value has changed
+ last_value = last_covariate_value[covariate_name]
+ if (
+ last_value is None or
+ (last_value is not None and
+ covariate_value != last_value)
+ ):
+ last_covariate_value[covariate_name] = covariate_value
+ CategoricalBiomarker.objects.create(
+ time=time,
+ subject=subject,
+ value=covariate_value,
+ biomarker_type=covariates[covariate_name]
+ )
+
+ self.merge_protocols()
+
+ def merge_protocols(self):
+ unique_protocols = []
+ protocol_subjects = []
+ for subject in self.subjects.all():
+ if subject.protocol is None:
+ continue
+ protocol = subject.protocol
+ index = None
+ for i, other_protocol in enumerate(unique_protocols):
+ if protocol.is_same_as(other_protocol):
+ index = i
+ break
+ if index is None:
+ unique_protocols.append(protocol)
+ protocol_subjects.append([subject])
+ else:
+ protocol_subjects[index].append(subject)
+ protocol.delete()
+
+ # migrate subjects to unique_protocols
+ for protocol, subjects in zip(unique_protocols, protocol_subjects):
+ for subject in subjects:
+ subject.protocol = protocol
+ subject.save()
diff --git a/pkpdapp/pkpdapp/models/dose.py b/pkpdapp/pkpdapp/models/dose.py
new file mode 100644
index 00000000..6b6f8af7
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/dose.py
@@ -0,0 +1,109 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from pkpdapp.models import Protocol, StoredModel
+from django.core.exceptions import ValidationError
+
+
+def validate_duration(value):
+ if value <= 0:
+ raise ValidationError(
+ 'Duration should be greater than 0'
+ )
+
+
+class DoseBase(models.Model):
+ """
+ A single dose event.
+ """
+
+ start_time = models.FloatField(
+ help_text=(
+ 'starting time point of dose, '
+ 'see protocol for units'
+ )
+ )
+ amount = models.FloatField(
+ help_text=(
+ 'amount of compound administered over the duration, '
+ 'see protocol for units. Rate of administration is '
+ 'assumed constant'
+ )
+ )
+ duration = models.FloatField(
+ default=1.0,
+ help_text=(
+ 'Duration of dose administration, '
+ 'see protocol for units. '
+ 'Duration must be greater than 0.'
+ ),
+ validators=[validate_duration]
+ )
+
+ repeats = models.IntegerField(
+ default=1,
+ help_text=(
+ 'Number of times to repeat the dose. '
+ ),
+ )
+
+ repeat_interval = models.FloatField(
+ default=1.0,
+ help_text=(
+ 'Interval between repeated doses. '
+ 'See protocol for units. '
+ ),
+ )
+
+ class Meta:
+ constraints = [
+ models.CheckConstraint(
+ name="Duration must be greater than 0",
+ check=models.Q(duration__gt=0),
+ ),
+ ]
+
+ def get_project(self):
+ return self.protocol.get_project()
+
+ def save(self, force_insert=False, force_update=False, *args, **kwargs):
+ super().save(force_insert, force_update, *args, **kwargs)
+
+ models = set()
+ for v in self.protocol.variables.all().select_related(
+ 'dosed_pk_model'
+ ):
+ models.add(v.dosed_pk_model)
+ for m in models:
+ m.update_simulator()
+
+ def is_same_as(self, other_dose):
+ if self.duration != other_dose.duration:
+ return False
+ if self.start_time != other_dose.start_time:
+ return False
+ if self.amount != other_dose.amount:
+ return False
+ return True
+
+
+class Dose(DoseBase, StoredModel):
+ protocol = models.ForeignKey(
+ Protocol, on_delete=models.CASCADE,
+ related_name='doses',
+ help_text='protocol containing this dose'
+ )
+
+ def create_stored_dose(self, stored_protocol):
+ stored_dose_kwargs = {
+ 'protocol': stored_protocol,
+ 'start_time': self.start_time,
+ 'amount': self.amount,
+ 'duration': self.duration,
+ 'read_only': True,
+ }
+ return Dose.objects.create(**stored_dose_kwargs)
diff --git a/pkpdapp/pkpdapp/models/efficacy_experiment.py b/pkpdapp/pkpdapp/models/efficacy_experiment.py
new file mode 100644
index 00000000..45e84318
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/efficacy_experiment.py
@@ -0,0 +1,42 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from pkpdapp.models import (
+ Compound
+)
+
+
+class EfficacyExperiment(models.Model):
+ name = models.CharField(
+ max_length=100, help_text='name of the experiment',
+ blank=True, default=''
+ )
+
+ c50 = models.FloatField(
+ help_text=(
+ 'half maximal effective concentration'
+ )
+ )
+
+ c50_unit = models.ForeignKey(
+ 'Unit', on_delete=models.PROTECT,
+ related_name='efficacy_experiments',
+ help_text='unit for c50'
+ )
+
+ hill_coefficient = models.FloatField(
+ default=1.0,
+ help_text=(
+ 'Hill coefficient measure of binding'
+ )
+ )
+
+ compound = models.ForeignKey(
+ Compound, on_delete=models.CASCADE,
+ related_name='efficacy_experiments',
+ help_text='compound for efficacy experiment'
+ )
diff --git a/pkpdapp/pkpdapp/models/inference.py b/pkpdapp/pkpdapp/models/inference.py
new file mode 100644
index 00000000..0ffb193d
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/inference.py
@@ -0,0 +1,264 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from pkpdapp.celery import app
+from pkpdapp.models import (
+ Project, PharmacodynamicModel,
+ CombinedModel,
+ StoredModel, LogLikelihoodParameter,
+ InferenceFunctionResult, InferenceResult
+)
+
+
+class Algorithm(models.Model):
+ name = models.CharField(
+ max_length=100,
+ help_text='name of the algorithm'
+ )
+
+ class Category(models.TextChoices):
+ SAMPLING = 'SA', 'Sampling'
+ OPTIMISATION = 'OP', 'Optimisation'
+ OTHER = 'OT', 'Optimisation'
+
+ category = models.CharField(
+ max_length=10,
+ choices=Category.choices
+ )
+
+
+def get_default_optimisation_algorithm():
+ return Algorithm.objects.get(name='CMAES')
+
+
+class Inference(StoredModel):
+ """
+ An inference process.
+ """
+
+ name = models.CharField(
+ max_length=100,
+ help_text='name of the dataset'
+ )
+ description = models.TextField(
+ help_text='short description of what this inference does',
+ blank=True, default=''
+ )
+
+ project = models.ForeignKey(
+ Project, on_delete=models.CASCADE,
+ help_text='Project that "owns" this inference object'
+ )
+
+ algorithm = models.ForeignKey(
+ Algorithm,
+ on_delete=models.PROTECT,
+ default=get_default_optimisation_algorithm,
+ help_text='algorithm used to perform the inference'
+ )
+
+ class InitializationStrategy(models.TextChoices):
+ DEFAULT_VALUE = 'D', 'Default Value of model'
+ RANDOM = 'R', 'Random from prior'
+ FROM_OTHER = 'F', 'From other inference'
+
+ initialization_strategy = models.CharField(
+ max_length=1,
+ choices=InitializationStrategy.choices,
+ default=InitializationStrategy.RANDOM,
+ )
+
+ initialization_inference = models.ForeignKey(
+ 'Inference',
+ on_delete=models.PROTECT,
+ blank=True, null=True,
+ )
+
+ # potentially for optimisation too (as in number of starting points)
+ number_of_chains = models.IntegerField(
+ default=4,
+ help_text='number of chains'
+ )
+
+ max_number_of_iterations = models.IntegerField(
+ default=1000,
+ help_text='maximum number of iterations'
+ )
+
+ burn_in = models.IntegerField(
+ default=0,
+ help_text='final iteration of burn-in',
+ )
+
+ number_of_iterations = models.IntegerField(
+ default=0,
+ help_text='number of iterations calculated'
+ )
+
+ time_elapsed = models.IntegerField(
+ default=0,
+ help_text='Elapsed run time for inference in seconds'
+ )
+
+ number_of_function_evals = models.IntegerField(
+ default=0,
+ help_text='number of function evaluations'
+ )
+
+ task_id = models.CharField(
+ max_length=40,
+ blank=True, null=True,
+ help_text='If executing, this is the celery task id'
+ )
+
+ # error = models.TextField(
+ # blank=True, null=True,
+ # help_text='If inference failed, an error message is here'
+ # )
+
+ metadata = models.JSONField(
+ default=dict,
+ help_text="metadata for inference",
+ )
+
+ def reset(self):
+ print('reset', self)
+ self.chains.all().delete()
+ self.log_likelihoods.all().delete()
+ self.number_of_iterations = 0
+ self.time_elapsed = 0
+ self.number_of_function_evals = 0
+ self.metadata = {}
+
+ def get_project(self):
+ return self.project
+
+ def store_inference(self):
+ # store related objects so we can recreate them later
+ old_log_likelihoods = self.log_likelihoods.all()
+
+ # save models used in this inference
+ old_pd_models = list(PharmacodynamicModel.objects.filter(
+ variables__log_likelihoods__inference=self
+ ).distinct())
+
+ old_pk_models = list(CombinedModel.objects.filter(
+ variables__log_likelihoods__inference=self
+ ).distinct())
+ # old_models += list(PkpdModel.objects.filter(
+ # variables__log_likelihoods__in=old_log_likelihoods
+ # ).distinct())
+
+ # create a map between old and new models so we can transfer
+ # the relationships
+ new_models = {
+ model.id: model.create_stored_model() for model in old_pd_models
+ }
+
+ # store pd models referred to by pk models
+ new_models.update({
+ model.pd_model.id: model.pd_model.create_stored_model()
+ for model in old_pk_models
+ if model.pd_model is not None
+ })
+
+ # finally store the pk models
+ new_models.update({
+ model.id: model.create_stored_model(
+ new_models[
+ model.pd_model.id if model.pd_model is not None else None
+ ]
+ )
+ for model in old_pk_models
+ })
+
+ self.id = None
+ self.pk = None
+
+ # save new as readonly
+ self.read_only = True
+ self.save()
+
+ # recreate log_likelihoods and remove default children
+ new_log_likelihoods = []
+ for log_likelihood in old_log_likelihoods:
+ new_ll = log_likelihood.create_stored_log_likelihood(
+ self, new_models
+ )
+
+ # delete auto-generated parents and children
+ new_ll.children.all().delete()
+ new_ll.parents.all().delete()
+
+ new_log_likelihoods.append(new_ll)
+
+ # recreate children relationships using indicies
+ # of old_log_likelihoods
+ for parent_index, parent in enumerate(old_log_likelihoods):
+ new_parent = new_log_likelihoods[parent_index]
+ for child in parent.children.all():
+ child_index = None
+ for i, ll in enumerate(old_log_likelihoods):
+ if ll == child:
+ child_index = i
+ new_child = new_log_likelihoods[child_index]
+
+ # get old parameter and save it as a new relationship
+ old_param = LogLikelihoodParameter.objects.get(
+ parent=parent, child=child
+ )
+ old_param.id = None
+ old_param.pk = None
+ old_param.parent = new_parent
+ old_param.child = new_child
+ old_param.save()
+
+ self.refresh_from_db()
+
+ def run_inference(self, test=False):
+ ll_names = [
+ ll.name for ll in self.log_likelihoods.all()
+ ]
+ if len(set(ll_names)) < len(ll_names):
+ raise RuntimeError(
+ (
+ 'inference has log-likelihoods '
+ 'with identical names! {}'
+ ).format(ll_names)
+ )
+
+ if not test:
+ from pkpdapp.tasks import run_inference
+ try:
+ result = run_inference.delay(self.id)
+ self.task_id = result.id
+ self.save()
+ except run_inference.OperationalError as exc:
+ print('Sending task raised: {}'.format(exc))
+
+ def get_maximum_likelihood(self):
+ chains = self.chains.all()
+
+ max_function_value = (
+ InferenceFunctionResult.objects.filter(
+ chain__in=chains
+ ).order_by(
+ '-value'
+ ).first()
+ )
+ results_for_mle = (
+ InferenceResult.objects.filter(
+ chain=max_function_value.chain,
+ iteration=max_function_value.iteration
+ )
+ )
+
+ return results_for_mle
+
+ def stop_inference(self):
+ if self.task_id is not None:
+ app.control.revoke(self.task_id, terminate=True)
diff --git a/pkpdapp/pkpdapp/models/inference_mixin.py b/pkpdapp/pkpdapp/models/inference_mixin.py
new file mode 100644
index 00000000..2033a7fa
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/inference_mixin.py
@@ -0,0 +1,856 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import transaction
+import numpy as np
+import pints
+import myokit
+import time
+import theano.tensor as tt
+import theano
+from tdigest import TDigest
+from pkpdapp.models import (
+ Inference,
+ InferenceResult,
+ InferenceChain, InferenceFunctionResult,
+ InferenceOutputResult,
+ LogLikelihood,
+ Subject
+)
+
+optimisers_dict = {
+ 'CMAES': pints.CMAES,
+ 'Nelder-Mead': pints.NelderMead,
+ 'PSO': pints.PSO,
+ 'SNES': pints.SNES,
+ 'XNES': pints.XNES
+}
+
+
+samplers_dict = {
+ 'Haario-Bardenet': pints.HaarioBardenetACMC,
+ 'Differential evolution': pints.DifferentialEvolutionMCMC,
+ 'DREAM': pints.DreamMCMC,
+ 'Emcee-hammer': pints.EmceeHammerMCMC,
+ 'Population MCMC': pints.PopulationMCMC
+}
+
+
+class ChainWriter:
+ """
+ utility class for buffering inference results writes to the database
+ """
+
+ def __init__(self, chains, priors, buffer_size):
+ self._iterations = []
+ self._fn_value_buffers = [
+ [] for _ in chains
+ ]
+ self._x0_buffers = [
+ [] for _ in chains
+ ]
+ self._chains = chains
+ self._priors = priors
+ self._buffer_size = buffer_size
+ self._prior_lengths = [
+ p.get_total_length() for p in priors
+ ]
+ self._prior_subjects = [
+ p.get_data()[2] for p in priors
+ ]
+ for i, subjects in enumerate(self._prior_subjects):
+ if subjects is not None:
+ self._prior_subjects[i] = [
+ Subject.objects.get(id=s) for s in subjects
+ ]
+ self._prior_slices = []
+ curr_index = 0
+ for prior_length in self._prior_lengths:
+ self._prior_slices.append(
+ slice(curr_index, curr_index + prior_length)
+ )
+ curr_index += prior_length
+
+ # InferenceOutputResult.objects.filter(
+ # chain__in=self._chains,
+ # ).delete()
+
+ # InferenceFunctionResult.objects.filter(
+ # chain__in=self._chains,
+ # ).delete()
+
+ def append(self, fn_values, x0s, iteration):
+ for buffer, x0 in zip(self._x0_buffers, x0s):
+ buffer.append(x0)
+ for buffer, fn_value in zip(self._fn_value_buffers, fn_values):
+ buffer.append(fn_value)
+ self._iterations.append(iteration)
+ if len(self._iterations) > self._buffer_size:
+ self.write()
+
+ def write(self):
+ function_results = []
+ inference_results = []
+ for x0_buffer, fn_values_buffer, chain in zip(
+ self._x0_buffers, self._fn_value_buffers, self._chains
+ ):
+ for iteration, x0, fn_value in zip(
+ self._iterations, x0_buffer, fn_values_buffer
+ ):
+ function_results.append(InferenceFunctionResult(
+ chain=chain,
+ iteration=iteration,
+ value=fn_value
+ ))
+ for prior_slice, prior, prior_subjects in zip(
+ self._prior_slices, self._priors, self._prior_subjects
+ ):
+ prior_values = x0[prior_slice]
+ if prior_subjects is None:
+ inference_results.append(InferenceResult(
+ chain=chain,
+ log_likelihood=prior,
+ iteration=iteration,
+ value=prior_values[0]
+ ))
+ else:
+ for value, subject in zip(
+ prior_values, prior_subjects
+ ):
+ inference_results.append(InferenceResult(
+ chain=chain,
+ log_likelihood=prior,
+ iteration=iteration,
+ subject=subject,
+ value=value
+ ))
+ InferenceFunctionResult.objects.bulk_create(function_results)
+ InferenceResult.objects.bulk_create(inference_results)
+
+ self._iterations = []
+ self._fn_value_buffers = [
+ [] for _ in self._chains
+ ]
+ self._x0_buffers = [
+ [] for _ in self._chains
+ ]
+
+
+class OutputWriter:
+ """
+ utility class for generating & writing output
+ results writes to the database
+ """
+
+ def __init__(self, chains,
+ log_likelihoods,
+ pints_log_posterior,
+ use_every_n_sample=1,
+ buffer_size=100,
+ store_output_range=True,
+ pooled=True,
+ ):
+
+ self._iterations = []
+ self._x0_buffers = [
+ [] for _ in chains
+ ]
+
+ self._chains = chains
+
+ self._log_likelihoods = log_likelihoods
+ self._pints_log_posterior = pints_log_posterior
+ data = [ll.get_data() for ll in log_likelihoods]
+ self._values = [d[0] for d in data]
+ self._times = [d[1] for d in data]
+ print('creating output thingo', pooled, 'is_pooled')
+ if pooled:
+ self._subjects = [
+ [None for _ in values]
+ for values in self._values
+ ]
+ self._unique_times = [
+ [times[0]] for times in self._times
+ ]
+ self._unique_times_index = [
+ [0] for _ in self._times
+ ]
+ self._times_index = [
+ [0] for _ in self._times
+ ]
+ for unique_times, unique_times_index, times_index, times in zip(
+ self._unique_times, self._unique_times_index,
+ self._times_index, self._times
+ ):
+ unique_index = 0
+ for i, t in enumerate(times[1:]):
+ if t != unique_times[-1]:
+ times_index.append(i + 1)
+ unique_times.append(t)
+ unique_index += 1
+ unique_times_index.append(unique_index)
+ else:
+ self._subjects = [
+ [Subject.objects.get(id=subject_id) for subject_id in d[2]]
+ for d in data
+ ]
+ for subjects in self._subjects:
+ print('subjects', subjects)
+ self._unique_times = self._times
+ self._unique_times_index = [
+ list(range(len(times))) for times in self._times
+ ]
+ self._times_index = self._unique_times_index
+
+ self._tdigests = [
+ [
+ [
+ TDigest() for _ in times
+ ]
+ for times in self._unique_times
+ ]
+ for _ in chains
+ ]
+
+ self._use_every_n_sample = use_every_n_sample
+ self._store_output_range = store_output_range
+ self._outputs = [
+ self.initialise_outputs(chain) for chain in self._chains
+ ]
+ self._buffer = 0
+ self._buffer_size = buffer_size
+ self._updated = False
+
+ def initialise_outputs(self, chain):
+ outputs = []
+ outputs_count = InferenceOutputResult.objects.filter(
+ chain=chain,
+ log_likelihood__in=self._log_likelihoods,
+ ).count()
+ if outputs_count != (
+ sum([len(times) for times in self._times])
+ ):
+ InferenceOutputResult.objects.filter(
+ chain=chain,
+ log_likelihood__in=self._log_likelihoods,
+ ).delete()
+ for log_likelihood, times, values, subjects in zip(
+ self._log_likelihoods, self._times, self._values,
+ self._subjects
+ ):
+ for time_val, value, subject in zip(times, values, subjects):
+ outputs.append(InferenceOutputResult.objects.create(
+ log_likelihood=log_likelihood,
+ chain=chain,
+ median=0,
+ percentile_min=0,
+ percentile_max=0,
+ subject=subject,
+ data=value,
+ time=time_val,
+ ))
+ return outputs
+
+ def append(self, x0s, iteration):
+ for buffer, x0 in zip(self._x0_buffers, x0s):
+ buffer.append(x0)
+ self._iterations.append(iteration)
+ if len(self._iterations) > self._buffer_size:
+ self.write()
+
+ def write(self):
+ for x0_buffer, tdigests_for_chain, chain, outputs in zip(
+ self._x0_buffers, self._tdigests, self._chains, self._outputs
+ ):
+ if self._store_output_range:
+ for iteration, x0 in zip(
+ self._iterations, x0_buffer
+ ):
+ if iteration % self._use_every_n_sample != 0:
+ continue
+ try:
+ results = \
+ self._pints_log_posterior.sample_generative_model(
+ self._pints_log_posterior.to_search(x0)
+ )
+ except myokit.SimulationError as e:
+ print(e)
+ continue
+ for times, tdigests, result, unique_times_index in zip(
+ self._times, tdigests_for_chain, results,
+ self._unique_times_index
+ ):
+ for i in range(len(times)):
+ value = result[i]
+ tdigests[unique_times_index[i]].update(value)
+
+ # write new percentiles
+ output_index = 0
+ for times, unique_times_index, tdigests, result in zip(
+ self._times, self._unique_times_index,
+ tdigests_for_chain, results
+ ):
+ for i in range(len(times)):
+ tdigest = tdigests[unique_times_index[i]]
+ maximum = tdigest.percentile(90)
+ minimum = tdigest.percentile(10)
+ median = tdigest.percentile(50)
+ outputs[output_index].median = median
+ outputs[output_index].percentile_min = minimum
+ outputs[output_index].percentile_max = maximum
+ output_index += 1
+
+ else:
+ # just use the last parameter values
+ output_index = 0
+ x0 = x0_buffer[-1]
+ try:
+ results_min, results, results_max = \
+ self._pints_log_posterior.generative_model_range(
+ self._pints_log_posterior.to_search(x0)
+ )
+ except myokit.SimulationError as e:
+ print(e)
+ continue
+ for times, tdigests, result, result_min, result_max in zip(
+ self._times, tdigests_for_chain,
+ results, results_min, results_max
+ ):
+ for i in range(len(times)):
+ outputs[output_index].median = result[i]
+ outputs[output_index].percentile_min = result_min[i]
+ outputs[output_index].percentile_max = result_max[i]
+ output_index += 1
+
+ with transaction.atomic():
+ [output.save() for output in outputs]
+
+ self._iterations = []
+ self._x0_buffers = [
+ [] for _ in self._chains
+ ]
+
+
+class InferenceMixin:
+ def __init__(self, inference):
+ print('inference mixin', inference.number_of_iterations)
+
+ # # select inference methods
+ self._inference_type, self._inference_method = (
+ self.get_inference_type_and_method(inference)
+ )
+
+ # types needed later
+ self.inference = inference
+
+ # get model parameters to be inferred
+ log_likelihoods = inference.log_likelihoods.all()
+
+ # this list defines the ordering in the parameter vector
+ # for the sampler
+ self._priors = [
+ ll
+ for ll in log_likelihoods
+ if ll.is_a_prior()
+ ]
+ self._pooled = all([
+ ll.get_total_length() == 1 for ll in self._priors
+ ])
+ self._prior_lengths = [
+ p.get_total_length() for p in self._priors
+ ]
+ self._prior_slices = []
+ curr_index = 0
+ for prior_length in self._prior_lengths:
+ self._prior_slices.append(
+ slice(curr_index, curr_index + prior_length)
+ )
+ curr_index += prior_length
+ self._prior_subjects = [
+ p.get_data()[2] for p in self._priors
+ ]
+ for i, subjects in enumerate(self._prior_subjects):
+ if subjects is not None:
+ self._prior_subjects[i] = [
+ Subject.objects.get(id=s) for s in subjects
+ ]
+
+ print('priors are')
+ for p in self._priors:
+ print(p.name, p.form)
+
+ # create forwards models
+ self._observed_log_likelihoods = [
+ ll
+ for ll in log_likelihoods
+ if ll.observed
+ ]
+ for ll in self._observed_log_likelihoods:
+ print('observed', ll.name, ll.biomarker_type)
+
+ if len(self._observed_log_likelihoods) == 0:
+ raise RuntimeError(
+ 'Error: must have at least one observed random variable '
+ 'in model'
+ )
+
+ pymc3_model = \
+ self._observed_log_likelihoods[0].create_pymc3_model(
+ *self._observed_log_likelihoods[1:]
+ )
+
+ self._pints_log_posterior = PyMC3LogPosterior(
+ pymc3_model, self._observed_log_likelihoods, self._priors,
+ optimisation=(self.inference.algorithm.category == 'OP')
+ )
+
+ # create chains if not exist
+ if self.inference.chains.count() == 0:
+ print('creating chains')
+ for i in range(self.inference.number_of_chains):
+ InferenceChain.objects.create(inference=self.inference)
+
+ if self.inference.chains.count() != self.inference.number_of_chains:
+ raise RuntimeError(
+ 'number of chains not equal to chains in database'
+ )
+
+ # create sampler objects
+ # If results already exist append to them, otherwise randomly
+ # sample prior for initial values.
+ # set inference results objects for each fitted parameter to be
+ # initial values
+ self._inference_objects = []
+ if (
+ self.inference.initialization_strategy ==
+ Inference.InitializationStrategy.FROM_OTHER
+ ):
+ other_chains = self.inference.initialization_inference.chains.all()
+ other_last_iteration = \
+ self.inference.initialization_inference.number_of_iterations
+ for i, chain in enumerate(self.inference.chains.all()):
+ x0 = []
+ if self.inference.number_of_iterations > 0:
+ print('restarting chains!')
+ for prior in self._priors:
+ x0.append(
+ prior.get_results(
+ chain=chain,
+ iteration=self.inference.number_of_iterations
+ )
+ )
+ x0 = np.hstack(x0)
+ else:
+ print('sample', [p.sample() for p in self._priors])
+ x0 = np.hstack(
+ [p.sample() for p in self._priors]
+ )
+ if (
+ self.inference.initialization_strategy ==
+ Inference.InitializationStrategy.DEFAULT_VALUE
+ ):
+ curr_index = 0
+ for xi, prior in enumerate(self._priors):
+ length = prior.get_total_length()
+ outputs = list(prior.outputs.all())
+ if (
+ len(outputs) > 0 and
+ outputs[0].variable is not None
+ ):
+ value = outputs[0].variable.get_default_value()
+ # if uniform prior then adjust default value
+ # to fall between bounds
+ if prior.form == prior.Form.UNIFORM:
+ lower, upper = \
+ prior.get_noise_log_likelihoods()
+ if (
+ lower.form == lower.Form.FIXED and
+ value < lower.value
+ ):
+ value = lower.value
+ if (
+ upper.form == upper.Form.FIXED and
+ value > upper.value
+ ):
+ value = upper.value
+ x0[
+ curr_index:curr_index + length
+ ] = value
+ curr_index += length
+ elif (
+ self.inference.initialization_strategy ==
+ Inference.InitializationStrategy.FROM_OTHER
+ ):
+ other_chain_index = min(i, len(other_chains) - 1)
+ other_chain = other_chains[other_chain_index]
+ curr_index = 0
+ for xi, this_prior in enumerate(
+ self._priors
+ ):
+ try:
+ length = prior.get_total_length()
+ other_prior = LogLikelihood.objects.get(
+ inference=(
+ self.inference.initialization_inference
+ ),
+ log_likelihood__name=this_prior.name
+ )
+ x0[curr_index:curr_index + length] = \
+ other_prior.get_results(
+ chain=other_chain,
+ iteration=other_last_iteration,
+ )
+
+ except InferenceResult.DoesNotExist:
+ pass
+
+ # write x0 to empty chain
+ self.inference.number_of_function_evals += 1
+ print('x0', x0)
+ fn_val = self._pints_log_posterior(
+ self._pints_log_posterior.to_search(x0)
+ )
+ if self.inference.algorithm.category == 'OP':
+ fn_val = -fn_val
+ print('starting function value', fn_val)
+ self.write_inference_results(
+ x0, fn_val,
+ self.inference.number_of_iterations, i
+ )
+
+ # apply transformations to initial point and create default sigma0
+ sigma0 = x0**2
+ sigma0[sigma0 == 0] = 1
+ # Use to create diagonal matrix
+ sigma0 = 0.01 * sigma0
+ print('sigma0', sigma0)
+ x0 = self._pints_log_posterior.to_search(x0)
+ self._inference_objects.append(
+ self._inference_method(x0, sigma0)
+ )
+
+ @ staticmethod
+ def get_inference_type_and_method(inference):
+ inference_type = inference.algorithm.category
+ methodname = inference.algorithm.name
+ if inference_type == 'SA':
+ method_dict = samplers_dict
+ else:
+ method_dict = optimisers_dict
+ inference_method = method_dict[methodname]
+ return inference_type, inference_method
+
+ def write_inference_results(self, values, fn_value, iteration,
+ chain_index):
+ # Writes inference results to one chain
+ chains = self.inference.chains.all()
+ InferenceFunctionResult.objects.create(
+ chain=chains[chain_index],
+ iteration=iteration,
+ value=fn_value
+ )
+ for prior_slice, prior, prior_subjects in zip(
+ self._prior_slices, self._priors, self._prior_subjects
+ ):
+ prior_values = values[prior_slice]
+ if prior_subjects is None:
+ InferenceResult.objects.create(
+ chain=chains[chain_index],
+ log_likelihood=prior,
+ iteration=iteration,
+ value=prior_values[0]
+ )
+ else:
+ for value, subject in zip(
+ prior_values, prior_subjects
+ ):
+ InferenceResult.objects.create(
+ chain=chains[chain_index],
+ log_likelihood=prior,
+ iteration=iteration,
+ subject=subject,
+ value=prior_values[0]
+ )
+
+ def step_inference(self, writer, output_writer):
+ # runs one set of ask / tell
+ fn_values = []
+ x0s = []
+ for obj in self._inference_objects:
+ x = obj.ask()
+ if self._inference_type == "SA": # sampling
+ score = self._pints_log_posterior(x)
+ self.inference.number_of_function_evals += 1
+ x, score, accepted = obj.tell(score)
+ else:
+ scores = [self._pints_log_posterior(xi) for xi in x]
+ self.inference.number_of_function_evals += len(x)
+ obj.tell(scores)
+ x = obj.xbest()
+ score = -obj.fbest()
+
+ x0s.append(self._pints_log_posterior.to_model(x))
+ fn_values.append(score)
+ writer.append(fn_values, x0s, self.inference.number_of_iterations)
+ output_writer.append(x0s, self.inference.number_of_iterations)
+
+ def run_inference(self):
+ # runs ask / tell
+ time_start = time.time()
+ max_iterations = self.inference.max_number_of_iterations
+ n_iterations = self.inference.number_of_iterations
+ initial_phase_iterations = -1
+ print('running inference')
+ if (
+ self.inference.algorithm.category == 'SA' and
+ self._inference_objects[0].needs_initial_phase()
+ ):
+ print('need to consider an initial phase')
+ dimensions = len(self._priors)
+ initial_phase_iterations = 500 * dimensions
+ if n_iterations < initial_phase_iterations:
+ print('Turning on initial phase')
+ for sampler in self._inference_objects:
+ sampler.set_initial_phase(True)
+
+ write_every_n_iteration = 500
+ evaluate_model_every_n_iterations = 10
+
+ writer = ChainWriter(
+ self.inference.chains.all(),
+ self._priors,
+ write_every_n_iteration,
+ )
+
+ output_writer = OutputWriter(
+ self.inference.chains.all(),
+ self._observed_log_likelihoods,
+ self._pints_log_posterior,
+ use_every_n_sample=evaluate_model_every_n_iterations,
+ buffer_size=write_every_n_iteration,
+ store_output_range=self.inference.algorithm.category == 'SA',
+ pooled=self._pooled
+ )
+ for i in range(n_iterations, max_iterations):
+ if i == initial_phase_iterations:
+ print('Turning off initial phase')
+ for sampler in self._inference_objects:
+ sampler.set_initial_phase(False)
+
+ self.inference.number_of_iterations += 1
+ self.step_inference(writer, output_writer)
+ time_now = time.time()
+ self.inference.time_elapsed = time_now - time_start
+
+ if i % write_every_n_iteration == 0:
+ # only save fields we've updated
+ self.inference.save(
+ update_fields=[
+ 'number_of_iterations',
+ 'number_of_function_evals',
+ 'time_elapsed',
+ ]
+ )
+
+ # write out the remaining iterations
+ writer.write()
+ output_writer.write()
+ self.inference.save()
+
+ def fixed_variables(self):
+ return self._fixed_variables
+
+
+class PyMC3LogPosterior(pints.LogPDF):
+ def __init__(self, model, log_likelihoods, priors, optimisation=False):
+ self._original_prior_names = [
+ p.name for p in priors
+ ]
+ self._transforms = [
+ model[p.name].distribution.transform for p in priors
+ ]
+ self._prior_lengths = [
+ p.get_total_length() for p in priors
+ ]
+ self._prior_slices = []
+ curr_index = 0
+ for prior_length in self._prior_lengths:
+ if prior_length > 1:
+ self._prior_slices.append(
+ slice(curr_index, curr_index + prior_length)
+ )
+ else:
+ self._prior_slices.append(curr_index)
+ curr_index += prior_length
+ print('slices are', self._prior_slices)
+ self._transform_names = [
+ t if t is None else t.name for t in self._transforms
+ ]
+ self._transform_backwards = [
+ self._transform_backward(t, l == 1) for t, l in zip(
+ self._transforms, self._prior_lengths
+ )
+ ]
+ self._transform_forwards = [
+ self._transform_forward(t, l == 1) for t, l in zip(
+ self._transforms, self._prior_lengths
+ )
+ ]
+ self._prior_names = [
+ self._get_name(p, t) for p, t in zip(priors, self._transforms)
+ ]
+ self._log_likelihoods = log_likelihoods
+ self._log_likelihood_names = [
+ self._get_name(ll, None) for ll in log_likelihoods
+ ]
+ mean_rvs = []
+ param1s_rvs = []
+ param1s_index = []
+ param1s = []
+ # assumes that all observed ll have 2 noise params
+ # assumes that the mean comes from a model
+ for i, ll in enumerate(self._log_likelihoods):
+ mean, param1 = ll.get_noise_log_likelihoods()
+ mean_name = mean.name + ll.name
+ mean_rvs.append(model[mean_name])
+ if param1.form == param1.Form.FIXED:
+ param1s.append(param1.value)
+ else:
+ param1s_rvs.append(model[param1.name])
+ param1s_index.append(i)
+ param1s.append(np.nan)
+ self._n_means = len(self._log_likelihoods)
+ self._param1s_index = param1s_index
+ self._param1s = np.array(param1s)
+ print('posterior_predictive', mean_rvs, param1s_rvs)
+ self._posterior_predictive = model.fastfn(mean_rvs + param1s_rvs)
+ self._model = model
+ self._logp = model.logp
+ if optimisation:
+ def function(x):
+ return -self._logp(x)
+ self._function = function
+ self._exception_value = np.inf
+ else:
+ self._function = self._logp
+ self._exception_value = -np.inf
+
+ def n_parameters(self):
+ return sum(self._prior_lengths)
+
+ def parameter_names(self):
+ return self._original_prior_names
+
+ @staticmethod
+ def _transform_forward(transform, is_scalar=True):
+ if is_scalar:
+ x = tt.dscalar('x')
+ x.tag.test_value = 1.0
+ else:
+ x = tt.dvector('x')
+ x.tag.test_value = [1.0]
+ if transform is None:
+ z = x
+ else:
+ z = transform.forward(x)
+ return theano.function([x], z)
+
+ @staticmethod
+ def _transform_backward(transform, is_scalar=True):
+ if is_scalar:
+ x = tt.dscalar('x')
+ x.tag.test_value = 1.0
+ else:
+ x = tt.dvector('x')
+ x.tag.test_value = [1.0]
+ if transform is None:
+ z = x
+ else:
+ z = transform.backward(x)
+ return theano.function([x], z)
+
+ def _get_name(self, prior, transform):
+ if transform is None:
+ return prior.name
+ return prior.name + '_{}__'.format(transform.name)
+
+ def _get_input_name(self, log_likelihood):
+ mean = log_likelihood.get_noise_log_likelihoods()[0]
+ print('name is ', mean.name + log_likelihood.name)
+ return mean.name + log_likelihood.name
+
+ def to_search(self, x):
+ y = x.copy()
+ for prior_index, prior_slice in enumerate(self._prior_slices):
+ y[prior_slice] = \
+ self._transform_forwards[prior_index](
+ y[prior_slice]
+ )
+ return y
+
+ def to_model(self, x):
+ y = x.copy()
+ for prior_index, prior_slice in enumerate(self._prior_slices):
+ y[prior_slice] = \
+ self._transform_backwards[prior_index](
+ y[prior_slice]
+ )
+ return y
+
+ def get_call_dict_from_params(self, x):
+ return {
+ self._prior_names[prior_index]: x[prior_slice]
+ for prior_index, prior_slice in enumerate(self._prior_slices)
+ }
+
+ def __call__(self, x):
+ call_dict = self.get_call_dict_from_params(x)
+ try:
+ result = self._function(call_dict)
+ except myokit.SimulationError as e:
+ print('ERROR in forward simulation at params:')
+ print(call_dict)
+ print(e)
+ result = self._exception_value
+ return result
+
+ def generative_model_range(self, x):
+ call_dict = self.get_call_dict_from_params(x)
+ results = self._posterior_predictive(call_dict)
+
+ means = results[:self._n_means]
+ param1s = self._param1s
+ for result, index in zip(results[self._n_means:], self._param1s_index):
+ param1s[index] = result
+ values = []
+ values_min = []
+ values_max = []
+ for output_values, param1, log_likelihood in zip(
+ means, param1s, self._log_likelihoods
+ ):
+ output_values_min, output_values_max = \
+ log_likelihood.noise_range(output_values, [0, param1])
+ values.append(output_values)
+ values_min.append(output_values_min)
+ values_max.append(output_values_max)
+ return values_min, values, values_max
+
+ def sample_generative_model(self, x):
+ call_dict = self.get_call_dict_from_params(x)
+ results = self._posterior_predictive(call_dict)
+ means = results[:self._n_means]
+ param1s = self._param1s
+ for result, index in zip(results[self._n_means:], self._param1s_index):
+ param1s[index] = result
+ sampled_values = []
+ for output_values, param1, log_likelihood in zip(
+ means, param1s, self._log_likelihoods
+ ):
+ output_values = \
+ log_likelihood.add_noise(output_values, [0, param1])
+ sampled_values.append(output_values)
+
+ return sampled_values
diff --git a/pkpdapp/pkpdapp/models/inference_results.py b/pkpdapp/pkpdapp/models/inference_results.py
new file mode 100644
index 00000000..99d7a080
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/inference_results.py
@@ -0,0 +1,197 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from pkpdapp.models import (
+ LogLikelihood,
+ Subject,
+)
+import pandas as pd
+
+
+class InferenceChain(models.Model):
+ inference = models.ForeignKey(
+ 'Inference',
+ on_delete=models.CASCADE,
+ related_name='chains',
+ help_text='inference for this chain'
+ )
+
+ def outputs_for(self, log_likelihood):
+ data = \
+ self.inference_output_results.filter(
+ log_likelihood=log_likelihood
+ ).order_by('time').values_list(
+ 'median', 'percentile_min', 'percentile_max', 'data',
+ 'time', 'subject'
+ )
+ if data:
+ (
+ medians,
+ percentile_mins,
+ percentile_maxs,
+ datas,
+ times,
+ subjects,
+ ) = list(zip(*data))
+ else:
+ medians = []
+ percentile_mins = []
+ percentile_maxs = []
+ datas = []
+ times = []
+ subjects = []
+
+ df = pd.DataFrame.from_dict({
+ 'medians': medians,
+ 'percentile_mins': percentile_mins,
+ 'percentile_maxs': percentile_maxs,
+ 'datas': datas,
+ 'times': times,
+ 'subjects': subjects,
+ })
+
+ return df
+
+ def as_pandas(self):
+ priors_values = \
+ self.inference_results.filter(
+ iteration__gt=self.inference.burn_in
+ ).order_by('iteration', 'subject').values_list(
+ 'log_likelihood', 'value', 'iteration', 'subject'
+ )
+ if priors_values:
+ priors, values, iterations, subjects = list(zip(*priors_values))
+ else:
+ priors = []
+ values = []
+ iterations = []
+ subjects = []
+ df = pd.DataFrame.from_dict({
+ 'priors': priors,
+ 'values': values,
+ 'iterations': iterations,
+ 'subjects': subjects,
+ })
+
+ return df
+
+ def function_as_pandas(self):
+ iteration_values = \
+ self.inference_function_results.filter(
+ iteration__gt=self.inference.burn_in
+ ).order_by('iteration').values_list(
+ 'value', 'iteration'
+ )
+ if iteration_values:
+ values, iterations = list(zip(*iteration_values))
+ else:
+ values = []
+ iterations = []
+ df = pd.DataFrame.from_dict({
+ 'values': values,
+ 'iterations': iterations,
+ })
+
+ return df
+
+
+class InferenceResult(models.Model):
+ """
+ Abstract class for inference results.
+ """
+ chain = models.ForeignKey(
+ InferenceChain,
+ on_delete=models.CASCADE,
+ related_name='inference_results',
+ help_text='Chain related to the row'
+ )
+ log_likelihood = models.ForeignKey(
+ LogLikelihood,
+ on_delete=models.CASCADE,
+ related_name='inference_results',
+ help_text='log_likelihood related to this result'
+ )
+ subject = models.ForeignKey(
+ Subject,
+ on_delete=models.PROTECT,
+ blank=True, null=True,
+ related_name='inference_results',
+ help_text='subject related to this result'
+ )
+ iteration = models.IntegerField(
+ help_text='Iteration'
+ )
+ value = models.FloatField(
+ help_text='estimated parameter value'
+ )
+
+
+class InferenceFunctionResult(models.Model):
+ """
+ model for logLikelihood evaluations during inference.
+ """
+ chain = models.ForeignKey(
+ InferenceChain,
+ on_delete=models.CASCADE,
+ related_name='inference_function_results',
+ help_text='Chain related to the row'
+ )
+ iteration = models.IntegerField(
+ help_text='Iteration'
+ )
+ value = models.FloatField(
+ help_text='estimated parameter value'
+ )
+
+
+class InferenceOutputResult(models.Model):
+ """
+ model for output values for a given logLikelihood.
+ """
+ log_likelihood = models.ForeignKey(
+ LogLikelihood,
+ on_delete=models.CASCADE,
+ related_name='inference_output_results',
+ help_text='log_likelihood related to the output result'
+ )
+
+ chain = models.ForeignKey(
+ InferenceChain,
+ on_delete=models.CASCADE,
+ related_name='inference_output_results',
+ help_text='Chain related to the output result'
+ )
+
+ median = models.FloatField(
+ help_text='median of output distribution'
+ )
+
+ percentile_min = models.FloatField(
+ blank=True, null=True,
+ help_text='10th percentile of output distribution'
+ )
+
+ percentile_max = models.FloatField(
+ blank=True, null=True,
+ help_text='90th percentile of output distribution'
+ )
+
+ data = models.FloatField(
+ help_text=(
+ 'data value for comparison'
+ )
+ )
+ time = models.FloatField(
+ help_text='time of output value'
+ )
+ subject = models.ForeignKey(
+ Subject,
+ on_delete=models.CASCADE,
+ blank=True, null=True,
+ related_name='inference_outputs',
+ help_text='subject of output value'
+ )
diff --git a/pkpdapp/pkpdapp/models/likelihoods.py b/pkpdapp/pkpdapp/models/likelihoods.py
new file mode 100644
index 00000000..a654cab6
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/likelihoods.py
@@ -0,0 +1,1089 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from django.db.models import Q
+import pymc3 as pm
+import theano
+import myokit
+import pints
+import numpy as np
+import scipy.stats as sps
+from pkpdapp.models import (
+ Variable,
+ BiomarkerType,
+ MyokitForwardModel,
+ Protocol,
+)
+
+
+class SolveCached:
+ def __init__(self, function):
+ self._cachedParam = None
+ self._cachedOutput = None
+ self._function = function
+
+ def __call__(self, x):
+ if np.any(x != self._cachedParam):
+ self._cachedOutput = self._function(x)
+ self._cachedParam = x
+ return self._cachedOutput
+
+
+class ODEGradop(theano.tensor.Op):
+ __props__ = ("name",)
+
+ def __init__(self, name, numpy_vsp, n_outputs):
+ self.name = name
+ self._numpy_vsp = numpy_vsp
+ self._n_outputs = n_outputs
+
+ def make_node(self, x, *gs):
+ x = theano.tensor.as_tensor_variable(x)
+ gs = [theano.tensor.as_tensor_variable(g) for g in gs]
+ node = theano.Apply(self, [x] + gs, [g.type() for g in gs])
+ return node
+
+ def perform(self, node, inputs_storage, output_storage):
+ x = inputs_storage[0]
+ outs = self._numpy_vsp(x, inputs_storage[1:]) # get the numerical VSP
+ for i in range(self._n_outputs):
+ output_storage[i][0] = outs[0]
+
+
+class ODEop(theano.tensor.Op):
+ __props__ = ("name",)
+
+ def __init__(self, name, ode_model, sensitivities=False):
+ self.name = name
+ self._ode_model = ode_model
+ self._n_outputs = ode_model.n_outputs()
+ self._output_shapes = ode_model.output_shapes()
+ if sensitivities:
+ self._cached_ode_model = SolveCached(self._ode_model.simulateS1)
+ else:
+ self._cached_ode_model = self._ode_model.simulate
+
+ if sensitivities:
+
+ def function(x):
+ (state,) = self._cached_ode_model(np.array(x, dtype=np.float64))
+ return state
+
+ else:
+
+ def function(x):
+ state = self._cached_ode_model(np.array(x, dtype=np.float64))
+ return state
+
+ self._function = function
+
+ if sensitivities:
+
+ def vjp(x, gs):
+ _, sens = self._cached_ode_model(np.array(x, dtype=np.float64))
+ return [s.T.dot(g) for s, g in zip(sens, gs)]
+
+ else:
+
+ def vjp(x, g):
+ raise NotImplementedError("sensitivities have been turned off")
+
+ self._vjp = vjp
+
+ def infer_shape(self, fgraph, node, input_shapes):
+ return self._output_shapes
+
+ def make_node(self, x):
+ x = theano.tensor.as_tensor_variable(x)
+ outputs = [theano.tensor.vector() for _ in range(self._n_outputs)]
+ return theano.tensor.Apply(self, [x], outputs)
+
+ def perform(self, node, inputs_storage, output_storage):
+ x = inputs_storage[0]
+ outs = self._function(x)
+ for i in range(self._n_outputs):
+ output_storage[i][0] = outs[i]
+
+ def grad(self, inputs, output_grads):
+ x = inputs[0]
+
+ # pass the VSP when asked for gradient
+ grad_op = ODEGradop("grad of " + self.name, self._vjp, self._n_outputs)
+ grad_op_apply = grad_op(x, *output_grads)
+
+ return [grad_op_apply]
+
+
+class LogLikelihoodParameter(models.Model):
+ """
+ each parent log_likelihood has one or more parameters, or children.
+ This model stores data on which input parameter this relationship
+ referres to
+ """
+
+ name = models.CharField(
+ max_length=100, help_text="name of log_likelihood parameter."
+ )
+ parent = models.ForeignKey(
+ "LogLikelihood", related_name="parameters", on_delete=models.CASCADE
+ )
+ parent_index = models.IntegerField(
+ blank=True,
+ null=True,
+ help_text=(
+ "parameter index for distribution and equation parameters. "
+ "blank for models (variable is used instead)"
+ ),
+ )
+ child = models.ForeignKey(
+ "LogLikelihood", related_name="outputs", on_delete=models.CASCADE
+ )
+ child_index = models.IntegerField(
+ default=0, help_text=("output index for all log_likelihoods. ")
+ )
+ variable = models.ForeignKey(
+ Variable,
+ related_name="log_likelihood_parameters",
+ blank=True,
+ null=True,
+ on_delete=models.PROTECT,
+ help_text="input model variable for this parameter.",
+ )
+ length = models.IntegerField(
+ blank=True,
+ null=True,
+ help_text=("length of array representing parameter. null for scalar"),
+ )
+
+ def set_fixed(self, value):
+ self.child.value = value
+ self.child.form = self.child.Form.FIXED
+ self.child.save()
+
+ def set_uniform_prior(self, lower, upper, biomarker_type=None):
+ child = self.child
+ child.form = child.Form.UNIFORM
+ if biomarker_type is not None:
+ child.biomarker_type = biomarker_type
+ child.time_independent_data = True
+ child.save()
+ if biomarker_type is not None:
+ _, _, subjects = child.get_data()
+ self.length = len(subjects)
+ self.save()
+ lower_param = LogLikelihoodParameter.objects.get(parent=child, parent_index=0)
+ lower_param.child.value = lower
+ lower_param.child.save()
+ upper_param = LogLikelihoodParameter.objects.get(parent=child, parent_index=1)
+ upper_param.child.value = upper
+ upper_param.child.save()
+
+
+class LogLikelihood(models.Model):
+ """
+ model class for log_likelihood functions.
+ """
+
+ inference = models.ForeignKey(
+ "Inference",
+ related_name="log_likelihoods",
+ on_delete=models.CASCADE,
+ help_text=("Log_likelihood belongs to this inference object. "),
+ )
+
+ name = models.CharField(max_length=100, help_text="name of log_likelihood.")
+
+ description = models.TextField(
+ blank=True,
+ null=True,
+ help_text=(
+ "description of log_likelihood. For equations will be the "
+ "code of that equation using Python syntax: arg1 * arg2^arg3"
+ ),
+ )
+
+ value = models.FloatField(
+ help_text="set if a fixed value is required",
+ blank=True,
+ null=True,
+ )
+
+ children = models.ManyToManyField(
+ "LogLikelihood",
+ related_name="parents",
+ symmetrical=False,
+ through=LogLikelihoodParameter,
+ through_fields=("parent", "child"),
+ )
+
+ variable = models.ForeignKey(
+ Variable,
+ related_name="log_likelihoods",
+ blank=True,
+ null=True,
+ on_delete=models.PROTECT,
+ help_text=("If form=MODEL, a variable (any) in the deterministic model. "),
+ )
+
+ biomarker_type = models.ForeignKey(
+ BiomarkerType,
+ on_delete=models.PROTECT,
+ blank=True,
+ null=True,
+ help_text=(
+ "data associated with this log_likelihood. "
+ "This is used for measurement data (observed=True) "
+ "or for covariates (observed=False). "
+ "The random variable associated with this log_likelihood "
+ "has the same shape as this data. "
+ "For covariates the subject ids in the data correspond "
+ "to the values of the random variable at that location."
+ ),
+ )
+
+ time_independent_data = models.BooleanField(
+ default=True,
+ help_text=(
+ "True if biomarker_type refers to time-independent data. "
+ "If there are multiple timepoints in biomarker_type then only "
+ "the first is taken "
+ ),
+ )
+
+ observed = models.BooleanField(
+ default=False, help_text=("True if this log_likelihood is observed ")
+ )
+
+ protocol_filter = models.ForeignKey(
+ Protocol,
+ on_delete=models.PROTECT,
+ blank=True,
+ null=True,
+ help_text=(
+ "filter subject data on this protocol" "(null implies all subjects)"
+ ),
+ )
+
+ class Form(models.TextChoices):
+ NORMAL = "N", "Normal"
+ UNIFORM = "U", "Uniform"
+ LOGNORMAL = "LN", "Log-Normal"
+ FIXED = "F", "Fixed"
+ SUM = "S", "Sum"
+ EQUATION = "E", "Equation"
+ MODEL = "M", "Model"
+
+ form = models.CharField(
+ max_length=2,
+ choices=Form.choices,
+ default=Form.FIXED,
+ )
+
+ class Meta:
+ constraints = [
+ models.CheckConstraint(
+ check=(
+ ~(
+ Q(form="F")
+ & Q(value__isnull=True)
+ & Q(biomarker_type__isnull=True)
+ )
+ ),
+ name=(
+ "%(class)s: fixed log_likelihood must have a value "
+ "or biomarker_type"
+ ),
+ ),
+ models.CheckConstraint(
+ check=(~(Q(form="M") & Q(variable__isnull=True))),
+ name=("%(class)s: model log_likelihood must have a variable"),
+ ),
+ models.CheckConstraint(
+ check=(
+ ~(
+ (Q(form="F") | Q(form="S") | Q(form="M"))
+ & Q(biomarker_type__isnull=False)
+ & Q(protocol_filter=False)
+ )
+ ),
+ name=("%(class)s: deterministic log_likelihoods cannot have data"),
+ ),
+ ]
+
+ __original_variable = None
+ __original_form = None
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ @classmethod
+ def from_db(cls, db, field_names, values):
+ instance = super().from_db(db, field_names, values)
+ # fix for infinite recursion when deleting inference
+ if "form" in field_names:
+ instance.__original_form = instance.form
+ if "variable" in field_names:
+ instance.__original_variable = instance.variable
+ return instance
+
+ def is_random(self):
+ # if fixed or is a distribution answer is easy
+ if self.form == self.Form.FIXED:
+ return False
+ if self.is_a_distribution():
+ return True
+
+ # if model or equation then need to look at the parameters to determine
+ # if random or not
+ for child in self.children.all():
+ if child.is_random():
+ return True
+
+ def is_a_distribution(self):
+ return (
+ self.form == self.Form.NORMAL
+ or self.form == self.Form.UNIFORM
+ or self.form == self.Form.LOGNORMAL
+ )
+
+ def is_a_prior(self):
+ """
+ True for distributions
+ """
+ return self.is_a_distribution() and not self.observed
+
+ def has_data(self):
+ """
+ True for distributions where there is data
+ """
+ return self.biomarker_type is not None
+
+ def sample(self):
+ # if fixed or equation just evaluate it
+ if self.form == self.Form.FIXED:
+ values, _, _ = self.get_data()
+ if values is None:
+ return self.value
+ else:
+ return values
+ elif self.form == self.Form.EQUATION:
+ params = self.get_noise_log_likelihoods()
+ param_values = [p.sample() for p in params]
+
+ args = ["arg{}".format(i) for i, _ in enumerate(param_values)]
+ args = ",".join(args)
+ code = (
+ "import numpy as np\n"
+ "def fun({}):\n"
+ " return {}\n"
+ "result = np.vectorize(fun)({})\n"
+ ).format(args, self.description, args)
+
+ lcls = {"arg{}".format(i): param for i, param in enumerate(param_values)}
+
+ exec(code, None, lcls)
+ return lcls["result"]
+
+ # otherwise must be a distribtion
+
+ # TODO: MODEL not supported
+ length = self.get_total_length()
+ # don't do an array length 1, use scalar instead
+ if length == 1:
+ length = None
+ noise_params = self.get_noise_params()
+ if self.form == self.Form.NORMAL:
+ value = np.random.normal(
+ loc=noise_params[0],
+ scale=noise_params[1],
+ size=length,
+ )
+ elif self.form == self.Form.LOGNORMAL:
+ value = np.random.lognormal(
+ mean=noise_params[0],
+ scale=noise_params[1],
+ size=length,
+ )
+ elif self.form == self.Form.UNIFORM:
+ value = np.random.uniform(
+ low=noise_params[0],
+ high=noise_params[1],
+ size=length,
+ )
+ return value
+
+ def add_noise(self, output_values, noise_params=None):
+ """
+ add noise to the simulated data according to the log_likelihood
+ """
+ if noise_params is None:
+ noise_params = self.get_noise_params()
+ if self.form == self.Form.NORMAL:
+ output_values += np.random.normal(
+ loc=noise_params[0], scale=noise_params[1], size=output_values.shape
+ )
+ elif self.form == self.Form.LOGNORMAL:
+ output_values += np.random.lognormal(
+ mean=noise_params[0], sigma=noise_params[1], size=output_values.shape
+ )
+ return output_values
+
+ def get_length_by_index(self):
+ outputs = list(self.outputs.order_by("child_index"))
+ if len(outputs) == 0:
+ n_distinct_outputs = 0
+ else:
+ n_distinct_outputs = outputs[-1].child_index + 1
+ length_by_index = [()] * n_distinct_outputs
+ for output in outputs:
+ length_by_index[output.child_index] = (
+ 1 if output.length is None else output.length
+ )
+ return length_by_index
+
+ def get_total_length(self):
+ length_by_index = self.get_length_by_index()
+ total_length = sum(length_by_index)
+ return total_length
+
+ def get_results(self, chain=None, iteration=None):
+ """
+ get inference results, respecting order of subjects
+ defined by this log_likelihood
+ """
+ return (
+ self.inference_results.filter(
+ chain=chain,
+ iteration=iteration,
+ )
+ .order_by("subject")
+ .values_list("value", flat=True)
+ )
+
+ def noise_range(self, output_values, noise_params=None):
+ """
+ return 10% and 90% noise levels from a set of output values
+ """
+ if noise_params is None:
+ noise_params = self.get_noise_params()
+ output_values_min = np.copy(output_values)
+ output_values_max = np.copy(output_values)
+ if self.form == self.Form.NORMAL:
+ for i in range(len(output_values)):
+ dist = sps.norm(
+ loc=output_values[i] + noise_params[0], scale=noise_params[1]
+ )
+ output_values_min[i] = dist.ppf(0.1)
+ output_values_max[i] = dist.ppf(0.9)
+ elif self.form == self.Form.LOGNORMAL:
+ for i in range(len(output_values)):
+ dist = sps.lognorm(
+ loc=output_values[i] + noise_params[0], scale=noise_params[1]
+ )
+ output_values_min[i] = dist.ppf(0.1)
+ output_values_max[i] = dist.ppf(0.9)
+
+ return output_values_min, output_values_max
+
+ def _create_pymc3_model(self, pm_model, parent, ops):
+ # we are a graph not a tree, so
+ # if name already in pm_model return it
+ # ode models can have multiple outputs, so make
+ # sure to choose the right one
+
+ if parent is not None:
+ param = LogLikelihoodParameter.objects.get(parent=parent, child=self)
+
+ # outputs for models are assumed to be unique and ordered
+ # by parent id, outputs for the rest can be non-unique, so use
+ # child_index in this case
+ if self.form == self.Form.MODEL:
+ parents = list(self.parents.order_by())
+ parent_index = parents.index(parent)
+ else:
+ parent_index = param.child_index
+
+ else:
+ parent_index = 0
+
+ name = self.name
+ try:
+ return ops[name][parent_index]
+ except KeyError:
+ pass
+
+ values, times, subjects = self.get_data()
+
+ outputs = list(self.outputs.order_by("child_index"))
+ if len(outputs) == 0:
+ n_distinct_outputs = 0
+ else:
+ n_distinct_outputs = outputs[-1].child_index + 1
+
+ # the distributions need a shape, take this from the data
+ # if no data then assume scalar
+ if self.is_a_distribution():
+ length_by_index = [()] * n_distinct_outputs
+ for output in outputs:
+ length_by_index[output.child_index] = (
+ 1 if output.length is None else output.length
+ )
+ total_length = sum(length_by_index)
+
+ # set shape and check total length of outputs is < this shape
+ if values is None:
+ shape = ()
+ if total_length > 1:
+ raise RuntimeError(
+ "log_likelihood {} is scalar but total length of "
+ "outputs is {}".format(self.name, total_length)
+ )
+ else:
+ shape = (len(values),)
+ if total_length > shape[0]:
+ raise RuntimeError(
+ "log_likelihood {} has data of length {} but total "
+ "length of outputs is {}".format(
+ self.name, shape[0], total_length
+ )
+ )
+ observed = values if self.observed else None
+
+ # if its not random, just evaluate it, otherwise create the pymc3 op
+ if not self.is_random():
+ value = self.sample()
+ if isinstance(value, list):
+ value = np.array(value)
+ op = theano.shared(value)
+ elif self.form == self.Form.NORMAL:
+ mean, sigma = self.get_noise_log_likelihoods()
+ mean = mean._create_pymc3_model(pm_model, self, ops)
+ sigma = sigma._create_pymc3_model(pm_model, self, ops)
+ op = pm.Normal(name, mean, sigma, observed=observed, shape=shape)
+ elif self.form == self.Form.LOGNORMAL:
+ mean, sigma = self.get_noise_log_likelihoods()
+ mean = mean._create_pymc3_model(pm_model, self, ops)
+ sigma = sigma._create_pymc3_model(pm_model, self, ops)
+ op = pm.LogNormal(name, mean, sigma, observed=observed, shape=shape)
+ elif self.form == self.Form.UNIFORM:
+ lower, upper = self.get_noise_log_likelihoods()
+ lower = lower._create_pymc3_model(pm_model, self, ops)
+ upper = upper._create_pymc3_model(pm_model, self, ops)
+ op = pm.Uniform(name, lower, upper, observed=observed, shape=shape)
+ elif self.form == self.Form.MODEL:
+ # ASSUMPTIONS / LIMITATIONS: - parents of models must be observed
+ # random variables (e.g. can't have equation to, say, measure 2 *
+ # model output - subject ids of output data, e.g. [0, 1, 2, 8, 10]
+ # are the same subjects of input data, we only check that the
+ # lengths of the subject vectors are the same
+
+ output_names = []
+ times = []
+ subjects = []
+ all_subjects = set()
+ for parent in parents:
+ output = LogLikelihoodParameter.objects.get(parent=parent, child=self)
+ _, this_times, this_subjects = parent.get_data()
+ output_names.append(output.variable.qname)
+ times.append(this_times)
+ subjects.append(this_subjects)
+ all_subjects.update(this_subjects)
+
+ all_subjects = sorted(list(all_subjects))
+ n_subjects = len(all_subjects)
+
+ # look at all parameters and check their length, if they are all
+ # scalar values then we can just run 1 sim, if any are vector
+ # values then each value is a different parameter for each subject,
+ # so we need to run a sim for every subject
+ all_params_scalar = all([p.length is None for p in self.parameters.all()])
+
+ if all_params_scalar:
+ subjects = None
+ else:
+ # transform subject ids into an index into all_subjects
+ for i, this_subjects in enumerate(subjects):
+ subjects[i] = np.searchsorted(all_subjects, this_subjects)
+
+ forward_model, fitted_parameters = self.create_forward_model(
+ output_names, times, subjects
+ )
+ forward_model_op = ODEop(name, forward_model)
+ if fitted_parameters:
+ # create child pymc3 models
+ all_params = [
+ param.child._create_pymc3_model(pm_model, self, ops)
+ for param in fitted_parameters
+ ]
+
+ # if any vector params, need to broadcast any scalars to
+ # max_length and create a 2d tensor to pass to the model with
+ # shape (n_params, max_length)
+ if not all_params_scalar:
+ max_length = max(
+ [
+ param.length if param.length is not None else 1
+ for param in fitted_parameters
+ ]
+ )
+ if max_length != n_subjects:
+ raise RuntimeError(
+ "Error: n_subjects given by params is "
+ "different to n_subjects given by output data."
+ )
+ for index in range(len(all_params)):
+ param = fitted_parameters[index]
+ pymc3_param = all_params[index]
+ if pymc3_param.ndim == 0:
+ all_params[index] = theano.tensor.tile(
+ pymc3_param, (max_length)
+ )
+
+ # now we stack them along axis 0
+ all_params = pm.math.stack(all_params, axis=0)
+ else:
+ all_params = []
+ op = forward_model_op(all_params)
+
+ # make sure its a list
+ if len(parents) == 1:
+ op = [op]
+
+ # track outputs of model so we can simulate
+ op = [
+ pm.Deterministic(name + parent.name, output)
+ for output, parent in zip(op, parents)
+ ]
+ elif self.form == self.Form.EQUATION:
+ params = self.get_noise_log_likelihoods()
+ pymc3_params = []
+ for param in params:
+ param = param._create_pymc3_model(pm_model, self, ops)
+ pymc3_params.append(param)
+ lcls = {"arg{}".format(i): param for i, param in enumerate(pymc3_params)}
+ op = eval(self.description, None, lcls)
+ elif self.form == self.Form.FIXED:
+ if self.biomarker_type is None:
+ op = theano.shared(self.value)
+ else:
+ op = theano.shared(np.array(values))
+ else:
+ raise RuntimeError("unrecognised form", self.form)
+
+ # split the op into its distinct outputs
+ if self.form == self.Form.MODEL:
+ ops[name] = op
+ elif n_distinct_outputs == 1:
+ ops[name] = [op]
+ else:
+ indexed_list = []
+ current_index = 0
+ for length in length_by_index:
+ indexed_list.append(op[current_index : current_index + length])
+ ops[name] = indexed_list
+
+ # if no parent then we don't need to return anything
+ if parent is None:
+ return None
+ return ops[name][parent_index]
+
+ def create_pymc3_model(self, *other_log_likelihoods):
+ ops = {}
+ with pm.Model() as pm_model:
+ self._create_pymc3_model(pm_model, None, ops)
+ for ll in other_log_likelihoods:
+ ll._create_pymc3_model(pm_model, None, ops)
+ return pm_model
+
+ def create_forward_model(self, output_names, output_times, output_subjects=None):
+ """
+ create pints forwards model for this log_likelihood.
+ """
+ model = self.get_model()
+ myokit_model = model.get_myokit_model()
+ print(myokit_model.code())
+ myokit_simulator = model.get_myokit_simulator()
+
+ fixed_parameters_dict = {
+ param.variable.qname: param.child.value
+ for param in self.parameters.all()
+ if (not param.child.is_random() and param.variable is not None)
+ }
+
+ conversion_factors = []
+ for name in output_names:
+ variable = model.variables.get(qname=name)
+ myokit_variable_sbml = myokit_model.get(name)
+
+ conversion_factor = myokit.Unit.conversion_factor(
+ myokit_variable_sbml.unit(), variable.unit.get_myokit_unit()
+ ).value()
+
+ conversion_factors.append(conversion_factor)
+
+ pints_model = MyokitForwardModel(
+ myokit_simulator,
+ myokit_model,
+ output_names,
+ conversion_factors,
+ output_times,
+ output_subjects,
+ fixed_parameters_dict,
+ )
+
+ fitted_parameters = [
+ self.get_param(name) for name in pints_model.variable_parameter_names()
+ ]
+
+ return pints_model, fitted_parameters
+
+ def get_param(self, qname):
+ param = LogLikelihoodParameter.objects.get(parent=self, variable__qname=qname)
+ return param
+
+ def filter_data_by_protocol(self, df):
+ """
+ filter data by categorical data
+ """
+ if df is None:
+ return None
+ if self.protocol_filter is None:
+ return df
+ else:
+ filtered_subjects = self.protocol_filter.subjects.values_list(
+ "id", flat=True
+ )
+ return df.loc[df["subjects"].isin(filtered_subjects)]
+
+ def get_data(self, fake=False):
+ """
+ return data. if fake=True and no data return
+ some fake times
+ """
+ if self.biomarker_type:
+ df = self.filter_data_by_protocol(
+ self.biomarker_type.data(first_time_only=self.time_independent_data)
+ )
+
+ if df is None or len(df) == 0:
+ return None, None, None
+
+ return (
+ df["values"].tolist(),
+ df["times"].tolist(),
+ df["subjects"].tolist(),
+ )
+ else:
+ return None, None, None
+
+ def get_noise_names(self):
+ """
+ get ordered list of noise log_likelihoods
+ """
+ noise_parameters = self.parameters.filter(
+ parent_index__isnull=False,
+ ).order_by("parent_index")
+
+ return [p.name for p in noise_parameters]
+
+ def get_noise_log_likelihoods(self):
+ """
+ get ordered list of noise log_likelihoods
+ """
+ noise_parameters = self.parameters.filter(
+ parent_index__isnull=False,
+ ).order_by("parent_index")
+
+ return [p.child for p in noise_parameters]
+
+ def get_noise_params(self):
+ """
+ get ordered list of noise param values
+ if any noise params have a prior on them then
+ this is sampled
+ """
+ return [child.sample() for child in self.get_noise_log_likelihoods()]
+
+ def create_pints_transform(self):
+ if False:
+ return pints.LogTransformation(n_parameters=1)
+ else:
+ return pints.IdentityTransformation(n_parameters=1)
+
+ def create_pints_prior(self):
+ noise_parameters = self.get_noise_params()
+ if self.form == self.Form.UNIFORM:
+ lower = noise_parameters[0]
+ upper = noise_parameters[1]
+ pints_log_prior = pints.UniformLogPrior(lower, upper)
+ elif self.form == self.Form.NORMAL:
+ mean = noise_parameters[0]
+ sd = noise_parameters[1]
+ pints_log_prior = pints.GaussianLogPrior(mean, sd)
+ return pints_log_prior
+
+ def create_pints_problem(self):
+ values, times, subjects = self.get_data()
+ model, fitted_children = self.create_pints_forward_model()
+ return pints.SingleOutputProblem(model, times, values), fitted_children
+
+ def create_pints_log_likelihood(self):
+ problem, fitted_children = self.create_pints_problem()
+ if self.form == self.Form.NORMAL:
+ noise_param = self.parameters.get(index=1)
+ if noise_param.child.form == noise_param.child.Form.FIXED:
+ value = noise_param.value
+ return (
+ pints.GaussianKnownSigmaLogLikelihood(problem, value),
+ fitted_children,
+ )
+ else:
+ return pints.GaussianLogLikelihood(problem), fitted_children + [
+ noise_param.child
+ ]
+ elif self.form == LogLikelihood.Form.LOGNORMAL:
+ noise_param = self.parameters.get(index=1)
+ return pints.LogNormalLogLikelihood(problem), fitted_children + [
+ noise_param.child
+ ]
+
+ raise RuntimeError("unknown log_likelihood form")
+
+ def get_model(self, variable=None):
+ """
+ if this is a log_likelihood that includes a mechanistic model
+ this model is returned, else None
+ """
+ if self.form != self.Form.MODEL:
+ return None
+ if variable is None:
+ return self.variable.get_model()
+ else:
+ return variable.get_model()
+
+ def get_model_variables(self):
+ """
+ if this is a log_likelihood that includes a mechanistic model
+ return a list of model parameters, else return []
+ """
+ model = self.get_model()
+ if model is None:
+ return []
+ else:
+ return model.variables.filter(Q(constant=True) | Q(state=True)).exclude(
+ name="time"
+ )
+
+ def get_model_outputs(self):
+ """
+ if this is a log_likelihood that includes a mechanistic model
+ return a list of model parameters, else return []
+ """
+ model = self.get_model()
+ if model is None:
+ return []
+ else:
+ return model.variables.filter(Q(constant=False)).exclude(name="time")
+
+ def save(self, force_insert=False, force_update=False, *args, **kwargs):
+ created = not self.pk
+
+ set_defaults = (
+ created
+ or self.get_model() != self.get_model(self.__original_variable)
+ or self.form != self.__original_form
+ )
+
+ if set_defaults:
+ if self.form == self.Form.MODEL:
+ self.name = self.variable.get_model().name
+
+ super().save(force_insert, force_update, *args, **kwargs)
+
+ # if the model or form is changed regenerate
+ # default children and parents
+ if set_defaults:
+ for child in self.children.all():
+ # make sure we don't delete models from children
+ if child.form != self.Form.MODEL:
+ child.delete()
+ if self.form == self.Form.MODEL:
+ for parent in self.parents.all():
+ parent.delete()
+ self.create_model_family()
+ if self.form == self.Form.EQUATION:
+ # save() is not responsible for generating
+ # equation children
+ pass
+ else: # a distribution
+ self.create_noise_children()
+
+ self.__original_variable = self.variable
+ self.__original_form = self.form
+
+ def create_model_family(self):
+ for model_variable in self.get_model_variables():
+ if not model_variable.constant:
+ continue
+ name = model_variable.qname
+ child = LogLikelihood.objects.create(
+ name=name,
+ inference=self.inference,
+ value=model_variable.get_default_value(),
+ variable=model_variable,
+ form=self.Form.FIXED,
+ )
+ LogLikelihoodParameter.objects.create(
+ parent=self,
+ child=child,
+ variable=model_variable,
+ name=model_variable.qname,
+ )
+
+ for i, model_variable in enumerate(self.get_model_outputs()):
+ parent = LogLikelihood.objects.create(
+ name=model_variable.qname,
+ inference=self.inference,
+ variable=model_variable,
+ form=self.Form.NORMAL,
+ time_independent_data=False,
+ )
+ # add the output_model
+ mean_param = parent.parameters.get(parent_index=0)
+ old_mean = mean_param.child
+ mean_param.child = self
+ old_mean.delete()
+ mean_param.name = model_variable.qname
+ mean_param.variable = model_variable
+ mean_param.save()
+
+ def create_noise_children(self):
+ # distribution parameters
+ variable = None
+ if self.variable:
+ variable = self.variable
+ elif self.outputs.count() > 0:
+ first_output = self.outputs.first()
+ if first_output.variable:
+ variable = first_output.variable
+ elif first_output.parent.variable:
+ variable = first_output.parent.variable
+ elif self.parameters.count() > 0:
+ for param in self.parameters.all():
+ if param.variable:
+ variable = param.variable
+
+ if self.form == self.Form.NORMAL:
+ names = [
+ "mean for " + self.name,
+ "standard deviation for " + self.name,
+ ]
+
+ if variable is not None:
+ mean = variable.get_default_value()
+ if (
+ variable.lower_bound is not None
+ and variable.upper_bound is not None
+ ):
+ sigma = 0.1 * (variable.upper_bound - variable.lower_bound)
+ else:
+ sigma = 0.1 * mean
+ defaults = [
+ mean,
+ sigma,
+ ]
+ else:
+ defaults = [0.0, 1.0]
+ elif self.form == self.Form.LOGNORMAL:
+ names = [
+ "mean for " + self.name,
+ "sigma for " + self.name,
+ ]
+
+ if variable is not None:
+ mean = variable.get_default_value()
+ if (
+ variable.lower_bound is not None
+ and variable.upper_bound is not None
+ ):
+ sigma = 0.1 * (variable.upper_bound - variable.lower_bound)
+ else:
+ sigma = 0.1 * mean
+ defaults = [
+ mean,
+ sigma,
+ ]
+ else:
+ defaults = [0.0, 1.0]
+ elif self.form == self.Form.UNIFORM:
+ names = [
+ "lower for " + self.name,
+ "upper for " + self.name,
+ ]
+
+ if variable is not None:
+ if variable.lower_bound is not None:
+ lower = variable.lower_bound
+ else:
+ lower = 0.1 * variable.get_default_value()
+ if variable.upper_bound is not None:
+ upper = variable.upper_bound
+ else:
+ upper = 10.0 * variable.get_default_value()
+ defaults = [
+ lower,
+ upper,
+ ]
+ else:
+ defaults = [0.0, 1.0]
+ else:
+ names = []
+ defaults = []
+ for param_index, (name, default) in enumerate(zip(names, defaults)):
+ child = LogLikelihood.objects.create(
+ name=name,
+ inference=self.inference,
+ value=default,
+ form=self.Form.FIXED,
+ )
+ LogLikelihoodParameter.objects.create(
+ parent=self,
+ child=child,
+ parent_index=param_index,
+ name=name,
+ )
+
+ def create_stored_log_likelihood(self, inference, new_models):
+ """
+ create stored log_likelihood, ignoring children for now
+ """
+ print("create_stored_log_likelihood", self.name)
+ new_variable = None
+ if self.variable is not None:
+ old_model = self.variable.get_model()
+ new_model = new_models[old_model.id]
+ variable_qname = self.variable.qname
+
+ new_variable = new_model.variables.get(qname=variable_qname)
+
+ stored_log_likelihood_kwargs = {
+ "inference": inference,
+ "name": self.name,
+ "value": self.value,
+ "variable": new_variable,
+ "biomarker_type": self.biomarker_type,
+ "observed": self.observed,
+ "protocol_filter": self.protocol_filter,
+ "form": self.form,
+ }
+
+ # this will create default children
+ stored_log_likelihood = LogLikelihood.objects.create(
+ **stored_log_likelihood_kwargs
+ )
+
+ return stored_log_likelihood
diff --git a/pkpdapp/pkpdapp/models/mechanistic_model.py b/pkpdapp/pkpdapp/models/mechanistic_model.py
new file mode 100644
index 00000000..74c97d40
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/mechanistic_model.py
@@ -0,0 +1,66 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from django.core.exceptions import ValidationError
+from pkpdapp.models import MyokitModelMixin
+
+
+class MechanisticModel(models.Model, MyokitModelMixin):
+ """
+ A PK or PD model, represented using mmt
+ """
+
+ DEFAULT_MMT = "[[model]]\n" "\n" "[myokit]\n" "time = 0 bind time"
+
+ DEFAULT_SBML = (
+ ''
+ ""
+ ''
+ " "
+ " "
+ )
+
+ name = models.CharField(max_length=100, help_text="name of the model")
+ description = models.TextField(
+ help_text="short description of the model", blank=True, default=""
+ )
+ mmt = models.TextField(
+ help_text=(
+ "the model represented using mmt " "(see https://myokit.readthedocs)"
+ ),
+ default=DEFAULT_MMT,
+ )
+ time_max = models.FloatField(
+ default=30,
+ help_text=(
+ "suggested maximum time to simulate for this model (in the time "
+ "units specified by the mmt model)"
+ ),
+ )
+
+ is_library_model = models.BooleanField(
+ default=False,
+ help_text=(
+ "whether this model is a library model (i.e. it is not an "
+ "uploaded user model)"
+ ),
+ )
+
+ class Meta:
+ abstract = True
+
+ def __str__(self):
+ return str(self.name)
+
+ def clean(self):
+ try:
+ self.create_myokit_model()
+ except Exception as e:
+ raise ValidationError({"mmt": str(e)})
diff --git a/pkpdapp/pkpdapp/models/myokit_forward_model.py b/pkpdapp/pkpdapp/models/myokit_forward_model.py
new file mode 100644
index 00000000..9915a67f
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/myokit_forward_model.py
@@ -0,0 +1,332 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import numpy as np
+from sys import float_info
+
+
+class MyokitForwardModel():
+ """
+ Arguments:
+ myokit_model -- a Myokit model.
+ myokit_simulator -- a Myokit simulator.
+ outputs -- a list of strings representing output names
+ times -- a list of ndarrays representing times for each output
+ representing state names in model
+ subjects(=None by default) -- a list of lists of subject ids (0 -> max
+ number of subjects) with the same shape as times, if not None then a
+ simulation will be run for every individual subject and values written
+ out according to this array, if None then only one simulation will be
+ run and then broadcast according to times
+ representing key-value pairs for fixed parameters
+ fixed_parameter_dict(=None by default) -- a dictionary
+ representing key-value pairs for fixed parameters
+ """
+
+ def __init__(
+ self, myokit_simulator, myokit_model,
+ outputs, conversion_factors, times, subjects=None,
+ fixed_parameter_dict=None
+ ):
+ model = myokit_model
+ self._sim = myokit_simulator
+ self._sim.set_tolerance(abs_tol=1e-11, rel_tol=1e-9)
+
+ # get all model states that will be used for inference
+ self._n_states = model.count_states()
+
+ # get initial conditions
+ self._output_names = [
+ var.qname() for var in model.variables(const=False)
+ ]
+
+ self._times = [np.array(t) for t in times]
+ if subjects is None:
+ self._subjects = subjects
+ else:
+ self._subjects = [np.array(s) for s in subjects]
+
+ self._n_subjects = None
+
+ # if we are dealing with subjects split the times according to subject
+ if self._subjects is not None:
+ self._n_subjects = max(
+ [np.max(s_array) for s_array in self._subjects]
+ ) + 1
+ print('n_subjects', self._n_subjects, self._subjects)
+ self._times_all = []
+ self._output_indices = []
+ for s in range(self._n_subjects):
+ times_by_subject = [
+ t_array[s_array == s]
+ for t_array, s_array in zip(self._times, self._subjects)
+ ]
+ self._times_all.append(
+ np.sort(list(set(np.concatenate(times_by_subject))))
+ )
+ self._output_indices.append([
+ np.searchsorted(self._times_all[-1], t)
+ for t in times_by_subject
+ ])
+
+ # if not then just make sure we can map from all times back to output
+ # times
+ else:
+ self._times_all = np.sort(list(set(np.concatenate(self._times))))
+ self._output_indices = [
+ np.searchsorted(self._times_all, t)
+ for t in self._times
+ ]
+
+ self._state_names = [
+ var.qname() for var in model.states()
+ ]
+
+ outputs_not_in_model = (
+ [v not in self._output_names for v in outputs]
+ )
+ if any(outputs_not_in_model):
+ raise ValueError(
+ 'All outputs must be within model. Outputs are:', outputs,
+ '. Outputs in the model are:', self._output_names
+ )
+ self._output_names = outputs
+ self._conversion_factor = {
+ name: conversion_factor
+ for name, conversion_factor in zip(outputs, conversion_factors)
+ }
+ self._n_outputs = len(outputs)
+
+ # find fixed and variable parameters
+ self._const_names = [
+ var.qname() for var in model.variables(const=True)
+ ]
+
+ # parameters are all const variables
+ self._all_parameter_names = self._const_names
+ self._n_all_parameters = len(self._all_parameter_names)
+
+ if fixed_parameter_dict is None:
+ self._fixed_parameter_dict = None
+ self._fixed_parameter_names = None
+ self._fixed_parameter_indices = None
+ self._variable_parameter_names = self._all_parameter_names
+ self._n_parameters = len(self._variable_parameter_names)
+ else:
+ if self._n_all_parameters < len(fixed_parameter_dict):
+ raise ValueError(
+ 'Number of fixed parameters must be fewer'
+ 'than total number of model parameters.'
+ )
+ fparams_not_in_model_params = [p not in self._all_parameter_names
+ for p
+ in fixed_parameter_dict.keys()]
+ if any(fparams_not_in_model_params):
+ raise ValueError(
+ 'All fixed parameter keys must correspond '
+ 'with model keys.'
+ )
+ self._fixed_parameter_dict = fixed_parameter_dict
+ self._fixed_parameter_names = list(fixed_parameter_dict.keys())
+ self._fixed_parameter_list = [
+ self._fixed_parameter_dict[name]
+ for name in self._fixed_parameter_names
+ ]
+ self._variable_parameter_names = [
+ x for x in self._all_parameter_names
+ if x not in self._fixed_parameter_names
+ ]
+ self._n_parameters = len(self._variable_parameter_names)
+ self._fixed_parameter_indices = [
+ self._all_parameter_names.index(v)
+ for v in self._fixed_parameter_names
+ ]
+
+ self._variable_parameter_indices = [
+ self._all_parameter_names.index(v)
+ for v in self._variable_parameter_names
+ ]
+
+ def n_outputs(self):
+ """
+ Returns the number of output dimensions.
+ By default this is the number of states.
+ """
+ return self._n_outputs
+
+ def n_parameters(self):
+ """
+ Returns the number of parameters in the model.
+ Parameters of the model are initial state values and structural
+ parameter values.
+ """
+ return self._n_parameters
+
+ def _set_const(self, parameters):
+ """
+ Sets values of constant model parameters.
+ """
+ for id_var, var in enumerate(self._const_names):
+ self._sim.set_constant(var, float(parameters[id_var]))
+
+ def _set_init(self, parameters):
+ """
+ Sets initial conditions of model.
+ """
+ model = self._sim._model
+ for id_var, var in enumerate(self._const_names):
+ model.get(var).set_rhs(float(parameters[id_var]))
+ states = model.initial_values(as_floats=True)
+
+ self._sim.set_state(states)
+
+ def simulate(self, parameters):
+ """
+ Returns the numerical solution of the model outputs for specified
+ parameters. Note, the parameter inputs should be ordered as
+ in `variable_parameter_names()`.
+
+ parameters should be 1d if self._subjects is None, 2d if self._subjects
+ is not None, with shape (n_parameters, n_subjects)
+ """
+ parameters = np.array(parameters)
+
+ if self._subjects is None and parameters.ndim != 1:
+ raise ValueError(
+ 'no subjects provided, but parameters shape is {}'.format(
+ parameters.shape
+ )
+ )
+
+ if self._subjects is not None and parameters.ndim != 2:
+ raise ValueError(
+ 'subjects provided, but parameters shape is {}'.format(
+ parameters.shape
+ )
+ )
+
+ if parameters.shape[0] != self._n_parameters:
+ raise ValueError('Dim 0 of parameters supplied must equal ' +
+ 'number of non-fixed model parameters.')
+
+ if (
+ self._subjects is not None and
+ parameters.shape[1] != self._n_subjects
+ ):
+ raise ValueError('Dim 1 of of parameters supplied must equal ' +
+ 'number of subjects.')
+
+ if self._subjects is None:
+ # ensure order of parameters works
+ if self._fixed_parameter_dict is None:
+ full_parameters = parameters
+ else:
+ full_parameters = np.empty((self._n_all_parameters))
+
+ # fill up parameter vector with fixed and variable values
+ for count, idx in enumerate(self._fixed_parameter_indices):
+ full_parameters[idx] = self._fixed_parameter_list[count]
+ for count, idx in enumerate(self._variable_parameter_indices):
+ full_parameters[idx] = parameters[count]
+
+ # Reset simulation
+ self._sim.reset()
+
+ # Set constant model parameters
+ self._set_const(full_parameters)
+
+ # Set initial conditions
+ self._set_init(full_parameters)
+
+ # Simulate: need +100*epsilon for times to ensure simulation
+ # surpasses last time
+ t_max = self._times_all[-1] + 1e2 * float_info.epsilon
+ log_times = self._times_all
+ output = self._sim.run(
+ t_max,
+ log=self._output_names, log_times=log_times
+ )
+
+ output = self._convert_units(output)
+
+ result = [
+ np.array(output[name])[indices]
+ for name, indices in zip(
+ self._output_names,
+ self._output_indices
+ )
+ ]
+ else:
+ # ensure order of parameters works
+ if self._fixed_parameter_dict is None:
+ full_parameters = parameters
+ else:
+ full_parameters = np.empty((self._n_all_parameters,
+ self._n_subjects))
+
+ # fill up parameter vector with fixed and variable values
+ for count, idx in enumerate(self._fixed_parameter_indices):
+ full_parameters[idx, :] = self._fixed_parameter_list[count]
+ for count, idx in enumerate(self._variable_parameter_indices):
+ full_parameters[idx, :] = parameters[count, :]
+
+ # preallocate results
+ result = [
+ np.empty_like(t) for t in self._times
+ ]
+ for s in range(self._n_subjects):
+ # Reset simulation
+ self._sim.reset()
+
+ # Set constant model parameters
+ self._set_const(full_parameters[:, s])
+
+ # Set initial conditions
+ self._set_init(full_parameters[:, s])
+
+ # Simulate: need +100*epsilon for times to ensure simulation
+ # surpasses last time
+ t_max = self._times_all[s][-1] + 1e2 * float_info.epsilon
+ log_times = self._times_all[s]
+ output = self._sim.run(
+ t_max,
+ log=self._output_names, log_times=log_times
+ )
+
+ output = self._convert_units(output)
+
+ # scatter this subject's output across result according to
+ # output_indices
+ for output_index, (name, indices, subjects) in enumerate(zip(
+ self._output_names,
+ self._output_indices[s],
+ self._subjects,
+ )):
+ result[output_index][s == subjects] = \
+ np.array(output[name])[indices]
+
+ return result
+
+ def _convert_units(self, output):
+ for key, value in output.items():
+ output[key] = self._conversion_factor[key] * np.frombuffer(value)
+ return output
+
+ def output_names(self):
+ """ Returns outputs of model. """
+ return self._output_names
+
+ def output_shapes(self):
+ """ Returns outputs of model. """
+ return [t.shape for t in self._times]
+
+ def variable_parameter_names(self):
+ """ The order expected for parameter inputs to simulate. """
+ return self._variable_parameter_names
+
+ def fixed_parameter_names(self):
+ """ The fixed parameters of model. """
+ return self._fixed_parameter_names
diff --git a/pkpdapp/pkpdapp/models/myokit_model_mixin.py b/pkpdapp/pkpdapp/models/myokit_model_mixin.py
new file mode 100644
index 00000000..9f824b3a
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/myokit_model_mixin.py
@@ -0,0 +1,674 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pkpdapp
+import numpy as np
+from myokit.formats.mathml import MathMLExpressionWriter
+from myokit.formats.sbml import SBMLParser
+import myokit
+import threading
+from django.core.cache import cache
+import logging
+
+logger = logging.getLogger(__name__)
+
+lock = threading.Lock()
+
+
+class MyokitModelMixin:
+ def _get_myokit_model_cache_key(self):
+ return "myokit_model_{}_{}".format(self._meta.db_table, self.id)
+
+ def _get_myokit_simulator_cache_key(self):
+ return "myokit_simulator_{}_{}".format(self._meta.db_table, self.id)
+
+ @staticmethod
+ def sbml_string_to_mmt(sbml):
+ model = MyokitModelMixin.parse_sbml_string(sbml)
+ return model.code()
+
+ @staticmethod
+ def parse_sbml_string(sbml):
+ with lock:
+ model = SBMLParser().parse_string(str.encode(sbml)).myokit_model()
+ return model
+
+ @staticmethod
+ def parse_mmt_string(mmt):
+ with lock:
+ model, _, _ = myokit.parse(mmt)
+ return model
+
+ def create_myokit_model(self):
+ return self.parse_mmt_string(self.mmt)
+
+ def create_myokit_simulator(self, override_tlag=None, model=None, time_max=None):
+ if override_tlag is None:
+ override_tlag = {}
+
+ if model is None:
+ model = self.get_myokit_model()
+
+ from pkpdapp.models import Variable
+
+ if override_tlag is None:
+ try:
+ tlag_value = self.variables.get(
+ qname="PKCompartment.tlag"
+ ).default_value
+ except Variable.DoesNotExist:
+ tlag_value = 0.0
+ else:
+ tlag_value = override_tlag
+
+ # add a dose_rate variable to the model for each
+ # dosed variable
+ for v in self.variables.filter(state=True):
+ if v.protocol:
+ myokit_v = model.get(v.qname)
+ set_administration(model, myokit_v)
+
+ protocols = {}
+ project = self.get_project()
+ if project is None:
+ compound = None
+ else:
+ compound = project.compound
+ for v in self.variables.filter(state=True):
+ if v.protocol:
+ # get tlag value default to 0
+ derived_param = v.qname + "_tlag_ud"
+ try:
+ tlag_value = self.variables.get(qname=derived_param).default_value
+ except Variable.DoesNotExist:
+ tlag_value = 0.0
+
+ # override tlag if set
+ if v.qname in override_tlag:
+ tlag_value = override_tlag[v.qname]
+
+ amount_var = model.get(v.qname)
+ time_var = model.binding("time")
+
+ is_target = False
+ if self.is_library_model:
+ is_target = "CT1" in v.qname or "AT1" in v.qname
+
+ amount_conversion_factor = v.protocol.amount_unit.convert_to(
+ amount_var.unit(), compound=compound, is_target=is_target
+ )
+
+ time_conversion_factor = v.protocol.time_unit.convert_to(
+ time_var.unit(), compound=compound
+ )
+
+ dosing_events = []
+ last_dose_time = tlag_value
+ for d in v.protocol.doses.all():
+ if d.repeat_interval <= 0:
+ continue
+ start_times = np.arange(
+ d.start_time + last_dose_time,
+ d.start_time + last_dose_time + d.repeat_interval * d.repeats,
+ d.repeat_interval,
+ )
+ if len(start_times) == 0:
+ continue
+ last_dose_time = start_times[-1]
+ dosing_events += [
+ (
+ (amount_conversion_factor / time_conversion_factor)
+ * (d.amount / d.duration),
+ time_conversion_factor * start_time,
+ time_conversion_factor * d.duration,
+ )
+ for start_time in start_times
+ ]
+ # if any dosing events are close to time_max,
+ # make them equal to time_max
+ if time_max is not None:
+ for i, (level, start, duration) in enumerate(dosing_events):
+ if abs(start - time_max) < 1e-6:
+ dosing_events[i] = (level, time_max, duration)
+ elif abs(start + duration - time_max) < 1e-6:
+ dosing_events[i] = (level, start, time_max - start)
+ protocols[_get_pacing_label(amount_var)] = get_protocol(dosing_events)
+
+ with lock:
+ sim = myokit.Simulation(model, protocol=protocols)
+ return sim
+
+ def get_myokit_simulator(self):
+ key = self._get_myokit_simulator_cache_key()
+ with lock:
+ myokit_simulator = cache.get(key)
+ if myokit_simulator is None:
+ myokit_simulator = self.create_myokit_simulator()
+ cache.set(key, myokit_simulator, timeout=None)
+ return myokit_simulator
+
+ def get_myokit_model(self):
+ key = self._get_myokit_model_cache_key()
+ with lock:
+ myokit_model = cache.get(key)
+ if myokit_model is None:
+ myokit_model = self.create_myokit_model()
+ cache.set(key, myokit_model, timeout=None)
+ return myokit_model
+
+ def is_variables_out_of_date(self):
+ model = self.get_myokit_model()
+
+ # just check if the number of const variables is right
+ # TODO: is this sufficient, we are also updating on save
+ # so I think it should be ok....?
+ all_const_variables = self.variables.filter(constant=True)
+ myokit_variable_count = sum(1 for _ in model.variables(const=True, sort=True))
+ # check if variables need updating
+ return len(all_const_variables) != myokit_variable_count
+
+ def update_simulator(self):
+ # delete simulator from cache
+ cache.delete(self._get_myokit_simulator_cache_key())
+
+ def update_model(self):
+ logger.info("UPDATE MODEL")
+ # delete model and simulators from cache
+ cache.delete(self._get_myokit_simulator_cache_key())
+ cache.delete(self._get_myokit_model_cache_key())
+
+ # update the variables of the model
+ from pkpdapp.models import Variable
+
+ removed_variables = []
+ if self.is_library_model:
+ removed_variables += [
+ "PKCompartment.b_term",
+ "PKCompartment.c_term",
+ ]
+ if not getattr(self, "has_saturation", True):
+ removed_variables += ["PKCompartment.Km", "PKCompartment.CLmax"]
+ if not getattr(self, "has_effect", True):
+ removed_variables += [
+ "PKCompartment.Ce",
+ "PKCompartment.AUCe",
+ "PKCompartment.ke0",
+ "PKCompartment.Kpu",
+ "PKCompartment.Kp",
+ ]
+ if not getattr(self, "has_hill_coefficient", True):
+ removed_variables += ["PDCompartment.HC"]
+ # tlag now on per variable basis
+ removed_variables += ["PKCompartment.tlag"]
+ if not getattr(self, "has_bioavailability", True):
+ removed_variables += ["PKCompartment.F"]
+
+ model = self.get_myokit_model()
+ new_variables = [
+ Variable.get_variable(self, v)
+ for v in model.variables(const=True, sort=True)
+ if v.is_literal() and v.qname() not in removed_variables
+ ]
+
+ # parameters could originally be outputs
+ for v in new_variables:
+ if not v.constant:
+ v.constant = True
+ v.save()
+ new_states = [
+ Variable.get_variable(self, v)
+ for v in model.variables(state=True, sort=True)
+ if v.qname() not in removed_variables
+ ]
+ new_outputs = [
+ Variable.get_variable(self, v)
+ for v in model.variables(const=False, state=False, sort=True)
+ if v.qname() not in removed_variables
+ ]
+ logger.debug("ALL NEW OUTPUTS")
+ for v in new_outputs:
+ if v.unit is not None:
+ logger.debug(
+ f"{v.qname} [{v.unit.symbol}], "
+ f"id = {v.id} constant = {v.constant}, "
+ f"state = {v.state}"
+ )
+ else:
+ logger.debug(
+ f"{v.qname}, id = {v.id} "
+ f"constant = {v.constant}, "
+ f"state = {v.state}"
+ )
+
+ for v in new_outputs:
+ # if output not in states set state false
+ # so only states with initial conditions as
+ # parameters will have state set to true
+ if v not in new_states and v.state is True:
+ v.state = False
+ v.save()
+
+ # parameters could originally be variables
+ if v.constant:
+ v.constant = False
+ v.save()
+
+ all_new_variables = new_variables + new_states + new_outputs
+ logger.debug("ALL NEW VARIABLES")
+ for v in all_new_variables:
+ if v.unit is not None:
+ logger.debug(
+ f"{v.qname} [{v.unit.symbol}], id = {v.id} "
+ f"constant = {v.constant}, state = {v.state}"
+ )
+ else:
+ logger.debug(
+ f"{v.qname}, id = {v.id} "
+ f"constant = {v.constant}, state = {v.state}"
+ )
+
+ # for library models: set new variables to defaults
+ if self.is_library_model and hasattr(self, "reset_params_to_defaults"):
+ project = self.get_project()
+ if project is not None:
+ species = project.species
+ compound_type = project.compound.compound_type
+ self.reset_params_to_defaults(species, compound_type, all_new_variables)
+
+ # delete all variables that are not in new
+ for variable in self.variables.all():
+ if variable not in all_new_variables:
+ logger.debug(f"DELETING VARIABLE {variable.qname} (id = {variable.id})")
+ variable.delete()
+ else:
+ logger.debug(
+ f"RETAINING VARIABLE {variable.qname} (id = {variable.id}, value = {variable.default_value})" # noqa: E501
+ )
+
+ self.variables.set(all_new_variables)
+
+ def set_variables_from_inference(self, inference):
+ results_for_mle = inference.get_maximum_likelihood()
+ for result in results_for_mle:
+ inference_var = result.log_likelihood.outputs.first().variable
+ # noise variables won't have a model variable
+ if inference_var is not None:
+ model_var = self.variables.filter(qname=inference_var.qname).first()
+ else:
+ model_var = None
+ if model_var is not None:
+ model_var.default_value = result.value
+ if (
+ model_var.lower_bound
+ and model_var.lower_bound > model_var.default_value
+ ):
+ model_var.lower_bound = model_var.default_value
+ if (
+ model_var.upper_bound
+ and model_var.upper_bound < model_var.default_value
+ ):
+ model_var.upper_bound = model_var.default_value
+ model_var.save()
+
+ @staticmethod
+ def _serialise_equation(equ):
+ writer = MathMLExpressionWriter()
+ writer.set_mode(presentation=True)
+ return writer.eq(equ)
+
+ @staticmethod
+ def _serialise_variable(var):
+ return {
+ "name": var.name(),
+ "qname": var.qname(),
+ "unit": str(var.unit()),
+ "default_value": float(var.value()),
+ "lower_bound": 0.0,
+ "upper_bound": 2.0,
+ "scale": "LN",
+ }
+
+ @classmethod
+ def _serialise_component(cls, c):
+ states = [
+ cls._serialise_variable(s) for s in c.variables(state=True, sort=True)
+ ]
+ variables = [
+ cls._serialise_variable(v) for v in c.variables(const=True, sort=True)
+ ]
+ outputs = [
+ cls._serialise_variable(o) for o in c.variables(const=False, sort=True)
+ ]
+ equations = [
+ cls._serialise_equation(e) for e in c.equations(bound=False, const=False)
+ ]
+ return {
+ "name": c.name(),
+ "states": states,
+ "variables": variables,
+ "outputs": outputs,
+ "equations": equations,
+ }
+
+ def states(self):
+ """states are dependent variables of the model to be solved"""
+ model = self.get_myokit_model()
+ states = model.variables(state=True, sort=True)
+ return [self._serialise_variable(s) for s in states]
+
+ def components(self):
+ """
+ outputs are dependent (e.g. y) and independent (e.g. time)
+ variables of the model to be solved
+ """
+ model = self.get_myokit_model()
+ return [self._serialise_component(c) for c in model.components(sort=True)]
+
+ def outputs(self):
+ """
+ outputs are dependent (e.g. y) and independent (e.g. time)
+ variables of the model to be solved
+ """
+ model = self.get_myokit_model()
+ outpts = model.variables(const=False, sort=True)
+ return [self._serialise_variable(o) for o in outpts]
+
+ def myokit_variables(self):
+ """
+ variables are independent variables of the model that are constant
+ over time. aka parameters of the model
+ """
+ model = self.get_myokit_model()
+ variables = model.variables(const=True, sort=True)
+ return [self._serialise_variable(v) for v in variables]
+
+ def _convert_unit(self, variable, myokit_variable_sbml, value):
+ is_target = False
+ if self.is_library_model:
+ is_target = "CT1" in variable.qname or "AT1" in variable.qname
+ if variable.unit is None:
+ conversion_factor = 1.0
+ else:
+ project = self.get_project()
+ compound = None
+ if project is not None:
+ compound = project.compound
+ conversion_factor = variable.unit.convert_to(
+ myokit_variable_sbml.unit(), compound=compound, is_target=is_target
+ )
+
+ return conversion_factor * value
+
+ def _convert_unit_qname(self, qname, value, myokit_model):
+ variable = self.variables.get(qname=qname)
+ myokit_variable_sbml = myokit_model.get(qname)
+ new_value = self._convert_unit(variable, myokit_variable_sbml, value)
+ return new_value
+
+ def _convert_bound_unit(self, binding, value, myokit_model):
+ myokit_variable_sbml = myokit_model.binding(binding)
+ variable = self.variables.get(qname=myokit_variable_sbml.qname())
+ return self._convert_unit(variable, myokit_variable_sbml, value)
+
+ if variable.unit is None:
+ conversion_factor = 1.0
+ else:
+ conversion_factor = myokit.Unit.conversion_factor(
+ variable.unit.get_myokit_unit(), myokit_variable_sbml.unit()
+ ).value()
+
+ return conversion_factor * value
+
+ def serialize_datalog(self, datalog, myokit_model):
+ result = {}
+ for k, v in datalog.items():
+ variable = self.variables.get(qname=k)
+ myokit_variable_sbml = myokit_model.get(k)
+
+ if variable.unit is None:
+ conversion_factor = 1.0
+ else:
+ conversion_factor = myokit.Unit.conversion_factor(
+ myokit_variable_sbml.unit(), variable.unit.get_myokit_unit()
+ ).value()
+
+ result[variable.id] = (conversion_factor * np.frombuffer(v)).tolist()
+
+ return result
+
+ def get_time_max(self):
+ return self.time_max
+
+ def simulate(self, outputs=None, variables=None, time_max=None):
+ """
+ Arguments
+ ---------
+ outputs: list
+ list of output names to return
+ variables: dict
+ dict mapping variable names to values for model parameters
+ time_max: float
+ maximum time to simulate to
+
+ Returns
+ -------
+ output: myokit.DataLog
+ a DataLog containing the solution, which is effectivly a dict
+ mapping output names to arrays of values
+ """
+
+ if time_max is None:
+ time_max = self.get_time_max()
+
+ if outputs is None:
+ outputs = []
+
+ default_variables = {
+ v.qname: v.get_default_value() for v in self.variables.filter(constant=True)
+ }
+ if variables is None:
+ variables = default_variables
+ else:
+ variables = {
+ **default_variables,
+ **variables,
+ }
+
+ model = self.get_myokit_model()
+
+ # Convert units
+ variables = {
+ qname: self._convert_unit_qname(qname, value, model)
+ for qname, value in variables.items()
+ }
+ time_max = self._convert_bound_unit("time", time_max, model)
+
+ # Set constants in model
+ for var_name, var_value in variables.items():
+ model.get(var_name).set_rhs(float(var_value))
+
+ # create simulator
+
+ # get tlag vars
+ override_tlag = {}
+ if isinstance(self, pkpdapp.models.CombinedModel):
+ for dv in self.derived_variables.all():
+ if dv.type == "TLG":
+ derived_param = dv.pk_variable.qname + "_tlag_ud"
+ if derived_param in variables:
+ override_tlag[dv.pk_variable.qname] = variables[derived_param]
+
+ sim = self.create_myokit_simulator(
+ override_tlag=override_tlag, model=model, time_max=time_max
+ )
+ # TODO: take these from simulation model
+ sim.set_tolerance(abs_tol=1e-06, rel_tol=1e-08)
+
+ # Simulate, logging only state variables given by `outputs`
+ return self.serialize_datalog(sim.run(time_max, log=outputs), model)
+
+
+def set_administration(model, drug_amount, direct=True):
+ r"""
+ Sets the route of administration of the compound.
+
+ The compound is administered to the selected compartment either
+ directly or indirectly. If it is administered directly, a dose rate
+ variable is added to the drug amount's rate of change expression
+
+ .. math ::
+
+ \frac{\text{d}A}{\text{d}t} = \text{RHS} + r_d,
+
+ where :math:`A` is the drug amount in the selected compartment, RHS is
+ the rate of change of :math:`A` prior to adding the dose rate, and
+ :math:`r_d` is the dose rate.
+
+ The dose rate can be set by :meth:`set_dosing_regimen`.
+
+ If the route of administration is indirect, a dosing compartment
+ is added to the model, which is connected to the selected compartment.
+ The dose rate variable is then added to the rate of change expression
+ of the dose amount variable in the dosing compartment. The drug amount
+ in the dosing compartment flows at a linear absorption rate into the
+ selected compartment
+
+ .. math ::
+
+ \frac{\text{d}A_d}{\text{d}t} = -k_aA_d + r_d \\
+ \frac{\text{d}A}{\text{d}t} = \text{RHS} + k_aA_d,
+
+ where :math:`A_d` is the amount of drug in the dose compartment and
+ :math:`k_a` is the absorption rate.
+
+ Setting an indirect administration route changes the number of
+ parameters of the model, and resets the parameter names to their
+ defaults.
+
+ Parameters
+ ----------
+ compartment
+ Compartment to which doses are either directly or indirectly
+ administered.
+ amount_var
+ Drug amount variable in the compartment. By default the drug amount
+ variable is assumed to be 'drug_amount'.
+ direct
+ A boolean flag that indicates whether the dose is administered
+ directly or indirectly to the compartment.
+ """
+ if not drug_amount.is_state():
+ raise ValueError(
+ "The variable <" + str(drug_amount) + "> is not a state "
+ "variable, and can therefore not be dosed."
+ )
+
+ # If administration is indirect, add a dosing compartment and update
+ # the drug amount variable to the one in the dosing compartment
+ time_unit = _get_time_unit(model)
+ if not direct:
+ drug_amount = _add_dose_compartment(model, drug_amount, time_unit)
+
+ # Add dose rate variable to the right hand side of the drug amount
+ _add_dose_rate(drug_amount, time_unit)
+
+
+def get_protocol(events):
+ """
+
+ Parameters
+ ----------
+ events
+ list of (level, start, duration)
+ """
+ myokit_protocol = myokit.Protocol()
+ for e in events:
+ myokit_protocol.schedule(e[0], e[1], e[2])
+
+ return myokit_protocol
+
+
+def _get_pacing_label(variable):
+ return f'pace_{variable.qname().replace(".", "_")}'
+
+
+def _add_dose_rate(drug_amount, time_unit):
+ """
+ Adds a dose rate variable to the state variable, which is bound to the
+ dosing regimen.
+ """
+ # Register a dose rate variable to the compartment and bind it to
+ # pace, i.e. tell myokit that its value is set by the dosing regimen/
+ # myokit.Protocol
+ compartment = drug_amount.parent()
+ dose_rate = compartment.add_variable_allow_renaming(str("dose_rate"))
+ dose_rate.set_binding(_get_pacing_label(drug_amount))
+
+ # Set initial value to 0 and unit to unit of drug amount over unit of
+ # time
+ dose_rate.set_rhs(0)
+ drug_amount_unit = drug_amount.unit()
+ if drug_amount_unit is not None and time_unit is not None:
+ dose_rate.set_unit(drug_amount.unit() / time_unit)
+
+ # Add the dose rate to the rhs of the drug amount variable
+ rhs = drug_amount.rhs()
+ drug_amount.set_rhs(myokit.Plus(rhs, myokit.Name(dose_rate)))
+
+
+def _get_time_unit(model):
+ """
+ Gets the model's time unit.
+ """
+ # Get bound variables
+ bound_variables = [var for var in model.variables(bound=True)]
+
+ # Get the variable that is bound to time
+ # (only one can exist in myokit.Model)
+ for var in bound_variables:
+ if var._binding == "time":
+ return var.unit()
+
+
+def _add_dose_compartment(model, drug_amount, time_unit):
+ """
+ Adds a dose compartment to the model with a linear absorption rate to
+ the connected compartment.
+ """
+ # Add a dose compartment to the model
+ dose_comp = model.add_component_allow_renaming("dose")
+
+ # Create a state variable for the drug amount in the dose compartment
+ dose_drug_amount = dose_comp.add_variable("drug_amount")
+ dose_drug_amount.set_rhs(0)
+ dose_drug_amount.set_unit(drug_amount.unit())
+ dose_drug_amount.promote()
+
+ # Create an absorption rate variable
+ absorption_rate = dose_comp.add_variable("absorption_rate")
+ absorption_rate.set_rhs(1)
+ absorption_rate.set_unit(1 / time_unit)
+
+ # Add outflow expression to dose compartment
+ dose_drug_amount.set_rhs(
+ myokit.Multiply(
+ myokit.PrefixMinus(myokit.Name(absorption_rate)),
+ myokit.Name(dose_drug_amount),
+ )
+ )
+
+ # Add inflow expression to connected compartment
+ rhs = drug_amount.rhs()
+ drug_amount.set_rhs(
+ myokit.Plus(
+ rhs,
+ myokit.Multiply(
+ myokit.Name(absorption_rate), myokit.Name(dose_drug_amount)
+ ),
+ )
+ )
+
+ return dose_drug_amount
diff --git a/pkpdapp/pkpdapp/models/pharmacodynamic_model.py b/pkpdapp/pkpdapp/models/pharmacodynamic_model.py
new file mode 100644
index 00000000..e2298688
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/pharmacodynamic_model.py
@@ -0,0 +1,62 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from django.urls import reverse
+from pkpdapp.models import (
+ MechanisticModel,
+ Project,
+ StoredModel,
+)
+
+
+class PharmacodynamicModel(MechanisticModel, StoredModel):
+ project = models.ForeignKey(
+ Project, on_delete=models.CASCADE,
+ related_name='pd_models',
+ blank=True, null=True,
+ help_text='Project that "owns" this model'
+ )
+ __original_mmt = None
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.__original_mmt = self.mmt
+
+ def get_absolute_url(self):
+ return reverse('pd_model-detail', kwargs={'pk': self.pk})
+
+ def get_project(self):
+ return self.project
+
+ def save(self, force_insert=False, force_update=False, *args, **kwargs):
+ created = not self.pk
+
+ super().save(force_insert, force_update, *args, **kwargs)
+
+ # don't update a stored model
+ if self.read_only:
+ return
+
+ if created or self.mmt != self.__original_mmt:
+ self.update_model()
+
+ self.__original_mmt = self.mmt
+
+ def create_stored_model(self):
+ stored_model_kwargs = {
+ 'name': self.name,
+ 'description': self.description,
+ 'project': self.project,
+ 'mmt': self.mmt,
+ 'time_max': self.time_max,
+ 'read_only': True,
+ }
+ stored_model = PharmacodynamicModel.objects.create(
+ **stored_model_kwargs)
+ for variable in self.variables.all():
+ variable.create_stored_variable(stored_model)
+ return stored_model
diff --git a/pkpdapp/pkpdapp/models/pharmacokinetic_model.py b/pkpdapp/pkpdapp/models/pharmacokinetic_model.py
new file mode 100644
index 00000000..10d97295
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/pharmacokinetic_model.py
@@ -0,0 +1,57 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.urls import reverse
+from pkpdapp.models import (
+ MechanisticModel,
+ StoredModel,
+)
+
+
+class PharmacokineticModel(MechanisticModel, StoredModel):
+ """
+ this just creates a concrete table for PK models without dosing
+ """
+ __original_mmt = None
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.__original_mmt = self.mmt
+
+ def get_project(self):
+ return None
+
+ def get_absolute_url(self):
+ return reverse('pk_model-detail', kwargs={'pk': self.pk})
+
+ def save(self, force_insert=False, force_update=False, *args, **kwargs):
+ created = not self.pk
+
+ super().save(force_insert, force_update, *args, **kwargs)
+
+ # don't update a stored model
+ if self.read_only:
+ return
+
+ if created or self.mmt != self.__original_mmt:
+ self.update_model()
+
+ self.__original_mmt = self.mmt
+
+ def create_stored_model(self):
+ stored_model_kwargs = {
+ 'name': self.name,
+ 'description': self.description,
+ 'mmt': self.mmt,
+ 'time_max': self.time_max,
+ 'read_only': True,
+ }
+ stored_model = PharmacokineticModel.objects.create(
+ **stored_model_kwargs)
+
+ # no need to store variables as they will be stored with the dosed pk
+ # model
+ return stored_model
diff --git a/pkpdapp/pkpdapp/models/profile.py b/pkpdapp/pkpdapp/models/profile.py
new file mode 100644
index 00000000..9dd62acd
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/profile.py
@@ -0,0 +1,16 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from django.contrib.auth.models import User
+
+
+class Profile(models.Model):
+ """
+ A user profile, containing neccessary information for users not held in
+ :model:`auth.User`.
+ """
+ user = models.OneToOneField(User, on_delete=models.CASCADE)
diff --git a/pkpdapp/pkpdapp/models/project.py b/pkpdapp/pkpdapp/models/project.py
new file mode 100644
index 00000000..6b901b2d
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/project.py
@@ -0,0 +1,68 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from django.contrib.auth.models import User
+from django.urls import reverse
+
+
+class Project(models.Model):
+ """
+ A project, containing multiple :model:`pkpdapp.Dataset`,
+ :model:`pkpdapp.PkpdModel` and users.
+ """
+ name = models.CharField(max_length=100, help_text='name of the project')
+ description = models.TextField(
+ help_text='short description of the project',
+ blank=True, default=''
+ )
+ users = models.ManyToManyField(
+ User,
+ through='ProjectAccess',
+ help_text='users with access to this project'
+ )
+
+ compound = models.OneToOneField(
+ 'Compound', on_delete=models.CASCADE,
+ )
+
+ created = models.DateTimeField(auto_now_add=True)
+
+ # species is a enum field
+ class Species(models.TextChoices):
+ MOUSE = 'M', 'Mouse'
+ RAT = 'R', 'Rat'
+ HUMAN = 'H', 'Human'
+ MONKEY = 'K', 'Monkey'
+ OTHER = 'O', 'Other'
+
+ species = models.CharField(
+ max_length=1,
+ choices=Species.choices,
+ default=Species.OTHER,
+ help_text='subject species'
+ )
+
+ def get_absolute_url(self):
+ return reverse('project-detail', kwargs={'pk': self.pk})
+
+ def __str__(self):
+ return str(self.name)
+
+
+class ProjectAccess(models.Model):
+ user = models.ForeignKey(User, on_delete=models.CASCADE)
+ project = models.ForeignKey(Project, on_delete=models.CASCADE)
+ read_only = models.BooleanField(
+ default=False,
+ help_text='True if user has read access only'
+ )
+
+ class Meta:
+ unique_together = ('user', 'project',)
+
+ def get_project(self):
+ return self.project
diff --git a/pkpdapp/pkpdapp/models/protocol.py b/pkpdapp/pkpdapp/models/protocol.py
new file mode 100644
index 00000000..ff94a26a
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/protocol.py
@@ -0,0 +1,151 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from django.urls import reverse
+from pkpdapp.models import (
+ Compound, Unit,
+ Project, StoredModel,
+)
+
+
+def get_h_unit():
+ try:
+ return Unit.objects.get(symbol='h')
+ except Unit.DoesNotExist:
+ return None
+
+
+def get_mg_unit():
+ try:
+ return Unit.objects.get(symbol='mg')
+ except Unit.DoesNotExist:
+ return None
+
+
+class Protocol(StoredModel):
+ """
+ Multiple doses forming a single protocol. Can optionally be associated with
+ a compound, dataset and subject.
+ """
+
+ name = models.CharField(
+ max_length=100, help_text='name of the protocol'
+ )
+ project = models.ForeignKey(
+ Project, on_delete=models.CASCADE,
+ related_name='protocols',
+ blank=True, null=True,
+ help_text='Project that "owns" this protocol.'
+ )
+ compound = models.ForeignKey(
+ Compound, on_delete=models.PROTECT,
+ blank=True, null=True,
+ help_text='drug compound'
+ )
+
+ class DoseType(models.TextChoices):
+ DIRECT = 'D', 'IV'
+ INDIRECT = 'I', 'Extravascular'
+
+ dose_type = models.CharField(
+ max_length=1,
+ choices=DoseType.choices,
+ default=DoseType.DIRECT,
+ )
+
+ time_unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ blank=True, null=True,
+ default=get_h_unit,
+ related_name='protocols_time',
+ help_text=(
+ 'unit for the start_time and duration values stored in each dose'
+ )
+ )
+
+ amount_unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ default=get_mg_unit,
+ blank=True, null=True,
+ related_name='protocols_amount',
+ help_text='unit for the amount value stored in each dose'
+ )
+
+ __original_dose_type = None
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.__original_dose_type = self.dose_type
+
+ def get_absolute_url(self):
+ return reverse('protocol-detail', kwargs={'pk': self.pk})
+
+ def get_project(self):
+ if self.project:
+ return self.project
+ else:
+ subject = self.subjects.first()
+ if subject is not None:
+ return subject.get_project()
+
+ return None
+
+ def __str__(self):
+ return str(self.name)
+
+ def get_dataset(self):
+ all_datasets = self.subjects.values('dataset').distinct()
+ if all_datasets:
+ return all_datasets[0]['dataset']
+ return None
+
+ def is_same_as(self, protocol):
+ if self.project != protocol.project:
+ return False
+ if self.compound != protocol.compound:
+ return False
+ if self.dose_type != protocol.dose_type:
+ return False
+ if self.time_unit != protocol.time_unit:
+ return False
+ if self.time_unit != protocol.time_unit:
+ return False
+ if self.amount_unit != protocol.amount_unit:
+ return False
+
+ my_doses = self.doses.order_by('start_time')
+ other_doses = protocol.doses.order_by('start_time')
+ for my_dose, other_dose in zip(my_doses, other_doses):
+ if not my_dose.is_same_as(other_dose):
+ return False
+ return True
+
+ def save(self, force_insert=False, force_update=False, *args, **kwargs):
+ super().save(force_insert, force_update, *args, **kwargs)
+
+ if self.dose_type != self.__original_dose_type:
+ for dosed_pk_model in self.dosed_pk_models.all():
+ dosed_pk_model.update_model()
+
+ self.__original_dose_type = self.dose_type
+
+ def create_stored_protocol(self):
+ if self.read_only:
+ return self
+ stored_protocol_kwargs = {
+ 'name': self.name,
+ 'project': self.project,
+ 'compound': self.compound,
+ 'dose_type': self.dose_type,
+ 'time_unit': self.time_unit,
+ 'amount_unit': self.amount_unit,
+ 'read_only': True,
+ }
+ stored_protocol = Protocol.objects.create(**stored_protocol_kwargs)
+ for dose in self.doses.all():
+ dose.create_stored_dose(stored_protocol)
+ return stored_protocol
diff --git a/pkpdapp/pkpdapp/models/simulation.py b/pkpdapp/pkpdapp/models/simulation.py
new file mode 100644
index 00000000..57aaf400
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/simulation.py
@@ -0,0 +1,174 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from django.core.validators import MinValueValidator
+
+
+# class to store options for simulation and plotting of results
+# a project can have multiple simulations
+class Simulation(models.Model):
+ """
+ A simulation, containing multiple :model:`pkpdapp.Dataset`,
+ :model:`pkpdapp.PkpdModel` and users.
+ """
+
+ name = models.CharField(max_length=100, help_text="name of the simulation")
+
+ project = models.ForeignKey(
+ "Project",
+ on_delete=models.CASCADE,
+ related_name="simulations",
+ )
+
+ nrows = models.IntegerField(default=1, help_text="number of subplot rows")
+
+ ncols = models.IntegerField(default=1, help_text="number of subplot columns")
+
+ time_max = models.FloatField(
+ default=30,
+ validators=[MinValueValidator(0)],
+ help_text="maximum time for the simulation",
+ )
+
+ time_max_unit = models.ForeignKey(
+ "Unit",
+ on_delete=models.PROTECT,
+ related_name="simulation_time_max",
+ help_text="unit for maximum time",
+ )
+
+ abs_tolerance = models.FloatField(
+ default=1e-6,
+ validators=[MinValueValidator(0)],
+ help_text="absolute tolerance for the simulation",
+ )
+
+ rel_tolerance = models.FloatField(
+ default=1e-6,
+ validators=[MinValueValidator(0)],
+ help_text="relative tolerance for the simulation",
+ )
+
+ def get_project(self):
+ return self.project
+
+
+# model for a simulation plot
+
+
+class SimulationPlot(models.Model):
+ simulation = models.ForeignKey(
+ "Simulation", on_delete=models.CASCADE, related_name="plots"
+ )
+ index = models.IntegerField(help_text="index of the plot in the simulation")
+
+ class ScaleOptions(models.TextChoices):
+ LINEAR = "lin", "Linear"
+ LOG2 = "lg2", "Log2"
+ LOG10 = "lg10", "Log10"
+ LN = "ln", "Ln"
+
+ x_scale = models.CharField(
+ max_length=4,
+ choices=ScaleOptions.choices,
+ default=ScaleOptions.LINEAR,
+ help_text="scale for x axis",
+ )
+
+ y_scale = models.CharField(
+ max_length=4,
+ choices=ScaleOptions.choices,
+ default=ScaleOptions.LINEAR,
+ help_text="scale for y axis",
+ )
+
+ y2_scale = models.CharField(
+ max_length=4,
+ choices=ScaleOptions.choices,
+ default=ScaleOptions.LINEAR,
+ help_text="scale for rhs y axis",
+ )
+
+ x_unit = models.ForeignKey(
+ "Unit",
+ on_delete=models.PROTECT,
+ related_name="simulation_plots",
+ help_text="unit for x axis",
+ )
+
+ y_unit = models.ForeignKey(
+ "Unit",
+ on_delete=models.PROTECT,
+ related_name="simulation_plots_y",
+ null=True,
+ blank=True,
+ help_text="unit for y axis",
+ )
+
+ y_unit2 = models.ForeignKey(
+ "Unit",
+ on_delete=models.PROTECT,
+ related_name="simulation_plots_y2",
+ null=True,
+ blank=True,
+ help_text="unit for rhs y axis",
+ )
+
+ min = models.FloatField(
+ null=True, blank=True, help_text="lower bound for the y axis"
+ )
+
+ max = models.FloatField(
+ null=True, blank=True, help_text="upper bound for the y axis"
+ )
+
+ min2 = models.FloatField(
+ null=True, blank=True, help_text="lower bound for the rhs y axis"
+ )
+
+ max2 = models.FloatField(
+ null=True, blank=True, help_text="upper bound for the rhs y axis"
+ )
+
+ def get_project(self):
+ return self.simulation.project
+
+
+# model for mapping a variable to a y axis
+class SimulationYAxis(models.Model):
+ plot = models.ForeignKey(
+ "SimulationPlot", on_delete=models.CASCADE, related_name="y_axes"
+ )
+
+ variable = models.ForeignKey(
+ "Variable", on_delete=models.CASCADE, related_name="y_axes"
+ )
+
+ # if true, the variable is plotted on the right y axis
+ right = models.BooleanField(
+ default=False, help_text="True if the variable is plotted on the right y axis"
+ )
+
+
+# model for a slider on the plot. the sliders alter the value of a variable
+# in the model
+class SimulationSlider(models.Model):
+ simulation = models.ForeignKey(
+ "Simulation", on_delete=models.CASCADE, related_name="sliders"
+ )
+
+ variable = models.ForeignKey(
+ "Variable", on_delete=models.CASCADE, related_name="sliders"
+ )
+
+
+class SimulationCxLine(models.Model):
+ plot = models.ForeignKey(
+ "SimulationPlot", on_delete=models.CASCADE, related_name="cx_lines"
+ )
+
+ value = models.FloatField(help_text="value of the line")
diff --git a/pkpdapp/pkpdapp/models/stored.py b/pkpdapp/pkpdapp/models/stored.py
new file mode 100644
index 00000000..447df7de
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/stored.py
@@ -0,0 +1,22 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from django.db import models
+
+
+class StoredModel(models.Model):
+ read_only = models.BooleanField(
+ default=False,
+ help_text='true if object has been stored'
+ )
+ datetime = models.DateTimeField(
+ help_text=(
+ 'datetime the object was stored.'
+ ),
+ null=True, blank=True
+ )
+
+ class Meta:
+ abstract = True
diff --git a/pkpdapp/pkpdapp/models/subject.py b/pkpdapp/pkpdapp/models/subject.py
new file mode 100644
index 00000000..33c8657c
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/subject.py
@@ -0,0 +1,56 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from jsonfield import JSONField
+
+
+class Subject(models.Model):
+ """
+ A subject in a particular dataset.
+ """
+ id_in_dataset = models.IntegerField(help_text='unique id in the dataset')
+ dataset = models.ForeignKey(
+ 'Dataset', on_delete=models.CASCADE,
+ related_name='subjects',
+ help_text='dataset containing this subject'
+ )
+ protocol = models.ForeignKey(
+ 'Protocol', on_delete=models.SET_NULL,
+ related_name='subjects',
+ blank=True, null=True,
+ help_text='dosing protocol for this subject.'
+ )
+ shape = models.IntegerField(
+ default=0,
+ help_text=(
+ 'Shape index associated with this subject. '
+ 'For plotting purposes in the frontend'
+ )
+ )
+ display = models.BooleanField(
+ default=True,
+ help_text=(
+ 'True if this subject will be displayed in the '
+ 'frontend, False otherwise'
+ )
+ )
+ metadata = JSONField(
+ default=dict,
+ help_text='subject metadata',
+ )
+
+ def get_project(self):
+ return self.dataset.get_project()
+
+ class Meta:
+ constraints = [
+ models.UniqueConstraint(fields=['id_in_dataset', 'dataset'],
+ name='subject_dataset_unique'),
+ ]
+
+ def __str__(self):
+ return str(self.id_in_dataset)
diff --git a/pkpdapp/pkpdapp/models/units.py b/pkpdapp/pkpdapp/models/units.py
new file mode 100644
index 00000000..b89e40c1
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/units.py
@@ -0,0 +1,304 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.db import models
+from django.db.models import Q
+import myokit
+
+# https://stackoverflow.com/questions/14711203/perform-a-logical-exclusive-or-on-a-django-q-object
+
+
+class QQ:
+ def __xor__(self, other):
+ not_self = self.clone()
+ not_other = other.clone()
+ not_self.negate()
+ not_other.negate()
+
+ x = self & not_other
+ y = not_self & other
+
+ return x | y
+
+
+class Unit(models.Model):
+ """
+ Model replicating the Unit class from myokit
+
+ Each Unit consists of:
+
+ - A list of seven floats: these are the exponents for the basic
+ SI units: [g, m, s, A, K, cd, mol]. Gram is used instead of the
+ SI defined kilogram to create a more coherent syntax.
+
+ - A multiplier. This includes both quantifiers (such as milli, kilo,
+ Mega etc) and conversion factors (for example 1inch = 2.54cm).
+ Multipliers are specified in powers of 10, e.g. to create an inch
+ use the multiplier log10(2.54).
+ """
+
+ symbol = models.CharField(max_length=50, help_text="symbol for unit display")
+ g = models.FloatField(default=0, help_text="grams exponent")
+ m = models.FloatField(default=0, help_text="meters exponent")
+ s = models.FloatField(default=0, help_text="seconds exponent")
+ A = models.FloatField(default=0, help_text="ampere exponent")
+ K = models.FloatField(default=0, help_text="kelvin exponent")
+ cd = models.FloatField(default=0, help_text="candela exponent")
+ mol = models.FloatField(default=0, help_text="mole exponent")
+ multiplier = models.FloatField(default=0, help_text="multiplier in powers of 10")
+
+ constraints = [
+ models.UniqueConstraint(fields=["symbol"], name="unique unit symbol")
+ ]
+
+ def get_myokit_unit(self):
+ return myokit.Unit(
+ exponents=[self.g, self.m, self.s, self.A, self.K, self.cd, self.mol],
+ multiplier=self.multiplier,
+ )
+
+ def get_project(self):
+ return None
+
+ @staticmethod
+ def get_unit_from_variable(v):
+ unit = v.unit()
+ if unit is None:
+ return None
+ exponents = unit.exponents()
+ multiplier = unit.multiplier_log_10()
+ close_enough = 1e-9
+ close_enough_units = Unit.objects.filter(
+ g__range=(
+ exponents[0] - close_enough,
+ exponents[0] + close_enough,
+ ),
+ m__range=(
+ exponents[1] - close_enough,
+ exponents[1] + close_enough,
+ ),
+ s__range=(
+ exponents[2] - close_enough,
+ exponents[2] + close_enough,
+ ),
+ A__range=(
+ exponents[3] - close_enough,
+ exponents[3] + close_enough,
+ ),
+ K__range=(
+ exponents[4] - close_enough,
+ exponents[4] + close_enough,
+ ),
+ cd__range=(
+ exponents[5] - close_enough,
+ exponents[5] + close_enough,
+ ),
+ mol__range=(
+ exponents[6] - close_enough,
+ exponents[6] + close_enough,
+ ),
+ multiplier__range=(
+ multiplier - close_enough,
+ multiplier + close_enough,
+ ),
+ )
+ if close_enough_units.count() > 0:
+ return close_enough_units[0]
+ else:
+ return Unit.objects.create(
+ symbol=str(unit),
+ g=exponents[0],
+ m=exponents[1],
+ s=exponents[2],
+ A=exponents[3],
+ K=exponents[4],
+ cd=exponents[5],
+ mol=exponents[6],
+ multiplier=multiplier,
+ )
+
+ def is_convertible_to(self, unit, compound=None):
+ try:
+ self.convert_to(unit, compound=compound)
+ except myokit.IncompatibleUnitError:
+ return False
+ return True
+
+ def convert_to(self, unit, compound=None, is_target=False):
+ if unit is None:
+ return 1.0
+ if isinstance(unit, myokit.Unit):
+ myokit_unit = unit
+ else:
+ myokit_unit = unit.get_myokit_unit()
+ helpers = []
+ if compound is not None:
+ if is_target:
+ helpers = [
+ f"{compound.target_molecular_mass} [{compound.target_molecular_mass_unit.symbol}]" # noqa: E501
+ ]
+ else:
+ helpers = [
+ f"{compound.molecular_mass} [{compound.molecular_mass_unit.symbol}]" # noqa: E501
+ ]
+ return myokit.Unit.conversion_factor(
+ self.get_myokit_unit(),
+ myokit_unit,
+ helpers=helpers,
+ ).value()
+
+ @staticmethod
+ def convert_between_myokit_units(
+ from_unit, to_unit, compound=None, is_target=False
+ ):
+ helpers = []
+ if compound is not None:
+ if is_target:
+ helpers = [
+ f"{compound.target_molecular_mass} [{compound.target_molecular_mass_unit.symbol}]" # noqa: E501
+ ]
+ else:
+ helpers = [
+ f"{compound.molecular_mass} [{compound.molecular_mass_unit.symbol}]" # noqa: E501
+ ]
+ return myokit.Unit.conversion_factor(
+ from_unit,
+ to_unit,
+ helpers=helpers,
+ ).value()
+
+ def get_compatible_units(self, compound=None):
+ close_enough = 1e-9
+ if compound is not None:
+ g_is_same = Q(
+ g__range=(
+ self.g - close_enough,
+ self.g + close_enough,
+ )
+ )
+ mol_is_same = Q(
+ mol__range=(
+ self.mol - close_enough,
+ self.mol + close_enough,
+ )
+ )
+ mol_added_to_g = Q(
+ g__range=(
+ self.g + self.mol - close_enough,
+ self.g + self.mol + close_enough,
+ )
+ )
+ g_added_to_mol = Q(
+ mol__range=(
+ self.mol + self.g - close_enough,
+ self.mol + self.g + close_enough,
+ )
+ )
+ no_g = Q(g=0)
+ self_has_g = self.g != 0
+ self_no_g_or_mol = self.g == 0 and self.mol == 0
+ no_mol = Q(mol=0)
+ self_has_mol = self.mol != 0
+ filter = mol_is_same & g_is_same
+ mol_and_g_add_to_zero = Q(mol=1, g=-1) | Q(mol=-1, g=1)
+
+ # take into account that '' is convertible to 'mol/g' or 'g/mol'
+ if self_no_g_or_mol:
+ filter |= mol_and_g_add_to_zero
+ if self_has_mol:
+ filter |= mol_added_to_g & no_mol
+ if self_has_g:
+ filter |= g_added_to_mol & no_g
+ compat_units = Unit.objects.filter(
+ filter,
+ Q(
+ m__range=(
+ self.m - close_enough,
+ self.m + close_enough,
+ )
+ ),
+ Q(
+ s__range=(
+ self.s - close_enough,
+ self.s + close_enough,
+ )
+ ),
+ Q(
+ A__range=(
+ self.A - close_enough,
+ self.A + close_enough,
+ )
+ ),
+ Q(
+ K__range=(
+ self.K - close_enough,
+ self.K + close_enough,
+ )
+ ),
+ Q(
+ cd__range=(
+ self.cd - close_enough,
+ self.cd + close_enough,
+ )
+ ),
+ )
+ return compat_units
+ else:
+ return Unit.objects.filter(
+ Q(
+ g__range=(
+ self.g - close_enough,
+ self.g + close_enough,
+ )
+ ),
+ Q(
+ mol__range=(
+ self.mol - close_enough,
+ self.mol + close_enough,
+ )
+ ),
+ Q(
+ m__range=(
+ self.m - close_enough,
+ self.m + close_enough,
+ )
+ ),
+ Q(
+ s__range=(
+ self.s - close_enough,
+ self.s + close_enough,
+ )
+ ),
+ Q(
+ A__range=(
+ self.A - close_enough,
+ self.A + close_enough,
+ )
+ ),
+ Q(
+ K__range=(
+ self.K - close_enough,
+ self.K + close_enough,
+ )
+ ),
+ Q(
+ cd__range=(
+ self.cd - close_enough,
+ self.cd + close_enough,
+ )
+ ),
+ )
+
+ def is_time_unit(self):
+ return (
+ self.s == 1
+ and self.g == 0
+ and self.m == 0
+ and self.A == 0
+ and self.K == 0
+ and self.cd == 0
+ and self.mol == 0
+ )
diff --git a/pkpdapp/pkpdapp/models/variable.py b/pkpdapp/pkpdapp/models/variable.py
new file mode 100644
index 00000000..2f006f28
--- /dev/null
+++ b/pkpdapp/pkpdapp/models/variable.py
@@ -0,0 +1,400 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from pkpdapp.models import (
+ Unit, CombinedModel,
+ PharmacokineticModel, PharmacodynamicModel,
+ StoredModel, Protocol,
+)
+import numpy as np
+from django.db.models import Q
+from django.db import models
+import logging
+logger = logging.getLogger(__name__)
+
+
+class Variable(StoredModel):
+ """
+ A single variable for a mechanistic model.
+ """
+ is_public = models.BooleanField(default=False)
+ lower_bound = models.FloatField(
+ blank=True, null=True,
+ help_text='lowest possible value for this variable'
+ )
+ upper_bound = models.FloatField(
+ blank=True, null=True,
+ help_text='largest possible value for this variable'
+ )
+ default_value = models.FloatField(
+ default=1,
+ help_text='default value for this variable'
+ )
+
+ is_log = models.BooleanField(
+ default=False,
+ help_text=(
+ 'True if default_value is stored as '
+ 'the log of this value'
+ )
+ )
+
+ name = models.CharField(max_length=100, help_text='name of the variable')
+ description = models.TextField(
+ blank=True, null=True,
+ help_text='description of the variable'
+ )
+ binding = models.CharField(
+ max_length=100,
+ help_text='myokit binding of the variable (e.g. time)',
+ blank=True, null=True,
+ )
+
+ qname = models.CharField(
+ max_length=200, help_text='fully qualitifed name of the variable')
+
+ unit = models.ForeignKey(
+ Unit, on_delete=models.PROTECT,
+ blank=True, null=True,
+ help_text=(
+ 'variable values are in this unit '
+ '(note this might be different from the unit '
+ 'in the stored sbml)'
+ )
+ )
+
+ unit_symbol = models.CharField(
+ max_length=20, blank=True, null=True,
+ help_text=(
+ 'if unit is None then this is the unit of this '
+ 'variable as a string'
+ )
+ )
+
+ constant = models.BooleanField(
+ default=True,
+ help_text=(
+ 'True for a constant variable of the model, '
+ 'i.e. a parameter. False if non-constant, '
+ 'i.e. an output of the model (default is True)'
+ )
+ )
+ state = models.BooleanField(
+ default=False,
+ help_text=(
+ 'True if it is a state variable of the model '
+ 'and has an initial condition parameter '
+ '(default is False)'
+ )
+ )
+
+ color = models.IntegerField(
+ default=0,
+ help_text=(
+ 'Color index associated with this variable. '
+ 'For display purposes in the frontend'
+ )
+ )
+ display = models.BooleanField(
+ default=True,
+ help_text=(
+ 'True if this variable will be displayed in the '
+ 'frontend, False otherwise'
+ )
+ )
+ axis = models.BooleanField(
+ default=False,
+ help_text=(
+ 'False/True if biomarker type displayed on LHS/RHS axis'
+ )
+ )
+
+ pd_model = models.ForeignKey(
+ PharmacodynamicModel,
+ blank=True, null=True,
+ on_delete=models.CASCADE,
+ related_name='variables',
+ help_text='pharmacodynamic model'
+ )
+ pk_model = models.ForeignKey(
+ PharmacokineticModel,
+ blank=True, null=True,
+ on_delete=models.CASCADE,
+ related_name='variables',
+ help_text='pharmacokinetic model'
+ )
+ dosed_pk_model = models.ForeignKey(
+ CombinedModel,
+ blank=True, null=True,
+ on_delete=models.CASCADE,
+ related_name='variables',
+ help_text='dosed pharmacokinetic model'
+ )
+
+ protocol = models.ForeignKey(
+ Protocol,
+ on_delete=models.SET_NULL,
+ related_name='variables',
+ blank=True, null=True,
+ help_text='dosing protocol'
+ )
+
+ class Meta:
+ constraints = [
+ models.CheckConstraint(
+ check=(
+ (Q(is_log=True) & Q(lower_bound__gt=0)) |
+ Q(is_log=False)
+ ),
+ name=(
+ '%(class)s: log scale must have a lower '
+ 'bound greater than zero'
+ )
+ ),
+ models.CheckConstraint(
+ check=(
+ (Q(pk_model__isnull=True) &
+ Q(dosed_pk_model__isnull=True) &
+ Q(pd_model__isnull=False)) |
+ (Q(pk_model__isnull=False) &
+ Q(dosed_pk_model__isnull=True) &
+ Q(pd_model__isnull=True)) |
+ (Q(pk_model__isnull=True) &
+ Q(dosed_pk_model__isnull=False) &
+ Q(pd_model__isnull=True))
+ ),
+ name='%(class)s: variable must belong to a model'
+ )
+ ]
+
+ def get_model(self):
+ model = None
+ if self.pd_model:
+ model = self.pd_model
+ if self.dosed_pk_model:
+ model = self.dosed_pk_model
+ if self.pk_model:
+ model = self.pk_model
+ return model
+
+ def get_default_value(self):
+ if self.is_log:
+ return np.exp(self.default_value)
+ else:
+ return self.default_value
+
+ def get_project(self):
+ model = self.get_model()
+ if model is not None:
+ return model.get_project()
+ else:
+ return None
+
+ @staticmethod
+ def get_variable_pk(model, myokit_variable):
+ num_variables = Variable.objects.filter(
+ pk_model=model,
+ ).count()
+ variables = Variable.objects.filter(
+ qname=myokit_variable.qname(),
+ pk_model=model,
+ )
+ found_variable = Variable._find_close_variable(
+ myokit_variable, variables,
+ compound=model.get_project().compound
+ )
+ if found_variable is not None:
+ return variables[0]
+ else:
+ state = myokit_variable.is_state()
+ if state:
+ value = myokit_variable.state_value()
+ else:
+ value = myokit_variable.value()
+ qname = myokit_variable.qname()
+ return Variable.objects.create(
+ name=myokit_variable.name(),
+ qname=qname,
+ default_value=value,
+ description=myokit_variable.meta.get('desc', ''),
+ binding=myokit_variable.binding(),
+ lower_bound=None,
+ upper_bound=None,
+ constant=myokit_variable.is_constant(),
+ state=state,
+ unit=Unit.get_unit_from_variable(myokit_variable),
+ pk_model=model,
+ color=num_variables,
+ display=myokit_variable.name() != 'time',
+ )
+
+ @staticmethod
+ def _find_close_variable(myokit_variable, variables, compound=None):
+ logger.debug('Looking for variable: {} [{}]'.format(
+ myokit_variable, myokit_variable.unit()
+ ))
+ found = None
+ for i, v in enumerate(variables):
+ # todo check if units are compatible...
+ if v.unit is None:
+ logger.debug('\tchecking variable: {}'.format(v.qname))
+ else:
+ logger.debug('\tchecking variable: {} [{}]'.format(
+ v.qname, v.unit.symbol
+ ))
+ if v.unit is None:
+ if myokit_variable.unit() is None:
+ found = i
+ elif (
+ myokit_variable.unit() is not None and
+ v.unit.is_convertible_to(
+ myokit_variable.unit(), compound=compound
+ )
+ ):
+ found = i
+ if found is not None:
+ logger.debug('Found variable: {}'.format(variables[found]))
+ return variables[found]
+ return None
+
+ @staticmethod
+ def get_variable_pd(model, myokit_variable):
+ num_variables = Variable.objects.filter(
+ pd_model=model,
+ ).count()
+ variables = Variable.objects.filter(
+ qname=myokit_variable.qname(),
+ pd_model=model,
+ )
+ project = model.get_project()
+ compound = None
+ if project is not None:
+ compound = project.compound
+ found_variable = Variable._find_close_variable(
+ myokit_variable, variables,
+ compound=compound
+ )
+ if found_variable is not None:
+ return variables[0]
+ else:
+ state = myokit_variable.is_state()
+ if state:
+ value = myokit_variable.state_value()
+ else:
+ value = myokit_variable.value()
+ qname = myokit_variable.qname()
+ return Variable.objects.create(
+ name=myokit_variable.name(),
+ qname=qname,
+ description=myokit_variable.meta.get('desc', ''),
+ constant=myokit_variable.is_constant(),
+ binding=myokit_variable.binding(),
+ default_value=value,
+ lower_bound=None,
+ upper_bound=None,
+ state=state,
+ unit=Unit.get_unit_from_variable(myokit_variable),
+ pd_model=model,
+ color=num_variables,
+ display=myokit_variable.name() != 'time',
+ )
+
+ @staticmethod
+ def get_variable_dosed_pk(model, myokit_variable):
+ num_variables = Variable.objects.filter(
+ dosed_pk_model=model,
+ ).count()
+ variables = Variable.objects.filter(
+ qname=myokit_variable.qname(),
+ dosed_pk_model=model,
+ )
+ compound = None
+ project = model.get_project()
+ if project is not None:
+ compound = project.compound
+ found_variable = Variable._find_close_variable(
+ myokit_variable, variables,
+ compound=compound
+ )
+ if found_variable is not None:
+ return variables[0]
+ else:
+ # lower and upper bounds for library models
+ lower = None
+ upper = None
+ if model.is_library_model:
+ if myokit_variable.qname() == 'PDCompartment.Imax':
+ upper = 1.0
+ elif myokit_variable.qname() == 'PKCompartment.F':
+ upper = 1.0
+ elif myokit_variable.qname() == 'PDCompartment.FE':
+ upper = 1.0
+ elif myokit_variable.qname() == 'PDCompartment.Emax':
+ lower = 1.0
+ state = myokit_variable.is_state()
+ if state:
+ value = myokit_variable.state_value()
+ else:
+ value = myokit_variable.value()
+ qname = myokit_variable.qname()
+ return Variable.objects.create(
+ name=myokit_variable.name(),
+ qname=qname,
+ description=myokit_variable.meta.get('desc', ''),
+ constant=myokit_variable.is_constant(),
+ default_value=value,
+ binding=myokit_variable.binding(),
+ lower_bound=lower,
+ upper_bound=upper,
+ state=state,
+ unit=Unit.get_unit_from_variable(myokit_variable),
+ dosed_pk_model=model,
+ color=num_variables,
+ display=myokit_variable.name() != 'time',
+ )
+
+ @staticmethod
+ def get_variable(model, myokit_variable):
+ if isinstance(model, PharmacokineticModel):
+ return Variable.get_variable_pk(model, myokit_variable)
+ elif isinstance(model, CombinedModel):
+ return Variable.get_variable_dosed_pk(model, myokit_variable)
+ elif isinstance(model, PharmacodynamicModel):
+ return Variable.get_variable_pd(model, myokit_variable)
+ else:
+ raise RuntimeError(
+ 'create_variable got unexpected model type {}'
+ .format(type(model)),
+ )
+
+ def create_stored_variable(self, stored_model):
+ stored_variable_kwargs = {
+ 'name': self.name,
+ 'qname': self.qname,
+ 'description': self.description,
+ 'unit': self.unit,
+ 'is_public': self.is_public,
+ 'binding': self.binding,
+ 'lower_bound': self.lower_bound,
+ 'upper_bound': self.upper_bound,
+ 'default_value': self.default_value,
+ 'is_log': self.is_log,
+ 'axis': self.axis,
+ 'display': self.display,
+ 'color': self.color,
+ 'state': self.state,
+ 'unit_symbol': self.unit_symbol,
+ 'constant': self.constant,
+ 'read_only': True,
+ 'protocol': (
+ self.protocol.create_stored_protocol()
+ if self.protocol is not None else None
+ ),
+ }
+ if isinstance(stored_model, PharmacodynamicModel):
+ stored_variable_kwargs['pd_model'] = stored_model
+ elif isinstance(stored_model, CombinedModel):
+ stored_variable_kwargs['dosed_pk_model'] = stored_model
+ return Variable.objects.create(**stored_variable_kwargs)
diff --git a/pkpdapp/pkpdapp/settings.py b/pkpdapp/pkpdapp/settings.py
new file mode 100644
index 00000000..d5e276d9
--- /dev/null
+++ b/pkpdapp/pkpdapp/settings.py
@@ -0,0 +1,419 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+"""
+Django settings for pkpdapp project.
+
+Generated by 'django-admin startproject' using Django 3.0.5.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/3.0/topics/settings/.
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/3.0/ref/settings/.
+"""
+
+import os
+import dj_database_url
+import ldap
+from django_auth_ldap.config import LDAPSearch
+
+# Set BASE_DIR to two directories up
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+# setup automatic pk column for models
+DEFAULT_AUTO_FIELD = 'django.db.models.AutoField'
+
+LOGGING = {
+ 'version': 1,
+ 'disable_existing_loggers': False,
+ 'handlers': {
+ 'console': {
+ 'class': 'logging.StreamHandler',
+ 'level': 'DEBUG',
+ 'formatter': 'simple'
+ },
+ 'file': {
+ 'class': 'logging.handlers.RotatingFileHandler',
+ 'filename': os.path.join(BASE_DIR, 'logfile.log'),
+ 'maxBytes': 1024 * 1024 * 5, # 5 MB
+ 'backupCount': 5,
+ 'level': 'DEBUG',
+ 'formatter': 'verbose'
+ }
+ },
+ 'loggers': {
+ 'django': {
+ 'handlers': ['console', 'file'],
+ 'level': 'INFO',
+ 'propagate': False,
+ },
+ 'pkpdapp': {
+ 'handlers': ['console', 'file'],
+ 'level': 'DEBUG',
+ 'propagate': False,
+ },
+ },
+ 'formatters': {
+ 'simple': {
+ 'format': '%(levelname)s %(message)s'
+ },
+ 'verbose': {
+ 'format': '%(asctime)s %(levelname)s %(module)s %(process)d %(thread)d %(message)s' # noqa: E501
+ }
+ }
+}
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
+
+SECRET_KEY = os.environ.get("SECRET_KEY", default='foo')
+
+DEBUG = int(os.environ.get("DEBUG", default=0))
+
+ALLOWED_HOSTS = [os.environ.get('HOST_NAME', 'localhost'), '127.0.0.1']
+
+if DEBUG:
+ ALLOWED_HOSTS.append('testserver')
+
+
+# Application definition - to use any of those you need to run `manage.py
+# migrate` first
+
+INSTALLED_APPS = [
+ # standard Django apps
+ 'django.contrib.admin',
+ 'django.contrib.admindocs',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+
+ # external apps
+ 'dpd_static_support',
+ 'django_extensions',
+ 'djoser',
+ 'rest_framework',
+ 'rest_framework.authtoken',
+ 'corsheaders',
+ 'drf_spectacular',
+
+ # internal apps
+ 'pkpdapp',
+]
+
+use_ldap = bool(int(os.environ.get('AUTH_LDAP_USE', '0')))
+if use_ldap:
+ AUTHENTICATION_BACKENDS = [
+ "django_auth_ldap.backend.LDAPBackend",
+ "django.contrib.auth.backends.ModelBackend",
+ ]
+ AUTH_LDAP_SERVER_URI = os.environ.get(
+ 'AUTH_LDAP_SERVER_URI',
+ 'ldap://ldap.forumsys.com:389'
+ )
+
+ use_direct_bind = bool(int(os.environ.get('AUTH_LDAP_DIRECT_BIND', '0')))
+ if use_direct_bind:
+ AUTH_LDAP_USER_DN_TEMPLATE = os.environ.get(
+ 'AUTH_LDAP_BIND_DN_TEMPLATE',
+ 'uid=%(user)s,dc=example,dc=com'
+ )
+ else:
+ AUTH_LDAP_BIND_DN = os.environ.get(
+ 'AUTH_LDAP_BIND_DN',
+ 'cn=read-only-admin,dc=example,dc=com'
+ )
+ AUTH_LDAP_BIND_PASSWORD = os.environ.get(
+ 'AUTH_LDAP_BIND_PASSWORD',
+ 'password'
+ )
+ AUTH_LDAP_USER_SEARCH = LDAPSearch(
+ os.environ.get(
+ 'AUTH_LDAP_SEARCH_BASE',
+ 'ou=mathematicians,dc=example,dc=com'
+ ),
+ ldap.SCOPE_SUBTREE,
+ os.environ.get(
+ 'AUTH_LDAP_SEARCH_FILTER',
+ "(uid=%(user)s)"
+ ),
+ )
+
+DJOSER = {
+ 'PASSWORD_RESET_CONFIRM_URL': 'reset-password/{uid}/{token}',
+ 'ACTIVATION_URL': 'activate/{uid}/{token}',
+ 'SEND_ACTIVATION_EMAIL': True,
+ 'SEND_CONFIRMATION_EMAIL': True,
+ 'PASSWORD_CHANGED_EMAIL_CONFIRMATION': True,
+ 'SERIALIZERS': {},
+ 'PERMISSIONS': {
+ 'activation': ['rest_framework.permissions.AllowAny'],
+ 'password_reset': ['rest_framework.permissions.AllowAny'],
+ 'password_reset_confirm': ['rest_framework.permissions.AllowAny'],
+ 'set_password': ['djoser.permissions.CurrentUserOrAdmin'],
+ 'username_reset': ['rest_framework.permissions.AllowAny'],
+ 'username_reset_confirm': ['rest_framework.permissions.AllowAny'],
+ 'set_username': ['djoser.permissions.CurrentUserOrAdmin'],
+ 'user_create': ['rest_framework.permissions.AllowAny'],
+ 'user_delete': ['djoser.permissions.CurrentUserOrAdmin'],
+ 'user': ['djoser.permissions.CurrentUserOrAdmin'],
+ 'user_list': ['djoser.permissions.CurrentUserOrAdmin'],
+ 'token_create': ['rest_framework.permissions.AllowAny'],
+ 'token_destroy': ['rest_framework.permissions.IsAuthenticated'],
+ },
+}
+
+
+# django rest framework library
+REST_FRAMEWORK = {
+ 'DEFAULT_RENDERER_CLASSES': [
+ 'rest_framework.renderers.JSONRenderer',
+ ],
+ 'DEFAULT_AUTHENTICATION_CLASSES': [
+ 'rest_framework.authentication.SessionAuthentication',
+ ],
+ 'DEFAULT_PERMISSION_CLASSES': [
+ 'rest_framework.permissions.IsAuthenticated',
+ ],
+ 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
+}
+
+SPECTACULAR_SETTINGS = {
+ 'TITLE': 'PKPDApp API',
+ 'DESCRIPTION': 'The API for the PKPDApp',
+ 'VERSION': '1.0.0',
+ 'SERVE_INCLUDE_SCHEMA': False,
+}
+
+
+CRISPY_TEMPLATE_PACK = 'bootstrap4'
+
+MARKDOWNIFY_MARKDOWN_EXTENSIONS = [
+ 'mdx_math',
+]
+
+MARKDOWNIFY_WHITELIST_TAGS = [
+ 'a',
+ 'abbr',
+ 'acronym',
+ 'b',
+ 'blockquote',
+ 'em',
+ 'i',
+ 'li',
+ 'ol',
+ 'p',
+ 'strong',
+ 'ul',
+ 'h',
+ 'script',
+]
+
+MARKDOWNIFY_WHITELIST_ATTRS = [
+ 'href',
+ 'src',
+ 'alt',
+ 'type',
+]
+
+MARKDOWNIFY_WHITELIST_STYLES = [
+ 'color',
+ 'font-weight',
+]
+
+MIDDLEWARE = [
+ "corsheaders.middleware.CorsMiddleware",
+ 'django.middleware.security.SecurityMiddleware',
+ 'whitenoise.middleware.WhiteNoiseMiddleware',
+
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+CORS_ALLOWED_ORIGINS = [
+ "http://127.0.0.1:3000",
+ "http://127.0.0.1:3001",
+ "http://127.0.0.1:3002",
+ "http://127.0.0.1:3003",
+ "http://127.0.0.1:3004",
+ "http://localhost:3000",
+ "http://" + os.environ.get('HOST_NAME', 'bamad.herokuapp.com')
+]
+
+CORS_ALLOW_ALL_ORIGINS = True
+
+CORS_EXPOSE_HEADERS = ['Content-Type', 'X-CSRFToken']
+CORS_ALLOW_CREDENTIALS = True
+
+ROOT_URLCONF = 'pkpdapp.urls'
+
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [os.path.join(BASE_DIR, 'pkpdapp', 'templates')],
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [
+ 'django.template.context_processors.debug',
+ 'django.template.context_processors.request',
+ 'django.contrib.auth.context_processors.auth',
+ 'django.contrib.messages.context_processors.messages',
+ ],
+ },
+ },
+]
+
+
+X_FRAME_OPTIONS = 'SAMEORIGIN'
+
+# WSGI_APPLICATION = 'bamad.wsgi.application'
+
+# authentication cookie settings
+CSRF_COOKIE_SAMESITE = 'Lax'
+SESSION_COOKIE_SAMESITE = 'Lax'
+CSRF_COOKIE_HTTPONLY = False
+SESSION_COOKIE_HTTPONLY = True
+
+# PROD ONLY
+# CSRF_COOKIE_SECURE = True
+# SESSION_COOKIE_SECURE = True
+
+
+WSGI_APPLICATION = 'pkpdapp.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+ 'OPTIONS': {
+ # 'timeout': 20,
+ }
+ }
+}
+
+DATABASE_URL = os.environ.get('DATABASE_URL')
+db_from_env = dj_database_url.config(
+ default=DATABASE_URL, conn_max_age=500, ssl_require=False
+)
+DATABASES['default'].update(db_from_env)
+
+
+# Password validation
+# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+ {
+ 'NAME':
+ 'django.contrib.auth.password_validation.'
+ 'UserAttributeSimilarityValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.'
+ 'MinimumLengthValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.'
+ 'CommonPasswordValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.'
+ 'NumericPasswordValidator',
+ },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/3.0/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_L10N = True
+
+USE_TZ = True
+
+# Media files (such as data sets and model files)
+MEDIA_URL = '/media/'
+MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/3.0/howto/static-files/
+STATIC_URL = '/static/'
+STATIC_ROOT = os.path.join(BASE_DIR, 'static')
+
+STATICFILES_DIRS = [
+]
+
+# Staticfiles finders for locating dash app assets and related files
+STATICFILES_FINDERS = [
+ # Django default finders
+ 'django.contrib.staticfiles.finders.FileSystemFinder',
+ 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
+]
+
+# Forever cachable files and compression support
+STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
+
+
+# Redirect to home URL after login (Default redirects to /accounts/profile/)
+LOGIN_REDIRECT_URL = '/'
+
+
+EMAIL_HOST = os.environ.get("EMAIL_HOST", default=None)
+if EMAIL_HOST is None:
+ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
+else:
+ EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
+
+EMAIL_PORT = os.environ.get("EMAIL_PORT", default='foo')
+EMAIL_HOST_USER = os.environ.get("EMAIL_HOST_USER", default='foo')
+EMAIL_HOST_PASSWORD = os.environ.get("EMAIL_HOST_PASSWORD", default='foo')
+DEFAULT_FROM_EMAIL = os.environ.get("DEFAULT_FROM_EMAIL",
+ default='webmaster@localhost')
+
+CACHES = {
+ 'default': {
+ 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
+ 'LOCATION': '127.0.0.1:11211',
+ }
+}
+
+DEFAULT_FROM_EMAIL = os.environ.get("DEFAULT_FROM_EMAIL",
+ default='webmaster@localhost')
+
+CLOUDAMQP_URL = os.environ.get("CLOUDAMQP_URL", default=None)
+if CLOUDAMQP_URL is None:
+ CELERY_BROKER_URL = [
+ 'amqp://',
+ 'amqp://{}:{}@rabbitmq:5672'.format(
+ os.environ.get("RABBITMQ_DEFAULT_USER",
+ default='guest'),
+ os.environ.get("RABBITMQ_DEFAULT_PASS",
+ default='guest')
+ )
+ ]
+else:
+ CELERY_BROKER_URL = CLOUDAMQP_URL
+
+CELERY_BROKER_TRANSPORT_OPTIONS = {
+ 'max_retries': 3,
+ 'interval_start': 0,
+ 'interval_step': 0.2,
+ 'interval_max': 0.5,
+}
diff --git a/pkpdapp/pkpdapp/signals/__init__.py b/pkpdapp/pkpdapp/signals/__init__.py
new file mode 100644
index 00000000..c181e488
--- /dev/null
+++ b/pkpdapp/pkpdapp/signals/__init__.py
@@ -0,0 +1,7 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from .add_profile_on_user_save import add_profile_on_user_save # noqa: F401
diff --git a/pkpdapp/pkpdapp/signals/add_profile_on_user_save.py b/pkpdapp/pkpdapp/signals/add_profile_on_user_save.py
new file mode 100644
index 00000000..e2217709
--- /dev/null
+++ b/pkpdapp/pkpdapp/signals/add_profile_on_user_save.py
@@ -0,0 +1,12 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from pkpdapp.models import Profile
+
+
+def add_profile_on_user_save(sender, **kwargs):
+ if kwargs['created']:
+ Profile.objects.create(user=kwargs['instance']).save()
diff --git a/pkpdapp/pkpdapp/tasks.py b/pkpdapp/pkpdapp/tasks.py
new file mode 100644
index 00000000..4f23b12b
--- /dev/null
+++ b/pkpdapp/pkpdapp/tasks.py
@@ -0,0 +1,28 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from celery import shared_task
+
+from pkpdapp.models import (
+ Inference, InferenceMixin
+)
+
+
+@shared_task
+def run_inference(inference_id):
+ inference = Inference.objects.get(id=inference_id)
+
+ print('task', inference.number_of_iterations, inference_id)
+ for ll in inference.log_likelihoods.all():
+ print('LL', ll.id, ll.name, ll.biomarker_type)
+
+ # create the mixin object to run the inference
+ inference_mixin = InferenceMixin(inference)
+ inference_mixin.run_inference()
+
+ # remove task id to indicate that we're finished
+ inference.task_id = None
+ inference.save()
diff --git a/pkpdapp/pkpdapp/tests/__init__.py b/pkpdapp/pkpdapp/tests/__init__.py
new file mode 100644
index 00000000..c062f5b8
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/__init__.py
@@ -0,0 +1,14 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+# flake8: noqa f401
+from .utils import create_pd_inference
+import os
+import django
+
+
+django.setup()
+dummy = ""
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pkpdapp.settings')
diff --git a/pkpdapp/pkpdapp/tests/test_models/__init__.py b/pkpdapp/pkpdapp/tests/test_models/__init__.py
new file mode 100644
index 00000000..d0505307
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/__init__.py
@@ -0,0 +1,5 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_biomarker_type.py b/pkpdapp/pkpdapp/tests/test_models/test_biomarker_type.py
new file mode 100644
index 00000000..e02f4b10
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_biomarker_type.py
@@ -0,0 +1,135 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pkpdapp.tests # noqa: F401
+from django.test import TestCase
+from pkpdapp.models import (
+ Dataset,
+ BiomarkerType,
+ Biomarker,
+ Unit,
+ Subject,
+)
+from django.utils import timezone
+from django.db.utils import IntegrityError
+import numpy as np
+
+
+class TestBiomarkerTypeModel(TestCase):
+ def setUp(self):
+ self.dataset = Dataset.objects.create(
+ name='my_cool_dataset',
+ datetime=timezone.now(),
+ description='description for my cool biomarker',
+ )
+
+ self.unit = Unit.objects.get(symbol='mg')
+ self.time_unit = Unit.objects.get(symbol='h')
+ self.biomarker_type = BiomarkerType.objects.create(
+ name='my_cool_biomarker_type',
+ description='description for my cool biomarker_type',
+ dataset=self.dataset,
+ stored_unit=self.unit,
+ display_unit=self.unit,
+ stored_time_unit=self.time_unit,
+ display_time_unit=self.time_unit,
+ )
+ self.biomarker_type2 = BiomarkerType.objects.create(
+ name='my_cool_biomarker_type 2',
+ description='description for my cool biomarker_type',
+ dataset=self.dataset,
+ stored_unit=self.unit,
+ display_unit=self.unit,
+ stored_time_unit=self.time_unit,
+ display_time_unit=self.time_unit,
+ )
+ self.subjects = [
+ Subject.objects.create(
+ id_in_dataset=1,
+ dataset=self.dataset,
+ ),
+ Subject.objects.create(
+ id_in_dataset=2,
+ dataset=self.dataset,
+ ),
+ ]
+
+ self.values = [0, 1, 2, 3]
+ self.times = [0, 2, 4, 6]
+ self.biomarker_subjects = [
+ self.subjects[0].id, self.subjects[0].id, self.subjects[0].id,
+ self.subjects[1].id
+ ]
+ self.biomarkers = [
+ Biomarker.objects.create(
+ time=time,
+ subject=self.subjects[0],
+ biomarker_type=self.biomarker_type,
+ value=value
+ ) for value, time in zip(self.values[:-1], self.times[:-1])
+ ]
+ self.biomarkers.append(
+ Biomarker.objects.create(
+ time=self.times[-1],
+ subject=self.subjects[1],
+ biomarker_type=self.biomarker_type,
+ value=self.values[-1]
+ )
+ )
+
+ def test_biomarker_type_creation(self):
+ self.assertTrue(
+ isinstance(self.biomarker_type, BiomarkerType)
+ )
+
+ def test_str(self):
+ self.assertEqual(
+ str(self.biomarker_type), "my_cool_biomarker_type"
+ )
+
+ def test_requires_a_unit(self):
+ with self.assertRaises(IntegrityError):
+ BiomarkerType.objects.create(
+ name='my_cool_biomarker_type2',
+ description='description',
+ dataset=self.dataset,
+ )
+
+ def test_unit_conversion(self):
+ new_unit = Unit.objects.get(symbol='g')
+ old_values = self.biomarker_type.data()['values']
+ self.biomarker_type.display_unit = new_unit
+ self.biomarker_type.save()
+ new_values = self.biomarker_type.data()['values']
+ np.testing.assert_array_equal(
+ old_values, 1e3 * new_values
+ )
+
+ def test_as_pandas(self):
+ df = self.biomarker_type.data()
+ np.testing.assert_array_equal(
+ df['values'], np.array(self.values)
+ )
+ np.testing.assert_array_equal(
+ df['times'], np.array(self.times)
+ )
+ np.testing.assert_array_equal(
+ df['subjects'], np.array(self.biomarker_subjects)
+ )
+
+ df = self.biomarker_type.data(first_time_only=True)
+
+ np.testing.assert_array_equal(
+ df['times'], [self.times[0], self.times[3]]
+ )
+ np.testing.assert_array_equal(
+ df['values'], [self.values[0], self.values[3]]
+ )
+
+ def test_empty_data(self):
+ df = self.biomarker_type2.data()
+ for key in ['values', 'times', 'subjects']:
+ self.assertEqual(len(df[key]), 0)
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_dataset.py b/pkpdapp/pkpdapp/tests/test_models/test_dataset.py
new file mode 100644
index 00000000..db9a7825
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_dataset.py
@@ -0,0 +1,64 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pkpdapp.tests # noqa: F401
+from django.test import TestCase
+from pkpdapp.models import (
+ Dataset,
+ BiomarkerType,
+ Biomarker,
+ Unit,
+ Subject,
+)
+from django.utils import timezone
+
+
+class TestBiomarkerTypeModel(TestCase):
+ def setUp(self):
+ self.dataset = Dataset.objects.create(
+ name='my_cool_dataset',
+ datetime=timezone.now(),
+ description='description for my cool biomarker',
+ )
+
+ self.unit = Unit.objects.get(symbol='mg')
+ self.time_unit = Unit.objects.get(symbol='h')
+ self.biomarker_type = BiomarkerType.objects.create(
+ name='my_cool_biomarker_type',
+ description='description for my cool biomarker_type',
+ dataset=self.dataset,
+ stored_unit=self.unit,
+ display_unit=self.unit,
+ stored_time_unit=self.time_unit,
+ display_time_unit=self.time_unit,
+ )
+ self.subject = Subject.objects.create(
+ id_in_dataset=1,
+ dataset=self.dataset,
+ )
+ self.values = [0, 1, 2]
+ self.times = [0, 2, 4]
+ self.subjects = [self.subject.id, self.subject.id, self.subject.id]
+ self.biomarkers = [
+ Biomarker.objects.create(
+ time=time,
+ subject=self.subject,
+ biomarker_type=self.biomarker_type,
+ value=value
+ ) for value, time in zip(self.values, self.times)
+ ]
+
+ def test_dataset_creation(self):
+ self.assertTrue(
+ isinstance(self.dataset, Dataset)
+ )
+
+ def test_dataset_deletion(self):
+ self.dataset.delete()
+ with self.assertRaises(BiomarkerType.DoesNotExist):
+ BiomarkerType.objects.get(id=self.biomarker_type.id)
+ with self.assertRaises(Biomarker.DoesNotExist):
+ Biomarker.objects.get(id=self.biomarkers[0].id)
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_inference.py b/pkpdapp/pkpdapp/tests/test_models/test_inference.py
new file mode 100644
index 00000000..59abcc67
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_inference.py
@@ -0,0 +1,52 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from django.test import TestCase
+from pkpdapp.models import (
+ InferenceResult, InferenceMixin,
+ InferenceFunctionResult
+)
+import numpy as np
+from pkpdapp.tests import create_pd_inference
+
+
+class TestInferenceSerializer(TestCase):
+ def setUp(self):
+ self.inference, log_likelihood, _, _, \
+ self.model, _ = create_pd_inference(
+ sampling=False)
+
+ # set uniform prior on first param, except amounts
+ self.param = log_likelihood.parameters.first()
+ self.param.set_uniform_prior(0.0, 2.0)
+
+ def test_run_inference(self):
+ self.inference.run_inference(test=True)
+ self.assertEqual(self.inference.name, 'bob')
+ self.assertEqual(self.inference.log_likelihoods.count(), 8)
+
+ def test_set_variables_from_inference(self):
+ inference_mixin = InferenceMixin(self.inference)
+ inference_mixin.run_inference()
+ chains = self.inference.chains.all()
+ results = np.array(InferenceResult.objects.filter(
+ chain__in=chains
+ ).order_by(
+ 'iteration', 'chain'
+ ).values_list('value', flat=True))
+ fresults = np.array(InferenceFunctionResult.objects.filter(
+ chain__in=chains
+ ).order_by(
+ 'iteration', 'chain'
+ ).values_list('value', flat=True))
+ max_value = results[np.argmax(fresults)]
+
+ fitted_variable = self.param.variable
+ old_value = fitted_variable.default_value
+ self.model.set_variables_from_inference(self.inference)
+ fitted_variable.refresh_from_db()
+ new_value = fitted_variable.default_value
+ self.assertEqual(new_value, max_value)
+ self.assertNotEqual(old_value, new_value)
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_inference_mixin.py b/pkpdapp/pkpdapp/tests/test_models/test_inference_mixin.py
new file mode 100644
index 00000000..a7d0f370
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_inference_mixin.py
@@ -0,0 +1,340 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.test import TestCase
+import numpy as np
+from pkpdapp.models import (
+ LogLikelihood,
+ InferenceMixin, InferenceChain, InferenceResult,
+ InferenceFunctionResult, LogLikelihoodParameter,
+)
+from pkpdapp.tests import create_pd_inference
+from django.core.cache import cache
+
+
+class TestInferenceMixinSingleOutputSampling(TestCase):
+ def setUp(self):
+ # ensure we've got nothing in the cache
+ cache._cache.flush_all()
+
+ self.inference, log_likelihood, _, _, _, _ = create_pd_inference(True)
+
+ # set uniform prior on everything, except amounts
+ for param in log_likelihood.parameters.all():
+ param.set_uniform_prior(0.0, 2.0)
+
+ # 'run' inference to create copies of models
+ self.inference.run_inference(test=True)
+
+ # create mixin object
+ self.inference_mixin = InferenceMixin(self.inference)
+
+ def test_objective_functions(self):
+ # Test log-posterior
+ log_posterior = self.inference_mixin._pints_log_posterior
+ log_posterior(
+ log_posterior.to_search([1.3, 0.5, 1.1, 0.9, 1.2, 1])
+ )
+
+ def test_inference_runs(self):
+ # tests that inference runs and writes results to db
+
+ self.inference_mixin.run_inference()
+
+ chains = self.inference_mixin.inference.chains.all()
+ self.assertEqual(len(chains), 3)
+ for chain in chains:
+ priors = self.inference_mixin._priors
+ fun_res = chain.inference_function_results
+ f_vals = fun_res.order_by('iteration').values_list(
+ 'value', flat=True
+ )
+ self.assertEqual(len(f_vals), 11)
+ p_vals_all = []
+ for prior in priors:
+ res = chain.inference_results.filter(log_likelihood=prior)
+ p_vals = res.order_by('iteration').values_list(
+ 'value', flat=True
+ )
+ self.assertEqual(len(p_vals), 11)
+ p_vals_all.append(p_vals)
+ iterations = res.order_by('iteration').values_list(
+ 'iteration', flat=True
+ )
+ expected = list(range(11))
+ self.assertTrue(np.array_equal(iterations, expected))
+
+ # transpose list of lists
+ p_vals_all = list(map(list, zip(*p_vals_all)))
+ fn = self.inference_mixin._pints_log_posterior
+ for idx, params in enumerate(p_vals_all):
+ print(f'comparing {fn(fn.to_search(params))} to {f_vals[idx]}')
+ self.assertTrue(
+ abs(fn(fn.to_search(params)) - f_vals[idx]) < 0.01
+ )
+
+ output_res = chain.inference_output_results.all()
+ self.assertTrue(len(output_res), 28)
+
+ inference = self.inference_mixin.inference
+ self.assertTrue(inference.time_elapsed > 0)
+ self.assertTrue(inference.number_of_function_evals > 0)
+
+
+class TestInferenceMixinSingleOutput(TestCase):
+ def setUp(self):
+ # ensure we've got nothing in the cache
+ cache._cache.flush_all()
+
+ self.inference, log_likelihood, _, _, _, _ = create_pd_inference()
+
+ # set uniform prior on everything, except amounts
+ for param in log_likelihood.parameters.all():
+ param.set_uniform_prior(0.0, 2.0)
+
+ # 'run' inference to create copies of models
+ self.inference.run_inference(test=True)
+
+ # create mixin object
+ self.inference_mixin = InferenceMixin(self.inference)
+
+ def test_inference_runs(self):
+ # tests that inference runs and writes results to db
+ self.inference_mixin.run_inference()
+
+ chains = self.inference_mixin.inference.chains.all()
+ self.assertEqual(len(chains), 3)
+ priors = self.inference_mixin._priors
+ for chain in chains:
+ fun_res = chain.inference_function_results
+ f_vals = fun_res.order_by('iteration').values_list(
+ 'value', flat=True
+ )
+ self.assertEqual(len(f_vals), 11)
+ p_vals_all = []
+ for prior in priors:
+ res = chain.inference_results.filter(log_likelihood=prior)
+ p_vals = res.order_by('iteration').values_list(
+ 'value', flat=True
+ )
+ self.assertEqual(len(p_vals), 11)
+ p_vals_all.append(p_vals)
+ iterations = res.order_by('iteration').values_list(
+ 'iteration', flat=True
+ )
+ expected = list(range(11))
+ self.assertTrue(np.array_equal(iterations, expected))
+
+ # don't test for inference log_posterior(param) = fn since they won't
+ # because of the way the 'best' params are picked
+
+ inference = self.inference_mixin.inference
+ self.assertTrue(inference.time_elapsed > 0)
+ self.assertTrue(inference.number_of_function_evals > 0)
+
+ def test_inference_can_be_restarted(self):
+ self.inference.chains.all().delete()
+ self.inference.chains.set([
+ InferenceChain.objects.create(inference=self.inference)
+ for i in range(self.inference.number_of_chains)
+ ])
+ self.inference.refresh_from_db()
+ for chain in self.inference.chains.all():
+ chain.inference_function_results.add(
+ InferenceFunctionResult.objects.create(
+ chain=chain,
+ iteration=0,
+ value=1.4
+ ),
+ InferenceFunctionResult.objects.create(
+ chain=chain,
+ iteration=1,
+ value=2.4
+ )
+ )
+ for prior in self.inference_mixin._priors:
+ chain.inference_results.add(
+ InferenceResult.objects.create(
+ chain=chain,
+ log_likelihood=prior,
+ iteration=0,
+ value=0.5,
+ ),
+ InferenceResult.objects.create(
+ chain=chain,
+ log_likelihood=prior,
+ iteration=1,
+ value=0.4,
+ )
+ )
+ chain.refresh_from_db()
+ self.inference.number_of_iterations = 1
+ self.inference.save()
+
+ # tests that inference runs and writes results to db
+ inference_mixin = InferenceMixin(self.inference)
+ inference_mixin.run_inference()
+
+ chains = inference_mixin.inference.chains.all()
+ self.assertEqual(len(chains), 3)
+ for chain in chains:
+ priors = inference_mixin._priors
+ fun_res = chain.inference_function_results
+ f_vals = fun_res.order_by('iteration').values_list(
+ 'value', flat=True
+ )
+ self.assertEqual(len(f_vals), 11)
+ p_vals_all = []
+ for prior in priors:
+ res = chain.inference_results.filter(log_likelihood=prior)
+ p_vals = res.order_by('iteration').values_list(
+ 'value', flat=True
+ )
+ self.assertEqual(len(p_vals), 11)
+ p_vals_all.append(p_vals)
+ iterations = res.order_by('iteration').values_list(
+ 'iteration', flat=True
+ )
+ expected = list(range(11))
+ self.assertTrue(np.array_equal(iterations, expected))
+
+
+class TestInferenceMixinSingleOutputOptimisationPopulation(TestCase):
+ def setUp(self):
+ # ensure we've got nothing in the cache
+ cache._cache.flush_all()
+
+ self.inference, log_likelihood, biomarker_type, \
+ _, _, _ = create_pd_inference()
+
+ # set uniform prior on everything, except
+ # we'll do a population prior on the first one
+ for i, param in enumerate(log_likelihood.parameters.all()):
+ if i == 0:
+ param.set_uniform_prior(
+ 0.0, 2.0, biomarker_type=biomarker_type
+ )
+ else:
+ param.set_uniform_prior(0.0, 2.0)
+
+ # 'run' inference to create copies of models
+ self.inference.run_inference(test=True)
+
+ # create mixin object
+ self.inference_mixin = InferenceMixin(self.inference)
+
+ def test_inference_runs(self):
+ # tests that inference runs and writes results to db
+ self.inference_mixin.run_inference()
+
+ chains = self.inference_mixin.inference.chains.all()
+ self.assertEqual(len(chains), 3)
+ priors = self.inference_mixin._priors
+ for chain in chains:
+ fun_res = chain.inference_function_results
+ f_vals = fun_res.order_by('iteration').values_list(
+ 'value', flat=True
+ )
+ self.assertEqual(len(f_vals), 11)
+ for prior in priors:
+ res = chain.inference_results.filter(log_likelihood=prior)
+ p_vals = res.order_by('iteration').values_list(
+ 'value', flat=True
+ )
+ length = prior.get_total_length()
+ self.assertEqual(len(p_vals), 11 * length)
+
+ # don't test for inference log_posterior(param) = fn since they won't
+ # because of the way the 'best' params are picked
+
+ inference = self.inference_mixin.inference
+ self.assertTrue(inference.time_elapsed > 0)
+ self.assertTrue(inference.number_of_function_evals > 0)
+
+
+class TestInferenceMixinSingleOutputOptimisationCovariate(TestCase):
+ def setUp(self):
+ # ensure we've got nothing in the cache
+ cache._cache.flush_all()
+
+ self.inference, log_likelihood, biomarker_type, \
+ covariate_biomarker_type, _, _ = create_pd_inference()
+
+ # set uniform prior on everything, except
+ # we'll do a population prior on the first one
+ for i, param in enumerate(log_likelihood.parameters.all()):
+ if i == 0:
+ # first param is sampled from a normal distribution with a mean
+ # derived from subject body weight
+ param.child.biomarker_type = covariate_biomarker_type
+ param.child.time_independent_data = True
+ param.child.form = LogLikelihood.Form.NORMAL
+ param.child.save()
+ body_weight_values, _, subjects = param.child.get_data()
+ param.length = len(subjects)
+ param.save()
+
+ # use a covariate to adjust the mean of the normal according to
+ # body weight
+ mean, sigma = param.child.get_noise_log_likelihoods()
+ mean.form = LogLikelihood.Form.EQUATION
+ mean.description = '1.0 if arg0 < 20 else 2.0'
+
+ mean.biomarker_type = covariate_biomarker_type
+ mean.time_independent_data = True
+ mean.save()
+ body_weight = LogLikelihood.objects.create(
+ name='Body weight',
+ inference=self.inference,
+ form=LogLikelihood.Form.FIXED,
+ biomarker_type=covariate_biomarker_type,
+ time_independent_data=True,
+ )
+ LogLikelihoodParameter.objects.create(
+ name='Body weight',
+ parent=mean,
+ child=body_weight,
+ parent_index=0,
+ length=len(subjects)
+ )
+ sigma.value = 0.01
+ sigma.save()
+ else:
+ param.set_uniform_prior(0.0, 2.0)
+
+ # 'run' inference to create copies of models
+ self.inference.run_inference(test=True)
+
+ # create mixin object
+ self.inference_mixin = InferenceMixin(self.inference)
+
+ def test_inference_runs(self):
+ # tests that inference runs and writes results to db
+ self.inference_mixin.run_inference()
+
+ chains = self.inference_mixin.inference.chains.all()
+ self.assertEqual(len(chains), 3)
+ priors = self.inference_mixin._priors
+ for chain in chains:
+ fun_res = chain.inference_function_results
+ f_vals = fun_res.order_by('iteration').values_list(
+ 'value', flat=True
+ )
+ self.assertEqual(len(f_vals), 11)
+ for prior in priors:
+ res = chain.inference_results.filter(log_likelihood=prior)
+ p_vals = res.order_by('iteration').values_list(
+ 'value', flat=True
+ )
+ length = prior.get_total_length()
+ self.assertEqual(len(p_vals), 11 * length)
+
+ # don't test for inference log_posterior(param) = fn since they won't
+ # because of the way the 'best' params are picked
+
+ inference = self.inference_mixin.inference
+ self.assertTrue(inference.time_elapsed > 0)
+ self.assertTrue(inference.number_of_function_evals > 0)
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_loglikelihood.py b/pkpdapp/pkpdapp/tests/test_models/test_loglikelihood.py
new file mode 100644
index 00000000..db0e4992
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_loglikelihood.py
@@ -0,0 +1,100 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.test import TestCase
+from pkpdapp.models import (
+ LogLikelihood,
+ LogLikelihoodParameter,
+)
+from pkpdapp.tests import create_pd_inference
+
+
+class TestInferenceMixinPdModel(TestCase):
+ def setUp(self):
+ self.inference, self.log_likelihood, self.biomarker_type, \
+ self.covariate_biomarker_type, self.model, \
+ _ = create_pd_inference(
+ sampling=True)
+
+ def test_create_pymc3_model(self):
+
+ # add a prior on the first param
+ first_param = self.log_likelihood.parameters.first()
+ prior_name = first_param.child.name
+ first_param.child.form = LogLikelihood.Form.NORMAL
+ first_param.child.save()
+
+ output = self.log_likelihood.parents.first()
+ model = output.create_pymc3_model()
+
+ # check everything is in there
+ model[prior_name]
+ model[output.name]
+ model.logp({prior_name: 0.3})
+
+ # check we can run predictive posteriors
+ model.fastfn([
+ model[self.log_likelihood.name + output.name]
+ ])
+
+ def test_population_model_with_covariate(self):
+ output = self.log_likelihood.parents.first()
+
+ values, times, subjects = output.get_data()
+ n_subjects = len(set(subjects))
+ print('n_subjects', n_subjects)
+
+ # first param is sampled from a normal distribution with a mean
+ # derived from subject body weight
+ first_param = self.log_likelihood.parameters.first()
+ first_param.length = n_subjects
+ first_param.save()
+ first_param.child.biomarker_type = self.covariate_biomarker_type
+ first_param.child.time_independent_data = True
+ first_param.child.form = LogLikelihood.Form.NORMAL
+ first_param.child.save()
+
+ # use a covariate to adjust the mean of the normal according to body
+ # weight
+ mean, sigma = first_param.child.get_noise_log_likelihoods()
+ mean.form = LogLikelihood.Form.EQUATION
+ mean.description = '1.0 if arg0 < 20 else 2.0'
+
+ mean.biomarker_type = self.covariate_biomarker_type
+ mean.time_independent_data = True
+ mean.save()
+ body_weight = LogLikelihood.objects.create(
+ name='Body weight',
+ inference=self.inference,
+ form=LogLikelihood.Form.FIXED,
+ biomarker_type=self.covariate_biomarker_type,
+ time_independent_data=True,
+ )
+ body_weight_values, _, subjects = body_weight.get_data()
+ LogLikelihoodParameter.objects.create(
+ name='Body weight',
+ parent=mean,
+ child=body_weight,
+ parent_index=0,
+ length=len(subjects)
+ )
+ sigma.value = 0.01
+ sigma.save()
+
+ model = output.create_pymc3_model()
+
+ model.logp({first_param.child.name: [0.3] * n_subjects})
+
+ max_logp = model[first_param.child.name].logp({
+ first_param.child.name: [
+ 1.0 if value < 20 else 2.0
+ for value in body_weight_values
+ ]
+ })
+ lower_logp = model[first_param.child.name].logp({
+ first_param.child.name: [1.0] * n_subjects
+ })
+ self.assertLess(lower_logp, max_logp)
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_mechanistic_model.py b/pkpdapp/pkpdapp/tests/test_models/test_mechanistic_model.py
new file mode 100644
index 00000000..38e93670
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_mechanistic_model.py
@@ -0,0 +1,136 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from django.test import TestCase
+from pkpdapp.models import (
+ PharmacodynamicModel,
+ Protocol,
+ PharmacokineticModel,
+ CombinedModel,
+ Dose,
+ Unit,
+)
+import myokit
+from django.core.exceptions import ValidationError
+from django.core.cache import cache
+import numpy as np
+
+
+class TestPharmodynamicModel(TestCase):
+ def setUp(self):
+ cache.clear()
+
+ def test_model_bad_mmt(self):
+ with self.assertRaises(myokit.ParseError):
+ PharmacodynamicModel.objects.create(
+ name="my_cool_model",
+ description="description for my cool model",
+ mmt="this is not sbml",
+ )
+
+ def test_model_clean(self):
+ m = PharmacodynamicModel(
+ name="my_cool_model",
+ description="description for my cool model",
+ mmt="this is not xml",
+ )
+ with self.assertRaises(ValidationError):
+ m.clean()
+
+ def test_model_creation(self):
+ m = PharmacodynamicModel.objects.create(
+ name="my_cool_model",
+ description="description for my cool model",
+ )
+ self.assertTrue(isinstance(m, PharmacodynamicModel))
+
+ def test_myokit_model(self):
+ m = PharmacodynamicModel.objects.get(
+ name="tumour_growth_gompertz",
+ )
+ model = m.get_myokit_model()
+ model_variables = [v.name() for v in model.variables()]
+ test_model_variables = ["TS0", "TSmax", "beta", "Growth", "TS", "t"]
+ self.assertCountEqual(model_variables, test_model_variables)
+
+
+class TestDosedPharmokineticModel(TestCase):
+ def setUp(self):
+ cache.clear()
+ self.pk = PharmacokineticModel.objects.get(
+ name="one_compartment_clinical",
+ )
+
+ self.model = CombinedModel.objects.create(
+ pk_model=self.pk,
+ )
+
+ self.p = Protocol.objects.create(
+ amount_unit=Unit.objects.get(symbol="pmol"),
+ time_unit=Unit.objects.get(symbol="h"),
+ name="my_cool_protocol",
+ dose_type=Protocol.DoseType.INDIRECT,
+ )
+
+ v = self.model.variables.get(qname="PKCompartment.A1")
+ v.protocol = self.p
+ v.save()
+
+ def test_store_model(self):
+ stored_model = self.model.create_stored_model()
+ self.assertTrue(isinstance(stored_model, CombinedModel))
+ self.assertTrue(stored_model.read_only)
+ self.assertEqual(
+ len(stored_model.variables.all()), len(self.model.variables.all())
+ )
+ v = stored_model.variables.get(qname="PKCompartment.A1")
+ self.assertEqual(v.protocol.name, "my_cool_protocol")
+ self.assertNotEqual(v.protocol.id, self.p.id)
+
+ def test_reset_to_default(self):
+ v = self.model.variables.get(qname="PKCompartment.CL")
+ self.assertNotEqual(v.default_value, 8)
+ self.assertNotEqual(v.unit.symbol, "mL/h")
+
+ self.model.reset_params_to_defaults("H", "LM")
+
+ v = self.model.variables.get(qname="PKCompartment.CL")
+ self.assertEqual(v.default_value, 8)
+ self.assertEqual(v.unit.symbol, "mL/h")
+
+ def test_myokit_model(self):
+ model = self.model.get_myokit_model()
+ pk_model = self.pk.get_myokit_model()
+ model_variables = [v.name() for v in model.variables()]
+ pk_model_variables = [v.name() for v in pk_model.variables()]
+
+ # check that the absorption_rate and dose_rate variable has been added,
+ # and the extra drug_amount state variable
+ self.assertCountEqual(
+ model_variables,
+ pk_model_variables,
+ )
+
+ # run a simulation with a a dose events
+ Dose.objects.create(
+ protocol=self.p,
+ start_time=0,
+ duration=0.1,
+ amount=1000,
+ )
+
+ # dosed model should have a concentration at t ~ 0.5
+ # of greater than 0.01
+ sim = self.model.get_myokit_simulator()
+
+ output = sim.run(self.model.time_max)
+ index = np.where(np.array(output["environment.t"]) > 0.5)[0][0]
+ self.assertGreater(output["PKCompartment.C1"][index], 0.01)
+
+ # non-dosed model should have a concentration at t ~ 0.5 of near zero
+ pk_sim = self.pk.get_myokit_simulator()
+ output = pk_sim.run(self.pk.time_max)
+ index = np.where(np.array(output["environment.t"]) > 0.5)[0][0]
+ self.assertLess(output["PKCompartment.C1"][index], 1e-6)
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_myokit_forward_model.py b/pkpdapp/pkpdapp/tests/test_models/test_myokit_forward_model.py
new file mode 100644
index 00000000..0dbdd119
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_myokit_forward_model.py
@@ -0,0 +1,230 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pkpdapp.tests # noqa: F401
+from django.test import TestCase
+from numpy.testing import assert_almost_equal
+from pkpdapp.models import (
+ PharmacodynamicModel,
+ MyokitForwardModel,
+ PharmacokineticModel
+)
+import numpy as np
+
+
+class TestMyokitForwardModelSingleOutput(TestCase):
+ def setUp(self):
+ m = PharmacodynamicModel.objects.get(
+ name='tumour_growth_gompertz',
+ )
+ self.model = m.get_myokit_model()
+ self.simulator = m.get_myokit_simulator()
+
+ self.parameter_dict = {
+ 'PDCompartment.beta': 1,
+ 'PDCompartment.TS0': 1,
+ 'PDCompartment.TSmax': 1,
+ }
+
+ all_keys = list(self.parameter_dict.keys())
+ self.fixed_dict = {
+ 'PDCompartment.TS0': 1,
+ }
+
+ variable_keys = (
+ [k for k in all_keys if k not in list(self.fixed_dict.keys())]
+ )
+ self.variable_parameter_values = [self.parameter_dict[v]
+ for v in variable_keys]
+
+ def test_run_myokit_pints_forward_model(self):
+ times = np.linspace(0, 100)
+
+ forward_model = MyokitForwardModel(
+ myokit_model=self.model,
+ myokit_simulator=self.simulator,
+ outputs=["PDCompartment.TS"],
+ times=[times],
+ fixed_parameter_dict=self.fixed_dict,
+ conversion_factors=[1.0],
+ )
+
+ z = forward_model.simulate(self.variable_parameter_values)
+ self.assertEqual(len(z), 1)
+ self.assertEqual(len(z[0]), len(times))
+
+ # try without any fixed parameters
+ forward_model = MyokitForwardModel(
+ myokit_model=self.model,
+ myokit_simulator=self.simulator,
+ outputs=["PDCompartment.TS"],
+ times=[times],
+ conversion_factors=[1.0],
+ )
+ z1 = forward_model.simulate(list(self.parameter_dict.values()))
+ self.assertTrue(np.array_equal(z, z1))
+
+ # try model with different variable parameters and check output differs
+ new_fixed_dict = {
+ 'PDCompartment.TS0': 2,
+ }
+ forward_model = MyokitForwardModel(
+ myokit_model=self.model,
+ myokit_simulator=self.simulator,
+ outputs=["PDCompartment.TS"],
+ times=[times],
+ fixed_parameter_dict=new_fixed_dict,
+ conversion_factors=[1.0],
+ )
+ z3 = forward_model.simulate(self.variable_parameter_values)
+ self.assertTrue(not np.array_equal(z3, z))
+
+ # check model with different parameter inputs gives different result
+ self.variable_parameter_values[0] = 7
+ forward_model = MyokitForwardModel(
+ myokit_model=self.model,
+ myokit_simulator=self.simulator,
+ outputs=["PDCompartment.TS"],
+ times=[times],
+ fixed_parameter_dict=new_fixed_dict,
+ conversion_factors=[1.0],
+ )
+ z4 = forward_model.simulate(self.variable_parameter_values)
+ self.assertTrue(not np.array_equal(z4, z3))
+
+ # try with subjects now, should get same result
+ times = np.linspace(0, 100)
+ n_subjects = 7
+ subjects = list(range(n_subjects)) * (len(times) // n_subjects + 1)
+ subjects = subjects[:len(times)]
+ all_keys = list(self.parameter_dict.keys())
+
+ fixed_dict = {
+ 'PDCompartment.TS0': [1] * n_subjects,
+ }
+
+ variable_keys = (
+ [k for k in all_keys if k not in list(self.fixed_dict.keys())]
+ )
+ variable_parameter_values = [
+ [self.parameter_dict[v]] * n_subjects for v in variable_keys
+ ]
+ variable_parameter_values = np.array(variable_parameter_values)
+ print('variable_parameter_values', variable_parameter_values.shape)
+
+ forward_model = MyokitForwardModel(
+ myokit_model=self.model,
+ myokit_simulator=self.simulator,
+ outputs=["PDCompartment.TS"],
+ times=[times],
+ subjects=[subjects],
+ fixed_parameter_dict=fixed_dict,
+ conversion_factors=[1.0],
+ )
+
+ z_subjects = forward_model.simulate(variable_parameter_values)
+ self.assertEqual(len(z_subjects), 1)
+ self.assertEqual(len(z_subjects[0]), len(times))
+ np.testing.assert_almost_equal(z_subjects[0], z[0])
+
+
+class TestMyokitPintsForwardModelMultipleOutput(TestCase):
+ def setUp(self):
+ m = PharmacokineticModel.objects.get(
+ name='three_compartment_preclinical',
+ )
+ self.model = m.get_myokit_model()
+ self.simulator = m.get_myokit_simulator()
+
+ def test_runs(self):
+ # all parameters are:
+ # full_dict = {
+ # 'PKCompartment.tlag': 1,
+ # 'PKCompartment.ka': 1,
+ # 'PKCompartment.F': 1,
+ # 'PKCompartment.V1': 1,
+ # 'PKCompartment.V2': 1,
+ # 'PKCompartment.V3': 1,
+ # 'PKCompartment.CL': 1,
+ # 'PKCompartment.Q1': 1,
+ # 'PKCompartment.Q2': 1,
+ # 'PKCompartment.CLmax': 1,
+ # 'PKCompartment.Km': 1,
+ # 'PKCompartment.ke0': 1,
+ # 'PKCompartment.Kpu': 1,
+ # }
+ fixed_dict = {
+ 'PKCompartment.tlag': 1,
+ 'PKCompartment.CLmax': 1,
+ 'PKCompartment.ke0': 1,
+ }
+ variable_parameters = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
+
+ desired_outputs = [
+ 'PKCompartment.A1',
+ 'PKCompartment.A2',
+ 'PKCompartment.A3',
+ ]
+
+ conversion_factors = [
+ 1.0,
+ 1.0,
+ 1.0,
+ ]
+
+ times = [
+ np.linspace(0, 100, 33),
+ np.linspace(0, 100, 10),
+ np.linspace(0, 100, 20),
+ ]
+
+ forward_model = MyokitForwardModel(
+ myokit_model=self.model,
+ myokit_simulator=self.simulator,
+ fixed_parameter_dict=fixed_dict,
+ outputs=desired_outputs,
+ times=times,
+ conversion_factors=conversion_factors
+ )
+
+ z = forward_model.simulate(variable_parameters)
+ self.assertEqual(len(z), 3)
+ self.assertEqual(len(z[0]), 33)
+ self.assertEqual(len(z[1]), 10)
+ self.assertEqual(len(z[2]), 20)
+
+ # do another ordering
+ desired_outputs = [
+ 'PKCompartment.A3',
+ 'PKCompartment.A1',
+ 'PKCompartment.A2',
+ ]
+
+ conversion_factors = [
+ 1.0,
+ 1.0,
+ 1.0,
+ ]
+
+ times = [
+ np.linspace(0, 100, 20),
+ np.linspace(0, 100, 33),
+ np.linspace(0, 100, 10),
+ ]
+
+ forward_model = MyokitForwardModel(
+ myokit_model=self.model,
+ myokit_simulator=self.simulator,
+ outputs=desired_outputs,
+ times=times,
+ fixed_parameter_dict=fixed_dict,
+ conversion_factors=conversion_factors
+ )
+
+ z_new = forward_model.simulate(variable_parameters)
+ assert_almost_equal(z_new[0], z[2])
+ assert_almost_equal(z_new[1], z[0])
+ assert_almost_equal(z_new[2], z[1])
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_other.py b/pkpdapp/pkpdapp/tests/test_models/test_other.py
new file mode 100644
index 00000000..002dc179
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_other.py
@@ -0,0 +1,89 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import pkpdapp.tests # noqa: F401
+from django.test import TestCase
+from pkpdapp.models import (
+ Dataset, Project,
+ PharmacodynamicModel,
+ Compound,
+)
+from django.contrib.auth.models import User
+from django.utils import timezone
+
+
+class TestCompoundModel(TestCase):
+ def test_model_creation(self):
+ c = Compound.objects.create(
+ name='my_cool_compound',
+ description='placebo',
+ molecular_mass=100,
+ target_molecular_mass=100,
+ )
+ self.assertTrue(isinstance(c, Compound))
+
+
+class TestProfileModel(TestCase):
+ def test_profile_creation(self):
+ u = User.objects.create_user(
+ 'john', 'lennon@thebeatles.com', 'johnpassword'
+ )
+ c = Compound.objects.create(
+ name='my_cool_compound',
+ description='placebo',
+ molecular_mass=100,
+ target_molecular_mass=100,
+ )
+ p = Project.objects.create(
+ name='my_cool_project',
+ description='description for my cool project',
+ compound=c,
+ )
+ self.assertEqual(u.profile.user.username, 'john')
+ u.profile.selected_project = p
+ self.assertEqual(u.profile.selected_project, p)
+
+
+class TestProjectModel(TestCase):
+ def setUp(self):
+ c = Compound.objects.create(
+ name='my_cool_compound',
+ description='placebo',
+ molecular_mass=100,
+ target_molecular_mass=100,
+ )
+
+ Project.objects.create(
+ name='my_cool_project',
+ description='description for my cool project',
+ compound=c,
+ )
+
+ def test_project_creation(self):
+ p = Project.objects.get(name='my_cool_project')
+ self.assertTrue(isinstance(p, Project))
+
+ def test_add_to_project(self):
+ p = Project.objects.get(name='my_cool_project')
+ d = Dataset.objects.create(
+ name='my_cool_dataset',
+ datetime=timezone.now(),
+ description='description for my cool dataset',
+ )
+ p.datasets.add(d)
+ self.assertQuerysetEqual(p.datasets.all(), [repr(d)])
+
+ m = PharmacodynamicModel.objects.create(
+ name='my_cool_model',
+ description='description for my cool model',
+ )
+ p.pd_models.add(m)
+ self.assertQuerysetEqual(p.pd_models.all(), [repr(m)])
+
+ u = User.objects.create_user(
+ 'john', 'lennon@thebeatles.com', 'johnpassword'
+ )
+ p.users.add(u)
+ self.assertQuerysetEqual(p.users.all(), [repr(u)])
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_pkpd_model.py b/pkpdapp/pkpdapp/tests/test_models/test_pkpd_model.py
new file mode 100644
index 00000000..fa49f197
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_pkpd_model.py
@@ -0,0 +1,146 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+
+from django.contrib.auth.models import User
+from django.test import TestCase
+from rest_framework.test import APIClient
+
+from pkpdapp.models import (
+ CombinedModel,
+ PharmacodynamicModel,
+ PharmacokineticModel,
+ PkpdMapping,
+ Project,
+ DerivedVariable,
+)
+
+
+class TestPkpdModel(TestCase):
+ def setUp(self):
+ self.project = Project.objects.get(
+ name="demo",
+ )
+
+ user = User.objects.get(username="demo")
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ def test_combined_model_creation(self):
+ pk_model = PharmacokineticModel.objects.get(name="one_compartment_clinical")
+ pd_model = PharmacodynamicModel.objects.get(
+ name="indirect_effects_stimulation_production"
+ )
+ pkpd_model = CombinedModel.objects.create(
+ name="my wonderful model",
+ pk_model=pk_model,
+ pd_model=pd_model,
+ project=self.project,
+ )
+ PkpdMapping.objects.create(
+ pkpd_model=pkpd_model,
+ pk_variable=pkpd_model.variables.get(
+ qname="PKCompartment.C1",
+ ),
+ pd_variable=pkpd_model.variables.get(
+ qname="PDCompartment.C_Drug",
+ ),
+ )
+ vars = pkpd_model.variables.values_list("qname", flat=True)
+ for var in ["PKCompartment.C1", "PDCompartment.C_Drug", "PDCompartment.E"]:
+ self.assertIn(var, vars)
+ self.assertFalse(
+ pkpd_model.get_myokit_model().get("PKCompartment.C1").is_state()
+ )
+ self.assertFalse(
+ pkpd_model.get_myokit_model().get("PKCompartment.C1").is_constant()
+ )
+ self.assertTrue(pkpd_model.get_myokit_model().get("PDCompartment.E").is_state())
+ self.assertFalse(pkpd_model.variables.get(qname="PKCompartment.C1").state)
+ self.assertFalse(pkpd_model.variables.get(qname="PKCompartment.C1").constant)
+ self.assertTrue(pkpd_model.variables.get(qname="PDCompartment.E").state)
+ pkpd_model.get_myokit_model().validate()
+ self.assertFalse(
+ pkpd_model.variables.get(qname="PDCompartment.C_Drug").constant
+ )
+
+ def test_combined_model_with_derived_variable(self):
+ pk_model = PharmacokineticModel.objects.get(name="one_compartment_clinical")
+ pd_model = PharmacodynamicModel.objects.get(
+ name="indirect_effects_stimulation_production"
+ )
+ pkpd_model = CombinedModel.objects.create(
+ name="my wonderful model",
+ pk_model=pk_model,
+ pd_model=pd_model,
+ project=self.project,
+ )
+ DerivedVariable.objects.create(
+ pkpd_model=pkpd_model,
+ pk_variable=pkpd_model.variables.get(
+ qname="PKCompartment.C1",
+ ),
+ type=DerivedVariable.Type.FRACTION_UNBOUND_PLASMA,
+ )
+ derived_var_qname = "PKCompartment.calc_C1_f"
+ PkpdMapping.objects.create(
+ pkpd_model=pkpd_model,
+ pk_variable=pkpd_model.variables.get(
+ qname=derived_var_qname,
+ ),
+ pd_variable=pkpd_model.variables.get(
+ qname="PDCompartment.C_Drug",
+ ),
+ )
+ vars = pkpd_model.variables.values_list("qname", flat=True)
+ for var in [derived_var_qname, "PDCompartment.C_Drug", "PDCompartment.E"]:
+ self.assertIn(var, vars)
+ self.assertFalse(
+ pkpd_model.get_myokit_model().get(derived_var_qname).is_state()
+ )
+ self.assertFalse(
+ pkpd_model.get_myokit_model().get(derived_var_qname).is_constant()
+ )
+ self.assertFalse(
+ pkpd_model.get_myokit_model().get("PDCompartment.C_Drug").is_constant()
+ )
+
+ def test_combine_multiple_pd_models(self):
+ pk = PharmacokineticModel.objects.get(
+ name="one_compartment_preclinical",
+ )
+ pd = PharmacodynamicModel.objects.get(
+ name="tumour_growth_gompertz",
+ )
+ pd2 = PharmacodynamicModel.objects.get(
+ name="tumour_growth_inhibition_delay_cell_distribution_conc_prop_kill", # noqa E501
+ )
+ combined = CombinedModel.objects.create(
+ name="my_combined_model",
+ pk_model=pk,
+ pd_model=pd,
+ pd_model2=pd2,
+ )
+
+ pk_vars = [v.qname() for v in pk.get_myokit_model().variables()]
+ pd_vars = [
+ v.qname()
+ for v in pd.get_myokit_model().variables()
+ if v.qname() != "environment.t"
+ ]
+ pd2_vars = [
+ v.qname().replace("PDCompartment", "PDCompartment2")
+ for v in pd2.get_myokit_model().variables()
+ if v.qname() != "environment.t"
+ ]
+ expected_vars = [v for v in pk_vars + pd_vars + pd2_vars]
+ removed_vars = ["PDCompartment2.TS", "PDCompartment2.TS0"]
+ for var in removed_vars:
+ expected_vars.remove(var)
+ model = combined.get_myokit_model()
+ model_vars = [v.qname() for v in model.variables()]
+ self.assertCountEqual(model_vars, expected_vars)
+ print("combined model validated", model.code())
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_protocol.py b/pkpdapp/pkpdapp/tests/test_models/test_protocol.py
new file mode 100644
index 00000000..ef6b05dd
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_protocol.py
@@ -0,0 +1,36 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pkpdapp.tests # noqa: F401
+from django.test import TestCase
+from pkpdapp.models import (
+ Protocol,
+ Compound,
+ Unit,
+)
+
+
+class TestProtocolModel(TestCase):
+ def test_model_creation(self):
+ au = Unit.objects.get(symbol='mg')
+ tu = Unit.objects.get(symbol='h')
+
+ c = Compound.objects.create(
+ name='my_cool_compound',
+ description='placebo',
+ molecular_mass=100,
+ target_molecular_mass=100,
+ )
+
+ # test optional dataset
+ p = Protocol.objects.create(
+ name='my_cool_protocol',
+ compound=c,
+ amount_unit=au,
+ time_unit=tu,
+ )
+
+ self.assertTrue(isinstance(p, Protocol))
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_subject.py b/pkpdapp/pkpdapp/tests/test_models/test_subject.py
new file mode 100644
index 00000000..a720089f
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_subject.py
@@ -0,0 +1,57 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pkpdapp.tests # noqa: F401
+from django.test import TestCase
+from pkpdapp.models import (
+ Dataset,
+ Subject,
+)
+from django.utils import timezone
+from django.db.utils import IntegrityError
+
+
+class TestSubjectModel(TestCase):
+ def setUp(self):
+ self.dataset = Dataset.objects.create(
+ name='test_subject_model',
+ datetime=timezone.now(),
+ description='description for my cool dataset',
+ )
+
+ def test_subject_creation(self):
+ metadata = {
+ 'test': 2
+ }
+ s = Subject.objects.create(
+ id_in_dataset=1, dataset=self.dataset, metadata=metadata
+ )
+ self.assertTrue(isinstance(s, Subject))
+
+ def test_subject_unique_constraint(self):
+
+ metadata = {
+ 'test': 2
+ }
+ Subject.objects.create(
+ id_in_dataset=2, dataset=self.dataset, metadata=metadata
+ )
+
+ # this is ok
+ d2 = Dataset.objects.create(
+ name='test_subject_model2',
+ datetime=timezone.now(),
+ description='description for my cool dataset',
+ )
+ Subject.objects.create(
+ id_in_dataset=2, dataset=d2, metadata=metadata
+ )
+
+ # this should raise error
+ with self.assertRaises(IntegrityError):
+ Subject.objects.create(
+ id_in_dataset=2, dataset=self.dataset, metadata=metadata
+ )
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_unit.py b/pkpdapp/pkpdapp/tests/test_models/test_unit.py
new file mode 100644
index 00000000..43c61859
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_unit.py
@@ -0,0 +1,77 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pkpdapp.tests # noqa: F401
+from django.test import TestCase
+from pkpdapp.models import (
+ Unit, Compound
+)
+
+
+class TestUnitModel(TestCase):
+ def setUp(self):
+ self.compound = Compound.objects.create(
+ name='test_unit_model',
+ description='description for my cool compound',
+ )
+
+ def check_compatible_unit(
+ self, unit_symbol, compatible_units, compound=None
+ ):
+ unit = Unit.objects.get(symbol=unit_symbol)
+ compat_symbols = [
+ u.symbol for u in unit.get_compatible_units(compound=compound)]
+ self.assertCountEqual(compat_symbols, compatible_units)
+
+ def test_compatible_units(self):
+ self.check_compatible_unit('s', ['s', 'min', 'h', 'day', 'week'])
+ self.check_compatible_unit(
+ 'ng/mL', ['ng/mL', 'µg/mL', 'mg/L', 'ng/L', 'g/L', 'g/dL', 'pg/mL'
+ ])
+
+ def test_compatible_units_mols(self):
+ self.check_compatible_unit('nmol', ['mol', 'nmol', 'pmol', 'µmol'])
+ self.check_compatible_unit(
+ 'nmol',
+ [
+ 'mol', 'nmol', 'pmol', 'µmol', 'mg', 'g', 'ng', 'kg'
+ ],
+ compound=self.compound
+ )
+ self.check_compatible_unit('mg', ['mg', 'g', 'ng', 'kg'])
+ self.check_compatible_unit(
+ 'mg',
+ ['mol', 'nmol', 'pmol', 'µmol', 'mg', 'g', 'ng', 'kg'],
+ compound=self.compound
+ )
+ self.check_compatible_unit(
+ 'nmol/L',
+ [
+ 'nmol/L', 'pmol/L', 'µmol/L', 'mg/L',
+ 'g/L', 'ng/mL', 'ng/L', 'pg/mL', 'µg/mL', 'g/dL'
+ ],
+ compound=self.compound
+ )
+
+ def test_compatible_units_mols_per_kg(self):
+ self.check_compatible_unit(
+ 'nmol/kg', ['nmol/kg', 'pmol/kg', 'µmol/kg'])
+ self.check_compatible_unit(
+ 'nmol/kg',
+ ['nmol/kg', 'pmol/kg', 'µmol/kg', 'mg/kg',
+ 'pg/kg', 'µg/kg', 'ng/kg', ''],
+ compound=self.compound
+ )
+ self.check_compatible_unit(
+ 'mg/kg', ['mg/kg', 'pg/kg', 'µg/kg', 'ng/kg', ''])
+ self.check_compatible_unit(
+ 'mg/kg',
+ [
+ 'nmol/kg', 'pmol/kg', 'µmol/kg', 'mg/kg',
+ 'pg/kg', 'µg/kg', 'ng/kg', 'g/mol', 'g/nmol', ''
+ ],
+ compound=self.compound
+ )
diff --git a/pkpdapp/pkpdapp/tests/test_models/test_variable.py b/pkpdapp/pkpdapp/tests/test_models/test_variable.py
new file mode 100644
index 00000000..1faad709
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_models/test_variable.py
@@ -0,0 +1,55 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import pkpdapp.tests # noqa: F401
+from django.db.utils import IntegrityError
+from pkpdapp.models import (
+ Variable, Unit,
+ PharmacokineticModel,
+)
+
+
+def TestVariableModel(TestCase):
+ def test_variable_creation(self):
+ n = 'variable name'
+ u = Unit.objects.get(symbol='mg')
+ lb = 0.001
+ ub = 3.1415
+ s = 'LN'
+ ls = 'LG'
+ pk = PharmacokineticModel.objects\
+ .get(name='one_compartment_pk_model')
+
+ v = Variable.objects.create(
+ name=n,
+ unit=u,
+ scale=s,
+ pk_model=pk,
+ lower_bound=lb,
+ upper_bound=ub
+ )
+ self.assertTrue(isinstance(v, Variable))
+
+ with self.assertRaises(IntegrityError) as context:
+ Variable.objects.create(
+ name=n,
+ unit=u,
+ scale=s,
+ lower_bound=lb,
+ upper_bound=ub
+ )
+ err_msg = 'variable must belong to a model'
+ self.assertTrue(err_msg in str(context.exception))
+
+ with self.assertRaises(IntegrityError) as context:
+ Variable.objects.create(
+ name=n,
+ unit=u,
+ scale=ls,
+ lower_bound=0,
+ upper_bound=ub
+ )
+ err_msg = 'log scale must have a lower bound greater than zero'
+ self.assertTrue(err_msg in str(context.exception))
diff --git a/pkpdapp/pkpdapp/tests/test_serializers/__init__.py b/pkpdapp/pkpdapp/tests/test_serializers/__init__.py
new file mode 100644
index 00000000..d0505307
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_serializers/__init__.py
@@ -0,0 +1,5 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
diff --git a/pkpdapp/pkpdapp/tests/test_serializers/test_inference.py b/pkpdapp/pkpdapp/tests/test_serializers/test_inference.py
new file mode 100644
index 00000000..4ea4f5a2
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_serializers/test_inference.py
@@ -0,0 +1,100 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from django.test import TestCase
+from rest_framework.exceptions import ValidationError
+from pkpdapp.models import (
+ InferenceMixin
+)
+from pkpdapp.api.serializers import (
+ InferenceSerializer, InferenceChainSerializer,
+)
+from pkpdapp.tests import create_pd_inference
+
+
+class TestInferenceSerializer(TestCase):
+ def setUp(self):
+ self.inference, log_likelihood, biomarker_type, \
+ _, self.model, _ = create_pd_inference(
+ sampling=False)
+
+ # set uniform prior on everything, except amounts
+ for i, param in enumerate(
+ log_likelihood.parameters.all()
+ ):
+ if i == 0:
+ param.set_uniform_prior(
+ 0.0, 2.0, biomarker_type=biomarker_type
+ )
+ else:
+ param.set_uniform_prior(0.0, 2.0)
+
+ def test_create(self):
+ serializer = InferenceSerializer()
+ data = {
+ 'name': 'test',
+ 'log_likelihoods': [],
+ 'project': self.inference.project.id,
+ }
+ validated_data = serializer.to_internal_value(data)
+ new_inference = serializer.create(validated_data)
+ self.assertEqual(new_inference.name, 'test')
+ self.assertEqual(len(new_inference.log_likelihoods.all()), 0)
+
+ def test_update(self):
+ serializer = InferenceSerializer(
+ self.inference
+ )
+ data = serializer.data
+ old_number_of_loglikelihoods = len(data['log_likelihoods'])
+ data['name'] = 'fred'
+ data['log_likelihoods'].append({
+ 'name': 'x',
+ 'form': 'N',
+ 'parameters': [],
+ })
+ validated_data = serializer.to_internal_value(data)
+ serializer.update(self.inference, validated_data)
+ self.assertEqual(self.inference.name, 'fred')
+
+ # new prior will add three new log_likelihood
+ # since a normal has 2 params
+ self.assertEqual(
+ len(self.inference.log_likelihoods.all()),
+ old_number_of_loglikelihoods + 3
+ )
+
+ # do it again with the same name, should have validation error
+ serializer = InferenceSerializer(
+ self.inference
+ )
+ data = serializer.data
+ old_number_of_loglikelihoods = len(data['log_likelihoods'])
+ data['log_likelihoods'].append({
+ 'name': 'x',
+ 'form': 'N',
+ 'parameters': [],
+ })
+ with self.assertRaisesRegex(
+ ValidationError,
+ "all log_likelihoods in an inference must have unique names"
+ ):
+ validated_data = serializer.to_internal_value(data)
+
+ def test_inference_results(self):
+ # create mixin object
+ inference_mixin = InferenceMixin(self.inference)
+ inference_mixin.run_inference()
+
+ chain = self.inference.chains.first()
+ chain_serializer = InferenceChainSerializer(chain)
+ data = chain_serializer.data
+ self.assertTrue('outputs' in data)
+ self.assertTrue(len(data['outputs']) > 0)
+ self.assertTrue('data' in data)
+ self.assertTrue('kde' in data['data'])
+ self.assertTrue(len(data['data']['kde']) > 0)
+ self.assertTrue('chain' in data['data'])
+ self.assertTrue(len(data['data']['chain']) > 0)
diff --git a/pkpdapp/pkpdapp/tests/test_serializers/test_likelihoods.py b/pkpdapp/pkpdapp/tests/test_serializers/test_likelihoods.py
new file mode 100644
index 00000000..1672c583
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_serializers/test_likelihoods.py
@@ -0,0 +1,37 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from django.test import TestCase
+from pkpdapp.api.serializers import (
+ LogLikelihoodSerializer
+)
+from pkpdapp.tests import create_pd_inference
+
+
+class TestLoglikelihoodSerializer(TestCase):
+ def setUp(self):
+ self.inference, self.log_likelihood, self.biomarker_type, \
+ _, self.model, _ = create_pd_inference()
+ self.parameters = self.log_likelihood.parameters.all()
+ self.prior = self.parameters[0].child
+
+ def test_serialize(self):
+ serializer = LogLikelihoodSerializer(
+ self.inference.log_likelihoods.all(),
+ many=True
+ )
+ data = serializer.data
+ self.assertEqual(len(data), 6)
+
+ def test_update(self):
+ serializer = LogLikelihoodSerializer(self.prior)
+ data = serializer.data
+
+ # update fixed value of 1st param
+ data['form'] = 'N'
+
+ validated_data = serializer.to_internal_value(data)
+ serializer.update(self.prior, validated_data)
+ self.assertEqual(self.prior.parameters.count(), 2)
diff --git a/pkpdapp/pkpdapp/tests/test_serializers/test_models.py b/pkpdapp/pkpdapp/tests/test_serializers/test_models.py
new file mode 100644
index 00000000..fcadd116
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_serializers/test_models.py
@@ -0,0 +1,66 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import pkpdapp.tests # noqa: F401
+import codecs
+from django.test import TestCase
+import urllib.request
+from pkpdapp.models import (
+ PharmacodynamicModel,
+ Project,
+)
+from pkpdapp.api.serializers import (
+ PharmacodynamicSbmlSerializer, PharmacodynamicSerializer
+)
+
+BASE_URL_DATASETS = 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/' # noqa: E501
+
+
+class TestPdModelSerializer(TestCase):
+ def setUp(self):
+ self.project = Project.objects.get(
+ name='demo',
+ )
+
+ def test_sbml_serialize(self):
+ pd_model = PharmacodynamicModel.objects.create(
+ name='test'
+ )
+ for filename in [
+ 'usecase2/ABx_updated3.xml'
+ ]:
+ with urllib.request.urlopen(
+ BASE_URL_DATASETS + filename, timeout=5
+ ) as f:
+ sbml_str = codecs.decode(f.read(), 'utf-8')
+ serializer = PharmacodynamicSbmlSerializer(
+ pd_model,
+ data={"sbml": sbml_str},
+ partial=True
+ )
+ self.assertTrue(serializer.is_valid())
+ serializer.save()
+
+ def test_bad_sbml(self):
+ pd_model = PharmacodynamicModel.objects.create(
+ name='test'
+ )
+ serializer = PharmacodynamicSbmlSerializer(
+ pd_model,
+ data={"sbml": "bad sbml"},
+ partial=True
+ )
+ self.assertFalse(serializer.is_valid())
+
+ def test_bad_mmt(self):
+ pd_model = PharmacodynamicModel.objects.create(
+ name='test'
+ )
+ serializer = PharmacodynamicSerializer(
+ pd_model,
+ data={"mmt": "bad sbml"},
+ partial=True
+ )
+ self.assertFalse(serializer.is_valid())
diff --git a/pkpdapp/pkpdapp/tests/test_serializers/test_monolix.py b/pkpdapp/pkpdapp/tests/test_serializers/test_monolix.py
new file mode 100644
index 00000000..ac347943
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_serializers/test_monolix.py
@@ -0,0 +1,62 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import pkpdapp.tests # noqa: F401
+from django.core.files.uploadedfile import SimpleUploadedFile
+from django.test import TestCase
+import urllib.request
+from pkpdapp.models import (
+ Project, Compound,
+)
+from pkpdapp.api.serializers import (
+ MonolixSerializer,
+)
+
+BASE_URL_DATASETS = 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/' # noqa: E501
+
+
+class TestMonolixSerializer(TestCase):
+ def test_import(self):
+ compound = Compound.objects.create(
+ name='test',
+ description='test',
+ molecular_mass=100,
+ target_molecular_mass=100,
+ )
+ project = Project.objects.create(
+ name='test',
+ compound=compound,
+ )
+ model_f = urllib.request.urlopen(
+ BASE_URL_DATASETS + 'usecase_monolix/PK_Model.txt', timeout=5
+ )
+ project_f = urllib.request.urlopen(
+ BASE_URL_DATASETS + 'usecase_monolix/Model_208.mlxtran', timeout=5
+ )
+ data_f = urllib.request.urlopen(
+ BASE_URL_DATASETS + 'usecase_monolix/TE_Data.txt', timeout=5
+ )
+
+ files = []
+ for f, n in zip(
+ [model_f, project_f, data_f],
+ ['model_txt', 'project_mlxtran', 'data_csv']
+ ):
+ content = SimpleUploadedFile(n, f.read())
+ files.append(content)
+
+ data = {
+ 'model_txt': files[0],
+ 'project_mlxtran': files[1],
+ 'data_csv': files[2],
+ }
+ serializer = MonolixSerializer(project, data=data)
+ print(serializer.is_valid())
+ print(serializer.errors)
+ self.assertTrue(serializer.is_valid())
+ serializer.save()
+ self.assertIn('pd_model', serializer.data)
+ self.assertIn('pk_model', serializer.data)
+ self.assertIn('data', serializer.data)
diff --git a/pkpdapp/pkpdapp/tests/test_utils/test_data_parser.py b/pkpdapp/pkpdapp/tests/test_utils/test_data_parser.py
new file mode 100644
index 00000000..088dc749
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_utils/test_data_parser.py
@@ -0,0 +1,130 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import django
+import codecs
+from django.utils import timezone
+import urllib.request
+from django.test import TestCase
+from pkpdapp.models.dataset import Dataset
+from pkpdapp.utils import DataParser
+
+django.setup()
+BASE_URL_DATASETS = 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/' # noqa: E501
+
+
+class TestDataParser(TestCase):
+ def test_parse(self):
+ for filename in [
+ 'datasets/TCB4dataset.csv',
+ 'datasets/demo_pk_data_upload.csv',
+ 'usecase_monolix/TE_Data.txt',
+ 'usecase0/usecase0.csv',
+ 'usecase1/usecase1.csv',
+ 'usecase2/PKPD_UseCase_Abx.csv',
+
+ ]:
+ with urllib.request.urlopen(
+ BASE_URL_DATASETS + filename, timeout=5
+ ) as f:
+ csv_str = codecs.decode(f.read(), 'utf-8')
+ parser = DataParser()
+ if filename == 'usecase_monolix/TE_Data.txt':
+ data = parser.parse_from_str(csv_str, delimiter='\t')
+ else:
+ data = parser.parse_from_str(csv_str)
+ expected = [
+ "SUBJECT_ID", "TIME", "AMOUNT", "OBSERVATION",
+ "TIME_UNIT", "AMOUNT_UNIT", "OBSERVATION_UNIT",
+ "OBSERVATION_NAME", "COMPOUND", "ROUTE", "INFUSION_TIME",
+ ]
+ for col in expected:
+ self.assertIn(col, data.columns.tolist())
+
+ dataset = Dataset.objects.create(
+ name=filename,
+ datetime=timezone.now(),
+ )
+ dataset.replace_data(data)
+
+ if filename == 'datasets/TCB4dataset.csv':
+ biomarker_types_in_file = [
+ 'IL2', 'IL10', 'IL6', 'IFNg', 'TNFa', 'Cells'
+ ]
+ covariate_columns = [
+ 'SUBJECT_GROUP', 'DOSE_GROUP', 'CL', 'YTYPE',
+ 'mdv', 'STUDYID'
+ ]
+ self.assertCountEqual(
+ biomarker_types_in_file + covariate_columns,
+ dataset.biomarker_types.values_list('name', flat=True),
+ )
+
+ if filename == 'usecase0/usecase0.csv':
+ # check that categorical covariate SEX is added
+ self.assertIn(
+ "SEX",
+ dataset.biomarker_types.values_list(
+ 'name', flat=True
+ )
+ )
+
+ # check that SEX is "Male" for single subjects
+ sex_bt = dataset.biomarker_types.get(name="SEX")
+ sex_data = sex_bt.data()
+ self.assertEqual(len(sex_data["values"]), 1)
+ self.assertEqual(sex_data["values"].iloc[0], "Male")
+
+ # default display for covariates is false
+ self.assertFalse(sex_bt.display)
+
+ if filename == 'datasets/demo_pk_data_upload.csv':
+
+ # check the right biomarker_types are there
+ biomarker_types_in_file = [
+ 'Docetaxel', 'Red blood cells', 'Hemoglobin',
+ 'Platelets ', 'White blood cells',
+ 'Neutrophiles absolute', 'Lymphocytes absolute',
+ 'Monocytes absolute', 'Eosinophils absolute',
+ 'Basophils absolute',
+ ]
+ covariate_columns = [
+ 'DOSE',
+ 'EVID',
+ 'CENS',
+ 'WT',
+ 'YTYPE',
+ 'MDV',
+ 'STUDYID',
+ 'SPECIES',
+ 'SEX',
+ 'SUBJECT_GROUP',
+ 'STUDYID.1',
+ 'DOSE_GROUP',
+ ]
+ self.assertCountEqual(
+ dataset.biomarker_types.values_list('name', flat=True),
+ biomarker_types_in_file + covariate_columns
+ )
+
+ # check the right number of subjects and protocols added
+ self.assertEqual(dataset.subjects.count(), 66)
+ protocols = set([
+ subject.protocol for subject in dataset.subjects.all()
+ ])
+ self.assertEqual(len(protocols), 39)
+ if filename == 'usecase_monolix/TE_Data.txt':
+ expected_names = [
+ 'observation', 'Dose', 'Dose_units', 'Dose_cat'
+ ]
+ biomarker_names = dataset.biomarker_types.values_list(
+ 'name', flat=True
+ )
+ self.assertCountEqual(biomarker_names, expected_names)
+ expected_units = ['', '', '', '']
+ biomarker_units = dataset.biomarker_types.values_list(
+ 'stored_unit__symbol', flat=True
+ )
+ self.assertCountEqual(biomarker_units, expected_units)
diff --git a/pkpdapp/pkpdapp/tests/test_utils/test_monolix_import.py b/pkpdapp/pkpdapp/tests/test_utils/test_monolix_import.py
new file mode 100644
index 00000000..c38404fb
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_utils/test_monolix_import.py
@@ -0,0 +1,93 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import django
+import codecs
+import urllib.request
+from django.test import TestCase
+from pkpdapp.models import (
+ Project
+)
+
+from pkpdapp.utils import (
+ monolix_import
+)
+
+django.setup()
+BASE_URL_DATASETS = 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/' # noqa: E501
+
+
+class TestMonolixImport(TestCase):
+ def test_import_project(self):
+ project = Project.objects.create(
+ name='test',
+ )
+ with urllib.request.urlopen(
+ BASE_URL_DATASETS + 'usecase_monolix/PK_Model.txt', timeout=5
+ ) as f:
+ monolix_model_str = codecs.decode(f.read(), 'utf-8')
+ with urllib.request.urlopen(
+ BASE_URL_DATASETS + 'usecase_monolix/Model_208.mlxtran', timeout=5
+ ) as f:
+ monolix_project_str = codecs.decode(f.read(), 'ascii')
+ with urllib.request.urlopen(
+ BASE_URL_DATASETS + 'usecase_monolix/TE_Data.txt', timeout=5
+ ) as f:
+ monolix_data_str = codecs.decode(f.read(), 'utf-8')
+
+ result = monolix_import(
+ project, monolix_project_str,
+ monolix_model_str, monolix_data_str, validate=False
+ )
+ self.assertIsNotNone(result)
+ pd_model, pk_model, dataset = result
+ constant_variables = pd_model.variables.filter(
+ constant=True).values_list('qname', flat=True)
+ expected_constant_variables = [
+ 'root.Cl', 'root.KD', 'root.R0', 'root.V', 'root.fres',
+ 'root.hind', 'root.ka', 'root.kdeg', 'root.koff'
+ ]
+ self.assertCountEqual(constant_variables, expected_constant_variables)
+ state_variables = pd_model.variables.filter(
+ state=True).values_list('qname', flat=True)
+ expected_state_variables = ['cmt1.A1', 'root.A2', 'root.A4', 'root.A5']
+ self.assertCountEqual(state_variables, expected_state_variables)
+ other_variables = pd_model.variables.filter(
+ constant=False, state=False).values_list('qname', flat=True)
+ expected_other_variables = [
+ 'root.A3', 'root.C2', 'root.C3', 'root.C4', 'root.C5',
+ 'root.CD_t', 'root.CR_t', 'root.PRR', 'root.RR', 'root.t'
+ ]
+ self.assertCountEqual(other_variables, expected_other_variables)
+ self.assertEqual(pk_model.dose_compartment, 'cmt1')
+
+ displayed_biomarkers = dataset.biomarker_types.filter(
+ display=True
+ ).values_list('name', flat=True)
+ expected_biomarkers = ['observation']
+ self.assertCountEqual(displayed_biomarkers, expected_biomarkers)
+ displayed_pd_variables = pd_model.variables.filter(
+ constant=False, display=True
+ ).values_list('qname', flat=True)
+ displayed_pk_variables = pk_model.variables.filter(
+ constant=False, display=True
+ ).values_list('qname', flat=True)
+ expected_variables = ['root.PRR']
+ self.assertCountEqual(displayed_pd_variables, expected_variables)
+ self.assertCountEqual(displayed_pk_variables, expected_variables)
+
+ pd_states = pd_model.variables.filter(
+ state=True
+ ).values_list('qname', flat=True)
+ pk_states = pk_model.variables.filter(
+ state=True
+ ).values_list('qname', flat=True)
+ expected_states = ['cmt1.A1', 'root.A2', 'root.A4', 'root.A5']
+ self.assertCountEqual(pd_states, expected_states)
+ self.assertCountEqual(pk_states, expected_states)
+
+ result = pk_model.simulate()
+ print(result)
diff --git a/pkpdapp/pkpdapp/tests/test_utils/test_monolix_parser.py b/pkpdapp/pkpdapp/tests/test_utils/test_monolix_parser.py
new file mode 100644
index 00000000..eb7b1644
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_utils/test_monolix_parser.py
@@ -0,0 +1,49 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import django
+import codecs
+import unittest
+import urllib.request
+from pkpdapp.utils import (
+ MonolixModelParser, MonolixProjectParser
+)
+
+django.setup()
+BASE_URL_DATASETS = 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/' # noqa: E501
+
+
+class TestMonolixParser(unittest.TestCase):
+ def test_parse_model(self):
+ with urllib.request.urlopen(
+ BASE_URL_DATASETS + 'usecase_monolix/PK_Model.txt', timeout=5
+ ) as f:
+ monolix_str = codecs.decode(f.read(), 'utf-8')
+ parser = MonolixModelParser()
+ model, (admin_id, tlag, direct) = parser.parse(monolix_str)
+ model.validate()
+ self.assertEqual(admin_id, 1)
+ self.assertEqual(tlag, 0)
+ self.assertEqual(direct, True)
+
+ def test_parse_project(self):
+ with urllib.request.urlopen(
+ BASE_URL_DATASETS + 'usecase_monolix/Model_208.mlxtran', timeout=5
+ ) as f:
+ monolix_str = codecs.decode(f.read(), 'ascii')
+ parser = MonolixProjectParser()
+ project = parser.parse(monolix_str)
+ self.assertCountEqual(
+ project.keys(),
+ ['', '', '', '', '', ]
+ )
+ self.assertCountEqual(
+ project[''].keys(),
+ ['[CONTENT]', '[FILEINFO]']
+ )
+ self.assertCountEqual(
+ project[''].keys(),
+ ['[COVARIATE]', '[INDIVIDUAL]', '[LONGITUDINAL]']
+ )
diff --git a/pkpdapp/pkpdapp/tests/test_views/__init__.py b/pkpdapp/pkpdapp/tests/test_views/__init__.py
new file mode 100644
index 00000000..d0505307
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_views/__init__.py
@@ -0,0 +1,5 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
diff --git a/pkpdapp/pkpdapp/tests/test_views/test_auce.py b/pkpdapp/pkpdapp/tests/test_views/test_auce.py
new file mode 100644
index 00000000..c726ce1c
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_views/test_auce.py
@@ -0,0 +1,68 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pkpdapp.tests # noqa: F401
+from rest_framework import status
+from rest_framework.test import APITestCase, APIClient
+from django.contrib.auth.models import User
+from pkpdapp.models import BiomarkerType, Dataset
+import unittest
+
+
+@unittest.skip("might not be needed anymore")
+class NcaTestCase(APITestCase):
+ def setUp(self):
+ user = User.objects.get(username='demo')
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ def test_auce_post(self):
+ dataset = Dataset.objects.get(
+ name='TCB4dataset'
+ )
+ biomarker_type = BiomarkerType.objects.get(
+ name='IL2',
+ dataset=dataset,
+ )
+ group_type = BiomarkerType.objects.get(
+ name='group',
+ dataset=dataset,
+ )
+ dose_type = BiomarkerType.objects.get(
+ name='dose',
+ dataset=dataset,
+ )
+ data = {
+ 'biomarker_type_id': biomarker_type.id,
+ 'group_type_id': group_type.id,
+ 'concentration_type_id': dose_type.id,
+ }
+ response = self.client.post(
+ "/api/auce/", data
+ )
+ self.assertEqual(
+ response.status_code, status.HTTP_200_OK
+ )
+
+ def test_auce_no_dose_group_amount(self):
+ biomarker_type = BiomarkerType.objects.get(
+ name='Docetaxel'
+ )
+ data = {
+ 'biomarker_type_id': biomarker_type.id,
+ }
+ response = self.client.post(
+ "/api/auce/", data
+ )
+ self.assertEqual(
+ response.status_code, status.HTTP_400_BAD_REQUEST
+ )
+ self.assertRegex(
+ response.data['group_type_id'],
+ (
+ 'required'
+ )
+ )
diff --git a/pkpdapp/pkpdapp/tests/test_views/test_biomarker_type.py b/pkpdapp/pkpdapp/tests/test_views/test_biomarker_type.py
new file mode 100644
index 00000000..56ae56d1
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_views/test_biomarker_type.py
@@ -0,0 +1,27 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import pkpdapp.tests # noqa: F401
+import django
+from django.contrib.auth.models import User
+from rest_framework import status
+from rest_framework.test import APIClient, APITestCase
+from pkpdapp.models import Project
+django.setup()
+
+
+class BiomarkerTypeTestCase(APITestCase):
+ def setUp(self):
+ user = User.objects.get(username='demo')
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ def test_bt_project_filter(self):
+ project = Project.objects.get(name="demo")
+ response = self.client.get(
+ "/api/biomarker_type/?project_id={}".format(project.pk)
+ )
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertTrue(len(response.data) == 0)
diff --git a/pkpdapp/pkpdapp/tests/test_views/test_combined_model.py b/pkpdapp/pkpdapp/tests/test_views/test_combined_model.py
new file mode 100644
index 00000000..1fb18cd2
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_views/test_combined_model.py
@@ -0,0 +1,177 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pkpdapp.tests # noqa: F401
+from rest_framework import status
+from rest_framework.test import APITestCase, APIClient
+from django.contrib.auth.models import User
+from pkpdapp.models import (
+ Project,
+ PharmacokineticModel,
+ CombinedModel,
+ PharmacodynamicModel,
+)
+import numpy as np
+
+
+class CombinedModelTestCase(APITestCase):
+ def setUp(self):
+ user = User.objects.get(username="demo")
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ def test_pk_project_filter(self):
+ response = self.client.get("/api/combined_model/?project_id=1")
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ response_data = response.data
+ self.assertEqual(len(response_data), 1)
+
+ def test_cannot_create_in_read_only_project(self):
+ user = User.objects.get(username="demo2")
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ project = Project.objects.get(name="demo")
+ response = self.client.post(
+ "/api/combined_model/", data={"name": "test", "project": project.id}
+ )
+ self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+
+ def create_combined_model(self, name, pd=None):
+ project = Project.objects.get(name="demo")
+ pk = PharmacokineticModel.objects.get(
+ name="one_compartment_clinical",
+ )
+ data = {
+ "name": name,
+ "project": project.id,
+ "pk_model": pk.id,
+ "mappings": [],
+ "derived_variables": [],
+ }
+ if pd is not None:
+ data["pd_model"] = pd.id
+ response = self.client.post("/api/combined_model/", data=data, format="json")
+ self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+ cm = CombinedModel.objects.get(pk=response.data["id"])
+
+ # set up a protocol
+ response = self.client.post(
+ "/api/protocol/",
+ data={
+ "name": "test protocol",
+ "project": project.id,
+ "doses": [
+ {
+ "start_time": 0,
+ "amount": 1,
+ "duration": 0.001,
+ "repeat_interval": 1,
+ "repeats": 1,
+ }
+ ],
+ },
+ format="json",
+ )
+ self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+
+ # attach it to the A1 variables
+ a1 = cm.variables.get(name="A1")
+ response = self.client.patch(
+ f"/api/variable/{a1.id}/",
+ data={
+ "protocol": response.data["id"],
+ },
+ format="json",
+ )
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+ if pd is not None:
+ c1 = cm.variables.get(name="C1")
+ drug_c = cm.variables.get(name="C_Drug")
+
+ response = self.client.patch(
+ f"/api/combined_model/{cm.id}/",
+ data={
+ "mappings": [
+ {
+ "pk_variable": c1.id,
+ "pd_variable": drug_c.id,
+ }
+ ],
+ "derived_variables": [],
+ },
+ format="json",
+ )
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+ return response.data
+
+ def simulate_combined_model(self, id):
+ response = self.client.post(
+ f"/api/combined_model/{id}/simulate",
+ data={
+ "outputs": [
+ "PDCompartment.C_Drug",
+ "PKCompartment.C1",
+ "PDCompartment.E",
+ ],
+ "variables": {},
+ },
+ format="json",
+ )
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ keys = [key for key in response.data["outputs"].keys()]
+ return (
+ response.data["outputs"][keys[0]],
+ response.data["outputs"][keys[1]],
+ response.data["outputs"][keys[2]],
+ )
+
+ def test_swap_mapped_pd_model(self):
+ pd1 = PharmacodynamicModel.objects.get(
+ name="indirect_effects_stimulation_elimination",
+ )
+ pd2 = PharmacodynamicModel.objects.get(
+ name="indirect_effects_inhibition_elimination",
+ )
+ model1 = self.create_combined_model("test1", pd1)
+ model2 = self.create_combined_model("test2", pd2)
+ c_drug1, c1_1, e1 = self.simulate_combined_model(model1["id"])
+ c_drug2, c1_2, e2 = self.simulate_combined_model(model2["id"])
+
+ # c_drug should be mapped to c1 and equal
+ np.testing.assert_allclose(c_drug1, c1_1, atol=1e-5, rtol=1e-5)
+
+ # swap the pd model for model 1, old mappings should be updated
+ cm = CombinedModel.objects.get(pk=model1["id"])
+ c1 = cm.variables.get(name="C1")
+ c_drug = cm.variables.get(name="C_Drug")
+ response = self.client.patch(
+ f"/api/combined_model/{model1['id']}/",
+ data={
+ "pd_model": pd2.id,
+ "mappings": [
+ {
+ "pk_variable": c1.id,
+ "pd_variable": c_drug.id,
+ }
+ ],
+ },
+ format="json",
+ )
+ model1 = response.data
+
+ # simulate the model again
+ c_drug3, c1_3, e3 = self.simulate_combined_model(model1["id"])
+
+ # c_drug3 should be mapped to c3 and equal
+ np.testing.assert_allclose(c_drug3, c1_3, atol=1e-5, rtol=1e-5)
+
+ # check that the data is the same as the second simulation
+ np.testing.assert_allclose(c_drug3, c_drug2, atol=1e-5, rtol=1e-5)
+ np.testing.assert_allclose(c1_3, c1_2, atol=1e-5, rtol=1e-5)
+ np.testing.assert_allclose(e3, e2, atol=1e-5, rtol=1e-5)
diff --git a/pkpdapp/pkpdapp/tests/test_views/test_dataset.py b/pkpdapp/pkpdapp/tests/test_views/test_dataset.py
new file mode 100644
index 00000000..c306a2fc
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_views/test_dataset.py
@@ -0,0 +1,49 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import pkpdapp.tests # noqa: F401
+from urllib.request import urlretrieve
+
+from django.contrib.auth.models import User
+from django.core.files import File
+from rest_framework import status
+from rest_framework.test import APIClient, APITestCase
+
+BASE_URL_DATASETS = 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/datasets/' # noqa: E501
+BASE_URL_MODELS = 'https://raw.githubusercontent.com/pkpdapp-team/pkpdapp-datafiles/main/models/' # noqa: E501
+
+
+def faux_test_file(url, ending='.csv'):
+ tempname, _ = urlretrieve(url)
+ file = File(open(tempname, 'rb'))
+ file.name = 'test' + ending
+ return file
+
+
+class DatasetTestCase(APITestCase):
+ def setUp(self):
+ user = User.objects.get(username='demo')
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ def test_dataset_creation(self):
+ data = {"name": "hello", "datatime": "", "description": "bye"}
+ response = self.client.post("/api/dataset/", data)
+ self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+ response_data = response.data
+ self.assertEqual(response_data["name"], data["name"])
+ self.assertEqual(response_data["description"], data["description"])
+
+ keys = response_data.keys()
+ present_keys = ['name', 'datetime', 'description', 'subjects',
+ 'biomarker_types']
+ for k in present_keys:
+ self.assertTrue(k in keys)
+
+ def test_dataset_project_filter(self):
+ response = self.client.get("/api/dataset/?project_id=1")
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ response_data = response.data
+ self.assertEqual(len(response_data), 0)
diff --git a/pkpdapp/pkpdapp/tests/test_views/test_inference.py b/pkpdapp/pkpdapp/tests/test_views/test_inference.py
new file mode 100644
index 00000000..2685d84e
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_views/test_inference.py
@@ -0,0 +1,361 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import status
+
+from django.contrib.auth.models import User
+from rest_framework.test import APIClient, APITestCase
+
+from pkpdapp.models import (
+ Algorithm,
+ Inference,
+ InferenceMixin,
+ Project,
+)
+from pkpdapp.tests import create_pd_inference
+
+
+class TestInferenceWizardView(APITestCase):
+ def setUp(self):
+ self.project = Project.objects.get(
+ name='demo',
+ )
+
+ user = User.objects.get(username='demo')
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ def test_population_and_covariates_inference(self):
+ inference, log_likelihood, \
+ biomarker_type, covariate_biomarker_type, \
+ pd_model, pd_dataset = create_pd_inference(
+ sampling=False)
+
+ pd_biomarker_names = [
+ biomarker_type.name,
+ covariate_biomarker_type.name,
+ ]
+
+ pd_output_name = log_likelihood.parents.first().name
+ pd_parameter_names = [
+ v.qname for v in pd_model.variables.filter(constant=True)
+ ]
+ data = {
+ # Inference parameters
+ 'name': "my inference run",
+ 'project': 1,
+ 'algorithm': 1,
+ 'initialization_strategy': 'R',
+ 'number_of_chains': 4,
+ 'max_number_of_iterations': 3000,
+ 'burn_in': 0,
+
+ # Model
+ 'model': {
+ 'form': 'PK',
+ 'id': pd_model.id
+ },
+ 'dataset': pd_dataset.id,
+ 'grouping': 'subject',
+
+ # Model parameters
+ 'parameters': [
+ {
+ 'name': pd_parameter_names[0],
+ 'form': 'N',
+ 'pooled': False,
+ 'parameters': [
+ (
+ r'0.1 * biomarker("{}") + '
+ r'parameter("population_parameter")'
+ .format(pd_biomarker_names[1])
+ ),
+ 0.1
+ ]
+ },
+ {
+ 'name': 'population_parameter',
+ 'form': 'N',
+ 'parameters': [1, 0.1]
+ },
+ ],
+
+ # output
+ 'observations': [
+ {
+ 'model': pd_output_name,
+ 'biomarker': pd_biomarker_names[0],
+ 'noise_form': 'N',
+ 'noise_param_form': 'N',
+ 'parameters': [0, 1]
+ },
+ ]
+ }
+ print(data)
+ response = self.client.post(
+ "/api/inference/wizard", data, format='json'
+ )
+
+ response_data = response.data
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+ # check inference fields
+ self.assertEqual(response_data['name'], 'my inference run')
+ self.assertEqual(response_data['project'], self.project.id)
+ self.assertEqual(response_data['initialization_strategy'], 'R')
+
+ # check number of log_likelihoods, and that the population_parameter is
+ # there
+ self.assertEqual(len(response_data['log_likelihoods']), 14)
+ found_it = False
+ for ll in response_data['log_likelihoods']:
+ if ll['name'] == 'population_parameter':
+ found_it = True
+ self.assertEqual(len(ll['parameters']), 2)
+ self.assertTrue(found_it)
+
+ # check that the equation log_likelihood looks ok
+ found_it = False
+ for ll in response_data['log_likelihoods']:
+ if ll['name'] == 'mean for ' + pd_parameter_names[0]:
+ found_it = True
+ self.assertEqual(len(ll['parameters']), 2)
+ self.assertTrue(
+ ll['description'] == '0.1 * arg0 + arg1' or
+ ll['description'] == '0.1 * arg1 + arg0'
+ )
+ self.assertTrue(found_it)
+
+ inference = Inference.objects.get(id=response_data['id'])
+
+ inference_mixin = InferenceMixin(inference)
+ log_posterior = inference_mixin._pints_log_posterior
+
+ # pymc3_model = log_posterior._model
+ # graph = pymc3.model_graph.model_to_graphviz(pymc3_model)
+ # graph.render(directory='test', view=True)
+
+ log_posterior(
+ log_posterior.to_search([0.5] * log_posterior.n_parameters())
+ )
+
+ def test_pd_inference_runs(self):
+ inference, log_likelihood, \
+ biomarker_type, \
+ covariate_biomarker_type, \
+ pd_model, pd_dataset = create_pd_inference(
+ sampling=False)
+
+ pd_biomarker_name = biomarker_type.name
+ pd_output_name = log_likelihood.parents.first().name
+ pd_parameter_names = [
+ v.qname for v in pd_model.variables.filter(constant=True)
+ ]
+
+ data = {
+ # Inference parameters
+ 'name': "test inference run",
+ 'project': self.project.id,
+ 'algorithm': Algorithm.objects.get(name='XNES').id,
+ 'initialization_strategy': 'R',
+ 'number_of_chains': 4,
+ 'max_number_of_iterations': 11,
+ 'burn_in': 0,
+
+ # Model
+ 'model': {
+ 'form': 'PD',
+ 'id': pd_model.id
+ },
+ 'dataset': pd_dataset.id,
+
+ # Model parameters
+ 'parameters': [
+ {
+ 'name': pd_parameter_names[0],
+ 'form': 'N',
+ 'parameters': [1, 0.1],
+ },
+ {
+ 'name': pd_parameter_names[1],
+ 'form': 'U',
+ 'parameters': [0.1, 0.2],
+ },
+ {
+ 'name': pd_parameter_names[2],
+ 'form': 'F',
+ 'parameters': [0.1],
+ }
+ ],
+ # output
+ 'observations': [
+ {
+ 'model': pd_output_name,
+ 'biomarker': pd_biomarker_name,
+ 'noise_form': 'N',
+ 'noise_param_form': 'N',
+ 'parameters': [0, 1],
+ },
+ ]
+ }
+ response = self.client.post(
+ "/api/inference/wizard", data, format='json'
+ )
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ response_data = response.data
+
+ # check inference fields
+ self.assertEqual(response_data['name'], 'test inference run')
+ self.assertEqual(response_data['project'], self.project.id)
+ self.assertEqual(response_data['initialization_strategy'], 'R')
+
+ # check number of log_likelihoods, and that the model ll is there
+ self.assertEqual(len(response_data['log_likelihoods']), 12)
+ found_it = False
+ for ll in response_data['log_likelihoods']:
+ print('looking in ', ll['name'])
+ if ll['name'] == 'my wonderful model':
+ found_it = True
+ self.assertEqual(len(ll['parameters']), 3)
+ model_id = ll['id']
+ self.assertTrue(found_it)
+
+ # check that the output log_likelihood is there and looks ok
+ found_it = False
+ for ll in response_data['log_likelihoods']:
+ if ll['name'] == pd_output_name:
+ found_it = True
+ self.assertEqual(len(ll['parameters']), 2)
+ self.assertEqual(ll['parameters'][0]['name'],
+ pd_output_name)
+ self.assertEqual(ll['form'], 'N')
+ self.assertEqual(
+ ll['biomarker_type'],
+ pd_dataset.biomarker_types.get(name=pd_biomarker_name).id
+ )
+ self.assertEqual(ll['parameters'][0]['child'], model_id)
+ sigma_ll = ll['parameters'][1]['child']
+ self.assertTrue(found_it)
+
+ # check that the sigma log_likelihood is there and looks ok
+ found_it = False
+ for ll in response_data['log_likelihoods']:
+ if ll['id'] == sigma_ll:
+ found_it = True
+ self.assertEqual(ll['form'], 'N')
+ self.assertEqual(len(ll['parameters']), 2)
+ self.assertTrue(found_it)
+
+ # check that the param 1 log_likelihood is there and looks ok
+ found_it = False
+ for ll in response_data['log_likelihoods']:
+ if ll['name'] == pd_parameter_names[1]:
+ found_it = True
+ self.assertEqual(ll['form'], 'U')
+ self.assertEqual(len(ll['parameters']), 2)
+ child_id = ll['parameters'][0]['child']
+ self.assertTrue(found_it)
+ found_it = False
+ for ll in response_data['log_likelihoods']:
+ if ll['id'] == child_id:
+ found_it = True
+ self.assertEqual(ll['form'], 'F')
+ self.assertEqual(ll['value'], 0.1)
+ self.assertTrue(found_it)
+
+ inference = Inference.objects.get(id=response_data['id'])
+
+ inference_mixin = InferenceMixin(inference)
+ log_posterior = inference_mixin._pints_log_posterior
+
+ # pymc3_model = log_posterior._model
+ # graph = pymc3.model_graph.model_to_graphviz(pymc3_model)
+ # graph.render(directory='test', view=True)
+
+ log_posterior(
+ log_posterior.to_search([0.5, 0.12, 0.1])
+ )
+
+ def test_errors(self):
+ inference, log_likelihood, biomarker_type, \
+ covariate_biomarker_type, pd_model, \
+ pd_dataset = create_pd_inference(
+ sampling=False)
+
+ pd_parameter_names = [
+ v.qname for v in pd_model.variables.filter(constant=True)
+ ]
+
+ data = {}
+ response = self.client.post(
+ "/api/inference/wizard", data, format='json'
+ )
+ self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+ self.assertIn('project', response.data)
+ self.assertIn('dataset', response.data)
+ self.assertIn('model', response.data)
+ self.assertIn('parameters', response.data)
+ self.assertIn('observations', response.data)
+
+ data = {
+ 'name': "test inference run",
+ 'project': self.project.id,
+ 'algorithm': Algorithm.objects.get(name='XNES').id,
+ 'initialization_strategy': 'R',
+ 'number_of_chains': 4,
+ 'max_number_of_iterations': 2,
+ 'burn_in': 0,
+
+ 'model': {
+ 'form': 'PD',
+ 'id': pd_model.id
+ },
+ 'dataset': pd_dataset.id,
+
+ 'parameters': [
+ {
+ 'name': pd_parameter_names[0],
+ 'form': 'N',
+ 'parameters': ['import pybamm', 1],
+ },
+ {
+ 'name': pd_parameter_names[1],
+ 'form': 'N',
+ 'parameters': ['1 + parameter("doesnt exist")', 1],
+ },
+ {
+ 'name': pd_parameter_names[2],
+ 'form': 'N',
+ 'parameters': ['1 + biomarker("doesnt exist")', 1],
+ },
+ ],
+ 'observations': [
+ {
+ 'model': 'not in the model, really',
+ 'biomarker': 'not in the dataset',
+ 'noise_form': 'N',
+ 'noise_param_form': 'N',
+ 'parameters': [0, 1],
+ },
+ ]
+ }
+
+ response = self.client.post(
+ "/api/inference/wizard", data, format='json'
+ )
+ self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
+ self.assertIn(
+ 'Expected', response.data['parameters'][0]['parameters'][0]
+ )
+ self.assertIn(
+ 'not in list of parameters',
+ response.data['parameters'][1]['parameters'][0]
+ )
+ self.assertIn(
+ 'not in list of biomarkers',
+ response.data['parameters'][2]['parameters'][0]
+ )
+ self.assertIn('model', response.data['observations'][0])
+ self.assertIn('biomarker', response.data['observations'][0])
diff --git a/pkpdapp/pkpdapp/tests/test_views/test_nca.py b/pkpdapp/pkpdapp/tests/test_views/test_nca.py
new file mode 100644
index 00000000..563612a0
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_views/test_nca.py
@@ -0,0 +1,66 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pkpdapp.tests # noqa: F401
+import unittest
+from rest_framework import status
+from rest_framework.test import APITestCase, APIClient
+from django.contrib.auth.models import User
+from pkpdapp.models import BiomarkerType, Protocol
+
+
+@unittest.skip("NCA deprecated")
+class NcaTestCase(APITestCase):
+ def setUp(self):
+ user = User.objects.get(username='demo')
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ def test_nca_post(self):
+ biomarker_type = BiomarkerType.objects.get(
+ name='Docetaxel'
+ )
+ protocol = Protocol.objects.get(
+ name='demo_pk_data-Docetaxel-5335'
+ )
+ subject = protocol.subjects.first()
+ data = {
+ 'subject_id': subject.id,
+ 'biomarker_type_id': biomarker_type.id,
+ }
+ response = self.client.post(
+ "/api/nca/", data
+ )
+ self.assertEqual(
+ response.status_code, status.HTTP_200_OK
+ )
+
+ def test_nca_post_fail_no_subject(self):
+ biomarker_type = BiomarkerType.objects.get(
+ name='Docetaxel'
+ )
+ protocol = Protocol.objects.get(
+ name='demo_pk_data-Docetaxel-5109'
+ )
+ subject = protocol.subjects.first()
+ data = {
+ 'subject_id': subject.id,
+ 'biomarker_type_id': biomarker_type.id,
+ }
+ response = self.client.post(
+ "/api/nca/", data
+ )
+ self.assertEqual(
+ response.status_code, status.HTTP_400_BAD_REQUEST
+ )
+ self.assertRegex(
+ response.data['biomarker_type'],
+ (
+ "BiomarkerType {} does not have measurements "
+ "for subject id"
+ .format(biomarker_type.id)
+ )
+ )
diff --git a/pkpdapp/pkpdapp/tests/test_views/test_pd_model.py b/pkpdapp/pkpdapp/tests/test_views/test_pd_model.py
new file mode 100644
index 00000000..d9f1f03b
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_views/test_pd_model.py
@@ -0,0 +1,56 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pkpdapp.tests # noqa: F401
+from rest_framework import status
+from rest_framework.test import APITestCase, APIClient
+from django.contrib.auth.models import User
+from pkpdapp.models import Project
+
+
+class PdModelTestCase(APITestCase):
+ def setUp(self):
+ user = User.objects.get(username='demo')
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ def test_pd_project_filter(self):
+ response = self.client.get("/api/pharmacodynamic/?project_id=1")
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ response_data = response.data
+ self.assertEqual(len(response_data), 0)
+
+ def test_pd_serializer(self):
+ response = self.client.get("/api/pharmacodynamic/1/")
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+ def test_cannot_edit_read_only_project(self):
+ user = User.objects.get(username='demo2')
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ project = Project.objects.get(name='demo')
+ response = self.client.post(
+ "/api/pharmacodynamic/",
+ data={
+ 'name': 'test',
+ 'project': project.id
+ }
+ )
+ self.assertEqual(
+ response.status_code, status.HTTP_403_FORBIDDEN
+ )
+
+ response = self.client.put(
+ "/api/combined_model/1/",
+ data={
+ 'name': 'test',
+ 'project': project.id
+ }
+ )
+ self.assertEqual(
+ response.status_code, status.HTTP_403_FORBIDDEN
+ )
diff --git a/pkpdapp/pkpdapp/tests/test_views/test_simulate.py b/pkpdapp/pkpdapp/tests/test_views/test_simulate.py
new file mode 100644
index 00000000..a15cbe06
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_views/test_simulate.py
@@ -0,0 +1,58 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from pkpdapp.models import (
+ PharmacodynamicModel, Variable,
+ CombinedModel,
+
+)
+from django.contrib.auth.models import User
+
+from rest_framework import status
+from django.urls import reverse
+
+from rest_framework.test import APITestCase, APIClient
+
+
+class TestSimulateView(APITestCase):
+ def setUp(self):
+ user = User.objects.get(username='demo')
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ def test_simulate(self):
+ pd = PharmacodynamicModel.objects.get(
+ name='tumour_growth_gompertz',
+ read_only=False,
+ )
+ m = CombinedModel.objects.create(
+ name='my wonderful model',
+ pd_model=pd,
+ )
+
+ url = reverse('simulate-combined-model', args=(m.pk,))
+ data = {
+ 'outputs': ['PDCompartment.TS', 'environment.t'],
+ 'variables': {
+ 'PDCompartment.TS0': 1.1,
+ },
+ }
+
+ response = self.client.post(url, data, format='json')
+
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ outputs = response.data.get('outputs')
+ self.assertCountEqual(
+ list(outputs.keys()),
+ [
+ Variable.objects.get(qname=qname, dosed_pk_model=m).id
+ for qname in data['outputs']
+ ]
+ )
+
+ url = reverse('simulate-combined-model', args=(123,))
+ response = self.client.post(url, data, format='json')
+ self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
diff --git a/pkpdapp/pkpdapp/tests/test_views/test_unit.py b/pkpdapp/pkpdapp/tests/test_views/test_unit.py
new file mode 100644
index 00000000..ada81c0c
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_views/test_unit.py
@@ -0,0 +1,37 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import status
+from rest_framework.test import APITestCase, APIClient
+from django.contrib.auth.models import User
+from pkpdapp.models import (
+ PharmacodynamicModel, CombinedModel
+)
+
+
+class UnitTestCase(APITestCase):
+ def setUp(self):
+ self.pd_model = PharmacodynamicModel.objects.get(
+ name='tumour_growth_gompertz',
+ )
+
+ self.dosed_pk_model = \
+ CombinedModel.objects.create(
+ pd_model=self.pd_model,
+ )
+
+ user = User.objects.get(username='demo')
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ def test_dosed_pk_project_filter(self):
+ response = self.client.get(
+ "/api/unit/?dosed_pk_model_id={}".format(
+ self.dosed_pk_model.id
+ )
+ )
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ response_data = response.data
+ self.assertGreater(len(response_data), 0)
diff --git a/pkpdapp/pkpdapp/tests/test_views/test_variable.py b/pkpdapp/pkpdapp/tests/test_views/test_variable.py
new file mode 100644
index 00000000..d6773e78
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/test_views/test_variable.py
@@ -0,0 +1,37 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from rest_framework import status
+from rest_framework.test import APITestCase, APIClient
+from django.contrib.auth.models import User
+from pkpdapp.models import (
+ PharmacodynamicModel, CombinedModel
+)
+
+
+class VariableTestCase(APITestCase):
+ def setUp(self):
+ self.pd_model = PharmacodynamicModel.objects.get(
+ name='tumour_growth_gompertz',
+ )
+
+ self.dosed_pk_model = \
+ CombinedModel.objects.create(
+ pd_model=self.pd_model,
+ )
+
+ user = User.objects.get(username='demo')
+ self.client = APIClient()
+ self.client.force_authenticate(user=user)
+
+ def test_dosed_pk_project_filter(self):
+ response = self.client.get(
+ "/api/variable/?dosed_pk_model_id={}".format(
+ self.dosed_pk_model.id
+ )
+ )
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ response_data = response.data
+ self.assertGreater(len(response_data), 0)
diff --git a/pkpdapp/pkpdapp/tests/utils.py b/pkpdapp/pkpdapp/tests/utils.py
new file mode 100644
index 00000000..6bd3c89d
--- /dev/null
+++ b/pkpdapp/pkpdapp/tests/utils.py
@@ -0,0 +1,123 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+from pkpdapp.models import (
+ Inference, PharmacodynamicModel,
+ CombinedModel,
+ Unit,
+ LogLikelihood,
+ Project, BiomarkerType, Biomarker,
+ Algorithm,
+ Dataset,
+ Subject,
+)
+
+
+def create_pd_inference(sampling=False):
+ project = Project.objects.get(
+ name='demo',
+ )
+ pd = PharmacodynamicModel.objects.get(
+ name='tumour_growth_gompertz',
+ read_only=False,
+ )
+ model = CombinedModel.objects.create(
+ name='my wonderful model',
+ pd_model=pd,
+ )
+ # generate some fake data
+ output = model.variables.get(qname='PDCompartment.TS')
+ time = model.variables.get(qname='environment.t')
+ data = model.simulate(outputs=[output.qname, time.qname])
+ print(data)
+ TS = data[output.id]
+ times = data[time.id]
+ dataset = Dataset.objects.create(
+ name='fake data',
+ project=project,
+ )
+ bt = BiomarkerType.objects.create(
+ name='fake data',
+ dataset=dataset,
+ stored_unit=Unit.objects.get(symbol='mL'),
+ display_unit=Unit.objects.get(symbol='mL'),
+ stored_time_unit=Unit.objects.get(symbol='day'),
+ display_time_unit=Unit.objects.get(symbol='day'),
+ )
+ subject1 = Subject.objects.create(
+ id_in_dataset=1,
+ dataset=dataset,
+ )
+ subject2 = Subject.objects.create(
+ id_in_dataset=2,
+ dataset=dataset,
+ )
+
+ for i, (t, ts) in enumerate(zip(times, TS)):
+ Biomarker.objects.create(
+ biomarker_type=bt,
+ time=t,
+ value=ts,
+ subject=subject1,
+ )
+ Biomarker.objects.create(
+ biomarker_type=bt,
+ time=t,
+ value=ts,
+ subject=subject2,
+ )
+
+ bt_covariate = BiomarkerType.objects.create(
+ name='fake body weight',
+ dataset=dataset,
+ stored_unit=Unit.objects.get(symbol='kg'),
+ display_unit=Unit.objects.get(symbol='kg'),
+ stored_time_unit=Unit.objects.get(symbol='day'),
+ display_time_unit=Unit.objects.get(symbol='day'),
+ )
+
+ for s in [subject1, subject2]:
+ Biomarker.objects.create(
+ biomarker_type=bt_covariate,
+ time=0,
+ value=20,
+ subject=s,
+ )
+
+ algorithm = Algorithm.objects.get(
+ name='Haario-Bardenet') if sampling \
+ else Algorithm.objects.get(name='XNES')
+ inference = Inference.objects.create(
+ name='bob',
+ project=project,
+ max_number_of_iterations=10,
+ algorithm=algorithm,
+ number_of_chains=3,
+ )
+
+ log_likelihood = LogLikelihood.objects.create(
+ variable=model.variables.first(),
+ inference=inference,
+ form=LogLikelihood.Form.MODEL
+ )
+
+ # remove all outputs except
+ output_names = [
+ 'PDCompartment.TS',
+ ]
+ outputs = []
+ for output in log_likelihood.outputs.all():
+ if output.variable.qname in output_names:
+ output.parent.biomarker_type = bt
+ output.parent.observed = True
+ output.parent.save()
+ outputs.append(output.parent)
+ else:
+ for param in output.parent.parameters.all():
+ if param != output:
+ param.child.delete()
+ output.parent.delete()
+
+ return inference, log_likelihood, bt, bt_covariate, model, dataset
diff --git a/pkpdapp/pkpdapp/urls.py b/pkpdapp/pkpdapp/urls.py
new file mode 100644
index 00000000..fca1f7dc
--- /dev/null
+++ b/pkpdapp/pkpdapp/urls.py
@@ -0,0 +1,90 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+"""
+URL config of the pkpdapp project.
+
+The `urlpatterns` list routes URLs to views. For more information please see
+https://docs.djangoproject.com/en/3.0/topics/http/urls/.
+"""
+
+from django.urls import include, path
+from django.contrib import admin
+from . import api
+from rest_framework import routers
+
+router = routers.DefaultRouter()
+router.register('dataset', api.DatasetView, basename='dataset')
+router.register('user', api.UserView, basename='user')
+router.register('subject', api.SubjectView, basename='subject')
+router.register('compound', api.CompoundView, basename='compound')
+router.register('project', api.ProjectView, basename='project')
+router.register('project_access', api.ProjectAccessView,
+ basename='project_access')
+router.register('dose', api.DoseView, basename='dose')
+router.register('unit', api.UnitView, basename='unit')
+router.register('variable', api.VariableView, basename='variable')
+router.register('protocol', api.ProtocolView, basename='protocol')
+router.register('biomarker_type', api.BiomarkerTypeView,
+ basename='biomarker_type')
+router.register(
+ 'pharmacokinetic', api.PharmacokineticView,
+ basename='pharmacokinetic'
+)
+router.register(
+ 'pharmacodynamic', api.PharmacodynamicView,
+ basename='pharmacodynamic'
+)
+
+router.register(
+ 'combined_model', api.CombinedModelView,
+ basename='combined_model'
+)
+
+router.register(
+ 'inference', api.InferenceView,
+ basename='inference'
+)
+router.register(
+ 'algorithm', api.AlgorithmView,
+ basename='algorithm'
+)
+router.register(
+ 'inference_chain', api.InferenceChainView,
+ basename='inference_chain'
+)
+router.register(
+ 'simulation', api.SimulationViewSet,
+ basename='simulation'
+)
+
+urlpatterns = [
+ path('admin/doc/', include('django.contrib.admindocs.urls')),
+ path('admin/', admin.site.urls),
+ path('accounts/', include('django.contrib.auth.urls')),
+ path('api/', include(router.urls), name='api'),
+ path('api/nca/', api.NcaView.as_view(), name='nca'),
+ path('api/auce/', api.AuceView.as_view(), name='auce'),
+ path('api/combined_model//simulate',
+ api.SimulateCombinedView.as_view(), name='simulate-combined-model'),
+ path(
+ 'api/inference/wizard',
+ api.InferenceWizardView.as_view(),
+ name='inference-wizard'
+ ),
+ path(
+ 'api/inference//stop',
+ api.StopInferenceView.as_view(),
+ name='stop-inference'
+ ),
+ path('api/pharmacodynamic//simulate',
+ api.SimulatePdView.as_view(), name='simulate-pharmacodynamic'),
+ path('api/csrf/', api.get_csrf, name='auth-csrf'),
+ path('api/login/', api.login_view, name='auth-login'),
+ path('api/logout/', api.logout_view, name='auth-logout'),
+ path('api/session/', api.SessionView.as_view(), name='auth-session'),
+ path('api/whoami/', api.WhoAmIView.as_view(), name='auth-whoami'),
+ path('api-auth/', include('rest_framework.urls'))
+]
diff --git a/pkpdapp/pkpdapp/utils/__init__.py b/pkpdapp/pkpdapp/utils/__init__.py
new file mode 100644
index 00000000..f7a84b9d
--- /dev/null
+++ b/pkpdapp/pkpdapp/utils/__init__.py
@@ -0,0 +1,14 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+# flake8: noqa f401
+
+from .nca import NCA
+from .auce import Auce
+from .expression_parser import ExpressionParser
+from .monolix_model_parser import MonolixModelParser
+from .monolix_project_parser import MonolixProjectParser
+from .data_parser import DataParser
+from .monolix_importer import monolix_import
diff --git a/pkpdapp/pkpdapp/utils/auce.py b/pkpdapp/pkpdapp/utils/auce.py
new file mode 100644
index 00000000..acf677f6
--- /dev/null
+++ b/pkpdapp/pkpdapp/utils/auce.py
@@ -0,0 +1,127 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import numpy as np
+from scipy.optimize import curve_fit
+
+
+def fsigmoid(concentration, top, bottom, EC50):
+ """
+ this function simulates Emax-EC50 curve for a
+ given concentration range
+ """
+ return (
+ bottom + concentration *
+ (top - bottom) / (EC50 + concentration)
+ )
+
+
+class Auce():
+ def __init__(
+ self, name, subject_ids, concentrations,
+ subject_times, subject_data
+ ):
+ """
+ Initialise AUCE class for calculating and storing
+ AUCE data and fits
+ :param name: {str} --- group name
+ :param subject_ids: {np.ndarray} --- array of subject ids
+ :param concentrations: {np.ndarray} --- array of concentrations, one
+ for each subject
+ :param subject_times: {list of np.ndarray} --- list of arrays of
+ observation times, one array for each subject
+ :param subject_datas: {list of np.ndarray} --- list of arrays of
+ biomarker values, one array for each subject
+ """
+
+ self.fit_type = 'Sigmoid'
+ self.name = name
+ self.subject_ids = subject_ids
+ self.concentrations = concentrations
+ self.subject_times = subject_times
+ self.subject_data = subject_data
+ self.auce = []
+ for values, times in zip(subject_data, subject_times):
+ self.auce.append(self.calculate_auce(values, times))
+
+ self.x = None
+ self.y = None
+ self.y_upper = None
+ self.y_lower = None
+ self.fit_EC50 = None
+ self.sigma_EC50 = None
+ self.fit_EC50_y = None
+ self.fitted_params = None
+ self.covariates = None
+ self.fit_top = None
+ self.sigma_top = None
+ self.fit_bottom = None
+ self.sigma_bottom = None
+
+ self.auce_fit(
+ self.concentrations, self.auce
+ )
+
+ @staticmethod
+ def calculate_auce(values, times):
+ return np.trapz(values, times)
+
+ def auce_fit(self, concentrations, auce):
+ if self.fit_type != 'Sigmoid':
+ return None
+ if len(concentrations) < 4:
+ return None
+
+ p0 = [max(auce), min(auce), 1000]
+ fitted_params, covariates = curve_fit(
+ fsigmoid, concentrations, auce, p0=p0
+ )
+
+ fit_top, fit_bottom, fit_EC50 = fitted_params
+
+ sigma_top, sigma_bottom, sigma_EC50 = np.sqrt(
+ np.diag(covariates)
+ )
+
+ if (
+ fit_EC50 <= 0 or
+ not sigma_bottom or
+ not sigma_EC50 or
+ not sigma_top or
+ fit_EC50 - abs(sigma_EC50) <= 0
+ ):
+ return None
+
+ if min(concentrations):
+ x = np.geomspace(
+ min(concentrations), max(concentrations), 500
+ )
+ else:
+ x = np.geomspace(0.1, max(concentrations), 500)
+
+ y = fsigmoid(x, *fitted_params)
+
+ y_upper = fsigmoid(
+ x, fit_top + abs(sigma_top),
+ fit_bottom + abs(sigma_bottom),
+ fit_EC50 - abs(sigma_EC50)
+ )
+ y_lower = fsigmoid(
+ x, fit_top - abs(sigma_top),
+ fit_bottom - abs(sigma_bottom),
+ fit_EC50 + abs(sigma_EC50)
+ )
+
+ self.x = x
+ self.y = y
+ self.y_upper = y_upper
+ self.y_lower = y_lower
+ self.fit_EC50 = fit_EC50
+ self.sigma_EC50 = sigma_EC50
+ self.fit_top = fit_top
+ self.sigma_top = sigma_top
+ self.fit_bottom = fit_bottom
+ self.sigma_bottom = sigma_bottom
diff --git a/pkpdapp/pkpdapp/utils/data_parser.py b/pkpdapp/pkpdapp/utils/data_parser.py
new file mode 100644
index 00000000..7e3f751e
--- /dev/null
+++ b/pkpdapp/pkpdapp/utils/data_parser.py
@@ -0,0 +1,264 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import pandas as pd
+from pkpdapp.models import Unit
+from io import StringIO
+
+
+class DataParser:
+ alternate_col_names = {
+ "SUBJECT_ID": [
+ "ID", "id", "Subject_id", "Subject", "SUBJID",
+ "SUBJECT_ID"
+ ],
+ "TIME": [
+ "Time", "TIME", "TIMEPOINT", "t", "T", "time"
+ ],
+ "TIME_UNIT": [
+ "Time_unit", "Time_units", "TIMEUNIT", "TIME_UNIT"
+ ],
+ "AMOUNT": [
+ "Amt", "Amount", "AMT", "AMOUNT"
+ ],
+ "AMOUNT_UNIT": [
+ "Amt_unit", "Amt_units", "AMTUNIT", "UNIT", "AMOUNT_UNIT"
+ ],
+ "OBSERVATION": [
+ "DV", "Observation", "Y", "YVAL", "OBSERVATION",
+ "OBSERVATION_VALUE", "OBSERVATIONVALUE"
+ ],
+ "OBSERVATION_NAME": [
+ "Observation_id", "YDESC", "YNAME", "YTYPE", "OBSERVATION_ID",
+ "OBSERVATION_NAME", "OBSERVATIONID", "OBSERVATIONNAME"
+ ],
+ "OBSERVATION_UNIT": [
+ "DV_units", "Observation_unit", "YUNIT", "UNIT",
+ "OBSERVATION_UNIT",
+ "OBSERVATIONUNIT"
+ ],
+ "COMPOUND": [
+ "Compound", "COMPOUND"
+ ],
+ "ROUTE": [
+ "Route", "ROUTE"
+ ],
+ "INFUSION_TIME": [
+ "TINF", "Tinf", "tinf", "Infusion_time", "INFUSIONTIME",
+ "INFUSION_TIME"
+ ],
+ }
+
+ required_cols = [
+ "SUBJECT_ID",
+ "TIME",
+ "AMOUNT",
+ "OBSERVATION",
+ ]
+
+ optional_cols = [
+ "TIME_UNIT",
+ "AMOUNT_UNIT",
+ "OBSERVATION_UNIT",
+ "OBSERVATION_NAME",
+ "COMPOUND",
+ "ROUTE",
+ "INFUSION_TIME",
+ ]
+
+ altername_unit_names = {
+ "h": ["hour"],
+ "day": ["d"],
+ }
+
+ def is_covariate_column(self, col_name):
+ return col_name not in self.required_cols + self.optional_cols
+
+ def validate(self, data: pd.DataFrame):
+ colnames = data.columns.astype(str).tolist()
+
+ # check that all required columns are present
+ error_cols = []
+ found_cols = {}
+ covariate_cols = {}
+ for col_name in self.required_cols:
+ col_alts = self.alternate_col_names[col_name]
+ found = False
+ for alternate_name in col_alts:
+ if alternate_name in colnames:
+ found_cols[col_name] = alternate_name
+ found = True
+ break
+ if not found:
+ error_cols.append(col_name)
+
+ if len(error_cols) > 0:
+ raise RuntimeError(
+ (
+ 'Error parsing file, '
+ 'does not have the following columns: {}'
+ ).format(error_cols)
+ )
+
+ # search for optional columns
+ for col_name in self.optional_cols:
+ col_alts = self.alternate_col_names[col_name]
+ for alternate_name in col_alts:
+ if alternate_name in colnames:
+ found_cols[col_name] = alternate_name
+ break
+
+ # all remaining columns are covariates
+ for col_name in colnames:
+ if col_name not in found_cols.values():
+ covariate_cols[col_name] = col_name
+
+ # set dataframe column names to standard names
+ # we support the amount unit and observation unit being the same column
+ inv_found_cols = {v: k for k, v in found_cols.items()}
+ if (
+ "AMOUNT_UNIT" in found_cols and
+ "OBSERVATION_UNIT" in found_cols and
+ found_cols["AMOUNT_UNIT"] == found_cols["OBSERVATION_UNIT"]
+ ):
+ amt_obs_unit_same_col = True
+ amt_obs_unit_col = found_cols["AMOUNT_UNIT"]
+
+ # manually set column map and then duplicate column
+ inv_found_cols[amt_obs_unit_col] = "AMOUNT_UNIT"
+ data = data.rename(columns=inv_found_cols)
+ data["OBSERVATION_UNIT"] = data["AMOUNT_UNIT"]
+ else:
+ amt_obs_unit_same_col = False
+ data = data.rename(columns=inv_found_cols)
+
+ # map alternate unit names to standard names
+ inv_altername_unit_names = {}
+ for k, v in self.altername_unit_names.items():
+ for v2 in v:
+ inv_altername_unit_names[v2] = k
+
+ def map_unit_names(x):
+ if x in inv_altername_unit_names:
+ return inv_altername_unit_names[x]
+ else:
+ return x
+ for unit_col in ["TIME_UNIT", "AMOUNT_UNIT", "OBSERVATION_UNIT"]:
+ if unit_col in found_cols:
+ data[unit_col] = data[unit_col].map(map_unit_names)
+
+ # put in default observation name if not present
+ if "OBSERVATION_NAME" not in found_cols:
+ data["OBSERVATION_NAME"] = "observation"
+
+ # put in default compound name if not present
+ if "COMPOUND" not in found_cols:
+ data["COMPOUND"] = "unknown compound"
+
+ # put in default route name if not present
+ if "ROUTE" not in found_cols:
+ data["ROUTE"] = "IV"
+
+ # put in default units if not present, convert any percentage units
+ # to dimensionless
+ for unit_col in ["TIME_UNIT", "AMOUNT_UNIT", "OBSERVATION_UNIT"]:
+ if unit_col not in found_cols:
+ data[unit_col] = ""
+ else:
+ def convert_percent_to_dim(x):
+ xl = x.lower()
+ if (
+ "percent" in xl or
+ "fraction" in xl or
+ "ratio" in xl or
+ "%" in xl
+ ):
+ return ""
+ else:
+ return x
+ data[unit_col] = data[unit_col].map(convert_percent_to_dim)
+
+ # put in default infusion time if not present
+ delta_time = data.sort_values(by=["TIME"]).groupby(
+ ["SUBJECT_ID"]
+ )["TIME"].diff().dropna()
+ min_delta_time = delta_time[delta_time > 0].min()
+ if "INFUSION_TIME" not in found_cols:
+ data["INFUSION_TIME"] = min_delta_time / 100.0
+
+ # check that infusion time is not zero or negative
+ if (
+ data["INFUSION_TIME"].apply(pd.to_numeric, errors='coerce') <= 0
+ ).any():
+ raise RuntimeError(
+ (
+ 'Error parsing file, '
+ 'contains zero infusion time'
+ )
+ )
+
+ # check that units are in database
+ for unit_col in ["TIME_UNIT", "AMOUNT_UNIT", "OBSERVATION_UNIT"]:
+ if unit_col in found_cols:
+ units = data[unit_col].unique().tolist()
+ pkpdapp_units = Unit.objects.all()
+ pkpdapp_units_symbols = \
+ pkpdapp_units.values_list('symbol', flat=True)
+ error_units = set([
+ u for u in units
+ if u not in pkpdapp_units_symbols
+ ])
+ if len(error_units) > 0:
+ raise RuntimeError(
+ (
+ 'Error parsing file, '
+ 'contains the following unknown units: {}'
+ ).format(error_units)
+ )
+
+ # check that time unit is constant
+ if "TIME_UNIT" in found_cols:
+ time_units = data["TIME_UNIT"].unique()
+ if len(time_units) > 1:
+ raise RuntimeError(
+ (
+ 'Error parsing file, '
+ 'contains multiple time units: {}'
+ ).format(time_units)
+ )
+
+ # check that units are same for each observation type
+ if "OBSERVATION_UNIT" in found_cols:
+ obs_units = data.groupby("OBSERVATION_NAME")[
+ "OBSERVATION_UNIT"].unique()
+ if amt_obs_unit_same_col:
+ max_num_units = 2
+ else:
+ max_num_units = 1
+ if obs_units.apply(lambda x: len(x) > max_num_units).any():
+ raise RuntimeError(
+ (
+ 'Error parsing file, '
+ 'contains multiple observation units: {}'
+ ).format(obs_units)
+ )
+
+ # check for missing data and drop any rows where data are missing
+ num_missing = data.isna().sum().sum()
+ if num_missing > 0:
+ data = data.fillna('')
+ return data
+
+ def parse_from_str(self, data_str, delimiter=None):
+ data = StringIO(data_str)
+ data = pd.read_csv(data, delimiter=delimiter)
+ data = self.validate(data)
+ return data
+
+ def parse_from_stream(self, data_stream, delimiter=None):
+ data = pd.read_csv(data_stream, delimiter=delimiter)
+ data = self.validate(data)
+ return data
diff --git a/pkpdapp/pkpdapp/utils/default_params.py b/pkpdapp/pkpdapp/utils/default_params.py
new file mode 100644
index 00000000..614e5aa7
--- /dev/null
+++ b/pkpdapp/pkpdapp/utils/default_params.py
@@ -0,0 +1,53 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+import openpyxl
+
+
+# Load the workbook
+workbook = openpyxl.load_workbook(
+ "pkpdapp/migrations/models/ParametersValue_Species.xlsx", data_only=True
+)
+
+sheet_names = [
+ "1cmpt_PK_Model",
+ "2cmpt_PK_Model",
+ "3cmpt_PK_Model",
+ "1cmpt_TMDD_Model",
+ "2cmpt_TMDD_Model",
+]
+model_names = [
+ "one_compartment",
+ "two_compartment",
+ "three_compartment",
+ "one_compartment_tmdd",
+ "two_compartment_tmdd",
+]
+species_list = ["M", "R", "K", "H"]
+compound_type = ["SM", "LM"]
+clinical = [False, False, False, True]
+
+defaults = {}
+
+for sheet_name, model_name in zip(sheet_names, model_names):
+ worksheet = workbook[sheet_name]
+
+ defaults[model_name] = {}
+ for row in worksheet.iter_rows():
+ parameter = row[0].value
+ if parameter is None:
+ continue
+ defaults[model_name][parameter] = {}
+ for i, species in enumerate(species_list):
+ defaults[model_name][parameter][species] = {}
+ for j, ctype in enumerate(compound_type):
+ rowi = i * 4 + j * 2 + 1
+ value = row[rowi].value
+ unit = row[rowi + 1].value
+ if_clinical = clinical[i]
+ defaults[model_name][parameter][species][ctype] = {
+ "value": value,
+ "unit": unit,
+ }
diff --git a/pkpdapp/pkpdapp/utils/expression_parser.py b/pkpdapp/pkpdapp/utils/expression_parser.py
new file mode 100644
index 00000000..8284d14d
--- /dev/null
+++ b/pkpdapp/pkpdapp/utils/expression_parser.py
@@ -0,0 +1,163 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+# based on fourFn.py example from pyparsing
+# (https://github.com/pyparsing/pyparsing/blob/master/examples/fourFn.py)
+# Copyright 2003-2019 by Paul McGuire
+#
+import math
+import operator
+from pyparsing import (
+ Literal,
+ Word,
+ Group,
+ Forward,
+ alphas,
+ alphanums,
+ Regex,
+ ParseException,
+ dbl_quoted_string,
+ sgl_quoted_string,
+ remove_quotes,
+ Suppress,
+ Keyword,
+ delimitedList,
+)
+
+epsilon = 1e-12
+opn = {
+ "+": operator.add,
+ "-": operator.sub,
+ "*": operator.mul,
+ "/": operator.truediv,
+ "^": operator.pow,
+}
+
+functions = {
+ "sin": math.sin,
+ "cos": math.cos,
+ "tan": math.tan,
+ "exp": math.exp,
+ "abs": abs,
+ "trunc": int,
+ "round": round,
+ "sgn": lambda a: -1 if a < -epsilon else 1 if a > epsilon else 0,
+ # functionsl with multiple arguments
+ "multiply": lambda a, b: a * b,
+ "hypot": math.hypot,
+ # functions with a variable number of arguments
+ "all": lambda *a: all(a),
+}
+
+
+class ExpressionParser:
+ """
+ expop :: '^'
+ multop :: '*' | '/'
+ addop :: '+' | '-'
+ integer :: ['+' | '-'] '0'..'9'+
+ atom :: real | Parameter '[' string ']'
+ | Biomarker '[' string ']'
+ | fn '(' expr ')'
+ | '(' expr ')'
+ factor :: atom [ expop factor ]*
+ term :: factor [ multop factor ]*
+ expr :: term [ addop term ]*
+ """
+ # map operator symbols to corresponding arithmetic operations
+
+ def __init__(self):
+ # use CaselessKeyword for e and pi, to avoid accidentally matching
+ # functions that start with 'e' or 'pi' (such as 'exp'); Keyword
+ # and CaselessKeyword only match whole words
+ param = Keyword("parameter")
+ biomarker = Keyword("biomarker")
+ string = (dbl_quoted_string | sgl_quoted_string).setParseAction(
+ remove_quotes, self.push_first
+ )
+ # fnumber = Combine(Word("+-"+nums, nums) +
+ # Optional("." + Optional(Word(nums))) +
+ # Optional(e + Word("+-"+nums, nums)))
+ # or use provided pyparsing_common.number, but convert back to str:
+ # fnumber = ppc.number().addParseAction(lambda t: str(t[0]))
+ fnumber = Regex(r"[+-]?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?")
+ ident = Word(alphas, alphanums + "_$")
+
+ plus, minus, mult, div = map(Literal, "+-*/")
+ lpar, rpar = map(Suppress, "()")
+ addop = plus | minus
+ multop = mult | div
+ expop = Literal("^")
+
+ expr = Forward()
+ expr_list = delimitedList(Group(expr))
+
+ # add parse action that replaces the function identifier with a (name,
+ # number of args) tuple
+ def insert_fn_argcount_tuple(t):
+ fn = t.pop(0)
+ num_args = len(t[0])
+ t.insert(0, (fn, num_args))
+
+ fn_call = (ident + lpar - Group(expr_list) + rpar).setParseAction(
+ insert_fn_argcount_tuple
+ )
+ atom = (
+ addop[...] +
+ (
+ (
+ param + lpar + string + rpar
+ ).setParseAction(self.push_first) |
+ (
+ biomarker + lpar + string + rpar
+ ).setParseAction(self.push_first) |
+ (
+ fn_call | fnumber | ident
+ ).setParseAction(self.push_first) |
+ Group(lpar + expr + rpar)
+ )
+ ).setParseAction(self.push_unary_minus)
+
+ # by defining exponentiation as "atom [ ^ factor ]..." instead of "atom
+ # [ ^ atom ]...", we get right-to-left exponents, instead of
+ # left-to-right that is, 2^3^2 = 2^(3^2), not (2^3)^2.
+ factor = Forward()
+ factor <<= atom + (expop + factor).setParseAction(self.push_first)[...]
+ term = factor + (multop + factor).setParseAction(self.push_first)[...]
+ expr <<= term + (addop + term).setParseAction(self.push_first)[...]
+
+ self.exprStack = []
+ self.bnf = expr
+
+ def push_first(self, toks):
+ self.exprStack.append(toks[0])
+
+ def push_unary_minus(self, toks):
+ for t in toks:
+ if t == "-":
+ self.exprStack.append("unary -")
+ else:
+ break
+
+ def parse(self, string, parseAll=True):
+ self.exprStack[:] = []
+ self.bnf.parseString(string, parseAll=parseAll)
+
+ def is_valid(self, string):
+ try:
+ self.parse(string)
+ return True
+ except ParseException:
+ return False
+
+ def get_params(self, string, parseAll=True):
+ self.exprStack[:] = []
+ self.bnf.parseString(string, parseAll=parseAll)
+ ret = []
+ for i, op in enumerate(self.exprStack):
+ if op == 'parameter' or op == 'biomarker':
+ ret.append((op, self.exprStack[i - 1]))
+ return list(set(ret))
diff --git a/pkpdapp/pkpdapp/utils/monolix_importer.py b/pkpdapp/pkpdapp/utils/monolix_importer.py
new file mode 100644
index 00000000..17350501
--- /dev/null
+++ b/pkpdapp/pkpdapp/utils/monolix_importer.py
@@ -0,0 +1,133 @@
+
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+from django.apps import apps
+
+from pkpdapp.models import (
+ Project
+)
+from pkpdapp.utils import (
+ MonolixModelParser,
+ MonolixProjectParser,
+ DataParser
+)
+
+
+def monolix_import(
+ app_project: Project, project_str: str,
+ model_str: str, data_str: str, validate: bool = True
+):
+ """
+ Import a Monolix project into the database.
+
+ Parameters
+ ----------
+ project
+ project file as a string
+ model
+ model file as a string
+ data
+ data file as a string
+ """
+
+ # parse the project file
+ project_parser = MonolixProjectParser()
+ project = project_parser.parse(project_str)
+
+ # parse the model file
+ model_parser = MonolixModelParser()
+ model, (admin_id, dosed_compartment, tlag,
+ direct, dosed_qname) = model_parser.parse(model_str)
+
+ # parse the data file
+ data_parser = DataParser()
+ delimiter = project['']['[FILEINFO]']['delimiter']
+ if delimiter == 'tab':
+ delimiter = '\t'
+ data = data_parser.parse_from_str(data_str, delimiter=delimiter)
+
+ if validate:
+ return
+
+ # set the parameters of the myokit model to match the typical population
+ # parameters
+ for parameter_name, parameter in project[
+ ''
+ ]['[INDIVIDUAL]']['DEFINITION:'].items():
+ typical_str = parameter['typical']
+ try:
+ typical_value = float(typical_str)
+ except ValueError:
+ # must refer to a population parameter
+ population_parameter = project[''][typical_str]
+ typical_value = population_parameter['value']
+ var = model.var('root.{}'.format(parameter_name))
+ var.set_rhs(typical_value)
+
+ # create the pd model
+ PharmacodynamicModel = apps.get_model('pkpdapp', 'PharmacodynamicModel')
+ pd_model = PharmacodynamicModel.objects.create(
+ name=project['']['[LONGITUDINAL]']['file'],
+ project=app_project,
+ mmt=model.code(),
+ )
+
+ # create the dataset
+ Dataset = apps.get_model('pkpdapp', 'Dataset')
+ dataset = Dataset.objects.create(
+ name=project['']['[FILEINFO]']['file'],
+ project=app_project,
+ )
+
+ # only display the fitted output of dataset
+ for bt in dataset.biomarker_types.all():
+ if bt.name == project['']['data']:
+ bt.display = True
+ else:
+ bt.display = False
+ bt.save()
+
+ if direct:
+ data.assign(ROUTE='IV')
+ else:
+ data.assign(ROUTE='Extravascular')
+
+ dataset.replace_data(data)
+
+ # get the right protocol
+ # (TODO: we cheat and only get the one for the first subject)
+ protocol = dataset.subjects.first().protocol
+
+ # create the pk model
+ CombinedModel = apps.get_model(
+ 'pkpdapp', 'CombinedModel')
+ pk_model = CombinedModel.objects.create(
+ name='Dosed {}'.format(project['']['[LONGITUDINAL]']['file']),
+ project=app_project,
+ pd_model=pd_model,
+ pk_model=None,
+ )
+
+ drug = pk_model.variables.get(qname=dosed_qname)
+ drug.protocol = protocol
+ drug.save()
+
+ # only display the fitted output of model
+ fit_variable = project['']['model']
+ model_variable = project[
+ ''
+ ][
+ '[LONGITUDINAL]'
+ ][
+ 'DEFINITION:'
+ ][fit_variable]['prediction']
+ for model in [pd_model, pk_model]:
+ for var in model.variables.filter(constant=False):
+ var.display = var.name == model_variable
+ var.save()
+
+ return pd_model, pk_model, dataset
diff --git a/pkpdapp/pkpdapp/utils/monolix_model_parser.py b/pkpdapp/pkpdapp/utils/monolix_model_parser.py
new file mode 100644
index 00000000..d3729058
--- /dev/null
+++ b/pkpdapp/pkpdapp/utils/monolix_model_parser.py
@@ -0,0 +1,329 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+# based on fourFn.py example from pyparsing
+# (https://github.com/pyparsing/pyparsing/blob/master/examples/fourFn.py)
+# Copyright 2003-2019 by Paul McGuire
+#
+from dataclasses import dataclass
+
+import myokit
+import numbers
+import pyparsing as pp
+import pyparsing.common as ppc
+
+pp.enable_all_warnings()
+
+binops = {
+ '/': myokit.Divide,
+ '*': myokit.Multiply,
+ '-': myokit.Minus,
+ '+': myokit.Plus,
+}
+
+
+@dataclass
+class Variable:
+ name: str
+ constant: bool
+ state: bool
+
+
+class MonolixModelParser:
+ """
+ expop :: '^'
+ multop :: '*' | '/'
+ addop :: '+' | '-'
+ integer :: ['+' | '-'] '0'..'9'+
+ atom :: real
+ | ident
+ | '(' expr ')'
+ factor :: atom [ expop factor ]*
+ term :: factor [ multop factor ]*
+ expr :: term [ addop term ]*
+ eqn :: term
+ """
+ # map operator symbols to corresponding arithmetic operations
+
+ def __init__(self):
+ # fnumber = Combine(Word("+-"+nums, nums) +
+ # Optional("." + Optional(Word(nums))) +
+ # Optional(e + Word("+-"+nums, nums)))
+ # or use provided pyparsing_common.number, but convert back to str:
+ fnumber = ppc.number()
+ ident = pp.Regex("[_a-zA-Z][_a-zA-Z0-9]*")
+ ident_0 = pp.Regex("[_a-zA-Z][_a-zA-Z0-9]*_0")
+ ddt_ident = pp.Regex("ddt_[_a-zA-Z][_a-zA-Z0-9]*")
+
+ plus, minus, mult, div = map(pp.Literal, "+-*/")
+ lpar, rpar = map(pp.Suppress, "()")
+ lcpar, rcpar = map(pp.Suppress, "{}")
+ addop = plus | minus
+ multop = mult | div
+ expop = pp.Literal("^")
+ equals = pp.Suppress("=")
+
+ expr = pp.Forward()
+ atom = (
+ addop[...] + (
+ (fnumber | ident).set_parse_action(self.push_first) |
+ pp.Group(lpar + expr + rpar)
+ )
+ ).set_parse_action(self.push_unary_minus)
+
+ # by defining exponentiation as "atom [ ^ factor ]..." instead of "atom
+ # [ ^ atom ]...", we get right-to-left exponents, instead of
+ # left-to-right that is, 2^3^2 = 2^(3^2), not (2^3)^2.
+ factor = pp.Forward()
+ factor <<= (
+ atom +
+ (expop + factor).set_parse_action(self.push_first)[...]
+ )
+ term = (
+ factor +
+ (multop + factor).set_parse_action(self.push_first)[...]
+ )
+ expr <<= (
+ term +
+ (addop + term).set_parse_action(self.push_first)[...]
+ )
+
+ ode_type = pp.Keyword('odeType') + equals + (pp.Keyword('stiff') |
+ pp.Keyword('nonStiff'))
+ equation = (
+ ident + equals +
+ pp.Group(expr).set_parse_action(self.construct_expr)
+ )
+ initial_condition = (
+ ident_0 + equals +
+ pp.Group(expr).set_parse_action(self.construct_expr)
+ )
+ rate_equation = (
+ ddt_ident + equals +
+ pp.Group(expr).set_parse_action(self.construct_expr)
+ )
+
+ fn_value = fnumber | ident
+ fn_arg = (ident + equals + fn_value) | fn_value
+ fn_call = (
+ ident + lpar -
+ pp.delimited_list(pp.Group(fn_arg), delim=',') + rpar
+ )
+
+ pk_block = ("PK:" + (
+ pp.Group(fn_call)
+ )[...]).set_parse_action(self.construct_pk)
+
+ equation_block = pp.Keyword("EQUATION:") + (
+ ode_type |
+ rate_equation.set_parse_action(
+ self.construct_rate_equation
+ ) |
+ initial_condition.set_parse_action(
+ self.construct_initial_condition
+ ) |
+ equation.set_parse_action(
+ self.construct_equation
+ )
+
+ )[...]
+
+ output_block = pp.Keyword("OUTPUT:") + (
+ ident + equals +
+ lcpar - pp.delimited_list(ident, delim=',') +
+ rcpar
+ )
+
+ inputs = (
+ pp.Keyword("input") + equals + lcpar -
+ pp.delimited_list(
+ ident, delim=','
+ ).set_parse_action(self.construct_inputs) +
+ rcpar
+ )
+
+ longitudinal_keyword = pp.Keyword("[LONGITUDINAL]")
+
+ longitudinal = (
+ longitudinal_keyword +
+ inputs +
+ (
+ pk_block & equation_block & output_block
+ )
+ )
+
+ src = "DESCRIPTION:" + pp.SkipTo(longitudinal_keyword) + longitudinal
+
+ monolix_comment = ';' + pp.restOfLine()
+ src.ignore(monolix_comment)
+
+ pp.autoname_elements()
+ self.parser = src
+ self.exprStack = []
+ self.variables = {}
+ self.pk = []
+ self.myokit_model: myokit.Model = myokit.Model()
+ self.units = {}
+ self.administration_id = None
+ self.tlag = None
+ self.direct_dosing = None
+ self.dosed_compartment = None
+ self.dosed_qname = None
+
+ def initialise_model(self):
+ self.myokit_model: myokit.Model = myokit.Model()
+ root_cmp = self.myokit_model.add_component('root')
+ t = self.get_or_construct_var('t', root_cmp)
+ t.set_binding('time')
+
+ def push_first(self, toks):
+ self.exprStack.append(toks[0])
+
+ def push_unary_minus(self, toks):
+ for t in toks:
+ if t == "-":
+ self.exprStack.append("unary -")
+ else:
+ break
+
+ def construct_pk(self, toks):
+ compartments = {}
+ for line in toks[1:]:
+ fn_name, *tok_args = line
+ args = {}
+ for i, arg in enumerate(tok_args):
+ if len(arg) == 2:
+ [name, value] = arg
+ args[name] = value
+ else:
+ [value] = arg
+ args[i] = value
+
+ if fn_name == 'compartment':
+ cmt = args.get('cmt', args.get(0, 1))
+ if not isinstance(cmt, str) or cmt[0].isalpha():
+ cmt = f'cmt{cmt}'
+ amount = args.get('amount', args.get(1, None))
+ volume = args.get('volume', args.get(2, 1))
+ concentration = args.get('concentration', args.get(3, None))
+ comp = self.myokit_model.add_component(cmt)
+ if isinstance(volume, str):
+ volume_var = self.get_or_construct_var(volume, comp)
+ else:
+ volume_var = myokit.Number(volume)
+ if amount:
+ amount_var = self.get_or_construct_var(amount, comp)
+ else:
+ raise pp.ParseException(
+ f'arg "amount" required for compartment {cmt}')
+ if concentration:
+ conc_var = self.get_or_construct_var(concentration, comp)
+ conc_var.set_rhs(myokit.Divide(amount_var, volume_var))
+ compartments[cmt] = amount_var
+
+ elif fn_name == 'iv':
+ cmt = args.get('cmt', args.get(0, 1))
+ if not isinstance(cmt, str) or cmt[0].isalpha():
+ cmt = f'cmt{cmt}'
+ adm = args.get('adm', args.get(1, 1))
+ if self.administration_id is not None:
+ raise pp.ParseException(
+ 'only a single administration id supported'
+ )
+ self.administration_id = str(adm)
+ tlag = args.get('Tlag', args.get(2, 0))
+ self.tlag = float(tlag)
+ # p = args.get('p', args.get(3, 1))
+
+ if cmt not in compartments:
+ raise pp.ParseException(
+ f'compartment {cmt} not found in pk block'
+ )
+ amount_var = compartments[cmt]
+ if not amount_var.is_state():
+ amount_var.promote(0)
+ direct = True
+ self.direct_dosing = direct
+ self.dosed_compartment = cmt
+ self.dosed_qname = amount_var.qname()
+
+ def construct_inputs(self, toks):
+ for name in toks:
+ _ = self.get_or_construct_var(name)
+
+ def construct_expr(self, toks):
+ toks[0] = self.construct_myokit_expr(self.exprStack)
+
+ def get_or_construct_var(self, name, compartment=None):
+ if compartment is None:
+ compartment = self.myokit_model.get('root')
+ if name not in self.variables:
+ var = compartment.add_variable(name)
+ var.set_rhs(0)
+ if name in self.units:
+ unit = myokit.Unit.parse_simple(self.units[name])
+ else:
+ unit = None
+ var.set_unit(unit)
+ self.variables[name] = var
+ return self.variables[name]
+
+ def construct_equation(self, toks):
+ name, expr = toks
+ var = self.get_or_construct_var(name)
+ var.set_rhs(expr)
+
+ def construct_rate_equation(self, toks):
+ name, expr = toks
+ # get rid of ddt_
+ name = name[4:]
+ var = self.get_or_construct_var(name)
+ if not var.is_state():
+ var.promote(0)
+ var.set_rhs(expr)
+
+ def construct_initial_condition(self, toks):
+ name, expr = toks
+ # get rid of _0
+ name = name[:-2]
+ var = self.get_or_construct_var(name)
+
+ if var == self.myokit_model.time():
+ var.set_rhs(expr)
+ elif var.is_state():
+ var.demote()
+ var.promote(expr)
+ else:
+ var.promote(expr)
+
+ def construct_myokit_expr(self, s):
+ op = s.pop()
+ if isinstance(op, numbers.Number):
+ return myokit.Number(op)
+ if op == "unary -":
+ return myokit.PrefixMinus(self.construct_myokit_expr(s))
+ if op in "+-*/^":
+ # note: operands are pushed onto the stack in reverse order
+ op2 = self.construct_myokit_expr(s)
+ op1 = self.construct_myokit_expr(s)
+ return binops[op](op1, op2)
+ elif op[0].isalpha():
+ var = self.get_or_construct_var(op)
+ return myokit.Name(var)
+ else:
+ raise pp.ParseException(f'unknown op {op}')
+
+ def parse(self, model_str, parseAll=True):
+ try:
+ self.initialise_model()
+ self.parser.parseString(model_str, parseAll=parseAll)
+ except pp.ParseException as err:
+ raise RuntimeError(err.explain())
+ return self.myokit_model, \
+ (
+ self.administration_id, self.dosed_compartment,
+ self.tlag, self.direct_dosing, self.dosed_qname
+ )
diff --git a/pkpdapp/pkpdapp/utils/monolix_project_parser.py b/pkpdapp/pkpdapp/utils/monolix_project_parser.py
new file mode 100644
index 00000000..9244d3b6
--- /dev/null
+++ b/pkpdapp/pkpdapp/utils/monolix_project_parser.py
@@ -0,0 +1,121 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+# based on fourFn.py example from pyparsing
+# (https://github.com/pyparsing/pyparsing/blob/master/examples/fourFn.py)
+# Copyright 2003-2019 by Paul McGuire
+#
+import pyparsing as pp
+import pyparsing.common as ppc
+
+pp.enable_all_warnings()
+
+
+class MonolixProjectParser:
+ def __init__(self):
+ fnumber = ppc.number()
+ ident = pp.Regex("[_a-zA-Z][-_a-zA-Z0-9]*")
+
+ lpar, rpar = map(pp.Suppress, "()")
+ lcpar, rcpar = map(pp.Suppress, "{}")
+ equals = pp.Suppress("=")
+
+ array = pp.Forward()
+ func_arg = ident
+ func = (
+ ident + lpar -
+ pp.delimited_list(pp.Group(func_arg), delim=',') + rpar
+ )
+ array_or_ident_or_number_or_func = (func | ident | fnumber | array)
+ array_entry = (ident + equals +
+ array_or_ident_or_number_or_func) | ident | fnumber
+ array <<= (
+ lcpar +
+ pp.delimited_list(pp.Group(array_entry), delim=',') +
+ rcpar
+ ).set_parse_action(self.parse_array)
+ entry_value = ident | pp.QuotedString("'") | array
+ entry = (ident + equals + entry_value)
+
+ entry_list = pp.ZeroOrMore(entry).set_parse_action(
+ self.parse_list_of_key_values)
+ definition_block = pp.Keyword("DEFINITION:") + entry_list
+ file_info = pp.Keyword("[FILEINFO]") + entry_list
+ file_content = pp.Keyword("[CONTENT]") + entry_list
+ data = (
+ pp.Keyword("") + (
+ file_info + file_content
+ ).set_parse_action(self.parse_list_of_key_values)
+ )
+ covariate = pp.Keyword("[COVARIATE]") + (
+ entry_list + pp.Opt(definition_block)
+ ).set_parse_action(self.parse_add_list_of_key_values)
+ individual = pp.Keyword("[INDIVIDUAL]") + (
+ entry_list + pp.Opt(definition_block)
+ ).set_parse_action(self.parse_add_list_of_key_values)
+ longitudinal = pp.Keyword("[LONGITUDINAL]") + (
+ entry_list + pp.Opt(definition_block)
+ ).set_parse_action(self.parse_add_list_of_key_values)
+ model = pp.Keyword("") + (
+ covariate + individual + longitudinal
+ ).set_parse_action(self.parse_list_of_key_values)
+
+ task_arg = (ident + equals + array_or_ident_or_number_or_func)
+ task = (
+ ident + lpar -
+ pp.Opt(pp.delimited_list(pp.Group(task_arg), delim=',')) + rpar
+ )
+ task_list = pp.ZeroOrMore(task).set_parse_action(
+ self.parse_list_of_key_values)
+ tasks = pp.Keyword("[TASKS]") + task_list
+
+ ident_or_string_or_number = ident | fnumber | pp.QuotedString("'")
+ key_value = ident + equals + ident_or_string_or_number
+ key_value_list = pp.ZeroOrMore(key_value).set_parse_action(
+ self.parse_list_of_key_values)
+ global_settings = pp.Keyword("GLOBAL:") + key_value_list
+ population_settings = pp.Keyword("POPULATION:") + key_value_list
+ settings = pp.Keyword("[SETTINGS]") + (
+ pp.Opt(global_settings) + pp.Opt(population_settings)
+ ).set_parse_action(self.parse_list_of_key_values)
+ monolix = pp.Keyword(
+ "") + (
+ tasks + settings
+ ).set_parse_action(self.parse_list_of_key_values)
+
+ fit = pp.Keyword("") + entry_list
+ parameter = pp.Keyword("") + entry_list
+ src = (data + model + fit + parameter +
+ monolix).set_parse_action(self.parse_list_of_key_values)
+
+ monolix_comment = ';' + pp.restOfLine()
+ src.ignore(monolix_comment)
+
+ pp.autoname_elements()
+ self.parser = src
+
+ def parse_array(self, s: str, loc: int, toks):
+ # if all elements are singletons, return a list of the elements
+ if all([len(x) == 1 for x in toks]):
+ return [[x[0] for x in toks]]
+ # if all elements are tuples, return a dict of the elements
+ return [{x[0]: x[1] if len(x) > 1 else True for x in toks}]
+
+ def parse_list_of_key_values(self, toks):
+ return [{toks[2 * i]: toks[2 * i + 1] for i in range(len(toks) // 2)}]
+
+ def parse_add_list_of_key_values(self, toks):
+ return [
+ toks[0] | {toks[2 * i + 1]: toks[2 * i + 2]
+ for i in range((len(toks) - 1) // 2)}
+ ]
+
+ def parse(self, project_str, parseAll=True) -> dict:
+ try:
+ result = self.parser.parseString(project_str, parseAll=parseAll)
+ except pp.ParseException as err:
+ raise RuntimeError(err.explain())
+ return result.asList()[0]
diff --git a/pkpdapp/pkpdapp/utils/nca.py b/pkpdapp/pkpdapp/utils/nca.py
new file mode 100644
index 00000000..b1f067d4
--- /dev/null
+++ b/pkpdapp/pkpdapp/utils/nca.py
@@ -0,0 +1,294 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+import numpy as np
+import scipy.stats as stats
+
+
+class NCA():
+ def __init__(self,
+ times, concs, DM,
+ doseSchedule='Single', administrationRoute='IVBolus'
+ ):
+ """
+ Initialise NCA class for calculating and storing NCA parameters
+ :param times: {np.ndarray} --- array of observation times
+ :param concs: {np.ndarray} --- array of observed concentration values
+ :param DM: {float} --- administered dose amount
+ :param doseSchedule: {string} Single or Multiple dose data
+ :param administrationRoute: {string} IVBolus, IVInfusion, ExtraVascular
+ """
+ # Check if intial concentration has been measured
+
+ if times[0] == 0:
+ self.is_c0extrapolated = False # initial concentration measured
+ self.times = times
+ self.concentrations = concs
+ self.dose_amount = DM # dose amount
+ self.c_0 = None # not extrapolated
+ self.administration_route = administrationRoute
+ else:
+ self.is_c0extrapolated = True # initial concentration NOT measured
+ c0 = self.extrapolate_c0(concs, times) # extrapolate initial conc
+ self.c_0 = c0
+ self.times = np.insert(times, 0, 0, axis=0)
+ self.concentrations = np.insert(concs, 0, c0, axis=0)
+ self.dose_amount = DM # dose amount
+ self.administration_route = administrationRoute
+
+ def calculate_nca(self):
+ """
+ Calculates and stores all single dose NCA parameters
+ :return: None
+ """
+ self.auc_0_last = self._auc_0_last()
+ self.aumc_0_last = self._aumc_0_last()
+ self.lambda_z, self.r2, self.num_points = self._Lambda_z()
+
+ self.auc_infinity = self._auc_infinity()
+ self.auc_infinity_dose = self._auc_infinity_dose()
+ # self.aucx_y
+ self.auc_extrap_percent = self._auc_extrap_percent()
+ self.cl = self._CL()
+ self.c_max, self.t_max = self._find_Cmax()
+ self.c_max_dose = self._C_max_Dose()
+ # C_max_x_y
+
+ self.aumc = self._aumc()
+ self.aumc_extrap_percent = self._aumc_extrap_percent()
+ self.mrt = self._MRT()
+ self.tlast = self._Tlast() # ?? above LOQ?
+ self.t_half = np.log(2) / self.lambda_z
+ # T_max_x_y
+ if self.administration_route == 'IVBolus':
+ self.v_ss = self._V_ss()
+ else:
+ self.v_ss = None
+
+ self.v_z = self._V_z()
+
+ @staticmethod
+ def extrapolate_c0(y, x):
+ """
+ Calculate initial concentration when not given, computed using a (log)
+ regression of the first two data points in a profile.
+ Arguments:
+ y {np.ndarray} -- y coordinates of points on curve
+ x {np.ndarray} -- x coordinates of points on curve
+
+ Returns:
+ c0 {double} -- extrapoloated c0
+ """
+ _, intercept, _, _, _ = \
+ stats.linregress(x[:2], np.log(y[:2]), )
+ c0 = np.exp(intercept)
+ return c0
+
+ @staticmethod
+ def log_trapz(y, x):
+ """Calculate area under curve using log trapezoidal method (log mean).
+ Arguments:
+ :param y {np.ndarray} -- y coordinates of points on curve
+ :param x {np.ndarray} -- x coordinates of points on curve
+ Returns:
+ :return area {double} -- area under curve
+ """
+ y1 = y[:-1]
+ x1 = x[:-1]
+ y2 = y[1:]
+ x2 = x[1:]
+
+ area = np.sum((y1 - y2) / (np.log(y1) - np.log(y2)) * (x2 - x1))
+ return area
+
+ @staticmethod
+ def linlog_trapz(y, x, linlog=True):
+ """
+ Calculate area under curve using combination of linear and log
+ trapezoidal method (linear when increasing, log when decreasing) or
+ optionally just linear trapezoidal method
+ :param y {np.ndarray} -- y coordinates of points on curve
+ :param x {np.ndarray} -- x coordinates of points on curve
+ :param linlog {bool} -- use linear-log trapezoidal method
+ Returns:
+ :return area {float} -- area under curve
+ """
+ if linlog: # use lin-log trapezoid
+ ymax_indx = np.argmax(y) # index of maximum concentration
+ # linear trapezium for increasing part
+ area1 = np.trapz(y[:ymax_indx + 1], x[:ymax_indx + 1])
+ # log trapezium for decreasing part
+ area2 = NCA.log_trapz(y[ymax_indx:], x[ymax_indx:])
+ area = area1 + area2
+ else: # use linear trapezoid only
+ area = np.trapz(x, y)
+ return area
+
+ def _auc_0_last(self, linlog=True):
+ """
+ Calculates area under the concentration–time curve (auc) from time 0 to
+ the last time point Tlast using linear-log trapezoidal method
+ Arguments:
+ :param y {np.ndarray} -- y coordinates of points on curve
+ :param x {np.ndarray} -- x coordinates of points on curve
+ Returns:
+ :return auc {float} -- aumc
+ """
+ y = self.concentrations
+ x = self.times
+ auc = self.linlog_trapz(y, x, linlog=linlog)
+ return auc
+
+ def _aumc_0_last(self, linlog=True):
+ """
+ Calculate area under the first moment of the concentration–time curve
+ (aumc) from time 0 to the last time point Tlast using linear log
+ trapezoidal method
+ Arguments:
+ :param y {np.ndarray} -- y coordinates of points on curve
+ :param x {np.ndarray} -- x coordinates of points on curve
+ Returns:
+ :return aumc {float} -- aumc
+ """
+ # conc * time for first moment curve
+ y = self.concentrations * self.times
+ x = self.times
+ aumc = self.linlog_trapz(y, x, linlog=linlog)
+ return aumc
+
+ def _Lambda_z(self):
+ """
+ Calculates terminal rate constant by performing set of linear
+ regressions on log(conc)-time data using the last n (=3,4,...) points
+ from the terminal (decreasing T >= Tmax) section of curve and returning
+ rate constant with maximum adj_r
+ :return lambda_z {float} -- terminal rate constant
+ :return R2 {float} -- coefficient of determination for best
+ linear regression
+ :return m {int} -- number of data points used in best linear regression
+ """
+ y = self.concentrations
+ x = self.times
+ r = 0
+ lambda_z = 0
+ cmax_indx = np.argmax(y) # index of max concentration
+ n_upper = len(y) - cmax_indx # max number of points to consider
+ for n in range(3, n_upper + 1): # perform regressions
+ slope, intercept, r_value, _, _ = \
+ stats.linregress(x[-n:], np.log(y[-n:]))
+ adj_r = 1 - ((1 - r_value ** 2) * (n - 1)) / (n - 2)
+ # Update lambda, r and m if adj_r has increased
+ if adj_r > r:
+ r = adj_r
+ lambda_z = np.abs(slope)
+ m = n
+ return lambda_z, r ** 2, m
+
+ def _auc_infinity(self):
+ """
+ Calculate total area under the concentration–time curve extrapolating
+ to Inf using the terminal rate constant Lambda_z.
+ :return: auc_inf {float} auc-Inf
+ """
+ auc_inf = self.auc_0_last + self.concentrations[-1] / self.lambda_z
+ return auc_inf
+
+ def _auc_infinity_dose(self):
+ """
+ Calculate auc-Infinity divided by administered dose amount
+ :return: {float} -- auc-Inf Dose = auc-Inf/DM
+ """
+ return self.auc_infinity / self.dose_amount
+
+ def _auc_extrap_percent(self):
+ """
+ Calculate fraction of total auc_infinity obtained from extrapolation
+ :return {float} -- extrapolated percentage
+ """
+ return 100 * (self.auc_infinity - self.auc_0_last) / self.auc_infinity
+
+ def _CL(self):
+ """
+ Calculate total drug clearance (DM/auc-Inf)
+ :return {float} -- total drug clearance CL = DM/auc-Inf
+ """
+ return self.dose_amount / self.auc_infinity
+
+ def _find_Cmax(self):
+ """
+ Find maximum observed concentration and corresponding time
+ :return {float} -- max concentration
+ :return {float} -- time of max conc
+ """
+ if self.is_c0extrapolated: # ignore extrapolated c0
+ indx = np.argmax(self.concentrations[1:]) + 1 # index of maximum
+ else:
+ indx = np.argmax(self.concentrations)
+ return self.concentrations[indx], self.times[indx]
+
+ def _C_max_Dose(self):
+ """
+ Calculate CmaxDose
+ :return: {float} -- CmaxDose = Cmax/DM
+ """
+ return self.c_max / self.dose_amount
+
+ def _aumc(self):
+ """
+ Calculate area under the first moment of the concentration–time curve
+ extrapolated to Inf
+ :return: aumc {float} -- aumc
+ """
+ aumc = self.aumc_0_last + \
+ self.concentrations[-1] / (self.lambda_z**2) + self.times[-1] * \
+ self.concentrations[-1] / self.lambda_z
+ return aumc
+
+ def _aumc_extrap_percent(self):
+ """
+ Calculate fraction of total aumc obtained from extrapolation
+ :return {float} -- extrapolated percentage
+ """
+ return 100 * (self.aumc - self.aumc_0_last) / self.aumc
+
+ def _MRT(self):
+ """
+ Calculate mean residence time (MRT) of drug
+ :return: {float} -- MRT = aumc/auc-Inf
+ """
+ return self.aumc / self.auc_infinity
+
+ def _Tlast(self):
+ """
+ :return: {float} -- time of last observed concentration value
+ """
+ return self.times[-1]
+
+ def _T_half(self):
+ """
+ Calculate terminal half life of drug (time to decay to half amount
+ under terminal rate constant)
+ :return: {float} -- terminal half life
+ """
+ return np.log(2) / self.tlast
+
+ def _V_ss(self):
+ """
+ Calculate apparent volume of distribution at equilibrium. (IV Bolus
+ doses only).
+ :return: {float} -- apparent volume of distribution
+ """
+ return (
+ (self.dose_amount * self.aumc) /
+ (self.auc_infinity * self.lambda_z)
+ )
+
+ def _V_z(self):
+ """
+ Calculate volume of distribution during the terminal phase.
+ :return: volume of distribution
+ """
+ return self.dose_amount / (self.auc_infinity * self.lambda_z)
diff --git a/pkpdapp/pkpdapp/wsgi.py b/pkpdapp/pkpdapp/wsgi.py
new file mode 100644
index 00000000..475d8803
--- /dev/null
+++ b/pkpdapp/pkpdapp/wsgi.py
@@ -0,0 +1,22 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+
+"""
+WSGI config for pkpdapp project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pkpdapp.settings')
+
+application = get_wsgi_application()
diff --git a/pkpdapp/schema.yml b/pkpdapp/schema.yml
new file mode 100644
index 00000000..d7b85b2d
--- /dev/null
+++ b/pkpdapp/schema.yml
@@ -0,0 +1,5348 @@
+openapi: 3.0.3
+info:
+ title: PKPDApp API
+ version: 1.0.0
+ description: The API for the PKPDApp
+paths:
+ /api/algorithm/:
+ get:
+ operationId: algorithm_list
+ tags:
+ - algorithm
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ post:
+ operationId: algorithm_create
+ tags:
+ - algorithm
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ /api/algorithm/{id}/:
+ get:
+ operationId: algorithm_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithm
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ put:
+ operationId: algorithm_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithm
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ patch:
+ operationId: algorithm_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithm
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedAlgorithm'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedAlgorithm'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedAlgorithm'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ delete:
+ operationId: algorithm_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithm
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/auce/:
+ post:
+ operationId: auce_create
+ tags:
+ - auce
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/biomarker_type/:
+ get:
+ operationId: biomarker_type_list
+ tags:
+ - biomarker_type
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/BiomarkerType'
+ description: ''
+ post:
+ operationId: biomarker_type_create
+ tags:
+ - biomarker_type
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ description: ''
+ /api/biomarker_type/{id}/:
+ get:
+ operationId: biomarker_type_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this biomarker type.
+ required: true
+ tags:
+ - biomarker_type
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ description: ''
+ put:
+ operationId: biomarker_type_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this biomarker type.
+ required: true
+ tags:
+ - biomarker_type
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ description: ''
+ patch:
+ operationId: biomarker_type_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this biomarker type.
+ required: true
+ tags:
+ - biomarker_type
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedBiomarkerType'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedBiomarkerType'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedBiomarkerType'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ description: ''
+ delete:
+ operationId: biomarker_type_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this biomarker type.
+ required: true
+ tags:
+ - biomarker_type
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/combined_model/:
+ get:
+ operationId: combined_model_list
+ parameters:
+ - in: query
+ name: project_id
+ schema:
+ type: integer
+ description: Filter results by project ID
+ tags:
+ - combined_model
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/CombinedModel'
+ description: ''
+ post:
+ operationId: combined_model_create
+ tags:
+ - combined_model
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ description: ''
+ /api/combined_model/{id}/:
+ get:
+ operationId: combined_model_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this combined model.
+ required: true
+ tags:
+ - combined_model
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ description: ''
+ put:
+ operationId: combined_model_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this combined model.
+ required: true
+ tags:
+ - combined_model
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ description: ''
+ patch:
+ operationId: combined_model_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this combined model.
+ required: true
+ tags:
+ - combined_model
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedCombinedModel'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedCombinedModel'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedCombinedModel'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ description: ''
+ delete:
+ operationId: combined_model_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this combined model.
+ required: true
+ tags:
+ - combined_model
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/combined_model/{id}/set_params_to_defaults/:
+ put:
+ operationId: combined_model_set_params_to_defaults_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this combined model.
+ required: true
+ tags:
+ - combined_model
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ description: ''
+ /api/combined_model/{id}/set_variables_from_inference/:
+ put:
+ operationId: combined_model_set_variables_from_inference_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this combined model.
+ required: true
+ tags:
+ - combined_model
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/CombinedModel'
+ description: ''
+ /api/combined_model/{id}/simulate:
+ post:
+ operationId: combined_model_simulate_create
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ required: true
+ tags:
+ - combined_model
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Simulate'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Simulate'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Simulate'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SimulateResponse'
+ description: ''
+ '400':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponse'
+ description: ''
+ '404':
+ description: No response body
+ /api/compound/:
+ get:
+ operationId: compound_list
+ tags:
+ - compound
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Compound'
+ description: ''
+ post:
+ operationId: compound_create
+ tags:
+ - compound
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ description: ''
+ /api/compound/{id}/:
+ get:
+ operationId: compound_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this compound.
+ required: true
+ tags:
+ - compound
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ description: ''
+ put:
+ operationId: compound_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this compound.
+ required: true
+ tags:
+ - compound
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ description: ''
+ patch:
+ operationId: compound_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this compound.
+ required: true
+ tags:
+ - compound
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedCompound'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedCompound'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedCompound'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ description: ''
+ delete:
+ operationId: compound_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this compound.
+ required: true
+ tags:
+ - compound
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/dataset/:
+ get:
+ operationId: dataset_list
+ tags:
+ - dataset
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ post:
+ operationId: dataset_create
+ tags:
+ - dataset
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ /api/dataset/{id}/:
+ get:
+ operationId: dataset_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dataset.
+ required: true
+ tags:
+ - dataset
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ put:
+ operationId: dataset_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dataset.
+ required: true
+ tags:
+ - dataset
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ patch:
+ operationId: dataset_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dataset.
+ required: true
+ tags:
+ - dataset
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedDataset'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedDataset'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedDataset'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ delete:
+ operationId: dataset_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dataset.
+ required: true
+ tags:
+ - dataset
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/dataset/{id}/csv/:
+ put:
+ operationId: dataset_csv_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dataset.
+ required: true
+ tags:
+ - dataset
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/DatasetCsv'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatasetCsv'
+ description: ''
+ /api/dose/:
+ get:
+ operationId: dose_list
+ tags:
+ - dose
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Dose'
+ description: ''
+ post:
+ operationId: dose_create
+ tags:
+ - dose
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ description: ''
+ /api/dose/{id}/:
+ get:
+ operationId: dose_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dose.
+ required: true
+ tags:
+ - dose
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ description: ''
+ put:
+ operationId: dose_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dose.
+ required: true
+ tags:
+ - dose
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ description: ''
+ patch:
+ operationId: dose_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dose.
+ required: true
+ tags:
+ - dose
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedDose'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedDose'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedDose'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ description: ''
+ delete:
+ operationId: dose_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dose.
+ required: true
+ tags:
+ - dose
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/inference/:
+ get:
+ operationId: inference_list
+ tags:
+ - inference
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Inference'
+ description: ''
+ post:
+ operationId: inference_create
+ tags:
+ - inference
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ description: ''
+ /api/inference/{id}/:
+ get:
+ operationId: inference_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference.
+ required: true
+ tags:
+ - inference
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ description: ''
+ put:
+ operationId: inference_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference.
+ required: true
+ tags:
+ - inference
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ description: ''
+ patch:
+ operationId: inference_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference.
+ required: true
+ tags:
+ - inference
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedInference'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedInference'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedInference'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ description: ''
+ delete:
+ operationId: inference_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference.
+ required: true
+ tags:
+ - inference
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/inference/{id}/stop:
+ post:
+ operationId: inference_stop_create
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ required: true
+ tags:
+ - inference
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/inference/wizard:
+ post:
+ operationId: inference_wizard_create
+ description: |-
+ expecting data in the form:
+ {
+
+ # Inference parameters
+ 'id': 1
+ 'name': "my inference run",
+ 'project': 1,
+ 'algorithm': 2,
+ 'initialization_strategy': 'R',
+ 'initialization_inference': 2,
+ 'number_of_chains': 4,
+ 'max_number_of_iterations': 3000,
+ 'burn_in': 0,
+
+ # Model
+ 'model': {
+ 'form': 'PK',
+ 'id': 5
+ }
+ 'dataset': 3,
+
+ # Model parameters
+ 'parameters': [
+ {
+ 'name': 'myokit.parameter1'
+ 'form': 'N',
+ 'pooled': False,
+ 'parameters': [
+ '2 * biomarker[subject_weight]',
+ 'parameter[parameter1_variance]'
+ ]
+ },
+ {
+ 'name': 'parameter1_variance'
+ 'form': 'N',
+ 'parameters': [0, 1]
+ },
+ {
+ 'name': 'myokit.parameter2'
+ 'form': 'U',
+ 'parameters': [-1, 1]
+ },
+ {
+ 'name': 'myokit.parameter3'
+ 'form': 'F',
+ 'parameters': [123.5]
+ },
+ ]
+
+ # output
+ 'observations': [
+ {
+ 'model': 'myokit.plasma_concentration',
+ 'biomarker': 'concentration,
+ 'noise_form': 'N',
+ 'noise_param_form': 'N',
+ 'parameters': [0, 1]
+ },
+ {
+ 'model': 'myokit.bacteria_count',
+ 'biomarker': 'bacteria,
+ 'noise_form': 'LN',
+ 'noise_param_form': 'F'
+ 'parameters': [123.3]
+ },
+ ]
+ }
+
+ Uses model as the base model. If it is a PK or PKPD model, creates a model
+ for each protocol used in the dataset, replacing the protocol of the model
+ with each new one.
+
+ This set of models has a set of parameters. If pooled is True or not given,
+ then parameters of the same qname are assumed to be identical, if pooled is
+ False, then the value of this parameter is different across each subject.
+ All Variable fields from the original model are copied over to the new
+ models. Priors and fixed values for each parameter in this set are provided
+ in 'parameters'. Distribution parameters for each prior can be provided
+ using a python expression, or a number. If a python expression is used, the
+ keywords Parameter[] are used to refer to other parameters in
+ the list. Additional parameters can be added to the list (parameters not in
+ the model) to contruct hierarchical inference. You can refer to biomarkers
+ in the expression using the keyword Biomarker[].
+
+ The 'observations' field maps model output variables with biomarkers in the
+ dataset
+ tags:
+ - inference
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/inference_chain/:
+ get:
+ operationId: inference_chain_list
+ tags:
+ - inference_chain
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/InferenceChain'
+ description: ''
+ post:
+ operationId: inference_chain_create
+ tags:
+ - inference_chain
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ description: ''
+ /api/inference_chain/{id}/:
+ get:
+ operationId: inference_chain_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference chain.
+ required: true
+ tags:
+ - inference_chain
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ description: ''
+ put:
+ operationId: inference_chain_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference chain.
+ required: true
+ tags:
+ - inference_chain
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ description: ''
+ patch:
+ operationId: inference_chain_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference chain.
+ required: true
+ tags:
+ - inference_chain
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedInferenceChain'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedInferenceChain'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedInferenceChain'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ description: ''
+ delete:
+ operationId: inference_chain_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference chain.
+ required: true
+ tags:
+ - inference_chain
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/nca/:
+ post:
+ operationId: nca_create
+ tags:
+ - nca
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/pharmacodynamic/:
+ get:
+ operationId: pharmacodynamic_list
+ tags:
+ - pharmacodynamic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ post:
+ operationId: pharmacodynamic_create
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ /api/pharmacodynamic/{id}/:
+ get:
+ operationId: pharmacodynamic_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ put:
+ operationId: pharmacodynamic_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ patch:
+ operationId: pharmacodynamic_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacodynamic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacodynamic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacodynamic'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ delete:
+ operationId: pharmacodynamic_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/pharmacodynamic/{id}/mmt/:
+ put:
+ operationId: pharmacodynamic_mmt_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ /api/pharmacodynamic/{id}/sbml/:
+ put:
+ operationId: pharmacodynamic_sbml_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PharmacodynamicSbml'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PharmacodynamicSbml'
+ description: ''
+ /api/pharmacodynamic/{id}/set_variables_from_inference/:
+ put:
+ operationId: pharmacodynamic_set_variables_from_inference_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ /api/pharmacodynamic/{id}/simulate:
+ post:
+ operationId: pharmacodynamic_simulate_create
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ required: true
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Simulate'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Simulate'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Simulate'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/SimulateResponse'
+ description: ''
+ '400':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ErrorResponse'
+ description: ''
+ '404':
+ description: No response body
+ /api/pharmacokinetic/:
+ get:
+ operationId: pharmacokinetic_list
+ tags:
+ - pharmacokinetic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ description: ''
+ post:
+ operationId: pharmacokinetic_create
+ tags:
+ - pharmacokinetic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ description: ''
+ /api/pharmacokinetic/{id}/:
+ get:
+ operationId: pharmacokinetic_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacokinetic model.
+ required: true
+ tags:
+ - pharmacokinetic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ description: ''
+ put:
+ operationId: pharmacokinetic_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacokinetic model.
+ required: true
+ tags:
+ - pharmacokinetic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ description: ''
+ patch:
+ operationId: pharmacokinetic_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacokinetic model.
+ required: true
+ tags:
+ - pharmacokinetic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacokinetic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacokinetic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacokinetic'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ description: ''
+ delete:
+ operationId: pharmacokinetic_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacokinetic model.
+ required: true
+ tags:
+ - pharmacokinetic
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/project/:
+ get:
+ operationId: project_list
+ description: Enable partial updates
+ tags:
+ - project
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Project'
+ description: ''
+ post:
+ operationId: project_create
+ description: Enable partial updates
+ tags:
+ - project
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Project'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Project'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ description: ''
+ /api/project/{id}/:
+ get:
+ operationId: project_retrieve
+ description: Enable partial updates
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project.
+ required: true
+ tags:
+ - project
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ description: ''
+ put:
+ operationId: project_update
+ description: Enable partial updates
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project.
+ required: true
+ tags:
+ - project
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Project'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Project'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ description: ''
+ patch:
+ operationId: project_partial_update
+ description: Enable partial updates
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project.
+ required: true
+ tags:
+ - project
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedProject'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedProject'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedProject'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ description: ''
+ delete:
+ operationId: project_destroy
+ description: Enable partial updates
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project.
+ required: true
+ tags:
+ - project
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/project/{id}/monolix/:
+ put:
+ operationId: project_monolix_update
+ description: Enable partial updates
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project.
+ required: true
+ tags:
+ - project
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Monolix'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Monolix'
+ description: ''
+ /api/project_access/:
+ get:
+ operationId: project_access_list
+ tags:
+ - project_access
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectAccess'
+ description: ''
+ post:
+ operationId: project_access_create
+ tags:
+ - project_access
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ description: ''
+ /api/project_access/{id}/:
+ get:
+ operationId: project_access_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project access.
+ required: true
+ tags:
+ - project_access
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ description: ''
+ put:
+ operationId: project_access_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project access.
+ required: true
+ tags:
+ - project_access
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ description: ''
+ patch:
+ operationId: project_access_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project access.
+ required: true
+ tags:
+ - project_access
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedProjectAccess'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedProjectAccess'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedProjectAccess'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ description: ''
+ delete:
+ operationId: project_access_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project access.
+ required: true
+ tags:
+ - project_access
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/protocol/:
+ get:
+ operationId: protocol_list
+ parameters:
+ - in: query
+ name: project_id
+ schema:
+ type: integer
+ description: Filter results by project ID
+ tags:
+ - protocol
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Protocol'
+ description: ''
+ post:
+ operationId: protocol_create
+ tags:
+ - protocol
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ description: ''
+ /api/protocol/{id}/:
+ get:
+ operationId: protocol_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this protocol.
+ required: true
+ tags:
+ - protocol
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ description: ''
+ put:
+ operationId: protocol_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this protocol.
+ required: true
+ tags:
+ - protocol
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ description: ''
+ patch:
+ operationId: protocol_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this protocol.
+ required: true
+ tags:
+ - protocol
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedProtocol'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedProtocol'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedProtocol'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ description: ''
+ delete:
+ operationId: protocol_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this protocol.
+ required: true
+ tags:
+ - protocol
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/session/:
+ get:
+ operationId: session_retrieve
+ tags:
+ - session
+ security:
+ - cookieAuth: []
+ - basicAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/simulation/:
+ get:
+ operationId: simulation_list
+ parameters:
+ - in: query
+ name: project_id
+ schema:
+ type: integer
+ description: Filter results by project ID
+ tags:
+ - simulation
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Simulation'
+ description: ''
+ post:
+ operationId: simulation_create
+ tags:
+ - simulation
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Simulation'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Simulation'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Simulation'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Simulation'
+ description: ''
+ /api/simulation/{id}/:
+ get:
+ operationId: simulation_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this simulation.
+ required: true
+ tags:
+ - simulation
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Simulation'
+ description: ''
+ put:
+ operationId: simulation_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this simulation.
+ required: true
+ tags:
+ - simulation
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Simulation'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Simulation'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Simulation'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Simulation'
+ description: ''
+ patch:
+ operationId: simulation_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this simulation.
+ required: true
+ tags:
+ - simulation
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedSimulation'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedSimulation'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedSimulation'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Simulation'
+ description: ''
+ delete:
+ operationId: simulation_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this simulation.
+ required: true
+ tags:
+ - simulation
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/subject/:
+ get:
+ operationId: subject_list
+ tags:
+ - subject
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Subject'
+ description: ''
+ post:
+ operationId: subject_create
+ tags:
+ - subject
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ description: ''
+ /api/subject/{id}/:
+ get:
+ operationId: subject_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this subject.
+ required: true
+ tags:
+ - subject
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ description: ''
+ put:
+ operationId: subject_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this subject.
+ required: true
+ tags:
+ - subject
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ description: ''
+ patch:
+ operationId: subject_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this subject.
+ required: true
+ tags:
+ - subject
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedSubject'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedSubject'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedSubject'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ description: ''
+ delete:
+ operationId: subject_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this subject.
+ required: true
+ tags:
+ - subject
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/unit/:
+ get:
+ operationId: unit_list
+ parameters:
+ - in: query
+ name: compound_id
+ schema:
+ type: integer
+ description: Enable conversions based on compound information
+ tags:
+ - unit
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Unit'
+ description: ''
+ post:
+ operationId: unit_create
+ tags:
+ - unit
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ description: ''
+ /api/unit/{id}/:
+ get:
+ operationId: unit_retrieve
+ parameters:
+ - in: query
+ name: compound_id
+ schema:
+ type: integer
+ description: Enable conversions based on compound information
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this unit.
+ required: true
+ tags:
+ - unit
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ description: ''
+ put:
+ operationId: unit_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this unit.
+ required: true
+ tags:
+ - unit
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ description: ''
+ patch:
+ operationId: unit_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this unit.
+ required: true
+ tags:
+ - unit
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedUnit'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedUnit'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedUnit'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ description: ''
+ delete:
+ operationId: unit_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this unit.
+ required: true
+ tags:
+ - unit
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/user/:
+ get:
+ operationId: user_list
+ tags:
+ - user
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ description: ''
+ post:
+ operationId: user_create
+ tags:
+ - user
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/User'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/User'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ description: ''
+ /api/user/{id}/:
+ get:
+ operationId: user_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this user.
+ required: true
+ tags:
+ - user
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ description: ''
+ put:
+ operationId: user_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this user.
+ required: true
+ tags:
+ - user
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/User'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/User'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ description: ''
+ patch:
+ operationId: user_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this user.
+ required: true
+ tags:
+ - user
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedUser'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedUser'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedUser'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ description: ''
+ delete:
+ operationId: user_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this user.
+ required: true
+ tags:
+ - user
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/variable/:
+ get:
+ operationId: variable_list
+ parameters:
+ - in: query
+ name: dosed_pk_model_id
+ schema:
+ type: integer
+ description: Filter results by dosed_pk_model ID
+ - in: query
+ name: pd_model_id
+ schema:
+ type: integer
+ description: Filter results by pd_model ID
+ - in: query
+ name: project_id
+ schema:
+ type: integer
+ description: Filter results by project ID
+ tags:
+ - variable
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Variable'
+ description: ''
+ post:
+ operationId: variable_create
+ tags:
+ - variable
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ description: ''
+ /api/variable/{id}/:
+ get:
+ operationId: variable_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this variable.
+ required: true
+ tags:
+ - variable
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ description: ''
+ put:
+ operationId: variable_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this variable.
+ required: true
+ tags:
+ - variable
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ description: ''
+ patch:
+ operationId: variable_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this variable.
+ required: true
+ tags:
+ - variable
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedVariable'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedVariable'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedVariable'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ description: ''
+ delete:
+ operationId: variable_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this variable.
+ required: true
+ tags:
+ - variable
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/whoami/:
+ get:
+ operationId: whoami_retrieve
+ tags:
+ - whoami
+ security:
+ - cookieAuth: []
+ - basicAuth: []
+ responses:
+ '200':
+ description: No response body
+components:
+ schemas:
+ Algorithm:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ name:
+ type: string
+ description: name of the algorithm
+ maxLength: 100
+ category:
+ $ref: '#/components/schemas/CategoryEnum'
+ required:
+ - category
+ - id
+ - name
+ BiomarkerType:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ data:
+ type: object
+ additionalProperties:
+ type: array
+ items: {}
+ nullable: true
+ readOnly: true
+ is_continuous:
+ type: boolean
+ readOnly: true
+ is_categorical:
+ type: boolean
+ readOnly: true
+ name:
+ type: string
+ description: name of the biomarker type
+ maxLength: 100
+ description:
+ type: string
+ nullable: true
+ description: short description of the biomarker type
+ display:
+ type: boolean
+ description: True if this biomarker type will be displayed in the frontend,
+ False otherwise
+ color:
+ type: integer
+ description: Color index associated with this biomarker type. For plotting
+ purposes in the frontend
+ axis:
+ type: boolean
+ description: True/False if biomarker type displayed on LHS/RHS axis
+ stored_unit:
+ type: integer
+ description: unit for the value stored in :model:`pkpdapp.Biomarker`
+ dataset:
+ type: integer
+ description: dataset containing this biomarker measurement
+ display_unit:
+ type: integer
+ description: unit to use when sending or displaying biomarker values
+ stored_time_unit:
+ type: integer
+ description: unit for the time values stored in :model:`pkpdapp.Biomarker`
+ display_time_unit:
+ type: integer
+ description: unit to use when sending or displaying time values
+ required:
+ - data
+ - dataset
+ - display_time_unit
+ - display_unit
+ - id
+ - is_categorical
+ - is_continuous
+ - name
+ - stored_time_unit
+ - stored_unit
+ CategoryEnum:
+ enum:
+ - SA
+ - OP
+ - OT
+ type: string
+ description: |-
+ * `SA` - Sampling
+ * `OP` - Optimisation
+ * `OT` - Optimisation
+ CombinedModel:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ mappings:
+ type: array
+ items:
+ $ref: '#/components/schemas/PkpdMapping'
+ derived_variables:
+ type: array
+ items:
+ $ref: '#/components/schemas/DerivedVariable'
+ components:
+ type: string
+ readOnly: true
+ variables:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ mmt:
+ type: string
+ readOnly: true
+ time_unit:
+ type: integer
+ readOnly: true
+ is_library_model:
+ type: boolean
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ species:
+ allOf:
+ - $ref: '#/components/schemas/CombinedModelSpeciesEnum'
+ description: |-
+ species
+
+ * `H` - human
+ * `R` - rat
+ * `N` - non-human primate
+ * `M` - mouse
+ has_saturation:
+ type: boolean
+ description: whether the pk model has saturation
+ has_effect:
+ type: boolean
+ description: whether the pk model has effect compartment
+ has_lag:
+ type: boolean
+ description: whether the pk model has lag
+ has_bioavailability:
+ type: boolean
+ description: whether the pk model has bioavailability
+ has_hill_coefficient:
+ type: boolean
+ description: whether the pd model has hill coefficient
+ time_max:
+ type: number
+ format: double
+ description: suggested time to simulate after the last dose (in the time
+ units specified by the mmt model)
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ pk_model:
+ type: integer
+ nullable: true
+ description: model
+ pd_model:
+ type: integer
+ nullable: true
+ description: PD part of model
+ pd_model2:
+ type: integer
+ nullable: true
+ description: second PD part of model
+ required:
+ - components
+ - derived_variables
+ - id
+ - is_library_model
+ - mappings
+ - mmt
+ - name
+ - time_unit
+ - variables
+ CombinedModelSpeciesEnum:
+ enum:
+ - H
+ - R
+ - N
+ - M
+ type: string
+ description: |-
+ * `H` - human
+ * `R` - rat
+ * `N` - non-human primate
+ * `M` - mouse
+ Compound:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ efficacy_experiments:
+ type: array
+ items:
+ $ref: '#/components/schemas/Efficacy'
+ name:
+ type: string
+ description: name of the compound
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the compound
+ molecular_mass:
+ type: number
+ format: double
+ description: molecular mass for compound for conversion from mol to grams
+ compound_type:
+ $ref: '#/components/schemas/CompoundTypeEnum'
+ fraction_unbound_plasma:
+ type: number
+ format: double
+ nullable: true
+ description: fraction unbound plasma (unitless)
+ blood_to_plasma_ratio:
+ type: number
+ format: double
+ nullable: true
+ description: blood to plasma ratio (unitless)
+ intrinsic_clearance:
+ type: number
+ format: double
+ nullable: true
+ description: intrinsic clearance
+ intrinsic_clearance_assay:
+ $ref: '#/components/schemas/IntrinsicClearanceAssayEnum'
+ fraction_unbound_including_cells:
+ type: number
+ format: double
+ nullable: true
+ description: fraction unbound in plasma and red blood cells (unitless)
+ target_molecular_mass:
+ type: number
+ format: double
+ description: molecular mass for target for conversion from mol to grams
+ target_concentration:
+ type: number
+ format: double
+ nullable: true
+ description: target concentration
+ dissociation_constant:
+ type: number
+ format: double
+ nullable: true
+ description: dissociation constant
+ is_soluble:
+ type: boolean
+ description: is the compound target soluble
+ use_efficacy:
+ type: integer
+ nullable: true
+ molecular_mass_unit:
+ type: integer
+ description: unit for molecular mass (e.g. g/mol)
+ intrinsic_clearance_unit:
+ type: integer
+ description: unit for intrinsic clearance
+ target_molecular_mass_unit:
+ type: integer
+ description: unit for target molecular mass (e.g. g/mol)
+ target_concentration_unit:
+ type: integer
+ description: unit for target concentration
+ dissociation_unit:
+ type: integer
+ description: unit for dissociation constant
+ required:
+ - efficacy_experiments
+ - id
+ - name
+ CompoundTypeEnum:
+ enum:
+ - SM
+ - LM
+ type: string
+ description: |-
+ * `SM` - Small Molecule
+ * `LM` - Large Molecule
+ Dataset:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ biomarker_types:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ subjects:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ protocols:
+ type: array
+ items:
+ $ref: '#/components/schemas/Protocol'
+ readOnly: true
+ name:
+ type: string
+ description: name of the dataset
+ maxLength: 100
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: date/time the experiment was conducted. All time measurements
+ are relative to this date/time, which is in YYYY-MM-DD HH:MM:SS format.
+ For example, 2020-07-18 14:30:59
+ description:
+ type: string
+ description: short description of the dataset
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ required:
+ - biomarker_types
+ - id
+ - name
+ - protocols
+ - subjects
+ DatasetCsv:
+ type: object
+ properties:
+ csv:
+ type: string
+ format: uri
+ required:
+ - csv
+ DerivedVariable:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ type:
+ allOf:
+ - $ref: '#/components/schemas/TypeEnum'
+ description: |-
+ type of derived variable
+
+ * `RO` - receptor occupancy
+ * `FUP` - faction unbound plasma
+ * `BPR` - blood plasma ratio
+ * `TLG` - dosing lag time
+ pkpd_model:
+ type: integer
+ description: PKPD model that this derived variable is for
+ pk_variable:
+ type: integer
+ description: base variable in PK part of model
+ required:
+ - id
+ - pk_variable
+ - pkpd_model
+ - type
+ Dose:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ start_time:
+ type: number
+ format: double
+ description: starting time point of dose, see protocol for units
+ amount:
+ type: number
+ format: double
+ description: amount of compound administered over the duration, see protocol
+ for units. Rate of administration is assumed constant
+ duration:
+ type: number
+ format: double
+ description: Duration of dose administration, see protocol for units. Duration
+ must be greater than 0.
+ repeats:
+ type: integer
+ description: 'Number of times to repeat the dose. '
+ repeat_interval:
+ type: number
+ format: double
+ description: 'Interval between repeated doses. See protocol for units. '
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ required:
+ - amount
+ - id
+ - start_time
+ DoseTypeEnum:
+ enum:
+ - D
+ - I
+ type: string
+ description: |-
+ * `D` - IV
+ * `I` - Extravascular
+ Efficacy:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ name:
+ type: string
+ description: name of the experiment
+ maxLength: 100
+ c50:
+ type: number
+ format: double
+ description: half maximal effective concentration
+ hill_coefficient:
+ type: number
+ format: double
+ description: Hill coefficient measure of binding
+ c50_unit:
+ type: integer
+ description: unit for c50
+ compound:
+ type: integer
+ description: compound for efficacy experiment
+ required:
+ - c50
+ - c50_unit
+ - compound
+ - id
+ ErrorResponse:
+ type: object
+ properties:
+ error:
+ type: string
+ required:
+ - error
+ FormEnum:
+ enum:
+ - N
+ - U
+ - LN
+ - F
+ - S
+ - E
+ - M
+ type: string
+ description: |-
+ * `N` - Normal
+ * `U` - Uniform
+ * `LN` - Log-Normal
+ * `F` - Fixed
+ * `S` - Sum
+ * `E` - Equation
+ * `M` - Model
+ Inference:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ log_likelihoods:
+ type: array
+ items:
+ $ref: '#/components/schemas/LogLikelihood'
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the dataset
+ maxLength: 100
+ description:
+ type: string
+ description: short description of what this inference does
+ initialization_strategy:
+ $ref: '#/components/schemas/InitializationStrategyEnum'
+ number_of_chains:
+ type: integer
+ description: number of chains
+ max_number_of_iterations:
+ type: integer
+ description: maximum number of iterations
+ burn_in:
+ type: integer
+ description: final iteration of burn-in
+ number_of_iterations:
+ type: integer
+ description: number of iterations calculated
+ time_elapsed:
+ type: integer
+ description: Elapsed run time for inference in seconds
+ number_of_function_evals:
+ type: integer
+ description: number of function evaluations
+ task_id:
+ type: string
+ nullable: true
+ description: If executing, this is the celery task id
+ maxLength: 40
+ metadata:
+ type: object
+ additionalProperties: {}
+ description: metadata for inference
+ project:
+ type: integer
+ description: Project that "owns" this inference object
+ algorithm:
+ type: integer
+ description: algorithm used to perform the inference
+ initialization_inference:
+ type: integer
+ nullable: true
+ required:
+ - id
+ - log_likelihoods
+ - name
+ - project
+ InferenceChain:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ data:
+ type: string
+ readOnly: true
+ outputs:
+ type: string
+ readOnly: true
+ inference:
+ type: integer
+ description: inference for this chain
+ required:
+ - data
+ - id
+ - inference
+ - outputs
+ InitializationStrategyEnum:
+ enum:
+ - D
+ - R
+ - F
+ type: string
+ description: |-
+ * `D` - Default Value of model
+ * `R` - Random from prior
+ * `F` - From other inference
+ IntrinsicClearanceAssayEnum:
+ enum:
+ - MS
+ - HC
+ type: string
+ description: |-
+ * `MS` - Microsomes
+ * `HC` - Hepatocytes
+ LogLikelihood:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ parameters:
+ type: array
+ items:
+ $ref: '#/components/schemas/LogLikelihoodParameter'
+ model:
+ type: array
+ items:
+ type: string
+ minLength: 2
+ maxLength: 2
+ nullable: true
+ readOnly: true
+ dataset:
+ type: integer
+ nullable: true
+ readOnly: true
+ time_variable:
+ type: integer
+ nullable: true
+ readOnly: true
+ is_a_prior:
+ type: boolean
+ readOnly: true
+ name:
+ type: string
+ description: name of log_likelihood.
+ maxLength: 100
+ description:
+ type: string
+ nullable: true
+ description: 'description of log_likelihood. For equations will be the code
+ of that equation using Python syntax: arg1 * arg2^arg3'
+ value:
+ type: number
+ format: double
+ nullable: true
+ description: set if a fixed value is required
+ time_independent_data:
+ type: boolean
+ description: 'True if biomarker_type refers to time-independent data. If
+ there are multiple timepoints in biomarker_type then only the first is
+ taken '
+ observed:
+ type: boolean
+ description: 'True if this log_likelihood is observed '
+ form:
+ $ref: '#/components/schemas/FormEnum'
+ inference:
+ type: integer
+ readOnly: true
+ description: 'Log_likelihood belongs to this inference object. '
+ variable:
+ type: integer
+ nullable: true
+ description: 'If form=MODEL, a variable (any) in the deterministic model. '
+ biomarker_type:
+ type: integer
+ nullable: true
+ description: data associated with this log_likelihood. This is used for
+ measurement data (observed=True) or for covariates (observed=False). The
+ random variable associated with this log_likelihood has the same shape
+ as this data. For covariates the subject ids in the data correspond to
+ the values of the random variable at that location.
+ protocol_filter:
+ type: integer
+ nullable: true
+ description: filter subject data on this protocol(null implies all subjects)
+ children:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ required:
+ - children
+ - dataset
+ - id
+ - inference
+ - is_a_prior
+ - model
+ - name
+ - parameters
+ - time_variable
+ LogLikelihoodParameter:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ name:
+ type: string
+ description: name of log_likelihood parameter.
+ maxLength: 100
+ parent_index:
+ type: integer
+ nullable: true
+ description: parameter index for distribution and equation parameters. blank
+ for models (variable is used instead)
+ child_index:
+ type: integer
+ description: 'output index for all log_likelihoods. '
+ length:
+ type: integer
+ nullable: true
+ description: length of array representing parameter. null for scalar
+ parent:
+ type: integer
+ readOnly: true
+ child:
+ type: integer
+ variable:
+ type: integer
+ nullable: true
+ description: input model variable for this parameter.
+ required:
+ - child
+ - id
+ - name
+ - parent
+ Monolix:
+ type: object
+ properties:
+ data_csv:
+ type: string
+ format: uri
+ writeOnly: true
+ model_txt:
+ type: string
+ format: uri
+ writeOnly: true
+ project_mlxtran:
+ type: string
+ format: uri
+ writeOnly: true
+ data:
+ type: string
+ readOnly: true
+ pd_model:
+ type: string
+ readOnly: true
+ pk_model:
+ type: string
+ readOnly: true
+ required:
+ - data
+ - data_csv
+ - model_txt
+ - pd_model
+ - pk_model
+ - project_mlxtran
+ PatchedAlgorithm:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ name:
+ type: string
+ description: name of the algorithm
+ maxLength: 100
+ category:
+ $ref: '#/components/schemas/CategoryEnum'
+ PatchedBiomarkerType:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ data:
+ type: object
+ additionalProperties:
+ type: array
+ items: {}
+ nullable: true
+ readOnly: true
+ is_continuous:
+ type: boolean
+ readOnly: true
+ is_categorical:
+ type: boolean
+ readOnly: true
+ name:
+ type: string
+ description: name of the biomarker type
+ maxLength: 100
+ description:
+ type: string
+ nullable: true
+ description: short description of the biomarker type
+ display:
+ type: boolean
+ description: True if this biomarker type will be displayed in the frontend,
+ False otherwise
+ color:
+ type: integer
+ description: Color index associated with this biomarker type. For plotting
+ purposes in the frontend
+ axis:
+ type: boolean
+ description: True/False if biomarker type displayed on LHS/RHS axis
+ stored_unit:
+ type: integer
+ description: unit for the value stored in :model:`pkpdapp.Biomarker`
+ dataset:
+ type: integer
+ description: dataset containing this biomarker measurement
+ display_unit:
+ type: integer
+ description: unit to use when sending or displaying biomarker values
+ stored_time_unit:
+ type: integer
+ description: unit for the time values stored in :model:`pkpdapp.Biomarker`
+ display_time_unit:
+ type: integer
+ description: unit to use when sending or displaying time values
+ PatchedCombinedModel:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ mappings:
+ type: array
+ items:
+ $ref: '#/components/schemas/PkpdMapping'
+ derived_variables:
+ type: array
+ items:
+ $ref: '#/components/schemas/DerivedVariable'
+ components:
+ type: string
+ readOnly: true
+ variables:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ mmt:
+ type: string
+ readOnly: true
+ time_unit:
+ type: integer
+ readOnly: true
+ is_library_model:
+ type: boolean
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ species:
+ allOf:
+ - $ref: '#/components/schemas/CombinedModelSpeciesEnum'
+ description: |-
+ species
+
+ * `H` - human
+ * `R` - rat
+ * `N` - non-human primate
+ * `M` - mouse
+ has_saturation:
+ type: boolean
+ description: whether the pk model has saturation
+ has_effect:
+ type: boolean
+ description: whether the pk model has effect compartment
+ has_lag:
+ type: boolean
+ description: whether the pk model has lag
+ has_bioavailability:
+ type: boolean
+ description: whether the pk model has bioavailability
+ has_hill_coefficient:
+ type: boolean
+ description: whether the pd model has hill coefficient
+ time_max:
+ type: number
+ format: double
+ description: suggested time to simulate after the last dose (in the time
+ units specified by the mmt model)
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ pk_model:
+ type: integer
+ nullable: true
+ description: model
+ pd_model:
+ type: integer
+ nullable: true
+ description: PD part of model
+ pd_model2:
+ type: integer
+ nullable: true
+ description: second PD part of model
+ PatchedCompound:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ efficacy_experiments:
+ type: array
+ items:
+ $ref: '#/components/schemas/Efficacy'
+ name:
+ type: string
+ description: name of the compound
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the compound
+ molecular_mass:
+ type: number
+ format: double
+ description: molecular mass for compound for conversion from mol to grams
+ compound_type:
+ $ref: '#/components/schemas/CompoundTypeEnum'
+ fraction_unbound_plasma:
+ type: number
+ format: double
+ nullable: true
+ description: fraction unbound plasma (unitless)
+ blood_to_plasma_ratio:
+ type: number
+ format: double
+ nullable: true
+ description: blood to plasma ratio (unitless)
+ intrinsic_clearance:
+ type: number
+ format: double
+ nullable: true
+ description: intrinsic clearance
+ intrinsic_clearance_assay:
+ $ref: '#/components/schemas/IntrinsicClearanceAssayEnum'
+ fraction_unbound_including_cells:
+ type: number
+ format: double
+ nullable: true
+ description: fraction unbound in plasma and red blood cells (unitless)
+ target_molecular_mass:
+ type: number
+ format: double
+ description: molecular mass for target for conversion from mol to grams
+ target_concentration:
+ type: number
+ format: double
+ nullable: true
+ description: target concentration
+ dissociation_constant:
+ type: number
+ format: double
+ nullable: true
+ description: dissociation constant
+ is_soluble:
+ type: boolean
+ description: is the compound target soluble
+ use_efficacy:
+ type: integer
+ nullable: true
+ molecular_mass_unit:
+ type: integer
+ description: unit for molecular mass (e.g. g/mol)
+ intrinsic_clearance_unit:
+ type: integer
+ description: unit for intrinsic clearance
+ target_molecular_mass_unit:
+ type: integer
+ description: unit for target molecular mass (e.g. g/mol)
+ target_concentration_unit:
+ type: integer
+ description: unit for target concentration
+ dissociation_unit:
+ type: integer
+ description: unit for dissociation constant
+ PatchedDataset:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ biomarker_types:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ subjects:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ protocols:
+ type: array
+ items:
+ $ref: '#/components/schemas/Protocol'
+ readOnly: true
+ name:
+ type: string
+ description: name of the dataset
+ maxLength: 100
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: date/time the experiment was conducted. All time measurements
+ are relative to this date/time, which is in YYYY-MM-DD HH:MM:SS format.
+ For example, 2020-07-18 14:30:59
+ description:
+ type: string
+ description: short description of the dataset
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ PatchedDose:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ start_time:
+ type: number
+ format: double
+ description: starting time point of dose, see protocol for units
+ amount:
+ type: number
+ format: double
+ description: amount of compound administered over the duration, see protocol
+ for units. Rate of administration is assumed constant
+ duration:
+ type: number
+ format: double
+ description: Duration of dose administration, see protocol for units. Duration
+ must be greater than 0.
+ repeats:
+ type: integer
+ description: 'Number of times to repeat the dose. '
+ repeat_interval:
+ type: number
+ format: double
+ description: 'Interval between repeated doses. See protocol for units. '
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ PatchedInference:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ log_likelihoods:
+ type: array
+ items:
+ $ref: '#/components/schemas/LogLikelihood'
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the dataset
+ maxLength: 100
+ description:
+ type: string
+ description: short description of what this inference does
+ initialization_strategy:
+ $ref: '#/components/schemas/InitializationStrategyEnum'
+ number_of_chains:
+ type: integer
+ description: number of chains
+ max_number_of_iterations:
+ type: integer
+ description: maximum number of iterations
+ burn_in:
+ type: integer
+ description: final iteration of burn-in
+ number_of_iterations:
+ type: integer
+ description: number of iterations calculated
+ time_elapsed:
+ type: integer
+ description: Elapsed run time for inference in seconds
+ number_of_function_evals:
+ type: integer
+ description: number of function evaluations
+ task_id:
+ type: string
+ nullable: true
+ description: If executing, this is the celery task id
+ maxLength: 40
+ metadata:
+ type: object
+ additionalProperties: {}
+ description: metadata for inference
+ project:
+ type: integer
+ description: Project that "owns" this inference object
+ algorithm:
+ type: integer
+ description: algorithm used to perform the inference
+ initialization_inference:
+ type: integer
+ nullable: true
+ PatchedInferenceChain:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ data:
+ type: string
+ readOnly: true
+ outputs:
+ type: string
+ readOnly: true
+ inference:
+ type: integer
+ description: inference for this chain
+ PatchedPharmacodynamic:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ components:
+ type: string
+ readOnly: true
+ variables:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ mmt:
+ type: string
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the model
+ time_max:
+ type: number
+ format: double
+ description: suggested maximum time to simulate for this model (in the time
+ units specified by the mmt model)
+ is_library_model:
+ type: boolean
+ description: whether this model is a library model (i.e. it is not an uploaded
+ user model)
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ PatchedPharmacokinetic:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the model
+ mmt:
+ type: string
+ description: the model represented using mmt (see https://myokit.readthedocs)
+ time_max:
+ type: number
+ format: double
+ description: suggested maximum time to simulate for this model (in the time
+ units specified by the mmt model)
+ is_library_model:
+ type: boolean
+ description: whether this model is a library model (i.e. it is not an uploaded
+ user model)
+ PatchedProject:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ user_access:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectAccess'
+ protocols:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ name:
+ type: string
+ description: name of the project
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the project
+ created:
+ type: string
+ format: date-time
+ readOnly: true
+ species:
+ allOf:
+ - $ref: '#/components/schemas/ProjectSpeciesEnum'
+ description: |-
+ subject species
+
+ * `M` - Mouse
+ * `R` - Rat
+ * `H` - Human
+ * `K` - Monkey
+ * `O` - Other
+ compound:
+ type: integer
+ users:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ description: users with access to this project
+ PatchedProjectAccess:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: True if user has read access only
+ user:
+ type: integer
+ project:
+ type: integer
+ readOnly: true
+ PatchedProtocol:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ doses:
+ type: array
+ items:
+ $ref: '#/components/schemas/Dose'
+ dataset:
+ type: string
+ readOnly: true
+ variables:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ subjects:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the protocol
+ maxLength: 100
+ dose_type:
+ $ref: '#/components/schemas/DoseTypeEnum'
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this protocol.
+ compound:
+ type: integer
+ nullable: true
+ description: drug compound
+ time_unit:
+ type: integer
+ nullable: true
+ description: unit for the start_time and duration values stored in each
+ dose
+ amount_unit:
+ type: integer
+ nullable: true
+ description: unit for the amount value stored in each dose
+ PatchedSimulation:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ sliders:
+ type: array
+ items:
+ $ref: '#/components/schemas/SimulationSlider'
+ plots:
+ type: array
+ items:
+ $ref: '#/components/schemas/SimulationPlot'
+ name:
+ type: string
+ description: name of the simulation
+ maxLength: 100
+ nrows:
+ type: integer
+ description: number of subplot rows
+ ncols:
+ type: integer
+ description: number of subplot columns
+ time_max:
+ type: number
+ format: double
+ minimum: 0
+ description: maximum time for the simulation
+ abs_tolerance:
+ type: number
+ format: double
+ minimum: 0
+ description: absolute tolerance for the simulation
+ rel_tolerance:
+ type: number
+ format: double
+ minimum: 0
+ description: relative tolerance for the simulation
+ project:
+ type: integer
+ time_max_unit:
+ type: integer
+ description: unit for maximum time
+ PatchedSubject:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ id_in_dataset:
+ type: integer
+ description: unique id in the dataset
+ shape:
+ type: integer
+ description: Shape index associated with this subject. For plotting purposes
+ in the frontend
+ display:
+ type: boolean
+ description: True if this subject will be displayed in the frontend, False
+ otherwise
+ metadata:
+ type: string
+ description: subject metadata
+ dataset:
+ type: integer
+ description: dataset containing this subject
+ protocol:
+ type: integer
+ nullable: true
+ description: dosing protocol for this subject.
+ PatchedUnit:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ compatible_units:
+ type: array
+ items:
+ type: object
+ additionalProperties:
+ type: string
+ readOnly: true
+ symbol:
+ type: string
+ description: symbol for unit display
+ maxLength: 50
+ g:
+ type: number
+ format: double
+ description: grams exponent
+ m:
+ type: number
+ format: double
+ description: meters exponent
+ s:
+ type: number
+ format: double
+ description: seconds exponent
+ A:
+ type: number
+ format: double
+ description: ampere exponent
+ K:
+ type: number
+ format: double
+ description: kelvin exponent
+ cd:
+ type: number
+ format: double
+ description: candela exponent
+ mol:
+ type: number
+ format: double
+ description: mole exponent
+ multiplier:
+ type: number
+ format: double
+ description: multiplier in powers of 10
+ PatchedUser:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ username:
+ type: string
+ description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
+ only.
+ pattern: ^[\w.@+-]+$
+ maxLength: 150
+ first_name:
+ type: string
+ maxLength: 150
+ last_name:
+ type: string
+ maxLength: 150
+ email:
+ type: string
+ format: email
+ title: Email address
+ maxLength: 254
+ profile:
+ allOf:
+ - $ref: '#/components/schemas/Profile'
+ readOnly: true
+ project_set:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ PatchedVariable:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ is_public:
+ type: boolean
+ lower_bound:
+ type: number
+ format: double
+ nullable: true
+ description: lowest possible value for this variable
+ upper_bound:
+ type: number
+ format: double
+ nullable: true
+ description: largest possible value for this variable
+ default_value:
+ type: number
+ format: double
+ description: default value for this variable
+ is_log:
+ type: boolean
+ description: True if default_value is stored as the log of this value
+ name:
+ type: string
+ description: name of the variable
+ maxLength: 100
+ description:
+ type: string
+ nullable: true
+ description: description of the variable
+ binding:
+ type: string
+ nullable: true
+ description: myokit binding of the variable (e.g. time)
+ maxLength: 100
+ qname:
+ type: string
+ description: fully qualitifed name of the variable
+ maxLength: 200
+ unit_symbol:
+ type: string
+ nullable: true
+ description: if unit is None then this is the unit of this variable as a
+ string
+ maxLength: 20
+ constant:
+ type: boolean
+ description: True for a constant variable of the model, i.e. a parameter.
+ False if non-constant, i.e. an output of the model (default is True)
+ state:
+ type: boolean
+ description: True if it is a state variable of the model and has an initial
+ condition parameter (default is False)
+ color:
+ type: integer
+ description: Color index associated with this variable. For display purposes
+ in the frontend
+ display:
+ type: boolean
+ description: True if this variable will be displayed in the frontend, False
+ otherwise
+ axis:
+ type: boolean
+ description: False/True if biomarker type displayed on LHS/RHS axis
+ unit:
+ type: integer
+ nullable: true
+ description: variable values are in this unit (note this might be different
+ from the unit in the stored sbml)
+ pd_model:
+ type: integer
+ nullable: true
+ description: pharmacodynamic model
+ pk_model:
+ type: integer
+ nullable: true
+ description: pharmacokinetic model
+ dosed_pk_model:
+ type: integer
+ nullable: true
+ description: dosed pharmacokinetic model
+ protocol:
+ type: integer
+ nullable: true
+ description: dosing protocol
+ Pharmacodynamic:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ components:
+ type: string
+ readOnly: true
+ variables:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ mmt:
+ type: string
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the model
+ time_max:
+ type: number
+ format: double
+ description: suggested maximum time to simulate for this model (in the time
+ units specified by the mmt model)
+ is_library_model:
+ type: boolean
+ description: whether this model is a library model (i.e. it is not an uploaded
+ user model)
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ required:
+ - components
+ - id
+ - name
+ - variables
+ PharmacodynamicSbml:
+ type: object
+ properties:
+ sbml:
+ type: string
+ writeOnly: true
+ required:
+ - sbml
+ Pharmacokinetic:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the model
+ mmt:
+ type: string
+ description: the model represented using mmt (see https://myokit.readthedocs)
+ time_max:
+ type: number
+ format: double
+ description: suggested maximum time to simulate for this model (in the time
+ units specified by the mmt model)
+ is_library_model:
+ type: boolean
+ description: whether this model is a library model (i.e. it is not an uploaded
+ user model)
+ required:
+ - id
+ - name
+ PkpdMapping:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ datetime:
+ type: string
+ format: date
+ readOnly: true
+ read_only:
+ type: boolean
+ readOnly: true
+ pkpd_model:
+ type: integer
+ description: PKPD model that this mapping is for
+ pk_variable:
+ type: integer
+ description: variable in PK part of model
+ pd_variable:
+ type: integer
+ description: variable in PD part of model
+ required:
+ - datetime
+ - id
+ - pd_variable
+ - pk_variable
+ - pkpd_model
+ - read_only
+ Profile:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ user:
+ type: integer
+ required:
+ - id
+ - user
+ Project:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ user_access:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectAccess'
+ protocols:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ name:
+ type: string
+ description: name of the project
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the project
+ created:
+ type: string
+ format: date-time
+ readOnly: true
+ species:
+ allOf:
+ - $ref: '#/components/schemas/ProjectSpeciesEnum'
+ description: |-
+ subject species
+
+ * `M` - Mouse
+ * `R` - Rat
+ * `H` - Human
+ * `K` - Monkey
+ * `O` - Other
+ compound:
+ type: integer
+ users:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ description: users with access to this project
+ required:
+ - compound
+ - created
+ - id
+ - name
+ - protocols
+ - user_access
+ - users
+ ProjectAccess:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: True if user has read access only
+ user:
+ type: integer
+ project:
+ type: integer
+ readOnly: true
+ required:
+ - id
+ - project
+ - user
+ ProjectSpeciesEnum:
+ enum:
+ - M
+ - R
+ - H
+ - K
+ - O
+ type: string
+ description: |-
+ * `M` - Mouse
+ * `R` - Rat
+ * `H` - Human
+ * `K` - Monkey
+ * `O` - Other
+ Protocol:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ doses:
+ type: array
+ items:
+ $ref: '#/components/schemas/Dose'
+ dataset:
+ type: string
+ readOnly: true
+ variables:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ subjects:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the protocol
+ maxLength: 100
+ dose_type:
+ $ref: '#/components/schemas/DoseTypeEnum'
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this protocol.
+ compound:
+ type: integer
+ nullable: true
+ description: drug compound
+ time_unit:
+ type: integer
+ nullable: true
+ description: unit for the start_time and duration values stored in each
+ dose
+ amount_unit:
+ type: integer
+ nullable: true
+ description: unit for the amount value stored in each dose
+ required:
+ - dataset
+ - doses
+ - id
+ - name
+ - subjects
+ - variables
+ Simulate:
+ type: object
+ properties:
+ outputs:
+ type: array
+ items:
+ type: string
+ variables:
+ type: object
+ additionalProperties:
+ type: number
+ format: double
+ time_max:
+ type: number
+ format: double
+ required:
+ - outputs
+ - variables
+ SimulateResponse:
+ type: object
+ properties:
+ time:
+ type: array
+ items:
+ type: number
+ format: double
+ outputs:
+ type: object
+ additionalProperties:
+ type: array
+ items:
+ type: number
+ format: double
+ required:
+ - outputs
+ - time
+ Simulation:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ sliders:
+ type: array
+ items:
+ $ref: '#/components/schemas/SimulationSlider'
+ plots:
+ type: array
+ items:
+ $ref: '#/components/schemas/SimulationPlot'
+ name:
+ type: string
+ description: name of the simulation
+ maxLength: 100
+ nrows:
+ type: integer
+ description: number of subplot rows
+ ncols:
+ type: integer
+ description: number of subplot columns
+ time_max:
+ type: number
+ format: double
+ minimum: 0
+ description: maximum time for the simulation
+ abs_tolerance:
+ type: number
+ format: double
+ minimum: 0
+ description: absolute tolerance for the simulation
+ rel_tolerance:
+ type: number
+ format: double
+ minimum: 0
+ description: relative tolerance for the simulation
+ project:
+ type: integer
+ time_max_unit:
+ type: integer
+ description: unit for maximum time
+ required:
+ - id
+ - name
+ - plots
+ - project
+ - sliders
+ - time_max_unit
+ SimulationCxLine:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ value:
+ type: number
+ format: double
+ description: value of the line
+ required:
+ - id
+ - value
+ SimulationPlot:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ y_axes:
+ type: array
+ items:
+ $ref: '#/components/schemas/SimulationYAxis'
+ cx_lines:
+ type: array
+ items:
+ $ref: '#/components/schemas/SimulationCxLine'
+ index:
+ type: integer
+ description: index of the plot in the simulation
+ x_scale:
+ allOf:
+ - $ref: '#/components/schemas/Y2ScaleEnum'
+ description: |-
+ scale for x axis
+
+ * `lin` - Linear
+ * `lg2` - Log2
+ * `lg10` - Log10
+ * `ln` - Ln
+ y_scale:
+ allOf:
+ - $ref: '#/components/schemas/Y2ScaleEnum'
+ description: |-
+ scale for y axis
+
+ * `lin` - Linear
+ * `lg2` - Log2
+ * `lg10` - Log10
+ * `ln` - Ln
+ y2_scale:
+ allOf:
+ - $ref: '#/components/schemas/Y2ScaleEnum'
+ description: |-
+ scale for rhs y axis
+
+ * `lin` - Linear
+ * `lg2` - Log2
+ * `lg10` - Log10
+ * `ln` - Ln
+ min:
+ type: number
+ format: double
+ nullable: true
+ description: lower bound for the y axis
+ max:
+ type: number
+ format: double
+ nullable: true
+ description: upper bound for the y axis
+ min2:
+ type: number
+ format: double
+ nullable: true
+ description: lower bound for the rhs y axis
+ max2:
+ type: number
+ format: double
+ nullable: true
+ description: upper bound for the rhs y axis
+ x_unit:
+ type: integer
+ description: unit for x axis
+ y_unit:
+ type: integer
+ nullable: true
+ description: unit for y axis
+ y_unit2:
+ type: integer
+ nullable: true
+ description: unit for rhs y axis
+ required:
+ - cx_lines
+ - id
+ - index
+ - x_unit
+ - y_axes
+ SimulationSlider:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ variable:
+ type: integer
+ required:
+ - id
+ - variable
+ SimulationYAxis:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ right:
+ type: boolean
+ description: True if the variable is plotted on the right y axis
+ variable:
+ type: integer
+ required:
+ - id
+ - variable
+ Subject:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ id_in_dataset:
+ type: integer
+ description: unique id in the dataset
+ shape:
+ type: integer
+ description: Shape index associated with this subject. For plotting purposes
+ in the frontend
+ display:
+ type: boolean
+ description: True if this subject will be displayed in the frontend, False
+ otherwise
+ metadata:
+ type: string
+ description: subject metadata
+ dataset:
+ type: integer
+ description: dataset containing this subject
+ protocol:
+ type: integer
+ nullable: true
+ description: dosing protocol for this subject.
+ required:
+ - dataset
+ - id
+ - id_in_dataset
+ TypeEnum:
+ enum:
+ - RO
+ - FUP
+ - BPR
+ - TLG
+ type: string
+ description: |-
+ * `RO` - receptor occupancy
+ * `FUP` - faction unbound plasma
+ * `BPR` - blood plasma ratio
+ * `TLG` - dosing lag time
+ Unit:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ compatible_units:
+ type: array
+ items:
+ type: object
+ additionalProperties:
+ type: string
+ readOnly: true
+ symbol:
+ type: string
+ description: symbol for unit display
+ maxLength: 50
+ g:
+ type: number
+ format: double
+ description: grams exponent
+ m:
+ type: number
+ format: double
+ description: meters exponent
+ s:
+ type: number
+ format: double
+ description: seconds exponent
+ A:
+ type: number
+ format: double
+ description: ampere exponent
+ K:
+ type: number
+ format: double
+ description: kelvin exponent
+ cd:
+ type: number
+ format: double
+ description: candela exponent
+ mol:
+ type: number
+ format: double
+ description: mole exponent
+ multiplier:
+ type: number
+ format: double
+ description: multiplier in powers of 10
+ required:
+ - compatible_units
+ - id
+ - symbol
+ User:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ username:
+ type: string
+ description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
+ only.
+ pattern: ^[\w.@+-]+$
+ maxLength: 150
+ first_name:
+ type: string
+ maxLength: 150
+ last_name:
+ type: string
+ maxLength: 150
+ email:
+ type: string
+ format: email
+ title: Email address
+ maxLength: 254
+ profile:
+ allOf:
+ - $ref: '#/components/schemas/Profile'
+ readOnly: true
+ project_set:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ required:
+ - id
+ - profile
+ - project_set
+ - username
+ Variable:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ is_public:
+ type: boolean
+ lower_bound:
+ type: number
+ format: double
+ nullable: true
+ description: lowest possible value for this variable
+ upper_bound:
+ type: number
+ format: double
+ nullable: true
+ description: largest possible value for this variable
+ default_value:
+ type: number
+ format: double
+ description: default value for this variable
+ is_log:
+ type: boolean
+ description: True if default_value is stored as the log of this value
+ name:
+ type: string
+ description: name of the variable
+ maxLength: 100
+ description:
+ type: string
+ nullable: true
+ description: description of the variable
+ binding:
+ type: string
+ nullable: true
+ description: myokit binding of the variable (e.g. time)
+ maxLength: 100
+ qname:
+ type: string
+ description: fully qualitifed name of the variable
+ maxLength: 200
+ unit_symbol:
+ type: string
+ nullable: true
+ description: if unit is None then this is the unit of this variable as a
+ string
+ maxLength: 20
+ constant:
+ type: boolean
+ description: True for a constant variable of the model, i.e. a parameter.
+ False if non-constant, i.e. an output of the model (default is True)
+ state:
+ type: boolean
+ description: True if it is a state variable of the model and has an initial
+ condition parameter (default is False)
+ color:
+ type: integer
+ description: Color index associated with this variable. For display purposes
+ in the frontend
+ display:
+ type: boolean
+ description: True if this variable will be displayed in the frontend, False
+ otherwise
+ axis:
+ type: boolean
+ description: False/True if biomarker type displayed on LHS/RHS axis
+ unit:
+ type: integer
+ nullable: true
+ description: variable values are in this unit (note this might be different
+ from the unit in the stored sbml)
+ pd_model:
+ type: integer
+ nullable: true
+ description: pharmacodynamic model
+ pk_model:
+ type: integer
+ nullable: true
+ description: pharmacokinetic model
+ dosed_pk_model:
+ type: integer
+ nullable: true
+ description: dosed pharmacokinetic model
+ protocol:
+ type: integer
+ nullable: true
+ description: dosing protocol
+ required:
+ - id
+ - name
+ - qname
+ Y2ScaleEnum:
+ enum:
+ - lin
+ - lg2
+ - lg10
+ - ln
+ type: string
+ description: |-
+ * `lin` - Linear
+ * `lg2` - Log2
+ * `lg10` - Log10
+ * `ln` - Ln
+ securitySchemes:
+ basicAuth:
+ type: http
+ scheme: basic
+ cookieAuth:
+ type: apiKey
+ in: cookie
+ name: sessionid
diff --git a/pkpdapp/schema.yml# b/pkpdapp/schema.yml#
new file mode 100644
index 00000000..6c37d1ca
--- /dev/null
+++ b/pkpdapp/schema.yml#
@@ -0,0 +1,4584 @@
+openapi: 3.0.3
+info:
+ title: PKPDApp API
+ version: 1.0.0
+ description: The API for the PKPDApp
+paths:
+ /api/algorithm/:
+ get:
+ operationId: algorithm_list
+ tags:
+ - algorithm
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ post:
+ operationId: algorithm_create
+ tags:
+ - algorithm
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ /api/algorithm/{id}/:
+ get:
+ operationId: algorithm_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithm
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ put:
+ operationId: algorithm_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithm
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ patch:
+ operationId: algorithm_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithm
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedAlgorithm'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedAlgorithm'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedAlgorithm'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Algorithm'
+ description: ''
+ delete:
+ operationId: algorithm_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this algorithm.
+ required: true
+ tags:
+ - algorithm
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/auce/:
+ post:
+ operationId: auce_create
+ tags:
+ - auce
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/biomarker_type/:
+ get:
+ operationId: biomarker_type_list
+ tags:
+ - biomarker_type
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/BiomarkerType'
+ description: ''
+ post:
+ operationId: biomarker_type_create
+ tags:
+ - biomarker_type
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ description: ''
+ /api/biomarker_type/{id}/:
+ get:
+ operationId: biomarker_type_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this biomarker type.
+ required: true
+ tags:
+ - biomarker_type
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ description: ''
+ put:
+ operationId: biomarker_type_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this biomarker type.
+ required: true
+ tags:
+ - biomarker_type
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ description: ''
+ patch:
+ operationId: biomarker_type_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this biomarker type.
+ required: true
+ tags:
+ - biomarker_type
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedBiomarkerType'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedBiomarkerType'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedBiomarkerType'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/BiomarkerType'
+ description: ''
+ delete:
+ operationId: biomarker_type_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this biomarker type.
+ required: true
+ tags:
+ - biomarker_type
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/compound/:
+ get:
+ operationId: compound_list
+ tags:
+ - compound
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Compound'
+ description: ''
+ post:
+ operationId: compound_create
+ tags:
+ - compound
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ description: ''
+ /api/compound/{id}/:
+ get:
+ operationId: compound_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this compound.
+ required: true
+ tags:
+ - compound
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ description: ''
+ put:
+ operationId: compound_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this compound.
+ required: true
+ tags:
+ - compound
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ description: ''
+ patch:
+ operationId: compound_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this compound.
+ required: true
+ tags:
+ - compound
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedCompound'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedCompound'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedCompound'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Compound'
+ description: ''
+ delete:
+ operationId: compound_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this compound.
+ required: true
+ tags:
+ - compound
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/dataset/:
+ get:
+ operationId: dataset_list
+ tags:
+ - dataset
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ post:
+ operationId: dataset_create
+ tags:
+ - dataset
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ /api/dataset/{id}/:
+ get:
+ operationId: dataset_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dataset.
+ required: true
+ tags:
+ - dataset
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ put:
+ operationId: dataset_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dataset.
+ required: true
+ tags:
+ - dataset
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ patch:
+ operationId: dataset_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dataset.
+ required: true
+ tags:
+ - dataset
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedDataset'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedDataset'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedDataset'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dataset'
+ description: ''
+ delete:
+ operationId: dataset_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dataset.
+ required: true
+ tags:
+ - dataset
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/dataset/{id}/csv/:
+ put:
+ operationId: dataset_csv_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dataset.
+ required: true
+ tags:
+ - dataset
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/DatasetCsv'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DatasetCsv'
+ description: ''
+ /api/dose/:
+ get:
+ operationId: dose_list
+ tags:
+ - dose
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Dose'
+ description: ''
+ post:
+ operationId: dose_create
+ tags:
+ - dose
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ description: ''
+ /api/dose/{id}/:
+ get:
+ operationId: dose_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dose.
+ required: true
+ tags:
+ - dose
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ description: ''
+ put:
+ operationId: dose_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dose.
+ required: true
+ tags:
+ - dose
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ description: ''
+ patch:
+ operationId: dose_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dose.
+ required: true
+ tags:
+ - dose
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedDose'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedDose'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedDose'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Dose'
+ description: ''
+ delete:
+ operationId: dose_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dose.
+ required: true
+ tags:
+ - dose
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/dosed_pharmacokinetic/:
+ get:
+ operationId: dosed_pharmacokinetic_list
+ tags:
+ - dosed_pharmacokinetic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ description: ''
+ post:
+ operationId: dosed_pharmacokinetic_create
+ tags:
+ - dosed_pharmacokinetic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ description: ''
+ /api/dosed_pharmacokinetic/{id}/:
+ get:
+ operationId: dosed_pharmacokinetic_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dosed pharmacokinetic
+ model.
+ required: true
+ tags:
+ - dosed_pharmacokinetic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ description: ''
+ put:
+ operationId: dosed_pharmacokinetic_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dosed pharmacokinetic
+ model.
+ required: true
+ tags:
+ - dosed_pharmacokinetic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ description: ''
+ patch:
+ operationId: dosed_pharmacokinetic_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dosed pharmacokinetic
+ model.
+ required: true
+ tags:
+ - dosed_pharmacokinetic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedDosedPharmacokinetic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedDosedPharmacokinetic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedDosedPharmacokinetic'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ description: ''
+ delete:
+ operationId: dosed_pharmacokinetic_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dosed pharmacokinetic
+ model.
+ required: true
+ tags:
+ - dosed_pharmacokinetic
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/dosed_pharmacokinetic/{id}/set_variables_from_inference/:
+ put:
+ operationId: dosed_pharmacokinetic_set_variables_from_inference_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this dosed pharmacokinetic
+ model.
+ required: true
+ tags:
+ - dosed_pharmacokinetic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/DosedPharmacokinetic'
+ description: ''
+ /api/dosed_pharmacokinetic/{id}/simulate:
+ post:
+ operationId: dosed_pharmacokinetic_simulate_create
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ required: true
+ tags:
+ - dosed_pharmacokinetic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/inference/:
+ get:
+ operationId: inference_list
+ tags:
+ - inference
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Inference'
+ description: ''
+ post:
+ operationId: inference_create
+ tags:
+ - inference
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ description: ''
+ /api/inference/{id}/:
+ get:
+ operationId: inference_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference.
+ required: true
+ tags:
+ - inference
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ description: ''
+ put:
+ operationId: inference_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference.
+ required: true
+ tags:
+ - inference
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ description: ''
+ patch:
+ operationId: inference_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference.
+ required: true
+ tags:
+ - inference
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedInference'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedInference'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedInference'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Inference'
+ description: ''
+ delete:
+ operationId: inference_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference.
+ required: true
+ tags:
+ - inference
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/inference/{id}/stop:
+ post:
+ operationId: inference_stop_create
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ required: true
+ tags:
+ - inference
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/inference/wizard:
+ post:
+ operationId: inference_wizard_create
+ description: |-
+ expecting data in the form:
+ {
+
+ # Inference parameters
+ 'id': 1
+ 'name': "my inference run",
+ 'project': 1,
+ 'algorithm': 2,
+ 'initialization_strategy': 'R',
+ 'initialization_inference': 2,
+ 'number_of_chains': 4,
+ 'max_number_of_iterations': 3000,
+ 'burn_in': 0,
+
+ # Model
+ 'model': {
+ 'form': 'PK',
+ 'id': 5
+ }
+ 'dataset': 3,
+
+ # Model parameters
+ 'parameters': [
+ {
+ 'name': 'myokit.parameter1'
+ 'form': 'N',
+ 'pooled': False,
+ 'parameters': [
+ '2 * biomarker[subject_weight]',
+ 'parameter[parameter1_variance]'
+ ]
+ },
+ {
+ 'name': 'parameter1_variance'
+ 'form': 'N',
+ 'parameters': [0, 1]
+ },
+ {
+ 'name': 'myokit.parameter2'
+ 'form': 'U',
+ 'parameters': [-1, 1]
+ },
+ {
+ 'name': 'myokit.parameter3'
+ 'form': 'F',
+ 'parameters': [123.5]
+ },
+ ]
+
+ # output
+ 'observations': [
+ {
+ 'model': 'myokit.plasma_concentration',
+ 'biomarker': 'concentration,
+ 'noise_form': 'N',
+ 'noise_param_form': 'N',
+ 'parameters': [0, 1]
+ },
+ {
+ 'model': 'myokit.bacteria_count',
+ 'biomarker': 'bacteria,
+ 'noise_form': 'LN',
+ 'noise_param_form': 'F'
+ 'parameters': [123.3]
+ },
+ ]
+ }
+
+ Uses model as the base model. If it is a PK or PKPD model, creates a model
+ for each protocol used in the dataset, replacing the protocol of the model
+ with each new one.
+
+ This set of models has a set of parameters. If pooled is True or not given,
+ then parameters of the same qname are assumed to be identical, if pooled is
+ False, then the value of this parameter is different across each subject.
+ All Variable fields from the original model are copied over to the new
+ models. Priors and fixed values for each parameter in this set are provided
+ in 'parameters'. Distribution parameters for each prior can be provided
+ using a python expression, or a number. If a python expression is used, the
+ keywords Parameter[] are used to refer to other parameters in
+ the list. Additional parameters can be added to the list (parameters not in
+ the model) to contruct hierarchical inference. You can refer to biomarkers
+ in the expression using the keyword Biomarker[].
+
+ The 'observations' field maps model output variables with biomarkers in the
+ dataset
+ tags:
+ - inference
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/inference_chain/:
+ get:
+ operationId: inference_chain_list
+ tags:
+ - inference_chain
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/InferenceChain'
+ description: ''
+ post:
+ operationId: inference_chain_create
+ tags:
+ - inference_chain
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ description: ''
+ /api/inference_chain/{id}/:
+ get:
+ operationId: inference_chain_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference chain.
+ required: true
+ tags:
+ - inference_chain
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ description: ''
+ put:
+ operationId: inference_chain_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference chain.
+ required: true
+ tags:
+ - inference_chain
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ description: ''
+ patch:
+ operationId: inference_chain_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference chain.
+ required: true
+ tags:
+ - inference_chain
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedInferenceChain'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedInferenceChain'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedInferenceChain'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/InferenceChain'
+ description: ''
+ delete:
+ operationId: inference_chain_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this inference chain.
+ required: true
+ tags:
+ - inference_chain
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/nca/:
+ post:
+ operationId: nca_create
+ tags:
+ - nca
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/pharmacodynamic/:
+ get:
+ operationId: pharmacodynamic_list
+ tags:
+ - pharmacodynamic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ post:
+ operationId: pharmacodynamic_create
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ /api/pharmacodynamic/{id}/:
+ get:
+ operationId: pharmacodynamic_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ put:
+ operationId: pharmacodynamic_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ patch:
+ operationId: pharmacodynamic_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacodynamic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacodynamic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacodynamic'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ delete:
+ operationId: pharmacodynamic_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/pharmacodynamic/{id}/mmt/:
+ put:
+ operationId: pharmacodynamic_mmt_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ /api/pharmacodynamic/{id}/sbml/:
+ put:
+ operationId: pharmacodynamic_sbml_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PharmacodynamicSbml'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PharmacodynamicSbml'
+ description: ''
+ /api/pharmacodynamic/{id}/set_variables_from_inference/:
+ put:
+ operationId: pharmacodynamic_set_variables_from_inference_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacodynamic model.
+ required: true
+ tags:
+ - pharmacodynamic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacodynamic'
+ description: ''
+ /api/pharmacodynamic/{id}/simulate:
+ post:
+ operationId: pharmacodynamic_simulate_create
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ required: true
+ tags:
+ - pharmacodynamic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/pharmacokinetic/:
+ get:
+ operationId: pharmacokinetic_list
+ tags:
+ - pharmacokinetic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ description: ''
+ post:
+ operationId: pharmacokinetic_create
+ tags:
+ - pharmacokinetic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ description: ''
+ /api/pharmacokinetic/{id}/:
+ get:
+ operationId: pharmacokinetic_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacokinetic model.
+ required: true
+ tags:
+ - pharmacokinetic
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ description: ''
+ put:
+ operationId: pharmacokinetic_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacokinetic model.
+ required: true
+ tags:
+ - pharmacokinetic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ description: ''
+ patch:
+ operationId: pharmacokinetic_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacokinetic model.
+ required: true
+ tags:
+ - pharmacokinetic
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacokinetic'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacokinetic'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedPharmacokinetic'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Pharmacokinetic'
+ description: ''
+ delete:
+ operationId: pharmacokinetic_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this pharmacokinetic model.
+ required: true
+ tags:
+ - pharmacokinetic
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/project/:
+ get:
+ operationId: project_list
+ description: Enable partial updates
+ tags:
+ - project
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Project'
+ description: ''
+ post:
+ operationId: project_create
+ description: Enable partial updates
+ tags:
+ - project
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Project'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Project'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ description: ''
+ /api/project/{id}/:
+ get:
+ operationId: project_retrieve
+ description: Enable partial updates
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project.
+ required: true
+ tags:
+ - project
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ description: ''
+ put:
+ operationId: project_update
+ description: Enable partial updates
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project.
+ required: true
+ tags:
+ - project
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Project'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Project'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ description: ''
+ patch:
+ operationId: project_partial_update
+ description: Enable partial updates
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project.
+ required: true
+ tags:
+ - project
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedProject'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedProject'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedProject'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Project'
+ description: ''
+ delete:
+ operationId: project_destroy
+ description: Enable partial updates
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project.
+ required: true
+ tags:
+ - project
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/project/{id}/monolix/:
+ put:
+ operationId: project_monolix_update
+ description: Enable partial updates
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project.
+ required: true
+ tags:
+ - project
+ requestBody:
+ content:
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Monolix'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Monolix'
+ description: ''
+ /api/project_access/:
+ get:
+ operationId: project_access_list
+ tags:
+ - project_access
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectAccess'
+ description: ''
+ post:
+ operationId: project_access_create
+ tags:
+ - project_access
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ description: ''
+ /api/project_access/{id}/:
+ get:
+ operationId: project_access_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project access.
+ required: true
+ tags:
+ - project_access
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ description: ''
+ put:
+ operationId: project_access_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project access.
+ required: true
+ tags:
+ - project_access
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ description: ''
+ patch:
+ operationId: project_access_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project access.
+ required: true
+ tags:
+ - project_access
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedProjectAccess'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedProjectAccess'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedProjectAccess'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/ProjectAccess'
+ description: ''
+ delete:
+ operationId: project_access_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this project access.
+ required: true
+ tags:
+ - project_access
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/protocol/:
+ get:
+ operationId: protocol_list
+ tags:
+ - protocol
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Protocol'
+ description: ''
+ post:
+ operationId: protocol_create
+ tags:
+ - protocol
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ description: ''
+ /api/protocol/{id}/:
+ get:
+ operationId: protocol_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this protocol.
+ required: true
+ tags:
+ - protocol
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ description: ''
+ put:
+ operationId: protocol_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this protocol.
+ required: true
+ tags:
+ - protocol
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ description: ''
+ patch:
+ operationId: protocol_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this protocol.
+ required: true
+ tags:
+ - protocol
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedProtocol'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedProtocol'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedProtocol'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Protocol'
+ description: ''
+ delete:
+ operationId: protocol_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this protocol.
+ required: true
+ tags:
+ - protocol
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/session/:
+ get:
+ operationId: session_retrieve
+ tags:
+ - session
+ security:
+ - cookieAuth: []
+ - basicAuth: []
+ responses:
+ '200':
+ description: No response body
+ /api/subject/:
+ get:
+ operationId: subject_list
+ tags:
+ - subject
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Subject'
+ description: ''
+ post:
+ operationId: subject_create
+ tags:
+ - subject
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ description: ''
+ /api/subject/{id}/:
+ get:
+ operationId: subject_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this subject.
+ required: true
+ tags:
+ - subject
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ description: ''
+ put:
+ operationId: subject_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this subject.
+ required: true
+ tags:
+ - subject
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ description: ''
+ patch:
+ operationId: subject_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this subject.
+ required: true
+ tags:
+ - subject
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedSubject'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedSubject'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedSubject'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Subject'
+ description: ''
+ delete:
+ operationId: subject_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this subject.
+ required: true
+ tags:
+ - subject
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/unit/:
+ get:
+ operationId: unit_list
+ tags:
+ - unit
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Unit'
+ description: ''
+ post:
+ operationId: unit_create
+ tags:
+ - unit
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ description: ''
+ /api/unit/{id}/:
+ get:
+ operationId: unit_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this unit.
+ required: true
+ tags:
+ - unit
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ description: ''
+ put:
+ operationId: unit_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this unit.
+ required: true
+ tags:
+ - unit
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ description: ''
+ patch:
+ operationId: unit_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this unit.
+ required: true
+ tags:
+ - unit
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedUnit'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedUnit'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedUnit'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Unit'
+ description: ''
+ delete:
+ operationId: unit_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this unit.
+ required: true
+ tags:
+ - unit
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/user/:
+ get:
+ operationId: user_list
+ tags:
+ - user
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/User'
+ description: ''
+ post:
+ operationId: user_create
+ tags:
+ - user
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/User'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/User'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ description: ''
+ /api/user/{id}/:
+ get:
+ operationId: user_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this user.
+ required: true
+ tags:
+ - user
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ description: ''
+ put:
+ operationId: user_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this user.
+ required: true
+ tags:
+ - user
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/User'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/User'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ description: ''
+ patch:
+ operationId: user_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this user.
+ required: true
+ tags:
+ - user
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedUser'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedUser'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedUser'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/User'
+ description: ''
+ delete:
+ operationId: user_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this user.
+ required: true
+ tags:
+ - user
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/variable/:
+ get:
+ operationId: variable_list
+ tags:
+ - variable
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: '#/components/schemas/Variable'
+ description: ''
+ post:
+ operationId: variable_create
+ tags:
+ - variable
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '201':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ description: ''
+ /api/variable/{id}/:
+ get:
+ operationId: variable_retrieve
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this variable.
+ required: true
+ tags:
+ - variable
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ description: ''
+ put:
+ operationId: variable_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this variable.
+ required: true
+ tags:
+ - variable
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ required: true
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ description: ''
+ patch:
+ operationId: variable_partial_update
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this variable.
+ required: true
+ tags:
+ - variable
+ requestBody:
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/PatchedVariable'
+ application/x-www-form-urlencoded:
+ schema:
+ $ref: '#/components/schemas/PatchedVariable'
+ multipart/form-data:
+ schema:
+ $ref: '#/components/schemas/PatchedVariable'
+ security:
+ - cookieAuth: []
+ responses:
+ '200':
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/Variable'
+ description: ''
+ delete:
+ operationId: variable_destroy
+ parameters:
+ - in: path
+ name: id
+ schema:
+ type: integer
+ description: A unique integer value identifying this variable.
+ required: true
+ tags:
+ - variable
+ security:
+ - cookieAuth: []
+ responses:
+ '204':
+ description: No response body
+ /api/whoami/:
+ get:
+ operationId: whoami_retrieve
+ tags:
+ - whoami
+ security:
+ - cookieAuth: []
+ - basicAuth: []
+ responses:
+ '200':
+ description: No response body
+components:
+ schemas:
+ Algorithm:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ name:
+ type: string
+ description: name of the algorithm
+ maxLength: 100
+ category:
+ $ref: '#/components/schemas/CategoryEnum'
+ required:
+ - category
+ - id
+ - name
+ BiomarkerType:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ data:
+ type: object
+ additionalProperties:
+ type: array
+ items: {}
+ nullable: true
+ readOnly: true
+ is_continuous:
+ type: boolean
+ readOnly: true
+ is_categorical:
+ type: boolean
+ readOnly: true
+ name:
+ type: string
+ description: name of the biomarker type
+ maxLength: 100
+ description:
+ type: string
+ nullable: true
+ description: short description of the biomarker type
+ display:
+ type: boolean
+ description: True if this biomarker type will be displayed in the frontend,
+ False otherwise
+ color:
+ type: integer
+ description: Color index associated with this biomarker type. For plotting
+ purposes in the frontend
+ axis:
+ type: boolean
+ description: True/False if biomarker type displayed on LHS/RHS axis
+ stored_unit:
+ type: integer
+ description: unit for the value stored in :model:`pkpdapp.Biomarker`
+ dataset:
+ type: integer
+ description: dataset containing this biomarker measurement
+ display_unit:
+ type: integer
+ description: unit to use when sending or displaying biomarker values
+ stored_time_unit:
+ type: integer
+ description: unit for the time values stored in :model:`pkpdapp.Biomarker`
+ display_time_unit:
+ type: integer
+ description: unit to use when sending or displaying time values
+ required:
+ - data
+ - dataset
+ - display_time_unit
+ - display_unit
+ - id
+ - is_categorical
+ - is_continuous
+ - name
+ - stored_time_unit
+ - stored_unit
+ CategoryEnum:
+ enum:
+ - SA
+ - OP
+ - OT
+ type: string
+ description: |-
+ * `SA` - Sampling
+ * `OP` - Optimisation
+ * `OT` - Optimisation
+ Compound:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ efficacy_experiments:
+ type: array
+ items:
+ $ref: '#/components/schemas/Efficacy'
+ name:
+ type: string
+ description: name of the compound
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the compound
+ molecular_mass:
+ type: number
+ format: double
+ description: molecular mass for compound for conversion from mol to grams
+ compound_type:
+ $ref: '#/components/schemas/CompoundTypeEnum'
+ fraction_unbound_plasma:
+ type: number
+ format: double
+ nullable: true
+ description: fraction unbound plasma (unitless)
+ blood_to_plasma_ratio:
+ type: number
+ format: double
+ nullable: true
+ description: blood to plasma ratio (unitless)
+ intrinsic_clearence:
+ type: number
+ format: double
+ nullable: true
+ description: intrinsic clearance
+ intrinsic_clearence_assay:
+ $ref: '#/components/schemas/IntrinsicClearenceAssayEnum'
+ fraction_unbound_including_cells:
+ type: number
+ format: double
+ nullable: true
+ description: fraction unbound in plasma and red blood cells (unitless)
+ target_concentration:
+ type: number
+ format: double
+ nullable: true
+ description: target concentration
+ dissociation_constant:
+ type: number
+ format: double
+ nullable: true
+ description: dissociation constant
+ calculate_receptor_occupancy:
+ type: boolean
+ description: calculate receptor occupancy
+ is_soluble:
+ type: boolean
+ description: is the compound target soluble
+ molecular_mass_unit:
+ type: integer
+ description: unit for molecular mass (e.g. g/mol)
+ intrinsic_clearence_unit:
+ type: integer
+ description: unit for intrinsic clearance
+ target_concentration_unit:
+ type: integer
+ description: unit for target concentration
+ dissociation_unit:
+ type: integer
+ description: unit for dissociation constant
+ required:
+ - efficacy_experiments
+ - id
+ - molecular_mass
+ - name
+ CompoundTypeEnum:
+ enum:
+ - SM
+ - LM
+ type: string
+ description: |-
+ * `SM` - Small Molecule
+ * `LM` - Large Molecule
+ Dataset:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ biomarker_types:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ subjects:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ protocols:
+ type: array
+ items:
+ $ref: '#/components/schemas/Protocol'
+ readOnly: true
+ name:
+ type: string
+ description: name of the dataset
+ maxLength: 100
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: date/time the experiment was conducted. All time measurements
+ are relative to this date/time, which is in YYYY-MM-DD HH:MM:SS format.
+ For example, 2020-07-18 14:30:59
+ description:
+ type: string
+ description: short description of the dataset
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ required:
+ - biomarker_types
+ - id
+ - name
+ - protocols
+ - subjects
+ DatasetCsv:
+ type: object
+ properties:
+ csv:
+ type: string
+ format: uri
+ required:
+ - csv
+ Dose:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ start_time:
+ type: number
+ format: double
+ description: starting time point of dose, see protocol for units
+ amount:
+ type: number
+ format: double
+ description: amount of compound administered over the duration, see protocol
+ for units. Rate of administration is assumed constant
+ duration:
+ type: number
+ format: double
+ description: Duration of dose administration, see protocol for units. Duration
+ must be greater than 0.
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ protocol:
+ type: integer
+ description: protocol containing this dose
+ required:
+ - amount
+ - id
+ - protocol
+ - start_time
+ DoseTypeEnum:
+ enum:
+ - D
+ - I
+ type: string
+ description: |-
+ * `D` - IV
+ * `I` - Extravascular
+ DosedPharmacokinetic:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ mappings:
+ type: array
+ items:
+ $ref: '#/components/schemas/PkpdMapping'
+ components:
+ type: string
+ readOnly: true
+ variables:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ mmt:
+ type: string
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ dose_compartment:
+ type: string
+ nullable: true
+ description: compartment name to be dosed
+ maxLength: 100
+ time_max:
+ type: number
+ format: double
+ description: suggested time to simulate after the last dose (in the time
+ units specified by the mmt model)
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ pk_model:
+ type: integer
+ nullable: true
+ description: model
+ pd_model:
+ type: integer
+ nullable: true
+ description: PD part of model
+ protocol:
+ type: integer
+ nullable: true
+ description: dosing protocol
+ required:
+ - components
+ - id
+ - mappings
+ - mmt
+ - name
+ - variables
+ Efficacy:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ name:
+ type: string
+ description: name of the experiment
+ maxLength: 100
+ c50:
+ type: number
+ format: double
+ description: half maximal effective concentration
+ hill_coefficient:
+ type: number
+ format: double
+ description: Hill coefficient measure of binding
+ c50_unit:
+ type: integer
+ description: unit for c50
+ compound:
+ type: integer
+ description: compound for efficacy experiment
+ required:
+ - c50
+ - c50_unit
+ - compound
+ - id
+ - name
+ FormEnum:
+ enum:
+ - N
+ - U
+ - LN
+ - F
+ - S
+ - E
+ - M
+ type: string
+ description: |-
+ * `N` - Normal
+ * `U` - Uniform
+ * `LN` - Log-Normal
+ * `F` - Fixed
+ * `S` - Sum
+ * `E` - Equation
+ * `M` - Model
+ Inference:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ log_likelihoods:
+ type: array
+ items:
+ $ref: '#/components/schemas/LogLikelihood'
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the dataset
+ maxLength: 100
+ description:
+ type: string
+ description: short description of what this inference does
+ initialization_strategy:
+ $ref: '#/components/schemas/InitializationStrategyEnum'
+ number_of_chains:
+ type: integer
+ description: number of chains
+ max_number_of_iterations:
+ type: integer
+ description: maximum number of iterations
+ burn_in:
+ type: integer
+ description: final iteration of burn-in
+ number_of_iterations:
+ type: integer
+ description: number of iterations calculated
+ time_elapsed:
+ type: integer
+ description: Elapsed run time for inference in seconds
+ number_of_function_evals:
+ type: integer
+ description: number of function evaluations
+ task_id:
+ type: string
+ nullable: true
+ description: If executing, this is the celery task id
+ maxLength: 40
+ metadata:
+ type: object
+ additionalProperties: {}
+ description: metadata for inference
+ project:
+ type: integer
+ description: Project that "owns" this inference object
+ algorithm:
+ type: integer
+ description: algorithm used to perform the inference
+ initialization_inference:
+ type: integer
+ nullable: true
+ required:
+ - id
+ - log_likelihoods
+ - name
+ - project
+ InferenceChain:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ data:
+ type: string
+ readOnly: true
+ outputs:
+ type: string
+ readOnly: true
+ inference:
+ type: integer
+ description: inference for this chain
+ required:
+ - data
+ - id
+ - inference
+ - outputs
+ InitializationStrategyEnum:
+ enum:
+ - D
+ - R
+ - F
+ type: string
+ description: |-
+ * `D` - Default Value of model
+ * `R` - Random from prior
+ * `F` - From other inference
+ IntrinsicClearenceAssayEnum:
+ enum:
+ - MS
+ - HC
+ type: string
+ description: |-
+ * `MS` - Microsomes
+ * `HC` - Hepatocytes
+ LogLikelihood:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ parameters:
+ type: array
+ items:
+ $ref: '#/components/schemas/LogLikelihoodParameter'
+ model:
+ type: array
+ items:
+ type: string
+ minLength: 2
+ maxLength: 2
+ nullable: true
+ readOnly: true
+ dataset:
+ type: integer
+ nullable: true
+ readOnly: true
+ time_variable:
+ type: integer
+ nullable: true
+ readOnly: true
+ is_a_prior:
+ type: boolean
+ readOnly: true
+ name:
+ type: string
+ description: name of log_likelihood.
+ maxLength: 100
+ description:
+ type: string
+ nullable: true
+ description: 'description of log_likelihood. For equations will be the code
+ of that equation using Python syntax: arg1 * arg2^arg3'
+ value:
+ type: number
+ format: double
+ nullable: true
+ description: set if a fixed value is required
+ time_independent_data:
+ type: boolean
+ description: 'True if biomarker_type refers to time-independent data. If
+ there are multiple timepoints in biomarker_type then only the first is
+ taken '
+ observed:
+ type: boolean
+ description: 'True if this log_likelihood is observed '
+ form:
+ $ref: '#/components/schemas/FormEnum'
+ inference:
+ type: integer
+ readOnly: true
+ description: 'Log_likelihood belongs to this inference object. '
+ variable:
+ type: integer
+ nullable: true
+ description: 'If form=MODEL, a variable (any) in the deterministic model. '
+ biomarker_type:
+ type: integer
+ nullable: true
+ description: data associated with this log_likelihood. This is used for
+ measurement data (observed=True) or for covariates (observed=False). The
+ random variable associated with this log_likelihood has the same shape
+ as this data. For covariates the subject ids in the data correspond to
+ the values of the random variable at that location.
+ protocol_filter:
+ type: integer
+ nullable: true
+ description: filter subject data on this protocol(null implies all subjects)
+ children:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ required:
+ - children
+ - dataset
+ - id
+ - inference
+ - is_a_prior
+ - model
+ - name
+ - parameters
+ - time_variable
+ LogLikelihoodParameter:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ name:
+ type: string
+ description: name of log_likelihood parameter.
+ maxLength: 100
+ parent_index:
+ type: integer
+ nullable: true
+ description: parameter index for distribution and equation parameters. blank
+ for models (variable is used instead)
+ child_index:
+ type: integer
+ description: 'output index for all log_likelihoods. '
+ length:
+ type: integer
+ nullable: true
+ description: length of array representing parameter. null for scalar
+ parent:
+ type: integer
+ readOnly: true
+ child:
+ type: integer
+ variable:
+ type: integer
+ nullable: true
+ description: input model variable for this parameter.
+ required:
+ - child
+ - id
+ - name
+ - parent
+ Monolix:
+ type: object
+ properties:
+ data_csv:
+ type: string
+ format: uri
+ writeOnly: true
+ model_txt:
+ type: string
+ format: uri
+ writeOnly: true
+ project_mlxtran:
+ type: string
+ format: uri
+ writeOnly: true
+ data:
+ type: string
+ readOnly: true
+ pd_model:
+ type: string
+ readOnly: true
+ pk_model:
+ type: string
+ readOnly: true
+ required:
+ - data
+ - data_csv
+ - model_txt
+ - pd_model
+ - pk_model
+ - project_mlxtran
+ PatchedAlgorithm:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ name:
+ type: string
+ description: name of the algorithm
+ maxLength: 100
+ category:
+ $ref: '#/components/schemas/CategoryEnum'
+ PatchedBiomarkerType:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ data:
+ type: object
+ additionalProperties:
+ type: array
+ items: {}
+ nullable: true
+ readOnly: true
+ is_continuous:
+ type: boolean
+ readOnly: true
+ is_categorical:
+ type: boolean
+ readOnly: true
+ name:
+ type: string
+ description: name of the biomarker type
+ maxLength: 100
+ description:
+ type: string
+ nullable: true
+ description: short description of the biomarker type
+ display:
+ type: boolean
+ description: True if this biomarker type will be displayed in the frontend,
+ False otherwise
+ color:
+ type: integer
+ description: Color index associated with this biomarker type. For plotting
+ purposes in the frontend
+ axis:
+ type: boolean
+ description: True/False if biomarker type displayed on LHS/RHS axis
+ stored_unit:
+ type: integer
+ description: unit for the value stored in :model:`pkpdapp.Biomarker`
+ dataset:
+ type: integer
+ description: dataset containing this biomarker measurement
+ display_unit:
+ type: integer
+ description: unit to use when sending or displaying biomarker values
+ stored_time_unit:
+ type: integer
+ description: unit for the time values stored in :model:`pkpdapp.Biomarker`
+ display_time_unit:
+ type: integer
+ description: unit to use when sending or displaying time values
+ PatchedCompound:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ efficacy_experiments:
+ type: array
+ items:
+ $ref: '#/components/schemas/Efficacy'
+ name:
+ type: string
+ description: name of the compound
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the compound
+ molecular_mass:
+ type: number
+ format: double
+ description: molecular mass for compound for conversion from mol to grams
+ compound_type:
+ $ref: '#/components/schemas/CompoundTypeEnum'
+ fraction_unbound_plasma:
+ type: number
+ format: double
+ nullable: true
+ description: fraction unbound plasma (unitless)
+ blood_to_plasma_ratio:
+ type: number
+ format: double
+ nullable: true
+ description: blood to plasma ratio (unitless)
+ intrinsic_clearence:
+ type: number
+ format: double
+ nullable: true
+ description: intrinsic clearance
+ intrinsic_clearence_assay:
+ $ref: '#/components/schemas/IntrinsicClearenceAssayEnum'
+ fraction_unbound_including_cells:
+ type: number
+ format: double
+ nullable: true
+ description: fraction unbound in plasma and red blood cells (unitless)
+ target_concentration:
+ type: number
+ format: double
+ nullable: true
+ description: target concentration
+ dissociation_constant:
+ type: number
+ format: double
+ nullable: true
+ description: dissociation constant
+ calculate_receptor_occupancy:
+ type: boolean
+ description: calculate receptor occupancy
+ is_soluble:
+ type: boolean
+ description: is the compound target soluble
+ molecular_mass_unit:
+ type: integer
+ description: unit for molecular mass (e.g. g/mol)
+ intrinsic_clearence_unit:
+ type: integer
+ description: unit for intrinsic clearance
+ target_concentration_unit:
+ type: integer
+ description: unit for target concentration
+ dissociation_unit:
+ type: integer
+ description: unit for dissociation constant
+ PatchedDataset:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ biomarker_types:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ subjects:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ protocols:
+ type: array
+ items:
+ $ref: '#/components/schemas/Protocol'
+ readOnly: true
+ name:
+ type: string
+ description: name of the dataset
+ maxLength: 100
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: date/time the experiment was conducted. All time measurements
+ are relative to this date/time, which is in YYYY-MM-DD HH:MM:SS format.
+ For example, 2020-07-18 14:30:59
+ description:
+ type: string
+ description: short description of the dataset
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ PatchedDose:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ start_time:
+ type: number
+ format: double
+ description: starting time point of dose, see protocol for units
+ amount:
+ type: number
+ format: double
+ description: amount of compound administered over the duration, see protocol
+ for units. Rate of administration is assumed constant
+ duration:
+ type: number
+ format: double
+ description: Duration of dose administration, see protocol for units. Duration
+ must be greater than 0.
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ protocol:
+ type: integer
+ description: protocol containing this dose
+ PatchedDosedPharmacokinetic:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ mappings:
+ type: array
+ items:
+ $ref: '#/components/schemas/PkpdMapping'
+ components:
+ type: string
+ readOnly: true
+ variables:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ mmt:
+ type: string
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ dose_compartment:
+ type: string
+ nullable: true
+ description: compartment name to be dosed
+ maxLength: 100
+ time_max:
+ type: number
+ format: double
+ description: suggested time to simulate after the last dose (in the time
+ units specified by the mmt model)
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ pk_model:
+ type: integer
+ nullable: true
+ description: model
+ pd_model:
+ type: integer
+ nullable: true
+ description: PD part of model
+ protocol:
+ type: integer
+ nullable: true
+ description: dosing protocol
+ PatchedInference:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ log_likelihoods:
+ type: array
+ items:
+ $ref: '#/components/schemas/LogLikelihood'
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the dataset
+ maxLength: 100
+ description:
+ type: string
+ description: short description of what this inference does
+ initialization_strategy:
+ $ref: '#/components/schemas/InitializationStrategyEnum'
+ number_of_chains:
+ type: integer
+ description: number of chains
+ max_number_of_iterations:
+ type: integer
+ description: maximum number of iterations
+ burn_in:
+ type: integer
+ description: final iteration of burn-in
+ number_of_iterations:
+ type: integer
+ description: number of iterations calculated
+ time_elapsed:
+ type: integer
+ description: Elapsed run time for inference in seconds
+ number_of_function_evals:
+ type: integer
+ description: number of function evaluations
+ task_id:
+ type: string
+ nullable: true
+ description: If executing, this is the celery task id
+ maxLength: 40
+ metadata:
+ type: object
+ additionalProperties: {}
+ description: metadata for inference
+ project:
+ type: integer
+ description: Project that "owns" this inference object
+ algorithm:
+ type: integer
+ description: algorithm used to perform the inference
+ initialization_inference:
+ type: integer
+ nullable: true
+ PatchedInferenceChain:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ data:
+ type: string
+ readOnly: true
+ outputs:
+ type: string
+ readOnly: true
+ inference:
+ type: integer
+ description: inference for this chain
+ PatchedPharmacodynamic:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ components:
+ type: string
+ readOnly: true
+ variables:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ mmt:
+ type: string
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the model
+ time_max:
+ type: number
+ format: double
+ description: suggested maximum time to simulate for this model (in the time
+ units specified by the mmt model)
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ PatchedPharmacokinetic:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the model
+ mmt:
+ type: string
+ description: the model represented using mmt (see https://myokit.readthedocs)
+ time_max:
+ type: number
+ format: double
+ description: suggested maximum time to simulate for this model (in the time
+ units specified by the mmt model)
+ PatchedProject:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ user_access:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectAccess'
+ name:
+ type: string
+ description: name of the project
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the project
+ compound:
+ type: integer
+ users:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ description: users with access to this project
+ PatchedProjectAccess:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: True if user has read access only
+ user:
+ type: integer
+ project:
+ type: integer
+ readOnly: true
+ PatchedProtocol:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ doses:
+ type: array
+ items:
+ $ref: '#/components/schemas/Dose'
+ readOnly: true
+ dose_ids:
+ type: array
+ items:
+ type: integer
+ writeOnly: true
+ writeOnly: true
+ dosed_pk_models:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ dataset:
+ type: string
+ readOnly: true
+ subjects:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the protocol
+ maxLength: 100
+ dose_type:
+ $ref: '#/components/schemas/DoseTypeEnum'
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this protocol.
+ compound:
+ type: integer
+ nullable: true
+ description: drug compound
+ time_unit:
+ type: integer
+ nullable: true
+ description: unit for the start_time and duration values stored in each
+ dose
+ amount_unit:
+ type: integer
+ nullable: true
+ description: unit for the amount value stored in each dose
+ PatchedSubject:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ id_in_dataset:
+ type: integer
+ description: unique id in the dataset
+ shape:
+ type: integer
+ description: Shape index associated with this subject. For plotting purposes
+ in the frontend
+ display:
+ type: boolean
+ description: True if this subject will be displayed in the frontend, False
+ otherwise
+ metadata:
+ type: string
+ description: subject metadata
+ dataset:
+ type: integer
+ description: dataset containing this subject
+ protocol:
+ type: integer
+ nullable: true
+ description: dosing protocol for this subject.
+ PatchedUnit:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ compatible_units:
+ type: array
+ items:
+ type: object
+ additionalProperties:
+ type: string
+ readOnly: true
+ symbol:
+ type: string
+ description: symbol for unit display
+ maxLength: 50
+ g:
+ type: number
+ format: double
+ description: grams exponent
+ m:
+ type: number
+ format: double
+ description: meters exponent
+ s:
+ type: number
+ format: double
+ description: seconds exponent
+ A:
+ type: number
+ format: double
+ description: ampere exponent
+ K:
+ type: number
+ format: double
+ description: kelvin exponent
+ cd:
+ type: number
+ format: double
+ description: candela exponent
+ mol:
+ type: number
+ format: double
+ description: mole exponent
+ multiplier:
+ type: number
+ format: double
+ description: multiplier in powers of 10
+ PatchedUser:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ username:
+ type: string
+ description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
+ only.
+ pattern: ^[\w.@+-]+$
+ maxLength: 150
+ first_name:
+ type: string
+ maxLength: 150
+ last_name:
+ type: string
+ maxLength: 150
+ email:
+ type: string
+ format: email
+ title: Email address
+ maxLength: 254
+ profile:
+ allOf:
+ - $ref: '#/components/schemas/Profile'
+ readOnly: true
+ project_set:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ PatchedVariable:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ is_public:
+ type: boolean
+ lower_bound:
+ type: number
+ format: double
+ description: lowest possible value for this variable
+ upper_bound:
+ type: number
+ format: double
+ description: largest possible value for this variable
+ default_value:
+ type: number
+ format: double
+ description: default value for this variable
+ is_log:
+ type: boolean
+ description: True if default_value is stored as the log of this value
+ name:
+ type: string
+ description: name of the variable
+ maxLength: 100
+ binding:
+ type: string
+ nullable: true
+ description: myokit binding of the variable (e.g. time)
+ maxLength: 100
+ qname:
+ type: string
+ description: fully qualitifed name of the variable
+ maxLength: 200
+ constant:
+ type: boolean
+ description: True for a constant variable of the model, i.e. a parameter.
+ False if non-constant, i.e. an output of the model (default is True)
+ state:
+ type: boolean
+ description: True if it is a state variable of the model and has an initial
+ condition parameter (default is False)
+ color:
+ type: integer
+ description: Color index associated with this variable. For display purposes
+ in the frontend
+ display:
+ type: boolean
+ description: True if this variable will be displayed in the frontend, False
+ otherwise
+ axis:
+ type: boolean
+ description: False/True if biomarker type displayed on LHS/RHS axis
+ unit:
+ type: integer
+ nullable: true
+ description: variable values are in this unit (note this might be different
+ from the unit in the stored sbml)
+ pd_model:
+ type: integer
+ nullable: true
+ description: pharmacodynamic model
+ pk_model:
+ type: integer
+ nullable: true
+ description: pharmacokinetic model
+ dosed_pk_model:
+ type: integer
+ nullable: true
+ description: dosed pharmacokinetic model
+ Pharmacodynamic:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ components:
+ type: string
+ readOnly: true
+ variables:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ mmt:
+ type: string
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the model
+ time_max:
+ type: number
+ format: double
+ description: suggested maximum time to simulate for this model (in the time
+ units specified by the mmt model)
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this model
+ required:
+ - components
+ - id
+ - name
+ - variables
+ PharmacodynamicSbml:
+ type: object
+ properties:
+ sbml:
+ type: string
+ writeOnly: true
+ required:
+ - sbml
+ Pharmacokinetic:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the model
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the model
+ mmt:
+ type: string
+ description: the model represented using mmt (see https://myokit.readthedocs)
+ time_max:
+ type: number
+ format: double
+ description: suggested maximum time to simulate for this model (in the time
+ units specified by the mmt model)
+ required:
+ - id
+ - name
+ PkpdMapping:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ datetime:
+ type: string
+ format: date
+ readOnly: true
+ read_only:
+ type: boolean
+ readOnly: true
+ pkpd_model:
+ type: integer
+ description: PKPD model that this mapping is for
+ pk_variable:
+ type: integer
+ description: variable in PK part of model
+ pd_variable:
+ type: integer
+ description: variable in PD part of model
+ required:
+ - datetime
+ - id
+ - pd_variable
+ - pk_variable
+ - pkpd_model
+ - read_only
+ Profile:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ user:
+ type: integer
+ required:
+ - id
+ - user
+ Project:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ user_access:
+ type: array
+ items:
+ $ref: '#/components/schemas/ProjectAccess'
+ name:
+ type: string
+ description: name of the project
+ maxLength: 100
+ description:
+ type: string
+ description: short description of the project
+ compound:
+ type: integer
+ users:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ description: users with access to this project
+ required:
+ - compound
+ - id
+ - name
+ - user_access
+ - users
+ ProjectAccess:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: True if user has read access only
+ user:
+ type: integer
+ project:
+ type: integer
+ readOnly: true
+ required:
+ - id
+ - project
+ - user
+ Protocol:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ doses:
+ type: array
+ items:
+ $ref: '#/components/schemas/Dose'
+ readOnly: true
+ dose_ids:
+ type: array
+ items:
+ type: integer
+ writeOnly: true
+ writeOnly: true
+ dosed_pk_models:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ dataset:
+ type: string
+ readOnly: true
+ subjects:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ name:
+ type: string
+ description: name of the protocol
+ maxLength: 100
+ dose_type:
+ $ref: '#/components/schemas/DoseTypeEnum'
+ project:
+ type: integer
+ nullable: true
+ description: Project that "owns" this protocol.
+ compound:
+ type: integer
+ nullable: true
+ description: drug compound
+ time_unit:
+ type: integer
+ nullable: true
+ description: unit for the start_time and duration values stored in each
+ dose
+ amount_unit:
+ type: integer
+ nullable: true
+ description: unit for the amount value stored in each dose
+ required:
+ - dataset
+ - dose_ids
+ - dosed_pk_models
+ - doses
+ - id
+ - name
+ - subjects
+ Subject:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ id_in_dataset:
+ type: integer
+ description: unique id in the dataset
+ shape:
+ type: integer
+ description: Shape index associated with this subject. For plotting purposes
+ in the frontend
+ display:
+ type: boolean
+ description: True if this subject will be displayed in the frontend, False
+ otherwise
+ metadata:
+ type: string
+ description: subject metadata
+ dataset:
+ type: integer
+ description: dataset containing this subject
+ protocol:
+ type: integer
+ nullable: true
+ description: dosing protocol for this subject.
+ required:
+ - dataset
+ - id
+ - id_in_dataset
+ Unit:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ compatible_units:
+ type: array
+ items:
+ type: object
+ additionalProperties:
+ type: string
+ readOnly: true
+ symbol:
+ type: string
+ description: symbol for unit display
+ maxLength: 50
+ g:
+ type: number
+ format: double
+ description: grams exponent
+ m:
+ type: number
+ format: double
+ description: meters exponent
+ s:
+ type: number
+ format: double
+ description: seconds exponent
+ A:
+ type: number
+ format: double
+ description: ampere exponent
+ K:
+ type: number
+ format: double
+ description: kelvin exponent
+ cd:
+ type: number
+ format: double
+ description: candela exponent
+ mol:
+ type: number
+ format: double
+ description: mole exponent
+ multiplier:
+ type: number
+ format: double
+ description: multiplier in powers of 10
+ required:
+ - compatible_units
+ - id
+ - symbol
+ User:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ username:
+ type: string
+ description: Required. 150 characters or fewer. Letters, digits and @/./+/-/_
+ only.
+ pattern: ^[\w.@+-]+$
+ maxLength: 150
+ first_name:
+ type: string
+ maxLength: 150
+ last_name:
+ type: string
+ maxLength: 150
+ email:
+ type: string
+ format: email
+ title: Email address
+ maxLength: 254
+ profile:
+ allOf:
+ - $ref: '#/components/schemas/Profile'
+ readOnly: true
+ project_set:
+ type: array
+ items:
+ type: integer
+ readOnly: true
+ required:
+ - id
+ - profile
+ - project_set
+ - username
+ Variable:
+ type: object
+ properties:
+ id:
+ type: integer
+ readOnly: true
+ read_only:
+ type: boolean
+ description: true if object has been stored
+ datetime:
+ type: string
+ format: date-time
+ nullable: true
+ description: datetime the object was stored.
+ is_public:
+ type: boolean
+ lower_bound:
+ type: number
+ format: double
+ description: lowest possible value for this variable
+ upper_bound:
+ type: number
+ format: double
+ description: largest possible value for this variable
+ default_value:
+ type: number
+ format: double
+ description: default value for this variable
+ is_log:
+ type: boolean
+ description: True if default_value is stored as the log of this value
+ name:
+ type: string
+ description: name of the variable
+ maxLength: 100
+ binding:
+ type: string
+ nullable: true
+ description: myokit binding of the variable (e.g. time)
+ maxLength: 100
+ qname:
+ type: string
+ description: fully qualitifed name of the variable
+ maxLength: 200
+ constant:
+ type: boolean
+ description: True for a constant variable of the model, i.e. a parameter.
+ False if non-constant, i.e. an output of the model (default is True)
+ state:
+ type: boolean
+ description: True if it is a state variable of the model and has an initial
+ condition parameter (default is False)
+ color:
+ type: integer
+ description: Color index associated with this variable. For display purposes
+ in the frontend
+ display:
+ type: boolean
+ description: True if this variable will be displayed in the frontend, False
+ otherwise
+ axis:
+ type: boolean
+ description: False/True if biomarker type displayed on LHS/RHS axis
+ unit:
+ type: integer
+ nullable: true
+ description: variable values are in this unit (note this might be different
+ from the unit in the stored sbml)
+ pd_model:
+ type: integer
+ nullable: true
+ description: pharmacodynamic model
+ pk_model:
+ type: integer
+ nullable: true
+ description: pharmacokinetic model
+ dosed_pk_model:
+ type: integer
+ nullable: true
+ description: dosed pharmacokinetic model
+ required:
+ - id
+ - name
+ - qname
+ securitySchemes:
+ basicAuth:
+ type: http
+ scheme: basic
+ cookieAuth:
+ type: apiKey
+ in: cookie
+ name: sessionid
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 00000000..d9b14896
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,27 @@
+gunicorn
+Django==3.2.19
+setuptools<=65.5.1
+django-cors-headers>=3.7.0
+dpd-static-support>=0.0.5
+pandas>=1.0
+whitenoise>=5.0.1
+docutils>=0.16
+python-markdown-math>=0.8
+pints @ git+https://github.com/pints-team/pints@i1403-multi-outputs#egg=pints
+myokit @ git+https://github.com/MichaelClerx/myokit@main#egg=myokit
+django-extensions>=3.1.1
+jsonfield>=3.1.0
+djangorestframework>=3.12.4
+djoser>=2.1.0
+python-memcached>=1.16.0
+psycopg2-binary>=2.9.1
+dj-database-url>=0.5.0
+django-polymorphic>=3.1.0
+drf-writable-nested>=0.6.3
+celery>=5.1.2
+tdigest>=0.5.2.2
+pymc3>=3.11.5
+django-auth-ldap>=4.1.0
+pyyaml>=6.0.0
+drf-spectacular>=0.26.2
+openpyxl>=3.1.2
\ No newline at end of file
diff --git a/run-tests.py b/run-tests.py
new file mode 100644
index 00000000..051e0c58
--- /dev/null
+++ b/run-tests.py
@@ -0,0 +1,91 @@
+#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#
+# This file has been adapted from PINTS (https://github.com/pints-team/pints/)
+# which is released under the BSD 3-clause license.
+#
+
+from __future__ import absolute_import, division
+from __future__ import print_function, unicode_literals
+import argparse
+import datetime
+import os
+import sys
+
+
+def run_copyright_checks():
+ """
+ Checks that the copyright year in LICENSE.md is up-to-date and that each
+ file contains the copyright header
+ """
+ print('\nChecking that copyright is up-to-date and complete.')
+
+ year_check = True
+ current_year = str(datetime.datetime.now().year)
+
+ with open('LICENSE.md', 'r') as license_file:
+ license_text = license_file.read()
+ if 'Copyright (c) ' + current_year in license_text:
+ print("Copyright notice in LICENSE.md is up-to-date.")
+ else:
+ print('Copyright notice in LICENSE.md is NOT up-to-date.')
+ year_check = False
+
+ # Recursively walk the pkpd directory and check copyright header is in
+ # each checked file type
+ header_check = True
+ checked_file_types = ['.py']
+ copyright_header = """#
+# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
+# is released under the BSD 3-clause license. See accompanying LICENSE.md for
+# copyright notice and full license details.
+#"""
+
+ for dirname, _, file_list in os.walk('pkpdapp'):
+ for f_name in file_list:
+ if any([f_name.endswith(x) for x in checked_file_types]):
+ path = os.path.join(dirname, f_name)
+ with open(path, 'r') as f:
+ if copyright_header not in f.read():
+ print('Copyright blurb missing from ' + path)
+ header_check = False
+
+ if header_check:
+ print('All files contain copyright header.')
+
+ if not year_check or not header_check:
+ print('FAILED')
+ sys.exit(1)
+
+
+if __name__ == '__main__':
+ # Set up argument parsing
+ parser = argparse.ArgumentParser(
+ description='Run tests for PKPDApp.',
+ # TODO:
+ epilog='To run individual unit tests, use e.g.'
+ ' $ pkpd/tests/test_toy_logistic_model.py',
+ )
+
+ # Copyright checks
+ parser.add_argument(
+ '--copyright',
+ action='store_true',
+ help='Check copyright runs to the current year',)
+
+ # Parse!
+ args = parser.parse_args()
+
+ # Run tests
+ has_run = False
+
+ # Copyright checks
+ if args.copyright:
+ has_run = True
+ run_copyright_checks()
+
+ # Help
+ if not has_run:
+ parser.print_help()
diff --git a/start-server.sh b/start-server.sh
new file mode 100755
index 00000000..7ec74e43
--- /dev/null
+++ b/start-server.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+# start-server.sh
+if [ -n "$DJANGO_SUPERUSER_USERNAME" ] && [ -n "$DJANGO_SUPERUSER_PASSWORD" ] ; then
+ (python manage.py createsuperuser --no-input)
+fi
+(python manage.py migrate --no-input)
+(celery -A pkpdapp worker --loglevel=INFO) &
+(gunicorn pkpdapp.wsgi:application --bind unix:/run/gunicorn.socket --workers 3) &
+nginx -g "daemon off;"