commit a6beb1261ff31b662e136d80c5d235572e074f16 Author: Anthony Lawn Date: Thu Feb 16 20:14:05 2023 -0600 Initial commit diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..a881f38 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,36 @@ +require("@rushstack/eslint-patch/modern-module-resolution"); + +module.exports = { + root: true, + env: { + node: true + }, + extends: [ + "plugin:vue/vue3-essential", + "@vue/eslint-config-typescript/recommended", + "@vue/eslint-config-prettier" + ], + parserOptions: { + ecmaVersion: 2020, + project: "tsconfig.json" + }, + ignorePatterns: ["src/lib"], + rules: { + "no-console": process.env.NODE_ENV === "production" ? "warn" : "off", + "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off", + "vue/script-setup-uses-vars": "warn", + "vue/no-mutating-props": "off", + "vue/multi-word-component-names": "off", + "@typescript-eslint/strict-boolean-expressions": [ + "error", + { + allowNullableObject: true, + allowNullableBoolean: true + } + ] + }, + globals: { + defineProps: "readonly", + defineEmits: "readonly" + } +}; diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..f4210ed --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,25 @@ +name: Build and Deploy +on: + push: + branches: + - 'main' +jobs: + build-and-deploy: + if: github.repository != 'profectus-engine/Profectus' # Don't build placeholder mod on main repo + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Install and Build 🔧 # This example project is built using npm and outputs the result to the 'build' folder. Replace with the commands required to build your project, or remove this step entirely if your site is pre-built. + run: | + npm ci + npm run build + + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@v4.2.5 + with: + branch: gh-pages # The branch the action should deploy to. + folder: dist # The folder the action should deploy. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..c6b970d --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,21 @@ +name: Build and Deploy +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Use Node.js 16.x + uses: actions/setup-node@v3 + with: + node-version: 16.x + - run: npm ci + - run: npm run build --if-present + - run: npm test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..403adbc --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +.DS_Store +node_modules +/dist + + +# local env files +.env.local +.env.*.local + +# Log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Editor directories and files +.idea +.vscode +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..008a2f9 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "arrowParens": "avoid", + "endOfLine": "auto", + "printWidth": 100, + "tabWidth": 4, + "trailingComma": "none" +} diff --git a/.replit b/.replit new file mode 100644 index 0000000..89785c6 --- /dev/null +++ b/.replit @@ -0,0 +1,13 @@ +run = "npm install; npm run dev" + +[packager] +language = "nodejs" + [packager.features] + packageSearch = true + guessImports = false + +[languages.javascript] +pattern = "**/{*.js,*.jsx,*.ts,*.tsx}" + + [languages.javascript.languageServer] + start = [ "typescript-language-server", "--stdio" ] diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..28c8581 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,23 @@ +{ + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "pwa-node", + "request": "launch", + "name": "Debug Current Test File", + "autoAttachChildProcesses": true, + "skipFiles": [ + "/**", + "**/node_modules/**" + ], + "program": "${workspaceRoot}/node_modules/vitest/vitest.mjs", + "args": [ + "run", + "${relativeFile}" + ], + "smartStep": true, + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..d46602a --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,12 @@ +{ + "vitest.commandLine": "npx vitest", + "editor.codeActionsOnSave": { + "source.fixAll.eslint": true + }, + "editor.defaultFormatter": "esbenp.prettier-vscode", + "git.ignoreLimitWarning": true, + "[typescriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "typescript.tsdk": "node_modules/typescript/lib" +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b982041 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,322 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [0.5.2] - 2022-08-22 +### Added +- onLoad event +- fontsLoaded event +- Dismissable notification you can add to VueFeatures when they're interactable +- Option on exponential modifiers to better support numbers less than 1 +- Utility function to track if a VueFeature is being hovered over +- Utility to unwrap Resources that may be in refs +- Utility to join JSX elements together with a joiner +- Type for converting readonly string arrays into a union of string values +### Changed +- The main and prestige layers no longer use arrow functions for their options functions +- Modifiers are now lazily loaded +- Collapsible modifier sections are now lazily loaded +- Converted several refs into shallow refs for improved performance +- Roboto Mono and Material Icons fonts are now bundled instead of downloaded from the web, so they work with PWAs +- Node bounds are now updated whenever that context has a node removed or added, fixing many issues with incorrect bounds +### Fixed +- trackResetTime not updating +- colorText prepending $s +- Default .replit config was broken +- Pixi.js canvases no longer rendering +- Node positions being shifted on initial page load due to fonts loading on firefox +- Modifier sections looked wrong if the topmost section wasn't visible + +## [0.5.1] - 2022-07-17 +### Added +- Notif component that displays a jumping exclamation point +- showAmount boolean to buyable displays +- Tab families now take option to style the tab buttons container +- Utility for creating text of a certain color +### Changed +- Improved typing of player.layers +- Improved typing of createCollapsibleModifierSections's parameters +- Made Particles vue component typed as GenericComponent due to issues generating documentation +- Minimized how much of pixi.js is included in the built site +- Split bundles into smaller bundles for faster loading +- Updated TypeScript +- Descriptions on buyables are now optional +- Improved tooltips performance +- Improved how MainDisplay displays effect strings +- MainDisplays are now sticky +- processComputable now binds uncached functions as well +### Fixed +- trackResetTime stopped working once its layer was removed and re-added +- Runtime compilation was disabled in vite config +- Websites had to be hosted on root directory to have assets load correctly +- Tooltips' persistent ref was lazily created +- In some situations Links would not update its bounding rect +- Achievements' and milestones' onComplete callbacks were firing on load +- Processed JSXFunctions were not considered coercable components by isCoercableComponent +- Error from passing in overlay text to bar component +### Removed +- lodash.cloneDeep dependency, which hasn't been used in awhile +- Some unused configs from vue-cli-service +### Documented +- Update vitepress, and updated the content of many pages +- Rest of /game +- Rest of /data +- layers.tsx +- Any type augmentations to Window object +- Various cleanup of docs comments +- Fixed doc generation being broken from switch to vite +### Tests +- Switched from jest to vitest + +## [0.5.0] - 2022-06-27 +### Added +- Projects now cache for offline play, and show notification when an update is available +- Projects can now be "installed" as a Progressive Web App +- Conversions can now be given a custom spend function, which defaults to setting the base resource amount to 0 +- Components for displaying Floor and Square Root symbols +### Changed +- **BREAKING** Several projInfo properties now default to empty strings, to prevent things like reusing project IDs +- **BREAKING** Replaced vue-cli-service with vite (should not break most projects) +- Updated dependencies +- Made all type-only imports explicit +- setupPassiveGeneration now works properly on independent conversions +- setupPassiveGeneration now takes an option cap it can't go over +- Improved typing for PlayerData.layers +- Options Functions have an improved `this` type - it now includes the options themselves +- Removed v-show being used in data/common.tsx +### Tests +- Implement Jest, and running tests automatically on push +- Tests written for utils/common.ts + +## [0.4.2] - 2022-05-23 +### Added +- costModifier to conversions +- onConvert(amountGained) to conversions +### Changed +- **BREAKING** getFirstFeature has a new signature, that will lead to improved performance +- trackResetTime is now intended to be used with a reset button +- regularFormat handles small numbers better +- Slider tooltips now appear below the slider, not above +- Node's mutation observers now ignore attributes. This shouldn't have issues with links/particle effect positions, but prevents a _lot_ of unnecessary node updates +- OptionsFunc no longer takes its S type parameter, as it was unnecessary. Layer options functions now have proper `this` typing + - Several functions have been updated to take BaseLayer instead of GenericLayer, to allow them to work with `this` inside layer options functions +### Fixed +- Particle effects and links would not always appear on reload or when switching layers +- Particle effects and links no longer appear in wrong spot after nodes are added or removed +- Collapsibles having wrong widths on the button and collapsed content sections +- Additive modifiers with negative values appeared like "+-" instead of "-" +- Buyables' onPurchase was not being called +- Reset button would display "Next:" if the buyMax property is a ref + +## [0.4.1] - 2022-05-10 +### Added +- findFeatures can now accept multiple feature types +- excludeFeatures can now be used to find features with a feature type _blacklist_ +- All the icons in the saves manager now have tooltips +### Changed +- All touch events that can be passive now are +- Layers' style and classes attributes are now applied to the tab element rather than the layer-tab +- Saving now always uses lz-string, and saveEncoding has been renamed to exportEncoding + - The property will now only affect exports, and defaults to base64 so exports can be shared in more places without issues +- Buyables can now have their onClick/purchase function overwritten +### Fixed +- Arrays in player were not being wrapped in proxies for things like NaN detection +- Error when switching between saves with different layers +- Links would sometimes error from trying to use nodes that were removed earlier that frame +- createModifierSection would require modifiers to have revert and enabled properties despite not using them +- Tab buttons would not use the style property if it was a ref +- Typings on the Board vue component were incorrect +- Offline time would always show, if offlineLimit is set to 0 +- Buyables will now call onPurchase() when cost and/or resource were not set +- Presets dropdown wouldn't deselect the option after creating the save +### Documented +- feature.ts + +## [0.4.0] - 2022-05-01 +### Added +- Saves can now be encoded in two new options: plaintext and lz compressed, determined by a new "saveEncoding" property in projInfo + - Saves will be loaded in whatever format is detected. The setting only applies when writing saves +- createModifierSection has new parameter to override the label used for the base value +- createCollapsibleModifierSections utility function to display `createModifierSection`s in collapsible forms +### Fixed +- Saves manager would not clear the current save from its cache when switching saves, leading to progress loss if flipping between saves +- Layer.minWidth being ignored +- Separators between tabs (player.tabs) would not extend to the bottom of the screen when scrolling +- Tree nodes not being clicked on their edges +### Changed +- **BREAKING** No features extend persistent anymore + - This will break ALL existing saves that aren't manually dealt with in fixOldSave + - Affected features: Achievement, Buyable, Grid, Infobox, Milestone, TabFamily, and Upgrade + - Affected features will now have a property within them where the persistent ref is stored. This means new persistent refs can now be safely added to these features +- Features with option functions with 0 required properties now don't require passing in an options function +- Improved the look of the goBack and minimize buttons (and made them more consistent with each other) +- Newly created saves are immediately switched to +- TooltipDirection and Direction have been merged into one enum +- Made layers shallow reactive, so it works better with dynamic layers +- Modifier functions all have more explicit types now +- Scaling functions take computables instead of processed computables +### Removed +- Unused tsParticles.d.ts file +### Documented +- modifiers.ts +- conversions.ts + +## [0.3.3] - 2022-04-24 +### Fixed +- Spacing between rows in Tree components +- Computed style attributes on tooltips were ignored +- Tooltips could cause infinite loops due to cyclical dependencies + +## [0.3.2] - 2022-04-23 +### Fixed +- Clickables and several other elements would not register clicks sometimes, if the display is updating rapidly +- createLayerTreeNode wasn't using display option correctly + +## [0.3.1] - 2022-04-23 +### Added +- Render utility methods that always return JSX Elements +### Changed +- **BREAKING** Tooltips overhaul + - Tree Nodes no longer have tooltips related properties + - Tooltips can now be added to any feature with a Vue component using the `addTooltip` function + - Any tooltip can be made pinnable by setting pinnable to true in the addTooltip options, or by passing a `Ref` to a Tooltip component + - Pinned tooltips have an icon to represent that. It can be disabled by setting the theme's `showPin` property to false +- Modifiers are now their own features rather than a part of conversions + - Including utilities to display the current state of all the modifiers +- TabFamilies' options function is now optional +- Layer.minWidth can take string values + - If parseable into a number, it'll have "px" appended. Otherwise it'll be un-processed +- TreeNodes now have Vue components attached to them +- `createResourceTooltip` now shows the resource name +- Made classic and aqua theme's `feature-foreground` color dark rather than light + +## [0.3.0] - 2022-04-10 +### Added +- conversion.currentAt [#4](https://github.com/profectus-engine/Profectus/pull/4) +- OptionsFunc utility type, improving type inferencing in feature types +- minimumGain property to ResetButton, defaulting to 1 +### Changed +- **BREAKING** Major persistence rework + - Removed makePersistent + - Removed old Persistent, and renamed PersistentRef to Persistent + - createLazyProxy now takes optional base object (replacing use cases for makePersistent) + - Added warnings when creating refs outside a layer + - Added warnings when persistent refs aren't included in their layer object +- **BREAKING** createLayer now takes id as the first param, rather than inside the option function +- resetButton now shows "Req:" instead of "Next:" when conversion.buyMax is false +- Conversion nextAt and currentAt now cap at 0 after reverting modifier +### Fixed +- Independent conversion gain calculation [#4](https://github.com/profectus-engine/Profectus/pull/4) +- Persistence issue when loading layer dynamically +- resetButton's gain and requirement display being incorrect when conversion.buyMax is false +- Independent conversions with buyMax false capping incorrectly + +## [0.2.2] - 2022-04-01 +Unironically posting an update on April Fool's Day ;) +### Changed +- **BREAKING** Replaced tsparticles with pixi-emitter. Different options, and behaves differently. +- Print key and value in lazy proxy's setter message +- Update bounding boxes after web fonts load in +### Removed +- safff.txt + +## [0.2.1] - 2022-03-29 +### Changed +- **BREAKING** Reworked conversion.modifyGainAmount into conversion.gainModifier, with several utility functions. This makes nextAt accurate with modified gain +### Fixed +- Made overlay nav not overlap leftmost layer + +## [0.2.0] - 2022-03-27 +### Added +- Particles feature +- Collapsible layout component +- Utility function for splitting off the first from the list of features that meets a given filter +### Changed +- **BREAKING** Reworked most of the code from Links into a generic Context component that manages the positions of features in the DOM +- Updated vue-cli and TS dependencies +- Challenges cannot be started when maxed, and `canStart` now defaults to `true` +- onClick listeners on various features now get passed a MouseEvent or TouchEvent when possible +- Minor style changes to Milestones, most notably removing min-height +### Fixed +- Buyables didn't support CoercableComponents for displays +- TreeNodes would have a double glow effect on hover +### Removed +- Unused mousemove listener attached to App.vue + +## [0.1.4] - 2022-03-13 +### Added +- You can now access this.on() from within a createLayer function (and other BaseLayer properties) +- Support for passing non-persistent refs to createResource +- dontMerge class to allow features to ignore mergeAdjacent +### Fixed +- Clickables would not merge adjacent +- onClick and onHold functions would not be bound to their object when being called +- Refs passed to a components style prop would be ignored +- Fixed z-index issue when stopping hovering over features with .can class + +## [0.1.3] - 2022-03-11 +### Added +- Milestone.complete +- Challenge.complete +- setupAutoClick function to run a clickable's onClick every tick +- setupAutoComplete function to attempt to complete a challenge every tick +- isAnyChallengeActive function to query if any challenge from a given list is active +- Hotkeys now appear in info modal, if any exist +- projInfo.json now includes a "enablePausing" option that can be used to prevent the player from pausing the game +- Added a "gameWon" global event +### Changed +- **BREAKING** Buyables now default to an infinite purchase limit +- **BREAKING** devSpeed, playedTime, offlineTime, and diff now use numbers instead of Decimals +- **BREAKING** Achievements and milestones now use watchEffect to check for completion, instead of polling each tick. shouldEarn properties now only accept functions +- Cached more decimal values for optimization +### Fixed +- Many types not being exported +- setupHoldToClick wouldn't stop clicking after a component is unmounted +- Header's banner would not have correct width +### Removed +- **BREAKING** Removed setupAutoReset +### Documentation +- Support for documentation generation using typedoc +- Hide main layer from docs +- Hide prestige layer from docs +- Use stub declaration files for libs that don't provide types (vue-panzoom and vue-textarea-autosize) + +## [0.1.2] - 2022-03-05 +### Changed +- **BREAKING** Removed "@" path alias, and used baseUrl instead +- **BREAKING** Renamed createExponentialScaling to createPolynomialScaling and removed coefficient parameter +- Changed options passed into createLayerTreeNode; now allows overriding display +- App component is no longer cloned before being passed to `createApp` +- Changed TS version from ^4.5.4 to ~4.5.5 +### Fixed +- Document title is set as soon as possible now + +## [0.1.1] - 2022-03-02 +### Added +- Configuration for Glitch projects +- Configuration for Replit projects +- Hide versionTitle if blank +### Changed +- **BREAKING** Renamed modInfo.json -> projInfo.json +- **BREAKING** Renamed mod.tsx -> projEntry.tsx +- Improved performance of branch drawing code +- Improved performance of formatting numbers +- Changed some projInfo default values to empty strings +- Renamed projInfo.allowSmall -> projInfo.defaultShowSmall +### Fixed +- Spacing on discord logo in NaN screen +- Some files accessing old location for persistence code +- Fixed lint-staged not being listed in devDependencies +- Branch locations were not accurate after scrolling +- Saves Manager displayed "default body" while closing +- Reset buttons activating when held down when canClick is false +- Lifting up on auto clickable elements not stopping the auto clicker +### Removed +- Removed Theme.stackedInfoboxes +- Removed Theme.showSingleTab + +## [0.1.0] - Initial Release diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..01c0262 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Anthony Lawn + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e535eb2 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# Profectus + +A game engine that grows with you + +[![Run on Repl.it](https://repl.it/badge/github/profectus-engine/Profectus)](https://repl.it/github/profectus-engine/Profectus) + +[Read the docs](https://moddingtree.com) + +## Project setup +``` +npm install +``` + +### Hosts dev server and hot-reloads modules as they're changed +``` +npm start +``` + +### Compiles and minifies for production +``` +npm run build +``` + +### Hosts the production build +``` +npm run preview +``` + +### Lints and fixes files +``` +npm run lint +``` + +### Runs the tests using vite-jest +``` +npm run test +``` diff --git a/index.html b/index.html new file mode 100644 index 0000000..9cc3526 --- /dev/null +++ b/index.html @@ -0,0 +1,24 @@ + + + + + + + + + + + + + Profectus + + + + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..7082e7c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,13799 @@ +{ + "name": "profectus", + "version": "0.5.2", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "profectus", + "version": "0.5.2", + "dependencies": { + "@fontsource/material-icons": "^4.5.4", + "@fontsource/roboto-mono": "^4.5.8", + "@pixi/app": "~6.3.2", + "@pixi/constants": "~6.3.2", + "@pixi/core": "~6.3.2", + "@pixi/display": "~6.3.2", + "@pixi/math": "~6.3.2", + "@pixi/particle-emitter": "^5.0.7", + "@pixi/sprite": "~6.3.2", + "@pixi/ticker": "~6.3.2", + "@vitejs/plugin-vue": "^2.3.3", + "@vitejs/plugin-vue-jsx": "^1.3.10", + "is-plain-object": "^5.0.0", + "lz-string": "^1.4.4", + "nanoevents": "^6.0.2", + "vite": "^2.9.12", + "vite-plugin-pwa": "^0.12.0", + "vite-tsconfig-paths": "^3.5.0", + "vue": "^3.2.26", + "vue-next-select": "^2.10.2", + "vue-panzoom": "https://github.com/thepaperpilot/vue-panzoom.git", + "vue-textarea-autosize": "^1.1.1", + "vue-toastification": "^2.0.0-rc.1", + "vue-transition-expand": "^0.1.0", + "vuedraggable": "^4.1.0" + }, + "devDependencies": { + "@ivanv/vue-collapse-transition": "^1.0.2", + "@rushstack/eslint-patch": "^1.1.0", + "@types/lz-string": "^1.3.34", + "@vue/eslint-config-prettier": "^7.0.0", + "@vue/eslint-config-typescript": "^10.0.0", + "eslint": "^8.6.0", + "jsdom": "^20.0.0", + "prettier": "^2.5.1", + "typescript": "^4.7.4", + "vitest": "^0.28.5", + "vue-tsc": "^0.38.1" + }, + "engines": { + "node": "16.x" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "dependencies": { + "@babel/highlight": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", + "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", + "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.10", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helpers": "^7.18.9", + "@babel/parser": "^7.18.10", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.10", + "@babel/types": "^7.18.10", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.18.12", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", + "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==", + "dependencies": { + "@babel/types": "^7.18.10", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", + "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", + "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", + "dependencies": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz", + "integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz", + "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz", + "integrity": "sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==", + "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" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", + "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", + "dependencies": { + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "dependencies": { + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", + "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz", + "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", + "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz", + "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==", + "dependencies": { + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "dependencies": { + "@babel/types": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.11.tgz", + "integrity": "sha512-oBUlbv+rjZLh2Ks9SKi4aL7eKaAXBWleHzU89mP0G6BMUlRxSckk9tSIkgDGydhgFxHuGSlBQZfnaD47oBEB7w==", + "dependencies": { + "@babel/helper-function-name": "^7.18.9", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.11", + "@babel/types": "^7.18.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", + "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", + "dependencies": { + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "dependencies": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz", + "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", + "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz", + "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-proposal-optional-chaining": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz", + "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "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" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", + "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", + "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz", + "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==", + "dependencies": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.18.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", + "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", + "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", + "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", + "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", + "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", + "dependencies": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz", + "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz", + "integrity": "sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", + "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz", + "integrity": "sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", + "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", + "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", + "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", + "dependencies": { + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", + "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", + "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", + "dependencies": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", + "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", + "dependencies": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz", + "integrity": "sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==", + "dependencies": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-identifier": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "dependencies": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz", + "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", + "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", + "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "regenerator-transform": "^0.15.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz", + "integrity": "sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", + "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", + "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.18.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.12.tgz", + "integrity": "sha512-2vjjam0cum0miPkenUbQswKowuxs/NjMwIKEq0zwegRxXk12C9YOF9STXnaUptITOtOJHKHpzvvWYOjbm6tc0w==", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-typescript": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", + "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz", + "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==", + "dependencies": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.18.10", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.18.9", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@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.18.6", + "@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.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.18.9", + "@babel/plugin-transform-classes": "^7.18.9", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.18.9", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.18.6", + "@babel/plugin-transform-modules-commonjs": "^7.18.6", + "@babel/plugin-transform-modules-systemjs": "^7.18.9", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.18.8", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.18.9", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.18.10", + "babel-plugin-polyfill-corejs2": "^0.3.2", + "babel-plugin-polyfill-corejs3": "^0.5.3", + "babel-plugin-polyfill-regenerator": "^0.4.0", + "core-js-compat": "^3.22.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "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" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", + "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz", + "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==", + "dependencies": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.10", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.11", + "@babel/types": "^7.18.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz", + "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==", + "dependencies": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cush/relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@cush/relative/-/relative-1.0.0.tgz", + "integrity": "sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==" + }, + "node_modules/@esbuild/android-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz", + "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz", + "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz", + "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", + "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz", + "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz", + "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz", + "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz", + "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz", + "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz", + "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz", + "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz", + "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz", + "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz", + "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz", + "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz", + "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz", + "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz", + "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz", + "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz", + "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz", + "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz", + "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", + "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "dev": true, + "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" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@fontsource/material-icons": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/@fontsource/material-icons/-/material-icons-4.5.4.tgz", + "integrity": "sha512-YGmXkkEdu6EIgpFKNmB/nIXzZocwSmbI01Ninpmml8x8BT0M6RR++V1KqOfpzZ6Cw/FQ2/KYonQ3x4IY/4VRRA==" + }, + "node_modules/@fontsource/roboto-mono": { + "version": "4.5.8", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-mono/-/roboto-mono-4.5.8.tgz", + "integrity": "sha512-AW44UkbQD0w1CT5mzDbsvhGZ6/bb0YmZzoELj6Sx8vcVEzcbYGUdt2Dtl5zqlOuYMWQFY1mniwWyVv+Bm/lVxw==" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", + "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/gitignore-to-minimatch": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", + "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "node_modules/@ivanv/vue-collapse-transition": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@ivanv/vue-collapse-transition/-/vue-collapse-transition-1.0.2.tgz", + "integrity": "sha512-eWEameFXJM/1khcoKbITvKjYYXDP1WKQ/Xf9ItJVPoEjCiOdocR3AgDAERzDrNNg4oWK28gRGi+0ft8Te27zxw==", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "node_modules/@jridgewell/source-map/node_modules/@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pixi/app": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/app/-/app-6.3.2.tgz", + "integrity": "sha512-V1jnhL92OPiquXtLxUeSZiVDd1mtjRnYpBKA958w29MrIRBx3Y6dgnvsaFZGGWBvSL//WRYV23iZKVL/jRGmmQ==", + "peerDependencies": { + "@pixi/core": "6.3.2", + "@pixi/display": "6.3.2" + } + }, + "node_modules/@pixi/constants": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-6.3.2.tgz", + "integrity": "sha512-sUE8QEJNl4vWUybS0YqpVUBWoOyLkr5bSj1+3mpmbWJTMVmLB2voFXo7XpSNCBlLH1SBN5flcgJlUWOCgNyATg==" + }, + "node_modules/@pixi/core": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/core/-/core-6.3.2.tgz", + "integrity": "sha512-91Fw0CbFpPtMKo5TG1wdaZGgR99lX87l15F7kgge7FM7ZR4EghLiJHU8whQ19f/UNOd8AG7mHD84lUB1VXXfoA==", + "dependencies": { + "@types/offscreencanvas": "^2019.6.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/pixijs" + }, + "peerDependencies": { + "@pixi/constants": "6.3.2", + "@pixi/math": "6.3.2", + "@pixi/runner": "6.3.2", + "@pixi/settings": "6.3.2", + "@pixi/ticker": "6.3.2", + "@pixi/utils": "6.3.2" + } + }, + "node_modules/@pixi/display": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/display/-/display-6.3.2.tgz", + "integrity": "sha512-D+WiM0BcyPK91RYxl7TXXVNz/5lOGs8Q6jtCMcWgTHwCXxWPOHFnNZ4KPJZpUQ7me8Tl2u+c9hfB5Oh1+17r/Q==", + "peerDependencies": { + "@pixi/math": "6.3.2", + "@pixi/settings": "6.3.2", + "@pixi/utils": "6.3.2" + } + }, + "node_modules/@pixi/math": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/math/-/math-6.3.2.tgz", + "integrity": "sha512-REXrCKQaT2shJ3p2Rpq1ZYV4iUeAOUFKnLN2KteQWtB5HQpB8b+w5xBGI+TcnY0FUhx92fbKPYTTvCftNZF4Jw==" + }, + "node_modules/@pixi/particle-emitter": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@pixi/particle-emitter/-/particle-emitter-5.0.7.tgz", + "integrity": "sha512-g0vf+z2pFr+znJEzAii6T7CfMAKsCZuRc8bVY2znJDYxEKoAuU+XuqzHtOkGeR/VuiNCuJhMFLh+BDfXN4Fubw==", + "peerDependencies": { + "@pixi/constants": "^6.0.4", + "@pixi/core": "^6.0.4", + "@pixi/display": "^6.0.4", + "@pixi/math": "^6.0.4", + "@pixi/sprite": "^6.0.4", + "@pixi/ticker": "^6.0.4" + } + }, + "node_modules/@pixi/runner": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-6.3.2.tgz", + "integrity": "sha512-Sspv4VTiV51GwoIg+WudHZHpT3ad5ukW20OLOR+eDOSLbgQEMfj4cTVRg27TvM/QZ/5LxeN3FqwWV+kiWpqCnw==", + "peer": true + }, + "node_modules/@pixi/settings": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-6.3.2.tgz", + "integrity": "sha512-i5cLDUWFnRub3LPa3x7IzkH8MjSwPHyHWzIZKG5t8RiCfbhVfhWGEdKO9AYp8yO/xcf7AqtPK4mikXziL48tXA==", + "peer": true, + "dependencies": { + "ismobilejs": "^1.1.0" + } + }, + "node_modules/@pixi/sprite": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-6.3.2.tgz", + "integrity": "sha512-T1KJ8l2f8Otn6Se6h4b2pz2nrUSe59Pnmj2WIzgBisM245h7dGATs05MisMaLV6Lg/3gTBTxsLBmKsbDSQqbNw==", + "peerDependencies": { + "@pixi/constants": "6.3.2", + "@pixi/core": "6.3.2", + "@pixi/display": "6.3.2", + "@pixi/math": "6.3.2", + "@pixi/settings": "6.3.2", + "@pixi/utils": "6.3.2" + } + }, + "node_modules/@pixi/ticker": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-6.3.2.tgz", + "integrity": "sha512-Au9IO85zCOOCz50aJALFxJ2C8gbgxvD0dSNm7A5FauanJbxDcctIyrW6I51nNyHyeLIUFEkuD2jE/DmcXsXnpw==", + "peerDependencies": { + "@pixi/settings": "6.3.2" + } + }, + "node_modules/@pixi/utils": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-6.3.2.tgz", + "integrity": "sha512-VpB403kfqwXK9w7Qb6ex0aW0g6pWI/t43F2Z8CA/lAfYcN3O0XoxDucvmkLTQWsMtYn+Yf7YhAcLV5SemKwP0A==", + "peer": true, + "dependencies": { + "@types/earcut": "^2.1.0", + "earcut": "^2.2.2", + "eventemitter3": "^3.1.0", + "url": "^0.11.0" + }, + "peerDependencies": { + "@pixi/constants": "6.3.2", + "@pixi/settings": "6.3.2" + } + }, + "node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-babel/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-babel/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "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" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-node-resolve/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-node-resolve/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + }, + "node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/plugin-replace/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/plugin-replace/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + }, + "node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz", + "integrity": "sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==", + "dev": true + }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "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" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "dev": true + }, + "node_modules/@types/chai-subset": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", + "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "dev": true, + "dependencies": { + "@types/chai": "*" + } + }, + "node_modules/@types/earcut": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/earcut/-/earcut-2.1.1.tgz", + "integrity": "sha512-w8oigUCDjElRHRRrMvn/spybSMyX8MTkKA5Dv+tS1IE/TgmNZPqUYtvYBXGY8cieSE66gm+szeK+bnbxC2xHTQ==", + "peer": true + }, + "node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "node_modules/@types/lz-string": { + "version": "1.3.34", + "resolved": "https://registry.npmjs.org/@types/lz-string/-/lz-string-1.3.34.tgz", + "integrity": "sha512-j6G1e8DULJx3ONf6NdR5JiR2ZY3K3PaaqiEuKYkLQO0Czfi1AzrtjfnfCROyWGeDd5IVMKCwsgSmMip9OWijow==", + "dev": true + }, + "node_modules/@types/node": { + "version": "18.7.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.9.tgz", + "integrity": "sha512-0N5Y1XAdcl865nDdjbO0m3T6FdmQ4ijE89/urOHLREyTXbpMWbSafx9y7XIsgWGtwUP2iYTinLyyW3FatAxBLQ==" + }, + "node_modules/@types/offscreencanvas": { + "version": "2019.7.0", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz", + "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==" + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/trusted-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", + "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.1.tgz", + "integrity": "sha512-S1iZIxrTvKkU3+m63YUOxYPKaP+yWDQrdhxTglVDVEVBf+aCSw85+BmJnyUaQQsk5TXFG/LpBu9fa+LrAQ91fQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/type-utils": "5.33.1", + "@typescript-eslint/utils": "5.33.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" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.33.1.tgz", + "integrity": "sha512-IgLLtW7FOzoDlmaMoXdxG8HOCByTBXrB1V2ZQYSEV1ggMmJfAkMWTwUjjzagS6OkfpySyhKFkBw7A9jYmcHpZA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/typescript-estree": "5.33.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.33.1.tgz", + "integrity": "sha512-8ibcZSqy4c5m69QpzJn8XQq9NnqAToC8OdH/W6IXPXv83vRyEDPYLdjAlUx8h/rbusq6MkW4YdQzURGOqsn3CA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/visitor-keys": "5.33.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.33.1.tgz", + "integrity": "sha512-X3pGsJsD8OiqhNa5fim41YtlnyiWMF/eKsEZGsHID2HcDqeSC5yr/uLOeph8rNF2/utwuI0IQoAK3fpoxcLl2g==", + "dev": true, + "dependencies": { + "@typescript-eslint/utils": "5.33.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.33.1.tgz", + "integrity": "sha512-7K6MoQPQh6WVEkMrMW5QOA5FO+BOwzHSNd0j3+BlBwd6vtzfZceJ8xJ7Um2XDi/O3umS8/qDX6jdy2i7CijkwQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.1.tgz", + "integrity": "sha512-JOAzJ4pJ+tHzA2pgsWQi4804XisPHOtbvwUyqsuuq8+y5B5GMZs7lI1xDWs6V2d7gE/Ez5bTGojSK12+IIPtXA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/visitor-keys": "5.33.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.33.1.tgz", + "integrity": "sha512-uphZjkMaZ4fE8CR4dU7BquOV6u0doeQAr8n6cQenl/poMaIyJtBu8eys5uk6u5HiDH01Mj5lzbJ5SfeDz7oqMQ==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/typescript-estree": "5.33.1", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.1.tgz", + "integrity": "sha512-nwIxOK8Z2MPWltLKMLOEZwmfBZReqUdbEoHQXeCpa+sRVARe5twpJGHCB4dk9903Yaf0nMAlGbQfaAH92F60eg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.33.1", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.4.tgz", + "integrity": "sha512-IfFNbtkbIm36O9KB8QodlwwYvTEsJb4Lll4c2IwB3VHc2gie2mSPtSzL0eYay7X2jd/2WX02FjSGTWR6OPr/zg==", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "vite": "^2.5.10", + "vue": "^3.2.25" + } + }, + "node_modules/@vitejs/plugin-vue-jsx": { + "version": "1.3.10", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-1.3.10.tgz", + "integrity": "sha512-Cf5zznh4yNMiEMBfTOztaDVDmK1XXfgxClzOSUVUc8WAmHzogrCUeM8B05ABzuGtg0D1amfng+mUmSIOFGP3Pw==", + "dependencies": { + "@babel/core": "^7.17.9", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.16.8", + "@rollup/pluginutils": "^4.2.0", + "@vue/babel-plugin-jsx": "^1.1.1", + "hash-sum": "^2.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@vitest/expect": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.28.5.tgz", + "integrity": "sha512-gqTZwoUTwepwGIatnw4UKpQfnoyV0Z9Czn9+Lo2/jLIt4/AXLTn+oVZxlQ7Ng8bzcNkR+3DqLJ08kNr8jRmdNQ==", + "dev": true, + "dependencies": { + "@vitest/spy": "0.28.5", + "@vitest/utils": "0.28.5", + "chai": "^4.3.7" + } + }, + "node_modules/@vitest/runner": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.28.5.tgz", + "integrity": "sha512-NKkHtLB+FGjpp5KmneQjTcPLWPTDfB7ie+MmF1PnUBf/tGe2OjGxWyB62ySYZ25EYp9krR5Bw0YPLS/VWh1QiA==", + "dev": true, + "dependencies": { + "@vitest/utils": "0.28.5", + "p-limit": "^4.0.0", + "pathe": "^1.1.0" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/spy": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.28.5.tgz", + "integrity": "sha512-7if6rsHQr9zbmvxN7h+gGh2L9eIIErgf8nSKYDlg07HHimCxp4H6I/X/DPXktVPPLQfiZ1Cw2cbDIx9fSqDjGw==", + "dev": true, + "dependencies": { + "tinyspy": "^1.0.2" + } + }, + "node_modules/@vitest/utils": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.28.5.tgz", + "integrity": "sha512-UyZdYwdULlOa4LTUSwZ+Paz7nBHGTT72jKwdFSV4IjHF1xsokp+CabMdhjvVhYwkLfO88ylJT46YMilnkSARZA==", + "dev": true, + "dependencies": { + "cli-truncate": "^3.1.0", + "diff": "^5.1.0", + "loupe": "^2.3.6", + "picocolors": "^1.0.0", + "pretty-format": "^27.5.1" + } + }, + "node_modules/@volar/code-gen": { + "version": "0.38.9", + "resolved": "https://registry.npmjs.org/@volar/code-gen/-/code-gen-0.38.9.tgz", + "integrity": "sha512-n6LClucfA+37rQeskvh9vDoZV1VvCVNy++MAPKj2dT4FT+Fbmty/SDQqnsEBtdEe6E3OQctFvA/IcKsx3Mns0A==", + "dev": true, + "dependencies": { + "@volar/source-map": "0.38.9" + } + }, + "node_modules/@volar/source-map": { + "version": "0.38.9", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-0.38.9.tgz", + "integrity": "sha512-ba0UFoHDYry+vwKdgkWJ6xlQT+8TFtZg1zj9tSjj4PykW1JZDuM0xplMotLun4h3YOoYfY9K1huY5gvxmrNLIw==", + "dev": true + }, + "node_modules/@volar/vue-code-gen": { + "version": "0.38.9", + "resolved": "https://registry.npmjs.org/@volar/vue-code-gen/-/vue-code-gen-0.38.9.tgz", + "integrity": "sha512-tzj7AoarFBKl7e41MR006ncrEmNPHALuk8aG4WdDIaG387X5//5KhWC5Ff3ZfB2InGSeNT+CVUd74M0gS20rjA==", + "dev": true, + "dependencies": { + "@volar/code-gen": "0.38.9", + "@volar/source-map": "0.38.9", + "@vue/compiler-core": "^3.2.37", + "@vue/compiler-dom": "^3.2.37", + "@vue/shared": "^3.2.37" + } + }, + "node_modules/@volar/vue-typescript": { + "version": "0.38.9", + "resolved": "https://registry.npmjs.org/@volar/vue-typescript/-/vue-typescript-0.38.9.tgz", + "integrity": "sha512-iJMQGU91ADi98u8V1vXd2UBmELDAaeSP0ZJaFjwosClQdKlJQYc6MlxxKfXBZisHqfbhdtrGRyaryulnYtliZw==", + "dev": true, + "dependencies": { + "@volar/code-gen": "0.38.9", + "@volar/source-map": "0.38.9", + "@volar/vue-code-gen": "0.38.9", + "@vue/compiler-sfc": "^3.2.37", + "@vue/reactivity": "^3.2.37" + } + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz", + "integrity": "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==" + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz", + "integrity": "sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==", + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "@vue/babel-helper-vue-transform-on": "^1.0.2", + "camelcase": "^6.0.0", + "html-tags": "^3.1.0", + "svg-tags": "^1.0.0" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.37.tgz", + "integrity": "sha512-81KhEjo7YAOh0vQJoSmAD68wLfYqJvoiD4ulyedzF+OEk/bk6/hx3fTNVfuzugIIaTrOx4PGx6pAiBRe5e9Zmg==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.37", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz", + "integrity": "sha512-yxJLH167fucHKxaqXpYk7x8z7mMEnXOw3G2q62FTkmsvNxu4FQSu5+3UMb+L7fjKa26DEzhrmCxAgFLLIzVfqQ==", + "dependencies": { + "@vue/compiler-core": "3.2.37", + "@vue/shared": "3.2.37" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz", + "integrity": "sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.37", + "@vue/compiler-dom": "3.2.37", + "@vue/compiler-ssr": "3.2.37", + "@vue/reactivity-transform": "3.2.37", + "@vue/shared": "3.2.37", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.37.tgz", + "integrity": "sha512-7mQJD7HdXxQjktmsWp/J67lThEIcxLemz1Vb5I6rYJHR5vI+lON3nPGOH3ubmbvYGt8xEUaAr1j7/tIFWiEOqw==", + "dependencies": { + "@vue/compiler-dom": "3.2.37", + "@vue/shared": "3.2.37" + } + }, + "node_modules/@vue/eslint-config-prettier": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz", + "integrity": "sha512-/CTc6ML3Wta1tCe1gUeO0EYnVXfo3nJXsIhZ8WJr3sov+cGASr6yuiibJTL6lmIBm7GobopToOuB3B6AWyV0Iw==", + "dev": true, + "dependencies": { + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0" + }, + "peerDependencies": { + "eslint": ">= 7.28.0", + "prettier": ">= 2.0.0" + } + }, + "node_modules/@vue/eslint-config-typescript": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-10.0.0.tgz", + "integrity": "sha512-F94cL8ug3FaYXlCfU5/wiGjk1qeadmoBpRGAOBq+qre3Smdupa59dd6ZJrsfRODpsMPyTG7330juMDsUvpZ3Rw==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "vue-eslint-parser": "^8.0.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0", + "eslint-plugin-vue": "^8.0.1" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.37.tgz", + "integrity": "sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A==", + "dependencies": { + "@vue/shared": "3.2.37" + } + }, + "node_modules/@vue/reactivity-transform": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.37.tgz", + "integrity": "sha512-IWopkKEb+8qpu/1eMKVeXrK0NLw9HicGviJzhJDEyfxTR9e1WtpnnbYkJWurX6WwoFP0sz10xQg8yL8lgskAZg==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.37", + "@vue/shared": "3.2.37", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.37.tgz", + "integrity": "sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ==", + "dependencies": { + "@vue/reactivity": "3.2.37", + "@vue/shared": "3.2.37" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.37.tgz", + "integrity": "sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw==", + "dependencies": { + "@vue/runtime-core": "3.2.37", + "@vue/shared": "3.2.37", + "csstype": "^2.6.8" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.37.tgz", + "integrity": "sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA==", + "dependencies": { + "@vue/compiler-ssr": "3.2.37", + "@vue/shared": "3.2.37" + }, + "peerDependencies": { + "vue": "3.2.37" + } + }, + "node_modules/@vue/shared": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.37.tgz", + "integrity": "sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==" + }, + "node_modules/abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "dependencies": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + } + }, + "node_modules/acorn-globals/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/amator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/amator/-/amator-1.1.0.tgz", + "integrity": "sha512-V5+aH8pe+Z3u/UG3L3pG3BaFQGXAyXHVQDroRwjPHdh08bcUEchAVsU1MCuJSCaU5o60wTK6KaE6te5memzgYw==", + "dependencies": { + "bezier-easing": "^2.0.3" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz", + "integrity": "sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==", + "dependencies": { + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.2", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz", + "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.2", + "core-js-compat": "^3.21.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz", + "integrity": "sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/bezier-easing": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz", + "integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig==" + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "peer": true + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "node_modules/browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001380", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001380.tgz", + "integrity": "sha512-OO+pPubxx16lkI7TVrbFpde8XHz66SMwstl1YWpg6uMGw56XnhYVwtPIjvX4kYpzwMwQKr4DDce394E03dQPGg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, + "node_modules/chai": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", + "hasInstallScript": true + }, + "node_modules/core-js-compat": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.24.1.tgz", + "integrity": "sha512-XhdNAGeRnTpp8xbD+sR/HFDK9CbeeeqXT6TuofXh3urqEevzkWmLRgrVoykodsw8okqo2pu1BOmuCKrHx63zdw==", + "dependencies": { + "browserslist": "^4.21.3", + "semver": "7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "peer": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.0.tgz", + "integrity": "sha512-Nv6ENEzyPQ6AItkGwLE2PGKinZZ9g59vSh2BeH6NqPu0OTKZ5ruJsVqh/orbAnqXc9pBbgXAIrc2EyaCj8NpGg==", + "dev": true + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "dev": true, + "dependencies": { + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/earcut": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", + "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", + "peer": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.225", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.225.tgz", + "integrity": "sha512-ICHvGaCIQR3P88uK8aRtx8gmejbVJyC6bB4LEC3anzBrIzdzC7aiZHY4iFfXhN4st6I7lMO0x4sgBHf/7kBvRw==" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/entities": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", + "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==", + "dev": true, + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.54.tgz", + "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==", + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/linux-loong64": "0.14.54", + "esbuild-android-64": "0.14.54", + "esbuild-android-arm64": "0.14.54", + "esbuild-darwin-64": "0.14.54", + "esbuild-darwin-arm64": "0.14.54", + "esbuild-freebsd-64": "0.14.54", + "esbuild-freebsd-arm64": "0.14.54", + "esbuild-linux-32": "0.14.54", + "esbuild-linux-64": "0.14.54", + "esbuild-linux-arm": "0.14.54", + "esbuild-linux-arm64": "0.14.54", + "esbuild-linux-mips64le": "0.14.54", + "esbuild-linux-ppc64le": "0.14.54", + "esbuild-linux-riscv64": "0.14.54", + "esbuild-linux-s390x": "0.14.54", + "esbuild-netbsd-64": "0.14.54", + "esbuild-openbsd-64": "0.14.54", + "esbuild-sunos-64": "0.14.54", + "esbuild-windows-32": "0.14.54", + "esbuild-windows-64": "0.14.54", + "esbuild-windows-arm64": "0.14.54" + } + }, + "node_modules/esbuild-android-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz", + "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-android-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz", + "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz", + "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-darwin-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz", + "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz", + "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-freebsd-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz", + "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-32": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz", + "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz", + "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz", + "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz", + "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-mips64le": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz", + "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-ppc64le": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz", + "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-riscv64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz", + "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-linux-s390x": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz", + "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-netbsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz", + "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-openbsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz", + "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-sunos-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz", + "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-32": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz", + "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz", + "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/esbuild-windows-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz", + "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "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" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.22.0.tgz", + "integrity": "sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==", + "dev": true, + "dependencies": { + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.10.4", + "@humanwhocodes/gitignore-to-minimatch": "^1.0.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.3", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "globby": "^11.1.0", + "grapheme-splitter": "^1.0.4", + "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" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz", + "integrity": "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==", + "dev": true, + "peer": true, + "dependencies": { + "eslint-utils": "^3.0.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.0.1", + "postcss-selector-parser": "^6.0.9", + "semver": "^7.3.5", + "vue-eslint-parser": "^8.0.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-vue/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "peer": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^2.0.0" + }, + "engines": { + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" + } + }, + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.3.tgz", + "integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==", + "dev": true, + "dependencies": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "peer": true + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "node_modules/fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "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" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "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" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fs-extra/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-regex": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/glob-regex/-/glob-regex-0.3.2.tgz", + "integrity": "sha512-m5blUd3/OqDTWwzBBtWBPrGlAzatRywHameHeekAZyZrskYouOGdNB8T/q6JucucvJXtOuyHIn0/Yia7iDasDw==" + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==" + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "node_modules/grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==" + }, + "node_modules/html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "dependencies": { + "whatwg-encoding": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/html-tags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/idb": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.2.tgz", + "integrity": "sha512-jjKrT1EnyZewQ/gCBb/eyiYrhGzws2FeY92Yx8qT9S9GeQAmo4JFVIiWRIfKW/6Ob9A+UDAOW9j9jn58fy2HIg==" + }, + "node_modules/ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "dependencies": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/ismobilejs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz", + "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==", + "peer": true + }, + "node_modules/jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jake/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/jake/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jake/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/jake/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/jake/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jake/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.0.tgz", + "integrity": "sha512-x4a6CKCgx00uCmP+QakBDFXwjAJ69IkkIWHmtmjd3wvXPcdOS44hfX2vqkOQrVrq8l9DhNNADZRXaCEWvgXtVA==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "acorn": "^8.7.1", + "acorn-globals": "^6.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.3.1", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "^7.0.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^3.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.8.0", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "canvas": "^2.5.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonfile/node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/local-pkg": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.2.tgz", + "integrity": "sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "node_modules/loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lz-string": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", + "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "node_modules/mlly": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.1.0.tgz", + "integrity": "sha512-cwzBrBfwGC1gYJyfcy8TcZU1f+dbH/T+TuOhtYP2wLv/Fb51/uV7HJQfBPtEupZ2ORLRU1EKFS/QfS3eo9+kBQ==", + "dev": true, + "dependencies": { + "acorn": "^8.8.1", + "pathe": "^1.0.0", + "pkg-types": "^1.0.1", + "ufo": "^1.0.1" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/nanoevents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/nanoevents/-/nanoevents-6.0.2.tgz", + "integrity": "sha512-FRS2otuFcPPYDPYViNWQ42+1iZqbXydinkRHTHFxrF4a1CpBfmydR9zkI44WSXAXCyPrkcGtPk5CnpW6Y3lFKQ==", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/ngraph.events": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-1.2.2.tgz", + "integrity": "sha512-JsUbEOzANskax+WSYiAPETemLWYXmixuPAlmZmhIbIj6FH/WDgEGCGnRwUQBK0GjOnVm8Ui+e5IJ+5VZ4e32eQ==" + }, + "node_modules/node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "peer": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.1.tgz", + "integrity": "sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg==", + "dev": true + }, + "node_modules/object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/panzoom": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/panzoom/-/panzoom-9.4.3.tgz", + "integrity": "sha512-xaxCpElcRbQsUtIdwlrZA90P90+BHip4Vda2BC8MEb4tkI05PmR6cKECdqUCZ85ZvBHjpI9htJrZBxV5Gp/q/w==", + "dependencies": { + "amator": "^1.1.0", + "ngraph.events": "^1.2.2", + "wheel": "^1.0.0" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse5": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", + "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", + "dev": true, + "dependencies": { + "entities": "^4.3.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz", + "integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-types": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.1.tgz", + "integrity": "sha512-jHv9HB+Ho7dj6ItwppRDDl0iZRYBD0jsakHXtFgoLr+cHSF6xC+QL54sJmWxyGxOLYSHm0afhXhXcQDQqH9z8g==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.0.0", + "pathe": "^1.0.0" + } + }, + "node_modules/postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + } + ], + "dependencies": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "peer": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-bytes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.0.0.tgz", + "integrity": "sha512-6UqkYefdogmzqAZWzJ7laYeJnaXDy2/J+ZqiiMtS7t7OfpXWTlaeGMwX8U6EFvPV/YWWEKRkS8hKS4k60WHTOg==", + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "engines": { + "node": ">=6" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "peer": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "node_modules/recrawl-sync": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/recrawl-sync/-/recrawl-sync-2.2.2.tgz", + "integrity": "sha512-E2sI4F25Fu2nrfV+KsnC7/qfk/spQIYXlonfQoS4rwxeNK5BjxnLPbWiRXHVXPwYBOTWtPX5765kTm/zJiL+LQ==", + "dependencies": { + "@cush/relative": "^1.0.0", + "glob-regex": "^0.3.0", + "slash": "^3.0.0", + "tslib": "^1.9.3" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, + "node_modules/regenerator-transform": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/regexpu-core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz", + "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==", + "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" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" + }, + "node_modules/regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "dependencies": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "2.77.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.3.tgz", + "integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "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" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/sortablejs": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", + "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "node_modules/std-env": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.2.tgz", + "integrity": "sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==", + "dev": true + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "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" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "engines": { + "node": ">=10" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.1.tgz", + "integrity": "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.8.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==" + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.14.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", + "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" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/tinybench": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.1.tgz", + "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.3.1.tgz", + "integrity": "sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-1.1.1.tgz", + "integrity": "sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "dependencies": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/tsconfig-paths": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.1.0.tgz", + "integrity": "sha512-AHx4Euop/dXFC+Vx589alFba8QItjF+8hf8LtmuiCwHyI4rHXQtOOENaM8kvYf5fR0dRChy3wzWIZ9WbB7FWow==", + "dependencies": { + "json5": "^2.2.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/ufo": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.0.1.tgz", + "integrity": "sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==", + "dev": true + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", + "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "peer": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "peer": true + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "peer": true + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "node_modules/vite": { + "version": "2.9.15", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.15.tgz", + "integrity": "sha512-fzMt2jK4vQ3yK56te3Kqpkaeq9DkcZfBbzHwYpobasvgYmP2SoAr6Aic05CsB4CzCZbsDv4sujX3pkEGhLabVQ==", + "dependencies": { + "esbuild": "^0.14.27", + "postcss": "^8.4.13", + "resolve": "^1.22.0", + "rollup": ">=2.59.0 <2.78.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": ">=12.2.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "less": "*", + "sass": "*", + "stylus": "*" + }, + "peerDependenciesMeta": { + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.28.5.tgz", + "integrity": "sha512-LmXb9saMGlrMZbXTvOveJKwMTBTNUH66c8rJnQ0ZPNX+myPEol64+szRzXtV5ORb0Hb/91yq+/D3oERoyAt6LA==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "mlly": "^1.1.0", + "pathe": "^1.1.0", + "picocolors": "^1.0.0", + "source-map": "^0.6.1", + "source-map-support": "^0.5.21", + "vite": "^3.0.0 || ^4.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": ">=v14.16.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/vite-node/node_modules/@esbuild/linux-loong64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", + "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vite-node/node_modules/esbuild": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", + "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.16.17", + "@esbuild/android-arm64": "0.16.17", + "@esbuild/android-x64": "0.16.17", + "@esbuild/darwin-arm64": "0.16.17", + "@esbuild/darwin-x64": "0.16.17", + "@esbuild/freebsd-arm64": "0.16.17", + "@esbuild/freebsd-x64": "0.16.17", + "@esbuild/linux-arm": "0.16.17", + "@esbuild/linux-arm64": "0.16.17", + "@esbuild/linux-ia32": "0.16.17", + "@esbuild/linux-loong64": "0.16.17", + "@esbuild/linux-mips64el": "0.16.17", + "@esbuild/linux-ppc64": "0.16.17", + "@esbuild/linux-riscv64": "0.16.17", + "@esbuild/linux-s390x": "0.16.17", + "@esbuild/linux-x64": "0.16.17", + "@esbuild/netbsd-x64": "0.16.17", + "@esbuild/openbsd-x64": "0.16.17", + "@esbuild/sunos-x64": "0.16.17", + "@esbuild/win32-arm64": "0.16.17", + "@esbuild/win32-ia32": "0.16.17", + "@esbuild/win32-x64": "0.16.17" + } + }, + "node_modules/vite-node/node_modules/rollup": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.15.0.tgz", + "integrity": "sha512-F9hrCAhnp5/zx/7HYmftvsNBkMfLfk/dXUh73hPSM2E3CRgap65orDNJbLetoiUFwSAk6iHPLvBrZ5iHYvzqsg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/vite-node/node_modules/vite": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.1.1.tgz", + "integrity": "sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==", + "dev": true, + "dependencies": { + "esbuild": "^0.16.14", + "postcss": "^8.4.21", + "resolve": "^1.22.1", + "rollup": "^3.10.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-plugin-pwa": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.12.3.tgz", + "integrity": "sha512-gmYdIVXpmBuNjzbJFPZFzxWYrX4lHqwMAlOtjmXBbxApiHjx9QPXKQPJjSpeTeosLKvVbNcKSAAhfxMda0QVNQ==", + "dependencies": { + "debug": "^4.3.4", + "fast-glob": "^3.2.11", + "pretty-bytes": "^6.0.0", + "rollup": "^2.75.7", + "workbox-build": "^6.5.3", + "workbox-window": "^6.5.3" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.0.0 || ^3.0.0-0", + "workbox-build": "^6.4.0", + "workbox-window": "^6.4.0" + } + }, + "node_modules/vite-tsconfig-paths": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-3.5.0.tgz", + "integrity": "sha512-NKIubr7gXgh/3uniQaOytSg+aKWPrjquP6anAy+zCWEn6h9fB8z2/qdlfQrTgZWaXJ2pHVlllrSdRZltHn9P4g==", + "dependencies": { + "debug": "^4.1.1", + "globrex": "^0.1.2", + "recrawl-sync": "^2.0.3", + "tsconfig-paths": "^4.0.0" + }, + "peerDependencies": { + "vite": ">2.0.0-0" + } + }, + "node_modules/vitest": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.28.5.tgz", + "integrity": "sha512-pyCQ+wcAOX7mKMcBNkzDwEHRGqQvHUl0XnoHR+3Pb1hytAHISgSxv9h0gUiSiYtISXUU3rMrKiKzFYDrI6ZIHA==", + "dev": true, + "dependencies": { + "@types/chai": "^4.3.4", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "@vitest/expect": "0.28.5", + "@vitest/runner": "0.28.5", + "@vitest/spy": "0.28.5", + "@vitest/utils": "0.28.5", + "acorn": "^8.8.1", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", + "chai": "^4.3.7", + "debug": "^4.3.4", + "local-pkg": "^0.4.2", + "pathe": "^1.1.0", + "picocolors": "^1.0.0", + "source-map": "^0.6.1", + "std-env": "^3.3.1", + "strip-literal": "^1.0.0", + "tinybench": "^2.3.1", + "tinypool": "^0.3.1", + "tinyspy": "^1.0.2", + "vite": "^3.0.0 || ^4.0.0", + "vite-node": "0.28.5", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": ">=v14.16.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@vitest/browser": "*", + "@vitest/ui": "*", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/@esbuild/linux-loong64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", + "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/vitest/node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/vitest/node_modules/esbuild": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", + "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.16.17", + "@esbuild/android-arm64": "0.16.17", + "@esbuild/android-x64": "0.16.17", + "@esbuild/darwin-arm64": "0.16.17", + "@esbuild/darwin-x64": "0.16.17", + "@esbuild/freebsd-arm64": "0.16.17", + "@esbuild/freebsd-x64": "0.16.17", + "@esbuild/linux-arm": "0.16.17", + "@esbuild/linux-arm64": "0.16.17", + "@esbuild/linux-ia32": "0.16.17", + "@esbuild/linux-loong64": "0.16.17", + "@esbuild/linux-mips64el": "0.16.17", + "@esbuild/linux-ppc64": "0.16.17", + "@esbuild/linux-riscv64": "0.16.17", + "@esbuild/linux-s390x": "0.16.17", + "@esbuild/linux-x64": "0.16.17", + "@esbuild/netbsd-x64": "0.16.17", + "@esbuild/openbsd-x64": "0.16.17", + "@esbuild/sunos-x64": "0.16.17", + "@esbuild/win32-arm64": "0.16.17", + "@esbuild/win32-ia32": "0.16.17", + "@esbuild/win32-x64": "0.16.17" + } + }, + "node_modules/vitest/node_modules/rollup": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.15.0.tgz", + "integrity": "sha512-F9hrCAhnp5/zx/7HYmftvsNBkMfLfk/dXUh73hPSM2E3CRgap65orDNJbLetoiUFwSAk6iHPLvBrZ5iHYvzqsg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/vitest/node_modules/vite": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.1.1.tgz", + "integrity": "sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==", + "dev": true, + "dependencies": { + "esbuild": "^0.16.14", + "postcss": "^8.4.21", + "resolve": "^1.22.1", + "rollup": "^3.10.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.37.tgz", + "integrity": "sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ==", + "dependencies": { + "@vue/compiler-dom": "3.2.37", + "@vue/compiler-sfc": "3.2.37", + "@vue/runtime-dom": "3.2.37", + "@vue/server-renderer": "3.2.37", + "@vue/shared": "3.2.37" + } + }, + "node_modules/vue-eslint-parser": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz", + "integrity": "sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==", + "dev": true, + "dependencies": { + "debug": "^4.3.2", + "eslint-scope": "^7.0.0", + "eslint-visitor-keys": "^3.1.0", + "espree": "^9.0.0", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vue-next-select": { + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/vue-next-select/-/vue-next-select-2.10.4.tgz", + "integrity": "sha512-9Lg1mD2h9w6mm4gkXPyVMWhOdUPtA/JF9VrNyo6mqjkh4ktGLVQpNhygVBCg13RFHdEq3iqawjeFmp3FJq+CUw==", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-panzoom": { + "version": "1.1.6", + "resolved": "git+ssh://git@github.com/thepaperpilot/vue-panzoom.git#fa3cc91f6842cdfbd1bfb433c75cac01f177fe2d", + "license": "MIT", + "dependencies": { + "panzoom": "^9.4.1" + } + }, + "node_modules/vue-textarea-autosize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vue-textarea-autosize/-/vue-textarea-autosize-1.1.1.tgz", + "integrity": "sha512-B33Mg5ZDEfj/whhoPBLg25qqAdGHGM2NjDT99Qi5MXRyeLmXb4C3s6EprAHqy3nU0cooWXFU+IekI5DpoEbnFg==", + "dependencies": { + "core-js": "^2.6.5" + } + }, + "node_modules/vue-toastification": { + "version": "2.0.0-rc.5", + "resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz", + "integrity": "sha512-q73e5jy6gucEO/U+P48hqX+/qyXDozAGmaGgLFm5tXX4wJBcVsnGp4e/iJqlm9xzHETYOilUuwOUje2Qg1JdwA==", + "peerDependencies": { + "vue": "^3.0.2" + } + }, + "node_modules/vue-transition-expand": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/vue-transition-expand/-/vue-transition-expand-0.1.0.tgz", + "integrity": "sha512-4UKkK/ILk+Qh3WWJoupt7pXfzpjvb7vTQTaVUhnkr+FeXArndJVDyIn2eWIn7i37cVFXKu2jsDR47QELOCq/gQ==", + "dependencies": { + "vue": "^2.5.16" + } + }, + "node_modules/vue-transition-expand/node_modules/@vue/compiler-sfc": { + "version": "2.7.9", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.9.tgz", + "integrity": "sha512-TD2FvT0fPUezw5RVP4tfwTZnKHP0QjeEUb39y7tORvOJQTjbOuHJEk4GPHUPsRaTeQ8rjuKjntyrYcEIx+ODxg==", + "dependencies": { + "@babel/parser": "^7.18.4", + "postcss": "^8.4.14", + "source-map": "^0.6.1" + } + }, + "node_modules/vue-transition-expand/node_modules/csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "node_modules/vue-transition-expand/node_modules/vue": { + "version": "2.7.9", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.9.tgz", + "integrity": "sha512-GeWCvAUkjzD5q4A3vgi8ka5r9bM6g8fmNmx/9VnHDKCaEzBcoVw+7UcQktZHrJ2jhlI+Zv8L57pMCIwM4h4MWg==", + "dependencies": { + "@vue/compiler-sfc": "2.7.9", + "csstype": "^3.1.0" + } + }, + "node_modules/vue-tsc": { + "version": "0.38.9", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-0.38.9.tgz", + "integrity": "sha512-Yoy5phgvGqyF98Fb4mYqboR4Q149jrdcGv5kSmufXJUq++RZJ2iMVG0g6zl+v3t4ORVWkQmRpsV4x2szufZ0LQ==", + "dev": true, + "dependencies": { + "@volar/vue-typescript": "0.38.9" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": "*" + } + }, + "node_modules/vuedraggable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz", + "integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==", + "dependencies": { + "sortablejs": "1.14.0" + }, + "peerDependencies": { + "vue": "^3.0.1" + } + }, + "node_modules/w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "dependencies": { + "browser-process-hrtime": "^1.0.0" + } + }, + "node_modules/w3c-xmlserializer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", + "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", + "dev": true, + "dependencies": { + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/wheel": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wheel/-/wheel-1.0.0.tgz", + "integrity": "sha512-XiCMHibOiqalCQ+BaNSwRoZ9FDTAvOsXxGHXChBugewDj7HC8VBIER71dEOiRH1fSdLbRCQzngKTSiZ06ZQzeA==" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/workbox-background-sync": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz", + "integrity": "sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-broadcast-update": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz", + "integrity": "sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-build": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.4.tgz", + "integrity": "sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==", + "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.4", + "workbox-broadcast-update": "6.5.4", + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-google-analytics": "6.5.4", + "workbox-navigation-preload": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-range-requests": "6.5.4", + "workbox-recipes": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4", + "workbox-streams": "6.5.4", + "workbox-sw": "6.5.4", + "workbox-window": "6.5.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, + "node_modules/workbox-build/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "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" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/workbox-build/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "node_modules/workbox-build/node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workbox-build/node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workbox-build/node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/workbox-build/node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "node_modules/workbox-build/node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/workbox-cacheable-response": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz", + "integrity": "sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-core": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==" + }, + "node_modules/workbox-expiration": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-google-analytics": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz", + "integrity": "sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==", + "dependencies": { + "workbox-background-sync": "6.5.4", + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-navigation-preload": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz", + "integrity": "sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-precaching": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", + "dependencies": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-range-requests": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz", + "integrity": "sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-recipes": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.4.tgz", + "integrity": "sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==", + "dependencies": { + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "node_modules/workbox-routing": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-strategies": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", + "dependencies": { + "workbox-core": "6.5.4" + } + }, + "node_modules/workbox-streams": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.4.tgz", + "integrity": "sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==", + "dependencies": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4" + } + }, + "node_modules/workbox-sw": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.4.tgz", + "integrity": "sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==" + }, + "node_modules/workbox-window": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.4.tgz", + "integrity": "sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==", + "dependencies": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.5.4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + }, + "dependencies": { + "@ampproject/remapping": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", + "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "requires": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@babel/code-frame": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", + "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "requires": { + "@babel/highlight": "^7.18.6" + } + }, + "@babel/compat-data": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.18.8.tgz", + "integrity": "sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ==" + }, + "@babel/core": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.18.10.tgz", + "integrity": "sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw==", + "requires": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.10", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helpers": "^7.18.9", + "@babel/parser": "^7.18.10", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.10", + "@babel/types": "^7.18.10", + "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/generator": { + "version": "7.18.12", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.18.12.tgz", + "integrity": "sha512-dfQ8ebCN98SvyL7IxNMCUtZQSq5R7kxgN+r8qYTGDmmSion1hX2C0zq2yo1bsCDhXixokv1SAWTZUMYbO/V5zg==", + "requires": { + "@babel/types": "^7.18.10", + "@jridgewell/gen-mapping": "^0.3.2", + "jsesc": "^2.5.1" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", + "integrity": "sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", + "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "requires": { + "@babel/helper-explode-assignable-expression": "^7.18.6", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.18.9.tgz", + "integrity": "sha512-tzLCyVmqUiFlcFoAPLA/gL9TeYrF61VLNtb+hvkuVaB5SUjW7jcfrglBIX1vUIoT7CLP3bBlIMeyEsIl2eFQNg==", + "requires": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-validator-option": "^7.18.6", + "browserslist": "^4.20.2", + "semver": "^6.3.0" + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.18.9.tgz", + "integrity": "sha512-WvypNAYaVh23QcjpMR24CwZY2Nz6hqdOcFdPbNpV56hL5H6KiFheO7Xm1aPdlLQ7d5emYZX7VZwPp9x3z+2opw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.18.6.tgz", + "integrity": "sha512-7LcpH1wnQLGrI+4v+nPp+zUvIkF9x0ddv1Hkdue10tg3gmRnLy97DXh4STiOf1qeIInyD69Qv5kKSZzKD8B/7A==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "regexpu-core": "^5.1.0" + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.2.tgz", + "integrity": "sha512-r9QJJ+uDWrd+94BSPcP6/de67ygLtvVy6cK4luE6MOuDsZIdoaPBnfSpbO/+LTifjPckbKXRuI9BB/Z2/y3iTg==", + "requires": { + "@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": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", + "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", + "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.18.9.tgz", + "integrity": "sha512-fJgWlZt7nxGksJS9a0XdSaI4XvpExnNIgRP+rVefWh5U7BL8pPuir6SJUmFKRfjWQ51OtWSzwOxhaH/EBWWc0A==", + "requires": { + "@babel/template": "^7.18.6", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", + "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz", + "integrity": "sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg==", + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-module-imports": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", + "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-module-transforms": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.18.9.tgz", + "integrity": "sha512-KYNqY0ICwfv19b31XzvmI/mfcylOzbLtowkw+mfvGPAQ3kfCnMLYbED3YecL5tPd8nAYFQFAd6JHp2LxZk/J1g==", + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/helper-validator-identifier": "^7.18.6", + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz", + "integrity": "sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.18.9.tgz", + "integrity": "sha512-aBXPT3bmtLryXaoJLyYPXPlSD4p1ld9aYeR+sJNOZjJJGiOpb+fKfh3NkcCu7J54nUJwCERPBExCCpyCOHnu/w==" + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz", + "integrity": "sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-wrap-function": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-replace-supers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.18.9.tgz", + "integrity": "sha512-dNsWibVI4lNT6HiuOIBr1oyxo40HvIVmbwPUm3XZ7wMh4k2WxrxTqZwSqw/eEmXDS9np0ey5M2bz9tBmO9c+YQ==", + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-member-expression-to-functions": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-simple-access": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.18.6.tgz", + "integrity": "sha512-iNpIgTgyAvDQpDj76POqg+YEt8fPxx3yaNBg3S30dxNKm2SWfYhD0TGrK/Eu9wHpUW63VQU894TsTg+GLbUa1g==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.18.9.tgz", + "integrity": "sha512-imytd2gHi3cJPsybLRbmFrF7u5BIEuI2cNheyKi3/iOBC63kNn3q8Crn2xVuESli0aM4KYsyEqKyS7lFL8YVtw==", + "requires": { + "@babel/types": "^7.18.9" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", + "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "requires": { + "@babel/types": "^7.18.6" + } + }, + "@babel/helper-string-parser": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", + "integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==" + }, + "@babel/helper-validator-identifier": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", + "integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==" + }, + "@babel/helper-validator-option": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", + "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==" + }, + "@babel/helper-wrap-function": { + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.18.11.tgz", + "integrity": "sha512-oBUlbv+rjZLh2Ks9SKi4aL7eKaAXBWleHzU89mP0G6BMUlRxSckk9tSIkgDGydhgFxHuGSlBQZfnaD47oBEB7w==", + "requires": { + "@babel/helper-function-name": "^7.18.9", + "@babel/template": "^7.18.10", + "@babel/traverse": "^7.18.11", + "@babel/types": "^7.18.10" + } + }, + "@babel/helpers": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.18.9.tgz", + "integrity": "sha512-Jf5a+rbrLoR4eNdUmnFu8cN5eNJT6qdTdOg5IHIzq87WwyRw9PwguLFOWYgktN/60IP4fgDUawJvs7PjQIzELQ==", + "requires": { + "@babel/template": "^7.18.6", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9" + } + }, + "@babel/highlight": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", + "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "requires": { + "@babel/helper-validator-identifier": "^7.18.6", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.18.11.tgz", + "integrity": "sha512-9JKn5vN+hDt0Hdqn1PiJ2guflwP+B6Ga8qbDuoF0PzzVhrzsKIJo8yGqVk6CmMHiMei9w1C1Bp9IMJSIK+HPIQ==" + }, + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz", + "integrity": "sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz", + "integrity": "sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-proposal-optional-chaining": "^7.18.9" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.18.10.tgz", + "integrity": "sha512-1mFuY2TOsR1hxbjCo4QL+qlIjV07p4H4EUYw2J/WCqsvFV6V9X9z9YhXbWndc/4fw+hYGlDT7egYxliMp5O6Ew==", + "requires": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-class-static-block": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz", + "integrity": "sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz", + "integrity": "sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz", + "integrity": "sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz", + "integrity": "sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.18.9.tgz", + "integrity": "sha512-kDDHQ5rflIeY5xl69CEqGEZ0KY369ehsCIEbTGb4siHG5BE9sga/T0r0OUwyZNLMmZE79E1kbsqAjwFCW4ds6Q==", + "requires": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.18.8" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz", + "integrity": "sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz", + "integrity": "sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz", + "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz", + "integrity": "sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-import-assertions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.18.6.tgz", + "integrity": "sha512-/DU3RXad9+bZwrgWJQKbr39gYbJpLJHezqEzRzi/BHRlJ9zsQb4CK2CA/5apllXNomwA1qHwzvHl+AdEmC5krQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", + "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-typescript": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.18.6.tgz", + "integrity": "sha512-mAWAuq4rvOepWCBid55JuRNvpTNf2UGVgoz4JV0fXEKolsVZDzsa4NqCef758WZJj/GDu0gVGItjKFiClTAmZA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz", + "integrity": "sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz", + "integrity": "sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag==", + "requires": { + "@babel/helper-module-imports": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-remap-async-to-generator": "^7.18.6" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz", + "integrity": "sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.18.9.tgz", + "integrity": "sha512-5sDIJRV1KtQVEbt/EIBwGy4T01uYIo4KRB3VUqzkhrAIOGx7AoctL9+Ux88btY0zXdDyPJ9mW+bg+v+XEkGmtw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.18.9.tgz", + "integrity": "sha512-EkRQxsxoytpTlKJmSPYrsOMjCILacAjtSVkd4gChEe2kXjFCun3yohhW5I7plXJhCemM0gKsaGMcO8tinvCA5g==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-optimise-call-expression": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-replace-supers": "^7.18.9", + "@babel/helper-split-export-declaration": "^7.18.6", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz", + "integrity": "sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.18.9.tgz", + "integrity": "sha512-p5VCYNddPLkZTq4XymQIaIfZNJwT9YsjkPOhkVEqt6QIpQFZVM9IltqqYpOEkJoN1DPznmxUDyZ5CTZs/ZCuHA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz", + "integrity": "sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz", + "integrity": "sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz", + "integrity": "sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw==", + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", + "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz", + "integrity": "sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ==", + "requires": { + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz", + "integrity": "sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz", + "integrity": "sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.18.6.tgz", + "integrity": "sha512-Pra5aXsmTsOnjM3IajS8rTaLCy++nGM4v3YR4esk5PCsyg9z8NA5oQLwxzMUtDBd8F+UmVza3VxoAaWCbzH1rg==", + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.18.6.tgz", + "integrity": "sha512-Qfv2ZOWikpvmedXQJDSbxNqy7Xr/j2Y8/KfijM0iJyKkBTmWuvCA1yeH1yDM7NJhBW/2aXxeucLj6i80/LAJ/Q==", + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-simple-access": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.18.9.tgz", + "integrity": "sha512-zY/VSIbbqtoRoJKo2cDTewL364jSlZGvn0LKOf9ntbfxOvjfmyrdtEEOAdswOswhZEb8UH3jDkCKHd1sPgsS0A==", + "requires": { + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-module-transforms": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-identifier": "^7.18.6", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz", + "integrity": "sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ==", + "requires": { + "@babel/helper-module-transforms": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.18.6.tgz", + "integrity": "sha512-UmEOGF8XgaIqD74bC8g7iV3RYj8lMf0Bw7NJzvnS9qQhM4mg+1WHKotUIdjxgD2RGrgFLZZPCFPFj3P/kVDYhg==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz", + "integrity": "sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz", + "integrity": "sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/helper-replace-supers": "^7.18.6" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.18.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.18.8.tgz", + "integrity": "sha512-ivfbE3X2Ss+Fj8nnXvKJS6sjRG4gzwPMsP+taZC+ZzEGjAYlvENixmt1sZ5Ca6tWls+BlKSGKPJ6OOXvXCbkFg==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz", + "integrity": "sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz", + "integrity": "sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6", + "regenerator-transform": "^0.15.0" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz", + "integrity": "sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", + "integrity": "sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.18.9.tgz", + "integrity": "sha512-39Q814wyoOPtIB/qGopNIL9xDChOE1pNU0ZY5dO0owhiVt/5kFm4li+/bBtwc7QotG0u5EPzqhZdjMtmqBqyQA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.18.9" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz", + "integrity": "sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz", + "integrity": "sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz", + "integrity": "sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-typescript": { + "version": "7.18.12", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.18.12.tgz", + "integrity": "sha512-2vjjam0cum0miPkenUbQswKowuxs/NjMwIKEq0zwegRxXk12C9YOF9STXnaUptITOtOJHKHpzvvWYOjbm6tc0w==", + "requires": { + "@babel/helper-create-class-features-plugin": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-typescript": "^7.18.6" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", + "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "requires": { + "@babel/helper-plugin-utils": "^7.18.9" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz", + "integrity": "sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA==", + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + } + }, + "@babel/preset-env": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.18.10.tgz", + "integrity": "sha512-wVxs1yjFdW3Z/XkNfXKoblxoHgbtUF7/l3PvvP4m02Qz9TZ6uZGxRVYjSQeR87oQmHco9zWitW5J82DJ7sCjvA==", + "requires": { + "@babel/compat-data": "^7.18.8", + "@babel/helper-compilation-targets": "^7.18.9", + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/helper-validator-option": "^7.18.6", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-async-generator-functions": "^7.18.10", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-dynamic-import": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-json-strings": "^7.18.6", + "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.18.9", + "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", + "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-private-methods": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", + "@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.18.6", + "@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.18.6", + "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-block-scoped-functions": "^7.18.6", + "@babel/plugin-transform-block-scoping": "^7.18.9", + "@babel/plugin-transform-classes": "^7.18.9", + "@babel/plugin-transform-computed-properties": "^7.18.9", + "@babel/plugin-transform-destructuring": "^7.18.9", + "@babel/plugin-transform-dotall-regex": "^7.18.6", + "@babel/plugin-transform-duplicate-keys": "^7.18.9", + "@babel/plugin-transform-exponentiation-operator": "^7.18.6", + "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-function-name": "^7.18.9", + "@babel/plugin-transform-literals": "^7.18.9", + "@babel/plugin-transform-member-expression-literals": "^7.18.6", + "@babel/plugin-transform-modules-amd": "^7.18.6", + "@babel/plugin-transform-modules-commonjs": "^7.18.6", + "@babel/plugin-transform-modules-systemjs": "^7.18.9", + "@babel/plugin-transform-modules-umd": "^7.18.6", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.18.6", + "@babel/plugin-transform-new-target": "^7.18.6", + "@babel/plugin-transform-object-super": "^7.18.6", + "@babel/plugin-transform-parameters": "^7.18.8", + "@babel/plugin-transform-property-literals": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-reserved-words": "^7.18.6", + "@babel/plugin-transform-shorthand-properties": "^7.18.6", + "@babel/plugin-transform-spread": "^7.18.9", + "@babel/plugin-transform-sticky-regex": "^7.18.6", + "@babel/plugin-transform-template-literals": "^7.18.9", + "@babel/plugin-transform-typeof-symbol": "^7.18.9", + "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-regex": "^7.18.6", + "@babel/preset-modules": "^0.1.5", + "@babel/types": "^7.18.10", + "babel-plugin-polyfill-corejs2": "^0.3.2", + "babel-plugin-polyfill-corejs3": "^0.5.3", + "babel-plugin-polyfill-regenerator": "^0.4.0", + "core-js-compat": "^3.22.1", + "semver": "^6.3.0" + } + }, + "@babel/preset-modules": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz", + "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==", + "requires": { + "@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/runtime": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz", + "integrity": "sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", + "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/parser": "^7.18.10", + "@babel/types": "^7.18.10" + } + }, + "@babel/traverse": { + "version": "7.18.11", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.18.11.tgz", + "integrity": "sha512-TG9PiM2R/cWCAy6BPJKeHzNbu4lPzOSZpeMfeNErskGpTJx6trEvFaVCbDvpcxwy49BKWmEPwiW8mrysNiDvIQ==", + "requires": { + "@babel/code-frame": "^7.18.6", + "@babel/generator": "^7.18.10", + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-function-name": "^7.18.9", + "@babel/helper-hoist-variables": "^7.18.6", + "@babel/helper-split-export-declaration": "^7.18.6", + "@babel/parser": "^7.18.11", + "@babel/types": "^7.18.10", + "debug": "^4.1.0", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.18.10", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.18.10.tgz", + "integrity": "sha512-MJvnbEiiNkpjo+LknnmRrqbY1GPUUggjv+wQVjetM/AONoupqRALB7I6jGqNUAZsKcRIEu2J6FRFvsczljjsaQ==", + "requires": { + "@babel/helper-string-parser": "^7.18.10", + "@babel/helper-validator-identifier": "^7.18.6", + "to-fast-properties": "^2.0.0" + } + }, + "@cush/relative": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@cush/relative/-/relative-1.0.0.tgz", + "integrity": "sha512-RpfLEtTlyIxeNPGKcokS+p3BZII/Q3bYxryFRglh5H3A3T8q9fsLYm72VYAMEOOIBLEa8o93kFLiBDUWKrwXZA==" + }, + "@esbuild/android-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz", + "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz", + "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz", + "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", + "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz", + "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz", + "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz", + "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz", + "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz", + "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz", + "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.14.54.tgz", + "integrity": "sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==", + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz", + "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz", + "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz", + "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz", + "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz", + "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz", + "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz", + "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz", + "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz", + "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz", + "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz", + "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==", + "dev": true, + "optional": true + }, + "@eslint/eslintrc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", + "integrity": "sha512-UWW0TMTmk2d7hLcWD1/e2g5HDM/HQ3csaLSqXCfqwh4uNDuNqlaKWXmEsL4Cs41Z0KnILNvwbHAah3C2yt06kw==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "@fontsource/material-icons": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/@fontsource/material-icons/-/material-icons-4.5.4.tgz", + "integrity": "sha512-YGmXkkEdu6EIgpFKNmB/nIXzZocwSmbI01Ninpmml8x8BT0M6RR++V1KqOfpzZ6Cw/FQ2/KYonQ3x4IY/4VRRA==" + }, + "@fontsource/roboto-mono": { + "version": "4.5.8", + "resolved": "https://registry.npmjs.org/@fontsource/roboto-mono/-/roboto-mono-4.5.8.tgz", + "integrity": "sha512-AW44UkbQD0w1CT5mzDbsvhGZ6/bb0YmZzoELj6Sx8vcVEzcbYGUdt2Dtl5zqlOuYMWQFY1mniwWyVv+Bm/lVxw==" + }, + "@humanwhocodes/config-array": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", + "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + } + }, + "@humanwhocodes/gitignore-to-minimatch": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz", + "integrity": "sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "dev": true + }, + "@ivanv/vue-collapse-transition": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@ivanv/vue-collapse-transition/-/vue-collapse-transition-1.0.2.tgz", + "integrity": "sha512-eWEameFXJM/1khcoKbITvKjYYXDP1WKQ/Xf9ItJVPoEjCiOdocR3AgDAERzDrNNg4oWK28gRGi+0ft8Te27zxw==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", + "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "requires": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", + "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" + }, + "@jridgewell/source-map": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", + "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "dependencies": { + "@jridgewell/gen-mapping": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", + "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + } + } + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "@jridgewell/trace-mapping": { + "version": "0.3.15", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.15.tgz", + "integrity": "sha512-oWZNOULl+UbhsgB51uuZzglikfIKSUBO/M9W2OfEjn7cmqoAiCgmv9lyACTUacZwBz0ITnJ2NqjU8Tx0DHL88g==", + "requires": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==" + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@pixi/app": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/app/-/app-6.3.2.tgz", + "integrity": "sha512-V1jnhL92OPiquXtLxUeSZiVDd1mtjRnYpBKA958w29MrIRBx3Y6dgnvsaFZGGWBvSL//WRYV23iZKVL/jRGmmQ==", + "requires": {} + }, + "@pixi/constants": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-6.3.2.tgz", + "integrity": "sha512-sUE8QEJNl4vWUybS0YqpVUBWoOyLkr5bSj1+3mpmbWJTMVmLB2voFXo7XpSNCBlLH1SBN5flcgJlUWOCgNyATg==" + }, + "@pixi/core": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/core/-/core-6.3.2.tgz", + "integrity": "sha512-91Fw0CbFpPtMKo5TG1wdaZGgR99lX87l15F7kgge7FM7ZR4EghLiJHU8whQ19f/UNOd8AG7mHD84lUB1VXXfoA==", + "requires": { + "@types/offscreencanvas": "^2019.6.4" + } + }, + "@pixi/display": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/display/-/display-6.3.2.tgz", + "integrity": "sha512-D+WiM0BcyPK91RYxl7TXXVNz/5lOGs8Q6jtCMcWgTHwCXxWPOHFnNZ4KPJZpUQ7me8Tl2u+c9hfB5Oh1+17r/Q==", + "requires": {} + }, + "@pixi/math": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/math/-/math-6.3.2.tgz", + "integrity": "sha512-REXrCKQaT2shJ3p2Rpq1ZYV4iUeAOUFKnLN2KteQWtB5HQpB8b+w5xBGI+TcnY0FUhx92fbKPYTTvCftNZF4Jw==" + }, + "@pixi/particle-emitter": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/@pixi/particle-emitter/-/particle-emitter-5.0.7.tgz", + "integrity": "sha512-g0vf+z2pFr+znJEzAii6T7CfMAKsCZuRc8bVY2znJDYxEKoAuU+XuqzHtOkGeR/VuiNCuJhMFLh+BDfXN4Fubw==", + "requires": {} + }, + "@pixi/runner": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-6.3.2.tgz", + "integrity": "sha512-Sspv4VTiV51GwoIg+WudHZHpT3ad5ukW20OLOR+eDOSLbgQEMfj4cTVRg27TvM/QZ/5LxeN3FqwWV+kiWpqCnw==", + "peer": true + }, + "@pixi/settings": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-6.3.2.tgz", + "integrity": "sha512-i5cLDUWFnRub3LPa3x7IzkH8MjSwPHyHWzIZKG5t8RiCfbhVfhWGEdKO9AYp8yO/xcf7AqtPK4mikXziL48tXA==", + "peer": true, + "requires": { + "ismobilejs": "^1.1.0" + } + }, + "@pixi/sprite": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-6.3.2.tgz", + "integrity": "sha512-T1KJ8l2f8Otn6Se6h4b2pz2nrUSe59Pnmj2WIzgBisM245h7dGATs05MisMaLV6Lg/3gTBTxsLBmKsbDSQqbNw==", + "requires": {} + }, + "@pixi/ticker": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-6.3.2.tgz", + "integrity": "sha512-Au9IO85zCOOCz50aJALFxJ2C8gbgxvD0dSNm7A5FauanJbxDcctIyrW6I51nNyHyeLIUFEkuD2jE/DmcXsXnpw==", + "requires": {} + }, + "@pixi/utils": { + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-6.3.2.tgz", + "integrity": "sha512-VpB403kfqwXK9w7Qb6ex0aW0g6pWI/t43F2Z8CA/lAfYcN3O0XoxDucvmkLTQWsMtYn+Yf7YhAcLV5SemKwP0A==", + "peer": true, + "requires": { + "@types/earcut": "^2.1.0", + "earcut": "^2.2.2", + "eventemitter3": "^3.1.0", + "url": "^0.11.0" + } + }, + "@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "requires": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + } + } + }, + "@rollup/plugin-node-resolve": { + "version": "11.2.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz", + "integrity": "sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==", + "requires": { + "@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" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + } + } + }, + "@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "requires": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "requires": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + } + }, + "estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==" + } + } + }, + "@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "requires": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + } + }, + "@rushstack/eslint-patch": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.1.4.tgz", + "integrity": "sha512-LwzQKA4vzIct1zNZzBmRKI9QuNpLgTQMEjsQLf3BXuGYb3QPTP4Yjf6mkdX+X1mYttZ808QpOwAzZjv28kq7DA==", + "dev": true + }, + "@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "requires": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true + }, + "@types/chai": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", + "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "dev": true + }, + "@types/chai-subset": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", + "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "dev": true, + "requires": { + "@types/chai": "*" + } + }, + "@types/earcut": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/earcut/-/earcut-2.1.1.tgz", + "integrity": "sha512-w8oigUCDjElRHRRrMvn/spybSMyX8MTkKA5Dv+tS1IE/TgmNZPqUYtvYBXGY8cieSE66gm+szeK+bnbxC2xHTQ==", + "peer": true + }, + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + }, + "@types/json-schema": { + "version": "7.0.11", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", + "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "dev": true + }, + "@types/lz-string": { + "version": "1.3.34", + "resolved": "https://registry.npmjs.org/@types/lz-string/-/lz-string-1.3.34.tgz", + "integrity": "sha512-j6G1e8DULJx3ONf6NdR5JiR2ZY3K3PaaqiEuKYkLQO0Czfi1AzrtjfnfCROyWGeDd5IVMKCwsgSmMip9OWijow==", + "dev": true + }, + "@types/node": { + "version": "18.7.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.9.tgz", + "integrity": "sha512-0N5Y1XAdcl865nDdjbO0m3T6FdmQ4ijE89/urOHLREyTXbpMWbSafx9y7XIsgWGtwUP2iYTinLyyW3FatAxBLQ==" + }, + "@types/offscreencanvas": { + "version": "2019.7.0", + "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.0.tgz", + "integrity": "sha512-PGcyveRIpL1XIqK8eBsmRBt76eFgtzuPiSTyKHZxnGemp2yzGzWpjYKAfK3wIMiU7eH+851yEpiuP8JZerTmWg==" + }, + "@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "requires": { + "@types/node": "*" + } + }, + "@types/trusted-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", + "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.33.1.tgz", + "integrity": "sha512-S1iZIxrTvKkU3+m63YUOxYPKaP+yWDQrdhxTglVDVEVBf+aCSw85+BmJnyUaQQsk5TXFG/LpBu9fa+LrAQ91fQ==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/type-utils": "5.33.1", + "@typescript-eslint/utils": "5.33.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" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.33.1.tgz", + "integrity": "sha512-IgLLtW7FOzoDlmaMoXdxG8HOCByTBXrB1V2ZQYSEV1ggMmJfAkMWTwUjjzagS6OkfpySyhKFkBw7A9jYmcHpZA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/typescript-estree": "5.33.1", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.33.1.tgz", + "integrity": "sha512-8ibcZSqy4c5m69QpzJn8XQq9NnqAToC8OdH/W6IXPXv83vRyEDPYLdjAlUx8h/rbusq6MkW4YdQzURGOqsn3CA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/visitor-keys": "5.33.1" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.33.1.tgz", + "integrity": "sha512-X3pGsJsD8OiqhNa5fim41YtlnyiWMF/eKsEZGsHID2HcDqeSC5yr/uLOeph8rNF2/utwuI0IQoAK3fpoxcLl2g==", + "dev": true, + "requires": { + "@typescript-eslint/utils": "5.33.1", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.33.1.tgz", + "integrity": "sha512-7K6MoQPQh6WVEkMrMW5QOA5FO+BOwzHSNd0j3+BlBwd6vtzfZceJ8xJ7Um2XDi/O3umS8/qDX6jdy2i7CijkwQ==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.33.1.tgz", + "integrity": "sha512-JOAzJ4pJ+tHzA2pgsWQi4804XisPHOtbvwUyqsuuq8+y5B5GMZs7lI1xDWs6V2d7gE/Ez5bTGojSK12+IIPtXA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/visitor-keys": "5.33.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/utils": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.33.1.tgz", + "integrity": "sha512-uphZjkMaZ4fE8CR4dU7BquOV6u0doeQAr8n6cQenl/poMaIyJtBu8eys5uk6u5HiDH01Mj5lzbJ5SfeDz7oqMQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.9", + "@typescript-eslint/scope-manager": "5.33.1", + "@typescript-eslint/types": "5.33.1", + "@typescript-eslint/typescript-estree": "5.33.1", + "eslint-scope": "^5.1.1", + "eslint-utils": "^3.0.0" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.33.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.33.1.tgz", + "integrity": "sha512-nwIxOK8Z2MPWltLKMLOEZwmfBZReqUdbEoHQXeCpa+sRVARe5twpJGHCB4dk9903Yaf0nMAlGbQfaAH92F60eg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.33.1", + "eslint-visitor-keys": "^3.3.0" + } + }, + "@vitejs/plugin-vue": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-2.3.4.tgz", + "integrity": "sha512-IfFNbtkbIm36O9KB8QodlwwYvTEsJb4Lll4c2IwB3VHc2gie2mSPtSzL0eYay7X2jd/2WX02FjSGTWR6OPr/zg==", + "requires": {} + }, + "@vitejs/plugin-vue-jsx": { + "version": "1.3.10", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-1.3.10.tgz", + "integrity": "sha512-Cf5zznh4yNMiEMBfTOztaDVDmK1XXfgxClzOSUVUc8WAmHzogrCUeM8B05ABzuGtg0D1amfng+mUmSIOFGP3Pw==", + "requires": { + "@babel/core": "^7.17.9", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.16.8", + "@rollup/pluginutils": "^4.2.0", + "@vue/babel-plugin-jsx": "^1.1.1", + "hash-sum": "^2.0.0" + } + }, + "@vitest/expect": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.28.5.tgz", + "integrity": "sha512-gqTZwoUTwepwGIatnw4UKpQfnoyV0Z9Czn9+Lo2/jLIt4/AXLTn+oVZxlQ7Ng8bzcNkR+3DqLJ08kNr8jRmdNQ==", + "dev": true, + "requires": { + "@vitest/spy": "0.28.5", + "@vitest/utils": "0.28.5", + "chai": "^4.3.7" + } + }, + "@vitest/runner": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.28.5.tgz", + "integrity": "sha512-NKkHtLB+FGjpp5KmneQjTcPLWPTDfB7ie+MmF1PnUBf/tGe2OjGxWyB62ySYZ25EYp9krR5Bw0YPLS/VWh1QiA==", + "dev": true, + "requires": { + "@vitest/utils": "0.28.5", + "p-limit": "^4.0.0", + "pathe": "^1.1.0" + }, + "dependencies": { + "p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "requires": { + "yocto-queue": "^1.0.0" + } + }, + "yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true + } + } + }, + "@vitest/spy": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.28.5.tgz", + "integrity": "sha512-7if6rsHQr9zbmvxN7h+gGh2L9eIIErgf8nSKYDlg07HHimCxp4H6I/X/DPXktVPPLQfiZ1Cw2cbDIx9fSqDjGw==", + "dev": true, + "requires": { + "tinyspy": "^1.0.2" + } + }, + "@vitest/utils": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.28.5.tgz", + "integrity": "sha512-UyZdYwdULlOa4LTUSwZ+Paz7nBHGTT72jKwdFSV4IjHF1xsokp+CabMdhjvVhYwkLfO88ylJT46YMilnkSARZA==", + "dev": true, + "requires": { + "cli-truncate": "^3.1.0", + "diff": "^5.1.0", + "loupe": "^2.3.6", + "picocolors": "^1.0.0", + "pretty-format": "^27.5.1" + } + }, + "@volar/code-gen": { + "version": "0.38.9", + "resolved": "https://registry.npmjs.org/@volar/code-gen/-/code-gen-0.38.9.tgz", + "integrity": "sha512-n6LClucfA+37rQeskvh9vDoZV1VvCVNy++MAPKj2dT4FT+Fbmty/SDQqnsEBtdEe6E3OQctFvA/IcKsx3Mns0A==", + "dev": true, + "requires": { + "@volar/source-map": "0.38.9" + } + }, + "@volar/source-map": { + "version": "0.38.9", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-0.38.9.tgz", + "integrity": "sha512-ba0UFoHDYry+vwKdgkWJ6xlQT+8TFtZg1zj9tSjj4PykW1JZDuM0xplMotLun4h3YOoYfY9K1huY5gvxmrNLIw==", + "dev": true + }, + "@volar/vue-code-gen": { + "version": "0.38.9", + "resolved": "https://registry.npmjs.org/@volar/vue-code-gen/-/vue-code-gen-0.38.9.tgz", + "integrity": "sha512-tzj7AoarFBKl7e41MR006ncrEmNPHALuk8aG4WdDIaG387X5//5KhWC5Ff3ZfB2InGSeNT+CVUd74M0gS20rjA==", + "dev": true, + "requires": { + "@volar/code-gen": "0.38.9", + "@volar/source-map": "0.38.9", + "@vue/compiler-core": "^3.2.37", + "@vue/compiler-dom": "^3.2.37", + "@vue/shared": "^3.2.37" + } + }, + "@volar/vue-typescript": { + "version": "0.38.9", + "resolved": "https://registry.npmjs.org/@volar/vue-typescript/-/vue-typescript-0.38.9.tgz", + "integrity": "sha512-iJMQGU91ADi98u8V1vXd2UBmELDAaeSP0ZJaFjwosClQdKlJQYc6MlxxKfXBZisHqfbhdtrGRyaryulnYtliZw==", + "dev": true, + "requires": { + "@volar/code-gen": "0.38.9", + "@volar/source-map": "0.38.9", + "@volar/vue-code-gen": "0.38.9", + "@vue/compiler-sfc": "^3.2.37", + "@vue/reactivity": "^3.2.37" + } + }, + "@vue/babel-helper-vue-transform-on": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz", + "integrity": "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==" + }, + "@vue/babel-plugin-jsx": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz", + "integrity": "sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "@vue/babel-helper-vue-transform-on": "^1.0.2", + "camelcase": "^6.0.0", + "html-tags": "^3.1.0", + "svg-tags": "^1.0.0" + } + }, + "@vue/compiler-core": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.37.tgz", + "integrity": "sha512-81KhEjo7YAOh0vQJoSmAD68wLfYqJvoiD4ulyedzF+OEk/bk6/hx3fTNVfuzugIIaTrOx4PGx6pAiBRe5e9Zmg==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.37", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" + } + }, + "@vue/compiler-dom": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.37.tgz", + "integrity": "sha512-yxJLH167fucHKxaqXpYk7x8z7mMEnXOw3G2q62FTkmsvNxu4FQSu5+3UMb+L7fjKa26DEzhrmCxAgFLLIzVfqQ==", + "requires": { + "@vue/compiler-core": "3.2.37", + "@vue/shared": "3.2.37" + } + }, + "@vue/compiler-sfc": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.37.tgz", + "integrity": "sha512-+7i/2+9LYlpqDv+KTtWhOZH+pa8/HnX/905MdVmAcI/mPQOBwkHHIzrsEsucyOIZQYMkXUiTkmZq5am/NyXKkg==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.37", + "@vue/compiler-dom": "3.2.37", + "@vue/compiler-ssr": "3.2.37", + "@vue/reactivity-transform": "3.2.37", + "@vue/shared": "3.2.37", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" + } + }, + "@vue/compiler-ssr": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.37.tgz", + "integrity": "sha512-7mQJD7HdXxQjktmsWp/J67lThEIcxLemz1Vb5I6rYJHR5vI+lON3nPGOH3ubmbvYGt8xEUaAr1j7/tIFWiEOqw==", + "requires": { + "@vue/compiler-dom": "3.2.37", + "@vue/shared": "3.2.37" + } + }, + "@vue/eslint-config-prettier": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-prettier/-/eslint-config-prettier-7.0.0.tgz", + "integrity": "sha512-/CTc6ML3Wta1tCe1gUeO0EYnVXfo3nJXsIhZ8WJr3sov+cGASr6yuiibJTL6lmIBm7GobopToOuB3B6AWyV0Iw==", + "dev": true, + "requires": { + "eslint-config-prettier": "^8.3.0", + "eslint-plugin-prettier": "^4.0.0" + } + }, + "@vue/eslint-config-typescript": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-10.0.0.tgz", + "integrity": "sha512-F94cL8ug3FaYXlCfU5/wiGjk1qeadmoBpRGAOBq+qre3Smdupa59dd6ZJrsfRODpsMPyTG7330juMDsUvpZ3Rw==", + "dev": true, + "requires": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "@typescript-eslint/parser": "^5.0.0", + "vue-eslint-parser": "^8.0.0" + } + }, + "@vue/reactivity": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.37.tgz", + "integrity": "sha512-/7WRafBOshOc6m3F7plwzPeCu/RCVv9uMpOwa/5PiY1Zz+WLVRWiy0MYKwmg19KBdGtFWsmZ4cD+LOdVPcs52A==", + "requires": { + "@vue/shared": "3.2.37" + } + }, + "@vue/reactivity-transform": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.37.tgz", + "integrity": "sha512-IWopkKEb+8qpu/1eMKVeXrK0NLw9HicGviJzhJDEyfxTR9e1WtpnnbYkJWurX6WwoFP0sz10xQg8yL8lgskAZg==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.37", + "@vue/shared": "3.2.37", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + } + }, + "@vue/runtime-core": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.37.tgz", + "integrity": "sha512-JPcd9kFyEdXLl/i0ClS7lwgcs0QpUAWj+SKX2ZC3ANKi1U4DOtiEr6cRqFXsPwY5u1L9fAjkinIdB8Rz3FoYNQ==", + "requires": { + "@vue/reactivity": "3.2.37", + "@vue/shared": "3.2.37" + } + }, + "@vue/runtime-dom": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.37.tgz", + "integrity": "sha512-HimKdh9BepShW6YozwRKAYjYQWg9mQn63RGEiSswMbW+ssIht1MILYlVGkAGGQbkhSh31PCdoUcfiu4apXJoPw==", + "requires": { + "@vue/runtime-core": "3.2.37", + "@vue/shared": "3.2.37", + "csstype": "^2.6.8" + } + }, + "@vue/server-renderer": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.37.tgz", + "integrity": "sha512-kLITEJvaYgZQ2h47hIzPh2K3jG8c1zCVbp/o/bzQOyvzaKiCquKS7AaioPI28GNxIsE/zSx+EwWYsNxDCX95MA==", + "requires": { + "@vue/compiler-ssr": "3.2.37", + "@vue/shared": "3.2.37" + } + }, + "@vue/shared": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.37.tgz", + "integrity": "sha512-4rSJemR2NQIo9Klm1vabqWjD8rs/ZaJSzMxkMNeJS6lHiUjjUeYFbooN19NgFjztubEKh3WlZUeOLVdbbUWHsw==" + }, + "abab": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", + "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "dev": true + }, + "acorn": { + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==" + }, + "acorn-globals": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-6.0.0.tgz", + "integrity": "sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==", + "dev": true, + "requires": { + "acorn": "^7.1.1", + "acorn-walk": "^7.1.1" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "requires": { + "debug": "4" + } + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "amator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/amator/-/amator-1.1.0.tgz", + "integrity": "sha512-V5+aH8pe+Z3u/UG3L3pG3BaFQGXAyXHVQDroRwjPHdh08bcUEchAVsU1MCuJSCaU5o60wTK6KaE6te5memzgYw==", + "requires": { + "bezier-easing": "^2.0.3" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true + }, + "async": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.4.tgz", + "integrity": "sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.2.tgz", + "integrity": "sha512-LPnodUl3lS0/4wN3Rb+m+UK8s7lj2jcLRrjho4gLw+OJs+I4bvGXshINesY5xx/apM+biTnQ9reDI8yj+0M5+Q==", + "requires": { + "@babel/compat-data": "^7.17.7", + "@babel/helper-define-polyfill-provider": "^0.3.2", + "semver": "^6.1.1" + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.5.3.tgz", + "integrity": "sha512-zKsXDh0XjnrUEW0mxIHLfjBfnXSMr5Q/goMe/fxpQnLm07mcOZiIZHBNWCMx60HmdvjxfXcalac0tfFg0wqxyw==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.2", + "core-js-compat": "^3.21.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.0.tgz", + "integrity": "sha512-RW1cnryiADFeHmfLS+WW/G431p1PsW5qdRdz0SDRi7TKcUgc7Oh/uXkT7MZ/+tGsT1BkczEAmD5XjUyJ5SWDTw==", + "requires": { + "@babel/helper-define-polyfill-provider": "^0.3.2" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "bezier-easing": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz", + "integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig==" + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "peer": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true + }, + "browserslist": { + "version": "4.21.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", + "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", + "requires": { + "caniuse-lite": "^1.0.30001370", + "electron-to-chromium": "^1.4.202", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.5" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==" + }, + "cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==" + }, + "caniuse-lite": { + "version": "1.0.30001380", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001380.tgz", + "integrity": "sha512-OO+pPubxx16lkI7TVrbFpde8XHz66SMwstl1YWpg6uMGw56XnhYVwtPIjvX4kYpzwMwQKr4DDce394E03dQPGg==" + }, + "chai": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, + "requires": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true + }, + "cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "requires": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "convert-source-map": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", + "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + }, + "core-js-compat": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.24.1.tgz", + "integrity": "sha512-XhdNAGeRnTpp8xbD+sR/HFDK9CbeeeqXT6TuofXh3urqEevzkWmLRgrVoykodsw8okqo2pu1BOmuCKrHx63zdw==", + "requires": { + "browserslist": "^4.21.3", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + } + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "peer": true + }, + "cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true + }, + "cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "requires": { + "cssom": "~0.3.6" + }, + "dependencies": { + "cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + } + } + }, + "csstype": { + "version": "2.6.20", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.20.tgz", + "integrity": "sha512-/WwNkdXfckNgw6S5R125rrW8ez139lBHWouiBvX8dfMFtcn6V81REDqnH7+CRpRipfYlyU1CmOnOxrmGcFOjeA==" + }, + "data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "requires": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + } + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decimal.js": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.0.tgz", + "integrity": "sha512-Nv6ENEzyPQ6AItkGwLE2PGKinZZ9g59vSh2BeH6NqPu0OTKZ5ruJsVqh/orbAnqXc9pBbgXAIrc2EyaCj8NpGg==", + "dev": true + }, + "deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "requires": { + "type-detect": "^4.0.0" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + }, + "define-properties": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "requires": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true + }, + "diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "dev": true + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "domexception": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", + "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "dev": true, + "requires": { + "webidl-conversions": "^7.0.0" + } + }, + "earcut": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz", + "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==", + "peer": true + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "ejs": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", + "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "requires": { + "jake": "^10.8.5" + } + }, + "electron-to-chromium": { + "version": "1.4.225", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.225.tgz", + "integrity": "sha512-ICHvGaCIQR3P88uK8aRtx8gmejbVJyC6bB4LEC3anzBrIzdzC7aiZHY4iFfXhN4st6I7lMO0x4sgBHf/7kBvRw==" + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "entities": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.3.1.tgz", + "integrity": "sha512-o4q/dYJlmyjP2zfnaWDUC6A3BQFmVTX+tZPezK7k0GLSU9QYCauscf5Y+qcEPzKL+EixVouYDgLQK5H9GrLpkg==", + "dev": true + }, + "es-abstract": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.1.tgz", + "integrity": "sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA==", + "requires": { + "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-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "esbuild": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.54.tgz", + "integrity": "sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==", + "requires": { + "@esbuild/linux-loong64": "0.14.54", + "esbuild-android-64": "0.14.54", + "esbuild-android-arm64": "0.14.54", + "esbuild-darwin-64": "0.14.54", + "esbuild-darwin-arm64": "0.14.54", + "esbuild-freebsd-64": "0.14.54", + "esbuild-freebsd-arm64": "0.14.54", + "esbuild-linux-32": "0.14.54", + "esbuild-linux-64": "0.14.54", + "esbuild-linux-arm": "0.14.54", + "esbuild-linux-arm64": "0.14.54", + "esbuild-linux-mips64le": "0.14.54", + "esbuild-linux-ppc64le": "0.14.54", + "esbuild-linux-riscv64": "0.14.54", + "esbuild-linux-s390x": "0.14.54", + "esbuild-netbsd-64": "0.14.54", + "esbuild-openbsd-64": "0.14.54", + "esbuild-sunos-64": "0.14.54", + "esbuild-windows-32": "0.14.54", + "esbuild-windows-64": "0.14.54", + "esbuild-windows-arm64": "0.14.54" + } + }, + "esbuild-android-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.54.tgz", + "integrity": "sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==", + "optional": true + }, + "esbuild-android-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.54.tgz", + "integrity": "sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==", + "optional": true + }, + "esbuild-darwin-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.54.tgz", + "integrity": "sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==", + "optional": true + }, + "esbuild-darwin-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.54.tgz", + "integrity": "sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==", + "optional": true + }, + "esbuild-freebsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.54.tgz", + "integrity": "sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==", + "optional": true + }, + "esbuild-freebsd-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.54.tgz", + "integrity": "sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==", + "optional": true + }, + "esbuild-linux-32": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.54.tgz", + "integrity": "sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==", + "optional": true + }, + "esbuild-linux-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.54.tgz", + "integrity": "sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==", + "optional": true + }, + "esbuild-linux-arm": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.54.tgz", + "integrity": "sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==", + "optional": true + }, + "esbuild-linux-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.54.tgz", + "integrity": "sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==", + "optional": true + }, + "esbuild-linux-mips64le": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.54.tgz", + "integrity": "sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==", + "optional": true + }, + "esbuild-linux-ppc64le": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.54.tgz", + "integrity": "sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==", + "optional": true + }, + "esbuild-linux-riscv64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.54.tgz", + "integrity": "sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==", + "optional": true + }, + "esbuild-linux-s390x": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.54.tgz", + "integrity": "sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==", + "optional": true + }, + "esbuild-netbsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.54.tgz", + "integrity": "sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==", + "optional": true + }, + "esbuild-openbsd-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.54.tgz", + "integrity": "sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==", + "optional": true + }, + "esbuild-sunos-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.54.tgz", + "integrity": "sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==", + "optional": true + }, + "esbuild-windows-32": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.54.tgz", + "integrity": "sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==", + "optional": true + }, + "esbuild-windows-64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.54.tgz", + "integrity": "sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==", + "optional": true + }, + "esbuild-windows-arm64": { + "version": "0.14.54", + "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.54.tgz", + "integrity": "sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==", + "optional": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + }, + "escodegen": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz", + "integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==", + "dev": true, + "requires": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "optionator": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", + "dev": true, + "requires": { + "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" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + } + } + }, + "eslint": { + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.22.0.tgz", + "integrity": "sha512-ci4t0sz6vSRKdmkOGmprBo6fmI4PrphDFMy5JEq/fNS0gQkJM3rLmrqcp8ipMcdobH3KtUP40KniAE9W19S4wA==", + "dev": true, + "requires": { + "@eslint/eslintrc": "^1.3.0", + "@humanwhocodes/config-array": "^0.10.4", + "@humanwhocodes/gitignore-to-minimatch": "^1.0.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.3", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.15.0", + "globby": "^11.1.0", + "grapheme-splitter": "^1.0.4", + "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" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "globals": { + "version": "13.17.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.17.0.tgz", + "integrity": "sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "eslint-config-prettier": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz", + "integrity": "sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==", + "dev": true, + "requires": {} + }, + "eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "requires": { + "prettier-linter-helpers": "^1.0.0" + } + }, + "eslint-plugin-vue": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz", + "integrity": "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==", + "dev": true, + "peer": true, + "requires": { + "eslint-utils": "^3.0.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.0.1", + "postcss-selector-parser": "^6.0.9", + "semver": "^7.3.5", + "vue-eslint-parser": "^8.0.1" + }, + "dependencies": { + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "peer": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^2.0.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true + } + } + }, + "eslint-visitor-keys": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", + "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "dev": true + }, + "espree": { + "version": "9.3.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.3.tgz", + "integrity": "sha512-ORs1Rt/uQTqUKjDdGCyrtYxbazf5umATSf/K4qxjmZHORR6HJk+2s/2Pqe+Kk49HHINC/xNIrGfgh8sZcll0ng==", + "dev": true, + "requires": { + "acorn": "^8.8.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.3.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", + "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + }, + "eventemitter3": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", + "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", + "peer": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fast-diff": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", + "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "dev": true + }, + "fast-glob": { + "version": "3.2.11", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", + "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", + "requires": { + "@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" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", + "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "requires": { + "reusify": "^1.0.4" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "requires": { + "minimatch": "^5.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", + "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "dev": true, + "requires": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "dev": true + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "optional": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "function.prototype.name": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", + "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "requires": { + "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": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true + }, + "functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==" + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + }, + "get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, + "get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==" + }, + "get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "glob-regex": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/glob-regex/-/glob-regex-0.3.2.tgz", + "integrity": "sha512-m5blUd3/OqDTWwzBBtWBPrGlAzatRywHameHeekAZyZrskYouOGdNB8T/q6JucucvJXtOuyHIn0/Yia7iDasDw==" + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "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" + } + }, + "globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==" + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "grapheme-splitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", + "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==" + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" + }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "hash-sum": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz", + "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==" + }, + "html-encoding-sniffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz", + "integrity": "sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==", + "dev": true, + "requires": { + "whatwg-encoding": "^2.0.0" + } + }, + "html-tags": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", + "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==" + }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "requires": { + "agent-base": "6", + "debug": "4" + } + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "idb": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.0.2.tgz", + "integrity": "sha512-jjKrT1EnyZewQ/gCBb/eyiYrhGzws2FeY92Yx8qT9S9GeQAmo4JFVIiWRIfKW/6Ob9A+UDAOW9j9jn58fy2HIg==" + }, + "ignore": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", + "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "internal-slot": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", + "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==", + "requires": { + "get-intrinsic": "^1.1.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + } + }, + "is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "requires": { + "has-bigints": "^1.0.1" + } + }, + "is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz", + "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==" + }, + "is-core-module": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.10.0.tgz", + "integrity": "sha512-Erxj2n/LDAZ7H8WNJXd9tw38GYM3dv8rk8Zcs+jJuxYTW7sozH+SS8NtrSjVL1/vpLvWi1hxy96IzjJ3EHTJJg==", + "requires": { + "has": "^1.0.3" + } + }, + "is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" + }, + "is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + }, + "is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==" + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true + }, + "is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==" + }, + "is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "requires": { + "call-bind": "^1.0.2" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "ismobilejs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz", + "integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==", + "peer": true + }, + "jake": { + "version": "10.8.5", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", + "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "requires": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "requires": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsdom": { + "version": "20.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.0.tgz", + "integrity": "sha512-x4a6CKCgx00uCmP+QakBDFXwjAJ69IkkIWHmtmjd3wvXPcdOS44hfX2vqkOQrVrq8l9DhNNADZRXaCEWvgXtVA==", + "dev": true, + "requires": { + "abab": "^2.0.6", + "acorn": "^8.7.1", + "acorn-globals": "^6.0.0", + "cssom": "^0.5.0", + "cssstyle": "^2.3.0", + "data-urls": "^3.0.2", + "decimal.js": "^10.3.1", + "domexception": "^4.0.0", + "escodegen": "^2.0.0", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^3.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.0", + "parse5": "^7.0.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^4.0.0", + "w3c-hr-time": "^1.0.2", + "w3c-xmlserializer": "^3.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^2.0.0", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0", + "ws": "^8.8.0", + "xml-name-validator": "^4.0.0" + } + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==" + }, + "json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json5": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz", + "integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==" + }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + }, + "dependencies": { + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + } + } + }, + "jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==" + }, + "leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "local-pkg": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.2.tgz", + "integrity": "sha512-mlERgSPrbxU3BP4qBqAvvwlgW4MTg78iwJdGGnv7kibKjWcJksrG3t6LB5lXI93wXRDvG4NpUgJFmTG4T6rdrg==", + "dev": true + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + }, + "loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "requires": { + "get-func-name": "^2.0.0" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "lz-string": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", + "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==" + }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true + }, + "mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "requires": { + "mime-db": "1.52.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "mlly": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.1.0.tgz", + "integrity": "sha512-cwzBrBfwGC1gYJyfcy8TcZU1f+dbH/T+TuOhtYP2wLv/Fb51/uV7HJQfBPtEupZ2ORLRU1EKFS/QfS3eo9+kBQ==", + "dev": true, + "requires": { + "acorn": "^8.8.1", + "pathe": "^1.0.0", + "pkg-types": "^1.0.1", + "ufo": "^1.0.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "nanoevents": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/nanoevents/-/nanoevents-6.0.2.tgz", + "integrity": "sha512-FRS2otuFcPPYDPYViNWQ42+1iZqbXydinkRHTHFxrF4a1CpBfmydR9zkI44WSXAXCyPrkcGtPk5CnpW6Y3lFKQ==" + }, + "nanoid": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "ngraph.events": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/ngraph.events/-/ngraph.events-1.2.2.tgz", + "integrity": "sha512-JsUbEOzANskax+WSYiAPETemLWYXmixuPAlmZmhIbIj6FH/WDgEGCGnRwUQBK0GjOnVm8Ui+e5IJ+5VZ4e32eQ==" + }, + "node-releases": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", + "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" + }, + "nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "peer": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "nwsapi": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.1.tgz", + "integrity": "sha512-JYOWTeFoS0Z93587vRJgASD5Ut11fYl5NyihP3KrYBvMe1FRRs6RN7m20SA/16GM4P6hTnZjT+UmDOt38UeXNg==", + "dev": true + }, + "object-inspect": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", + "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", + "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "panzoom": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/panzoom/-/panzoom-9.4.3.tgz", + "integrity": "sha512-xaxCpElcRbQsUtIdwlrZA90P90+BHip4Vda2BC8MEb4tkI05PmR6cKECdqUCZ85ZvBHjpI9htJrZBxV5Gp/q/w==", + "requires": { + "amator": "^1.1.0", + "ngraph.events": "^1.2.2", + "wheel": "^1.0.0" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse5": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.0.0.tgz", + "integrity": "sha512-y/t8IXSPWTuRZqXc0ajH/UwDj4mnqLEbSttNbThcFhGrZuOyoyvNBO85PBp2jQa55wY9d07PBNjsK8ZP3K5U6g==", + "dev": true, + "requires": { + "entities": "^4.3.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pathe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz", + "integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==", + "dev": true + }, + "pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true + }, + "picocolors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pkg-types": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.1.tgz", + "integrity": "sha512-jHv9HB+Ho7dj6ItwppRDDl0iZRYBD0jsakHXtFgoLr+cHSF6xC+QL54sJmWxyGxOLYSHm0afhXhXcQDQqH9z8g==", + "dev": true, + "requires": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.0.0", + "pathe": "^1.0.0" + } + }, + "postcss": { + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "peer": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", + "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "dev": true + }, + "prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "requires": { + "fast-diff": "^1.1.2" + } + }, + "pretty-bytes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.0.0.tgz", + "integrity": "sha512-6UqkYefdogmzqAZWzJ7laYeJnaXDy2/J+ZqiiMtS7t7OfpXWTlaeGMwX8U6EFvPV/YWWEKRkS8hKS4k60WHTOg==" + }, + "pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", + "peer": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==" + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "recrawl-sync": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/recrawl-sync/-/recrawl-sync-2.2.2.tgz", + "integrity": "sha512-E2sI4F25Fu2nrfV+KsnC7/qfk/spQIYXlonfQoS4rwxeNK5BjxnLPbWiRXHVXPwYBOTWtPX5765kTm/zJiL+LQ==", + "requires": { + "@cush/relative": "^1.0.0", + "glob-regex": "^0.3.0", + "slash": "^3.0.0", + "tslib": "^1.9.3" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==" + }, + "regenerate-unicode-properties": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.0.1.tgz", + "integrity": "sha512-vn5DU6yg6h8hP/2OkQo3K7uVILvY4iu0oI4t3HFa81UPkhGJwkRwM10JEc3upjdhHjs/k8GJY1sRBhk5sr69Bw==", + "requires": { + "regenerate": "^1.4.2" + } + }, + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, + "regenerator-transform": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.0.tgz", + "integrity": "sha512-LsrGtPmbYg19bcPHwdtmXwbW+TqNvtY4riE3P83foeHRroMbH6/2ddFBfab3t7kbzc7v7p4wbkIecHImqt0QNg==", + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regexp.prototype.flags": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", + "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "functions-have-names": "^1.2.2" + } + }, + "regexpp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", + "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", + "dev": true + }, + "regexpu-core": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.1.0.tgz", + "integrity": "sha512-bb6hk+xWd2PEOkj5It46A16zFMs2mv86Iwpdu94la4S3sJ7C973h2dHpYKwIBGaWSO7cIRJ+UX0IeMaWcO4qwA==", + "requires": { + "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": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.6.0.tgz", + "integrity": "sha512-ozE883Uigtqj3bx7OhL1KNbCzGyW2NQZPl6Hs09WTvCuZD5sTI4JY58bkbQWa/Y9hxIsvJ3M8Nbf7j54IqeZbA==" + }, + "regjsparser": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.8.4.tgz", + "integrity": "sha512-J3LABycON/VNEu3abOviqGHuB/LOtOQj8SKmfP9anY5GfAVw/SPjwzSjxGjbZXIxbGfqTHtJw58C2Li/WkStmA==", + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==" + } + } + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "resolve": { + "version": "1.22.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", + "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "requires": { + "is-core-module": "^2.9.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==" + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "rollup": { + "version": "2.77.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.77.3.tgz", + "integrity": "sha512-/qxNTG7FbmefJWoeeYJFbHehJ2HNWnjkAFRKzWN/45eNBBF/r8lo992CwcJXEzyVxs5FmfId+vTSTQDb+bxA+g==", + "requires": { + "fsevents": "~2.3.2" + } + }, + "rollup-plugin-terser": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", + "requires": { + "@babel/code-frame": "^7.10.4", + "jest-worker": "^26.2.1", + "serialize-javascript": "^4.0.0", + "terser": "^5.0.0" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "requires": { + "xmlchars": "^2.2.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "requires": { + "randombytes": "^2.1.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" + }, + "slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + } + } + }, + "sortablejs": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", + "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==" + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, + "source-map-js": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + }, + "source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" + }, + "stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, + "std-env": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.2.tgz", + "integrity": "sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA==", + "dev": true + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "strip-ansi": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz", + "integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + } + } + }, + "string.prototype.matchall": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", + "integrity": "sha512-f48okCX7JiwVi1NXCVWcFnZgADDC/n2vePlQ/KUCNqCikLLilQvwjMO8+BHVKvgzH0JB0J9LEPgxOGT02RoETg==", + "requires": { + "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": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz", + "integrity": "sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz", + "integrity": "sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==", + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.19.5" + } + }, + "stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "requires": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==" + }, + "strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==" + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "strip-literal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.1.tgz", + "integrity": "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==", + "dev": true, + "requires": { + "acorn": "^8.8.2" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==" + }, + "symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true + }, + "temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==" + }, + "tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "requires": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + } + }, + "terser": { + "version": "5.14.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.14.2.tgz", + "integrity": "sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==", + "requires": { + "@jridgewell/source-map": "^0.3.2", + "acorn": "^8.5.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "tinybench": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.3.1.tgz", + "integrity": "sha512-hGYWYBMPr7p4g5IarQE7XhlyWveh1EKhy4wUBS1LrHXCKYgvz+4/jCqgmJqZxxldesn05vccrtME2RLLZNW7iA==", + "dev": true + }, + "tinypool": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.3.1.tgz", + "integrity": "sha512-zLA1ZXlstbU2rlpA4CIeVaqvWq41MTWqLY3FfsAXgC8+f7Pk7zroaJQxDgxn1xNudKW6Kmj4808rPFShUlIRmQ==", + "dev": true + }, + "tinyspy": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-1.1.1.tgz", + "integrity": "sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g==", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg==", + "dev": true, + "requires": { + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.1.2" + } + }, + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dev": true, + "requires": { + "punycode": "^2.1.1" + } + }, + "tsconfig-paths": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.1.0.tgz", + "integrity": "sha512-AHx4Euop/dXFC+Vx589alFba8QItjF+8hf8LtmuiCwHyI4rHXQtOOENaM8kvYf5fR0dRChy3wzWIZ9WbB7FWow==", + "requires": { + "json5": "^2.2.1", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + } + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true + }, + "type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==" + }, + "typescript": { + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", + "dev": true + }, + "ufo": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.0.1.tgz", + "integrity": "sha512-boAm74ubXHY7KJQZLlXrtMz52qFvpsbOxDcZOnw/Wf+LS4Mmyu7JxmzD4tDLtUQtmZECypJ0FrCz4QIe6dvKRA==", + "dev": true + }, + "unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "requires": { + "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": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz", + "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==" + }, + "unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "requires": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz", + "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==" + }, + "unicode-property-aliases-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz", + "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==" + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==" + }, + "update-browserslist-db": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", + "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "peer": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "peer": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "peer": true + }, + "v8-compile-cache": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", + "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", + "dev": true + }, + "vite": { + "version": "2.9.15", + "resolved": "https://registry.npmjs.org/vite/-/vite-2.9.15.tgz", + "integrity": "sha512-fzMt2jK4vQ3yK56te3Kqpkaeq9DkcZfBbzHwYpobasvgYmP2SoAr6Aic05CsB4CzCZbsDv4sujX3pkEGhLabVQ==", + "requires": { + "esbuild": "^0.14.27", + "fsevents": "~2.3.2", + "postcss": "^8.4.13", + "resolve": "^1.22.0", + "rollup": ">=2.59.0 <2.78.0" + } + }, + "vite-node": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.28.5.tgz", + "integrity": "sha512-LmXb9saMGlrMZbXTvOveJKwMTBTNUH66c8rJnQ0ZPNX+myPEol64+szRzXtV5ORb0Hb/91yq+/D3oERoyAt6LA==", + "dev": true, + "requires": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "mlly": "^1.1.0", + "pathe": "^1.1.0", + "picocolors": "^1.0.0", + "source-map": "^0.6.1", + "source-map-support": "^0.5.21", + "vite": "^3.0.0 || ^4.0.0" + }, + "dependencies": { + "@esbuild/linux-loong64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", + "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", + "dev": true, + "optional": true + }, + "esbuild": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", + "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.16.17", + "@esbuild/android-arm64": "0.16.17", + "@esbuild/android-x64": "0.16.17", + "@esbuild/darwin-arm64": "0.16.17", + "@esbuild/darwin-x64": "0.16.17", + "@esbuild/freebsd-arm64": "0.16.17", + "@esbuild/freebsd-x64": "0.16.17", + "@esbuild/linux-arm": "0.16.17", + "@esbuild/linux-arm64": "0.16.17", + "@esbuild/linux-ia32": "0.16.17", + "@esbuild/linux-loong64": "0.16.17", + "@esbuild/linux-mips64el": "0.16.17", + "@esbuild/linux-ppc64": "0.16.17", + "@esbuild/linux-riscv64": "0.16.17", + "@esbuild/linux-s390x": "0.16.17", + "@esbuild/linux-x64": "0.16.17", + "@esbuild/netbsd-x64": "0.16.17", + "@esbuild/openbsd-x64": "0.16.17", + "@esbuild/sunos-x64": "0.16.17", + "@esbuild/win32-arm64": "0.16.17", + "@esbuild/win32-ia32": "0.16.17", + "@esbuild/win32-x64": "0.16.17" + } + }, + "rollup": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.15.0.tgz", + "integrity": "sha512-F9hrCAhnp5/zx/7HYmftvsNBkMfLfk/dXUh73hPSM2E3CRgap65orDNJbLetoiUFwSAk6iHPLvBrZ5iHYvzqsg==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "vite": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.1.1.tgz", + "integrity": "sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==", + "dev": true, + "requires": { + "esbuild": "^0.16.14", + "fsevents": "~2.3.2", + "postcss": "^8.4.21", + "resolve": "^1.22.1", + "rollup": "^3.10.0" + } + } + } + }, + "vite-plugin-pwa": { + "version": "0.12.3", + "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-0.12.3.tgz", + "integrity": "sha512-gmYdIVXpmBuNjzbJFPZFzxWYrX4lHqwMAlOtjmXBbxApiHjx9QPXKQPJjSpeTeosLKvVbNcKSAAhfxMda0QVNQ==", + "requires": { + "debug": "^4.3.4", + "fast-glob": "^3.2.11", + "pretty-bytes": "^6.0.0", + "rollup": "^2.75.7", + "workbox-build": "^6.5.3", + "workbox-window": "^6.5.3" + } + }, + "vite-tsconfig-paths": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-3.5.0.tgz", + "integrity": "sha512-NKIubr7gXgh/3uniQaOytSg+aKWPrjquP6anAy+zCWEn6h9fB8z2/qdlfQrTgZWaXJ2pHVlllrSdRZltHn9P4g==", + "requires": { + "debug": "^4.1.1", + "globrex": "^0.1.2", + "recrawl-sync": "^2.0.3", + "tsconfig-paths": "^4.0.0" + } + }, + "vitest": { + "version": "0.28.5", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.28.5.tgz", + "integrity": "sha512-pyCQ+wcAOX7mKMcBNkzDwEHRGqQvHUl0XnoHR+3Pb1hytAHISgSxv9h0gUiSiYtISXUU3rMrKiKzFYDrI6ZIHA==", + "dev": true, + "requires": { + "@types/chai": "^4.3.4", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "@vitest/expect": "0.28.5", + "@vitest/runner": "0.28.5", + "@vitest/spy": "0.28.5", + "@vitest/utils": "0.28.5", + "acorn": "^8.8.1", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", + "chai": "^4.3.7", + "debug": "^4.3.4", + "local-pkg": "^0.4.2", + "pathe": "^1.1.0", + "picocolors": "^1.0.0", + "source-map": "^0.6.1", + "std-env": "^3.3.1", + "strip-literal": "^1.0.0", + "tinybench": "^2.3.1", + "tinypool": "^0.3.1", + "tinyspy": "^1.0.2", + "vite": "^3.0.0 || ^4.0.0", + "vite-node": "0.28.5", + "why-is-node-running": "^2.2.2" + }, + "dependencies": { + "@esbuild/linux-loong64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", + "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", + "dev": true, + "optional": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "esbuild": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", + "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", + "dev": true, + "requires": { + "@esbuild/android-arm": "0.16.17", + "@esbuild/android-arm64": "0.16.17", + "@esbuild/android-x64": "0.16.17", + "@esbuild/darwin-arm64": "0.16.17", + "@esbuild/darwin-x64": "0.16.17", + "@esbuild/freebsd-arm64": "0.16.17", + "@esbuild/freebsd-x64": "0.16.17", + "@esbuild/linux-arm": "0.16.17", + "@esbuild/linux-arm64": "0.16.17", + "@esbuild/linux-ia32": "0.16.17", + "@esbuild/linux-loong64": "0.16.17", + "@esbuild/linux-mips64el": "0.16.17", + "@esbuild/linux-ppc64": "0.16.17", + "@esbuild/linux-riscv64": "0.16.17", + "@esbuild/linux-s390x": "0.16.17", + "@esbuild/linux-x64": "0.16.17", + "@esbuild/netbsd-x64": "0.16.17", + "@esbuild/openbsd-x64": "0.16.17", + "@esbuild/sunos-x64": "0.16.17", + "@esbuild/win32-arm64": "0.16.17", + "@esbuild/win32-ia32": "0.16.17", + "@esbuild/win32-x64": "0.16.17" + } + }, + "rollup": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.15.0.tgz", + "integrity": "sha512-F9hrCAhnp5/zx/7HYmftvsNBkMfLfk/dXUh73hPSM2E3CRgap65orDNJbLetoiUFwSAk6iHPLvBrZ5iHYvzqsg==", + "dev": true, + "requires": { + "fsevents": "~2.3.2" + } + }, + "vite": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.1.1.tgz", + "integrity": "sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==", + "dev": true, + "requires": { + "esbuild": "^0.16.14", + "fsevents": "~2.3.2", + "postcss": "^8.4.21", + "resolve": "^1.22.1", + "rollup": "^3.10.0" + } + } + } + }, + "vue": { + "version": "3.2.37", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.37.tgz", + "integrity": "sha512-bOKEZxrm8Eh+fveCqS1/NkG/n6aMidsI6hahas7pa0w/l7jkbssJVsRhVDs07IdDq7h9KHswZOgItnwJAgtVtQ==", + "requires": { + "@vue/compiler-dom": "3.2.37", + "@vue/compiler-sfc": "3.2.37", + "@vue/runtime-dom": "3.2.37", + "@vue/server-renderer": "3.2.37", + "@vue/shared": "3.2.37" + } + }, + "vue-eslint-parser": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz", + "integrity": "sha512-dzHGG3+sYwSf6zFBa0Gi9ZDshD7+ad14DGOdTLjruRVgZXe2J+DcZ9iUhyR48z5g1PqRa20yt3Njna/veLJL/g==", + "dev": true, + "requires": { + "debug": "^4.3.2", + "eslint-scope": "^7.0.0", + "eslint-visitor-keys": "^3.1.0", + "espree": "^9.0.0", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.5" + }, + "dependencies": { + "eslint-scope": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", + "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "semver": { + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "vue-next-select": { + "version": "2.10.4", + "resolved": "https://registry.npmjs.org/vue-next-select/-/vue-next-select-2.10.4.tgz", + "integrity": "sha512-9Lg1mD2h9w6mm4gkXPyVMWhOdUPtA/JF9VrNyo6mqjkh4ktGLVQpNhygVBCg13RFHdEq3iqawjeFmp3FJq+CUw==", + "requires": {} + }, + "vue-panzoom": { + "version": "git+ssh://git@github.com/thepaperpilot/vue-panzoom.git#fa3cc91f6842cdfbd1bfb433c75cac01f177fe2d", + "from": "vue-panzoom@https://github.com/thepaperpilot/vue-panzoom.git", + "requires": { + "panzoom": "^9.4.1" + } + }, + "vue-textarea-autosize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vue-textarea-autosize/-/vue-textarea-autosize-1.1.1.tgz", + "integrity": "sha512-B33Mg5ZDEfj/whhoPBLg25qqAdGHGM2NjDT99Qi5MXRyeLmXb4C3s6EprAHqy3nU0cooWXFU+IekI5DpoEbnFg==", + "requires": { + "core-js": "^2.6.5" + } + }, + "vue-toastification": { + "version": "2.0.0-rc.5", + "resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz", + "integrity": "sha512-q73e5jy6gucEO/U+P48hqX+/qyXDozAGmaGgLFm5tXX4wJBcVsnGp4e/iJqlm9xzHETYOilUuwOUje2Qg1JdwA==", + "requires": {} + }, + "vue-transition-expand": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/vue-transition-expand/-/vue-transition-expand-0.1.0.tgz", + "integrity": "sha512-4UKkK/ILk+Qh3WWJoupt7pXfzpjvb7vTQTaVUhnkr+FeXArndJVDyIn2eWIn7i37cVFXKu2jsDR47QELOCq/gQ==", + "requires": { + "vue": "^2.5.16" + }, + "dependencies": { + "@vue/compiler-sfc": { + "version": "2.7.9", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.9.tgz", + "integrity": "sha512-TD2FvT0fPUezw5RVP4tfwTZnKHP0QjeEUb39y7tORvOJQTjbOuHJEk4GPHUPsRaTeQ8rjuKjntyrYcEIx+ODxg==", + "requires": { + "@babel/parser": "^7.18.4", + "postcss": "^8.4.14", + "source-map": "^0.6.1" + } + }, + "csstype": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", + "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + }, + "vue": { + "version": "2.7.9", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.9.tgz", + "integrity": "sha512-GeWCvAUkjzD5q4A3vgi8ka5r9bM6g8fmNmx/9VnHDKCaEzBcoVw+7UcQktZHrJ2jhlI+Zv8L57pMCIwM4h4MWg==", + "requires": { + "@vue/compiler-sfc": "2.7.9", + "csstype": "^3.1.0" + } + } + } + }, + "vue-tsc": { + "version": "0.38.9", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-0.38.9.tgz", + "integrity": "sha512-Yoy5phgvGqyF98Fb4mYqboR4Q149jrdcGv5kSmufXJUq++RZJ2iMVG0g6zl+v3t4ORVWkQmRpsV4x2szufZ0LQ==", + "dev": true, + "requires": { + "@volar/vue-typescript": "0.38.9" + } + }, + "vuedraggable": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/vuedraggable/-/vuedraggable-4.1.0.tgz", + "integrity": "sha512-FU5HCWBmsf20GpP3eudURW3WdWTKIbEIQxh9/8GE806hydR9qZqRRxRE3RjqX7PkuLuMQG/A7n3cfj9rCEchww==", + "requires": { + "sortablejs": "1.14.0" + } + }, + "w3c-hr-time": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz", + "integrity": "sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==", + "dev": true, + "requires": { + "browser-process-hrtime": "^1.0.0" + } + }, + "w3c-xmlserializer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-3.0.0.tgz", + "integrity": "sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==", + "dev": true, + "requires": { + "xml-name-validator": "^4.0.0" + } + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true + }, + "whatwg-encoding": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-2.0.0.tgz", + "integrity": "sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==", + "dev": true, + "requires": { + "iconv-lite": "0.6.3" + } + }, + "whatwg-mimetype": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", + "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "dev": true + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + }, + "wheel": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wheel/-/wheel-1.0.0.tgz", + "integrity": "sha512-XiCMHibOiqalCQ+BaNSwRoZ9FDTAvOsXxGHXChBugewDj7HC8VBIER71dEOiRH1fSdLbRCQzngKTSiZ06ZQzeA==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "requires": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "workbox-background-sync": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.5.4.tgz", + "integrity": "sha512-0r4INQZMyPky/lj4Ou98qxcThrETucOde+7mRGJl13MPJugQNKeZQOdIJe/1AchOP23cTqHcN/YVpD6r8E6I8g==", + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "workbox-broadcast-update": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.5.4.tgz", + "integrity": "sha512-I/lBERoH1u3zyBosnpPEtcAVe5lwykx9Yg1k6f8/BGEPGaMMgZrwVrqL1uA9QZ1NGGFoyE6t9i7lBjOlDhFEEw==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-build": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.5.4.tgz", + "integrity": "sha512-kgRevLXEYvUW9WS4XoziYqZ8Q9j/2ziJYEtTrjdz5/L/cTUa2XfyMP2i7c3p34lgqJ03+mTiz13SdFef2POwbA==", + "requires": { + "@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.4", + "workbox-broadcast-update": "6.5.4", + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-google-analytics": "6.5.4", + "workbox-navigation-preload": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-range-requests": "6.5.4", + "workbox-recipes": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4", + "workbox-streams": "6.5.4", + "workbox-sw": "6.5.4", + "workbox-window": "6.5.4" + }, + "dependencies": { + "@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "requires": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + } + }, + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==" + }, + "source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "requires": { + "whatwg-url": "^7.0.0" + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "requires": { + "punycode": "^2.1.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + } + } + }, + "workbox-cacheable-response": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.5.4.tgz", + "integrity": "sha512-DCR9uD0Fqj8oB2TSWQEm1hbFs/85hXXoayVwFKLVuIuxwJaihBsLsp4y7J9bvZbqtPJ1KlCkmYVGQKrBU4KAug==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-core": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.5.4.tgz", + "integrity": "sha512-OXYb+m9wZm8GrORlV2vBbE5EC1FKu71GGp0H4rjmxmF4/HLbMCoTFws87M3dFwgpmg0v00K++PImpNQ6J5NQ6Q==" + }, + "workbox-expiration": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.5.4.tgz", + "integrity": "sha512-jUP5qPOpH1nXtjGGh1fRBa1wJL2QlIb5mGpct3NzepjGG2uFFBn4iiEBiI9GUmfAFR2ApuRhDydjcRmYXddiEQ==", + "requires": { + "idb": "^7.0.1", + "workbox-core": "6.5.4" + } + }, + "workbox-google-analytics": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.5.4.tgz", + "integrity": "sha512-8AU1WuaXsD49249Wq0B2zn4a/vvFfHkpcFfqAFHNHwln3jK9QUYmzdkKXGIZl9wyKNP+RRX30vcgcyWMcZ9VAg==", + "requires": { + "workbox-background-sync": "6.5.4", + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-navigation-preload": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.5.4.tgz", + "integrity": "sha512-IIwf80eO3cr8h6XSQJF+Hxj26rg2RPFVUmJLUlM0+A2GzB4HFbQyKkrgD5y2d84g2IbJzP4B4j5dPBRzamHrng==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-precaching": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.5.4.tgz", + "integrity": "sha512-hSMezMsW6btKnxHB4bFy2Qfwey/8SYdGWvVIKFaUm8vJ4E53JAY+U2JwLTRD8wbLWoP6OVUdFlXsTdKu9yoLTg==", + "requires": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-range-requests": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.5.4.tgz", + "integrity": "sha512-Je2qR1NXCFC8xVJ/Lux6saH6IrQGhMpDrPXWZWWS8n/RD+WZfKa6dSZwU+/QksfEadJEr/NfY+aP/CXFFK5JFg==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-recipes": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.5.4.tgz", + "integrity": "sha512-QZNO8Ez708NNwzLNEXTG4QYSKQ1ochzEtRLGaq+mr2PyoEIC1xFW7MrWxrONUxBFOByksds9Z4//lKAX8tHyUA==", + "requires": { + "workbox-cacheable-response": "6.5.4", + "workbox-core": "6.5.4", + "workbox-expiration": "6.5.4", + "workbox-precaching": "6.5.4", + "workbox-routing": "6.5.4", + "workbox-strategies": "6.5.4" + } + }, + "workbox-routing": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.5.4.tgz", + "integrity": "sha512-apQswLsbrrOsBUWtr9Lf80F+P1sHnQdYodRo32SjiByYi36IDyL2r7BH1lJtFX8fwNHDa1QOVY74WKLLS6o5Pg==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-strategies": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.5.4.tgz", + "integrity": "sha512-DEtsxhx0LIYWkJBTQolRxG4EI0setTJkqR4m7r4YpBdxtWJH1Mbg01Cj8ZjNOO8etqfA3IZaOPHUxCs8cBsKLw==", + "requires": { + "workbox-core": "6.5.4" + } + }, + "workbox-streams": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.5.4.tgz", + "integrity": "sha512-FXKVh87d2RFXkliAIheBojBELIPnWbQdyDvsH3t74Cwhg0fDheL1T8BqSM86hZvC0ZESLsznSYWw+Va+KVbUzg==", + "requires": { + "workbox-core": "6.5.4", + "workbox-routing": "6.5.4" + } + }, + "workbox-sw": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.5.4.tgz", + "integrity": "sha512-vo2RQo7DILVRoH5LjGqw3nphavEjK4Qk+FenXeUsknKn14eCNedHOXWbmnvP4ipKhlE35pvJ4yl4YYf6YsJArA==" + }, + "workbox-window": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.5.4.tgz", + "integrity": "sha512-HnLZJDwYBE+hpG25AQBO8RUWBJRaCsI9ksQJEp3aCOFCaG5kqaToAYXFRAHxzRluM2cQbGzdQF5rjKPWPA1fug==", + "requires": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "6.5.4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "ws": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz", + "integrity": "sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==", + "dev": true, + "requires": {} + }, + "xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true + }, + "xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8403380 --- /dev/null +++ b/package.json @@ -0,0 +1,57 @@ +{ + "name": "profectus", + "version": "0.5.2", + "private": true, + "scripts": { + "start": "vite", + "dev": "vite", + "build": "vue-tsc --noEmit && vite build", + "preview": "vite preview", + "test": "vitest run", + "testw": "vitest", + "serve": "vite preview --host" + }, + "dependencies": { + "@fontsource/material-icons": "^4.5.4", + "@fontsource/roboto-mono": "^4.5.8", + "@pixi/app": "~6.3.2", + "@pixi/constants": "~6.3.2", + "@pixi/core": "~6.3.2", + "@pixi/display": "~6.3.2", + "@pixi/math": "~6.3.2", + "@pixi/particle-emitter": "^5.0.7", + "@pixi/sprite": "~6.3.2", + "@pixi/ticker": "~6.3.2", + "@vitejs/plugin-vue": "^2.3.3", + "@vitejs/plugin-vue-jsx": "^1.3.10", + "is-plain-object": "^5.0.0", + "lz-string": "^1.4.4", + "nanoevents": "^6.0.2", + "vite": "^2.9.12", + "vite-plugin-pwa": "^0.12.0", + "vite-tsconfig-paths": "^3.5.0", + "vue": "^3.2.26", + "vue-next-select": "^2.10.2", + "vue-panzoom": "https://github.com/thepaperpilot/vue-panzoom.git", + "vue-textarea-autosize": "^1.1.1", + "vue-toastification": "^2.0.0-rc.1", + "vue-transition-expand": "^0.1.0", + "vuedraggable": "^4.1.0" + }, + "devDependencies": { + "@ivanv/vue-collapse-transition": "^1.0.2", + "@rushstack/eslint-patch": "^1.1.0", + "@types/lz-string": "^1.3.34", + "@vue/eslint-config-prettier": "^7.0.0", + "@vue/eslint-config-typescript": "^10.0.0", + "eslint": "^8.6.0", + "jsdom": "^20.0.0", + "prettier": "^2.5.1", + "typescript": "^4.7.4", + "vitest": "^0.28.5", + "vue-tsc": "^0.38.1" + }, + "engines": { + "node": "16.x" + } +} diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000..e570640 Binary files /dev/null and b/public/apple-touch-icon.png differ diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..028a67e Binary files /dev/null and b/public/favicon.ico differ diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..afa6845 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/pwa-192x192.png b/public/pwa-192x192.png new file mode 100644 index 0000000..00eaafd Binary files /dev/null and b/public/pwa-192x192.png differ diff --git a/public/pwa-512x512.png b/public/pwa-512x512.png new file mode 100644 index 0000000..1ad85e8 Binary files /dev/null and b/public/pwa-512x512.png differ diff --git a/public/robots.txt b/public/robots.txt new file mode 100644 index 0000000..c2a49f4 --- /dev/null +++ b/public/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Allow: / diff --git a/replit.nix b/replit.nix new file mode 100644 index 0000000..1b59d2e --- /dev/null +++ b/replit.nix @@ -0,0 +1,7 @@ +{ pkgs }: { + deps = [ + pkgs.nodejs-16_x + pkgs.nodePackages.typescript-language-server + pkgs.nodePackages.npm + ]; +} diff --git a/saves/.placehold b/saves/.placehold new file mode 100644 index 0000000..e69de29 diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..6535b0a --- /dev/null +++ b/src/App.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/src/components/Context.vue b/src/components/Context.vue new file mode 100644 index 0000000..33cbf2b --- /dev/null +++ b/src/components/Context.vue @@ -0,0 +1,89 @@ + + + + + diff --git a/src/components/Game.vue b/src/components/Game.vue new file mode 100644 index 0000000..680273a --- /dev/null +++ b/src/components/Game.vue @@ -0,0 +1,91 @@ + + + + + + + diff --git a/src/components/GameOverScreen.vue b/src/components/GameOverScreen.vue new file mode 100644 index 0000000..999554d --- /dev/null +++ b/src/components/GameOverScreen.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/src/components/Hotkey.vue b/src/components/Hotkey.vue new file mode 100644 index 0000000..7e9c876 --- /dev/null +++ b/src/components/Hotkey.vue @@ -0,0 +1,70 @@ + + + + + + + diff --git a/src/components/Info.vue b/src/components/Info.vue new file mode 100644 index 0000000..24a15e8 --- /dev/null +++ b/src/components/Info.vue @@ -0,0 +1,131 @@ + + + + + diff --git a/src/components/Layer.vue b/src/components/Layer.vue new file mode 100644 index 0000000..a3fffda --- /dev/null +++ b/src/components/Layer.vue @@ -0,0 +1,209 @@ + + + + + + + diff --git a/src/components/MarkNode.vue b/src/components/MarkNode.vue new file mode 100644 index 0000000..c730279 --- /dev/null +++ b/src/components/MarkNode.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/src/components/Modal.vue b/src/components/Modal.vue new file mode 100644 index 0000000..9fd5f06 --- /dev/null +++ b/src/components/Modal.vue @@ -0,0 +1,139 @@ + + + + + diff --git a/src/components/NaNScreen.vue b/src/components/NaNScreen.vue new file mode 100644 index 0000000..511d1b6 --- /dev/null +++ b/src/components/NaNScreen.vue @@ -0,0 +1,130 @@ + + + + + diff --git a/src/components/Nav.vue b/src/components/Nav.vue new file mode 100644 index 0000000..b265635 --- /dev/null +++ b/src/components/Nav.vue @@ -0,0 +1,271 @@ + + + + + diff --git a/src/components/Node.vue b/src/components/Node.vue new file mode 100644 index 0000000..7f5b118 --- /dev/null +++ b/src/components/Node.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/src/components/Notif.vue b/src/components/Notif.vue new file mode 100644 index 0000000..583117a --- /dev/null +++ b/src/components/Notif.vue @@ -0,0 +1,43 @@ + + + + + diff --git a/src/components/Options.vue b/src/components/Options.vue new file mode 100644 index 0000000..93b57fa --- /dev/null +++ b/src/components/Options.vue @@ -0,0 +1,167 @@ + + + + + diff --git a/src/components/Profectus.vue b/src/components/Profectus.vue new file mode 100644 index 0000000..3a7700b --- /dev/null +++ b/src/components/Profectus.vue @@ -0,0 +1,195 @@ + + + diff --git a/src/components/Save.vue b/src/components/Save.vue new file mode 100644 index 0000000..1ff2496 --- /dev/null +++ b/src/components/Save.vue @@ -0,0 +1,204 @@ + + + + + + + diff --git a/src/components/SavesManager.vue b/src/components/SavesManager.vue new file mode 100644 index 0000000..91edd40 --- /dev/null +++ b/src/components/SavesManager.vue @@ -0,0 +1,334 @@ + + + + + + + diff --git a/src/components/TPS.vue b/src/components/TPS.vue new file mode 100644 index 0000000..a460a09 --- /dev/null +++ b/src/components/TPS.vue @@ -0,0 +1,53 @@ + + + + + diff --git a/src/components/common/features.css b/src/components/common/features.css new file mode 100644 index 0000000..cbed01a --- /dev/null +++ b/src/components/common/features.css @@ -0,0 +1,38 @@ +.feature:not(li), +.feature:not(li) button { + position: relative; + padding: 5px; + border-radius: var(--border-radius); + border: 2px solid rgba(0, 0, 0, 0.125); + margin: var(--feature-margin); + box-sizing: border-box; + color: var(--feature-foreground); + z-index: 0; + transition: all 0.5s, z-index 0s 0.5s; +} + +.can, +.can button { + background-color: var(--layer-color); + cursor: pointer; +} + +.can:hover, +.can:hover button { + transform: scale(1.15, 1.15); + box-shadow: 0 0 20px var(--points); + z-index: 1; + transition: all 0.5s, z-index 0s; +} + +.locked, +.locked button { + background-color: var(--locked); + cursor: not-allowed; +} + +.bought, +.bought button { + background-color: var(--bought); + cursor: default; +} diff --git a/src/components/common/fields.css b/src/components/common/fields.css new file mode 100644 index 0000000..48737e1 --- /dev/null +++ b/src/components/common/fields.css @@ -0,0 +1,13 @@ +.field { + display: flex; + position: relative; + min-height: 2em; + margin: 10px 0; + user-select: none; + justify-content: space-between; + align-items: center; +} + +.field > * { + margin: 0; +} diff --git a/src/components/common/modifiers.css b/src/components/common/modifiers.css new file mode 100644 index 0000000..dc9e66d --- /dev/null +++ b/src/components/common/modifiers.css @@ -0,0 +1,21 @@ +.modifier-container { + display: flex; + padding: 1px 8px; +} + +.modifier-container:nth-child(2n) { + background: var(--raised-background); +} + +.modifier-amount { + flex-shrink: 0; + text-align: right; +} +:not(:first-of-type, :last-of-type) > .modifier-amount::after { + content: var(--unit); + opacity: 0; +} + +.modifier-description { + flex-grow: 1; +} diff --git a/src/components/common/table.css b/src/components/common/table.css new file mode 100644 index 0000000..a48d191 --- /dev/null +++ b/src/components/common/table.css @@ -0,0 +1,128 @@ +.table { + display: flex; + flex-flow: column wrap; + justify-content: center; + align-items: center; + max-width: 100%; + margin: 0 auto; +} + +.table + .table { + margin-top: 10px; +} + +.row { + display: flex; + flex-flow: row wrap; + justify-content: center; + align-items: stretch; + max-width: 100%; + margin: 0 10px; +} + +.row > :not(.feature) { + margin: 0; + display: flex; +} + +.col { + display: flex; + flex-flow: column wrap; + justify-content: center; + align-items: center; + height: 100%; + margin: 10px 0; +} + +.row.mergeAdjacent > .feature:not(.dontMerge), +.row.mergeAdjacent > .tooltip-container > .feature:not(.dontMerge) { + margin-left: 0; + margin-right: 0; + border-radius: 0; +} + +.row.mergeAdjacent > .feature:not(.dontMerge):first-child, +.row.mergeAdjacent > .tooltip-container:first-child > .feature:not(.dontMerge) { + border-radius: var(--border-radius) 0 0 var(--border-radius); +} + +.row.mergeAdjacent > .feature:not(.dontMerge):last-child, +.row.mergeAdjacent > .tooltip-container:last-child > .feature:not(.dontMerge) { + border-radius: 0 var(--border-radius) var(--border-radius) 0; +} + +.row.mergeAdjacent > .feature:not(.dontMerge):first-child:last-child, +.row.mergeAdjacent > .tooltip-container:first-child:last-child > .feature:not(.dontMerge) { + border-radius: var(--border-radius); +} + +.row-grid.mergeAdjacent > .feature:not(.dontMerge), +.row-grid.mergeAdjacent > .tooltip-container > .feature:not(.dontMerge) { + margin-left: 0; + margin-right: 0; + margin-bottom: 0; + margin-top: 0; + border-radius: 0; +} + +.row-grid.mergeAdjacent > .feature:not(.dontMerge):last-child, +.row-grid.mergeAdjacent > .tooltip-container:last-child > .feature:not(.dontMerge) { + border-radius: 0 0 0 0; +} + + +.row-grid.mergeAdjacent > .feature:not(.dontMerge):first-child, +.row-grid.mergeAdjacent > .tooltip-container:first-child > .feature:not(.dontMerge) { + border-radius: 0 0 0 0; +} + +.table-grid > .row-grid.mergeAdjacent:last-child > .feature:not(.dontMerge):first-child { + border-radius: 0 0 0 var(--border-radius); +} + +.table-grid > .row-grid.mergeAdjacent:first-child > .feature:not(.dontMerge):last-child { + border-radius: 0 var(--border-radius) 0 0; +} + +.table-grid > .row-grid.mergeAdjacent:first-child > .feature:not(.dontMerge):first-child { + border-radius: var(--border-radius) 0 0 0; +} + +.table-grid > .row-grid.mergeAdjacent:last-child > .feature:not(.dontMerge):last-child { + border-radius: 0 0 var(--border-radius) 0; +} + + +/* +TODO how to implement mergeAdjacent for grids? +.row.mergeAdjacent + .row.mergeAdjacent > .feature:not(.dontMerge) { + border-top-left-radius: 0; + border-top-right-radius: 0; +} +*/ + +.col.mergeAdjacent .feature:not(.dontMerge) { + margin-top: 0; + margin-bottom: 0; + border-radius: 0; +} + +.col.mergeAdjacent .feature:not(.dontMerge):first-child { + border-radius: var(--border-radius) var(--border-radius) 0 0; +} + +.col.mergeAdjacent .feature:not(.dontMerge):last-child { + border-radius: 0 0 var(--border-radius) var(--border-radius); +} + +.col.mergeAdjacent .feature:not(.dontMerge):first-child:last-child { + border-radius: var(--border-radius); +} + +/* +TODO how to implement mergeAdjacent for grids? +.col.mergeAdjacent + .col.mergeAdjacent > .feature:not(.dontMerge) { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} +*/ diff --git a/src/components/fields/DangerButton.vue b/src/components/fields/DangerButton.vue new file mode 100644 index 0000000..9fb1836 --- /dev/null +++ b/src/components/fields/DangerButton.vue @@ -0,0 +1,78 @@ + + + + + + + diff --git a/src/components/fields/FeedbackButton.vue b/src/components/fields/FeedbackButton.vue new file mode 100644 index 0000000..42dcdaa --- /dev/null +++ b/src/components/fields/FeedbackButton.vue @@ -0,0 +1,74 @@ + + + + + diff --git a/src/components/fields/Select.vue b/src/components/fields/Select.vue new file mode 100644 index 0000000..72a31b2 --- /dev/null +++ b/src/components/fields/Select.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/src/components/fields/Slider.vue b/src/components/fields/Slider.vue new file mode 100644 index 0000000..1b1e9a8 --- /dev/null +++ b/src/components/fields/Slider.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/src/components/fields/Text.vue b/src/components/fields/Text.vue new file mode 100644 index 0000000..397ccfd --- /dev/null +++ b/src/components/fields/Text.vue @@ -0,0 +1,99 @@ + + + + + diff --git a/src/components/fields/Toggle.vue b/src/components/fields/Toggle.vue new file mode 100644 index 0000000..4017033 --- /dev/null +++ b/src/components/fields/Toggle.vue @@ -0,0 +1,117 @@ + + + + + diff --git a/src/components/layout/Collapsible.vue b/src/components/layout/Collapsible.vue new file mode 100644 index 0000000..b9ef1f3 --- /dev/null +++ b/src/components/layout/Collapsible.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/src/components/layout/Column.vue b/src/components/layout/Column.vue new file mode 100644 index 0000000..c9dd027 --- /dev/null +++ b/src/components/layout/Column.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/components/layout/Row.vue b/src/components/layout/Row.vue new file mode 100644 index 0000000..861c9ff --- /dev/null +++ b/src/components/layout/Row.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/components/layout/Spacer.vue b/src/components/layout/Spacer.vue new file mode 100644 index 0000000..a5cfa56 --- /dev/null +++ b/src/components/layout/Spacer.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/components/layout/Sticky.vue b/src/components/layout/Sticky.vue new file mode 100644 index 0000000..d761210 --- /dev/null +++ b/src/components/layout/Sticky.vue @@ -0,0 +1,49 @@ + + + + + diff --git a/src/components/layout/VerticalRule.vue b/src/components/layout/VerticalRule.vue new file mode 100644 index 0000000..04a8adf --- /dev/null +++ b/src/components/layout/VerticalRule.vue @@ -0,0 +1,18 @@ + + + + + diff --git a/src/components/math/Floor.vue b/src/components/math/Floor.vue new file mode 100644 index 0000000..7010c59 --- /dev/null +++ b/src/components/math/Floor.vue @@ -0,0 +1,5 @@ + diff --git a/src/components/math/Fraction.vue b/src/components/math/Fraction.vue new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/components/math/Fraction.vue @@ -0,0 +1 @@ + diff --git a/src/components/math/Sqrt.vue b/src/components/math/Sqrt.vue new file mode 100644 index 0000000..461846f --- /dev/null +++ b/src/components/math/Sqrt.vue @@ -0,0 +1,8 @@ + diff --git a/src/data/Changelog.vue b/src/data/Changelog.vue new file mode 100644 index 0000000..54e53a5 --- /dev/null +++ b/src/data/Changelog.vue @@ -0,0 +1,83 @@ + + + + + diff --git a/src/data/common.css b/src/data/common.css new file mode 100644 index 0000000..728c160 --- /dev/null +++ b/src/data/common.css @@ -0,0 +1,9 @@ +.modifier-toggle { + padding-right: 10px; + transform: translateY(-1px); + display: inline-block; +} + +.modifier-toggle.collapsed { + transform: translate(-5px, -5px) rotate(-90deg); +} diff --git a/src/data/common.tsx b/src/data/common.tsx new file mode 100644 index 0000000..9f1436f --- /dev/null +++ b/src/data/common.tsx @@ -0,0 +1,492 @@ +import Collapsible from "components/layout/Collapsible.vue"; +import type { Clickable, ClickableOptions, GenericClickable } from "features/clickables/clickable"; +import { createClickable } from "features/clickables/clickable"; +import type { GenericConversion } from "features/conversion"; +import type { CoercableComponent, JSXFunction, OptionsFunc, Replace } from "features/feature"; +import { jsx, setDefault } from "features/feature"; +import { GenericMilestone } from "features/milestones/milestone"; +import { displayResource, Resource } from "features/resources/resource"; +import type { GenericTree, GenericTreeNode, TreeNode, TreeNodeOptions } from "features/trees/tree"; +import { createTreeNode } from "features/trees/tree"; +import { GenericFormula } from "game/formulas"; +import type { Modifier } from "game/modifiers"; +import type { Persistent } from "game/persistence"; +import { DefaultValue, persistent } from "game/persistence"; +import player from "game/player"; +import settings from "game/settings"; +import type { DecimalSource } from "util/bignum"; +import Decimal, { format, formatSmall, formatTime } from "util/bignum"; +import type { WithRequired } from "util/common"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { convertComputable, processComputable } from "util/computed"; +import { getFirstFeature, renderColJSX, renderJSX } from "util/vue"; +import type { ComputedRef, Ref } from "vue"; +import { computed, unref } from "vue"; +import "./common.css"; + +/** An object that configures a {@link ResetButton} */ +export interface ResetButtonOptions extends ClickableOptions { + /** The conversion the button uses to calculate how much resources will be gained on click */ + conversion: GenericConversion; + /** The tree this reset button is apart of */ + tree: GenericTree; + /** The specific tree node associated with this reset button */ + treeNode: GenericTreeNode; + /** + * Text to display on low conversion amounts, describing what "resetting" is in this context. + * Defaults to "Reset for ". + */ + resetDescription?: Computable; + /** Whether or not to show how much currency would be required to make the gain amount increase. */ + showNextAt?: Computable; + /** + * The content to display on the button. + * By default, this includes the reset description, and amount of currency to be gained. + */ + display?: Computable; + /** + * Whether or not this button can currently be clicked. + * Defaults to checking the current gain amount is greater than {@link minimumGain} + */ + canClick?: Computable; + /** + * When {@link canClick} is left to its default, minimumGain is used to only enable the reset button when a sufficient amount of currency to gain is available. + */ + minimumGain?: Computable; + /** A persistent ref to track how much time has passed since the last time this tree node was reset. */ + resetTime?: Persistent; +} + +/** + * A button that is used to control a conversion. + * It will show how much can be converted currently, and can show when that amount will go up, as well as handle only being clickable when a sufficient amount of currency can be gained. + * Assumes this button is associated with a specific node on a tree, and triggers that tree's reset propagation. + */ +export type ResetButton = Replace< + Clickable, + { + resetDescription: GetComputableTypeWithDefault>; + showNextAt: GetComputableTypeWithDefault; + display: GetComputableTypeWithDefault>; + canClick: GetComputableTypeWithDefault>; + minimumGain: GetComputableTypeWithDefault; + onClick: (event?: MouseEvent | TouchEvent) => void; + } +>; + +/** A type that matches any valid {@link ResetButton} object. */ +export type GenericResetButton = Replace< + GenericClickable & ResetButton, + { + resetDescription: ProcessedComputable; + showNextAt: ProcessedComputable; + display: ProcessedComputable; + canClick: ProcessedComputable; + minimumGain: ProcessedComputable; + } +>; + +/** + * Lazily creates a reset button with the given options. + * @param optionsFunc A function that returns the options object for this reset button. + */ +export function createResetButton( + optionsFunc: OptionsFunc +): ResetButton { + return createClickable(() => { + const resetButton = optionsFunc(); + + processComputable(resetButton as T, "showNextAt"); + setDefault(resetButton, "showNextAt", true); + setDefault(resetButton, "minimumGain", 1); + + if (resetButton.resetDescription == null) { + resetButton.resetDescription = computed(() => + Decimal.lt(resetButton.conversion.gainResource.value, 1e3) ? "Reset for " : "" + ); + } else { + processComputable(resetButton as T, "resetDescription"); + } + + if (resetButton.display == null) { + resetButton.display = jsx(() => ( + + {unref(resetButton.resetDescription as ProcessedComputable)} + + {displayResource( + resetButton.conversion.gainResource, + Decimal.max( + unref(resetButton.conversion.actualGain), + unref(resetButton.minimumGain as ProcessedComputable) + ) + )} + {" "} + {resetButton.conversion.gainResource.displayName} + {unref(resetButton.showNextAt) != null ? ( +
+
+ {unref(resetButton.conversion.buyMax) ? "Next:" : "Req:"}{" "} + {displayResource( + resetButton.conversion.baseResource, + unref(resetButton.conversion.buyMax) || + Decimal.floor(unref(resetButton.conversion.actualGain)).neq(1) + ? unref(resetButton.conversion.nextAt) + : unref(resetButton.conversion.currentAt) + )}{" "} + {resetButton.conversion.baseResource.displayName} +
+ ) : null} +
+ )); + } + + if (resetButton.canClick == null) { + resetButton.canClick = computed(() => + Decimal.gte( + unref(resetButton.conversion.actualGain), + unref(resetButton.minimumGain as ProcessedComputable) + ) + ); + } + + const onClick = resetButton.onClick; + resetButton.onClick = function (event?: MouseEvent | TouchEvent) { + if (unref(resetButton.canClick) === false) { + return; + } + resetButton.conversion.convert(); + resetButton.tree.reset(resetButton.treeNode); + if (resetButton.resetTime) { + resetButton.resetTime.value = resetButton.resetTime[DefaultValue]; + } + onClick?.(event); + }; + + return resetButton; + }) as unknown as ResetButton; +} + +/** An object that configures a {@link LayerTreeNode} */ +export interface LayerTreeNodeOptions extends TreeNodeOptions { + /** The ID of the layer this tree node is associated with */ + layerID: string; + /** The color to display this tree node as */ + color: Computable; // marking as required + /** + * The content to display in the tree node. + * Defaults to the layer's ID + */ + display?: Computable; + /** Whether or not to append the layer to the tabs list. + * If set to false, then the tree node will instead always remove all tabs to its right and then add the layer tab. + * Defaults to true. + */ + append?: Computable; +} +/** A tree node that is associated with a given layer, and which opens the layer when clicked. */ +export type LayerTreeNode = Replace< + TreeNode, + { + display: GetComputableTypeWithDefault; + append: GetComputableType; + } +>; +/** A type that matches any valid {@link LayerTreeNode} object. */ +export type GenericLayerTreeNode = Replace< + LayerTreeNode, + { + display: ProcessedComputable; + append?: ProcessedComputable; + } +>; + +/** + * Lazily creates a tree node that's associated with a specific layer, with the given options. + * @param optionsFunc A function that returns the options object for this tree node. + */ +export function createLayerTreeNode( + optionsFunc: OptionsFunc +): LayerTreeNode { + return createTreeNode(() => { + const options = optionsFunc(); + processComputable(options as T, "display"); + setDefault(options, "display", options.layerID); + processComputable(options as T, "append"); + return { + ...options, + display: options.display, + onClick: unref((options as unknown as GenericLayerTreeNode).append) + ? function () { + if (player.tabs.includes(options.layerID)) { + const index = player.tabs.lastIndexOf(options.layerID); + player.tabs.splice(index, 1); + } else { + player.tabs.push(options.layerID); + } + } + : function () { + player.tabs.splice(1, 1, options.layerID); + } + }; + }) as unknown as LayerTreeNode; +} + +/** An option object for a modifier display as a single section. **/ +export interface Section { + /** The header for this modifier. **/ + title: Computable; + /** A subtitle for this modifier, e.g. to explain the context for the modifier. **/ + subtitle?: Computable; + /** The modifier to be displaying in this section. **/ + modifier: WithRequired; + /** The base value being modified. **/ + base?: Computable; + /** The unit of measurement for the base. **/ + unit?: string; + /** The label to call the base amount. Defaults to "Base". **/ + baseText?: Computable; + /** Whether or not this section should be currently visible to the player. **/ + visible?: Computable; +} + +/** + * Takes an array of modifier "sections", and creates a JSXFunction that can render all those sections, and allow each section to be collapsed. + * Also returns a list of persistent refs that are used to control which sections are currently collapsed. + * @param sectionsFunc A function that returns the sections to display. + * @param smallerIsBetter Determines whether numbers larger or smaller than the base should be displayed as red. + */ +export function createCollapsibleModifierSections( + sectionsFunc: () => Section[], + smallerIsBetter = false +): [JSXFunction, Persistent>] { + const sections: Section[] = []; + const processed: + | { + base: ProcessedComputable[]; + baseText: ProcessedComputable[]; + visible: ProcessedComputable[]; + title: ProcessedComputable[]; + subtitle: ProcessedComputable[]; + } + | Record = {}; + let calculated = false; + function calculateSections() { + if (!calculated) { + sections.push(...sectionsFunc()); + processed.base = sections.map(s => convertComputable(s.base)); + processed.baseText = sections.map(s => convertComputable(s.baseText)); + processed.visible = sections.map(s => convertComputable(s.visible)); + processed.title = sections.map(s => convertComputable(s.title)); + processed.subtitle = sections.map(s => convertComputable(s.subtitle)); + calculated = true; + } + return sections; + } + + const collapsed = persistent>({}); + const jsxFunc = jsx(() => { + const sections = calculateSections(); + + let firstVisibleSection = true; + const sectionJSX = sections.map((s, i) => { + if (unref(processed.visible[i]) === false) return null; + const header = ( +

(collapsed.value[i] = !collapsed.value[i])} + style="cursor: pointer" + > + + ▼ + + {unref(processed.title[i])} + {unref(processed.subtitle[i]) != null ? ( + ({unref(processed.subtitle[i])}) + ) : null} +

+ ); + + const modifiers = unref(collapsed.value[i]) ? null : ( + <> +
+ + {renderJSX(unref(processed.baseText[i]) ?? "Base")} + + + {format(unref(processed.base[i]) ?? 1)} + {s.unit} + +
+ {renderJSX(unref(s.modifier.description))} + + ); + + const hasPreviousSection = !firstVisibleSection; + firstVisibleSection = false; + + const base = unref(processed.base[i]) ?? 1; + const total = s.modifier.apply(base); + + return ( + <> + {hasPreviousSection ?
: null} +
+ {header} +
+ {modifiers} +
+
+ Total + + {formatSmall(total)} + {s.unit} + +
+
+ + ); + }); + return <>{sectionJSX}; + }); + return [jsxFunc, collapsed]; +} + +/** + * Creates an HTML string for a span that writes some given text in a given color. + * @param textToColor The content to change the color of + * @param color The color to change the content to look like. Defaults to the current theme's accent 2 variable. + */ +export function colorText(textToColor: string, color = "var(--accent2)"): JSX.Element { + return {textToColor}; +} + +/** + * Creates a collapsible display of a list of milestones + * @param milestones A dictionary of the milestones to display, inserted in the order from easiest to hardest + */ +export function createCollapsibleMilestones(milestones: Record) { + // Milestones are typically defined from easiest to hardest, and we want to show hardest first + const orderedMilestones = Object.values(milestones).reverse(); + const collapseMilestones = persistent(true); + const lockedMilestones = computed(() => + orderedMilestones.filter(m => m.earned.value === false) + ); + const { firstFeature, collapsedContent, hasCollapsedContent } = getFirstFeature( + orderedMilestones, + m => m.earned.value + ); + const display = jsx(() => { + const milestonesToDisplay = [...lockedMilestones.value]; + if (firstFeature.value) { + milestonesToDisplay.push(firstFeature.value); + } + return renderColJSX( + ...milestonesToDisplay, + jsx(() => ( + + )) + ); + }); + return { + collapseMilestones, + display + }; +} + +/** + * Utility function for getting an ETA for when a target will be reached by a resource with a known (and assumed consistent) gain. + * @param resource The resource that will be increasing over time. + * @param rate The rate at which the resource is increasing. + * @param target The target amount of the resource to estimate the duration until. + */ +export function estimateTime( + resource: Resource, + rate: Computable, + target: Computable +) { + const processedRate = convertComputable(rate); + const processedTarget = convertComputable(target); + return computed(() => { + const currRate = unref(processedRate); + const currTarget = unref(processedTarget); + if (Decimal.gte(resource.value, currTarget)) { + return "Now"; + } else if (Decimal.lt(currRate, 0)) { + return "Never"; + } + return formatTime(Decimal.sub(currTarget, resource.value).div(currRate)); + }); +} + +/** + * Utility function for displaying the result of a formula such that it will, when told to, preview how the formula's result will change. + * Requires a formula with a single variable inside. + * @param formula The formula to display the result of. + * @param showPreview Whether or not to preview how the formula's result will change. + * @param previewAmount The amount to _add_ to the current formula's variable amount to preview the change in result. + */ +export function createFormulaPreview( + formula: GenericFormula, + showPreview: Computable, + previewAmount: Computable = 1 +): ComputedRef { + const processedShowPreview = convertComputable(showPreview); + const processedPreviewAmount = convertComputable(previewAmount); + if (!formula.hasVariable()) { + throw "Cannot create formula preview if the formula does not have a variable"; + } + return computed(() => { + if (unref(processedShowPreview)) { + const curr = formatSmall(formula.evaluate()); + const preview = formatSmall( + formula.evaluate( + Decimal.add( + unref(formula.innermostVariable ?? 0), + unref(processedPreviewAmount) + ) + ) + ); + return jsx(() => ( + <> + + + {curr}→{preview} + + + + )); + } + return formatSmall(formula.evaluate()); + }); +} diff --git a/src/data/layers/prestige.tsx b/src/data/layers/prestige.tsx new file mode 100644 index 0000000..4490ded --- /dev/null +++ b/src/data/layers/prestige.tsx @@ -0,0 +1,73 @@ +/** + * @module + * @hidden + */ +import { main } from "data/projEntry"; +import { createCumulativeConversion, createPolynomialScaling } from "features/conversion"; +import { jsx } from "features/feature"; +import { createHotkey } from "features/hotkey"; +import { createReset } from "features/reset"; +import MainDisplay from "features/resources/MainDisplay.vue"; +import { createResource } from "features/resources/resource"; +import { addTooltip } from "features/tooltips/tooltip"; +import { createResourceTooltip } from "features/trees/tree"; +import { BaseLayer, createLayer } from "game/layers"; +import type { DecimalSource } from "util/bignum"; +import { render } from "util/vue"; +import { createLayerTreeNode, createResetButton } from "../common"; + +const id = "p"; +const layer = createLayer(id, function (this: BaseLayer) { + const name = "Prestige"; + const color = "#4BDC13"; + const points = createResource(0, "prestige points"); + + const conversion = createCumulativeConversion(() => ({ + scaling: createPolynomialScaling(10, 0.5), + baseResource: main.points, + gainResource: points, + roundUpCost: true + })); + + const reset = createReset(() => ({ + thingsToReset: (): Record[] => [layer] + })); + + const treeNode = createLayerTreeNode(() => ({ + layerID: id, + color, + reset + })); + addTooltip(treeNode, { + display: createResourceTooltip(points), + pinnable: true + }); + + const resetButton = createResetButton(() => ({ + conversion, + tree: main.tree, + treeNode + })); + + const hotkey = createHotkey(() => ({ + description: "Reset for prestige points", + key: "p", + onPress: resetButton.onClick + })); + + return { + name, + color, + points, + display: jsx(() => ( + <> + + {render(resetButton)} + + )), + treeNode, + hotkey + }; +}); + +export default layer; diff --git a/src/data/projEntry.tsx b/src/data/projEntry.tsx new file mode 100644 index 0000000..e4640b6 --- /dev/null +++ b/src/data/projEntry.tsx @@ -0,0 +1,103 @@ +import Spacer from "components/layout/Spacer.vue"; +import { jsx } from "features/feature"; +import { createResource, trackBest, trackOOMPS, trackTotal } from "features/resources/resource"; +import type { GenericTree } from "features/trees/tree"; +import { branchedResetPropagation, createTree } from "features/trees/tree"; +import { globalBus } from "game/events"; +import type { BaseLayer, GenericLayer } from "game/layers"; +import { createLayer } from "game/layers"; +import type { Player } from "game/player"; +import player from "game/player"; +import type { DecimalSource } from "util/bignum"; +import Decimal, { format, formatTime } from "util/bignum"; +import { render } from "util/vue"; +import { computed, toRaw } from "vue"; +import prestige from "./layers/prestige"; + +/** + * @hidden + */ +export const main = createLayer("main", function (this: BaseLayer) { + const points = createResource(10); + const best = trackBest(points); + const total = trackTotal(points); + + const pointGain = computed(() => { + // eslint-disable-next-line prefer-const + let gain = new Decimal(1); + return gain; + }); + globalBus.on("update", diff => { + points.value = Decimal.add(points.value, Decimal.times(pointGain.value, diff)); + }); + const oomps = trackOOMPS(points, pointGain); + + const tree = createTree(() => ({ + nodes: [[prestige.treeNode]], + branches: [], + onReset() { + points.value = toRaw(this.resettingNode.value) === toRaw(prestige.treeNode) ? 0 : 10; + best.value = points.value; + total.value = points.value; + }, + resetPropagation: branchedResetPropagation + })) as GenericTree; + + return { + name: "Tree", + links: tree.links, + display: jsx(() => ( + <> + {player.devSpeed === 0 ?
Game Paused
: null} + {player.devSpeed != null && player.devSpeed !== 0 && player.devSpeed !== 1 ? ( +
Dev Speed: {format(player.devSpeed)}x
+ ) : null} + {player.offlineTime != null && player.offlineTime !== 0 ? ( +
Offline Time: {formatTime(player.offlineTime)}
+ ) : null} +
+ {Decimal.lt(points.value, "1e1000") ? You have : null} +

{format(points.value)}

+ {Decimal.lt(points.value, "1e1e6") ? points : null} +
+ {Decimal.gt(pointGain.value, 0) ?
({oomps.value})
: null} + + {render(tree)} + + )), + points, + best, + total, + oomps, + tree + }; +}); + +/** + * Given a player save data object being loaded, return a list of layers that should currently be enabled. + * If your project does not use dynamic layers, this should just return all layers. + */ +export const getInitialLayers = ( + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + player: Partial +): Array => [main, prestige]; + +/** + * A computed ref whose value is true whenever the game is over. + */ +export const hasWon = computed(() => { + return false; +}); + +/** + * Given a player save data object being loaded with a different version, update the save data object to match the structure of the current version. + * @param oldVersion The version of the save being loaded in + * @param player The save data being loaded in + */ +/* eslint-disable @typescript-eslint/no-unused-vars */ +export function fixOldSave( + oldVersion: string | undefined, + player: Partial + // eslint-disable-next-line @typescript-eslint/no-empty-function +): void {} +/* eslint-enable @typescript-eslint/no-unused-vars */ diff --git a/src/data/projInfo-schema.json b/src/data/projInfo-schema.json new file mode 100644 index 0000000..0cea13c --- /dev/null +++ b/src/data/projInfo-schema.json @@ -0,0 +1,93 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "The name of the project, which will appear in the info tab and the header, if enabled. The page title will also be set to this value." + }, + "description": { + "type": "string", + "description": "A description of the project, which will be used when the project is installed as a Progressive Web Application." + }, + "id": { + "type": "string", + "description": "This is a unique ID used when saving player data. Changing this will effectively erase all save data for all players. This ID MUST be unique to your project, and should not be left as the default value. Otherwise, your project may use the save data from another project and cause issues for both projects.", + "minLength": 1 + }, + "author": { + "type": "string", + "description": "The author of the project, which will appear in the info tab." + }, + "discordName": { + "type": "string", + "description": "The text to display for the discord server to point users to. This will appear when hovering over the discord icon, inside the info tab, the game over screen, as well as the NaN detected screen." + }, + "discordLink": { + "type": "string", + "description": "The link for the discord server to point users to." + }, + "versionNumber": { + "type": "string", + "description": "The current version of the project loaded. If the player data was last saved in a different version of the project, fixOldSave will be run, so you can perform any save migrations necessary. This will also appear in the nav, the info tab, and the game over screen.", + "markdownDescription": "The current version of the project loaded. If the player data was last saved in a different version of the project, [fixOldSave](https://moddingtree.com/guide/creating-your-project/project-entry.html#fixoldsave) will be run, so you can perform any save migrations necessary. This will also appear in the nav, the info tab, and the game over screen." + }, + "versionTitle": { + "type": "string", + "description": "The display name for the current version of the project loaded. This will also appear in the nav, the info tab, and the game over screen unless set to an empty string." + }, + "allowGoBack": { + "type": "boolean", + "description": "Whether or not to allow tabs (besides the first) to display a \"back\" button to close them (and any other tabs to the right of them)." + }, + "defaultShowSmall": { + "type": "boolean", + "description": "Whether or not to allow resources to display small values (<.001). If false they'll just display as 0. Individual resources can also be configured to override this value." + }, + "defaultDecimalsShown": { + "type": "number", + "description": "Default precision to display numbers at when passed into format. Individual format calls can override this value, and resources can be configured with a custom precision as well.", + "markdownDescription": "Default precision to display numbers at when passed into format. Individual format calls can override this value, and resources can be configured with a custom precision as well." + }, + "useHeader": { + "type": "boolean", + "description": "Whether or not to display the nav as a header at the top of the screen. If disabled, the nav will appear on the left side of the screen laid over the first tab." + }, + "banner": { + "type": ["boolean", "null"], + "description": "A path to an image file to display as the logo of the app. If null, the title will be shown instead. This will appear in the nav when useHeader is true.", + "markdownDescription": "A path to an image file to display as the logo of the app. If null, the title will be shown instead. This will appear in the nav when `useHeader` is true." + }, + "logo": { + "type": "string", + "description": "A path to an image file to display as the logo of the app within the info tab. If left blank no logo will be shown." + }, + "initialTabs": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "uniqueItems": true, + "description": "The list of initial tabs to display on new saves. This value must have at least one element. Each element should be the ID of the layer to display in that tab." + }, + "maxTickLength": { + "type": "number", + "description": "The longest duration a single tick can be, in seconds. When calculating things like offline time, a single tick will be forced to be this amount or lower. This will make calculating offline time spread out across many ticks as necessary. The default value is 1 hour." + }, + "offlineLimit": { + "type": "number", + "description": "The max amount of time that can be stored as offline time, in hours." + }, + "enablePausing": { + "type": "boolean", + "description": "Whether or not to allow the player to pause the game. Turning this off disables the toggle from the options menu as well as the NaN screen. Developers can still manually pause by just setting player.devSpeed to 0 in console (or 1 to resume).", + "markdownDescription": "Whether or not to allow the player to pause the game. Turning this off disables the toggle from the options menu as well as the NaN screen. Developers can still manually pause by just running `player.devSpeed = 0` in console (or `= 1` to resume)." + }, + "exportEncoding": { + "type": "string", + "enum": ["base64", "lz", "plain"], + "description": "The encoding to use when exporting to the clipboard. Plain-text is fast to generate but is easiest for the player to manipulate and cheat with. Base 64 is slightly slower and the string will be longer but will offer a small barrier to people trying to cheat. LZ-String is the slowest method, but produces the smallest strings and still offers a small barrier to those trying to cheat. Some sharing platforms like pastebin may automatically delete base64 encoded text, and some sites might not support all the characters used in lz-string exports." + } + } +} \ No newline at end of file diff --git a/src/data/projInfo.json b/src/data/projInfo.json new file mode 100644 index 0000000..b32ef22 --- /dev/null +++ b/src/data/projInfo.json @@ -0,0 +1,26 @@ +{ + "$schema": "./projInfo-schema.json", + + "title": "Profectus", + "description": "A project made in Profectus", + "id": "", + "author": "", + "discordName": "", + "discordLink": "", + + "versionNumber": "0.0", + "versionTitle": "Initial Commit", + + "allowGoBack": true, + "defaultShowSmall": false, + "defaultDecimalsShown": 2, + "useHeader": true, + "banner": null, + "logo": "", + "initialTabs": [ "main" ], + + "maxTickLength": 3600, + "offlineLimit": 1, + "enablePausing": true, + "exportEncoding": "base64" +} diff --git a/src/data/themes.ts b/src/data/themes.ts new file mode 100644 index 0000000..7a24e1b --- /dev/null +++ b/src/data/themes.ts @@ -0,0 +1,137 @@ +/** A object of all CSS variables determined by the current theme. */ +export interface ThemeVars { + "--foreground": string; + "--background": string; + "--feature-foreground": string; + "--tooltip-background": string; + "--raised-background": string; + "--points": string; + "--locked": string; + "--highlighted": string; + "--bought": string; + "--danger": string; + "--link": string; + "--outline": string; + "--accent1": string; + "--accent2": string; + "--accent3": string; + "--border-radius": string; + "--modal-border": string; + "--feature-margin": string; +} + +/** An object representing a theme the player can use to change the look of the game. */ +export interface Theme { + /** The values of the theme's CSS variables. */ + variables: ThemeVars; + /** Whether or not tabs should "float" in the center of their container. */ + floatingTabs: boolean; + /** Whether or not adjacent features should merge together - removing the margin between them, and only applying the border radius to the first and last elements in the row or column. */ + mergeAdjacent: boolean; + /** Whether or not to show a pin icon on pinned tooltips. */ + showPin: boolean; +} + +declare module "@vue/runtime-dom" { + /** Make CSS properties accept any CSS variables usually controlled by a theme. */ + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface CSSProperties extends Partial {} + + interface HTMLAttributes { + style?: StyleValue; + } +} + +const defaultTheme: Theme = { + variables: { + "--foreground": "#dfdfdf", + "--background": "#0f0f0f", + "--feature-foreground": "#0f0f0f", + "--tooltip-background": "rgba(0, 0, 0, 0.75)", + "--raised-background": "#0f0f0f", + "--points": "#ffffff", + "--locked": "#bf8f8f", + "--highlighted": "#333", + "--bought": "#77bf5f", + "--danger": "rgb(220, 53, 69)", + "--link": "#02f2f2", + "--outline": "#dfdfdf", + "--accent1": "#627a82", + "--accent2": "#658262", + "--accent3": "#7c6282", + + "--border-radius": "15px", + "--modal-border": "solid 2px var(--color)", + "--feature-margin": "0px" + }, + floatingTabs: true, + mergeAdjacent: true, + showPin: true +}; + +/** An enum of all available themes and their internal IDs. The keys are their display names. */ +export enum Themes { + Classic = "classic", + Paper = "paper", + Nordic = "nordic", + Aqua = "aqua" +} + +/** A dictionary of all available themes. */ +export default { + classic: defaultTheme, + paper: { + ...defaultTheme, + variables: { + ...defaultTheme.variables, + "--background": "#2a323d", + "--feature-foreground": "#000", + "--raised-background": "#333c4a", + "--locked": "#3a3e45", + "--bought": "#5C8A58", + "--outline": "#333c4a", + "--border-radius": "4px", + "--modal-border": "", + "--feature-margin": "5px" + }, + floatingTabs: false + } as Theme, + // Based on https://www.nordtheme.com + nordic: { + ...defaultTheme, + variables: { + ...defaultTheme.variables, + "--foreground": "#D8DEE9", + "--background": "#2E3440", + "--feature-foreground": "#000", + "--raised-background": "#3B4252", + "--points": "#E5E9F0", + "--locked": "#4c566a", + "--highlighted": "#434c5e", + "--bought": "#8FBCBB", + "--danger": "#D08770", + "--link": "#88C0D0", + "--outline": "#3B4252", + "--accent1": "#B48EAD", + "--accent2": "#A3BE8C", + "--accent3": "#EBCB8B", + "--border-radius": "4px", + "--modal-border": "solid 2px #3B4252", + "--feature-margin": "5px" + }, + floatingTabs: false + } as Theme, + aqua: { + ...defaultTheme, + variables: { + ...defaultTheme.variables, + "--foreground": "#bfdfff", + "--background": "#001f3f", + "--tooltip-background": "rgba(0, 15, 31, 0.75)", + "--raised-background": "#001f3f", + "--points": "#dfefff", + "--locked": "#c4a7b3", + "--outline": "#bfdfff" + } + } as Theme +} as Record; diff --git a/src/features/achievements/Achievement.vue b/src/features/achievements/Achievement.vue new file mode 100644 index 0000000..78ac17b --- /dev/null +++ b/src/features/achievements/Achievement.vue @@ -0,0 +1,81 @@ + + + + + diff --git a/src/features/achievements/achievement.tsx b/src/features/achievements/achievement.tsx new file mode 100644 index 0000000..500e93f --- /dev/null +++ b/src/features/achievements/achievement.tsx @@ -0,0 +1,132 @@ +import AchievementComponent from "features/achievements/Achievement.vue"; +import { + CoercableComponent, + Component, + GatherProps, + getUniqueID, + isVisible, + OptionsFunc, + Replace, + setDefault, + StyleValue, + Visibility +} from "features/feature"; +import "game/notifications"; +import type { Persistent } from "game/persistence"; +import { persistent } from "game/persistence"; +import player from "game/player"; +import settings from "game/settings"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { coerceComponent } from "util/vue"; +import { unref, watchEffect } from "vue"; +import { useToast } from "vue-toastification"; + +const toast = useToast(); + +export const AchievementType = Symbol("Achievement"); + +export interface AchievementOptions { + visibility?: Computable; + shouldEarn?: () => boolean; + display?: Computable; + mark?: Computable; + image?: Computable; + style?: Computable; + classes?: Computable>; + onComplete?: VoidFunction; +} + +export interface BaseAchievement { + id: string; + earned: Persistent; + complete: VoidFunction; + type: typeof AchievementType; + [Component]: typeof AchievementComponent; + [GatherProps]: () => Record; +} + +export type Achievement = Replace< + T & BaseAchievement, + { + visibility: GetComputableTypeWithDefault; + display: GetComputableType; + mark: GetComputableType; + image: GetComputableType; + style: GetComputableType; + classes: GetComputableType; + } +>; + +export type GenericAchievement = Replace< + Achievement, + { + visibility: ProcessedComputable; + } +>; + +export function createAchievement( + optionsFunc?: OptionsFunc +): Achievement { + const earned = persistent(false); + return createLazyProxy(() => { + const achievement = optionsFunc?.() ?? ({} as ReturnType>); + achievement.id = getUniqueID("achievement-"); + achievement.type = AchievementType; + achievement[Component] = AchievementComponent; + + achievement.earned = earned; + achievement.complete = function () { + earned.value = true; + }; + + processComputable(achievement as T, "visibility"); + setDefault(achievement, "visibility", Visibility.Visible); + processComputable(achievement as T, "display"); + processComputable(achievement as T, "mark"); + processComputable(achievement as T, "image"); + processComputable(achievement as T, "style"); + processComputable(achievement as T, "classes"); + + achievement[GatherProps] = function (this: GenericAchievement) { + const { visibility, display, earned, image, style, classes, mark, id } = this; + return { visibility, display, earned, image, style: unref(style), classes, mark, id }; + }; + + if (achievement.shouldEarn) { + const genericAchievement = achievement as GenericAchievement; + watchEffect(() => { + if (settings.active !== player.id) return; + if ( + !genericAchievement.earned.value && + isVisible(genericAchievement.visibility) && + genericAchievement.shouldEarn?.() + ) { + genericAchievement.earned.value = true; + genericAchievement.onComplete?.(); + if (genericAchievement.display != null) { + const Display = coerceComponent(unref(genericAchievement.display)); + toast.info( +
+

Achievement earned!

+
+ {/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */} + {/* @ts-ignore */} + +
+
+ ); + } + } + }); + } + + return achievement as unknown as Achievement; + }); +} diff --git a/src/features/action.tsx b/src/features/action.tsx new file mode 100644 index 0000000..5d7e555 --- /dev/null +++ b/src/features/action.tsx @@ -0,0 +1,247 @@ +import { isArray } from "@vue/shared"; +import ClickableComponent from "features/clickables/Clickable.vue"; +import { + Component, + findFeatures, + GatherProps, + GenericComponent, + getUniqueID, + jsx, + JSXFunction, + OptionsFunc, + Replace, + setDefault, + StyleValue, + Visibility +} from "features/feature"; +import { globalBus } from "game/events"; +import { persistent } from "game/persistence"; +import Decimal, { DecimalSource } from "lib/break_eternity"; +import { Unsubscribe } from "nanoevents"; +import { Direction } from "util/common"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { coerceComponent, isCoercableComponent, render } from "util/vue"; +import { computed, Ref, ref, unref } from "vue"; +import { BarOptions, createBar, GenericBar } from "./bars/bar"; +import { ClickableOptions } from "./clickables/clickable"; + +export const ActionType = Symbol("Action"); + +export interface ActionOptions extends Omit { + duration: Computable; + autoStart?: Computable; + onClick: (amount: DecimalSource) => void; + barOptions?: Partial; +} + +export interface BaseAction { + id: string; + type: typeof ActionType; + isHolding: Ref; + progress: Ref; + progressBar: GenericBar; + update: (diff: number) => void; + [Component]: GenericComponent; + [GatherProps]: () => Record; +} + +export type Action = Replace< + T & BaseAction, + { + duration: GetComputableType; + autoStart: GetComputableTypeWithDefault; + visibility: GetComputableTypeWithDefault; + canClick: GetComputableTypeWithDefault; + classes: GetComputableType; + style: GetComputableType; + mark: GetComputableType; + display: JSXFunction; + onClick: VoidFunction; + } +>; + +export type GenericAction = Replace< + Action, + { + autoStart: ProcessedComputable; + visibility: ProcessedComputable; + canClick: ProcessedComputable; + } +>; + +export function createAction( + optionsFunc?: OptionsFunc +): Action { + const progress = persistent(0); + return createLazyProxy(() => { + const action = optionsFunc?.() ?? ({} as ReturnType>); + action.id = getUniqueID("action-"); + action.type = ActionType; + action[Component] = ClickableComponent as GenericComponent; + + // Required because of display changing types + const genericAction = action as unknown as GenericAction; + + action.isHolding = ref(false); + action.progress = progress; + + processComputable(action as T, "visibility"); + setDefault(action, "visibility", Visibility.Visible); + processComputable(action as T, "duration"); + processComputable(action as T, "autoStart"); + setDefault(action, "autoStart", false); + processComputable(action as T, "canClick"); + setDefault(action, "canClick", true); + processComputable(action as T, "classes"); + processComputable(action as T, "style"); + processComputable(action as T, "mark"); + processComputable(action as T, "display"); + + const style = action.style as ProcessedComputable; + action.style = computed(() => { + const currStyle: StyleValue[] = [ + { + cursor: Decimal.gte( + progress.value, + unref(action.duration as ProcessedComputable) + ) + ? "pointer" + : "progress", + display: "flex", + flexDirection: "column" + } + ]; + const originalStyle = unref(style); + if (isArray(originalStyle)) { + currStyle.push(...originalStyle); + } else if (originalStyle != null) { + currStyle.push(originalStyle); + } + return currStyle as StyleValue; + }); + + action.progressBar = createBar(() => ({ + direction: Direction.Right, + width: 100, + height: 10, + style: "margin-top: 8px", + borderStyle: "border-color: black", + baseStyle: "margin-top: -1px", + progress: () => Decimal.div(progress.value, unref(genericAction.duration)), + ...action.barOptions + })); + + const canClick = action.canClick as ProcessedComputable; + action.canClick = computed( + () => + unref(canClick) && + Decimal.gte( + progress.value, + unref(action.duration as ProcessedComputable) + ) + ); + + const display = action.display as GetComputableType; + action.display = jsx(() => { + const currDisplay = unref(display); + let Comp: GenericComponent | undefined; + if (isCoercableComponent(currDisplay)) { + Comp = coerceComponent(currDisplay); + } else if (currDisplay != null) { + const Title = coerceComponent(currDisplay.title ?? "", "h3"); + const Description = coerceComponent(currDisplay.description, "div"); + Comp = coerceComponent( + jsx(() => ( + + {currDisplay.title != null ? ( +
+ + </div> + ) : null} + <Description /> + </span> + )) + ); + } + return ( + <> + <div style="flex-grow: 1" /> + {Comp == null ? null : <Comp />} + <div style="flex-grow: 1" /> + {render(genericAction.progressBar)} + </> + ); + }); + + const onClick = action.onClick.bind(action); + action.onClick = function () { + if (unref(action.canClick) === false) { + return; + } + const amount = Decimal.div(progress.value, unref(genericAction.duration)); + onClick?.(amount); + progress.value = 0; + }; + + action.update = function (diff) { + const duration = unref(genericAction.duration); + if (Decimal.gte(progress.value, duration)) { + progress.value = duration; + } else { + progress.value = Decimal.add(progress.value, diff); + if (genericAction.isHolding.value || unref(genericAction.autoStart)) { + genericAction.onClick(); + } + } + }; + + action[GatherProps] = function (this: GenericAction) { + const { + display, + visibility, + style, + classes, + onClick, + isHolding, + canClick, + small, + mark, + id + } = this; + return { + display, + visibility, + style: unref(style), + classes, + onClick, + isHolding, + canClick, + small, + mark, + id + }; + }; + + return action as unknown as Action<T>; + }); +} + +const listeners: Record<string, Unsubscribe | undefined> = {}; +globalBus.on("addLayer", layer => { + const actions: GenericAction[] = findFeatures(layer, ActionType) as GenericAction[]; + listeners[layer.id] = layer.on("postUpdate", diff => { + actions.forEach(action => action.update(diff)); + }); +}); +globalBus.on("removeLayer", layer => { + // unsubscribe from postUpdate + listeners[layer.id]?.(); + listeners[layer.id] = undefined; +}); diff --git a/src/features/bars/Bar.vue b/src/features/bars/Bar.vue new file mode 100644 index 0000000..3c4b91c --- /dev/null +++ b/src/features/bars/Bar.vue @@ -0,0 +1,183 @@ +<template> + <div + v-if="isVisible(visibility)" + :style="[ + { + width: unref(width) + 'px', + height: unref(height) + 'px', + visibility: isHidden(visibility) ? 'hidden' : undefined + }, + unref(style) ?? {} + ]" + :class="{ + bar: true, + ...unref(classes) + }" + > + <div + class="overlayTextContainer border" + :style="[ + { width: unref(width) + 'px', height: unref(height) + 'px' }, + unref(borderStyle) ?? {} + ]" + > + <span v-if="component" class="overlayText" :style="unref(textStyle)"> + <component :is="component" /> + </span> + </div> + <div + class="border" + :style="[ + { width: unref(width) + 'px', height: unref(height) + 'px' }, + unref(style) ?? {}, + unref(baseStyle) ?? {}, + unref(borderStyle) ?? {} + ]" + > + <div class="fill" :style="[barStyle, unref(style) ?? {}, unref(fillStyle) ?? {}]" /> + </div> + <MarkNode :mark="unref(mark)" /> + <Node :id="id" /> + </div> +</template> + +<script lang="ts"> +import MarkNode from "components/MarkNode.vue"; +import Node from "components/Node.vue"; +import { CoercableComponent, isHidden, isVisible, Visibility } from "features/feature"; +import type { DecimalSource } from "util/bignum"; +import Decimal from "util/bignum"; +import { Direction } from "util/common"; +import { computeOptionalComponent, processedPropType, unwrapRef } from "util/vue"; +import type { CSSProperties, StyleValue } from "vue"; +import { computed, defineComponent, toRefs, unref } from "vue"; + +export default defineComponent({ + props: { + progress: { + type: processedPropType<DecimalSource>(String, Object, Number), + required: true + }, + width: { + type: processedPropType<number>(Number), + required: true + }, + height: { + type: processedPropType<number>(Number), + required: true + }, + direction: { + type: processedPropType<Direction>(String), + required: true + }, + display: processedPropType<CoercableComponent>(Object, String, Function), + visibility: { + type: processedPropType<Visibility | boolean>(Number, Boolean), + required: true + }, + style: processedPropType<StyleValue>(Object, String, Array), + classes: processedPropType<Record<string, boolean>>(Object), + borderStyle: processedPropType<StyleValue>(Object, String, Array), + textStyle: processedPropType<StyleValue>(Object, String, Array), + baseStyle: processedPropType<StyleValue>(Object, String, Array), + fillStyle: processedPropType<StyleValue>(Object, String, Array), + mark: processedPropType<boolean | string>(Boolean, String), + id: { + type: String, + required: true + } + }, + components: { + MarkNode, + Node + }, + setup(props) { + const { progress, width, height, direction, display } = toRefs(props); + + const normalizedProgress = computed(() => { + let progressNumber = + progress.value instanceof Decimal + ? progress.value.toNumber() + : Number(progress.value); + return (1 - Math.min(Math.max(progressNumber, 0), 1)) * 100; + }); + + const barStyle = computed(() => { + const barStyle: Partial<CSSProperties> = { + width: unwrapRef(width) + 0.5 + "px", + height: unwrapRef(height) + 0.5 + "px" + }; + switch (unref(direction)) { + case Direction.Up: + barStyle.clipPath = `inset(${normalizedProgress.value}% 0% 0% 0%)`; + barStyle.width = unwrapRef(width) + 1 + "px"; + break; + case Direction.Down: + barStyle.clipPath = `inset(0% 0% ${normalizedProgress.value}% 0%)`; + barStyle.width = unwrapRef(width) + 1 + "px"; + break; + case Direction.Right: + barStyle.clipPath = `inset(0% ${normalizedProgress.value}% 0% 0%)`; + break; + case Direction.Left: + barStyle.clipPath = `inset(0% 0% 0% ${normalizedProgress.value} + '%)`; + break; + case Direction.Default: + barStyle.clipPath = "inset(0% 50% 0% 0%)"; + break; + } + return barStyle; + }); + + const component = computeOptionalComponent(display); + + return { + normalizedProgress, + barStyle, + component, + unref, + Visibility, + isVisible, + isHidden + }; + } +}); +</script> + +<style scoped> +.bar { + position: relative; + display: table; +} + +.overlayTextContainer { + position: absolute; + border-radius: 10px; + vertical-align: middle; + display: flex; + justify-content: center; + z-index: 3; +} + +.overlayText { + z-index: 6; +} + +.border { + border: 2px solid; + border-radius: 10px; + border-color: var(--foreground); + overflow: hidden; + mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC); + margin: 0; +} + +.fill { + position: absolute; + background-color: var(--foreground); + overflow: hidden; + margin-left: -0.5px; + transition-duration: 0.2s; + z-index: 2; +} +</style> diff --git a/src/features/bars/bar.ts b/src/features/bars/bar.ts new file mode 100644 index 0000000..f0436f4 --- /dev/null +++ b/src/features/bars/bar.ts @@ -0,0 +1,134 @@ +import BarComponent from "features/bars/Bar.vue"; +import type { + CoercableComponent, + GenericComponent, + OptionsFunc, + Replace, + StyleValue +} from "features/feature"; +import { Component, GatherProps, getUniqueID, setDefault, Visibility } from "features/feature"; +import type { DecimalSource } from "util/bignum"; +import { Direction } from "util/common"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { unref } from "vue"; + +export const BarType = Symbol("Bar"); + +export interface BarOptions { + visibility?: Computable<Visibility | boolean>; + width: Computable<number>; + height: Computable<number>; + direction: Computable<Direction>; + style?: Computable<StyleValue>; + classes?: Computable<Record<string, boolean>>; + borderStyle?: Computable<StyleValue>; + baseStyle?: Computable<StyleValue>; + textStyle?: Computable<StyleValue>; + fillStyle?: Computable<StyleValue>; + progress: Computable<DecimalSource>; + display?: Computable<CoercableComponent>; + mark?: Computable<boolean | string>; +} + +export interface BaseBar { + id: string; + type: typeof BarType; + [Component]: typeof BarComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Bar<T extends BarOptions> = Replace< + T & BaseBar, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + width: GetComputableType<T["width"]>; + height: GetComputableType<T["height"]>; + direction: GetComputableType<T["direction"]>; + style: GetComputableType<T["style"]>; + classes: GetComputableType<T["classes"]>; + borderStyle: GetComputableType<T["borderStyle"]>; + baseStyle: GetComputableType<T["baseStyle"]>; + textStyle: GetComputableType<T["textStyle"]>; + fillStyle: GetComputableType<T["fillStyle"]>; + progress: GetComputableType<T["progress"]>; + display: GetComputableType<T["display"]>; + mark: GetComputableType<T["mark"]>; + } +>; + +export type GenericBar = Replace< + Bar<BarOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + } +>; + +export function createBar<T extends BarOptions>( + optionsFunc: OptionsFunc<T, BaseBar, GenericBar> +): Bar<T> { + return createLazyProxy(() => { + const bar = optionsFunc(); + bar.id = getUniqueID("bar-"); + bar.type = BarType; + bar[Component] = BarComponent; + + processComputable(bar as T, "visibility"); + setDefault(bar, "visibility", Visibility.Visible); + processComputable(bar as T, "width"); + processComputable(bar as T, "height"); + processComputable(bar as T, "direction"); + processComputable(bar as T, "style"); + processComputable(bar as T, "classes"); + processComputable(bar as T, "borderStyle"); + processComputable(bar as T, "baseStyle"); + processComputable(bar as T, "textStyle"); + processComputable(bar as T, "fillStyle"); + processComputable(bar as T, "progress"); + processComputable(bar as T, "display"); + processComputable(bar as T, "mark"); + + bar[GatherProps] = function (this: GenericBar) { + const { + progress, + width, + height, + direction, + display, + visibility, + style, + classes, + borderStyle, + textStyle, + baseStyle, + fillStyle, + mark, + id + } = this; + return { + progress, + width, + height, + direction, + display, + visibility, + style: unref(style), + classes, + borderStyle, + textStyle, + baseStyle, + fillStyle, + mark, + id + }; + }; + + return bar as unknown as Bar<T>; + }); +} diff --git a/src/features/boards/Board.vue b/src/features/boards/Board.vue new file mode 100644 index 0000000..f1f8b83 --- /dev/null +++ b/src/features/boards/Board.vue @@ -0,0 +1,262 @@ +<template> + <panZoom + v-if="isVisible(visibility)" + v-show="isHidden(visibility)" + :style="[ + { + width, + height + }, + style + ]" + :class="classes" + selector=".g1" + :options="{ initialZoom: 1, minZoom: 0.1, maxZoom: 10, zoomDoubleClickSpeed: 1 }" + ref="stage" + @init="onInit" + @mousemove="drag" + @touchmove="drag" + @mousedown="(e: MouseEvent) => mouseDown(e)" + @touchstart="(e: TouchEvent) => mouseDown(e)" + @mouseup="() => endDragging(dragging)" + @touchend.passive="() => endDragging(dragging)" + @mouseleave="() => endDragging(dragging)" + > + <svg class="stage" width="100%" height="100%"> + <g class="g1"> + <transition-group name="link" appear> + <g v-for="(link, i) in unref(links) || []" :key="i"> + <BoardLinkVue :link="link" /> + </g> + </transition-group> + <transition-group name="grow" :duration="500" appear> + <g v-for="node in sortedNodes" :key="node.id" style="transition-duration: 0s"> + <BoardNodeVue + :node="node" + :nodeType="types[node.type]" + :dragging="draggingNode" + :dragged="dragged" + :hasDragged="hasDragged" + :receivingNode="receivingNode?.id === node.id" + :selectedNode="unref(selectedNode)" + :selectedAction="unref(selectedAction)" + @mouseDown="mouseDown" + @endDragging="endDragging" + /> + </g> + </transition-group> + </g> + </svg> + </panZoom> +</template> + +<script setup lang="ts"> +import type { + BoardData, + BoardNode, + BoardNodeLink, + GenericBoardNodeAction, + GenericNodeType +} from "features/boards/board"; +import { getNodeProperty } from "features/boards/board"; +import type { StyleValue } from "features/feature"; +import { isHidden, isVisible, Visibility } from "features/feature"; +import type { ProcessedComputable } from "util/computed"; +import { computed, ref, Ref, toRefs, unref } from "vue"; +import BoardLinkVue from "./BoardLink.vue"; +import BoardNodeVue from "./BoardNode.vue"; + +const _props = defineProps<{ + nodes: Ref<BoardNode[]>; + types: Record<string, GenericNodeType>; + state: Ref<BoardData>; + visibility: ProcessedComputable<Visibility | boolean>; + width?: ProcessedComputable<string>; + height?: ProcessedComputable<string>; + style?: ProcessedComputable<StyleValue>; + classes?: ProcessedComputable<Record<string, boolean>>; + links: Ref<BoardNodeLink[] | null>; + selectedAction: Ref<GenericBoardNodeAction | null>; + selectedNode: Ref<BoardNode | null>; + mousePosition: Ref<{ x: number; y: number } | null>; +}>(); +const props = toRefs(_props); + +const lastMousePosition = ref({ x: 0, y: 0 }); +const dragged = ref({ x: 0, y: 0 }); +const dragging = ref<number | null>(null); +const hasDragged = ref(false); +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const stage = ref<any>(null); + +const draggingNode = computed(() => + dragging.value == null ? undefined : props.nodes.value.find(node => node.id === dragging.value) +); + +const sortedNodes = computed(() => { + const nodes = props.nodes.value.slice(); + if (draggingNode.value) { + const node = nodes.splice(nodes.indexOf(draggingNode.value), 1)[0]; + nodes.push(node); + } + return nodes; +}); + +const receivingNode = computed(() => { + const node = draggingNode.value; + if (node == null) { + return null; + } + + const position = { + x: node.position.x + dragged.value.x, + y: node.position.y + dragged.value.y + }; + let smallestDistance = Number.MAX_VALUE; + return props.nodes.value.reduce((smallest: BoardNode | null, curr: BoardNode) => { + if (curr.id === node.id) { + return smallest; + } + const nodeType = props.types.value[curr.type]; + const canAccept = getNodeProperty(nodeType.canAccept, curr); + if (!canAccept) { + return smallest; + } + + const distanceSquared = + Math.pow(position.x - curr.position.x, 2) + Math.pow(position.y - curr.position.y, 2); + let size = getNodeProperty(nodeType.size, curr); + if (distanceSquared > smallestDistance || distanceSquared > size * size) { + return smallest; + } + + smallestDistance = distanceSquared; + return curr; + }, null); +}); + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function onInit(panzoomInstance: any) { + panzoomInstance.setTransformOrigin(null); +} + +function mouseDown(e: MouseEvent | TouchEvent, nodeID: number | null = null, draggable = false) { + if (dragging.value == null) { + e.preventDefault(); + e.stopPropagation(); + + let clientX, clientY; + if ("touches" in e) { + if (e.touches.length === 1) { + clientX = e.touches[0].clientX; + clientY = e.touches[0].clientY; + } else { + return; + } + } else { + clientX = e.clientX; + clientY = e.clientY; + } + lastMousePosition.value = { + x: clientX, + y: clientY + }; + dragged.value = { x: 0, y: 0 }; + hasDragged.value = false; + + if (draggable) { + dragging.value = nodeID; + } + } + if (nodeID != null) { + props.state.value.selectedNode = null; + props.state.value.selectedAction = null; + } +} + +function drag(e: MouseEvent | TouchEvent) { + const { x, y, scale } = stage.value.panZoomInstance.getTransform(); + + let clientX, clientY; + if ("touches" in e) { + if (e.touches.length === 1) { + clientX = e.touches[0].clientX; + clientY = e.touches[0].clientY; + } else { + endDragging(dragging.value); + props.mousePosition.value = null; + return; + } + } else { + clientX = e.clientX; + clientY = e.clientY; + } + + props.mousePosition.value = { + x: (clientX - x) / scale, + y: (clientY - y) / scale + }; + + dragged.value = { + x: dragged.value.x + (clientX - lastMousePosition.value.x) / scale, + y: dragged.value.y + (clientY - lastMousePosition.value.y) / scale + }; + lastMousePosition.value = { + x: clientX, + y: clientY + }; + + if (Math.abs(dragged.value.x) > 10 || Math.abs(dragged.value.y) > 10) { + hasDragged.value = true; + } + + if (dragging.value != null) { + e.preventDefault(); + e.stopPropagation(); + } +} + +function endDragging(nodeID: number | null) { + if (dragging.value != null && dragging.value === nodeID && draggingNode.value != null) { + draggingNode.value.position.x += Math.round(dragged.value.x / 25) * 25; + draggingNode.value.position.y += Math.round(dragged.value.y / 25) * 25; + + const nodes = props.nodes.value; + nodes.splice(nodes.indexOf(draggingNode.value), 1); + nodes.push(draggingNode.value); + + if (receivingNode.value) { + props.types.value[receivingNode.value.type].onDrop?.( + receivingNode.value, + draggingNode.value + ); + } + + dragging.value = null; + } else if (!hasDragged.value) { + props.state.value.selectedNode = null; + props.state.value.selectedAction = null; + } +} +</script> + +<style> +.vue-pan-zoom-scene { + width: 100%; + height: 100%; + cursor: grab; +} + +.vue-pan-zoom-scene:active { + cursor: grabbing; +} + +.g1 { + transition-duration: 0s; +} + +.link-enter-from, +.link-leave-to { + opacity: 0; +} +</style> diff --git a/src/features/boards/BoardLink.vue b/src/features/boards/BoardLink.vue new file mode 100644 index 0000000..cb61914 --- /dev/null +++ b/src/features/boards/BoardLink.vue @@ -0,0 +1,59 @@ +<template> + <line + class="link" + v-bind="link" + :class="{ pulsing: link.pulsing }" + :x1="startPosition.x" + :y1="startPosition.y" + :x2="endPosition.x" + :y2="endPosition.y" + /> +</template> + +<script setup lang="ts"> +import type { BoardNodeLink } from "features/boards/board"; +import { computed, toRefs, unref } from "vue"; + +const _props = defineProps<{ + link: BoardNodeLink; +}>(); +const props = toRefs(_props); + +const startPosition = computed(() => { + const position = props.link.value.startNode.position; + if (props.link.value.offsetStart) { + position.x += unref(props.link.value.offsetStart).x; + position.y += unref(props.link.value.offsetStart).y; + } + return position; +}); + +const endPosition = computed(() => { + const position = props.link.value.endNode.position; + if (props.link.value.offsetEnd) { + position.x += unref(props.link.value.offsetEnd).x; + position.y += unref(props.link.value.offsetEnd).y; + } + return position; +}); +</script> + +<style scoped> +.link.pulsing { + animation: pulsing 2s ease-in infinite; +} + +@keyframes pulsing { + 0% { + opacity: 0.25; + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0.25; + } +} +</style> diff --git a/src/features/boards/BoardNode.vue b/src/features/boards/BoardNode.vue new file mode 100644 index 0000000..a153afd --- /dev/null +++ b/src/features/boards/BoardNode.vue @@ -0,0 +1,365 @@ +<template> + <g + class="boardnode" + :class="node.type" + :style="{ opacity: dragging?.id === node.id && hasDragged ? 0.5 : 1 }" + :transform="`translate(${position.x},${position.y})`" + > + <transition name="actions" appear> + <g v-if="isSelected && actions"> + <!-- TODO move to separate file --> + <g + v-for="(action, index) in actions" + :key="action.id" + class="action" + :class="{ selected: selectedAction?.id === action.id }" + :transform="`translate( + ${ + (-size - 30) * + Math.sin(((actions.length - 1) / 2 - index) * actionDistance) + }, + ${ + (size + 30) * + Math.cos(((actions.length - 1) / 2 - index) * actionDistance) + } + )`" + @mousedown="e => performAction(e, action)" + @touchstart="e => performAction(e, action)" + @mouseup="e => actionMouseUp(e, action)" + @touchend.stop="e => actionMouseUp(e, action)" + > + <circle + :fill="getNodeProperty(action.fillColor, node)" + r="20" + :stroke-width="selectedAction?.id === action.id ? 4 : 0" + :stroke="outlineColor" + /> + <text :fill="titleColor" class="material-icons">{{ + getNodeProperty(action.icon, node) + }}</text> + </g> + </g> + </transition> + + <g + class="node-container" + @mouseenter="isHovering = true" + @mouseleave="isHovering = false" + @mousedown="mouseDown" + @touchstart.passive="mouseDown" + @mouseup="mouseUp" + @touchend.passive="mouseUp" + > + <g v-if="shape === Shape.Circle"> + <circle + v-if="canAccept" + class="receiver" + :r="size + 8" + :fill="backgroundColor" + :stroke="receivingNode ? '#0F0' : '#0F03'" + :stroke-width="2" + /> + + <circle + class="body" + :r="size" + :fill="fillColor" + :stroke="outlineColor" + :stroke-width="4" + /> + + <circle + class="progressFill" + v-if="progressDisplay === ProgressDisplay.Fill" + :r="Math.max(size * progress - 2, 0)" + :fill="progressColor" + /> + <circle + v-else + :r="size + 4.5" + class="progressRing" + fill="transparent" + :stroke-dasharray="(size + 4.5) * 2 * Math.PI" + :stroke-width="5" + :stroke-dashoffset=" + (size + 4.5) * 2 * Math.PI - progress * (size + 4.5) * 2 * Math.PI + " + :stroke="progressColor" + /> + </g> + <g v-else-if="shape === Shape.Diamond" transform="rotate(45, 0, 0)"> + <rect + v-if="canAccept" + class="receiver" + :width="size * sqrtTwo + 16" + :height="size * sqrtTwo + 16" + :transform="`translate(${-(size * sqrtTwo + 16) / 2}, ${ + -(size * sqrtTwo + 16) / 2 + })`" + :fill="backgroundColor" + :stroke="receivingNode ? '#0F0' : '#0F03'" + :stroke-width="2" + /> + + <rect + class="body" + :width="size * sqrtTwo" + :height="size * sqrtTwo" + :transform="`translate(${(-size * sqrtTwo) / 2}, ${(-size * sqrtTwo) / 2})`" + :fill="fillColor" + :stroke="outlineColor" + :stroke-width="4" + /> + + <rect + v-if="progressDisplay === ProgressDisplay.Fill" + class="progressFill" + :width="Math.max(size * sqrtTwo * progress - 2, 0)" + :height="Math.max(size * sqrtTwo * progress - 2, 0)" + :transform="`translate(${-Math.max(size * sqrtTwo * progress - 2, 0) / 2}, ${ + -Math.max(size * sqrtTwo * progress - 2, 0) / 2 + })`" + :fill="progressColor" + /> + <rect + v-else + class="progressDiamond" + :width="size * sqrtTwo + 9" + :height="size * sqrtTwo + 9" + :transform="`translate(${-(size * sqrtTwo + 9) / 2}, ${ + -(size * sqrtTwo + 9) / 2 + })`" + fill="transparent" + :stroke-dasharray="(size * sqrtTwo + 9) * 4" + :stroke-width="5" + :stroke-dashoffset=" + (size * sqrtTwo + 9) * 4 - progress * (size * sqrtTwo + 9) * 4 + " + :stroke="progressColor" + /> + </g> + + <text :fill="titleColor" class="node-title">{{ title }}</text> + </g> + + <transition name="fade" appear> + <g v-if="label"> + <text + :fill="label.color || titleColor" + class="node-title" + :class="{ pulsing: label.pulsing }" + :y="-size - 20" + >{{ label.text }} + </text> + </g> + </transition> + + <transition name="fade" appear> + <text + v-if="isSelected && selectedAction" + :fill="titleColor" + class="node-title" + :y="size + 75" + >Tap again to confirm</text + > + </transition> + </g> +</template> + +<script setup lang="ts"> +import themes from "data/themes"; +import type { BoardNode, GenericBoardNodeAction, GenericNodeType } from "features/boards/board"; +import { ProgressDisplay, getNodeProperty, Shape } from "features/boards/board"; +import { Visibility } from "features/feature"; +import settings from "game/settings"; +import { computed, ref, toRefs, unref, watch } from "vue"; + +const sqrtTwo = Math.sqrt(2); + +const _props = defineProps<{ + node: BoardNode; + nodeType: GenericNodeType; + dragging?: BoardNode; + dragged?: { + x: number; + y: number; + }; + hasDragged?: boolean; + receivingNode?: boolean; + selectedNode?: BoardNode | null; + selectedAction?: GenericBoardNodeAction | null; +}>(); +const props = toRefs(_props); +const emit = defineEmits<{ + (e: "mouseDown", event: MouseEvent | TouchEvent, node: number, isDraggable: boolean): void; + (e: "endDragging", node: number): void; +}>(); + +const isHovering = ref(false); +const isSelected = computed(() => unref(props.selectedNode) === unref(props.node)); +const isDraggable = computed(() => + getNodeProperty(props.nodeType.value.draggable, unref(props.node)) +); + +watch(isDraggable, value => { + const node = unref(props.node); + if (unref(props.dragging) === node && !value) { + emit("endDragging", node.id); + } +}); + +const actions = computed(() => { + const node = unref(props.node); + return getNodeProperty(props.nodeType.value.actions, node)?.filter( + action => getNodeProperty(action.visibility, node) !== Visibility.None + ); +}); + +const position = computed(() => { + const node = unref(props.node); + const dragged = unref(props.dragged); + + return getNodeProperty(props.nodeType.value.draggable, node) && + unref(props.dragging)?.id === node.id && + dragged + ? { + x: node.position.x + Math.round(dragged.x / 25) * 25, + y: node.position.y + Math.round(dragged.y / 25) * 25 + } + : node.position; +}); + +const shape = computed(() => getNodeProperty(props.nodeType.value.shape, unref(props.node))); +const title = computed(() => getNodeProperty(props.nodeType.value.title, unref(props.node))); +const label = computed(() => getNodeProperty(props.nodeType.value.label, unref(props.node))); +const size = computed(() => getNodeProperty(props.nodeType.value.size, unref(props.node))); +const progress = computed( + () => getNodeProperty(props.nodeType.value.progress, unref(props.node)) ?? 0 +); +const backgroundColor = computed(() => themes[settings.theme].variables["--background"]); +const outlineColor = computed( + () => + getNodeProperty(props.nodeType.value.outlineColor, unref(props.node)) ?? + themes[settings.theme].variables["--outline"] +); +const fillColor = computed( + () => + getNodeProperty(props.nodeType.value.fillColor, unref(props.node)) ?? + themes[settings.theme].variables["--raised-background"] +); +const progressColor = computed(() => + getNodeProperty(props.nodeType.value.progressColor, unref(props.node)) +); +const titleColor = computed( + () => + getNodeProperty(props.nodeType.value.titleColor, unref(props.node)) ?? + themes[settings.theme].variables["--foreground"] +); +const progressDisplay = computed(() => + getNodeProperty(props.nodeType.value.progressDisplay, unref(props.node)) +); +const canAccept = computed( + () => + unref(props.dragging) != null && + unref(props.hasDragged) && + getNodeProperty(props.nodeType.value.canAccept, unref(props.node)) +); +const actionDistance = computed(() => + getNodeProperty(props.nodeType.value.actionDistance, unref(props.node)) +); + +function mouseDown(e: MouseEvent | TouchEvent) { + emit("mouseDown", e, props.node.value.id, isDraggable.value); +} + +function mouseUp() { + if (!props.hasDragged?.value) { + props.nodeType.value.onClick?.(props.node.value); + } +} + +function performAction(e: MouseEvent | TouchEvent, action: GenericBoardNodeAction) { + // If the onClick function made this action selected, + // don't propagate the event (which will deselect everything) + if (action.onClick(unref(props.node)) || unref(props.selectedAction)?.id === action.id) { + e.preventDefault(); + e.stopPropagation(); + } +} + +function actionMouseUp(e: MouseEvent | TouchEvent, action: GenericBoardNodeAction) { + if (unref(props.selectedAction)?.id === action.id) { + e.preventDefault(); + e.stopPropagation(); + } +} +</script> + +<style scoped> +.boardnode { + cursor: pointer; + transition-duration: 0s; +} + +.node-title { + text-anchor: middle; + dominant-baseline: middle; + font-family: monospace; + font-size: 200%; + pointer-events: none; +} + +.progressRing { + transform: rotate(-90deg); +} + +.action:not(.boardnode):hover circle, +.action:not(.boardnode).selected circle { + r: 25; +} + +.action:not(.boardnode):hover text, +.action:not(.boardnode).selected text { + font-size: 187.5%; /* 150% * 1.25 */ +} + +.action:not(.boardnode) text { + text-anchor: middle; + dominant-baseline: central; +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +.pulsing { + animation: pulsing 2s ease-in infinite; +} + +@keyframes pulsing { + 0% { + opacity: 0.25; + } + + 50% { + opacity: 1; + } + + 100% { + opacity: 0.25; + } +} +</style> + +<style> +.actions-enter-from .action, +.actions-leave-to .action { + transform: translate(0, 0); +} + +.grow-enter-from .node-container, +.grow-leave-to .node-container { + transform: scale(0); +} +</style> diff --git a/src/features/boards/board.ts b/src/features/boards/board.ts new file mode 100644 index 0000000..7f79110 --- /dev/null +++ b/src/features/boards/board.ts @@ -0,0 +1,397 @@ +import BoardComponent from "features/boards/Board.vue"; +import type { OptionsFunc, Replace, StyleValue } from "features/feature"; +import { + Component, + findFeatures, + GatherProps, + getUniqueID, + setDefault, + Visibility +} from "features/feature"; +import { globalBus } from "game/events"; +import { DefaultValue, deletePersistent, Persistent, State } from "game/persistence"; +import { persistent } from "game/persistence"; +import type { Unsubscribe } from "nanoevents"; +import { isFunction } from "util/common"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { computed, ref, Ref, unref } from "vue"; +import panZoom from "vue-panzoom"; +import type { Link } from "../links/links"; + +globalBus.on("setupVue", app => panZoom.install(app)); + +export const BoardType = Symbol("Board"); + +export type NodeComputable<T> = Computable<T> | ((node: BoardNode) => T); + +export enum ProgressDisplay { + Outline = "Outline", + Fill = "Fill" +} + +export enum Shape { + Circle = "Circle", + Diamond = "Triangle" +} + +export interface BoardNode { + id: number; + position: { + x: number; + y: number; + }; + type: string; + state?: State; + pinned?: boolean; +} + +export interface BoardNodeLink extends Omit<Link, "startNode" | "endNode"> { + startNode: BoardNode; + endNode: BoardNode; + pulsing?: boolean; +} + +export interface NodeLabel { + text: string; + color?: string; + pulsing?: boolean; +} + +export type BoardData = { + nodes: BoardNode[]; + selectedNode: number | null; + selectedAction: string | null; +}; + +export interface NodeTypeOptions { + title: NodeComputable<string>; + label?: NodeComputable<NodeLabel | null>; + size: NodeComputable<number>; + draggable?: NodeComputable<boolean>; + shape: NodeComputable<Shape>; + canAccept?: boolean | Ref<boolean> | ((node: BoardNode, otherNode: BoardNode) => boolean); + progress?: NodeComputable<number>; + progressDisplay?: NodeComputable<ProgressDisplay>; + progressColor?: NodeComputable<string>; + fillColor?: NodeComputable<string>; + outlineColor?: NodeComputable<string>; + titleColor?: NodeComputable<string>; + actions?: BoardNodeActionOptions[]; + actionDistance?: NodeComputable<number>; + onClick?: (node: BoardNode) => void; + onDrop?: (node: BoardNode, otherNode: BoardNode) => void; + update?: (node: BoardNode, diff: number) => void; +} + +export interface BaseNodeType { + nodes: Ref<BoardNode[]>; +} + +export type NodeType<T extends NodeTypeOptions> = Replace< + T & BaseNodeType, + { + title: GetComputableType<T["title"]>; + label: GetComputableType<T["label"]>; + size: GetComputableTypeWithDefault<T["size"], 50>; + draggable: GetComputableTypeWithDefault<T["draggable"], false>; + shape: GetComputableTypeWithDefault<T["shape"], Shape.Circle>; + canAccept: GetComputableTypeWithDefault<T["canAccept"], false>; + progress: GetComputableType<T["progress"]>; + progressDisplay: GetComputableTypeWithDefault<T["progressDisplay"], ProgressDisplay.Fill>; + progressColor: GetComputableTypeWithDefault<T["progressColor"], "none">; + fillColor: GetComputableType<T["fillColor"]>; + outlineColor: GetComputableType<T["outlineColor"]>; + titleColor: GetComputableType<T["titleColor"]>; + actions?: GenericBoardNodeAction[]; + actionDistance: GetComputableTypeWithDefault<T["actionDistance"], number>; + } +>; + +export type GenericNodeType = Replace< + NodeType<NodeTypeOptions>, + { + size: NodeComputable<number>; + draggable: NodeComputable<boolean>; + shape: NodeComputable<Shape>; + canAccept: NodeComputable<boolean>; + progressDisplay: NodeComputable<ProgressDisplay>; + progressColor: NodeComputable<string>; + actionDistance: NodeComputable<number>; + } +>; + +export interface BoardNodeActionOptions { + id: string; + visibility?: NodeComputable<Visibility | boolean>; + icon: NodeComputable<string>; + fillColor?: NodeComputable<string>; + tooltip: NodeComputable<string>; + links?: NodeComputable<BoardNodeLink[]>; + onClick: (node: BoardNode) => boolean | undefined; +} + +export interface BaseBoardNodeAction { + links?: Ref<BoardNodeLink[]>; +} + +export type BoardNodeAction<T extends BoardNodeActionOptions> = Replace< + T & BaseBoardNodeAction, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + icon: GetComputableType<T["icon"]>; + fillColor: GetComputableType<T["fillColor"]>; + tooltip: GetComputableType<T["tooltip"]>; + links: GetComputableType<T["links"]>; + } +>; + +export type GenericBoardNodeAction = Replace< + BoardNodeAction<BoardNodeActionOptions>, + { + visibility: NodeComputable<Visibility | boolean>; + } +>; + +export interface BoardOptions { + visibility?: Computable<Visibility | boolean>; + height?: Computable<string>; + width?: Computable<string>; + classes?: Computable<Record<string, boolean>>; + style?: Computable<StyleValue>; + startNodes: () => Omit<BoardNode, "id">[]; + types: Record<string, NodeTypeOptions>; + state?: Computable<BoardData>; + links?: Computable<BoardNodeLink[] | null>; +} + +export interface BaseBoard { + id: string; + nodes: Ref<BoardNode[]>; + selectedNode: Ref<BoardNode | null>; + selectedAction: Ref<GenericBoardNodeAction | null>; + mousePosition: Ref<{ x: number; y: number } | null>; + type: typeof BoardType; + [Component]: typeof BoardComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Board<T extends BoardOptions> = Replace< + T & BaseBoard, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + types: Record<string, GenericNodeType>; + height: GetComputableType<T["height"]>; + width: GetComputableType<T["width"]>; + classes: GetComputableType<T["classes"]>; + style: GetComputableType<T["style"]>; + state: GetComputableTypeWithDefault<T["state"], Persistent<BoardData>>; + links: GetComputableTypeWithDefault<T["links"], Ref<BoardNodeLink[] | null>>; + } +>; + +export type GenericBoard = Replace< + Board<BoardOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + state: ProcessedComputable<BoardData>; + links: ProcessedComputable<BoardNodeLink[] | null>; + } +>; + +export function createBoard<T extends BoardOptions>( + optionsFunc: OptionsFunc<T, BaseBoard, GenericBoard> +): Board<T> { + const state = persistent<BoardData>({ + nodes: [], + selectedNode: null, + selectedAction: null + }); + + return createLazyProxy(() => { + const board = optionsFunc(); + board.id = getUniqueID("board-"); + board.type = BoardType; + board[Component] = BoardComponent; + + if (board.state) { + deletePersistent(state); + processComputable(board as T, "state"); + } else { + state[DefaultValue] = { + nodes: board.startNodes().map((n, i) => { + (n as BoardNode).id = i; + return n as BoardNode; + }), + selectedNode: null, + selectedAction: null + }; + board.state = state; + } + + board.nodes = computed(() => unref(processedBoard.state).nodes); + board.selectedNode = computed( + () => + processedBoard.nodes.value.find( + node => node.id === unref(processedBoard.state).selectedNode + ) || null + ); + board.selectedAction = computed(() => { + const selectedNode = processedBoard.selectedNode.value; + if (selectedNode == null) { + return null; + } + const type = processedBoard.types[selectedNode.type]; + if (type.actions == null) { + return null; + } + return ( + type.actions.find( + action => action.id === unref(processedBoard.state).selectedAction + ) || null + ); + }); + board.mousePosition = ref(null); + if (board.links) { + processComputable(board as T, "links"); + } else { + board.links = computed(() => { + if (processedBoard.selectedAction.value == null) { + return null; + } + if ( + processedBoard.selectedAction.value.links && + processedBoard.selectedNode.value + ) { + return getNodeProperty( + processedBoard.selectedAction.value.links, + processedBoard.selectedNode.value + ); + } + return null; + }); + } + processComputable(board as T, "visibility"); + setDefault(board, "visibility", Visibility.Visible); + processComputable(board as T, "width"); + setDefault(board, "width", "100%"); + processComputable(board as T, "height"); + setDefault(board, "height", "400px"); + processComputable(board as T, "classes"); + processComputable(board as T, "style"); + + for (const type in board.types) { + const nodeType: NodeTypeOptions & Partial<BaseNodeType> = board.types[type]; + + processComputable(nodeType as NodeTypeOptions, "title"); + processComputable(nodeType as NodeTypeOptions, "label"); + processComputable(nodeType as NodeTypeOptions, "size"); + setDefault(nodeType, "size", 50); + processComputable(nodeType as NodeTypeOptions, "draggable"); + setDefault(nodeType, "draggable", false); + processComputable(nodeType as NodeTypeOptions, "shape"); + setDefault(nodeType, "shape", Shape.Circle); + processComputable(nodeType as NodeTypeOptions, "canAccept"); + setDefault(nodeType, "canAccept", false); + processComputable(nodeType as NodeTypeOptions, "progress"); + processComputable(nodeType as NodeTypeOptions, "progressDisplay"); + setDefault(nodeType, "progressDisplay", ProgressDisplay.Fill); + processComputable(nodeType as NodeTypeOptions, "progressColor"); + setDefault(nodeType, "progressColor", "none"); + processComputable(nodeType as NodeTypeOptions, "fillColor"); + processComputable(nodeType as NodeTypeOptions, "outlineColor"); + processComputable(nodeType as NodeTypeOptions, "titleColor"); + processComputable(nodeType as NodeTypeOptions, "actionDistance"); + setDefault(nodeType, "actionDistance", Math.PI / 6); + nodeType.nodes = computed(() => + unref(processedBoard.state).nodes.filter(node => node.type === type) + ); + setDefault(nodeType, "onClick", function (node: BoardNode) { + unref(processedBoard.state).selectedNode = node.id; + }); + + if (nodeType.actions) { + for (const action of nodeType.actions) { + processComputable(action, "visibility"); + setDefault(action, "visibility", Visibility.Visible); + processComputable(action, "icon"); + processComputable(action, "fillColor"); + processComputable(action, "tooltip"); + processComputable(action, "links"); + } + } + } + + board[GatherProps] = function (this: GenericBoard) { + const { + nodes, + types, + state, + visibility, + width, + height, + style, + classes, + links, + selectedAction, + selectedNode, + mousePosition + } = this; + return { + nodes, + types, + state, + visibility, + width, + height, + style: unref(style), + classes, + links, + selectedAction, + selectedNode, + mousePosition + }; + }; + + // This is necessary because board.types is different from T and Board + const processedBoard = board as unknown as Board<T>; + return processedBoard; + }); +} + +export function getNodeProperty<T>(property: NodeComputable<T>, node: BoardNode): T { + return isFunction<T, [BoardNode], Computable<T>>(property) ? property(node) : unref(property); +} + +export function getUniqueNodeID(board: GenericBoard): number { + let id = 0; + board.nodes.value.forEach(node => { + if (node.id >= id) { + id = node.id + 1; + } + }); + return id; +} + +const listeners: Record<string, Unsubscribe | undefined> = {}; +globalBus.on("addLayer", layer => { + const boards: GenericBoard[] = findFeatures(layer, BoardType) as GenericBoard[]; + listeners[layer.id] = layer.on("postUpdate", diff => { + boards.forEach(board => { + Object.values(board.types).forEach(type => + type.nodes.value.forEach(node => type.update?.(node, diff)) + ); + }); + }); +}); +globalBus.on("removeLayer", layer => { + // unsubscribe from postUpdate + listeners[layer.id]?.(); + listeners[layer.id] = undefined; +}); diff --git a/src/features/challenges/Challenge.vue b/src/features/challenges/Challenge.vue new file mode 100644 index 0000000..f64f203 --- /dev/null +++ b/src/features/challenges/Challenge.vue @@ -0,0 +1,206 @@ +<template> + <div + v-if="isVisible(visibility)" + :style="[ + { + visibility: isHidden(visibility) ? 'hidden' : undefined + }, + notifyStyle, + unref(style) ?? {} + ]" + :class="{ + feature: true, + challenge: true, + done: unref(completed), + canStart: unref(canStart) && !unref(maxed), + maxed: unref(maxed), + ...unref(classes) + }" + > + <button + class="toggleChallenge" + @click="toggle" + :disabled="!unref(canStart) || unref(maxed)" + > + {{ buttonText }} + </button> + <component v-if="unref(comp)" :is="unref(comp)" /> + <MarkNode :mark="unref(mark)" /> + <Node :id="id" /> + </div> +</template> + +<script lang="tsx"> +import "components/common/features.css"; +import MarkNode from "components/MarkNode.vue"; +import Node from "components/Node.vue"; +import type { GenericChallenge } from "features/challenges/challenge"; +import type { StyleValue } from "features/feature"; +import { isHidden, isVisible, jsx, Visibility } from "features/feature"; +import { getHighNotifyStyle, getNotifyStyle } from "game/notifications"; +import { coerceComponent, isCoercableComponent, processedPropType, unwrapRef } from "util/vue"; +import type { Component, PropType, UnwrapRef } from "vue"; +import { computed, defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue"; + +export default defineComponent({ + props: { + active: { + type: processedPropType<boolean>(Boolean), + required: true + }, + maxed: { + type: processedPropType<boolean>(Boolean), + required: true + }, + canComplete: { + type: processedPropType<boolean>(Boolean), + required: true + }, + display: processedPropType<UnwrapRef<GenericChallenge["display"]>>( + String, + Object, + Function + ), + visibility: { + type: processedPropType<Visibility | boolean>(Number, Boolean), + required: true + }, + style: processedPropType<StyleValue>(String, Object, Array), + classes: processedPropType<Record<string, boolean>>(Object), + completed: { + type: processedPropType<boolean>(Boolean), + required: true + }, + canStart: { + type: processedPropType<boolean>(Boolean), + required: true + }, + mark: processedPropType<boolean | string>(Boolean, String), + id: { + type: String, + required: true + }, + toggle: { + type: Function as PropType<VoidFunction>, + required: true + } + }, + components: { + MarkNode, + Node + }, + setup(props) { + const { active, maxed, canComplete, display } = toRefs(props); + + const buttonText = computed(() => { + if (active.value) { + return canComplete.value ? "Finish" : "Exit Early"; + } + if (maxed.value) { + return "Completed"; + } + return "Start"; + }); + + const comp = shallowRef<Component | string>(""); + + const notifyStyle = computed(() => { + const currActive = unwrapRef(active); + const currCanComplete = unwrapRef(canComplete); + if (currActive) { + if (currCanComplete) { + return getHighNotifyStyle(); + } + return getNotifyStyle(); + } + return {}; + }); + + watchEffect(() => { + const currDisplay = unwrapRef(display); + if (currDisplay == null) { + comp.value = ""; + return; + } + if (isCoercableComponent(currDisplay)) { + comp.value = coerceComponent(currDisplay); + return; + } + const Title = coerceComponent(currDisplay.title || "", "h3"); + const Description = coerceComponent(currDisplay.description, "div"); + const Goal = coerceComponent(currDisplay.goal || ""); + const Reward = coerceComponent(currDisplay.reward || ""); + const EffectDisplay = coerceComponent(currDisplay.effectDisplay || ""); + comp.value = coerceComponent( + jsx(() => ( + <span> + {currDisplay.title != null ? ( + <div> + <Title /> + </div> + ) : null} + <Description /> + {currDisplay.goal != null ? ( + <div> + <br /> + Goal: <Goal /> + </div> + ) : null} + {currDisplay.reward != null ? ( + <div> + <br /> + Reward: <Reward /> + </div> + ) : null} + {currDisplay.effectDisplay != null ? ( + <div> + Currently: <EffectDisplay /> + </div> + ) : null} + </span> + )) + ); + }); + + return { + buttonText, + notifyStyle, + comp, + Visibility, + isVisible, + isHidden, + unref + }; + } +}); +</script> + +<style scoped> +.challenge { + background-color: var(--locked); + width: 300px; + min-height: 300px; + color: black; + font-size: 15px; + display: flex; + flex-flow: column; + align-items: center; +} + +.challenge.done { + background-color: var(--bought); +} + +.challenge button { + min-height: 50px; + width: 120px; + border-radius: var(--border-radius); + box-shadow: none !important; + background: transparent; +} + +.challenge.canStart button { + cursor: pointer; + background-color: var(--layer-color); +} +</style> diff --git a/src/features/challenges/challenge.tsx b/src/features/challenges/challenge.tsx new file mode 100644 index 0000000..ef4c77d --- /dev/null +++ b/src/features/challenges/challenge.tsx @@ -0,0 +1,326 @@ +import { isArray } from "@vue/shared"; +import Toggle from "components/fields/Toggle.vue"; +import ChallengeComponent from "features/challenges/Challenge.vue"; +import type { CoercableComponent, OptionsFunc, Replace, StyleValue } from "features/feature"; +import { + Component, + GatherProps, + getUniqueID, + isVisible, + jsx, + setDefault, + Visibility +} from "features/feature"; +import type { GenericReset } from "features/reset"; +import type { Resource } from "features/resources/resource"; +import { globalBus } from "game/events"; +import type { Persistent } from "game/persistence"; +import { persistent } from "game/persistence"; +import settings, { registerSettingField } from "game/settings"; +import type { DecimalSource } from "util/bignum"; +import Decimal from "util/bignum"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import type { Ref, WatchStopHandle } from "vue"; +import { computed, unref, watch } from "vue"; + +export const ChallengeType = Symbol("ChallengeType"); + +export interface ChallengeOptions { + visibility?: Computable<Visibility | boolean>; + canStart?: Computable<boolean>; + reset?: GenericReset; + canComplete?: Computable<boolean | DecimalSource>; + completionLimit?: Computable<DecimalSource>; + mark?: Computable<boolean | string>; + resource?: Resource; + goal?: Computable<DecimalSource>; + classes?: Computable<Record<string, boolean>>; + style?: Computable<StyleValue>; + display?: Computable< + | CoercableComponent + | { + title?: CoercableComponent; + description: CoercableComponent; + goal?: CoercableComponent; + reward?: CoercableComponent; + effectDisplay?: CoercableComponent; + } + >; + onComplete?: VoidFunction; + onExit?: VoidFunction; + onEnter?: VoidFunction; +} + +export interface BaseChallenge { + id: string; + completions: Persistent<DecimalSource>; + completed: Ref<boolean>; + maxed: Ref<boolean>; + active: Persistent<boolean>; + toggle: VoidFunction; + complete: (remainInChallenge?: boolean) => void; + type: typeof ChallengeType; + [Component]: typeof ChallengeComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Challenge<T extends ChallengeOptions> = Replace< + T & BaseChallenge, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + canStart: GetComputableTypeWithDefault<T["canStart"], true>; + canComplete: GetComputableTypeWithDefault<T["canComplete"], Ref<boolean>>; + completionLimit: GetComputableTypeWithDefault<T["completionLimit"], 1>; + mark: GetComputableTypeWithDefault<T["mark"], Ref<boolean>>; + goal: GetComputableType<T["goal"]>; + classes: GetComputableType<T["classes"]>; + style: GetComputableType<T["style"]>; + display: GetComputableType<T["display"]>; + } +>; + +export type GenericChallenge = Replace< + Challenge<ChallengeOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + canStart: ProcessedComputable<boolean>; + canComplete: ProcessedComputable<boolean | DecimalSource>; + completionLimit: ProcessedComputable<DecimalSource>; + mark: ProcessedComputable<boolean>; + } +>; + +export function createChallenge<T extends ChallengeOptions>( + optionsFunc: OptionsFunc<T, BaseChallenge, GenericChallenge> +): Challenge<T> { + const completions = persistent(0); + const active = persistent(false); + return createLazyProxy(() => { + const challenge = optionsFunc(); + + if ( + challenge.canComplete == null && + (challenge.resource == null || challenge.goal == null) + ) { + console.warn( + "Cannot create challenge without a canComplete property or a resource and goal property", + challenge + ); + throw "Cannot create challenge without a canComplete property or a resource and goal property"; + } + + challenge.id = getUniqueID("challenge-"); + challenge.type = ChallengeType; + challenge[Component] = ChallengeComponent; + + challenge.completions = completions; + challenge.active = active; + challenge.completed = computed(() => + Decimal.gt((challenge as GenericChallenge).completions.value, 0) + ); + challenge.maxed = computed(() => + Decimal.gte( + (challenge as GenericChallenge).completions.value, + unref((challenge as GenericChallenge).completionLimit) + ) + ); + challenge.toggle = function () { + const genericChallenge = challenge as GenericChallenge; + if (genericChallenge.active.value) { + if ( + unref(genericChallenge.canComplete) !== false && + !genericChallenge.maxed.value + ) { + let completions: boolean | DecimalSource = unref(genericChallenge.canComplete); + if (typeof completions === "boolean") { + completions = 1; + } + genericChallenge.completions.value = Decimal.min( + Decimal.add(genericChallenge.completions.value, completions), + unref(genericChallenge.completionLimit) + ); + genericChallenge.onComplete?.(); + } + genericChallenge.active.value = false; + genericChallenge.onExit?.(); + genericChallenge.reset?.reset(); + } else if ( + unref(genericChallenge.canStart) && + isVisible(genericChallenge.visibility) && + !genericChallenge.maxed.value + ) { + genericChallenge.reset?.reset(); + genericChallenge.active.value = true; + genericChallenge.onEnter?.(); + } + }; + challenge.complete = function (remainInChallenge?: boolean) { + const genericChallenge = challenge as GenericChallenge; + let completions: boolean | DecimalSource = unref(genericChallenge.canComplete); + if ( + genericChallenge.active.value && + completions !== false && + (completions === true || Decimal.neq(0, completions)) && + !genericChallenge.maxed.value + ) { + if (typeof completions === "boolean") { + completions = 1; + } + genericChallenge.completions.value = Decimal.min( + Decimal.add(genericChallenge.completions.value, completions), + unref(genericChallenge.completionLimit) + ); + genericChallenge.onComplete?.(); + if (remainInChallenge !== true) { + genericChallenge.active.value = false; + genericChallenge.onExit?.(); + genericChallenge.reset?.reset(); + } + } + }; + processComputable(challenge as T, "visibility"); + setDefault(challenge, "visibility", Visibility.Visible); + const visibility = challenge.visibility as ProcessedComputable<Visibility | boolean>; + challenge.visibility = computed(() => { + if (settings.hideChallenges === true && unref(challenge.maxed)) { + return Visibility.None; + } + return unref(visibility); + }); + if (challenge.canComplete == null) { + challenge.canComplete = computed(() => { + const genericChallenge = challenge as GenericChallenge; + if ( + !genericChallenge.active.value || + genericChallenge.resource == null || + genericChallenge.goal == null + ) { + return false; + } + return Decimal.gte(genericChallenge.resource.value, unref(genericChallenge.goal)); + }); + } + if (challenge.mark == null) { + challenge.mark = computed( + () => + Decimal.gt(unref((challenge as GenericChallenge).completionLimit), 1) && + !!unref(challenge.maxed) + ); + } + + processComputable(challenge as T, "canStart"); + setDefault(challenge, "canStart", true); + processComputable(challenge as T, "canComplete"); + processComputable(challenge as T, "completionLimit"); + setDefault(challenge, "completionLimit", 1); + processComputable(challenge as T, "mark"); + processComputable(challenge as T, "goal"); + processComputable(challenge as T, "classes"); + processComputable(challenge as T, "style"); + processComputable(challenge as T, "display"); + + if (challenge.reset != null) { + globalBus.on("reset", currentReset => { + if (currentReset === challenge.reset && (challenge.active as Ref<boolean>).value) { + (challenge.toggle as VoidFunction)(); + } + }); + } + + challenge[GatherProps] = function (this: GenericChallenge) { + const { + active, + maxed, + canComplete, + display, + visibility, + style, + classes, + completed, + canStart, + mark, + id, + toggle + } = this; + return { + active, + maxed, + canComplete, + display, + visibility, + style: unref(style), + classes, + completed, + canStart, + mark, + id, + toggle + }; + }; + + return challenge as unknown as Challenge<T>; + }); +} + +export function setupAutoComplete( + challenge: GenericChallenge, + autoActive: Computable<boolean> = true, + exitOnComplete = true +): WatchStopHandle { + const isActive = typeof autoActive === "function" ? computed(autoActive) : autoActive; + return watch( + [challenge.canComplete as Ref<boolean>, isActive as Ref<boolean>], + ([canComplete, isActive]) => { + if (canComplete && isActive) { + challenge.complete(!exitOnComplete); + } + } + ); +} + +export function createActiveChallenge( + challenges: GenericChallenge[] +): Ref<GenericChallenge | undefined> { + return computed(() => challenges.find(challenge => challenge.active.value)); +} + +export function isAnyChallengeActive( + challenges: GenericChallenge[] | Ref<GenericChallenge | undefined> +): Ref<boolean> { + if (isArray(challenges)) { + challenges = createActiveChallenge(challenges); + } + return computed(() => (challenges as Ref<GenericChallenge | undefined>).value != null); +} + +declare module "game/settings" { + interface Settings { + hideChallenges: boolean; + } +} + +globalBus.on("loadSettings", settings => { + setDefault(settings, "hideChallenges", false); +}); + +registerSettingField( + jsx(() => ( + <Toggle + title={jsx(() => ( + <span class="option-title"> + Hide maxed challenges + <desc>Hide challenges that have been fully completed.</desc> + </span> + ))} + onUpdate:modelValue={value => (settings.hideChallenges = value)} + modelValue={settings.hideChallenges} + /> + )) +); diff --git a/src/features/clickables/Clickable.vue b/src/features/clickables/Clickable.vue new file mode 100644 index 0000000..ac001a2 --- /dev/null +++ b/src/features/clickables/Clickable.vue @@ -0,0 +1,140 @@ +<template> + <button + v-if="isVisible(visibility)" + :style="[ + { visibility: isHidden(visibility) ? 'hidden' : undefined }, + unref(style) ?? [] + ]" + @click="onClick" + @mousedown="start" + @mouseleave="stop" + @mouseup="stop" + @touchstart.passive="start" + @touchend.passive="stop" + @touchcancel.passive="stop" + :class="{ + feature: true, + clickable: true, + can: unref(canClick), + locked: !unref(canClick), + small, + ...unref(classes) + }" + > + <component v-if="unref(comp)" :is="unref(comp)" /> + <MarkNode :mark="unref(mark)" /> + <Node :id="id" /> + </button> +</template> + +<script lang="tsx"> +import "components/common/features.css"; +import MarkNode from "components/MarkNode.vue"; +import Node from "components/Node.vue"; +import type { GenericClickable } from "features/clickables/clickable"; +import type { StyleValue } from "features/feature"; +import { isHidden, isVisible, jsx, Visibility } from "features/feature"; +import { + coerceComponent, + isCoercableComponent, + processedPropType, + setupHoldToClick, + unwrapRef +} from "util/vue"; +import type { Component, PropType, UnwrapRef } from "vue"; +import { defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue"; + +export default defineComponent({ + props: { + display: { + type: processedPropType<UnwrapRef<GenericClickable["display"]>>( + Object, + String, + Function + ), + required: true + }, + visibility: { + type: processedPropType<Visibility | boolean>(Number, Boolean), + required: true + }, + style: processedPropType<StyleValue>(Object, String, Array), + classes: processedPropType<Record<string, boolean>>(Object), + onClick: Function as PropType<(e?: MouseEvent | TouchEvent) => void>, + onHold: Function as PropType<VoidFunction>, + canClick: { + type: processedPropType<boolean>(Boolean), + required: true + }, + small: Boolean, + mark: processedPropType<boolean | string>(Boolean, String), + id: { + type: String, + required: true + } + }, + components: { + Node, + MarkNode + }, + setup(props) { + const { display, onClick, onHold } = toRefs(props); + + const comp = shallowRef<Component | string>(""); + + watchEffect(() => { + const currDisplay = unwrapRef(display); + if (currDisplay == null) { + comp.value = ""; + return; + } + if (isCoercableComponent(currDisplay)) { + comp.value = coerceComponent(currDisplay); + return; + } + const Title = coerceComponent(currDisplay.title ?? "", "h3"); + const Description = coerceComponent(currDisplay.description, "div"); + comp.value = coerceComponent( + jsx(() => ( + <span> + {currDisplay.title != null ? ( + <div> + <Title /> + </div> + ) : null} + <Description /> + </span> + )) + ); + }); + + const { start, stop } = setupHoldToClick(onClick, onHold); + + return { + start, + stop, + comp, + Visibility, + isVisible, + isHidden, + unref + }; + } +}); +</script> + +<style scoped> +.clickable { + min-height: 120px; + width: 120px; + font-size: 10px; +} + +.clickable.small { + min-height: unset; +} + +.clickable > * { + pointer-events: none; +} +</style> diff --git a/src/features/clickables/clickable.ts b/src/features/clickables/clickable.ts new file mode 100644 index 0000000..c7c83e3 --- /dev/null +++ b/src/features/clickables/clickable.ts @@ -0,0 +1,147 @@ +import ClickableComponent from "features/clickables/Clickable.vue"; +import type { + CoercableComponent, + GenericComponent, + OptionsFunc, + Replace, + StyleValue +} from "features/feature"; +import { Component, GatherProps, getUniqueID, setDefault, Visibility } from "features/feature"; +import type { BaseLayer } from "game/layers"; +import type { Unsubscribe } from "nanoevents"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { computed, unref } from "vue"; + +export const ClickableType = Symbol("Clickable"); + +export interface ClickableOptions { + visibility?: Computable<Visibility | boolean>; + canClick?: Computable<boolean>; + classes?: Computable<Record<string, boolean>>; + style?: Computable<StyleValue>; + mark?: Computable<boolean | string>; + display?: Computable< + | CoercableComponent + | { + title?: CoercableComponent; + description: CoercableComponent; + } + >; + small?: boolean; + onClick?: (e?: MouseEvent | TouchEvent) => void; + onHold?: VoidFunction; +} + +export interface BaseClickable { + id: string; + type: typeof ClickableType; + [Component]: typeof ClickableComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Clickable<T extends ClickableOptions> = Replace< + T & BaseClickable, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + canClick: GetComputableTypeWithDefault<T["canClick"], true>; + classes: GetComputableType<T["classes"]>; + style: GetComputableType<T["style"]>; + mark: GetComputableType<T["mark"]>; + display: GetComputableType<T["display"]>; + } +>; + +export type GenericClickable = Replace< + Clickable<ClickableOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + canClick: ProcessedComputable<boolean>; + } +>; + +export function createClickable<T extends ClickableOptions>( + optionsFunc?: OptionsFunc<T, BaseClickable, GenericClickable> +): Clickable<T> { + return createLazyProxy(() => { + const clickable = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>); + clickable.id = getUniqueID("clickable-"); + clickable.type = ClickableType; + clickable[Component] = ClickableComponent; + + processComputable(clickable as T, "visibility"); + setDefault(clickable, "visibility", Visibility.Visible); + processComputable(clickable as T, "canClick"); + setDefault(clickable, "canClick", true); + processComputable(clickable as T, "classes"); + processComputable(clickable as T, "style"); + processComputable(clickable as T, "mark"); + processComputable(clickable as T, "display"); + + if (clickable.onClick) { + const onClick = clickable.onClick.bind(clickable); + clickable.onClick = function (e) { + if (unref(clickable.canClick) !== false) { + onClick(e); + } + }; + } + if (clickable.onHold) { + const onHold = clickable.onHold.bind(clickable); + clickable.onHold = function () { + if (unref(clickable.canClick) !== false) { + onHold(); + } + }; + } + + clickable[GatherProps] = function (this: GenericClickable) { + const { + display, + visibility, + style, + classes, + onClick, + onHold, + canClick, + small, + mark, + id + } = this; + return { + display, + visibility, + style: unref(style), + classes, + onClick, + onHold, + canClick, + small, + mark, + id + }; + }; + + return clickable as unknown as Clickable<T>; + }); +} + +export function setupAutoClick( + layer: BaseLayer, + clickable: GenericClickable, + autoActive: Computable<boolean> = true +): Unsubscribe { + const isActive: ProcessedComputable<boolean> = + typeof autoActive === "function" ? computed(autoActive) : autoActive; + return layer.on("update", () => { + if (unref(isActive) && unref(clickable.canClick)) { + clickable.onClick?.(); + } + }); +} diff --git a/src/features/conversion.ts b/src/features/conversion.ts new file mode 100644 index 0000000..97637fa --- /dev/null +++ b/src/features/conversion.ts @@ -0,0 +1,536 @@ +import type { OptionsFunc, Replace } from "features/feature"; +import { setDefault } from "features/feature"; +import type { Resource } from "features/resources/resource"; +import type { BaseLayer } from "game/layers"; +import type { Modifier } from "game/modifiers"; +import type { DecimalSource } from "util/bignum"; +import Decimal from "util/bignum"; +import type { WithRequired } from "util/common"; +import type { Computable, GetComputableTypeWithDefault, ProcessedComputable } from "util/computed"; +import { convertComputable, processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import type { Ref } from "vue"; +import { computed, unref } from "vue"; + +/** An object that configures a {@link Conversion}. */ +export interface ConversionOptions { + /** + * The scaling function that is used to determine the rate of conversion from one {@link features/resources/resource.Resource} to the other. + */ + scaling: ScalingFunction; + /** + * How much of the output resource the conversion can currently convert for. + * Typically this will be set for you in a conversion constructor. + */ + currentGain?: Computable<DecimalSource>; + /** + * The absolute amount the output resource will be changed by. + * Typically this will be set for you in a conversion constructor. + * This will differ from {@link currentGain} in the cases where the conversion isn't just adding the converted amount to the output resource. + */ + actualGain?: Computable<DecimalSource>; + /** + * The amount of the input resource currently being required in order to produce the {@link currentGain}. + * That is, if it went below this value then {@link currentGain} would decrease. + * Typically this will be set for you in a conversion constructor. + */ + currentAt?: Computable<DecimalSource>; + /** + * The amount of the input resource required to make {@link currentGain} increase. + * Typically this will be set for you in a conversion constructor. + */ + nextAt?: Computable<DecimalSource>; + /** + * The input {@link features/resources/resource.Resource} for this conversion. + */ + baseResource: Resource; + /** + * The output {@link features/resources/resource.Resource} for this conversion. i.e. the resource being generated. + */ + gainResource: Resource; + /** + * Whether or not to cap the amount of the output resource gained by converting at 1. + * Defaults to true. + */ + buyMax?: Computable<boolean>; + /** + * Whether or not to round up the cost to generate a given amount of the output resource. + */ + roundUpCost?: Computable<boolean>; + /** + * The function that performs the actual conversion from {@link baseResource} to {@link gainResource}. + * Typically this will be set for you in a conversion constructor. + */ + convert?: VoidFunction; + /** + * The function that spends the {@link baseResource} as part of the conversion. + * Defaults to setting the {@link baseResource} amount to 0. + */ + spend?: (amountGained: DecimalSource) => void; + /** + * A callback that happens after a conversion has been completed. + * Receives the amount gained via conversion. + * This will not be called whenever using currentGain without calling convert (e.g. passive generation) + */ + onConvert?: (amountGained: DecimalSource) => void; + /** + * An additional modifier that will be applied to the gain amounts. + * Must be reversible in order to correctly calculate {@link nextAt}. + * @see {@link game/modifiers.createSequentialModifier} if you want to apply multiple modifiers. + */ + gainModifier?: WithRequired<Modifier, "revert">; + /** + * A modifier that will be applied to the cost amounts. + * That is to say, this modifier will be applied to the amount of baseResource before going into the scaling function. + * A cost modifier of x0.5 would give gain amounts equal to the player having half the baseResource they actually have. + * Must be reversible in order to correctly calculate {@link nextAt}. + * @see {@link game/modifiers.createSequentialModifier} if you want to apply multiple modifiers. + */ + costModifier?: WithRequired<Modifier, "revert">; +} + +/** + * The properties that are added onto a processed {@link ConversionOptions} to create a {@link Conversion}. + */ +export interface BaseConversion { + /** + * The function that performs the actual conversion. + */ + convert: VoidFunction; +} + +/** An object that converts one {@link features/resources/resource.Resource} into another at a given rate. */ +export type Conversion<T extends ConversionOptions> = Replace< + T & BaseConversion, + { + currentGain: GetComputableTypeWithDefault<T["currentGain"], Ref<DecimalSource>>; + actualGain: GetComputableTypeWithDefault<T["actualGain"], Ref<DecimalSource>>; + currentAt: GetComputableTypeWithDefault<T["currentAt"], Ref<DecimalSource>>; + nextAt: GetComputableTypeWithDefault<T["nextAt"], Ref<DecimalSource>>; + buyMax: GetComputableTypeWithDefault<T["buyMax"], true>; + spend: undefined extends T["spend"] ? (amountGained: DecimalSource) => void : T["spend"]; + roundUpCost: GetComputableTypeWithDefault<T["roundUpCost"], true>; + } +>; + +/** A type that matches any valid {@link Conversion} object. */ +export type GenericConversion = Replace< + Conversion<ConversionOptions>, + { + currentGain: ProcessedComputable<DecimalSource>; + actualGain: ProcessedComputable<DecimalSource>; + currentAt: ProcessedComputable<DecimalSource>; + nextAt: ProcessedComputable<DecimalSource>; + buyMax: ProcessedComputable<boolean>; + spend: (amountGained: DecimalSource) => void; + roundUpCost: ProcessedComputable<boolean>; + } +>; + +/** + * Lazily creates a conversion with the given options. + * You typically shouldn't use this function directly. Instead use one of the other conversion constructors, which will then call this. + * @param optionsFunc Conversion options. + * @see {@link createCumulativeConversion}. + * @see {@link createIndependentConversion}. + */ +export function createConversion<T extends ConversionOptions>( + optionsFunc: OptionsFunc<T, BaseConversion, GenericConversion> +): Conversion<T> { + return createLazyProxy(() => { + const conversion = optionsFunc(); + + if (conversion.currentGain == null) { + conversion.currentGain = computed(() => { + let gain = conversion.gainModifier + ? conversion.gainModifier.apply( + conversion.scaling.currentGain(conversion as GenericConversion) + ) + : conversion.scaling.currentGain(conversion as GenericConversion); + gain = Decimal.floor(gain).max(0); + + if (unref(conversion.buyMax) === false) { + gain = gain.min(1); + } + return gain; + }); + } + if (conversion.actualGain == null) { + conversion.actualGain = conversion.currentGain; + } + if (conversion.currentAt == null) { + conversion.currentAt = computed(() => { + let current = conversion.scaling.currentAt(conversion as GenericConversion); + if (unref((conversion as GenericConversion).roundUpCost)) + current = Decimal.ceil(current); + return current; + }); + } + if (conversion.nextAt == null) { + conversion.nextAt = computed(() => { + let next = conversion.scaling.nextAt(conversion as GenericConversion); + if (unref((conversion as GenericConversion).roundUpCost)) next = Decimal.ceil(next); + return next; + }); + } + + if (conversion.convert == null) { + conversion.convert = function () { + const amountGained = unref((conversion as GenericConversion).currentGain); + conversion.gainResource.value = Decimal.add( + conversion.gainResource.value, + amountGained + ); + (conversion as GenericConversion).spend(amountGained); + conversion.onConvert?.(amountGained); + }; + } + + if (conversion.spend == null) { + conversion.spend = function () { + conversion.baseResource.value = 0; + }; + } + + processComputable(conversion as T, "currentGain"); + processComputable(conversion as T, "actualGain"); + processComputable(conversion as T, "currentAt"); + processComputable(conversion as T, "nextAt"); + processComputable(conversion as T, "buyMax"); + setDefault(conversion, "buyMax", true); + processComputable(conversion as T, "roundUpCost"); + setDefault(conversion, "roundUpCost", true); + + return conversion as unknown as Conversion<T>; + }); +} + +/** + * A collection of functions that allow a conversion to scale the amount of resources gained based on the input resource. + * This typically shouldn't be created directly. Instead use one of the scaling function constructors. + * @see {@link createLinearScaling}. + * @see {@link createPolynomialScaling}. + */ +export interface ScalingFunction { + /** + * Calculates the amount of the output resource a conversion should be able to currently produce. + * This should be based off of `conversion.baseResource.value`. + * The conversion is responsible for applying the gainModifier, so this function should be un-modified. + * It does not need to be clamped or rounded. + */ + currentGain: (conversion: GenericConversion) => DecimalSource; + /** + * Calculates the amount of the input resource that is required for the current value of `conversion.currentGain`. + * Note that `conversion.currentGain` has been modified by `conversion.gainModifier`, so you will need to revert that as appropriate. + * The conversion is responsible for rounding up the amount as appropriate. + * The returned value should not be below 0. + */ + currentAt: (conversion: GenericConversion) => DecimalSource; + /** + * Calculates the amount of the input resource that would be required for the current value of `conversion.currentGain` to increase. + * Note that `conversion.currentGain` has been modified by `conversion.gainModifier`, so you will need to revert that as appropriate. + * The conversion is responsible for rounding up the amount as appropriate. + * The returned value should not be below 0. + */ + nextAt: (conversion: GenericConversion) => DecimalSource; +} + +/** + * Creates a scaling function based off the formula `(baseResource - base) * coefficient`. + * If the baseResource value is less than base then the currentGain will be 0. + * @param base The base variable in the scaling formula. + * @param coefficient The coefficient variable in the scaling formula. + * @example + * A scaling function created via `createLinearScaling(10, 0.5)` would produce the following values: + * | Base Resource | Current Gain | + * | ------------- | ------------ | + * | 10 | 1 | + * | 12 | 2 | + * | 20 | 6 | + */ +export function createLinearScaling( + base: Computable<DecimalSource>, + coefficient: Computable<DecimalSource> +): ScalingFunction { + const processedBase = convertComputable(base); + const processedCoefficient = convertComputable(coefficient); + return { + currentGain(conversion) { + let baseAmount: DecimalSource = unref(conversion.baseResource.value); + if (conversion.costModifier) { + baseAmount = conversion.costModifier.apply(baseAmount); + } + if (Decimal.lt(baseAmount, unref(processedBase))) { + return 0; + } + + return Decimal.sub(baseAmount, unref(processedBase)) + .sub(1) + .times(unref(processedCoefficient)) + .add(1); + }, + currentAt(conversion) { + let current: DecimalSource = unref(conversion.currentGain); + if (conversion.gainModifier) { + current = conversion.gainModifier.revert(current); + } + current = Decimal.max(0, current) + .sub(1) + .div(unref(processedCoefficient)) + .add(unref(processedBase)); + if (conversion.costModifier) { + current = conversion.costModifier.revert(current); + } + return current; + }, + nextAt(conversion) { + let next: DecimalSource = Decimal.add(unref(conversion.currentGain), 1).floor(); + if (conversion.gainModifier) { + next = conversion.gainModifier.revert(next); + } + next = Decimal.max(0, next) + .sub(1) + .div(unref(processedCoefficient)) + .add(unref(processedBase)) + .max(unref(processedBase)); + if (conversion.costModifier) { + next = conversion.costModifier.revert(next); + } + return next; + } + }; +} + +/** + * Creates a scaling function based off the formula `(baseResource / base) ^ exponent`. + * If the baseResource value is less than base then the currentGain will be 0. + * @param base The base variable in the scaling formula. + * @param exponent The exponent variable in the scaling formula. + * @example + * A scaling function created via `createPolynomialScaling(10, 0.5)` would produce the following values: + * | Base Resource | Current Gain | + * | ------------- | ------------ | + * | 10 | 1 | + * | 40 | 2 | + * | 250 | 5 | + */ +export function createPolynomialScaling( + base: Computable<DecimalSource>, + exponent: Computable<DecimalSource> +): ScalingFunction { + const processedBase = convertComputable(base); + const processedExponent = convertComputable(exponent); + return { + currentGain(conversion) { + let baseAmount: DecimalSource = unref(conversion.baseResource.value); + if (conversion.costModifier) { + baseAmount = conversion.costModifier.apply(baseAmount); + } + if (Decimal.lt(baseAmount, unref(processedBase))) { + return 0; + } + + const gain = Decimal.div(baseAmount, unref(processedBase)).pow( + unref(processedExponent) + ); + + if (gain.isNan()) { + return new Decimal(0); + } + return gain; + }, + currentAt(conversion) { + let current: DecimalSource = unref(conversion.currentGain); + if (conversion.gainModifier) { + current = conversion.gainModifier.revert(current); + } + current = Decimal.max(0, current) + .root(unref(processedExponent)) + .times(unref(processedBase)); + if (conversion.costModifier) { + current = conversion.costModifier.revert(current); + } + return current; + }, + nextAt(conversion) { + let next: DecimalSource = Decimal.add(unref(conversion.currentGain), 1).floor(); + if (conversion.gainModifier) { + next = conversion.gainModifier.revert(next); + } + next = Decimal.max(0, next) + .root(unref(processedExponent)) + .times(unref(processedBase)) + .max(unref(processedBase)); + if (conversion.costModifier) { + next = conversion.costModifier.revert(next); + } + return next; + } + }; +} + +/** + * Creates a conversion that simply adds to the gainResource amount upon converting. + * This is similar to the behavior of "normal" layers in The Modding Tree. + * This is equivalent to just calling createConversion directly. + * @param optionsFunc Conversion options. + */ +export function createCumulativeConversion<S extends ConversionOptions>( + optionsFunc: OptionsFunc<S, BaseConversion, GenericConversion> +): Conversion<S> { + return createConversion(optionsFunc); +} + +/** + * Creates a conversion that will replace the gainResource amount with the new amount upon converting. + * This is similar to the behavior of "static" layers in The Modding Tree. + * @param optionsFunc Converison options. + */ +export function createIndependentConversion<S extends ConversionOptions>( + optionsFunc: OptionsFunc<S, BaseConversion, GenericConversion> +): Conversion<S> { + return createConversion(() => { + const conversion: S = optionsFunc(); + + setDefault(conversion, "buyMax", false); + + if (conversion.currentGain == null) { + conversion.currentGain = computed(() => { + let gain = conversion.gainModifier + ? conversion.gainModifier.apply( + conversion.scaling.currentGain(conversion as GenericConversion) + ) + : conversion.scaling.currentGain(conversion as GenericConversion); + gain = Decimal.floor(gain).max(conversion.gainResource.value); + + if (unref(conversion.buyMax) === false) { + gain = gain.min(Decimal.add(conversion.gainResource.value, 1)); + } + return gain; + }); + } + if (conversion.actualGain == null) { + conversion.actualGain = computed(() => { + let gain = Decimal.sub( + Decimal.floor(conversion.scaling.currentGain(conversion as GenericConversion)), + conversion.gainResource.value + ).max(0); + + if (unref(conversion.buyMax) === false) { + gain = gain.min(1); + } + return gain; + }); + } + setDefault(conversion, "convert", function () { + const amountGained = unref((conversion as GenericConversion).actualGain); + conversion.gainResource.value = conversion.gainModifier + ? conversion.gainModifier.apply( + unref((conversion as GenericConversion).currentGain) + ) + : unref((conversion as GenericConversion).currentGain); + (conversion as GenericConversion).spend(amountGained); + conversion.onConvert?.(amountGained); + }); + + return conversion; + }) as Conversion<S>; +} + +/** + * This will automatically increase the value of conversion.gainResource without lowering the value of the input resource. + * It will by default perform 100% of a conversion's currentGain per second. + * If you use a ref for the rate you can set it's value to 0 when passive generation should be disabled. + * @param layer The layer this passive generation will be associated with. Typically `this` when calling this function from inside a layer's options function. + * @param conversion The conversion that will determine how much generation there is. + * @param rate A multiplier to multiply against the conversion's currentGain. + * @param cap A value that should not be passed via passive generation. If null, no cap is applied. + */ +export function setupPassiveGeneration( + layer: BaseLayer, + conversion: GenericConversion, + rate: Computable<DecimalSource> = 1, + cap: Computable<DecimalSource | null> = null +): void { + const processedRate = convertComputable(rate); + const processedCap = convertComputable(cap); + layer.on("preUpdate", diff => { + const currRate = unref(processedRate); + if (Decimal.neq(currRate, 0)) { + conversion.gainResource.value = Decimal.add( + conversion.gainResource.value, + Decimal.times(currRate, diff).times(Decimal.ceil(unref(conversion.actualGain))) + ) + .min(unref(processedCap) ?? Decimal.dInf) + .max(conversion.gainResource.value); + } + }); +} + +/** + * Given a value, this function finds the amount above a certain value and raises it to a power. + * If the power is <1, this will effectively make the value scale slower after the cap. + * @param value The raw value. + * @param cap The value after which the softcap should be applied. + * @param power The power to raise value above the cap to. + * @example + * A softcap added via `addSoftcap(scaling, 100, 0.5)` would produce the following values: + * | Raw Value | Softcapped Value | + * | --------- | ---------------- | + * | 1 | 1 | + * | 100 | 100 | + * | 125 | 105 | + * | 200 | 110 | + */ +export function softcap( + value: DecimalSource, + cap: DecimalSource, + power: DecimalSource = 0.5 +): DecimalSource { + if (Decimal.lte(value, cap)) { + return value; + } else { + return Decimal.pow(value, power).times(Decimal.pow(cap, Decimal.sub(1, power))); + } +} + +/** + * Creates a scaling function based off an existing scaling function, with a softcap applied to it. + * The softcap will take any value above a certain value and raise it to a power. + * If the power is <1, this will effectively make the value scale slower after the cap. + * @param scaling The raw scaling function. + * @param cap The value after which the softcap should be applied. + * @param power The power to raise value about the cap to. + * @see {@link softcap}. + */ +export function addSoftcap( + scaling: ScalingFunction, + cap: ProcessedComputable<DecimalSource>, + power: ProcessedComputable<DecimalSource> = 0.5 +): ScalingFunction { + return { + ...scaling, + currentAt: conversion => + softcap(scaling.currentAt(conversion), unref(cap), Decimal.recip(unref(power))), + nextAt: conversion => + softcap(scaling.nextAt(conversion), unref(cap), Decimal.recip(unref(power))), + currentGain: conversion => + softcap(scaling.currentGain(conversion), unref(cap), unref(power)) + }; +} + +/** + * Creates a scaling function off an existing function, with a hardcap applied to it. + * The harcap will ensure that the currentGain will stop at a given cap. + * @param scaling The raw scaling function. + * @param cap The maximum value the scaling function can output. + */ +export function addHardcap( + scaling: ScalingFunction, + cap: ProcessedComputable<DecimalSource> +): ScalingFunction { + return { + ...scaling, + currentGain: conversion => Decimal.min(scaling.currentGain(conversion), unref(cap)) + }; +} diff --git a/src/features/feature.ts b/src/features/feature.ts new file mode 100644 index 0000000..d234997 --- /dev/null +++ b/src/features/feature.ts @@ -0,0 +1,151 @@ +import Decimal from "util/bignum"; +import { DoNotCache, ProcessedComputable } from "util/computed"; +import type { CSSProperties, DefineComponent } from "vue"; +import { isRef, unref } from "vue"; + +/** + * A symbol to use as a key for a vue component a feature can be rendered with + * @see {@link util/vue.VueFeature} + */ +export const Component = Symbol("Component"); +/** + * A symbol to use as a key for a prop gathering function that a feature can use to send to its component + * @see {@link util/vue.VueFeature} + */ +export const GatherProps = Symbol("GatherProps"); + +/** + * A type referring to a function that returns JSX and is marked that it shouldn't be wrapped in a ComputedRef + * @see {@link jsx} + */ +export type JSXFunction = (() => JSX.Element) & { [DoNotCache]: true }; +/** + * Any value that can be coerced into (or is) a vue component + */ +export type CoercableComponent = string | DefineComponent | JSXFunction; +/** + * Any value that can be passed into an HTML element's style attribute. + * Note that Profectus uses its own StyleValue and CSSProperties that are extended, + * in order to have additional properties added to them, such as variable CSS variables. + */ +export type StyleValue = string | CSSProperties | Array<string | CSSProperties>; + +/** A type that refers to any vue component */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type GenericComponent = DefineComponent<any, any, any>; + +/** Utility type that is S, with any properties from T that aren't already present in S */ +export type Replace<T, S> = S & Omit<T, keyof S>; + +/** + * Utility function for a function that returns an object of a given type, + * with "this" bound to what the type will eventually be processed into. + * Intended for making lazily evaluated objects. + */ +export type OptionsFunc<T, R = Record<string, unknown>, S = R> = () => T & + Partial<R> & + ThisType<T & S>; + +let id = 0; +/** + * Gets a unique ID to give to each feature, used for any sort of system that needs to identify + * elements in the DOM rather than references to the feature itself. (For example, branches) + * IDs are guaranteed unique, but _NOT_ persistent - they likely will change between updates. + * @param prefix A string to prepend to the id to make it more readable in the inspector tools + */ +export function getUniqueID(prefix = "feature-"): string { + return prefix + id++; +} + +/** Enum for what the visibility of a feature or component should be */ +export enum Visibility { + /** The feature or component should be visible */ + Visible, + /** The feature or component should not appear but still take up space */ + Hidden, + /** The feature or component should not appear not take up space */ + None +} + +export function isVisible(visibility: ProcessedComputable<Visibility | boolean>) { + const currVisibility = unref(visibility); + return currVisibility !== Visibility.None && currVisibility !== false; +} + +export function isHidden(visibility: ProcessedComputable<Visibility | boolean>) { + const currVisibility = unref(visibility); + return currVisibility === Visibility.Hidden; +} + +/** + * Takes a function and marks it as JSX so it won't get auto-wrapped into a ComputedRef. + * The function may also return empty string as empty JSX tags cause issues. + */ +export function jsx(func: () => JSX.Element | ""): JSXFunction { + (func as Partial<JSXFunction>)[DoNotCache] = true; + return func as JSXFunction; +} + +/** Utility function to set a property on an object if and only if it doesn't already exist */ +export function setDefault<T, K extends keyof T>( + object: T, + key: K, + value: T[K] +): asserts object is Exclude<T, K> & Required<Pick<T, K>> { + if (object[key] === undefined && value != undefined) { + object[key] = value; + } +} + +/** + * Traverses an object and returns all features of the given type(s) + * @param obj The object to traverse + * @param types The feature types that will be searched for + */ +export function findFeatures(obj: Record<string, unknown>, ...types: symbol[]): unknown[] { + const objects: unknown[] = []; + const handleObject = (obj: Record<string, unknown>) => { + Object.keys(obj).forEach(key => { + const value = obj[key]; + if (value != null && typeof value === "object") { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + if (types.includes((value as Record<string, any>).type)) { + objects.push(value); + } else if (!(value instanceof Decimal) && !isRef(value)) { + handleObject(value as Record<string, unknown>); + } + } + }); + }; + handleObject(obj); + return objects; +} + +/** + * Traverses an object and returns all features that are _not_ any of the given types. + * Features are any object with a "type" property that has a symbol value. + * @param obj The object to traverse + * @param types The feature types that will be skipped over + */ +export function excludeFeatures(obj: Record<string, unknown>, ...types: symbol[]): unknown[] { + const objects: unknown[] = []; + const handleObject = (obj: Record<string, unknown>) => { + Object.keys(obj).forEach(key => { + const value = obj[key]; + if (value != null && typeof value === "object") { + if ( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + typeof (value as Record<string, any>).type == "symbol" && + // eslint-disable-next-line @typescript-eslint/no-explicit-any + !types.includes((value as Record<string, any>).type) + ) { + objects.push(value); + } else if (!(value instanceof Decimal) && !isRef(value)) { + handleObject(value as Record<string, unknown>); + } + } + }); + }; + handleObject(obj); + return objects; +} diff --git a/src/features/grids/Grid.vue b/src/features/grids/Grid.vue new file mode 100644 index 0000000..2950604 --- /dev/null +++ b/src/features/grids/Grid.vue @@ -0,0 +1,60 @@ +<template> + <div + v-if="isVisible(visibility)" + :style="{ + visibility: isHidden(visibility) ? 'hidden' : undefined + }" + class="table-grid" + > + <div v-for="row in unref(rows)" class="row-grid" :class="{ mergeAdjacent }" :key="row"> + <GridCell + v-for="col in unref(cols)" + :key="col" + v-bind="gatherCellProps(unref(cells)[row * 100 + col])" + /> + </div> + </div> +</template> + +<script lang="ts"> +import "components/common/table.css"; +import themes from "data/themes"; +import { isHidden, isVisible, Visibility } from "features/feature"; +import type { GridCell } from "features/grids/grid"; +import settings from "game/settings"; +import { processedPropType } from "util/vue"; +import { computed, defineComponent, unref } from "vue"; +import GridCellVue from "./GridCell.vue"; + +export default defineComponent({ + props: { + visibility: { + type: processedPropType<Visibility | boolean>(Number, Boolean), + required: true + }, + rows: { + type: processedPropType<number>(Number), + required: true + }, + cols: { + type: processedPropType<number>(Number), + required: true + }, + cells: { + type: processedPropType<Record<string, GridCell>>(Object), + required: true + } + }, + components: { GridCell: GridCellVue }, + setup() { + const mergeAdjacent = computed(() => themes[settings.theme].mergeAdjacent); + + function gatherCellProps(cell: GridCell) { + const { visibility, onClick, onHold, display, title, style, canClick, id } = cell; + return { visibility, onClick, onHold, display, title, style, canClick, id }; + } + + return { unref, gatherCellProps, Visibility, mergeAdjacent, isVisible, isHidden }; + } +}); +</script> diff --git a/src/features/grids/GridCell.vue b/src/features/grids/GridCell.vue new file mode 100644 index 0000000..876b7c3 --- /dev/null +++ b/src/features/grids/GridCell.vue @@ -0,0 +1,98 @@ +<template> + <button + v-if="isVisible(visibility)" + :class="{ feature: true, tile: true, can: unref(canClick), locked: !unref(canClick) }" + :style="[ + { + visibility: isHidden(visibility) ? 'hidden' : undefined + }, + unref(style) ?? {} + ]" + @click="onClick" + @mousedown="start" + @mouseleave="stop" + @mouseup="stop" + @touchstart.passive="start" + @touchend.passive="stop" + @touchcancel.passive="stop" + > + <div v-if="title"><component :is="titleComponent" /></div> + <component :is="component" style="white-space: pre-line" /> + <Node :id="id" /> + </button> +</template> + +<script lang="ts"> +import "components/common/features.css"; +import Node from "components/Node.vue"; +import type { CoercableComponent, StyleValue } from "features/feature"; +import { isHidden, isVisible, Visibility } from "features/feature"; +import { + computeComponent, + computeOptionalComponent, + processedPropType, + setupHoldToClick +} from "util/vue"; +import type { PropType } from "vue"; +import { defineComponent, toRefs, unref } from "vue"; + +export default defineComponent({ + props: { + visibility: { + type: processedPropType<Visibility | boolean>(Number, Boolean), + required: true + }, + onClick: Function as PropType<(e?: MouseEvent | TouchEvent) => void>, + onHold: Function as PropType<VoidFunction>, + display: { + type: processedPropType<CoercableComponent>(Object, String, Function), + required: true + }, + title: processedPropType<CoercableComponent>(Object, String, Function), + style: processedPropType<StyleValue>(String, Object, Array), + canClick: { + type: processedPropType<boolean>(Boolean), + required: true + }, + id: { + type: String, + required: true + } + }, + components: { + Node + }, + setup(props) { + const { onClick, onHold, title, display } = toRefs(props); + + const { start, stop } = setupHoldToClick(onClick, onHold); + + const titleComponent = computeOptionalComponent(title); + const component = computeComponent(display); + + return { + start, + stop, + titleComponent, + component, + Visibility, + unref, + isVisible, + isHidden + }; + } +}); +</script> + +<style scoped> +.tile { + min-height: 80px; + width: 80px; + font-size: 10px; + background-color: var(--layer-color); +} + +.tile > * { + pointer-events: none; +} +</style> diff --git a/src/features/grids/grid.ts b/src/features/grids/grid.ts new file mode 100644 index 0000000..eda80da --- /dev/null +++ b/src/features/grids/grid.ts @@ -0,0 +1,302 @@ +import type { CoercableComponent, OptionsFunc, Replace, StyleValue } from "features/feature"; +import { Component, GatherProps, getUniqueID, setDefault, Visibility } from "features/feature"; +import GridComponent from "features/grids/Grid.vue"; +import type { Persistent, State } from "game/persistence"; +import { persistent } from "game/persistence"; +import { isFunction } from "util/common"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import type { Ref } from "vue"; +import { computed, unref } from "vue"; + +export const GridType = Symbol("Grid"); + +export type CellComputable<T> = Computable<T> | ((id: string | number, state: State) => T); + +function createGridProxy(grid: GenericGrid): Record<string | number, GridCell> { + return new Proxy({}, getGridHandler(grid)) as Record<string | number, GridCell>; +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function getGridHandler(grid: GenericGrid): ProxyHandler<Record<string | number, GridCell>> { + const keys = computed(() => { + const keys = []; + for (let row = 1; row <= unref(grid.rows); row++) { + for (let col = 1; col <= unref(grid.cols); col++) { + keys.push((row * 100 + col).toString()); + } + } + return keys; + }); + return { + get(target: Record<string | number, GridCell>, key: PropertyKey) { + if (key === "isProxy") { + return true; + } + + if (typeof key === "symbol") { + return (grid as never)[key]; + } + + if (!keys.value.includes(key.toString())) { + return undefined; + } + + if (target[key] == null) { + target[key] = new Proxy( + grid, + getCellHandler(key.toString()) + ) as unknown as GridCell; + } + + return target[key]; + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + set(target: Record<string | number, GridCell>, key: PropertyKey, value: any) { + console.warn("Cannot set grid cells", target, key, value); + return false; + }, + ownKeys() { + return keys.value; + }, + has(target: Record<string | number, GridCell>, key: PropertyKey) { + return keys.value.includes(key.toString()); + }, + getOwnPropertyDescriptor(target: Record<string | number, GridCell>, key: PropertyKey) { + if (keys.value.includes(key.toString())) { + return { + configurable: true, + enumerable: true, + writable: false + }; + } + } + }; +} + +function getCellHandler(id: string): ProxyHandler<GenericGrid> { + const keys = [ + "id", + "visibility", + "canClick", + "startState", + "state", + "style", + "classes", + "title", + "display", + "onClick", + "onHold" + ]; + const cache: Record<string, Ref<unknown>> = {}; + return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + get(target, key, receiver): any { + if (key === "isProxy") { + return true; + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let prop = (target as any)[key]; + + if (isFunction(prop)) { + return () => prop.call(receiver, id, target.getState(id)); + } + if (prop != undefined || typeof key === "symbol") { + return prop; + } + + key = key.slice(0, 1).toUpperCase() + key.slice(1); + + if (key === "startState") { + return prop.call(receiver, id); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + prop = (target as any)[`get${key}`]; + if (isFunction(prop)) { + if (!(key in cache)) { + cache[key] = computed(() => prop.call(receiver, id, target.getState(id))); + } + return cache[key].value; + } else if (prop != undefined) { + return unref(prop); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + prop = (target as any)[`on${key}`]; + if (isFunction(prop)) { + return () => prop.call(receiver, id, target.getState(id)); + } else if (prop != undefined) { + return prop; + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + return (target as any)[key]; + }, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + set(target: Record<string, any>, key: string, value: any, receiver: typeof Proxy): boolean { + key = `set${key.slice(0, 1).toUpperCase() + key.slice(1)}`; + if (key in target && isFunction(target[key]) && target[key].length < 3) { + target[key].call(receiver, id, value); + return true; + } else { + console.warn(`No setter for "${key}".`, target); + return false; + } + }, + ownKeys() { + return keys; + }, + has(target, key) { + return keys.includes(key.toString()); + }, + getOwnPropertyDescriptor(target, key) { + if (keys.includes(key.toString())) { + return { + configurable: true, + enumerable: true, + writable: false + }; + } + } + }; +} + +export interface GridCell { + id: string; + visibility: Visibility | boolean; + canClick: boolean; + startState: State; + state: State; + style?: StyleValue; + classes?: Record<string, boolean>; + title?: CoercableComponent; + display: CoercableComponent; + onClick?: (e?: MouseEvent | TouchEvent) => void; + onHold?: VoidFunction; +} + +export interface GridOptions { + visibility?: Computable<Visibility | boolean>; + rows: Computable<number>; + cols: Computable<number>; + getVisibility?: CellComputable<Visibility | boolean>; + getCanClick?: CellComputable<boolean>; + getStartState: Computable<State> | ((id: string | number) => State); + getStyle?: CellComputable<StyleValue>; + getClasses?: CellComputable<Record<string, boolean>>; + getTitle?: CellComputable<CoercableComponent>; + getDisplay: CellComputable<CoercableComponent>; + onClick?: (id: string | number, state: State, e?: MouseEvent | TouchEvent) => void; + onHold?: (id: string | number, state: State) => void; +} + +export interface BaseGrid { + id: string; + getID: (id: string | number, state: State) => string; + getState: (id: string | number) => State; + setState: (id: string | number, state: State) => void; + cells: Record<string | number, GridCell>; + cellState: Persistent<Record<string | number, State>>; + type: typeof GridType; + [Component]: typeof GridComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Grid<T extends GridOptions> = Replace< + T & BaseGrid, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + rows: GetComputableType<T["rows"]>; + cols: GetComputableType<T["cols"]>; + getVisibility: GetComputableTypeWithDefault<T["getVisibility"], Visibility.Visible>; + getCanClick: GetComputableTypeWithDefault<T["getCanClick"], true>; + getStartState: GetComputableType<T["getStartState"]>; + getStyle: GetComputableType<T["getStyle"]>; + getClasses: GetComputableType<T["getClasses"]>; + getTitle: GetComputableType<T["getTitle"]>; + getDisplay: GetComputableType<T["getDisplay"]>; + } +>; + +export type GenericGrid = Replace< + Grid<GridOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + getVisibility: ProcessedComputable<Visibility | boolean>; + getCanClick: ProcessedComputable<boolean>; + } +>; + +export function createGrid<T extends GridOptions>( + optionsFunc: OptionsFunc<T, BaseGrid, GenericGrid> +): Grid<T> { + const cellState = persistent<Record<string | number, State>>({}); + return createLazyProxy(() => { + const grid = optionsFunc(); + grid.id = getUniqueID("grid-"); + grid[Component] = GridComponent; + + grid.cellState = cellState; + + grid.getID = function (this: GenericGrid, cell: string | number) { + return grid.id + "-" + cell; + }; + grid.getState = function (this: GenericGrid, cell: string | number) { + if (this.cellState.value[cell] != undefined) { + return cellState.value[cell]; + } + return this.cells[cell].startState; + }; + grid.setState = function (this: GenericGrid, cell: string | number, state: State) { + cellState.value[cell] = state; + }; + + grid.cells = createGridProxy(grid as GenericGrid); + + processComputable(grid as T, "visibility"); + setDefault(grid, "visibility", Visibility.Visible); + processComputable(grid as T, "rows"); + processComputable(grid as T, "cols"); + processComputable(grid as T, "getVisibility"); + setDefault(grid, "getVisibility", Visibility.Visible); + processComputable(grid as T, "getCanClick"); + setDefault(grid, "getCanClick", true); + processComputable(grid as T, "getStartState"); + processComputable(grid as T, "getStyle"); + processComputable(grid as T, "getClasses"); + processComputable(grid as T, "getTitle"); + processComputable(grid as T, "getDisplay"); + + if (grid.onClick) { + const onClick = grid.onClick.bind(grid); + grid.onClick = function (id, state, e) { + if (unref((grid as GenericGrid).cells[id].canClick)) { + onClick(id, state, e); + } + }; + } + if (grid.onHold) { + const onHold = grid.onHold.bind(grid); + grid.onHold = function (id, state) { + if (unref((grid as GenericGrid).cells[id].canClick)) { + onHold(id, state); + } + }; + } + + grid[GatherProps] = function (this: GenericGrid) { + const { visibility, rows, cols, cells, id } = this; + return { visibility, rows, cols, cells, id }; + }; + + return grid as unknown as Grid<T>; + }); +} diff --git a/src/features/hotkey.tsx b/src/features/hotkey.tsx new file mode 100644 index 0000000..595344d --- /dev/null +++ b/src/features/hotkey.tsx @@ -0,0 +1,119 @@ +import { hasWon } from "data/projEntry"; +import type { OptionsFunc, Replace } from "features/feature"; +import { findFeatures, jsx, setDefault } from "features/feature"; +import { globalBus } from "game/events"; +import player from "game/player"; +import { registerInfoComponent } from "game/settings"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { shallowReactive, unref } from "vue"; +import Hotkey from "components/Hotkey.vue"; + +export const hotkeys: Record<string, GenericHotkey | undefined> = shallowReactive({}); +export const HotkeyType = Symbol("Hotkey"); + +export interface HotkeyOptions { + enabled?: Computable<boolean>; + key: string; + description: Computable<string>; + onPress: VoidFunction; +} + +export interface BaseHotkey { + type: typeof HotkeyType; +} + +export type Hotkey<T extends HotkeyOptions> = Replace< + T & BaseHotkey, + { + enabled: GetComputableTypeWithDefault<T["enabled"], true>; + description: GetComputableType<T["description"]>; + } +>; + +export type GenericHotkey = Replace< + Hotkey<HotkeyOptions>, + { + enabled: ProcessedComputable<boolean>; + } +>; + +const uppercaseNumbers = [")", "!", "@", "#", "$", "%", "^", "&", "*", "("]; + +export function createHotkey<T extends HotkeyOptions>( + optionsFunc: OptionsFunc<T, BaseHotkey, GenericHotkey> +): Hotkey<T> { + return createLazyProxy(() => { + const hotkey = optionsFunc(); + hotkey.type = HotkeyType; + + processComputable(hotkey as T, "enabled"); + setDefault(hotkey, "enabled", true); + processComputable(hotkey as T, "description"); + + return hotkey as unknown as Hotkey<T>; + }); +} + +globalBus.on("addLayer", layer => { + (findFeatures(layer, HotkeyType) as GenericHotkey[]).forEach(hotkey => { + hotkeys[hotkey.key] = hotkey; + }); +}); + +globalBus.on("removeLayer", layer => { + (findFeatures(layer, HotkeyType) as GenericHotkey[]).forEach(hotkey => { + hotkeys[hotkey.key] = undefined; + }); +}); + +document.onkeydown = function (e) { + if ((e.target as HTMLElement | null)?.tagName === "INPUT") { + return; + } + if (hasWon.value && !player.keepGoing) { + return; + } + let key = e.key; + if (uppercaseNumbers.includes(key)) { + key = "shift+" + uppercaseNumbers.indexOf(key); + } else if (e.shiftKey) { + key = "shift+" + key; + } + if (e.ctrlKey) { + key = "ctrl+" + key; + } + const hotkey = hotkeys[key]; + if (hotkey && unref(hotkey.enabled)) { + e.preventDefault(); + hotkey.onPress(); + } +}; + +registerInfoComponent( + jsx(() => { + const keys = Object.values(hotkeys).filter(hotkey => unref(hotkey?.enabled)); + if (keys.length === 0) { + return ""; + } + return ( + <div> + <br /> + <h4>Hotkeys</h4> + <div style="column-count: 2"> + {keys.map(hotkey => ( + <div> + <Hotkey hotkey={hotkey as GenericHotkey} /> {hotkey?.description} + </div> + ))} + </div> + </div> + ); + }) +); diff --git a/src/features/infoboxes/Infobox.vue b/src/features/infoboxes/Infobox.vue new file mode 100644 index 0000000..302d985 --- /dev/null +++ b/src/features/infoboxes/Infobox.vue @@ -0,0 +1,183 @@ +<template> + <div + class="infobox" + v-if="isVisible(visibility)" + :style="[ + { + borderColor: unref(color), + visibility: isHidden(visibility) ? 'hidden' : undefined + }, + unref(style) ?? {} + ]" + :class="{ collapsed: unref(collapsed), stacked, ...unref(classes) }" + > + <button + class="title" + :style="[{ backgroundColor: unref(color) }, unref(titleStyle) || []]" + @click="collapsed.value = !unref(collapsed)" + > + <span class="toggle">▼</span> + <component :is="titleComponent" /> + </button> + <CollapseTransition> + <div v-if="!unref(collapsed)" class="body" :style="{ backgroundColor: unref(color) }"> + <component :is="bodyComponent" :style="unref(bodyStyle)" /> + </div> + </CollapseTransition> + <Node :id="id" /> + </div> +</template> + +<script lang="ts"> +import CollapseTransition from "@ivanv/vue-collapse-transition/src/CollapseTransition.vue"; +import Node from "components/Node.vue"; +import themes from "data/themes"; +import type { CoercableComponent } from "features/feature"; +import { isHidden, isVisible, Visibility } from "features/feature"; +import settings from "game/settings"; +import { computeComponent, processedPropType } from "util/vue"; +import type { PropType, Ref, StyleValue } from "vue"; +import { computed, defineComponent, toRefs, unref } from "vue"; + +export default defineComponent({ + props: { + visibility: { + type: processedPropType<Visibility | boolean>(Number, Boolean), + required: true + }, + display: { + type: processedPropType<CoercableComponent>(Object, String, Function), + required: true + }, + title: { + type: processedPropType<CoercableComponent>(Object, String, Function), + required: true + }, + color: processedPropType<string>(String), + collapsed: { + type: Object as PropType<Ref<boolean>>, + required: true + }, + style: processedPropType<StyleValue>(Object, String, Array), + titleStyle: processedPropType<StyleValue>(Object, String, Array), + bodyStyle: processedPropType<StyleValue>(Object, String, Array), + classes: processedPropType<Record<string, boolean>>(Object), + id: { + type: String, + required: true + } + }, + components: { + Node, + CollapseTransition + }, + setup(props) { + const { title, display } = toRefs(props); + + const titleComponent = computeComponent(title); + const bodyComponent = computeComponent(display); + const stacked = computed(() => themes[settings.theme].mergeAdjacent); + + return { + titleComponent, + bodyComponent, + stacked, + unref, + Visibility, + isVisible, + isHidden + }; + } +}); +</script> + +<style scoped> +.infobox { + position: relative; + width: 600px; + max-width: 95%; + margin-top: 0; + text-align: left; + border-style: solid; + border-width: 0px; + box-sizing: border-box; + border-radius: 5px; +} + +.infobox.stacked { + border-width: 4px; +} + +.infobox:not(.stacked) + .infobox:not(.stacked) { + margin-top: 20px; +} + +.infobox + :not(.infobox) { + margin-top: 10px; +} + +.title { + font-size: 24px; + color: black; + cursor: pointer; + border: none; + padding: 4px; + width: auto; + text-align: left; + padding-left: 30px; +} + +.infobox:not(.stacked) .title { + border-top-left-radius: 5px; + border-top-right-radius: 5px; +} + +.infobox.stacked + .infobox.stacked { + border-top-left-radius: 0; + border-top-right-radius: 0; + margin-top: -5px; +} + +.stacked .title { + width: 100%; +} + +.collapsed:not(.stacked) .title::after { + content: ""; + position: absolute; + left: 0; + right: 0; + bottom: 0; + height: 4px; + background-color: inherit; +} + +.toggle { + position: absolute; + left: 10px; +} + +.collapsed .toggle { + transform: rotate(-90deg); +} + +.body { + transition-duration: 0.5s; + border-radius: 5px; + border-top-left-radius: 0; +} + +.infobox:not(.stacked) .body { + padding: 4px; +} + +.body > * { + padding: 8px; + width: 100%; + display: block; + box-sizing: border-box; + border-radius: 5px; + border-top-left-radius: 0; + background-color: var(--background); +} +</style> diff --git a/src/features/infoboxes/infobox.ts b/src/features/infoboxes/infobox.ts new file mode 100644 index 0000000..43e3ffa --- /dev/null +++ b/src/features/infoboxes/infobox.ts @@ -0,0 +1,109 @@ +import type { CoercableComponent, OptionsFunc, Replace, StyleValue } from "features/feature"; +import { Component, GatherProps, getUniqueID, setDefault, Visibility } from "features/feature"; +import InfoboxComponent from "features/infoboxes/Infobox.vue"; +import type { Persistent } from "game/persistence"; +import { persistent } from "game/persistence"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { unref } from "vue"; + +export const InfoboxType = Symbol("Infobox"); + +export interface InfoboxOptions { + visibility?: Computable<Visibility | boolean>; + color?: Computable<string>; + style?: Computable<StyleValue>; + titleStyle?: Computable<StyleValue>; + bodyStyle?: Computable<StyleValue>; + classes?: Computable<Record<string, boolean>>; + title: Computable<CoercableComponent>; + display: Computable<CoercableComponent>; +} + +export interface BaseInfobox { + id: string; + collapsed: Persistent<boolean>; + type: typeof InfoboxType; + [Component]: typeof InfoboxComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Infobox<T extends InfoboxOptions> = Replace< + T & BaseInfobox, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + color: GetComputableType<T["color"]>; + style: GetComputableType<T["style"]>; + titleStyle: GetComputableType<T["titleStyle"]>; + bodyStyle: GetComputableType<T["bodyStyle"]>; + classes: GetComputableType<T["classes"]>; + title: GetComputableType<T["title"]>; + display: GetComputableType<T["display"]>; + } +>; + +export type GenericInfobox = Replace< + Infobox<InfoboxOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + } +>; + +export function createInfobox<T extends InfoboxOptions>( + optionsFunc: OptionsFunc<T, BaseInfobox, GenericInfobox> +): Infobox<T> { + const collapsed = persistent<boolean>(false); + return createLazyProxy(() => { + const infobox = optionsFunc(); + infobox.id = getUniqueID("infobox-"); + infobox.type = InfoboxType; + infobox[Component] = InfoboxComponent; + + infobox.collapsed = collapsed; + + processComputable(infobox as T, "visibility"); + setDefault(infobox, "visibility", Visibility.Visible); + processComputable(infobox as T, "color"); + processComputable(infobox as T, "style"); + processComputable(infobox as T, "titleStyle"); + processComputable(infobox as T, "bodyStyle"); + processComputable(infobox as T, "classes"); + processComputable(infobox as T, "title"); + processComputable(infobox as T, "display"); + + infobox[GatherProps] = function (this: GenericInfobox) { + const { + visibility, + display, + title, + color, + collapsed, + style, + titleStyle, + bodyStyle, + classes, + id + } = this; + return { + visibility, + display, + title, + color, + collapsed, + style: unref(style), + titleStyle, + bodyStyle, + classes, + id + }; + }; + + return infobox as unknown as Infobox<T>; + }); +} diff --git a/src/features/links/Link.vue b/src/features/links/Link.vue new file mode 100644 index 0000000..f7b9580 --- /dev/null +++ b/src/features/links/Link.vue @@ -0,0 +1,57 @@ +<template> + <line + stroke-width="15px" + stroke="white" + v-bind="link" + :x1="startPosition.x" + :y1="startPosition.y" + :x2="endPosition.x" + :y2="endPosition.y" + /> +</template> + +<script setup lang="ts"> +import type { Link } from "features/links/links"; +import type { FeatureNode } from "game/layers"; +import { computed, toRefs } from "vue"; + +const _props = defineProps<{ + link: Link; + startNode: FeatureNode; + endNode: FeatureNode; + boundingRect: DOMRect | undefined; +}>(); +const props = toRefs(_props); + +const startPosition = computed(() => { + const rect = props.startNode.value.rect; + const boundingRect = props.boundingRect.value; + const position = boundingRect + ? { + x: rect.x + rect.width / 2 - boundingRect.x, + y: rect.y + rect.height / 2 - boundingRect.y + } + : { x: 0, y: 0 }; + if (props.link.value.offsetStart) { + position.x += props.link.value.offsetStart.x; + position.y += props.link.value.offsetStart.y; + } + return position; +}); + +const endPosition = computed(() => { + const rect = props.endNode.value.rect; + const boundingRect = props.boundingRect.value; + const position = boundingRect + ? { + x: rect.x + rect.width / 2 - boundingRect.x, + y: rect.y + rect.height / 2 - boundingRect.y + } + : { x: 0, y: 0 }; + if (props.link.value.offsetEnd) { + position.x += props.link.value.offsetEnd.x; + position.y += props.link.value.offsetEnd.y; + } + return position; +}); +</script> diff --git a/src/features/links/Links.vue b/src/features/links/Links.vue new file mode 100644 index 0000000..dafab2b --- /dev/null +++ b/src/features/links/Links.vue @@ -0,0 +1,64 @@ +<template> + <svg v-if="validLinks" v-bind="$attrs"> + <LinkVue + v-for="(link, index) in validLinks" + :key="index" + :link="link" + :boundingRect="boundingRect" + :startNode="nodes[link.startNode.id]!" + :endNode="nodes[link.endNode.id]!" + /> + </svg> + <div ref="resizeListener" class="resize-listener" /> +</template> + +<script setup lang="ts"> +import type { Link } from "features/links/links"; +import type { FeatureNode } from "game/layers"; +import { BoundsInjectionKey, NodesInjectionKey } from "game/layers"; +import { computed, inject, onMounted, ref, toRef, watch } from "vue"; +import LinkVue from "./Link.vue"; + +const _props = defineProps<{ links?: Link[] }>(); +const links = toRef(_props, "links"); + +const resizeListener = ref<Element | null>(null); + +const nodes = inject(NodesInjectionKey, ref<Record<string, FeatureNode | undefined>>({})); +const outerBoundingRect = inject(BoundsInjectionKey, ref<DOMRect | undefined>(undefined)); +const boundingRect = ref<DOMRect | undefined>(resizeListener.value?.getBoundingClientRect()); +watch( + outerBoundingRect, + () => (boundingRect.value = resizeListener.value?.getBoundingClientRect()) +); +onMounted(() => (boundingRect.value = resizeListener.value?.getBoundingClientRect())); + +const validLinks = computed(() => { + const n = nodes.value; + return ( + links.value?.filter(link => n[link.startNode.id]?.rect && n[link.startNode.id]?.rect) ?? [] + ); +}); +</script> + +<style scoped> +.resize-listener { + position: absolute; + top: 0px; + left: 0; + right: -4px; + bottom: 5px; + z-index: -10; + pointer-events: none; +} + +svg { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: -10; + pointer-events: none; +} +</style> diff --git a/src/features/links/links.ts b/src/features/links/links.ts new file mode 100644 index 0000000..5ab8779 --- /dev/null +++ b/src/features/links/links.ts @@ -0,0 +1,62 @@ +import type { OptionsFunc, Replace } from "features/feature"; +import { GatherProps, Component } from "features/feature"; +import type { Position } from "game/layers"; +import type { Computable, GetComputableType, ProcessedComputable } from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import type { SVGAttributes } from "vue"; +import LinksComponent from "./Links.vue"; + +export const LinksType = Symbol("Links"); + +export interface Link extends SVGAttributes { + startNode: { id: string }; + endNode: { id: string }; + offsetStart?: Position; + offsetEnd?: Position; +} + +export interface LinksOptions { + links: Computable<Link[]>; +} + +export interface BaseLinks { + type: typeof LinksType; + [Component]: typeof LinksComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Links<T extends LinksOptions> = Replace< + T & BaseLinks, + { + links: GetComputableType<T["links"]>; + } +>; + +export type GenericLinks = Replace< + Links<LinksOptions>, + { + links: ProcessedComputable<Link[]>; + } +>; + +export function createLinks<T extends LinksOptions>( + optionsFunc: OptionsFunc<T, BaseLinks, GenericLinks> +): Links<T> { + return createLazyProxy(() => { + const links = optionsFunc(); + links.type = LinksType; + links[Component] = LinksComponent; + + processComputable(links as T, "links"); + + links[GatherProps] = function (this: GenericLinks) { + const { links } = this; + return { + links + }; + }; + + return links as unknown as Links<T>; + }); +} diff --git a/src/features/milestones/Milestone.vue b/src/features/milestones/Milestone.vue new file mode 100644 index 0000000..e5dac97 --- /dev/null +++ b/src/features/milestones/Milestone.vue @@ -0,0 +1,128 @@ +<template> + <div + v-if="isVisible(visibility)" + :style="[ + { + visibility: isHidden(visibility) ? 'hidden' : undefined + }, + unref(style) ?? {} + ]" + :class="{ feature: true, milestone: true, done: unref(earned), ...unref(classes) }" + > + <component :is="unref(comp)" /> + <Node :id="id" /> + </div> +</template> + +<script lang="tsx"> +import "components/common/features.css"; +import Node from "components/Node.vue"; +import type { StyleValue } from "features/feature"; +import { isHidden, isVisible, jsx, Visibility } from "features/feature"; +import type { GenericMilestone } from "features/milestones/milestone"; +import { coerceComponent, isCoercableComponent, processedPropType, unwrapRef } from "util/vue"; +import type { Component, UnwrapRef } from "vue"; +import { defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue"; + +export default defineComponent({ + props: { + visibility: { + type: processedPropType<Visibility | boolean>(Number, Boolean), + required: true + }, + display: { + type: processedPropType<UnwrapRef<GenericMilestone["display"]>>( + String, + Object, + Function + ), + required: true + }, + style: processedPropType<StyleValue>(String, Object, Array), + classes: processedPropType<Record<string, boolean>>(Object), + earned: { + type: processedPropType<boolean>(Boolean), + required: true + }, + id: { + type: String, + required: true + } + }, + components: { + Node + }, + setup(props) { + const { display } = toRefs(props); + + const comp = shallowRef<Component | string>(""); + + watchEffect(() => { + const currDisplay = unwrapRef(display); + if (currDisplay == null) { + comp.value = ""; + return; + } + if (isCoercableComponent(currDisplay)) { + comp.value = coerceComponent(currDisplay); + return; + } + const Requirement = coerceComponent(currDisplay.requirement, "h3"); + const EffectDisplay = coerceComponent(currDisplay.effectDisplay || "", "b"); + const OptionsDisplay = coerceComponent(currDisplay.optionsDisplay || "", "span"); + comp.value = coerceComponent( + jsx(() => ( + <span> + <Requirement /> + {currDisplay.effectDisplay != null ? ( + <div> + <EffectDisplay /> + </div> + ) : null} + {currDisplay.optionsDisplay != null ? ( + <div class="equal-spaced"> + <OptionsDisplay /> + </div> + ) : null} + </span> + )) + ); + }); + + return { + comp, + unref, + Visibility, + isVisible, + isHidden + }; + } +}); +</script> + +<style scoped> +.milestone { + width: calc(100% - 10px); + min-width: 120px; + padding-left: 5px; + padding-right: 5px; + background-color: var(--locked); + border-width: 4px; + border-radius: 5px; + color: rgba(0, 0, 0, 0.5); +} + +.milestone.done { + background-color: var(--bought); + cursor: default; +} + +.milestone :deep(.equal-spaced) { + display: flex; + justify-content: center; +} + +.milestone :deep(.equal-spaced > *) { + margin: auto; +} +</style> diff --git a/src/features/milestones/milestone.tsx b/src/features/milestones/milestone.tsx new file mode 100644 index 0000000..6ea736b --- /dev/null +++ b/src/features/milestones/milestone.tsx @@ -0,0 +1,235 @@ +import Select from "components/fields/Select.vue"; +import type { + CoercableComponent, + GenericComponent, + OptionsFunc, + Replace, + StyleValue +} from "features/feature"; +import { + Component, + GatherProps, + getUniqueID, + isVisible, + jsx, + setDefault, + Visibility +} from "features/feature"; +import MilestoneComponent from "features/milestones/Milestone.vue"; +import { globalBus } from "game/events"; +import "game/notifications"; +import type { Persistent } from "game/persistence"; +import { persistent } from "game/persistence"; +import player from "game/player"; +import settings, { registerSettingField } from "game/settings"; +import { camelToTitle } from "util/common"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { coerceComponent, isCoercableComponent } from "util/vue"; +import { computed, unref, watchEffect } from "vue"; +import { useToast } from "vue-toastification"; + +const toast = useToast(); + +export const MilestoneType = Symbol("Milestone"); + +export enum MilestoneDisplay { + All = "all", + //Last = "last", + Configurable = "configurable", + Incomplete = "incomplete", + None = "none" +} + +export interface MilestoneOptions { + visibility?: Computable<Visibility | boolean>; + shouldEarn?: () => boolean; + style?: Computable<StyleValue>; + classes?: Computable<Record<string, boolean>>; + display?: Computable< + | CoercableComponent + | { + requirement: CoercableComponent; + effectDisplay?: CoercableComponent; + optionsDisplay?: CoercableComponent; + } + >; + showPopups?: Computable<boolean>; + onComplete?: VoidFunction; +} + +export interface BaseMilestone { + id: string; + earned: Persistent<boolean>; + complete: VoidFunction; + type: typeof MilestoneType; + [Component]: typeof MilestoneComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Milestone<T extends MilestoneOptions> = Replace< + T & BaseMilestone, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + style: GetComputableType<T["style"]>; + classes: GetComputableType<T["classes"]>; + display: GetComputableType<T["display"]>; + showPopups: GetComputableType<T["showPopups"]>; + } +>; + +export type GenericMilestone = Replace< + Milestone<MilestoneOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + } +>; + +export function createMilestone<T extends MilestoneOptions>( + optionsFunc?: OptionsFunc<T, BaseMilestone, GenericMilestone> +): Milestone<T> { + const earned = persistent<boolean>(false); + return createLazyProxy(() => { + const milestone = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>); + milestone.id = getUniqueID("milestone-"); + milestone.type = MilestoneType; + milestone[Component] = MilestoneComponent; + + milestone.earned = earned; + milestone.complete = function () { + const genericMilestone = milestone as GenericMilestone; + earned.value = true; + genericMilestone.onComplete?.(); + if (genericMilestone.display != null && unref(genericMilestone.showPopups) === true) { + const display = unref(genericMilestone.display); + const Display = coerceComponent( + isCoercableComponent(display) ? display : display.requirement + ); + toast( + <> + <h3>Milestone earned!</h3> + <div> + {/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */} + {/* @ts-ignore */} + <Display /> + </div> + </> + ); + } + }; + + processComputable(milestone as T, "visibility"); + setDefault(milestone, "visibility", Visibility.Visible); + const visibility = milestone.visibility as ProcessedComputable<Visibility | boolean>; + milestone.visibility = computed(() => { + const display = unref((milestone as GenericMilestone).display); + switch (settings.msDisplay) { + default: + case MilestoneDisplay.All: + return unref(visibility); + case MilestoneDisplay.Configurable: + if ( + unref(milestone.earned) && + !( + display != null && + typeof display == "object" && + "optionsDisplay" in (display as Record<string, unknown>) + ) + ) { + return Visibility.None; + } + return unref(visibility); + case MilestoneDisplay.Incomplete: + if (unref(milestone.earned)) { + return Visibility.None; + } + return unref(visibility); + case MilestoneDisplay.None: + return Visibility.None; + } + }); + + processComputable(milestone as T, "style"); + processComputable(milestone as T, "classes"); + processComputable(milestone as T, "display"); + processComputable(milestone as T, "showPopups"); + + milestone[GatherProps] = function (this: GenericMilestone) { + const { visibility, display, style, classes, earned, id } = this; + return { visibility, display, style: unref(style), classes, earned, id }; + }; + + if (milestone.shouldEarn) { + const genericMilestone = milestone as GenericMilestone; + watchEffect(() => { + if (settings.active !== player.id) return; + if ( + !genericMilestone.earned.value && + isVisible(genericMilestone.visibility) && + genericMilestone.shouldEarn?.() + ) { + genericMilestone.earned.value = true; + genericMilestone.onComplete?.(); + if ( + genericMilestone.display != null && + unref(genericMilestone.showPopups) === true + ) { + const display = unref(genericMilestone.display); + const Display = coerceComponent( + isCoercableComponent(display) ? display : display.requirement + ); + toast( + <> + <h3>Milestone earned!</h3> + <div> + {/* eslint-disable-next-line @typescript-eslint/ban-ts-comment */} + {/* @ts-ignore */} + <Display /> + </div> + </> + ); + } + } + }); + } + + return milestone as unknown as Milestone<T>; + }); +} + +declare module "game/settings" { + interface Settings { + msDisplay: MilestoneDisplay; + } +} + +globalBus.on("loadSettings", settings => { + setDefault(settings, "msDisplay", MilestoneDisplay.All); +}); + +const msDisplayOptions = Object.values(MilestoneDisplay).map(option => ({ + label: camelToTitle(option), + value: option +})); + +registerSettingField( + jsx(() => ( + <Select + title={jsx(() => ( + <span class="option-title"> + Show milestones + <desc>Select which milestones to display based on criterias.</desc> + </span> + ))} + options={msDisplayOptions} + onUpdate:modelValue={value => (settings.msDisplay = value as MilestoneDisplay)} + modelValue={settings.msDisplay} + /> + )) +); diff --git a/src/features/particles/Particles.vue b/src/features/particles/Particles.vue new file mode 100644 index 0000000..1f7de78 --- /dev/null +++ b/src/features/particles/Particles.vue @@ -0,0 +1,94 @@ +<template> + <div + ref="resizeListener" + class="resize-listener" + :style="unref(style)" + :class="unref(classes)" + /> +</template> + +<script lang="tsx"> +import { Application } from "@pixi/app"; +import type { StyleValue } from "features/feature"; +import { globalBus } from "game/events"; +import "lib/pixi"; +import { processedPropType } from "util/vue"; +import type { PropType } from "vue"; +import { defineComponent, nextTick, onBeforeUnmount, onMounted, ref, shallowRef, unref } from "vue"; + +// TODO get typing support on the Particles component +export default defineComponent({ + props: { + style: processedPropType<StyleValue>(String, Object, Array), + classes: processedPropType<Record<string, boolean>>(Object), + onInit: { + type: Function as PropType<(app: Application) => void>, + required: true + }, + id: { + type: String, + required: true + }, + onContainerResized: Function as PropType<(rect: DOMRect) => void>, + onHotReload: Function as PropType<VoidFunction> + }, + setup(props) { + const app = shallowRef<null | Application>(null); + + const resizeObserver = new ResizeObserver(updateBounds); + const resizeListener = shallowRef<HTMLElement | null>(null); + + onMounted(() => { + // ResizeListener exists because ResizeObserver's don't work when told to observe an SVG element + const resListener = resizeListener.value; + if (resListener != null) { + resizeObserver.observe(resListener); + app.value = new Application({ + resizeTo: resListener, + backgroundAlpha: 0 + }); + resizeListener.value?.appendChild(app.value.view); + props.onInit?.(app.value as Application); + } + updateBounds(); + if (props.onHotReload) { + nextTick(props.onHotReload); + } + }); + onBeforeUnmount(() => { + app.value?.destroy(); + }); + + let isDirty = true; + function updateBounds() { + if (isDirty) { + isDirty = false; + nextTick(() => { + if (resizeListener.value != null) { + props.onContainerResized?.(resizeListener.value.getBoundingClientRect()); + } + isDirty = true; + }); + } + } + globalBus.on("fontsLoaded", updateBounds); + + return { + unref, + resizeListener + }; + } +}); +</script> + +<style scoped> +.not-fullscreen, +.resize-listener { + position: absolute; + top: 0px; + left: 0; + right: -4px; + bottom: 5px; + pointer-events: none; +} +</style> diff --git a/src/features/particles/particles.tsx b/src/features/particles/particles.tsx new file mode 100644 index 0000000..0b5b23f --- /dev/null +++ b/src/features/particles/particles.tsx @@ -0,0 +1,94 @@ +import { Application } from "@pixi/app"; +import type { EmitterConfigV3 } from "@pixi/particle-emitter"; +import { Emitter, upgradeConfig } from "@pixi/particle-emitter"; +import type { GenericComponent, OptionsFunc, Replace, StyleValue } from "features/feature"; +import { Component, GatherProps, getUniqueID } from "features/feature"; +import ParticlesComponent from "features/particles/Particles.vue"; +import type { Computable, GetComputableType } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { Ref, shallowRef, unref } from "vue"; + +export const ParticlesType = Symbol("Particles"); + +export interface ParticlesOptions { + classes?: Computable<Record<string, boolean>>; + style?: Computable<StyleValue>; + onContainerResized?: (boundingRect: DOMRect) => void; + onHotReload?: VoidFunction; +} + +export interface BaseParticles { + id: string; + app: Ref<null | Application>; + addEmitter: (config: EmitterConfigV3) => Promise<Emitter>; + type: typeof ParticlesType; + [Component]: GenericComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Particles<T extends ParticlesOptions> = Replace< + T & BaseParticles, + { + classes: GetComputableType<T["classes"]>; + style: GetComputableType<T["style"]>; + } +>; + +export type GenericParticles = Particles<ParticlesOptions>; + +export function createParticles<T extends ParticlesOptions>( + optionsFunc?: OptionsFunc<T, BaseParticles, GenericParticles> +): Particles<T> { + return createLazyProxy(() => { + const particles = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>); + particles.id = getUniqueID("particles-"); + particles.type = ParticlesType; + particles[Component] = ParticlesComponent; + + particles.app = shallowRef(null); + particles.addEmitter = (config: EmitterConfigV3): Promise<Emitter> => { + const genericParticles = particles as GenericParticles; + if (genericParticles.app.value) { + return Promise.resolve(new Emitter(genericParticles.app.value.stage, config)); + } + return new Promise<Emitter>(resolve => { + emittersToAdd.push({ resolve, config }); + }); + }; + + let emittersToAdd: { + resolve: (value: Emitter | PromiseLike<Emitter>) => void; + config: EmitterConfigV3; + }[] = []; + + function onInit(app: Application) { + const genericParticles = particles as GenericParticles; + genericParticles.app.value = app; + emittersToAdd.forEach(({ resolve, config }) => resolve(new Emitter(app.stage, config))); + emittersToAdd = []; + } + + particles.onContainerResized = particles.onContainerResized?.bind(particles); + + particles[GatherProps] = function (this: GenericParticles) { + const { id, style, classes, onContainerResized, onHotReload } = this; + return { + id, + style: unref(style), + classes, + onContainerResized, + onHotReload, + onInit + }; + }; + + return particles as unknown as Particles<T>; + }); +} + +declare global { + interface Window { + upgradeConfig: typeof upgradeConfig; + } +} +window.upgradeConfig = upgradeConfig; diff --git a/src/features/repeatable.tsx b/src/features/repeatable.tsx new file mode 100644 index 0000000..96bea11 --- /dev/null +++ b/src/features/repeatable.tsx @@ -0,0 +1,275 @@ +import { isArray } from "@vue/shared"; +import ClickableComponent from "features/clickables/Clickable.vue"; +import type { CoercableComponent, OptionsFunc, Replace, StyleValue } from "features/feature"; +import { Component, GatherProps, getUniqueID, jsx, setDefault, Visibility } from "features/feature"; +import { DefaultValue, Persistent, persistent } from "game/persistence"; +import { + createVisibilityRequirement, + displayRequirements, + maxRequirementsMet, + payRequirements, + Requirements, + requirementsMet +} from "game/requirements"; +import type { DecimalSource } from "util/bignum"; +import Decimal, { formatWhole } from "util/bignum"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { coerceComponent, isCoercableComponent } from "util/vue"; +import type { Ref } from "vue"; +import { computed, unref } from "vue"; + +/** A symbol used to identify {@link Repeatable} features. */ +export const RepeatableType = Symbol("Repeatable"); + +/** A type that can be used to customize the {@link Repeatable} display. */ +export type RepeatableDisplay = + | CoercableComponent + | { + /** A header to appear at the top of the display. */ + title?: CoercableComponent; + /** The main text that appears in the display. */ + description?: CoercableComponent; + /** A description of the current effect of this repeatable, bsed off its amount. */ + effectDisplay?: CoercableComponent; + /** Whether or not to show the current amount of this repeatable at the bottom of the display. */ + showAmount?: boolean; + }; + +/** An object that configures a {@link Repeatable}. */ +export interface RepeatableOptions { + /** Whether this repeatable should be visible. */ + visibility?: Computable<Visibility | boolean>; + /** The requirement(s) to increase this repeatable. */ + requirements: Requirements; + /** The maximum amount obtainable for this repeatable. */ + limit?: Computable<DecimalSource>; + /** The initial amount this repeatable has on a new save / after reset. */ + initialAmount?: DecimalSource; + /** Dictionary of CSS classes to apply to this feature. */ + classes?: Computable<Record<string, boolean>>; + /** CSS to apply to this feature. */ + style?: Computable<StyleValue>; + /** Shows a marker on the corner of the feature. */ + mark?: Computable<boolean | string>; + /** Toggles a smaller design for the feature. */ + small?: Computable<boolean>; + /** Whether or not clicking this repeatable should attempt to maximize amount based on the requirements met. Requires {@link requirements} to be a requirement or array of requirements with {@link Requirement.canMaximize} true. */ + maximize?: Computable<boolean>; + /** The display to use for this repeatable. */ + display?: Computable<RepeatableDisplay>; +} + +/** + * The properties that are added onto a processed {@link RepeatableOptions} to create a {@link Repeatable}. + */ +export interface BaseRepeatable { + /** An auto-generated ID for identifying features that appear in the DOM. Will not persistent between refreshes or updates. */ + id: string; + /** The current amount this repeatable has. */ + amount: Persistent<DecimalSource>; + /** Whether or not this repeatable's amount is at it's limit. */ + maxed: Ref<boolean>; + /** Whether or not this repeatable can be clicked. */ + canClick: ProcessedComputable<boolean>; + /** A function that gets called when this repeatable is clicked. */ + onClick: (event?: MouseEvent | TouchEvent) => void; + /** A symbol that helps identify features of the same type. */ + type: typeof RepeatableType; + /** The Vue component used to render this feature. */ + [Component]: typeof ClickableComponent; + /** A function to gather the props the vue component requires for this feature. */ + [GatherProps]: () => Record<string, unknown>; +} + +/** An object that represents a feature with multiple "levels" with scaling requirements. */ +export type Repeatable<T extends RepeatableOptions> = Replace< + T & BaseRepeatable, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + requirements: GetComputableType<T["requirements"]>; + limit: GetComputableTypeWithDefault<T["limit"], Decimal>; + classes: GetComputableType<T["classes"]>; + style: GetComputableType<T["style"]>; + mark: GetComputableType<T["mark"]>; + small: GetComputableType<T["small"]>; + maximize: GetComputableType<T["maximize"]>; + display: Ref<CoercableComponent>; + } +>; + +/** A type that matches any valid {@link Repeatable} object. */ +export type GenericRepeatable = Replace< + Repeatable<RepeatableOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + limit: ProcessedComputable<DecimalSource>; + } +>; + +/** + * Lazily creates a repeatable with the given options. + * @param optionsFunc Repeatable options. + */ +export function createRepeatable<T extends RepeatableOptions>( + optionsFunc: OptionsFunc<T, BaseRepeatable, GenericRepeatable> +): Repeatable<T> { + const amount = persistent<DecimalSource>(0); + return createLazyProxy(() => { + const repeatable = optionsFunc(); + + repeatable.id = getUniqueID("repeatable-"); + repeatable.type = RepeatableType; + repeatable[Component] = ClickableComponent; + + repeatable.amount = amount; + repeatable.amount[DefaultValue] = repeatable.initialAmount ?? 0; + + const limitRequirement = { + requirementMet: computed(() => + Decimal.sub( + unref((repeatable as GenericRepeatable).limit), + (repeatable as GenericRepeatable).amount.value + ) + ), + requiresPay: false, + visibility: Visibility.None + } as const; + const visibilityRequirement = createVisibilityRequirement(repeatable as GenericRepeatable); + if (isArray(repeatable.requirements)) { + repeatable.requirements.unshift(visibilityRequirement); + repeatable.requirements.push(limitRequirement); + } else { + repeatable.requirements = [ + visibilityRequirement, + repeatable.requirements, + limitRequirement + ]; + } + + repeatable.maxed = computed(() => + Decimal.gte( + (repeatable as GenericRepeatable).amount.value, + unref((repeatable as GenericRepeatable).limit) + ) + ); + processComputable(repeatable as T, "classes"); + const classes = repeatable.classes as + | ProcessedComputable<Record<string, boolean>> + | undefined; + repeatable.classes = computed(() => { + const currClasses = unref(classes) || {}; + if ((repeatable as GenericRepeatable).maxed.value) { + currClasses.bought = true; + } + return currClasses; + }); + repeatable.canClick = computed(() => requirementsMet(repeatable.requirements)); + const onClick = repeatable.onClick; + repeatable.onClick = function (this: GenericRepeatable, event?: MouseEvent | TouchEvent) { + const genericRepeatable = repeatable as GenericRepeatable; + if (!unref(genericRepeatable.canClick)) { + return; + } + payRequirements( + repeatable.requirements, + unref(genericRepeatable.maximize) + ? maxRequirementsMet(genericRepeatable.requirements) + : 1 + ); + genericRepeatable.amount.value = Decimal.add(genericRepeatable.amount.value, 1); + onClick?.(event); + }; + processComputable(repeatable as T, "display"); + const display = repeatable.display; + repeatable.display = jsx(() => { + // TODO once processComputable types correctly, remove this "as X" + const currDisplay = unref(display) as RepeatableDisplay; + if (isCoercableComponent(currDisplay)) { + const CurrDisplay = coerceComponent(currDisplay); + return <CurrDisplay />; + } + if (currDisplay != null) { + const genericRepeatable = repeatable as GenericRepeatable; + const Title = coerceComponent(currDisplay.title ?? "", "h3"); + const Description = coerceComponent(currDisplay.description ?? ""); + const EffectDisplay = coerceComponent(currDisplay.effectDisplay ?? ""); + + return ( + <span> + {currDisplay.title == null ? null : ( + <div> + <Title /> + </div> + )} + {currDisplay.description == null ? null : <Description />} + {currDisplay.showAmount === false ? null : ( + <div> + <br /> + {unref(genericRepeatable.limit) === Decimal.dInf ? ( + <>Amount: {formatWhole(genericRepeatable.amount.value)}</> + ) : ( + <> + Amount: {formatWhole(genericRepeatable.amount.value)} /{" "} + {formatWhole(unref(genericRepeatable.limit))} + </> + )} + </div> + )} + {currDisplay.effectDisplay == null ? null : ( + <div> + <br /> + Currently: <EffectDisplay /> + </div> + )} + {genericRepeatable.maxed.value ? null : ( + <div> + <br /> + {displayRequirements( + genericRepeatable.requirements, + unref(genericRepeatable.maximize) + ? maxRequirementsMet(genericRepeatable.requirements) + : 1 + )} + </div> + )} + </span> + ); + } + return ""; + }); + + processComputable(repeatable as T, "visibility"); + setDefault(repeatable, "visibility", Visibility.Visible); + processComputable(repeatable as T, "limit"); + setDefault(repeatable, "limit", Decimal.dInf); + processComputable(repeatable as T, "style"); + processComputable(repeatable as T, "mark"); + processComputable(repeatable as T, "small"); + processComputable(repeatable as T, "maximize"); + + repeatable[GatherProps] = function (this: GenericRepeatable) { + const { display, visibility, style, classes, onClick, canClick, small, mark, id } = + this; + return { + display, + visibility, + style: unref(style), + classes, + onClick, + canClick, + small, + mark, + id + }; + }; + + return repeatable as unknown as Repeatable<T>; + }); +} diff --git a/src/features/reset.ts b/src/features/reset.ts new file mode 100644 index 0000000..487238c --- /dev/null +++ b/src/features/reset.ts @@ -0,0 +1,96 @@ +import type { OptionsFunc, Replace } from "features/feature"; +import { getUniqueID } from "features/feature"; +import { globalBus } from "game/events"; +import type { BaseLayer } from "game/layers"; +import type { NonPersistent, Persistent } from "game/persistence"; +import { DefaultValue, persistent } from "game/persistence"; +import type { Unsubscribe } from "nanoevents"; +import Decimal from "util/bignum"; +import type { Computable, GetComputableType } from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { isRef, unref } from "vue"; + +export const ResetType = Symbol("Reset"); + +export interface ResetOptions { + thingsToReset: Computable<Record<string, unknown>[]>; + onReset?: VoidFunction; +} + +export interface BaseReset { + id: string; + reset: VoidFunction; + type: typeof ResetType; +} + +export type Reset<T extends ResetOptions> = Replace< + T & BaseReset, + { + thingsToReset: GetComputableType<T["thingsToReset"]>; + } +>; + +export type GenericReset = Reset<ResetOptions>; + +export function createReset<T extends ResetOptions>( + optionsFunc: OptionsFunc<T, BaseReset, GenericReset> +): Reset<T> { + return createLazyProxy(() => { + const reset = optionsFunc(); + reset.id = getUniqueID("reset-"); + reset.type = ResetType; + + reset.reset = function () { + const handleObject = (obj: unknown) => { + if (obj != null && typeof obj === "object") { + if (DefaultValue in obj) { + const persistent = obj as NonPersistent; + persistent.value = persistent[DefaultValue]; + } else if (!(obj instanceof Decimal) && !isRef(obj)) { + Object.values(obj).forEach(obj => + handleObject(obj as Record<string, unknown>) + ); + } + } + }; + unref((reset as GenericReset).thingsToReset).forEach(handleObject); + globalBus.emit("reset", reset as GenericReset); + reset.onReset?.(); + }; + + processComputable(reset as T, "thingsToReset"); + + return reset as unknown as Reset<T>; + }); +} + +const listeners: Record<string, Unsubscribe | undefined> = {}; +export function trackResetTime(layer: BaseLayer, reset: GenericReset): Persistent<Decimal> { + const resetTime = persistent<Decimal>(new Decimal(0)); + globalBus.on("addLayer", layerBeingAdded => { + if (layer.id === layerBeingAdded.id) { + listeners[layer.id]?.(); + listeners[layer.id] = layer.on("preUpdate", diff => { + resetTime.value = Decimal.add(resetTime.value, diff); + }); + } + }); + globalBus.on("reset", currentReset => { + if (currentReset === reset) { + resetTime.value = new Decimal(0); + } + }); + return resetTime; +} +globalBus.on("removeLayer", layer => { + // unsubscribe from preUpdate + listeners[layer.id]?.(); + listeners[layer.id] = undefined; +}); + +declare module "game/events" { + interface GlobalEvents { + reset: (reset: GenericReset) => void; + } +} diff --git a/src/features/resources/MainDisplay.vue b/src/features/resources/MainDisplay.vue new file mode 100644 index 0000000..660c298 --- /dev/null +++ b/src/features/resources/MainDisplay.vue @@ -0,0 +1,58 @@ +<template> + <Sticky> + <div + class="main-display-container" + :class="classes ?? {}" + :style="[{ height: `${(effectRef?.$el.clientHeight ?? 0) + 50}px` }, style ?? {}]" + > + <div class="main-display"> + <span v-if="showPrefix">You have </span> + <ResourceVue :resource="resource" :color="color || 'white'" /> + {{ resource.displayName + }}<!-- remove whitespace --> + <span v-if="effectComponent" + >, <component :is="effectComponent" ref="effectRef" + /></span> + </div> + </div> + </Sticky> +</template> + +<script setup lang="ts"> +import Sticky from "components/layout/Sticky.vue"; +import type { CoercableComponent } from "features/feature"; +import type { Resource } from "features/resources/resource"; +import ResourceVue from "features/resources/Resource.vue"; +import Decimal from "util/bignum"; +import { computeOptionalComponent } from "util/vue"; +import { ComponentPublicInstance, ref, Ref, StyleValue } from "vue"; +import { computed, toRefs } from "vue"; + +const _props = defineProps<{ + resource: Resource; + color?: string; + classes?: Record<string, boolean>; + style?: StyleValue; + effectDisplay?: CoercableComponent; +}>(); +const props = toRefs(_props); + +const effectRef = ref<ComponentPublicInstance | null>(null); + +const effectComponent = computeOptionalComponent( + props.effectDisplay as Ref<CoercableComponent | undefined> +); + +const showPrefix = computed(() => { + return Decimal.lt(props.resource.value, "1e1000"); +}); +</script> + +<style> +.main-display-container { + vertical-align: middle; + margin-bottom: 20px; + display: flex; + transition-duration: 0s; +} +</style> diff --git a/src/features/resources/Resource.vue b/src/features/resources/Resource.vue new file mode 100644 index 0000000..928f2da --- /dev/null +++ b/src/features/resources/Resource.vue @@ -0,0 +1,18 @@ +<template> + <h2 :style="{ color, 'text-shadow': '0px 0px 10px ' + color }"> + {{ amount }} + </h2> +</template> + +<script setup lang="ts"> +import type { Resource } from "features/resources/resource"; +import { displayResource } from "features/resources/resource"; +import { computed } from "vue"; + +const props = defineProps<{ + resource: Resource; + color: string; +}>(); + +const amount = computed(() => displayResource(props.resource)); +</script> diff --git a/src/features/resources/resource.ts b/src/features/resources/resource.ts new file mode 100644 index 0000000..be42e7e --- /dev/null +++ b/src/features/resources/resource.ts @@ -0,0 +1,153 @@ +import { globalBus } from "game/events"; +import { NonPersistent, Persistent, State } from "game/persistence"; +import { persistent } from "game/persistence"; +import player from "game/player"; +import settings from "game/settings"; +import type { DecimalSource } from "util/bignum"; +import Decimal, { format, formatWhole } from "util/bignum"; +import type { ProcessedComputable } from "util/computed"; +import { loadingSave } from "util/save"; +import type { ComputedRef, Ref } from "vue"; +import { computed, isRef, ref, unref, watch } from "vue"; + +export interface Resource<T = DecimalSource> extends Ref<T> { + displayName: string; + precision: number; + small?: boolean; +} + +export function createResource<T extends State>( + defaultValue: T, + displayName?: string, + precision?: number, + small?: boolean | undefined +): Resource<T> & Persistent<T> & { [NonPersistent]: Resource<T> }; +export function createResource<T extends State>( + defaultValue: Ref<T>, + displayName?: string, + precision?: number, + small?: boolean | undefined +): Resource<T>; +export function createResource<T extends State>( + defaultValue: T | Ref<T>, + displayName = "points", + precision = 0, + small: boolean | undefined = undefined +) { + const resource: Partial<Resource<T>> = isRef(defaultValue) + ? defaultValue + : persistent(defaultValue); + resource.displayName = displayName; + resource.precision = precision; + resource.small = small; + if (!isRef(defaultValue)) { + const nonPersistentResource = (resource as Persistent<T>)[ + NonPersistent + ] as unknown as Resource<T>; + nonPersistentResource.displayName = displayName; + nonPersistentResource.precision = precision; + nonPersistentResource.small = small; + } + return resource as Resource<T>; +} + +export function trackBest(resource: Resource): Ref<DecimalSource> { + const best = persistent(resource.value); + watch(resource, amount => { + if (loadingSave.value) { + return; + } + if (Decimal.gt(amount, best.value)) { + best.value = amount; + } + }); + return best; +} + +export function trackTotal(resource: Resource): Ref<DecimalSource> { + const total = persistent(resource.value); + watch(resource, (amount, prevAmount) => { + if (loadingSave.value) { + return; + } + if (Decimal.gt(amount, prevAmount)) { + total.value = Decimal.add(total.value, Decimal.sub(amount, prevAmount)); + } + }); + return total; +} + +const tetra8 = new Decimal("10^^8"); +const e100 = new Decimal("1e100"); +export function trackOOMPS( + resource: Resource, + pointGain?: ComputedRef<DecimalSource> +): Ref<string> { + const oomps = ref<DecimalSource>(0); + const oompsMag = ref(0); + const lastPoints = ref<DecimalSource>(0); + + globalBus.on("update", diff => { + oompsMag.value = 0; + if (Decimal.lte(resource.value, e100)) { + lastPoints.value = resource.value; + return; + } + + let curr = resource.value; + let prev = lastPoints.value; + lastPoints.value = curr; + if (Decimal.gt(curr, prev)) { + if (Decimal.gte(curr, tetra8)) { + curr = Decimal.slog(curr, 1e10); + prev = Decimal.slog(prev, 1e10); + oomps.value = curr.sub(prev).div(diff); + oompsMag.value = -1; + } else { + while ( + Decimal.div(curr, prev).log(10).div(diff).gte("100") && + oompsMag.value <= 5 && + Decimal.gt(prev, 0) + ) { + curr = Decimal.log10(curr); + prev = Decimal.log10(prev); + oomps.value = curr.sub(prev).div(diff); + oompsMag.value++; + } + } + } + }); + + const oompsString = computed(() => { + if (oompsMag.value === 0) { + return pointGain + ? format(pointGain.value, resource.precision, resource.small) + + " " + + resource.displayName + + "/s" + : ""; + } + return ( + format(oomps.value) + + " OOM" + + (oompsMag.value < 0 ? "^OOM" : "^" + oompsMag.value) + + "s/sec" + ); + }); + return oompsString; +} + +export function displayResource(resource: Resource, overrideAmount?: DecimalSource): string { + const amount = overrideAmount ?? resource.value; + if (Decimal.eq(resource.precision, 0)) { + return formatWhole(resource.small ? amount : Decimal.floor(amount)); + } + return format(amount, resource.precision, resource.small); +} + +export function unwrapResource(resource: ProcessedComputable<Resource>): Resource { + if ("displayName" in resource) { + return resource; + } + return unref(resource); +} diff --git a/src/features/tabs/Tab.vue b/src/features/tabs/Tab.vue new file mode 100644 index 0000000..103cdf6 --- /dev/null +++ b/src/features/tabs/Tab.vue @@ -0,0 +1,13 @@ +<template> + <component :is="component" /> +</template> + +<script setup lang="ts"> +import type { CoercableComponent } from "features/feature"; +import { computeComponent } from "util/vue"; +import { toRefs } from "vue"; + +const _props = defineProps<{ display: CoercableComponent }>(); +const { display } = toRefs(_props); +const component = computeComponent(display); +</script> diff --git a/src/features/tabs/TabButton.vue b/src/features/tabs/TabButton.vue new file mode 100644 index 0000000..fcd8942 --- /dev/null +++ b/src/features/tabs/TabButton.vue @@ -0,0 +1,116 @@ +<template> + <button + v-if="isVisible(visibility)" + @click="selectTab" + class="tabButton" + :style="[ + { + visibility: isHidden(visibility) ? 'hidden' : undefined + }, + glowColorStyle, + unref(style) ?? {} + ]" + :class="{ + active, + ...unref(classes) + }" + > + <component :is="component" /> + </button> +</template> + +<script lang="ts"> +import type { CoercableComponent, StyleValue } from "features/feature"; +import { isHidden, isVisible, Visibility } from "features/feature"; +import { getNotifyStyle } from "game/notifications"; +import { computeComponent, processedPropType, unwrapRef } from "util/vue"; +import { computed, defineComponent, toRefs, unref } from "vue"; + +export default defineComponent({ + props: { + visibility: { + type: processedPropType<Visibility | boolean>(Number, Boolean), + required: true + }, + display: { + type: processedPropType<CoercableComponent>(Object, String, Function), + required: true + }, + style: processedPropType<StyleValue>(String, Object, Array), + classes: processedPropType<Record<string, boolean>>(Object), + glowColor: processedPropType<string>(String), + active: Boolean, + floating: Boolean + }, + emits: ["selectTab"], + setup(props, { emit }) { + const { display, glowColor, floating } = toRefs(props); + + const component = computeComponent(display); + + const glowColorStyle = computed(() => { + const color = unwrapRef(glowColor); + if (color != null) { + return {}; + } + if (unref(floating)) { + return getNotifyStyle(color); + } + return { boxShadow: `0px 9px 5px -6px ${color}` }; + }); + + function selectTab() { + emit("selectTab"); + } + + return { + selectTab, + component, + glowColorStyle, + unref, + Visibility, + isVisible, + isHidden + }; + } +}); +</script> + +<style scoped> +.tabButton { + background-color: transparent; + color: var(--foreground); + font-size: 20px; + cursor: pointer; + padding: 5px 20px; + margin: 5px; + border-radius: 5px; + border: 2px solid; + flex-shrink: 0; + border-color: var(--layer-color); +} + +.tabButton:hover { + transform: scale(1.1, 1.1); + text-shadow: 0 0 7px var(--foreground); +} + +:not(.floating) > .tabButton { + height: 50px; + margin: 0; + border-left: none; + border-right: none; + border-top: none; + border-bottom-width: 4px; + border-radius: 0; + transform: unset; +} + +:not(.floating) .tabButton:not(.active) { + border-bottom-color: transparent; +} + +.tabButton > * { + pointer-events: none; +} +</style> diff --git a/src/features/tabs/TabFamily.vue b/src/features/tabs/TabFamily.vue new file mode 100644 index 0000000..436f81a --- /dev/null +++ b/src/features/tabs/TabFamily.vue @@ -0,0 +1,249 @@ +<template> + <div + v-if="isVisible(visibility)" + class="tab-family-container" + :class="{ ...unref(classes), ...tabClasses }" + :style="[ + { + visibility: isHidden(visibility) ? 'hidden' : undefined + }, + unref(style) ?? [], + tabStyle ?? [] + ]" + > + <Sticky + class="tab-buttons-container" + :class="unref(buttonContainerClasses)" + :style="unref(buttonContainerStyle)" + > + <div class="tab-buttons" :class="{ floating }"> + <TabButton + v-for="(button, id) in unref(tabs)" + @selectTab="selected.value = id" + :floating="floating" + :key="id" + :active="unref(button.tab) === unref(activeTab)" + v-bind="gatherButtonProps(button)" + /> + </div> + </Sticky> + <template v-if="unref(activeTab)"> + <component :is="unref(component)" /> + </template> + </div> +</template> + +<script lang="ts"> +import Sticky from "components/layout/Sticky.vue"; +import themes from "data/themes"; +import type { CoercableComponent, StyleValue } from "features/feature"; +import { isHidden, isVisible, Visibility } from "features/feature"; +import type { GenericTab } from "features/tabs/tab"; +import TabButton from "features/tabs/TabButton.vue"; +import type { GenericTabButton } from "features/tabs/tabFamily"; +import settings from "game/settings"; +import { coerceComponent, isCoercableComponent, processedPropType, unwrapRef } from "util/vue"; +import type { Component, PropType, Ref } from "vue"; +import { computed, defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue"; + +export default defineComponent({ + props: { + visibility: { + type: processedPropType<Visibility | boolean>(Number, Boolean), + required: true + }, + activeTab: { + type: processedPropType<GenericTab | CoercableComponent | null>(Object), + required: true + }, + selected: { + type: Object as PropType<Ref<string>>, + required: true + }, + tabs: { + type: processedPropType<Record<string, GenericTabButton>>(Object), + required: true + }, + style: processedPropType<StyleValue>(String, Object, Array), + classes: processedPropType<Record<string, boolean>>(Object), + buttonContainerStyle: processedPropType<StyleValue>(String, Object, Array), + buttonContainerClasses: processedPropType<Record<string, boolean>>(Object) + }, + components: { + Sticky, + TabButton + }, + setup(props) { + const { activeTab } = toRefs(props); + + const floating = computed(() => { + return themes[settings.theme].floatingTabs; + }); + + const component = shallowRef<Component | string>(""); + + watchEffect(() => { + const currActiveTab = unwrapRef(activeTab); + if (currActiveTab == null) { + component.value = ""; + return; + } + if (isCoercableComponent(currActiveTab)) { + component.value = coerceComponent(currActiveTab); + return; + } + component.value = coerceComponent(unref(currActiveTab.display)); + }); + + const tabClasses = computed(() => { + const currActiveTab = unwrapRef(activeTab); + const tabClasses = + isCoercableComponent(currActiveTab) || !currActiveTab + ? undefined + : unref(currActiveTab.classes); + return tabClasses; + }); + + const tabStyle = computed(() => { + const currActiveTab = unwrapRef(activeTab); + return isCoercableComponent(currActiveTab) || !currActiveTab + ? undefined + : unref(currActiveTab.style); + }); + + function gatherButtonProps(button: GenericTabButton) { + const { display, style, classes, glowColor, visibility } = button; + return { display, style: unref(style), classes, glowColor, visibility }; + } + + return { + floating, + tabClasses, + tabStyle, + Visibility, + component, + gatherButtonProps, + unref, + isVisible, + isHidden + }; + } +}); +</script> + +<style scoped> +.tab-family-container { + margin: calc(50px + var(--feature-margin)) 20px var(--feature-margin) 20px; + position: relative; + border: solid 4px; + border-color: var(--outline); +} + +.layer-tab > .tab-family-container:first-child { + margin: -4px -11px var(--feature-margin) -11px; +} + +.layer-tab > .tab-family-container:first-child:nth-last-child(3) { + border-bottom-style: none; + border-left-style: none; + border-right-style: none; + height: calc(100% + 50px); +} + +.modal-body > .tab-family-container:first-child { + margin: calc(10px + var(--feature-margin)) 10px 0 10px; + border: none; +} + +.tab-family-container > :nth-child(2) { + margin-top: 20px; +} + +.modal-body > .tab-family-container > :nth-child(2) { + /* TODO Why does it need this instead of 20px? */ + margin-top: 50px; +} + +.tab-family-container[data-v-f18896fc] > :last-child { + margin-bottom: 20px; +} + +.tab-buttons-container { + z-index: 4; +} + +.tab-buttons-container:not(.floating) { + border-bottom: solid 4px; + border-color: inherit; +} + +:not(.layer-tab):not(.modal-body) > .tab-family-container > .tab-buttons-container:not(.floating) { + width: calc(100% + 6px); + margin-left: -3px; +} + +.tab-buttons-container:not(.floating) .tab-buttons { + text-align: left; + margin-bottom: -4px; +} + +.tab-buttons-container.floating .tab-buttons { + justify-content: center; + margin-top: -25px; +} + +.tab-buttons { + margin-bottom: 24px; + display: flex; + flex-flow: wrap; + z-index: 4; +} + +.layer-tab + > .tab-family-container:first-child:nth-last-child(3) + > .tab-buttons-container + > .tab-buttons { + padding-right: 60px; +} + +.tab-buttons:not(.floating) { + text-align: left; + border-bottom: inherit; + border-width: 4px; + box-sizing: border-box; + height: 50px; +} + +.modal-body .tab-buttons { + width: 100%; + margin-left: 0; + margin-right: 0; + padding-left: 0; +} + +.showGoBack + > .tab-family-container:first-child + > .tab-buttons-container:not(.floating) + .tab-buttons { + padding-left: 70px; +} + +:not(.showGoBack) + > .tab-family-container + > .tab-buttons-container:not(.floating):first-child + .tab-buttons { + padding-left: 0; +} + +.minimizable > .tab-buttons-container:not(.floating):first-child { + padding-right: 50px; +} + +.tab-buttons-container:not(.floating):first-child .tab-buttons { + margin-top: -50px; +} + +.tab-buttons-container + * { + margin-top: 20px; +} +</style> diff --git a/src/features/tabs/tab.ts b/src/features/tabs/tab.ts new file mode 100644 index 0000000..3f205fc --- /dev/null +++ b/src/features/tabs/tab.ts @@ -0,0 +1,49 @@ +import type { CoercableComponent, OptionsFunc, Replace, StyleValue } from "features/feature"; +import { Component, GatherProps, getUniqueID } from "features/feature"; +import TabComponent from "features/tabs/Tab.vue"; +import type { Computable, GetComputableType } from "util/computed"; +import { createLazyProxy } from "util/proxies"; + +export const TabType = Symbol("Tab"); + +export interface TabOptions { + classes?: Computable<Record<string, boolean>>; + style?: Computable<StyleValue>; + display: Computable<CoercableComponent>; +} + +export interface BaseTab { + id: string; + type: typeof TabType; + [Component]: typeof TabComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Tab<T extends TabOptions> = Replace< + T & BaseTab, + { + classes: GetComputableType<T["classes"]>; + style: GetComputableType<T["style"]>; + display: GetComputableType<T["display"]>; + } +>; + +export type GenericTab = Tab<TabOptions>; + +export function createTab<T extends TabOptions>( + optionsFunc: OptionsFunc<T, BaseTab, GenericTab> +): Tab<T> { + return createLazyProxy(() => { + const tab = optionsFunc(); + tab.id = getUniqueID("tab-"); + tab.type = TabType; + tab[Component] = TabComponent; + + tab[GatherProps] = function (this: GenericTab) { + const { display } = this; + return { display }; + }; + + return tab as unknown as Tab<T>; + }); +} diff --git a/src/features/tabs/tabFamily.ts b/src/features/tabs/tabFamily.ts new file mode 100644 index 0000000..51d298e --- /dev/null +++ b/src/features/tabs/tabFamily.ts @@ -0,0 +1,177 @@ +import type { CoercableComponent, OptionsFunc, Replace, StyleValue } from "features/feature"; +import { + Component, + GatherProps, + getUniqueID, + isVisible, + setDefault, + Visibility +} from "features/feature"; +import TabButtonComponent from "features/tabs/TabButton.vue"; +import TabFamilyComponent from "features/tabs/TabFamily.vue"; +import type { Persistent } from "game/persistence"; +import { persistent } from "game/persistence"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import type { Ref } from "vue"; +import { computed, unref } from "vue"; +import type { GenericTab } from "./tab"; + +export const TabButtonType = Symbol("TabButton"); +export const TabFamilyType = Symbol("TabFamily"); + +export interface TabButtonOptions { + visibility?: Computable<Visibility | boolean>; + tab: Computable<GenericTab | CoercableComponent>; + display: Computable<CoercableComponent>; + classes?: Computable<Record<string, boolean>>; + style?: Computable<StyleValue>; + glowColor?: Computable<string>; +} + +export interface BaseTabButton { + type: typeof TabButtonType; + [Component]: typeof TabButtonComponent; +} + +export type TabButton<T extends TabButtonOptions> = Replace< + T & BaseTabButton, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + tab: GetComputableType<T["tab"]>; + display: GetComputableType<T["display"]>; + classes: GetComputableType<T["classes"]>; + style: GetComputableType<T["style"]>; + glowColor: GetComputableType<T["glowColor"]>; + } +>; + +export type GenericTabButton = Replace< + TabButton<TabButtonOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + } +>; + +export interface TabFamilyOptions { + visibility?: Computable<Visibility | boolean>; + classes?: Computable<Record<string, boolean>>; + style?: Computable<StyleValue>; + buttonContainerClasses?: Computable<Record<string, boolean>>; + buttonContainerStyle?: Computable<StyleValue>; +} + +export interface BaseTabFamily { + id: string; + tabs: Record<string, TabButtonOptions>; + activeTab: Ref<GenericTab | CoercableComponent | null>; + selected: Persistent<string>; + type: typeof TabFamilyType; + [Component]: typeof TabFamilyComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type TabFamily<T extends TabFamilyOptions> = Replace< + T & BaseTabFamily, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + tabs: Record<string, GenericTabButton>; + } +>; + +export type GenericTabFamily = Replace< + TabFamily<TabFamilyOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + } +>; + +export function createTabFamily<T extends TabFamilyOptions>( + tabs: Record<string, () => TabButtonOptions>, + optionsFunc?: OptionsFunc<T, BaseTabFamily, GenericTabFamily> +): TabFamily<T> { + if (Object.keys(tabs).length === 0) { + console.warn("Cannot create tab family with 0 tabs"); + throw "Cannot create tab family with 0 tabs"; + } + + const selected = persistent(Object.keys(tabs)[0]); + return createLazyProxy(() => { + const tabFamily = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>); + + tabFamily.id = getUniqueID("tabFamily-"); + tabFamily.type = TabFamilyType; + tabFamily[Component] = TabFamilyComponent; + + tabFamily.tabs = Object.keys(tabs).reduce<Record<string, GenericTabButton>>( + (parsedTabs, tab) => { + const tabButton: TabButtonOptions & Partial<BaseTabButton> = tabs[tab](); + tabButton.type = TabButtonType; + tabButton[Component] = TabButtonComponent; + + processComputable(tabButton as TabButtonOptions, "visibility"); + setDefault(tabButton, "visibility", Visibility.Visible); + processComputable(tabButton as TabButtonOptions, "tab"); + processComputable(tabButton as TabButtonOptions, "display"); + processComputable(tabButton as TabButtonOptions, "classes"); + processComputable(tabButton as TabButtonOptions, "style"); + processComputable(tabButton as TabButtonOptions, "glowColor"); + parsedTabs[tab] = tabButton as GenericTabButton; + return parsedTabs; + }, + {} + ); + tabFamily.selected = selected; + tabFamily.activeTab = computed(() => { + const tabs = unref(processedTabFamily.tabs); + if (selected.value in tabs && isVisible(tabs[selected.value].visibility)) { + return unref(tabs[selected.value].tab); + } + const firstTab = Object.values(tabs).find(tab => isVisible(tab.visibility)); + if (firstTab) { + return unref(firstTab.tab); + } + return null; + }); + + processComputable(tabFamily as T, "visibility"); + setDefault(tabFamily, "visibility", Visibility.Visible); + processComputable(tabFamily as T, "classes"); + processComputable(tabFamily as T, "style"); + processComputable(tabFamily as T, "buttonContainerClasses"); + processComputable(tabFamily as T, "buttonContainerStyle"); + + tabFamily[GatherProps] = function (this: GenericTabFamily) { + const { + visibility, + activeTab, + selected, + tabs, + style, + classes, + buttonContainerClasses, + buttonContainerStyle + } = this; + return { + visibility, + activeTab, + selected, + tabs, + style: unref(style), + classes, + buttonContainerClasses, + buttonContainerStyle + }; + }; + + // This is necessary because board.types is different from T and TabFamily + const processedTabFamily = tabFamily as unknown as TabFamily<T>; + return processedTabFamily; + }); +} diff --git a/src/features/tooltips/Tooltip.vue b/src/features/tooltips/Tooltip.vue new file mode 100644 index 0000000..1911186 --- /dev/null +++ b/src/features/tooltips/Tooltip.vue @@ -0,0 +1,226 @@ +<template> + <div + class="tooltip-container" + :class="{ shown: isShown }" + @mouseenter="isHovered = true" + @mouseleave="isHovered = false" + @click.capture="togglePinned" + > + <slot /> + <component v-if="elementComp" :is="elementComp" /> + <transition name="fade"> + <div + v-if="isShown" + class="tooltip" + :class="{ + top: unref(direction) === Direction.Up, + left: unref(direction) === Direction.Left, + right: unref(direction) === Direction.Right, + bottom: unref(direction) === Direction.Down, + ...unref(classes) + }" + :style="[ + { + '--xoffset': unref(xoffset) || '0px', + '--yoffset': unref(yoffset) || '0px' + }, + unref(style) ?? {} + ]" + > + <span v-if="showPin" class="material-icons pinned">push_pin</span> + <component v-if="comp" :is="comp" /> + </div> + </transition> + </div> +</template> + +<script lang="tsx"> +import themes from "data/themes"; +import type { CoercableComponent } from "features/feature"; +import { jsx, StyleValue } from "features/feature"; +import type { Persistent } from "game/persistence"; +import settings from "game/settings"; +import { Direction } from "util/common"; +import type { VueFeature } from "util/vue"; +import { + coerceComponent, + computeOptionalComponent, + processedPropType, + renderJSX, + unwrapRef +} from "util/vue"; +import type { Component, PropType } from "vue"; +import { computed, defineComponent, ref, shallowRef, toRefs, unref } from "vue"; + +export default defineComponent({ + props: { + element: Object as PropType<VueFeature>, + display: { + type: processedPropType<CoercableComponent>(Object, String, Function), + required: true + }, + style: processedPropType<StyleValue>(Object, String, Array), + classes: processedPropType<Record<string, boolean>>(Object), + direction: processedPropType<Direction>(String), + xoffset: processedPropType<string>(String), + yoffset: processedPropType<string>(String), + pinned: Object as PropType<Persistent<boolean>> + }, + setup(props) { + const { element, display, pinned } = toRefs(props); + + const isHovered = ref(false); + const isShown = computed(() => (unwrapRef(pinned) || isHovered.value) && comp.value); + const comp = computeOptionalComponent(display); + + const elementComp = shallowRef<Component | "" | null>( + coerceComponent( + jsx(() => { + const currComponent = unwrapRef(element); + return currComponent == null ? "" : renderJSX(currComponent); + }) + ) + ); + + function togglePinned(e: MouseEvent) { + const isPinned = pinned as unknown as Persistent<boolean> | undefined; // Vue typing :/ + if (e.shiftKey && isPinned) { + isPinned.value = !isPinned.value; + e.stopPropagation(); + e.preventDefault(); + } + } + + const showPin = computed(() => unwrapRef(pinned) && themes[settings.theme].showPin); + + return { + Direction, + isHovered, + isShown, + comp, + elementComp, + unref, + togglePinned, + showPin + }; + } +}); +</script> + +<style scoped> +.tooltip-container { + position: relative; + --xoffset: 0px; + --yoffset: 0px; + text-shadow: none !important; +} + +.tooltip, +.tooltip::after { + pointer-events: none; + position: absolute; +} + +.tooltip { + text-align: center; + width: 150px; + font-size: 14px; + line-height: 1.2; + bottom: calc(100% + var(--yoffset)); + left: calc(50% + var(--xoffset)); + margin-bottom: 5px; + transform: translateX(-50%); + padding: 7px; + border-radius: 3px; + background-color: var(--tooltip-background); + color: var(--points); + z-index: 100 !important; + word-break: break-word; +} + +.tooltip :deep(hr) { + margin: var(--feature-margin) 0; +} + +.shown { + z-index: 10; +} + +.fade-enter-from, +.fade-leave-to { + opacity: 0; +} + +.tooltip::after { + content: " "; + position: absolute; + top: 100%; + bottom: 100%; + left: calc(50% - var(--xoffset)); + width: 0; + margin-left: -5px; + border-width: 5px; + border-style: solid; + border-color: var(--tooltip-background) transparent transparent transparent; +} + +.tooltip.left, +.side-nodes .tooltip:not(.right):not(.bottom):not(.top) { + bottom: calc(50% + var(--yoffset)); + left: unset; + right: calc(100% + var(--xoffset)); + margin-bottom: unset; + margin-right: 5px; + transform: translateY(50%); +} + +.tooltip.left::after, +.side-nodes .tooltip:not(.right):not(.bottom):not(.top)::after { + top: calc(50% + var(--yoffset)); + bottom: unset; + left: 100%; + right: 100%; + margin-left: unset; + margin-top: -5px; + border-color: transparent transparent transparent var(--tooltip-background); +} + +.tooltip.right { + bottom: calc(50% + var(--yoffset)); + left: calc(100% + var(--xoffset)); + margin-bottom: unset; + margin-left: 5px; + transform: translateY(50%); +} + +.tooltip.right::after { + top: calc(50% + var(--yoffset)); + left: 0; + right: 100%; + margin-left: -10px; + margin-top: -5px; + border-color: transparent var(--tooltip-background) transparent transparent; +} + +.tooltip.bottom { + top: calc(100% + var(--yoffset)); + bottom: unset; + left: calc(50% + var(--xoffset)); + margin-bottom: unset; + margin-top: 5px; + transform: translateX(-50%); +} + +.tooltip.bottom::after { + top: 0; + margin-top: -10px; + border-color: transparent transparent var(--tooltip-background) transparent; +} + +.pinned { + position: absolute; + right: -5px; + top: -5px; + transform: rotateZ(45deg); +} +</style> diff --git a/src/features/tooltips/tooltip.ts b/src/features/tooltips/tooltip.ts new file mode 100644 index 0000000..dcc618f --- /dev/null +++ b/src/features/tooltips/tooltip.ts @@ -0,0 +1,108 @@ +import type { CoercableComponent, Replace, StyleValue } from "features/feature"; +import { Component, GatherProps, setDefault } from "features/feature"; +import { persistent } from "game/persistence"; +import { Direction } from "util/common"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import type { VueFeature } from "util/vue"; +import type { Ref } from "vue"; +import { nextTick, unref } from "vue"; +import TooltipComponent from "./Tooltip.vue"; + +declare module "@vue/runtime-dom" { + interface CSSProperties { + "--xoffset"?: string; + "--yoffset"?: string; + } +} + +export interface TooltipOptions { + pinnable?: boolean; + display: Computable<CoercableComponent>; + classes?: Computable<Record<string, boolean>>; + style?: Computable<StyleValue>; + direction?: Computable<Direction>; + xoffset?: Computable<string>; + yoffset?: Computable<string>; +} + +export interface BaseTooltip { + pinned?: Ref<boolean>; +} + +export type Tooltip<T extends TooltipOptions> = Replace< + T & BaseTooltip, + { + pinnable: T["pinnable"] extends undefined ? false : T["pinnable"]; + pinned: T["pinnable"] extends true ? Ref<boolean> : undefined; + display: GetComputableType<T["display"]>; + classes: GetComputableType<T["classes"]>; + style: GetComputableType<T["style"]>; + direction: GetComputableTypeWithDefault<T["direction"], Direction.Up>; + xoffset: GetComputableType<T["xoffset"]>; + yoffset: GetComputableType<T["yoffset"]>; + } +>; + +export type GenericTooltip = Replace< + Tooltip<TooltipOptions>, + { + pinnable: boolean; + pinned: Ref<boolean> | undefined; + direction: ProcessedComputable<Direction>; + } +>; + +export function addTooltip<T extends TooltipOptions>( + element: VueFeature, + options: T & ThisType<Tooltip<T>> & Partial<BaseTooltip> +): Tooltip<T> { + processComputable(options as T, "display"); + processComputable(options as T, "classes"); + processComputable(options as T, "style"); + processComputable(options as T, "direction"); + setDefault(options, "direction", Direction.Up); + processComputable(options as T, "xoffset"); + processComputable(options as T, "yoffset"); + + if (options.pinnable) { + if ("pinned" in element) { + console.error( + "Cannot add pinnable tooltip to element that already has a property called 'pinned'" + ); + options.pinnable = false; + } else { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (element as any).pinned = options.pinned = persistent<boolean>(false); + } + } + + nextTick(() => { + const elementComponent = element[Component]; + element[Component] = TooltipComponent; + const elementGatherProps = element[GatherProps].bind(element); + element[GatherProps] = function gatherTooltipProps(this: GenericTooltip) { + const { display, classes, style, direction, xoffset, yoffset, pinned } = this; + return { + element: { + [Component]: elementComponent, + [GatherProps]: elementGatherProps + }, + display, + classes, + style: unref(style), + direction, + xoffset, + yoffset, + pinned + }; + }.bind(options as GenericTooltip); + }); + + return options as unknown as Tooltip<T>; +} diff --git a/src/features/trees/Tree.vue b/src/features/trees/Tree.vue new file mode 100644 index 0000000..cba9fbd --- /dev/null +++ b/src/features/trees/Tree.vue @@ -0,0 +1,105 @@ +<template> + <component :is="nodesComp" /> + <component v-if="leftNodesComp" :is="leftNodesComp" /> + <component v-if="rightNodesComp" :is="rightNodesComp" /> + <Links v-if="branches" :links="unref(branches)" /> +</template> + +<script lang="tsx"> +import "components/common/table.css"; +import { jsx } from "features/feature"; +import Links from "features/links/Links.vue"; +import type { GenericTreeNode, TreeBranch } from "features/trees/tree"; +import { coerceComponent, processedPropType, renderJSX, unwrapRef } from "util/vue"; +import type { Component } from "vue"; +import { defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue"; + +export default defineComponent({ + props: { + nodes: { + type: processedPropType<GenericTreeNode[][]>(Array), + required: true + }, + leftSideNodes: processedPropType<GenericTreeNode[]>(Array), + rightSideNodes: processedPropType<GenericTreeNode[]>(Array), + branches: processedPropType<TreeBranch[]>(Array) + }, + components: { Links }, + setup(props) { + const { nodes, leftSideNodes, rightSideNodes } = toRefs(props); + + const nodesComp = shallowRef<Component | "">(); + watchEffect(() => { + const currNodes = unwrapRef(nodes); + nodesComp.value = coerceComponent( + jsx(() => ( + <> + {currNodes.map(row => ( + <span class="row tree-row" style="margin: 50px auto;"> + {row.map(renderJSX)} + </span> + ))} + </> + )) + ); + }); + + const leftNodesComp = shallowRef<Component | "">(); + watchEffect(() => { + const currNodes = unwrapRef(leftSideNodes); + leftNodesComp.value = currNodes + ? coerceComponent( + jsx(() => ( + <span class="left-side-nodes small">{currNodes.map(renderJSX)}</span> + )) + ) + : ""; + }); + + const rightNodesComp = shallowRef<Component | "">(); + watchEffect(() => { + const currNodes = unwrapRef(rightSideNodes); + rightNodesComp.value = currNodes + ? coerceComponent( + jsx(() => <span class="side-nodes small">{currNodes.map(renderJSX)}</span>) + ) + : ""; + }); + + return { + unref, + nodesComp, + leftNodesComp, + rightNodesComp + }; + } +}); +</script> + +<style scoped> +.left-side-nodes { + position: absolute; + left: 15px; + top: 65px; +} + +.side-nodes { + position: absolute; + right: 15px; + top: 65px; +} + +.left-side-nodes :deep(.treeNode), +.side-nodes :deep(.treeNode) { + margin: 20px auto; +} + +.small :deep(.treeNode) { + height: 60px; + width: 60px; +} + +.small :deep(.treeNode) > *:first-child { + font-size: 30px; +} +</style> diff --git a/src/features/trees/TreeNode.vue b/src/features/trees/TreeNode.vue new file mode 100644 index 0000000..ea48eeb --- /dev/null +++ b/src/features/trees/TreeNode.vue @@ -0,0 +1,123 @@ +<template> + <div + v-if="isVisible(visibility)" + :style="{ visibility: isHidden(visibility) ? 'hidden' : undefined }" + :class="{ + treeNode: true, + can: unref(canClick), + ...unref(classes) + }" + @click="onClick" + @mousedown="start" + @mouseleave="stop" + @mouseup="stop" + @touchstart.passive="start" + @touchend.passive="stop" + @touchcancel.passive="stop" + > + <div + :style="[ + { + backgroundColor: unref(color), + boxShadow: `-4px -4px 4px rgba(0, 0, 0, 0.25) inset, 0 0 20px ${unref( + glowColor + )}` + }, + unref(style) ?? [] + ]" + > + <component :is="unref(comp)" /> + </div> + <MarkNode :mark="unref(mark)" /> + <Node :id="id" /> + </div> +</template> + +<script lang="ts"> +import MarkNode from "components/MarkNode.vue"; +import Node from "components/Node.vue"; +import type { CoercableComponent, StyleValue } from "features/feature"; +import { isHidden, isVisible, Visibility } from "features/feature"; +import { + computeOptionalComponent, + isCoercableComponent, + processedPropType, + setupHoldToClick +} from "util/vue"; +import type { PropType } from "vue"; +import { defineComponent, toRefs, unref } from "vue"; + +export default defineComponent({ + props: { + display: processedPropType<CoercableComponent>(Object, String, Function), + visibility: { + type: processedPropType<Visibility | boolean>(Number, Boolean), + required: true + }, + style: processedPropType<StyleValue>(String, Object, Array), + classes: processedPropType<Record<string, boolean>>(Object), + onClick: Function as PropType<(e?: MouseEvent | TouchEvent) => void>, + onHold: Function as PropType<VoidFunction>, + color: processedPropType<string>(String), + glowColor: processedPropType<string>(String), + canClick: { + type: processedPropType<boolean>(Boolean), + required: true + }, + mark: processedPropType<boolean | string>(Boolean, String), + id: { + type: String, + required: true + } + }, + components: { + MarkNode, + Node + }, + setup(props) { + const { onClick, onHold, display } = toRefs(props); + + const comp = computeOptionalComponent(display); + + const { start, stop } = setupHoldToClick(onClick, onHold); + + return { + start, + stop, + comp, + unref, + Visibility, + isCoercableComponent, + isVisible, + isHidden + }; + } +}); +</script> + +<style scoped> +.treeNode { + height: 100px; + width: 100px; + border-radius: 50%; + padding: 0; + margin: 0 10px 0 10px; +} + +.treeNode > *:first-child { + width: 100%; + height: 100%; + border: 2px solid rgba(0, 0, 0, 0.125); + border-radius: inherit; + font-size: 40px; + color: rgba(0, 0, 0, 0.5); + text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.25); + box-shadow: -4px -4px 4px rgba(0, 0, 0, 0.25) inset, 0px 0px 20px var(--background); + text-transform: capitalize; + display: flex; +} + +.treeNode > *:first-child > * { + pointer-events: none; +} +</style> diff --git a/src/features/trees/tree.ts b/src/features/trees/tree.ts new file mode 100644 index 0000000..bcbf333 --- /dev/null +++ b/src/features/trees/tree.ts @@ -0,0 +1,305 @@ +import type { CoercableComponent, OptionsFunc, Replace, StyleValue } from "features/feature"; +import { Component, GatherProps, getUniqueID, setDefault, Visibility } from "features/feature"; +import type { Link } from "features/links/links"; +import type { GenericReset } from "features/reset"; +import type { Resource } from "features/resources/resource"; +import { displayResource } from "features/resources/resource"; +import TreeComponent from "features/trees/Tree.vue"; +import TreeNodeComponent from "features/trees/TreeNode.vue"; +import type { DecimalSource } from "util/bignum"; +import Decimal, { format, formatWhole } from "util/bignum"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { convertComputable, processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import type { Ref } from "vue"; +import { computed, ref, shallowRef, unref } from "vue"; + +export const TreeNodeType = Symbol("TreeNode"); +export const TreeType = Symbol("Tree"); + +export interface TreeNodeOptions { + visibility?: Computable<Visibility | boolean>; + canClick?: Computable<boolean>; + color?: Computable<string>; + display?: Computable<CoercableComponent>; + glowColor?: Computable<string>; + classes?: Computable<Record<string, boolean>>; + style?: Computable<StyleValue>; + mark?: Computable<boolean | string>; + reset?: GenericReset; + onClick?: (e?: MouseEvent | TouchEvent) => void; + onHold?: VoidFunction; +} + +export interface BaseTreeNode { + id: string; + type: typeof TreeNodeType; + [Component]: typeof TreeNodeComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type TreeNode<T extends TreeNodeOptions> = Replace< + T & BaseTreeNode, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + canClick: GetComputableTypeWithDefault<T["canClick"], true>; + color: GetComputableType<T["color"]>; + display: GetComputableType<T["display"]>; + glowColor: GetComputableType<T["glowColor"]>; + classes: GetComputableType<T["classes"]>; + style: GetComputableType<T["style"]>; + mark: GetComputableType<T["mark"]>; + } +>; + +export type GenericTreeNode = Replace< + TreeNode<TreeNodeOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + canClick: ProcessedComputable<boolean>; + } +>; + +export function createTreeNode<T extends TreeNodeOptions>( + optionsFunc?: OptionsFunc<T, BaseTreeNode, GenericTreeNode> +): TreeNode<T> { + return createLazyProxy(() => { + const treeNode = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>); + treeNode.id = getUniqueID("treeNode-"); + treeNode.type = TreeNodeType; + treeNode[Component] = TreeNodeComponent; + + processComputable(treeNode as T, "visibility"); + setDefault(treeNode, "visibility", Visibility.Visible); + processComputable(treeNode as T, "canClick"); + setDefault(treeNode, "canClick", true); + processComputable(treeNode as T, "color"); + processComputable(treeNode as T, "display"); + processComputable(treeNode as T, "glowColor"); + processComputable(treeNode as T, "classes"); + processComputable(treeNode as T, "style"); + processComputable(treeNode as T, "mark"); + + if (treeNode.onClick) { + const onClick = treeNode.onClick.bind(treeNode); + treeNode.onClick = function (e) { + if (unref(treeNode.canClick) !== false) { + onClick(e); + } + }; + } + if (treeNode.onHold) { + const onHold = treeNode.onHold.bind(treeNode); + treeNode.onHold = function () { + if (unref(treeNode.canClick) !== false) { + onHold(); + } + }; + } + + treeNode[GatherProps] = function (this: GenericTreeNode) { + const { + display, + visibility, + style, + classes, + onClick, + onHold, + color, + glowColor, + canClick, + mark, + id + } = this; + return { + display, + visibility, + style, + classes, + onClick, + onHold, + color, + glowColor, + canClick, + mark, + id + }; + }; + + return treeNode as unknown as TreeNode<T>; + }); +} + +export interface TreeBranch extends Omit<Link, "startNode" | "endNode"> { + startNode: GenericTreeNode; + endNode: GenericTreeNode; +} + +export interface TreeOptions { + visibility?: Computable<Visibility | boolean>; + nodes: Computable<GenericTreeNode[][]>; + leftSideNodes?: Computable<GenericTreeNode[]>; + rightSideNodes?: Computable<GenericTreeNode[]>; + branches?: Computable<TreeBranch[]>; + resetPropagation?: ResetPropagation; + onReset?: (node: GenericTreeNode) => void; +} + +export interface BaseTree { + id: string; + links: Ref<Link[]>; + reset: (node: GenericTreeNode) => void; + isResetting: Ref<boolean>; + resettingNode: Ref<GenericTreeNode | null>; + type: typeof TreeType; + [Component]: typeof TreeComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Tree<T extends TreeOptions> = Replace< + T & BaseTree, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + nodes: GetComputableType<T["nodes"]>; + leftSideNodes: GetComputableType<T["leftSideNodes"]>; + rightSideNodes: GetComputableType<T["rightSideNodes"]>; + branches: GetComputableType<T["branches"]>; + } +>; + +export type GenericTree = Replace< + Tree<TreeOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + } +>; + +export function createTree<T extends TreeOptions>( + optionsFunc: OptionsFunc<T, BaseTree, GenericTree> +): Tree<T> { + return createLazyProxy(() => { + const tree = optionsFunc(); + tree.id = getUniqueID("tree-"); + tree.type = TreeType; + tree[Component] = TreeComponent; + + tree.isResetting = ref(false); + tree.resettingNode = shallowRef(null); + + tree.reset = function (node) { + const genericTree = tree as GenericTree; + genericTree.isResetting.value = true; + genericTree.resettingNode.value = node; + genericTree.resetPropagation?.(genericTree, node); + genericTree.onReset?.(node); + genericTree.isResetting.value = false; + genericTree.resettingNode.value = null; + }; + tree.links = computed(() => { + const genericTree = tree as GenericTree; + return unref(genericTree.branches) ?? []; + }); + + processComputable(tree as T, "visibility"); + setDefault(tree, "visibility", Visibility.Visible); + processComputable(tree as T, "nodes"); + processComputable(tree as T, "leftSideNodes"); + processComputable(tree as T, "rightSideNodes"); + processComputable(tree as T, "branches"); + + tree[GatherProps] = function (this: GenericTree) { + const { nodes, leftSideNodes, rightSideNodes, branches } = this; + return { nodes, leftSideNodes, rightSideNodes, branches }; + }; + + return tree as unknown as Tree<T>; + }); +} + +export type ResetPropagation = { + (tree: GenericTree, resettingNode: GenericTreeNode): void; +}; + +export const defaultResetPropagation = function ( + tree: GenericTree, + resettingNode: GenericTreeNode +): void { + const nodes = unref(tree.nodes); + const row = nodes.findIndex(nodes => nodes.includes(resettingNode)) - 1; + for (let x = row; x >= 0; x--) { + nodes[x].forEach(node => node.reset?.reset()); + } +}; + +export const invertedResetPropagation = function ( + tree: GenericTree, + resettingNode: GenericTreeNode +): void { + const nodes = unref(tree.nodes); + const row = nodes.findIndex(nodes => nodes.includes(resettingNode)) + 1; + for (let x = row; x < nodes.length; x++) { + nodes[x].forEach(node => node.reset?.reset()); + } +}; + +export const branchedResetPropagation = function ( + tree: GenericTree, + resettingNode: GenericTreeNode +): void { + const visitedNodes = [resettingNode]; + let currentNodes = [resettingNode]; + if (tree.branches != null) { + const branches = unref(tree.branches); + while (currentNodes.length > 0) { + const nextNodes: GenericTreeNode[] = []; + currentNodes.forEach(node => { + branches + .filter(branch => branch.startNode === node || branch.endNode === node) + .map(branch => { + if (branch.startNode === node) { + return branch.endNode; + } + return branch.startNode; + }) + .filter(node => !visitedNodes.includes(node)) + .forEach(node => { + // Check here instead of in the filter because this check's results may + // change as we go through each node + if (!nextNodes.includes(node)) { + nextNodes.push(node); + node.reset?.reset(); + } + }); + }); + currentNodes = nextNodes; + visitedNodes.push(...currentNodes); + } + } +}; + +export function createResourceTooltip( + resource: Resource, + requiredResource: Resource | null = null, + requirement: Computable<DecimalSource> = 0 +): Ref<string> { + const req = convertComputable(requirement); + return computed(() => { + if (requiredResource == null || Decimal.gte(resource.value, unref(req))) { + return displayResource(resource) + " " + resource.displayName; + } + return `Reach ${ + Decimal.eq(requiredResource.precision, 0) + ? formatWhole(unref(req)) + : format(unref(req), requiredResource.precision) + } ${requiredResource.displayName} to unlock (You have ${ + Decimal.eq(requiredResource.precision, 0) + ? formatWhole(requiredResource.value) + : format(requiredResource.value, requiredResource.precision) + })`; + }); +} diff --git a/src/features/upgrades/Upgrade.vue b/src/features/upgrades/Upgrade.vue new file mode 100644 index 0000000..d1fb6c3 --- /dev/null +++ b/src/features/upgrades/Upgrade.vue @@ -0,0 +1,136 @@ +<template> + <button + v-if="isVisible(visibility)" + :style="[ + { + visibility: isHidden(visibility) ? 'hidden' : undefined + }, + unref(style) ?? {} + ]" + @click="purchase" + :class="{ + feature: true, + upgrade: true, + can: unref(canPurchase), + locked: !unref(canPurchase), + bought: unref(bought), + ...unref(classes) + }" + :disabled="!unref(canPurchase)" + > + <component v-if="unref(component)" :is="unref(component)" /> + <MarkNode :mark="unref(mark)" /> + <Node :id="id" /> + </button> +</template> + +<script lang="tsx"> +import "components/common/features.css"; +import MarkNode from "components/MarkNode.vue"; +import Node from "components/Node.vue"; +import type { StyleValue } from "features/feature"; +import { isHidden, isVisible, jsx, Visibility } from "features/feature"; +import type { GenericUpgrade } from "features/upgrades/upgrade"; +import { displayRequirements, Requirements } from "game/requirements"; +import { coerceComponent, isCoercableComponent, processedPropType, unwrapRef } from "util/vue"; +import type { Component, PropType, UnwrapRef } from "vue"; +import { defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue"; + +export default defineComponent({ + props: { + display: { + type: processedPropType<UnwrapRef<GenericUpgrade["display"]>>(String, Object, Function), + required: true + }, + visibility: { + type: processedPropType<Visibility | boolean>(Number, Boolean), + required: true + }, + style: processedPropType<StyleValue>(String, Object, Array), + classes: processedPropType<Record<string, boolean>>(Object), + requirements: { + type: Object as PropType<Requirements>, + required: true + }, + canPurchase: { + type: processedPropType<boolean>(Boolean), + required: true + }, + bought: { + type: processedPropType<boolean>(Boolean), + required: true + }, + mark: processedPropType<boolean | string>(Boolean, String), + id: { + type: String, + required: true + }, + purchase: { + type: Function as PropType<VoidFunction>, + required: true + } + }, + components: { + Node, + MarkNode + }, + setup(props) { + const { display, requirements, bought } = toRefs(props); + + const component = shallowRef<Component | string>(""); + + watchEffect(() => { + const currDisplay = unwrapRef(display); + if (currDisplay == null) { + component.value = ""; + return; + } + if (isCoercableComponent(currDisplay)) { + component.value = coerceComponent(currDisplay); + return; + } + const Title = coerceComponent(currDisplay.title || "", "h3"); + const Description = coerceComponent(currDisplay.description, "div"); + const EffectDisplay = coerceComponent(currDisplay.effectDisplay || ""); + component.value = coerceComponent( + jsx(() => ( + <span> + {currDisplay.title != null ? ( + <div> + <Title /> + </div> + ) : null} + <Description /> + {currDisplay.effectDisplay != null ? ( + <div> + Currently: <EffectDisplay /> + </div> + ) : null} + {bought.value ? null : <><br />{displayRequirements(requirements.value)}</>} + </span> + )) + ); + }); + + return { + component, + unref, + Visibility, + isVisible, + isHidden + }; + } +}); +</script> + +<style scoped> +.upgrade { + min-height: 120px; + width: 120px; + font-size: 10px; +} + +.upgrade > * { + pointer-events: none; +} +</style> diff --git a/src/features/upgrades/upgrade.ts b/src/features/upgrades/upgrade.ts new file mode 100644 index 0000000..5eda0e0 --- /dev/null +++ b/src/features/upgrades/upgrade.ts @@ -0,0 +1,169 @@ +import { isArray } from "@vue/shared"; +import type { + CoercableComponent, + GenericComponent, + OptionsFunc, + Replace, + StyleValue +} from "features/feature"; +import { + Component, + findFeatures, + GatherProps, + getUniqueID, + setDefault, + Visibility +} from "features/feature"; +import UpgradeComponent from "features/upgrades/Upgrade.vue"; +import type { GenericLayer } from "game/layers"; +import type { Persistent } from "game/persistence"; +import { persistent } from "game/persistence"; +import { + createVisibilityRequirement, + payRequirements, + Requirements, + requirementsMet +} from "game/requirements"; +import { isFunction } from "util/common"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import type { Ref } from "vue"; +import { computed, unref } from "vue"; + +export const UpgradeType = Symbol("Upgrade"); + +export interface UpgradeOptions { + visibility?: Computable<Visibility | boolean>; + classes?: Computable<Record<string, boolean>>; + style?: Computable<StyleValue>; + display?: Computable< + | CoercableComponent + | { + title?: CoercableComponent; + description: CoercableComponent; + effectDisplay?: CoercableComponent; + } + >; + requirements: Requirements; + mark?: Computable<boolean | string>; + onPurchase?: VoidFunction; +} + +export interface BaseUpgrade { + id: string; + bought: Persistent<boolean>; + canPurchase: Ref<boolean>; + purchase: VoidFunction; + type: typeof UpgradeType; + [Component]: typeof UpgradeComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export type Upgrade<T extends UpgradeOptions> = Replace< + T & BaseUpgrade, + { + visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>; + classes: GetComputableType<T["classes"]>; + style: GetComputableType<T["style"]>; + display: GetComputableType<T["display"]>; + requirements: GetComputableType<T["requirements"]>; + mark: GetComputableType<T["mark"]>; + } +>; + +export type GenericUpgrade = Replace< + Upgrade<UpgradeOptions>, + { + visibility: ProcessedComputable<Visibility | boolean>; + } +>; + +export function createUpgrade<T extends UpgradeOptions>( + optionsFunc: OptionsFunc<T, BaseUpgrade, GenericUpgrade> +): Upgrade<T> { + const bought = persistent<boolean>(false); + return createLazyProxy(() => { + const upgrade = optionsFunc(); + upgrade.id = getUniqueID("upgrade-"); + upgrade.type = UpgradeType; + upgrade[Component] = UpgradeComponent; + + upgrade.bought = bought; + upgrade.canPurchase = computed(() => requirementsMet(upgrade.requirements)); + upgrade.purchase = function () { + const genericUpgrade = upgrade as GenericUpgrade; + if (!unref(genericUpgrade.canPurchase)) { + return; + } + payRequirements(upgrade.requirements); + bought.value = true; + genericUpgrade.onPurchase?.(); + }; + + const visibilityRequirement = createVisibilityRequirement(upgrade as GenericUpgrade); + if (isArray(upgrade.requirements)) { + upgrade.requirements.unshift(visibilityRequirement); + } else { + upgrade.requirements = [visibilityRequirement, upgrade.requirements]; + } + + processComputable(upgrade as T, "visibility"); + setDefault(upgrade, "visibility", Visibility.Visible); + processComputable(upgrade as T, "classes"); + processComputable(upgrade as T, "style"); + processComputable(upgrade as T, "display"); + processComputable(upgrade as T, "mark"); + + upgrade[GatherProps] = function (this: GenericUpgrade) { + const { + display, + visibility, + style, + classes, + requirements, + canPurchase, + bought, + mark, + id, + purchase + } = this; + return { + display, + visibility, + style: unref(style), + classes, + requirements, + canPurchase, + bought, + mark, + id, + purchase + }; + }; + + return upgrade as unknown as Upgrade<T>; + }); +} + +export function setupAutoPurchase( + layer: GenericLayer, + autoActive: Computable<boolean>, + upgrades: GenericUpgrade[] = [] +): void { + upgrades = + upgrades.length === 0 ? (findFeatures(layer, UpgradeType) as GenericUpgrade[]) : upgrades; + const isAutoActive: ProcessedComputable<boolean> = isFunction(autoActive) + ? computed(autoActive) + : autoActive; + layer.on("update", () => { + if (unref(isAutoActive)) { + upgrades.forEach(upgrade => upgrade.purchase()); + } + }); +} diff --git a/src/game/events.ts b/src/game/events.ts new file mode 100644 index 0000000..a167042 --- /dev/null +++ b/src/game/events.ts @@ -0,0 +1,61 @@ +import type { Settings } from "game/settings"; +import { createNanoEvents } from "nanoevents"; +import type { App } from "vue"; +import type { GenericLayer } from "./layers"; + +/** All types of events able to be sent or emitted from the global event bus. */ +export interface GlobalEvents { + /** + * Sent whenever a layer is added. + * @param layer The layer being added. + * @param saveData The layer's save data object within player. + */ + addLayer: (layer: GenericLayer, saveData: Record<string, unknown>) => void; + /** + * Sent whenever a layer is removed. + * @param layer The layer being removed. + */ + removeLayer: (layer: GenericLayer) => void; + /** + * Sent every game tick. Runs the life cycle of the project. + * @param diff The delta time since last tick, in ms. + * @param trueDiff The delta time since last tick, in ms. Unaffected by time modifiers like {@link game/player.Player.devSpeed} or {@link game/player.Player.offlineTime}. Intended for things like updating animations. + */ + update: (diff: number, trueDiff: number) => void; + /** + * Sent when constructing the {@link Settings} object. + * Use it to add default values for custom properties to the object. + * @param settings The settings object being constructed. + * @see {@link features/features.setDefault} for setting default values. + */ + loadSettings: (settings: Partial<Settings>) => void; + /** + * Sent when the game has ended. + */ + gameWon: VoidFunction; + /** + * Sent when setting up the Vue Application instance. + * Use it to register global components or otherwise set up things that should affect Vue globally. + * @param vue The Vue App being constructed. + */ + setupVue: (vue: App) => void; + /** + * Sent whenever a save has finished loading. + * Happens when the page is opened and upon switching saves in the saves manager. + */ + onLoad: VoidFunction; + /** + * Using document.fonts.ready returns too early on firefox, so we use document.fonts.onloadingdone instead, which doesn't accept multiple listeners. + * This event fires when that callback is called. + */ + fontsLoaded: VoidFunction; +} + +/** A global event bus for hooking into {@link GlobalEvents}. */ +export const globalBus = createNanoEvents<GlobalEvents>(); + +if ("fonts" in document) { + // This line breaks tests + // JSDom doesn't add document.fonts, and Object.defineProperty doesn't seem to work on document + document.fonts.onloadingdone = () => globalBus.emit("fontsLoaded"); +} diff --git a/src/game/formulas.ts b/src/game/formulas.ts new file mode 100644 index 0000000..e812de3 --- /dev/null +++ b/src/game/formulas.ts @@ -0,0 +1,2247 @@ +import { Resource } from "features/resources/resource"; +import Decimal, { DecimalSource } from "util/bignum"; +import { Computable, convertComputable, ProcessedComputable } from "util/computed"; +import { computed, ComputedRef, ref, Ref, unref } from "vue"; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type GenericFormula = Formula<any>; +export type FormulaSource = ProcessedComputable<DecimalSource> | GenericFormula; +export type InvertibleFormula = GenericFormula & { + invert: (value: DecimalSource) => DecimalSource; +}; +export type IntegrableFormula = GenericFormula & { + evaluateIntegral: (variable?: DecimalSource) => DecimalSource; +}; +export type InvertibleIntegralFormula = GenericFormula & { + invertIntegral: (value: DecimalSource) => DecimalSource; +}; + +export type FormulaOptions<T extends [FormulaSource] | FormulaSource[]> = + | { + variable: ProcessedComputable<DecimalSource>; + } + | { + inputs: [FormulaSource]; + } + | { + inputs: T; + evaluate: (this: Formula<T>, ...inputs: GuardedFormulasToDecimals<T>) => DecimalSource; + invert?: ( + this: Formula<T>, + value: DecimalSource, + ...inputs: [...T, ...unknown[]] + ) => DecimalSource; + integrate?: ( + this: Formula<T>, + variable: DecimalSource | undefined, + ...inputs: T + ) => DecimalSource; + invertIntegral?: (this: Formula<T>, value: DecimalSource, ...inputs: T) => DecimalSource; + hasVariable?: boolean; + }; + +function hasVariable(value: FormulaSource): value is InvertibleFormula { + return value instanceof Formula && value.hasVariable(); +} + +// It's really hard to type mapped tuples, but these classes seem to manage +type FormulasToDecimals<T extends FormulaSource[]> = { + [K in keyof T]: DecimalSource; +}; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type TupleGuard<T extends any[]> = T extends any[] ? FormulasToDecimals<T> : never; +type GuardedFormulasToDecimals<T extends FormulaSource[]> = TupleGuard<T>; + +export function unrefFormulaSource(value: FormulaSource, variable?: DecimalSource) { + return value instanceof Formula ? value.evaluate(variable) : unref(value); +} + +function passthrough(value: DecimalSource) { + return value; +} + +function invertNeg(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.neg(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateNeg(variable: DecimalSource | undefined, lhs: FormulaSource) { + return Decimal.pow(unrefFormulaSource(lhs, variable), 2).div(2).neg(); +} + +function invertAdd(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.sub(value, unrefFormulaSource(rhs))); + } else if (hasVariable(rhs)) { + return rhs.invert(Decimal.sub(value, unrefFormulaSource(lhs))); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateAdd(variable: DecimalSource | undefined, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.pow(x, 2) + .div(2) + .add(Decimal.times(unrefFormulaSource(rhs), x)); + } else if (hasVariable(rhs)) { + const x = unrefFormulaSource(rhs, variable); + return Decimal.pow(x, 2) + .div(2) + .add(Decimal.times(unrefFormulaSource(lhs), x)); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegrateAdd(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const b = unrefFormulaSource(rhs); + return lhs.invert(Decimal.pow(b, 2).add(Decimal.times(value, 2)).sub(b)); + } else if (hasVariable(rhs)) { + const b = unrefFormulaSource(lhs); + return rhs.invert(Decimal.pow(b, 2).add(Decimal.times(value, 2)).sub(b)); + } + throw "Could not invert due to no input being a variable"; +} + +function invertSub(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.add(value, unrefFormulaSource(rhs))); + } else if (hasVariable(rhs)) { + return rhs.invert(Decimal.sub(unrefFormulaSource(lhs), value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateSub(variable: DecimalSource | undefined, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.pow(x, 2) + .div(2) + .add(Decimal.times(unrefFormulaSource(rhs), x).neg()); + } else if (hasVariable(rhs)) { + const x = unrefFormulaSource(rhs, variable); + return Decimal.sub(unrefFormulaSource(lhs), Decimal.div(x, 2)).times(x); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegrateSub(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const b = unrefFormulaSource(rhs); + return lhs.invert(Decimal.pow(b, 2).add(Decimal.times(value, 2)).sqrt().sub(b)); + } else if (hasVariable(rhs)) { + const b = unrefFormulaSource(lhs); + return rhs.invert(Decimal.pow(b, 2).add(Decimal.times(value, 2)).sqrt().sub(b)); + } + throw "Could not invert due to no input being a variable"; +} + +function invertMul(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.div(value, unrefFormulaSource(rhs))); + } else if (hasVariable(rhs)) { + return rhs.invert(Decimal.div(value, unrefFormulaSource(lhs))); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateMul(variable: DecimalSource | undefined, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.pow(x, 2).div(2).times(unrefFormulaSource(rhs)); + } else if (hasVariable(rhs)) { + const x = unrefFormulaSource(rhs, variable); + return Decimal.pow(x, 2).div(2).times(unrefFormulaSource(lhs)); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegrateMul(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const b = unrefFormulaSource(rhs); + return lhs.invert(Decimal.sqrt(value).times(Decimal.sqrt(2)).div(Decimal.sqrt(b))); + } else if (hasVariable(rhs)) { + const b = unrefFormulaSource(lhs); + return rhs.invert(Decimal.sqrt(value).times(Decimal.sqrt(2)).div(Decimal.sqrt(b))); + } + throw "Could not invert due to no input being a variable"; +} + +function invertDiv(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.mul(value, unrefFormulaSource(rhs))); + } else if (hasVariable(rhs)) { + return rhs.invert(Decimal.div(unrefFormulaSource(lhs), value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateDiv(variable: DecimalSource | undefined, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.pow(x, 2).div(Decimal.times(2, unrefFormulaSource(rhs))); + } else if (hasVariable(rhs)) { + const x = unrefFormulaSource(rhs, variable); + return Decimal.pow(x, 2).div(Decimal.times(2, unrefFormulaSource(lhs))); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegrateDiv(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const b = unrefFormulaSource(rhs); + return lhs.invert(Decimal.sqrt(value).times(Decimal.sqrt(2)).times(Decimal.sqrt(b))); + } else if (hasVariable(rhs)) { + const b = unrefFormulaSource(lhs); + return rhs.invert(Decimal.sqrt(value).times(Decimal.sqrt(2)).times(Decimal.sqrt(b))); + } + throw "Could not invert due to no input being a variable"; +} + +function invertRecip(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.recip(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateRecip(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.ln(x); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegrateRecip(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.exp(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function invertLog10(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.pow10(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateLog10(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.times(x, Decimal.sub(Decimal.ln(x), 1).div(Decimal.ln(10))); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegrateLog10(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert( + Decimal.exp(Decimal.ln(2).add(Decimal.ln(5)).times(value).div(Math.E).lambertw().add(1)) + ); + } + throw "Could not invert due to no input being a variable"; +} + +function invertLog(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.pow(unrefFormulaSource(rhs), value)); + } else if (hasVariable(rhs)) { + return rhs.invert(Decimal.root(unrefFormulaSource(lhs), value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateLog(variable: DecimalSource | undefined, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.times( + x, + Decimal.sub(Decimal.ln(x), 1).div(Decimal.ln(unrefFormulaSource(rhs))) + ); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegrateLog(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const numerator = Decimal.ln(unrefFormulaSource(rhs)).times(value); + return lhs.invert(numerator.div(numerator.div(Math.E).lambertw())); + } + throw "Could not invert due to no input being a variable"; +} + +function invertLog2(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.pow(2, value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateLog2(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.times(x, Decimal.sub(Decimal.ln(x), 1).div(Decimal.ln(2))); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegrateLog2(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.exp(Decimal.ln(2).times(value).div(Math.E).lambertw().add(1))); + } + throw "Could not invert due to no input being a variable"; +} + +function invertLn(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.exp(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateLn(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.times(x, Decimal.ln(x).sub(1)); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegrateLn(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.exp(Decimal.div(value, Math.E).lambertw().add(1))); + } + throw "Could not invert due to no input being a variable"; +} + +function invertPow(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.root(value, unrefFormulaSource(rhs))); + } else if (hasVariable(rhs)) { + return rhs.invert(Decimal.ln(value).div(Decimal.ln(unrefFormulaSource(lhs)))); + } + throw "Could not invert due to no input being a variable"; +} + +function integratePow(variable: DecimalSource | undefined, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + const pow = Decimal.add(unrefFormulaSource(rhs), 1); + return Decimal.pow(x, pow).div(pow); + } else if (hasVariable(rhs)) { + const x = unrefFormulaSource(rhs, variable); + const b = unrefFormulaSource(lhs); + return Decimal.pow(b, x).div(Decimal.ln(b)); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegratePow(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const b = unrefFormulaSource(rhs); + return lhs.invert(Decimal.negate(b).sub(1).negate().times(value).root(Decimal.add(b, 1))); + } else if (hasVariable(rhs)) { + const denominator = Decimal.ln(unrefFormulaSource(lhs)); + return rhs.invert(Decimal.times(denominator, value).ln().div(denominator)); + } + throw "Could not invert due to no input being a variable"; +} + +function invertPow10(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.root(value, 10)); + } + throw "Could not invert due to no input being a variable"; +} + +function integratePow10(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.ln(x).sub(1).times(x).div(Decimal.ln(10)); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegratePow10(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert( + Decimal.ln(2).add(Decimal.ln(5)).times(value).div(Math.E).lambertw().add(1).exp() + ); + } + throw "Could not invert due to no input being a variable"; +} + +function invertPowBase(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.ln(value).div(unrefFormulaSource(rhs))); + } else if (hasVariable(rhs)) { + return rhs.invert(Decimal.root(unrefFormulaSource(lhs), value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integratePowBase( + variable: DecimalSource | undefined, + lhs: FormulaSource, + rhs: FormulaSource +) { + if (hasVariable(lhs)) { + const b = unrefFormulaSource(rhs, variable); + return Decimal.pow(b, unrefFormulaSource(lhs)).div(Decimal.ln(b)); + } else if (hasVariable(rhs)) { + const denominator = Decimal.add(unrefFormulaSource(lhs, variable), 1); + return Decimal.pow(unrefFormulaSource(rhs), denominator).div(denominator); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegratePowBase(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const b = unrefFormulaSource(rhs); + return lhs.invert(Decimal.ln(b).times(value).ln().div(Decimal.ln(b))); + } else if (hasVariable(rhs)) { + const b = unrefFormulaSource(lhs); + return rhs.invert(Decimal.neg(b).sub(1).negate().times(value).root(Decimal.add(b, 1))); + } + throw "Could not invert due to no input being a variable"; +} + +function invertRoot(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.root(value, Decimal.recip(unrefFormulaSource(rhs)))); + } else if (hasVariable(rhs)) { + return rhs.invert(Decimal.ln(unrefFormulaSource(lhs)).div(Decimal.ln(value))); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateRoot( + variable: DecimalSource | undefined, + lhs: FormulaSource, + rhs: FormulaSource +) { + if (hasVariable(lhs)) { + const b = unrefFormulaSource(rhs); + return Decimal.pow(unrefFormulaSource(lhs, variable), Decimal.recip(b).add(1)) + .times(b) + .div(Decimal.add(b, 1)); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertIntegrateRoot(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + const b = unrefFormulaSource(rhs); + return lhs.invert( + Decimal.add(b, 1) + .times(value) + .div(b) + .pow(Decimal.div(b, Decimal.add(b, 1))) + ); + } + throw "Could not invert due to no input being a variable"; +} + +function invertExp(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.ln(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateExp(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return Decimal.exp(unrefFormulaSource(lhs, variable)); + } + throw "Could not integrate due to no input being a variable"; +} + +function tetrate( + value: DecimalSource, + height: DecimalSource = 2, + payload: DecimalSource = Decimal.fromComponents_noNormalize(1, 0, 1) +) { + const heightNumber = Decimal.minabs(height, 1e308).toNumber(); + return Decimal.tetrate(value, heightNumber, payload); +} + +function invertTetrate( + value: DecimalSource, + base: FormulaSource, + height: FormulaSource, + payload: FormulaSource +) { + if (hasVariable(base)) { + return base.invert( + Decimal.slog(value, Decimal.minabs(1e308, unrefFormulaSource(height)).toNumber()) + ); + } + // Other params can't be inverted ATM + throw "Could not invert due to no input being a variable"; +} + +function iteratedexp( + value: DecimalSource, + height: DecimalSource = 2, + payload: DecimalSource = Decimal.fromComponents_noNormalize(1, 0, 1) +) { + const heightNumber = Decimal.minabs(height, 1e308).toNumber(); + return Decimal.iteratedexp(value, heightNumber, new Decimal(payload)); +} + +function invertIteratedExp( + value: DecimalSource, + lhs: FormulaSource, + height: FormulaSource, + payload: FormulaSource +) { + if (hasVariable(lhs)) { + return lhs.invert( + Decimal.iteratedlog( + value, + Math.E, + Decimal.minabs(1e308, unrefFormulaSource(height)).toNumber() + ) + ); + } + // Other params can't be inverted ATM + throw "Could not invert due to no input being a variable"; +} + +function iteratedLog(value: DecimalSource, lhs: DecimalSource = 10, times: DecimalSource = 2) { + const timesNumber = Decimal.minabs(times, 1e308).toNumber(); + return Decimal.iteratedlog(value, lhs, timesNumber); +} + +function slog(value: DecimalSource, lhs: DecimalSource = 10) { + const baseNumber = Decimal.minabs(lhs, 1e308).toNumber(); + return Decimal.slog(value, baseNumber); +} + +function invertSlog(value: DecimalSource, lhs: FormulaSource, rhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert( + Decimal.tetrate(value, Decimal.minabs(1e308, unrefFormulaSource(rhs)).toNumber()) + ); + } + // Other params can't be inverted ATM + throw "Could not invert due to no input being a variable"; +} + +function layeradd(value: DecimalSource, diff: DecimalSource, base: DecimalSource) { + const diffNumber = Decimal.minabs(diff, 1e308).toNumber(); + return Decimal.layeradd(value, diffNumber, base); +} + +function invertLayeradd( + value: DecimalSource, + lhs: FormulaSource, + diff: FormulaSource, + base: FormulaSource +) { + if (hasVariable(lhs)) { + return lhs.invert( + Decimal.layeradd( + value, + Decimal.minabs(1e308, unrefFormulaSource(diff)).negate().toNumber() + ) + ); + } + // Other params can't be inverted ATM + throw "Could not invert due to no input being a variable"; +} + +function invertLambertw(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.pow(Math.E, value).times(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function invertSsqrt(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.tetrate(value, 2)); + } + throw "Could not invert due to no input being a variable"; +} + +function pentate(value: DecimalSource, height: DecimalSource, payload: DecimalSource) { + const heightNumber = Decimal.minabs(height, 1e308).toNumber(); + return Decimal.pentate(value, heightNumber, payload); +} + +function invertSin(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.asin(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateSin(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return Decimal.cos(unrefFormulaSource(lhs, variable)).neg(); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertCos(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.acos(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateCos(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return Decimal.sin(unrefFormulaSource(lhs, variable)); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertTan(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.atan(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateTan(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return Decimal.cos(unrefFormulaSource(lhs, variable)).ln().neg(); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertAsin(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.sin(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateAsin(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.asin(x) + .times(x) + .add(Decimal.sqrt(Decimal.sub(1, Decimal.pow(x, 2)))); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertAcos(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.cos(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateAcos(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.acos(x) + .times(x) + .sub(Decimal.sqrt(Decimal.sub(1, Decimal.pow(x, 2)))); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertAtan(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.tan(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateAtan(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.atan(x) + .times(x) + .sub(Decimal.ln(Decimal.pow(x, 2).add(1)).div(2)); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertSinh(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.asinh(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateSinh(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.cosh(x); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertCosh(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.acosh(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateCosh(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.sinh(x); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertTanh(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.atanh(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateTanh(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.cosh(x).ln(); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertAsinh(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.sinh(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateAsinh(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.asinh(x).times(x).sub(Decimal.pow(x, 2).add(1).sqrt()); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertAcosh(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.cosh(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateAcosh(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.acosh(x) + .times(x) + .sub(Decimal.add(x, 1).sqrt().times(Decimal.sub(x, 1).sqrt())); + } + throw "Could not integrate due to no input being a variable"; +} + +function invertAtanh(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + return lhs.invert(Decimal.tanh(value)); + } + throw "Could not invert due to no input being a variable"; +} + +function integrateAtanh(variable: DecimalSource | undefined, lhs: FormulaSource) { + if (hasVariable(lhs)) { + const x = unrefFormulaSource(lhs, variable); + return Decimal.atanh(x) + .times(x) + .add(Decimal.sub(1, Decimal.pow(x, 2)).ln().div(2)); + } + throw "Could not integrate due to no input being a variable"; +} + +/** + * A class that can be used for cost/goal functions. It can be evaluated similar to a cost function, but also provides extra features for supported formulas. For example, a lot of math functions can be inverted. + * Typically, the use of these extra features is to support cost/goal functions that have multiple levels purchased/completed at once efficiently. + * @see {@link calculateMaxAffordable} + * @see {@link game/requirements.createCostRequirement} + */ +export default class Formula<T extends [FormulaSource] | FormulaSource[]> { + readonly inputs: T; + + private readonly internalEvaluate: + | ((...inputs: GuardedFormulasToDecimals<T>) => DecimalSource) + | undefined; + private readonly internalInvert: + | ((value: DecimalSource, ...inputs: T) => DecimalSource) + | undefined; + private readonly internalIntegrate: + | ((variable: DecimalSource | undefined, ...inputs: T) => DecimalSource) + | undefined; + private readonly internalInvertIntegral: + | ((value: DecimalSource, ...inputs: T) => DecimalSource) + | undefined; + private readonly internalHasVariable: boolean; + + public readonly innermostVariable: ProcessedComputable<DecimalSource> | undefined; + + constructor(options: FormulaOptions<T>) { + // Variable case + if ("variable" in options) { + this.inputs = [options.variable] as T; + this.internalHasVariable = true; + this.innermostVariable = options.variable; + return; + } + // Constant case + if (!("evaluate" in options)) { + if (options.inputs.length !== 1) { + throw "Evaluate function is required if inputs is not length 1"; + } + this.inputs = options.inputs as T; + this.internalHasVariable = false; + return; + } + + const { inputs, evaluate, invert, integrate, invertIntegral, hasVariable } = options; + if (invert == null && invertIntegral == null && hasVariable) { + throw "A formula cannot be marked as having a variable if it is not invertible"; + } + + this.inputs = inputs; + this.internalEvaluate = evaluate; + this.internalIntegrate = integrate; + + const numVariables = inputs.filter( + input => input instanceof Formula && input.hasVariable() + ).length; + const variable = inputs.find(input => input instanceof Formula && input.hasVariable()) as + | GenericFormula + | undefined; + + this.internalHasVariable = + numVariables === 1 || (numVariables === 0 && hasVariable === true); + if (this.internalHasVariable) { + this.innermostVariable = variable?.innermostVariable; + } + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this.internalInvert = + this.internalHasVariable && variable?.isInvertible() ? invert : undefined; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + this.internalInvertIntegral = + this.internalHasVariable && variable?.isIntegralInvertible() + ? invertIntegral + : undefined; + } + + /** Type predicate that this formula can be inverted. */ + isInvertible(): this is InvertibleFormula { + return ( + this.internalHasVariable && + (this.internalInvert != null || this.internalEvaluate == null) + ); + } + + /** Type predicate that this formula can be integrated. */ + isIntegrable(): this is IntegrableFormula { + return this.internalHasVariable && this.internalIntegrate != null; + } + + /** Type predicate that this formula has an integral function that can be inverted. */ + isIntegralInvertible(): this is InvertibleIntegralFormula { + return ( + this.internalHasVariable && + (this.internalInvertIntegral != null || this.internalEvaluate == null) + ); + } + + /** Whether or not this formula has a singular variable inside it, which can be accessed via {@link innermostVariable}. */ + hasVariable(): boolean { + return this.internalHasVariable; + } + + /** + * Evaluate the current result of the formula + * @param variable Optionally override the value of the variable while evaluating. Ignored if there is not variable + */ + evaluate(variable?: DecimalSource): DecimalSource { + return ( + this.internalEvaluate?.call( + this, + ...(this.inputs.map(input => + unrefFormulaSource(input, variable) + ) as GuardedFormulasToDecimals<T>) + ) ?? + variable ?? + unrefFormulaSource(this.inputs[0]) + ); + } + + /** + * Takes a potential result of the formula, and calculates what value the variable inside the formula would have to be for that result to occur. Only works if there's a single variable and if the formula is invertible. + * @param value The result of the formula + * @see {@link isInvertible} + */ + invert(value: DecimalSource): DecimalSource { + if (this.internalInvert) { + return this.internalInvert.call(this, value, ...this.inputs); + } else if (this.inputs.length === 1 && this.internalHasVariable) { + return value; + } + throw "Cannot invert non-invertible formula"; + } + + /** + * Evaluate the result of the indefinite integral (sans the constant of integration). Only works if there's a single variable and the formula is integrable + * @param variable Optionally override the value of the variable while evaluating + * @see {@link isIntegrable} + */ + evaluateIntegral(variable?: DecimalSource): DecimalSource { + if (this.internalIntegrate) { + return this.internalIntegrate.call(this, variable, ...this.inputs); + } else if (this.inputs.length === 1 && this.internalHasVariable) { + return variable ?? unrefFormulaSource(this.inputs[0]); + } + throw "Cannot integrate formula without variable"; + } + + /** + * Given the potential result of the formula's integral (sand the constant of integration), calculate what value the variable inside the formula would have to be for that result to occur. Only works if there's a single variable and if the formula's integral is invertible. + * @param value The result of the integral. + * @see {@link isIntegralInvertible} + */ + invertIntegral(value: DecimalSource): DecimalSource { + // This is nearly completely non-functional + // Proper nesting will require somehow using integration by substitution or integration by parts + if (this.internalInvertIntegral) { + return this.internalInvertIntegral.call(this, value, ...this.inputs); + } else if (this.inputs.length === 1 && this.internalHasVariable) { + return value; + } + throw "Cannot invert integral of formula without invertible integral"; + } + + /** + * Compares if two formulas are equivalent to each other. Note that function contexts can lead to false negatives. + * @param other The formula to compare to this one. + */ + equals(other: GenericFormula): boolean { + return ( + this.inputs.length === other.inputs.length && + this.inputs.every((input, i) => + input instanceof Formula && other.inputs[i] instanceof Formula + ? input.equals(other.inputs[i]) + : !(input instanceof Formula) && + !(other.inputs[i] instanceof Formula) && + Decimal.eq(unref(input), unref(other.inputs[i])) + ) && + this.internalEvaluate === other.internalEvaluate && + this.internalInvert === other.internalInvert && + this.internalIntegrate === other.internalIntegrate && + this.internalInvertIntegral === other.internalInvertIntegral && + this.internalHasVariable === other.internalHasVariable + ); + } + + /** + * Creates a formula that evaluates to a constant value. + * @param value The constant value for this formula. + */ + public static constant( + value: ProcessedComputable<DecimalSource> + ): InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula { + return new Formula({ inputs: [value] }) as InvertibleFormula; + } + + /** + * Creates a formula that is marked as the variable for an outer formula. Typically used for inverting and integrating. + * @param value The variable for this formula. + */ + public static variable( + value: ProcessedComputable<DecimalSource> + ): InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula { + return new Formula({ variable: value }) as InvertibleFormula; + } + + /** + * Creates a step-wise formula. After {@ref start} the formula will have an additional modifier. + * This function assumes the incoming {@ref value} will be continuous and monotonically increasing. + * @param value The value before applying the step + * @param start The value at which to start applying the step + * @param formulaModifier How this step should modify the formula. The incoming value will be the unmodified formula value _minus the start value_. So for example if an incoming formula evaluates to 200 and has a step that starts at 150, the formulaModifier would be given 50 as the parameter + */ + public static step( + value: FormulaSource, + start: Computable<DecimalSource>, + formulaModifier: ( + value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula + ) => GenericFormula + ): GenericFormula { + const lhsRef = ref<DecimalSource>(0); + const formula = formulaModifier(Formula.variable(lhsRef)); + const processedStart = convertComputable(start); + function evalStep(lhs: DecimalSource) { + if (Decimal.lt(lhs, unref(processedStart))) { + return lhs; + } + lhsRef.value = Decimal.sub(lhs, unref(processedStart)); + return Decimal.add(formula.evaluate(), unref(processedStart)); + } + function invertStep(value: DecimalSource, lhs: FormulaSource) { + if (hasVariable(lhs)) { + if (Decimal.gt(value, unref(processedStart))) { + value = Decimal.add( + formula.invert(Decimal.sub(value, unref(processedStart))), + unref(processedStart) + ); + } + return lhs.invert(value); + } + throw "Could not invert due to no input being a variable"; + } + return new Formula({ + inputs: [value], + evaluate: evalStep, + invert: formula.isInvertible() && formula.hasVariable() ? invertStep : undefined + }); + } + + /** + * Applies a modifier to a formula under a given condition. + * @param value The incoming formula value + * @param condition Whether or not to apply the modifier + * @param formulaModifier The modifier to apply to the incoming formula if the condition is true + */ + public static if( + value: FormulaSource, + condition: Computable<boolean>, + formulaModifier: ( + value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula + ) => GenericFormula + ): GenericFormula { + const lhsRef = ref<DecimalSource>(0); + const formula = formulaModifier(Formula.variable(lhsRef)); + const processedCondition = convertComputable(condition); + function evalStep(lhs: DecimalSource) { + if (unref(processedCondition)) { + lhsRef.value = lhs; + return formula.evaluate(); + } else { + return lhs; + } + } + function invertStep(value: DecimalSource, lhs: FormulaSource) { + if (!hasVariable(lhs)) { + throw "Could not invert due to no input being a variable"; + } + if (unref(processedCondition)) { + return lhs.invert(formula.invert(value)); + } else { + return lhs.invert(value); + } + } + return new Formula({ + inputs: [value], + evaluate: evalStep, + invert: formula.isInvertible() && formula.hasVariable() ? invertStep : undefined + }); + } + /** @see {@link if} */ + public static conditional( + value: FormulaSource, + condition: Computable<boolean>, + formulaModifier: ( + value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula + ) => GenericFormula + ) { + return Formula.if(value, condition, formulaModifier); + } + + public static abs(value: FormulaSource): GenericFormula { + return new Formula({ inputs: [value], evaluate: Decimal.abs }); + } + + public static neg<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static neg(value: FormulaSource): GenericFormula; + public static neg(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.neg, + invert: invertNeg, + integrate: integrateNeg + }); + } + public static negate<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static negate(value: FormulaSource): GenericFormula; + public static negate(value: FormulaSource) { + return Formula.neg(value); + } + public static negated<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static negated(value: FormulaSource): GenericFormula; + public static negated(value: FormulaSource) { + return Formula.neg(value); + } + + public static sign(value: FormulaSource): GenericFormula { + return new Formula({ inputs: [value], evaluate: Decimal.sign }); + } + public static sgn(value: FormulaSource) { + return Formula.sign(value); + } + + public static round(value: FormulaSource): GenericFormula { + return new Formula({ inputs: [value], evaluate: Decimal.round }); + } + + public static floor(value: FormulaSource): GenericFormula { + return new Formula({ inputs: [value], evaluate: Decimal.floor }); + } + + public static ceil(value: FormulaSource): GenericFormula { + return new Formula({ inputs: [value], evaluate: Decimal.ceil }); + } + + public static trunc(value: FormulaSource): GenericFormula { + return new Formula({ inputs: [value], evaluate: Decimal.trunc }); + } + + public static add<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static add<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static add(value: FormulaSource, other: FormulaSource): GenericFormula; + public static add(value: FormulaSource, other: FormulaSource) { + return new Formula({ + inputs: [value, other], + evaluate: Decimal.add, + invert: invertAdd, + integrate: integrateAdd, + invertIntegral: invertIntegrateAdd + }); + } + public static plus<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static plus<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static plus(value: FormulaSource, other: FormulaSource): GenericFormula; + public static plus(value: FormulaSource, other: FormulaSource) { + return Formula.add(value, other); + } + + public static sub<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static sub<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static sub(value: FormulaSource, other: FormulaSource): GenericFormula; + public static sub(value: FormulaSource, other: FormulaSource) { + return new Formula({ + inputs: [value, other], + evaluate: Decimal.sub, + invert: invertSub, + integrate: integrateSub, + invertIntegral: invertIntegrateSub + }); + } + public static subtract<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static subtract<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static subtract(value: FormulaSource, other: FormulaSource): GenericFormula; + public static subtract(value: FormulaSource, other: FormulaSource) { + return Formula.sub(value, other); + } + public static minus<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static minus<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static minus(value: FormulaSource, other: FormulaSource): GenericFormula; + public static minus(value: FormulaSource, other: FormulaSource) { + return Formula.sub(value, other); + } + + public static mul<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static mul<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static mul(value: FormulaSource, other: FormulaSource): GenericFormula; + public static mul(value: FormulaSource, other: FormulaSource) { + return new Formula({ + inputs: [value, other], + evaluate: Decimal.mul, + invert: invertMul, + integrate: integrateMul, + invertIntegral: invertIntegrateMul + }); + } + public static multiply<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static multiply<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static multiply(value: FormulaSource, other: FormulaSource): GenericFormula; + public static multiply(value: FormulaSource, other: FormulaSource) { + return Formula.mul(value, other); + } + public static times<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static times<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static times(value: FormulaSource, other: FormulaSource): GenericFormula; + public static times(value: FormulaSource, other: FormulaSource) { + return Formula.mul(value, other); + } + + public static div<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static div<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static div(value: FormulaSource, other: FormulaSource): GenericFormula; + public static div(value: FormulaSource, other: FormulaSource) { + return new Formula({ + inputs: [value, other], + evaluate: Decimal.div, + invert: invertDiv, + integrate: integrateDiv, + invertIntegral: invertIntegrateDiv + }); + } + public static divide<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static divide<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static divide(value: FormulaSource, other: FormulaSource): GenericFormula; + public static divide(value: FormulaSource, other: FormulaSource) { + return Formula.div(value, other); + } + + public static recip<T extends GenericFormula>(value: T): T; + public static recip(value: FormulaSource): GenericFormula; + public static recip(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.recip, + invert: invertRecip, + integrate: integrateRecip, + invertIntegral: invertIntegrateRecip + }); + } + public static reciprocal<T extends GenericFormula>(value: T): T; + public static reciprocal(value: FormulaSource): GenericFormula; + public static reciprocal(value: FormulaSource): GenericFormula { + return Formula.recip(value); + } + public static reciprocate<T extends GenericFormula>(value: T): T; + public static reciprocate(value: FormulaSource): GenericFormula; + public static reciprocate(value: FormulaSource) { + return Formula.recip(value); + } + + public static max(value: FormulaSource, other: FormulaSource): GenericFormula { + return new Formula({ + inputs: [value, other], + evaluate: Decimal.max, + invert: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource, + invertIntegral: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource + }); + } + + public static min(value: FormulaSource, other: FormulaSource): GenericFormula { + return new Formula({ + inputs: [value, other], + evaluate: Decimal.min, + invert: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource, + invertIntegral: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource + }); + } + + public static minabs(value: FormulaSource, other: FormulaSource): GenericFormula { + return new Formula({ + inputs: [value, other], + evaluate: Decimal.minabs, + invert: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource, + invertIntegral: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource + }); + } + + public static maxabs(value: FormulaSource, other: FormulaSource): GenericFormula { + return new Formula({ + inputs: [value, other], + evaluate: Decimal.maxabs, + invert: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource, + invertIntegral: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource + }); + } + + public static clamp( + value: FormulaSource, + min: FormulaSource, + max: FormulaSource + ): GenericFormula { + return new Formula({ + inputs: [value, min, max], + evaluate: Decimal.clamp, + invert: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource, FormulaSource] + ) => DecimalSource, + invertIntegral: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource, FormulaSource] + ) => DecimalSource + }); + } + + public static clampMin(value: FormulaSource, min: FormulaSource): GenericFormula { + return new Formula({ + inputs: [value, min], + evaluate: Decimal.clampMin, + invert: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource, + invertIntegral: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource + }); + } + + public static clampMax(value: FormulaSource, max: FormulaSource): GenericFormula { + return new Formula({ + inputs: [value, max], + evaluate: Decimal.clampMax, + invert: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource, + invertIntegral: passthrough as ( + value: DecimalSource, + ...inputs: [FormulaSource, FormulaSource] + ) => DecimalSource + }); + } + + public static pLog10(value: FormulaSource): GenericFormula { + return new Formula({ inputs: [value], evaluate: Decimal.pLog10 }); + } + + public static absLog10(value: FormulaSource): GenericFormula { + return new Formula({ inputs: [value], evaluate: Decimal.absLog10 }); + } + + public static log10<T extends GenericFormula>(value: T): T; + public static log10(value: FormulaSource): GenericFormula; + public static log10(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.log10, + invert: invertLog10, + integrate: integrateLog10, + invertIntegral: invertIntegrateLog10 + }); + } + + public static log<T extends GenericFormula>(value: T, base: FormulaSource): T; + public static log<T extends GenericFormula>(value: FormulaSource, base: T): T; + public static log(value: FormulaSource, base: FormulaSource): GenericFormula; + public static log(value: FormulaSource, base: FormulaSource) { + return new Formula({ + inputs: [value, base], + evaluate: Decimal.log, + invert: invertLog, + integrate: integrateLog, + invertIntegral: invertIntegrateLog + }); + } + public static logarithm<T extends GenericFormula>(value: T, base: FormulaSource): T; + public static logarithm<T extends GenericFormula>(value: FormulaSource, base: T): T; + public static logarithm(value: FormulaSource, base: FormulaSource): GenericFormula; + public static logarithm(value: FormulaSource, base: FormulaSource) { + return Formula.log(value, base); + } + + public static log2<T extends GenericFormula>(value: T): T; + public static log2(value: FormulaSource): GenericFormula; + public static log2(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.log2, + invert: invertLog2, + integrate: integrateLog2, + invertIntegral: invertIntegrateLog2 + }); + } + + public static ln<T extends GenericFormula>(value: T): T; + public static ln(value: FormulaSource): GenericFormula; + public static ln(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.ln, + invert: invertLn, + integrate: integrateLn, + invertIntegral: invertIntegrateLn + }); + } + + public static pow<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static pow<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static pow(value: FormulaSource, other: FormulaSource): GenericFormula; + public static pow(value: FormulaSource, other: FormulaSource) { + return new Formula({ + inputs: [value, other], + evaluate: Decimal.pow, + invert: invertPow, + integrate: integratePow, + invertIntegral: invertIntegratePow + }); + } + + public static pow10<T extends GenericFormula>(value: T): T; + public static pow10(value: FormulaSource): GenericFormula; + public static pow10(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.pow10, + invert: invertPow10, + integrate: integratePow10, + invertIntegral: invertIntegratePow10 + }); + } + + public static pow_base<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static pow_base<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static pow_base(value: FormulaSource, other: FormulaSource): GenericFormula; + public static pow_base(value: FormulaSource, other: FormulaSource) { + return new Formula({ + inputs: [value, other], + evaluate: Decimal.pow_base, + invert: invertPowBase, + integrate: integratePowBase, + invertIntegral: invertIntegratePowBase + }); + } + + public static root<T extends GenericFormula>(value: T, other: FormulaSource): T; + public static root<T extends GenericFormula>(value: FormulaSource, other: T): T; + public static root(value: FormulaSource, other: FormulaSource): GenericFormula; + public static root(value: FormulaSource, other: FormulaSource) { + return new Formula({ + inputs: [value, other], + evaluate: Decimal.root, + invert: invertRoot, + integrate: integrateRoot, + invertIntegral: invertIntegrateRoot + }); + } + + public static factorial(value: FormulaSource) { + return new Formula({ inputs: [value], evaluate: Decimal.factorial }); + } + + public static gamma(value: FormulaSource) { + return new Formula({ inputs: [value], evaluate: Decimal.gamma }); + } + + public static lngamma(value: FormulaSource) { + return new Formula({ inputs: [value], evaluate: Decimal.lngamma }); + } + + public static exp<T extends GenericFormula>(value: T): Omit<T, "invertsIntegral">; + public static exp(value: FormulaSource): GenericFormula; + public static exp(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.exp, + invert: invertExp, + integrate: integrateExp + }); + } + + public static sqr<T extends GenericFormula>(value: T): T; + public static sqr(value: FormulaSource): GenericFormula; + public static sqr(value: FormulaSource) { + return Formula.pow(value, 2); + } + + public static sqrt<T extends GenericFormula>(value: T): T; + public static sqrt(value: FormulaSource): GenericFormula; + public static sqrt(value: FormulaSource) { + return Formula.root(value, 2); + } + + public static cube<T extends GenericFormula>(value: T): T; + public static cube(value: FormulaSource): GenericFormula; + public static cube(value: FormulaSource) { + return Formula.pow(value, 3); + } + + public static cbrt<T extends GenericFormula>(value: T): T; + public static cbrt(value: FormulaSource): GenericFormula; + public static cbrt(value: FormulaSource) { + return Formula.root(value, 3); + } + + public static tetrate<T extends GenericFormula>( + value: T, + height?: FormulaSource, + payload?: FormulaSource + ): Omit<T, "integrate" | "invertIntegral">; + public static tetrate( + value: FormulaSource, + height?: FormulaSource, + payload?: FormulaSource + ): GenericFormula; + public static tetrate( + value: FormulaSource, + height: FormulaSource = 2, + payload: FormulaSource = Decimal.fromComponents_noNormalize(1, 0, 1) + ) { + return new Formula({ + inputs: [value, height, payload], + evaluate: tetrate, + invert: invertTetrate + }); + } + + public static iteratedexp<T extends GenericFormula>( + value: T, + height?: FormulaSource, + payload?: FormulaSource + ): Omit<T, "integrate" | "invertIntegral">; + public static iteratedexp( + value: FormulaSource, + height?: FormulaSource, + payload?: FormulaSource + ): GenericFormula; + public static iteratedexp( + value: FormulaSource, + height: FormulaSource = 2, + payload: FormulaSource = Decimal.fromComponents_noNormalize(1, 0, 1) + ) { + return new Formula({ + inputs: [value, height, payload], + evaluate: iteratedexp, + invert: invertIteratedExp + }); + } + + public static iteratedlog( + value: FormulaSource, + base: FormulaSource = 10, + times: FormulaSource = 1 + ): GenericFormula { + return new Formula({ inputs: [value, base, times], evaluate: iteratedLog }); + } + + public static slog<T extends GenericFormula>( + value: T, + base?: FormulaSource + ): Omit<T, "integrate" | "invertIntegral">; + public static slog(value: FormulaSource, base?: FormulaSource): GenericFormula; + public static slog(value: FormulaSource, base: FormulaSource = 10) { + return new Formula({ inputs: [value, base], evaluate: slog, invert: invertSlog }); + } + + public static layeradd10(value: FormulaSource, diff: FormulaSource) { + return new Formula({ inputs: [value, diff], evaluate: Decimal.layeradd10 }); + } + + public static layeradd<T extends GenericFormula>( + value: T, + diff: FormulaSource, + base?: FormulaSource + ): Omit<T, "integrate" | "invertIntegral">; + public static layeradd( + value: FormulaSource, + diff: FormulaSource, + base?: FormulaSource + ): GenericFormula; + public static layeradd(value: FormulaSource, diff: FormulaSource, base: FormulaSource = 10) { + return new Formula({ + inputs: [value, diff, base], + evaluate: layeradd, + invert: invertLayeradd + }); + } + + public static lambertw<T extends GenericFormula>( + value: T + ): Omit<T, "integrate" | "invertIntegral">; + public static lambertw(value: FormulaSource): GenericFormula; + public static lambertw(value: FormulaSource) { + return new Formula({ inputs: [value], evaluate: Decimal.lambertw, invert: invertLambertw }); + } + + public static ssqrt<T extends GenericFormula>( + value: T + ): Omit<T, "integrate" | "invertIntegral">; + public static ssqrt(value: FormulaSource): GenericFormula; + public static ssqrt(value: FormulaSource) { + return new Formula({ inputs: [value], evaluate: Decimal.ssqrt, invert: invertSsqrt }); + } + + public static pentate( + value: FormulaSource, + height: FormulaSource = 2, + payload: FormulaSource = Decimal.fromComponents_noNormalize(1, 0, 1) + ): GenericFormula { + return new Formula({ inputs: [value, height, payload], evaluate: pentate }); + } + + public static sin<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static sin(value: FormulaSource): GenericFormula; + public static sin(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.sin, + invert: invertAsin, + integrate: integrateSin + }); + } + + public static cos<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static cos(value: FormulaSource): GenericFormula; + public static cos(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.cos, + invert: invertAcos, + integrate: integrateCos + }); + } + + public static tan<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static tan(value: FormulaSource): GenericFormula; + public static tan(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.tan, + invert: invertAtan, + integrate: integrateTan + }); + } + + public static asin<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static asin(value: FormulaSource): GenericFormula; + public static asin(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.asin, + invert: invertSin, + integrate: integrateAsin + }); + } + + public static acos<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static acos(value: FormulaSource): GenericFormula; + public static acos(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.acos, + invert: invertCos, + integrate: integrateAcos + }); + } + + public static atan<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static atan(value: FormulaSource): GenericFormula; + public static atan(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.atan, + invert: invertTan, + integrate: integrateAtan + }); + } + + public static sinh<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static sinh(value: FormulaSource): GenericFormula; + public static sinh(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.sinh, + invert: invertAsinh, + integrate: integrateSinh + }); + } + + public static cosh<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static cosh(value: FormulaSource): GenericFormula; + public static cosh(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.cosh, + invert: invertAcosh, + integrate: integrateCosh + }); + } + + public static tanh<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static tanh(value: FormulaSource): GenericFormula; + public static tanh(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.tanh, + invert: invertAtanh, + integrate: integrateTanh + }); + } + + public static asinh<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static asinh(value: FormulaSource): GenericFormula; + public static asinh(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.asinh, + invert: invertSinh, + integrate: integrateAsinh + }); + } + + public static acosh<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static acosh(value: FormulaSource): GenericFormula; + public static acosh(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.acosh, + invert: invertCosh, + integrate: integrateAcosh + }); + } + + public static atanh<T extends GenericFormula>(value: T): Omit<T, "invertIntegral">; + public static atanh(value: FormulaSource): GenericFormula; + public static atanh(value: FormulaSource) { + return new Formula({ + inputs: [value], + evaluate: Decimal.atanh, + invert: invertTanh, + integrate: integrateAtanh + }); + } + + public step( + start: Computable<DecimalSource>, + formulaModifier: ( + value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula + ) => GenericFormula + ) { + return Formula.step(this, start, formulaModifier); + } + + public if( + condition: Computable<boolean>, + formulaModifier: ( + value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula + ) => GenericFormula + ) { + return Formula.if(this, condition, formulaModifier); + } + public conditional( + condition: Computable<boolean>, + formulaModifier: ( + value: InvertibleFormula & IntegrableFormula & InvertibleIntegralFormula + ) => GenericFormula + ) { + return Formula.if(this, condition, formulaModifier); + } + + public abs() { + return Formula.abs(this); + } + + public neg<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public neg(this: GenericFormula): GenericFormula; + public neg(this: GenericFormula) { + return Formula.neg(this); + } + public negate<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public negate(this: GenericFormula): GenericFormula; + public negate(this: GenericFormula) { + return Formula.neg(this); + } + public negated<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public negated(this: GenericFormula): GenericFormula; + public negated(this: GenericFormula) { + return Formula.neg(this); + } + + public sign() { + return Formula.sign(this); + } + public sgn() { + return this.sign(); + } + + public round() { + return Formula.round(this); + } + + public floor() { + return Formula.floor(this); + } + + public ceil() { + return Formula.ceil(this); + } + + public trunc() { + return Formula.trunc(this); + } + + public add<T extends GenericFormula>(this: T, value: FormulaSource): T; + public add<T extends GenericFormula>(this: GenericFormula, value: T): T; + public add(this: GenericFormula, value: FormulaSource): GenericFormula; + public add(this: GenericFormula, value: FormulaSource) { + return Formula.add(this, value); + } + public plus<T extends GenericFormula>(this: T, value: FormulaSource): T; + public plus<T extends GenericFormula>(this: GenericFormula, value: T): T; + public plus(this: GenericFormula, value: FormulaSource): GenericFormula; + public plus(value: FormulaSource) { + return Formula.add(this, value); + } + + public sub<T extends GenericFormula>(this: T, value: FormulaSource): T; + public sub<T extends GenericFormula>(this: GenericFormula, value: T): T; + public sub(this: GenericFormula, value: FormulaSource): GenericFormula; + public sub(value: FormulaSource) { + return Formula.sub(this, value); + } + public subtract<T extends GenericFormula>(this: T, value: FormulaSource): T; + public subtract<T extends GenericFormula>(this: GenericFormula, value: T): T; + public subtract(this: GenericFormula, value: FormulaSource): GenericFormula; + public subtract(value: FormulaSource) { + return Formula.sub(this, value); + } + public minus<T extends GenericFormula>(this: T, value: FormulaSource): T; + public minus<T extends GenericFormula>(this: GenericFormula, value: T): T; + public minus(this: GenericFormula, value: FormulaSource): GenericFormula; + public minus(value: FormulaSource) { + return Formula.sub(this, value); + } + + public mul<T extends GenericFormula>(this: T, value: FormulaSource): T; + public mul<T extends GenericFormula>(this: GenericFormula, value: T): T; + public mul(this: GenericFormula, value: FormulaSource): GenericFormula; + public mul(value: FormulaSource) { + return Formula.mul(this, value); + } + public multiply<T extends GenericFormula>(this: T, value: FormulaSource): T; + public multiply<T extends GenericFormula>(this: GenericFormula, value: T): T; + public multiply(this: GenericFormula, value: FormulaSource): GenericFormula; + public multiply(value: FormulaSource) { + return Formula.mul(this, value); + } + public times<T extends GenericFormula>(this: T, value: FormulaSource): T; + public times<T extends GenericFormula>(this: GenericFormula, value: T): T; + public times(this: GenericFormula, value: FormulaSource): GenericFormula; + public times(value: FormulaSource) { + return Formula.mul(this, value); + } + + public div<T extends GenericFormula>(this: T, value: FormulaSource): T; + public div<T extends GenericFormula>(this: GenericFormula, value: T): T; + public div(this: GenericFormula, value: FormulaSource): GenericFormula; + public div(value: FormulaSource) { + return Formula.div(this, value); + } + public divide<T extends GenericFormula>(this: T, value: FormulaSource): T; + public divide<T extends GenericFormula>(this: GenericFormula, value: T): T; + public divide(this: GenericFormula, value: FormulaSource): GenericFormula; + public divide(value: FormulaSource) { + return Formula.div(this, value); + } + public divideBy<T extends GenericFormula>(this: T, value: FormulaSource): T; + public divideBy<T extends GenericFormula>(this: GenericFormula, value: T): T; + public divideBy(this: GenericFormula, value: FormulaSource): GenericFormula; + public divideBy(value: FormulaSource) { + return Formula.div(this, value); + } + public dividedBy<T extends GenericFormula>(this: T, value: FormulaSource): T; + public dividedBy<T extends GenericFormula>(this: GenericFormula, value: T): T; + public dividedBy(this: GenericFormula, value: FormulaSource): GenericFormula; + public dividedBy(value: FormulaSource) { + return Formula.div(this, value); + } + + public recip<T extends GenericFormula>(this: T): T; + public recip(this: FormulaSource): GenericFormula; + public recip() { + return Formula.recip(this); + } + public reciprocal<T extends GenericFormula>(this: T): T; + public reciprocal(this: FormulaSource): GenericFormula; + public reciprocal() { + return Formula.recip(this); + } + public reciprocate<T extends GenericFormula>(this: T): T; + public reciprocate(this: FormulaSource): GenericFormula; + public reciprocate() { + return Formula.recip(this); + } + + public max(value: FormulaSource) { + return Formula.max(this, value); + } + + public min(value: FormulaSource) { + return Formula.min(this, value); + } + + public maxabs(value: FormulaSource) { + return Formula.maxabs(this, value); + } + + public minabs(value: FormulaSource) { + return Formula.minabs(this, value); + } + + public clamp(min: FormulaSource, max: FormulaSource) { + return Formula.clamp(this, min, max); + } + + public clampMin(value: FormulaSource) { + return Formula.clampMin(this, value); + } + + public clampMax(value: FormulaSource) { + return Formula.clampMax(this, value); + } + + public pLog10() { + return Formula.pLog10(this); + } + + public absLog10() { + return Formula.absLog10(this); + } + + public log10<T extends GenericFormula>(this: T): T; + public log10(this: FormulaSource): GenericFormula; + public log10() { + return Formula.log10(this); + } + + public log<T extends GenericFormula>(this: T, value: FormulaSource): T; + public log<T extends GenericFormula>(this: FormulaSource, value: T): T; + public log(this: FormulaSource, value: FormulaSource): GenericFormula; + public log(value: FormulaSource) { + return Formula.log(this, value); + } + public logarithm<T extends GenericFormula>(this: T, value: FormulaSource): T; + public logarithm<T extends GenericFormula>(this: FormulaSource, value: T): T; + public logarithm(this: FormulaSource, value: FormulaSource): GenericFormula; + public logarithm(value: FormulaSource) { + return Formula.log(this, value); + } + + public log2<T extends GenericFormula>(this: T): T; + public log2(this: FormulaSource): GenericFormula; + public log2() { + return Formula.log2(this); + } + + public ln<T extends GenericFormula>(this: T): T; + public ln(this: FormulaSource): GenericFormula; + public ln() { + return Formula.ln(this); + } + + public pow<T extends GenericFormula>(this: T, value: FormulaSource): T; + public pow<T extends GenericFormula>(this: FormulaSource, value: T): T; + public pow(this: FormulaSource, value: FormulaSource): GenericFormula; + public pow(value: FormulaSource) { + return Formula.pow(this, value); + } + + public pow10<T extends GenericFormula>(this: T): T; + public pow10(this: FormulaSource): GenericFormula; + public pow10() { + return Formula.pow10(this); + } + + public pow_base<T extends GenericFormula>(this: T, value: FormulaSource): T; + public pow_base<T extends GenericFormula>(this: FormulaSource, value: T): T; + public pow_base(this: FormulaSource, value: FormulaSource): GenericFormula; + public pow_base(value: FormulaSource) { + return Formula.pow_base(this, value); + } + + public root<T extends GenericFormula>(this: T, value: FormulaSource): T; + public root<T extends GenericFormula>(this: FormulaSource, value: T): T; + public root(this: FormulaSource, value: FormulaSource): GenericFormula; + public root(value: FormulaSource) { + return Formula.root(this, value); + } + + public factorial() { + return Formula.factorial(this); + } + + public gamma() { + return Formula.gamma(this); + } + public lngamma() { + return Formula.lngamma(this); + } + + public exp<T extends GenericFormula>(this: T): Omit<T, "invertsIntegral">; + public exp(this: FormulaSource): GenericFormula; + public exp(this: FormulaSource) { + return Formula.exp(this); + } + + public sqr<T extends GenericFormula>(this: T): T; + public sqr(this: FormulaSource): GenericFormula; + public sqr() { + return Formula.pow(this, 2); + } + + public sqrt<T extends GenericFormula>(this: T): T; + public sqrt(this: FormulaSource): GenericFormula; + public sqrt() { + return Formula.root(this, 2); + } + public cube<T extends GenericFormula>(this: T): T; + public cube(this: FormulaSource): GenericFormula; + public cube() { + return Formula.pow(this, 3); + } + + public cbrt<T extends GenericFormula>(this: T): T; + public cbrt(this: FormulaSource): GenericFormula; + public cbrt() { + return Formula.root(this, 3); + } + + public tetrate<T extends GenericFormula>( + this: T, + height?: FormulaSource, + payload?: FormulaSource + ): Omit<T, "integrate" | "invertIntegral">; + public tetrate( + this: FormulaSource, + height?: FormulaSource, + payload?: FormulaSource + ): GenericFormula; + public tetrate( + this: FormulaSource, + height: FormulaSource = 2, + payload: FormulaSource = Decimal.fromComponents_noNormalize(1, 0, 1) + ) { + return Formula.tetrate(this, height, payload); + } + + public iteratedexp<T extends GenericFormula>( + this: T, + height?: FormulaSource, + payload?: FormulaSource + ): Omit<T, "integrate" | "invertIntegral">; + public iteratedexp( + this: FormulaSource, + height?: FormulaSource, + payload?: FormulaSource + ): GenericFormula; + public iteratedexp( + this: FormulaSource, + height: FormulaSource = 2, + payload: FormulaSource = Decimal.fromComponents_noNormalize(1, 0, 1) + ) { + return Formula.iteratedexp(this, height, payload); + } + + public iteratedlog(base: FormulaSource = 10, times: FormulaSource = 1) { + return Formula.iteratedlog(this, base, times); + } + + public slog<T extends GenericFormula>( + this: T, + base?: FormulaSource + ): Omit<T, "integrate" | "invertIntegral">; + public slog(this: FormulaSource, base?: FormulaSource): GenericFormula; + public slog(this: FormulaSource, base: FormulaSource = 10) { + return Formula.slog(this, base); + } + + public layeradd10(diff: FormulaSource) { + return Formula.layeradd10(this, diff); + } + + public layeradd<T extends GenericFormula>( + this: T, + diff: FormulaSource, + base?: FormulaSource + ): Omit<T, "integrate" | "invertIntegral">; + public layeradd(this: FormulaSource, diff: FormulaSource, base?: FormulaSource): GenericFormula; + public layeradd(this: FormulaSource, diff: FormulaSource, base: FormulaSource) { + return Formula.layeradd(this, diff, base); + } + + public lambertw<T extends GenericFormula>(this: T): Omit<T, "integrate" | "invertIntegral">; + public lambertw(this: FormulaSource): GenericFormula; + public lambertw(this: FormulaSource) { + return Formula.lambertw(this); + } + + public ssqrt<T extends GenericFormula>(this: T): Omit<T, "integrate" | "invertIntegral">; + public ssqrt(this: FormulaSource): GenericFormula; + public ssqrt(this: FormulaSource) { + return Formula.ssqrt(this); + } + + public pentate( + height: FormulaSource = 2, + payload: FormulaSource = Decimal.fromComponents_noNormalize(1, 0, 1) + ) { + return Formula.pentate(this, height, payload); + } + + public sin<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public sin(this: FormulaSource): GenericFormula; + public sin(this: FormulaSource) { + return Formula.sin(this); + } + + public cos<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public cos(this: FormulaSource): GenericFormula; + public cos(this: FormulaSource) { + return Formula.cos(this); + } + + public tan<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public tan(this: FormulaSource): GenericFormula; + public tan(this: FormulaSource) { + return Formula.tan(this); + } + + public asin<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public asin(this: FormulaSource): GenericFormula; + public asin(this: FormulaSource) { + return Formula.asin(this); + } + + public acos<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public acos(this: FormulaSource): GenericFormula; + public acos(this: FormulaSource) { + return Formula.acos(this); + } + + public atan<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public atan(this: FormulaSource): GenericFormula; + public atan(this: FormulaSource) { + return Formula.atan(this); + } + + public sinh<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public sinh(this: FormulaSource): GenericFormula; + public sinh(this: FormulaSource) { + return Formula.sinh(this); + } + + public cosh<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public cosh(this: FormulaSource): GenericFormula; + public cosh(this: FormulaSource) { + return Formula.cosh(this); + } + + public tanh<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public tanh(this: FormulaSource): GenericFormula; + public tanh(this: FormulaSource) { + return Formula.tanh(this); + } + + public asinh<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public asinh(this: FormulaSource): GenericFormula; + public asinh(this: FormulaSource) { + return Formula.asinh(this); + } + + public acosh<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public acosh(this: FormulaSource): GenericFormula; + public acosh(this: FormulaSource) { + return Formula.acosh(this); + } + + public atanh<T extends GenericFormula>(this: T): Omit<T, "invertIntegral">; + public atanh(this: FormulaSource): GenericFormula; + public atanh(this: FormulaSource) { + return Formula.atanh(this); + } +} + +/** + * Utility for calculating the maximum amount of purchases possible with a given formula and resource. If {@ref spendResources} is changed to false, the calculation will be much faster with higher numbers. + * @param formula The formula to use for calculating buy max from + * @param resource The resource used when purchasing (is only read from) + * @param spendResources Whether or not to count spent resources on each purchase or not + */ +export function calculateMaxAffordable( + formula: InvertibleFormula, + resource: Resource, + spendResources?: true +): ComputedRef<DecimalSource>; +export function calculateMaxAffordable( + formula: InvertibleIntegralFormula, + resource: Resource, + spendResources: Computable<boolean> +): ComputedRef<DecimalSource>; +export function calculateMaxAffordable( + formula: InvertibleFormula, + resource: Resource, + spendResources: Computable<boolean> = true +) { + const computedSpendResources = convertComputable(spendResources); + return computed(() => { + if (unref(computedSpendResources)) { + if (!formula.isIntegrable() || !formula.isIntegralInvertible()) { + throw "Cannot calculate max affordable of formula with non-invertible integral"; + } + return Decimal.floor( + formula.invertIntegral(Decimal.add(resource.value, formula.evaluateIntegral())) + ).sub(unref(formula.innermostVariable) ?? 0); + } else { + if (!formula.isInvertible()) { + throw "Cannot calculate max affordable of non-invertible formula"; + } + return Decimal.floor((formula as InvertibleFormula).invert(resource.value)); + } + }); +} + +/** + * Utility for calculating the cost of a formula for a given amount of purchases. If {@ref spendResources} is changed to false, the calculation will be much faster with higher numbers. + * @param formula The formula to use for calculating buy max from + * @param amountToBuy The amount of purchases to calculate the cost for + * @param spendResources Whether or not to count spent resources on each purchase or not + */ +export function calculateCost( + formula: InvertibleFormula, + amountToBuy: DecimalSource, + spendResources?: true +): DecimalSource; +export function calculateCost( + formula: InvertibleIntegralFormula, + amountToBuy: DecimalSource, + spendResources: boolean +): DecimalSource; +export function calculateCost( + formula: InvertibleFormula, + amountToBuy: DecimalSource, + spendResources = true +) { + const newValue = Decimal.add(amountToBuy, unref(formula.innermostVariable) ?? 0); + if (spendResources) { + return Decimal.sub(formula.evaluateIntegral(newValue), formula.evaluateIntegral()); + } else { + return formula.evaluate(newValue); + } +} diff --git a/src/game/gameLoop.ts b/src/game/gameLoop.ts new file mode 100644 index 0000000..b001dd6 --- /dev/null +++ b/src/game/gameLoop.ts @@ -0,0 +1,109 @@ +import projInfo from "data/projInfo.json"; +import { globalBus } from "game/events"; +import settings from "game/settings"; +import Decimal from "util/bignum"; +import { loadingSave } from "util/save"; +import type { Ref } from "vue"; +import { watch } from "vue"; +import player from "./player"; +import state from "./state"; + +let intervalID: NodeJS.Timer | null = null; + +// Not imported immediately due to dependency cycles +// This gets set during startGameLoop(), and will only be used in the update function +let hasWon: null | Ref<boolean> = null; + +function update() { + const now = Date.now(); + let diff = (now - player.time) / 1e3; + player.time = now; + const trueDiff = diff; + + state.lastTenTicks.push(trueDiff); + if (state.lastTenTicks.length > 10) { + state.lastTenTicks = state.lastTenTicks.slice(1); + } + + // Stop here if the game is paused on the win screen + if (hasWon?.value && !player.keepGoing) { + return; + } + // Stop here if the player had a NaN value + if (state.hasNaN) { + return; + } + + diff = Math.max(diff, 0); + + if (player.devSpeed === 0) { + return; + } + + loadingSave.value = false; + + // Add offline time if any + if (player.offlineTime != undefined) { + if (Decimal.gt(player.offlineTime, projInfo.offlineLimit * 3600)) { + player.offlineTime = projInfo.offlineLimit * 3600; + } + if (Decimal.gt(player.offlineTime, 0) && player.devSpeed !== 0) { + const offlineDiff = Math.max(player.offlineTime / 10, diff); + player.offlineTime = player.offlineTime - offlineDiff; + diff += offlineDiff; + } else if (player.devSpeed === 0) { + player.offlineTime += diff; + } + if (!player.offlineProd || Decimal.lt(player.offlineTime, 0)) { + player.offlineTime = null; + } + } + + // Cap at max tick length + diff = Math.min(diff, projInfo.maxTickLength); + + // Apply dev speed + if (player.devSpeed != undefined) { + diff *= player.devSpeed; + } + + if (!Number.isFinite(diff)) { + diff = 1e308; + } + + // Update + if (Decimal.eq(diff, 0)) { + return; + } + + player.timePlayed += diff; + if (!Number.isFinite(player.timePlayed)) { + player.timePlayed = 1e308; + } + globalBus.emit("update", diff, trueDiff); + + if (settings.unthrottled) { + requestAnimationFrame(update); + if (intervalID != null) { + clearInterval(intervalID); + intervalID = null; + } + } else if (intervalID == null) { + intervalID = setInterval(update, 50); + } +} + +/** Starts the game loop for the project, which updates the game in ticks. */ +export async function startGameLoop() { + hasWon = (await import("data/projEntry")).hasWon; + watch(hasWon, hasWon => { + if (hasWon) { + globalBus.emit("gameWon"); + } + }); + if (settings.unthrottled) { + requestAnimationFrame(update); + } else { + intervalID = setInterval(update, 50); + } +} diff --git a/src/game/layers.tsx b/src/game/layers.tsx new file mode 100644 index 0000000..c689235 --- /dev/null +++ b/src/game/layers.tsx @@ -0,0 +1,374 @@ +import Modal from "components/Modal.vue"; +import type { + CoercableComponent, + JSXFunction, + OptionsFunc, + Replace, + StyleValue +} from "features/feature"; +import { jsx, setDefault } from "features/feature"; +import { globalBus } from "game/events"; +import type { Persistent } from "game/persistence"; +import { persistent } from "game/persistence"; +import player from "game/player"; +import type { Emitter } from "nanoevents"; +import { createNanoEvents } from "nanoevents"; +import type { + Computable, + GetComputableType, + GetComputableTypeWithDefault, + ProcessedComputable +} from "util/computed"; +import { processComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { computed, InjectionKey, Ref } from "vue"; +import { ref, shallowReactive, unref } from "vue"; + +/** A feature's node in the DOM that has its size tracked. */ +export interface FeatureNode { + rect: DOMRect; + observer: MutationObserver; + element: HTMLElement; +} + +/** + * An injection key that a {@link ContextComponent} will use to provide a function that registers a {@link FeatureNode} with the given id and HTML element. + */ +export const RegisterNodeInjectionKey: InjectionKey<(id: string, element: HTMLElement) => void> = + Symbol("RegisterNode"); +/** + * An injection key that a {@link ContextComponent} will use to provide a function that unregisters a {@link FeatureNode} with the given id. + */ +export const UnregisterNodeInjectionKey: InjectionKey<(id: string) => void> = + Symbol("UnregisterNode"); +/** + * An injection key that a {@link ContextComponent} will use to provide a ref to a map of all currently registered {@link FeatureNode}s. + */ +export const NodesInjectionKey: InjectionKey<Ref<Record<string, FeatureNode | undefined>>> = + Symbol("Nodes"); +/** + * An injection key that a {@link ContextComponent} will use to provide a ref to a bounding rect of the Context. + */ +export const BoundsInjectionKey: InjectionKey<Ref<DOMRect | undefined>> = Symbol("Bounds"); + +/** All types of events able to be sent or emitted from a layer's emitter. */ +export interface LayerEvents { + /** + * Sent every game tick, before the update event. Intended for "generation" type actions. + * @param diff The delta time since last tick, in ms. + */ + preUpdate: (diff: number) => void; + /** + * Sent every game tick. Intended for "automation" type actions. + * @param diff The delta time since last tick, in ms. + */ + update: (diff: number) => void; + /** + * Sent every game tick, after the update event. Intended for checking state. + * @param diff The delta time since last tick, in ms. + */ + postUpdate: (diff: number) => void; +} + +/** + * A reference to all the current layers. + * It is shallow reactive so it will update when layers are added or removed, but not interfere with the existing refs within each layer. + */ +export const layers: Record<string, Readonly<GenericLayer> | undefined> = shallowReactive({}); + +declare global { + /** Augment the window object so the layers can be accessed from the console. */ + interface Window { + layers: Record<string, Readonly<GenericLayer> | undefined>; + } +} +window.layers = layers; + +declare module "@vue/runtime-dom" { + /** Augment CSS Properties to allow for setting the layer color CSS variable. */ + interface CSSProperties { + "--layer-color"?: string; + } +} + +/** An object representing the position of some entity. */ +export interface Position { + /** The X component of the entity's position. */ + x: number; + /** The Y component of the entity's position. */ + y: number; +} + +/** + * An object that configures a {@link Layer}. + * Even moreso than features, the developer is expected to include extra properties in this object. + * All {@link game/persistence.Persistent} refs must be included somewhere within the layer object. + */ +export interface LayerOptions { + /** The color of the layer, used to theme the entire layer's display. */ + color?: Computable<string>; + /** + * The layout of this layer's features. + * When the layer is open in {@link game/player.PlayerData.tabs}, this is the content that is displayed. + */ + display: Computable<CoercableComponent>; + /** An object of classes that should be applied to the display. */ + classes?: Computable<Record<string, boolean>>; + /** Styles that should be applied to the display. */ + style?: Computable<StyleValue>; + /** + * The name of the layer, used on minimized tabs. + * Defaults to {@link BaseLayer.id}. + */ + name?: Computable<string>; + /** + * Whether or not the layer can be minimized. + * Defaults to true. + */ + minimizable?: Computable<boolean>; + /** + * The layout of this layer's features. + * When the layer is open in {@link game/player.PlayerData.tabs}, but the tab is {@link Layer.minimized} this is the content that is displayed. + */ + minimizedDisplay?: Computable<CoercableComponent>; + /** + * Whether or not to force the go back button to be hidden. + * If true, go back will be hidden regardless of {@link data/projInfo.allowGoBack}. + */ + forceHideGoBack?: Computable<boolean>; + /** + * A CSS min-width value that is applied to the layer. + * Can be a number, in which case the unit is assumed to be px. + * Defaults to 600px. + */ + minWidth?: Computable<number | string>; +} + +/** The properties that are added onto a processed {@link LayerOptions} to create a {@link Layer} */ +export interface BaseLayer { + /** + * The ID of the layer. + * Populated from the {@link createLayer} parameters. + * Used for saving and tracking open tabs. + */ + id: string; + /** A persistent ref tracking if the tab is minimized or not. */ + minimized: Persistent<boolean>; + /** An emitter for sending {@link LayerEvents} events for this layer. */ + emitter: Emitter<LayerEvents>; + /** A function to register an event listener on {@link emitter}. */ + on: OmitThisParameter<Emitter<LayerEvents>["on"]>; + /** A function to emit a {@link LayerEvents} event to this layer. */ + emit: <K extends keyof LayerEvents>(...args: [K, ...Parameters<LayerEvents[K]>]) => void; + /** A map of {@link FeatureNode}s present in this layer's {@link ContextComponent} component. */ + nodes: Ref<Record<string, FeatureNode | undefined>>; +} + +/** An unit of game content. Displayed to the user as a tab or modal. */ +export type Layer<T extends LayerOptions> = Replace< + T & BaseLayer, + { + color: GetComputableType<T["color"]>; + display: GetComputableType<T["display"]>; + classes: GetComputableType<T["classes"]>; + style: GetComputableType<T["style"]>; + name: GetComputableTypeWithDefault<T["name"], string>; + minWidth: GetComputableTypeWithDefault<T["minWidth"], 600>; + minimizable: GetComputableTypeWithDefault<T["minimizable"], true>; + minimizedDisplay: GetComputableType<T["minimizedDisplay"]>; + forceHideGoBack: GetComputableType<T["forceHideGoBack"]>; + } +>; + +/** A type that matches any valid {@link Layer} object. */ +export type GenericLayer = Replace< + Layer<LayerOptions>, + { + name: ProcessedComputable<string>; + minWidth: ProcessedComputable<number>; + minimizable: ProcessedComputable<boolean>; + } +>; + +/** + * When creating layers, this object a map of layer ID to a set of any created persistent refs in order to check they're all included in the final layer object. + */ +export const persistentRefs: Record<string, Set<Persistent>> = {}; +/** + * When creating layers, this array stores the layers currently being created, as a stack. + */ +export const addingLayers: string[] = []; +/** + * Lazily creates a layer with the given options. + * @param id The ID this layer will have. See {@link BaseLayer.id}. + * @param optionsFunc Layer options. + */ +export function createLayer<T extends LayerOptions>( + id: string, + optionsFunc: OptionsFunc<T, BaseLayer> +): Layer<T> { + return createLazyProxy(() => { + const layer = {} as T & Partial<BaseLayer>; + const emitter = (layer.emitter = createNanoEvents<LayerEvents>()); + layer.on = emitter.on.bind(emitter); + layer.emit = emitter.emit.bind(emitter) as <K extends keyof LayerEvents>( + ...args: [K, ...Parameters<LayerEvents[K]>] + ) => void; + layer.nodes = ref({}); + layer.id = id; + + addingLayers.push(id); + persistentRefs[id] = new Set(); + layer.minimized = persistent(false); + Object.assign(layer, optionsFunc.call(layer as BaseLayer)); + if ( + addingLayers[addingLayers.length - 1] == null || + addingLayers[addingLayers.length - 1] !== id + ) { + throw `Adding layers stack in invalid state. This should not happen\nStack: ${addingLayers}\nTrying to pop ${layer.id}`; + } + addingLayers.pop(); + + processComputable(layer as T, "color"); + processComputable(layer as T, "display"); + processComputable(layer as T, "classes"); + processComputable(layer as T, "style"); + processComputable(layer as T, "name"); + setDefault(layer, "name", layer.id); + processComputable(layer as T, "minWidth"); + setDefault(layer, "minWidth", 600); + processComputable(layer as T, "minimizable"); + setDefault(layer, "minimizable", true); + processComputable(layer as T, "minimizedDisplay"); + + const style = layer.style as ProcessedComputable<StyleValue> | undefined; + layer.style = computed(() => { + let width = unref(layer.minWidth as ProcessedComputable<number | string>); + if (typeof width === "number" || !Number.isNaN(parseInt(width))) { + width = width + "px"; + } + return [ + unref(style) ?? "", + layer.minimized?.value + ? { + flexGrow: "0", + flexShrink: "0", + width: "60px", + minWidth: "", + flexBasis: "", + margin: "0" + } + : { + flexGrow: "", + flexShrink: "", + width: "", + minWidth: width, + flexBasis: width, + margin: "" + } + ]; + }) as Ref<StyleValue>; + + return layer as unknown as Layer<T>; + }); +} + +/** + * Enables a layer object, so it will be updated every tick. + * Note that accessing a layer/its properties does NOT require it to be enabled. + * For dynamic layers you can call this function and {@link removeLayer} as necessary. Just make sure {@link data/projEntry.getInitialLayers} will provide an accurate list of layers based on the player data object. + * For static layers just make {@link data/projEntry.getInitialLayers} return all the layers. + * @param layer The layer to add. + * @param player The player data object, which will have a data object for this layer. + */ +export function addLayer( + layer: GenericLayer, + player: { layers?: Record<string, Record<string, unknown>> } +): void { + console.info("Adding layer", layer.id); + if (layers[layer.id]) { + console.error( + "Attempted to add layer with same ID as existing layer", + layer.id, + layers[layer.id] + ); + return; + } + + setDefault(player, "layers", {}); + if (player.layers[layer.id] == null) { + player.layers[layer.id] = {}; + } + layers[layer.id] = layer; + + globalBus.emit("addLayer", layer, player.layers[layer.id]); +} + +/** + * Convenience method for getting a layer by its ID with correct typing. + * @param layerID The ID of the layer to get. + */ +export function getLayer<T extends GenericLayer>(layerID: string): T { + return layers[layerID] as T; +} + +/** + * Disables a layer, so it will no longer be updated every tick. + * Note that accessing a layer/its properties does NOT require it to be enabled. + * @param layer The layer to remove. + */ +export function removeLayer(layer: GenericLayer): void { + console.info("Removing layer", layer.id); + globalBus.emit("removeLayer", layer); + + layers[layer.id] = undefined; +} + +/** + * Convenience method for removing and immediately re-adding a layer. + * This is useful for layers with dynamic content, to ensure persistent refs are correctly configured. + * @param layer Layer to remove and then re-add + */ +export function reloadLayer(layer: GenericLayer): void { + removeLayer(layer); + + // Re-create layer + addLayer(layer, player); +} + +/** + * Utility function for creating a modal that display's a {@link LayerOptions.display}. + * Returns the modal itself, which can be rendered anywhere you need, as well as a function to open the modal. + * @param layer The layer to display in the modal. + */ +export function setupLayerModal(layer: GenericLayer): { + openModal: VoidFunction; + modal: JSXFunction; +} { + const showModal = ref(false); + return { + openModal: () => (showModal.value = true), + modal: jsx(() => ( + <Modal + modelValue={showModal.value} + onUpdate:modelValue={value => (showModal.value = value)} + v-slots={{ + header: () => <h2>{unref(layer.name)}</h2>, + body: unref(layer.display) + }} + /> + )) + }; +} + +globalBus.on("update", function updateLayers(diff) { + Object.values(layers).forEach(layer => { + layer?.emit("preUpdate", diff); + }); + Object.values(layers).forEach(layer => { + layer?.emit("update", diff); + }); + Object.values(layers).forEach(layer => { + layer?.emit("postUpdate", diff); + }); +}); diff --git a/src/game/modifiers.tsx b/src/game/modifiers.tsx new file mode 100644 index 0000000..fd96c77 --- /dev/null +++ b/src/game/modifiers.tsx @@ -0,0 +1,365 @@ +import "components/common/modifiers.css"; +import type { CoercableComponent } from "features/feature"; +import { jsx } from "features/feature"; +import settings from "game/settings"; +import type { DecimalSource } from "util/bignum"; +import Decimal, { formatSmall } from "util/bignum"; +import type { WithRequired } from "util/common"; +import type { Computable, ProcessedComputable } from "util/computed"; +import { convertComputable } from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { renderJSX } from "util/vue"; +import { computed, unref } from "vue"; + +/** + * An object that can be used to apply or unapply some modification to a number. + * Being reversible requires the operation being invertible, but some features may rely on that. + * Descriptions can be optionally included for displaying them to the player. + * The built-in modifier creators are designed to display the modifiers using {@link createModifierSection}. + */ +export interface Modifier { + /** Applies some operation on the input and returns the result. */ + apply: (gain: DecimalSource) => DecimalSource; + /** Reverses the operation applied by the apply property. Required by some features. */ + revert?: (gain: DecimalSource) => DecimalSource; + /** + * Whether or not this modifier should be considered enabled. + * Typically for use with modifiers passed into {@link createSequentialModifier}. + */ + enabled?: ProcessedComputable<boolean>; + /** + * A description of this modifier. + * @see {@link createModifierSection}. + */ + description?: ProcessedComputable<CoercableComponent>; +} + +/** + * Utility type used to narrow down a modifier type that will have a description and/or enabled property based on optional parameters, T and S (respectively). + */ +export type ModifierFromOptionalParams<T, S> = T extends undefined + ? S extends undefined + ? Omit<WithRequired<Modifier, "revert">, "description" | "enabled"> + : Omit<WithRequired<Modifier, "revert" | "enabled">, "description"> + : S extends undefined + ? Omit<WithRequired<Modifier, "revert" | "description">, "enabled"> + : WithRequired<Modifier, "revert" | "enabled" | "description">; + +/** An object that configures an additive modifier via {@link createAdditiveModifier}. */ +export interface AdditiveModifierOptions { + /** The amount to add to the input value. */ + addend: Computable<DecimalSource>; + /** Description of what this modifier is doing. */ + description?: Computable<CoercableComponent> | undefined; + /** A computable that will be processed and passed directly into the returned modifier. */ + enabled?: Computable<boolean> | undefined; + /** Determines if numbers larger or smaller than 0 should be displayed as red. */ + smallerIsBetter?: boolean; +} + +/** + * Create a modifier that adds some value to the input value. + * @param optionsFunc Additive modifier options. + */ +export function createAdditiveModifier<T extends AdditiveModifierOptions>( + optionsFunc: () => T +): ModifierFromOptionalParams<T["description"], T["enabled"]> { + return createLazyProxy(() => { + const { addend, description, enabled, smallerIsBetter } = optionsFunc(); + + const processedAddend = convertComputable(addend); + const processedDescription = convertComputable(description); + const processedEnabled = enabled == null ? undefined : convertComputable(enabled); + return { + apply: (gain: DecimalSource) => Decimal.add(gain, unref(processedAddend)), + revert: (gain: DecimalSource) => Decimal.sub(gain, unref(processedAddend)), + enabled: processedEnabled, + description: + description == null + ? undefined + : jsx(() => ( + <div class="modifier-container"> + {unref(processedDescription) != null ? ( + <span class="modifier-description"> + {/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */} + {renderJSX(unref(processedDescription)!)} + </span> + ) : null} + <span + class="modifier-amount" + style={ + ( + smallerIsBetter === true + ? Decimal.gt(unref(processedAddend), 0) + : Decimal.lt(unref(processedAddend), 0) + ) + ? "color: var(--danger)" + : "" + } + > + {Decimal.gte(unref(processedAddend), 0) ? "+" : ""} + {formatSmall(unref(processedAddend))} + </span> + </div> + )) + }; + }) as unknown as ModifierFromOptionalParams<T["description"], T["enabled"]>; +} + +/** An object that configures an multiplicative modifier via {@link createMultiplicativeModifier}. */ +export interface MultiplicativeModifierOptions { + /** The amount to multiply the input value by. */ + multiplier: Computable<DecimalSource>; + /** Description of what this modifier is doing. */ + description?: Computable<CoercableComponent> | undefined; + /** A computable that will be processed and passed directly into the returned modifier. */ + enabled?: Computable<boolean> | undefined; + /** Determines if numbers larger or smaller than 1 should be displayed as red. */ + smallerIsBetter?: boolean; +} + +/** + * Create a modifier that multiplies the input value by some value. + * @param optionsFunc Multiplicative modifier options. + */ +export function createMultiplicativeModifier<T extends MultiplicativeModifierOptions>( + optionsFunc: () => T +): ModifierFromOptionalParams<T["description"], T["enabled"]> { + return createLazyProxy(() => { + const { multiplier, description, enabled, smallerIsBetter } = optionsFunc(); + + const processedMultiplier = convertComputable(multiplier); + const processedDescription = convertComputable(description); + const processedEnabled = enabled == null ? undefined : convertComputable(enabled); + return { + apply: (gain: DecimalSource) => Decimal.times(gain, unref(processedMultiplier)), + revert: (gain: DecimalSource) => Decimal.div(gain, unref(processedMultiplier)), + enabled: processedEnabled, + description: + description == null + ? undefined + : jsx(() => ( + <div class="modifier-container"> + {unref(processedDescription) != null ? ( + <span class="modifier-description"> + {/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */} + {renderJSX(unref(processedDescription)!)} + </span> + ) : null} + <span + class="modifier-amount" + style={ + ( + smallerIsBetter === true + ? Decimal.gt(unref(processedMultiplier), 1) + : Decimal.lt(unref(processedMultiplier), 1) + ) + ? "color: var(--danger)" + : "" + } + > + ×{formatSmall(unref(processedMultiplier))} + </span> + </div> + )) + }; + }) as unknown as ModifierFromOptionalParams<T["description"], T["enabled"]>; +} + +/** An object that configures an exponential modifier via {@link createExponentialModifier}. */ +export interface ExponentialModifierOptions { + /** The amount to raise the input value to the power of. */ + exponent: Computable<DecimalSource>; + /** Description of what this modifier is doing. */ + description?: Computable<CoercableComponent> | undefined; + /** A computable that will be processed and passed directly into the returned modifier. */ + enabled?: Computable<boolean> | undefined; + /** Add 1 before calculating, then remove it afterwards. This prevents low numbers from becoming lower. */ + supportLowNumbers?: boolean; + /** Determines if numbers larger or smaller than 1 should be displayed as red. */ + smallerIsBetter?: boolean; +} + +/** + * Create a modifier that raises the input value to the power of some value. + * @param optionsFunc Exponential modifier options. + */ +export function createExponentialModifier<T extends ExponentialModifierOptions>( + optionsFunc: () => T +): ModifierFromOptionalParams<T["description"], T["enabled"]> { + return createLazyProxy(() => { + const { exponent, description, enabled, supportLowNumbers, smallerIsBetter } = + optionsFunc(); + + const processedExponent = convertComputable(exponent); + const processedDescription = convertComputable(description); + const processedEnabled = enabled == null ? undefined : convertComputable(enabled); + return { + apply: (gain: DecimalSource) => { + let result = gain; + if (supportLowNumbers) { + result = Decimal.add(result, 1); + } + result = Decimal.pow(result, unref(processedExponent)); + if (supportLowNumbers) { + result = Decimal.sub(result, 1); + } + return result; + }, + revert: (gain: DecimalSource) => { + let result = gain; + if (supportLowNumbers) { + result = Decimal.add(result, 1); + } + result = Decimal.root(result, unref(processedExponent)); + if (supportLowNumbers) { + result = Decimal.sub(result, 1); + } + return result; + }, + enabled: processedEnabled, + description: + description == null + ? undefined + : jsx(() => ( + <div class="modifier-container"> + {unref(processedDescription) != null ? ( + <span class="modifier-description"> + {/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */} + {renderJSX(unref(processedDescription)!)} + {supportLowNumbers ? " (+1 effective)" : null} + </span> + ) : null} + <span + class="modifier-amount" + style={ + ( + smallerIsBetter === true + ? Decimal.gt(unref(processedExponent), 1) + : Decimal.lt(unref(processedExponent), 1) + ) + ? "color: var(--danger)" + : "" + } + > + ^{formatSmall(unref(processedExponent))} + </span> + </div> + )) + }; + }) as unknown as ModifierFromOptionalParams<T["description"], T["enabled"]>; +} + +/** + * Takes an array of modifiers and applies and reverses them in order. + * Modifiers that are not enabled will not be applied nor reversed. + * Also joins their descriptions together. + * @param modifiersFunc The modifiers to perform sequentially. + * @see {@link createModifierSection}. + */ +export function createSequentialModifier< + T extends Modifier[], + S = T extends WithRequired<Modifier, "revert">[] + ? WithRequired<Modifier, "description" | "revert"> + : Omit<WithRequired<Modifier, "description">, "revert"> +>(modifiersFunc: () => T): S { + return createLazyProxy(() => { + const modifiers = modifiersFunc(); + + return { + apply: (gain: DecimalSource) => + modifiers + .filter(m => unref(m.enabled) !== false) + .reduce((gain, modifier) => modifier.apply(gain), gain), + revert: modifiers.every(m => m.revert != null) + ? (gain: DecimalSource) => + modifiers + .filter(m => unref(m.enabled) !== false) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + .reduceRight((gain, modifier) => modifier.revert!(gain), gain) + : undefined, + enabled: computed(() => modifiers.filter(m => unref(m.enabled) !== false).length > 0), + description: jsx(() => ( + <> + {( + modifiers + .filter(m => unref(m.enabled) !== false) + .map(m => unref(m.description)) + .filter(d => d) as CoercableComponent[] + ).map(renderJSX)} + </> + )) + }; + }) as unknown as S; +} + +/** An object that configures a modifier section via {@link createModifierSection}. */ +export interface ModifierSectionOptions { + /** The header for the section. */ + title: string; + /** Smaller text that appears in the header after the title. */ + subtitle?: string; + /** The modifier to render. */ + modifier: WithRequired<Modifier, "description">; + /** The base value that'll be passed into the modifier. Defaults to 1. */ + base?: DecimalSource; + /** The unit of the value being modified, if any. */ + unit?: string; + /** The label to use for the base value. Defaults to "Base". */ + baseText?: CoercableComponent; + /** Determines if numbers larger or smaller than the base should be displayed as red. */ + smallerIsBetter?: boolean; +} + +/** + * Create a JSX element that displays a modifier. + * Intended to be used with the output from {@link createSequentialModifier}. + * @param options Modifier section options. + */ +export function createModifierSection({ + title, + subtitle, + modifier, + base, + unit, + baseText, + smallerIsBetter +}: ModifierSectionOptions) { + const total = modifier.apply(base ?? 1); + return ( + <div style={{ "--unit": settings.alignUnits && unit != null ? "'" + unit + "'" : "" }}> + <h3> + {title} + {subtitle == null ? null : <span class="subtitle"> ({subtitle})</span>} + </h3> + <br /> + <div class="modifier-container"> + <span class="modifier-description">{renderJSX(baseText ?? "Base")}</span> + <span class="modifier-amount"> + {formatSmall(base ?? 1)} + {unit} + </span> + </div> + {renderJSX(unref(modifier.description))} + <hr /> + <div class="modifier-container"> + <span class="modifier-description">Total</span> + <span + class="modifier-amount" + style={ + ( + smallerIsBetter === true + ? Decimal.gt(total, base ?? 1) + : Decimal.lt(total, base ?? 1) + ) + ? "color: var(--danger)" + : "" + } + > + {formatSmall(total)} + {unit} + </span> + </div> + </div> + ); +} diff --git a/src/game/notifications.ts b/src/game/notifications.ts new file mode 100644 index 0000000..5a43c1a --- /dev/null +++ b/src/game/notifications.ts @@ -0,0 +1,55 @@ +import { globalBus } from "game/events"; +import { convertComputable } from "util/computed"; +import { trackHover, VueFeature } from "util/vue"; +import { nextTick, Ref } from "vue"; +import { ref, watch } from "vue"; +import Toast from "vue-toastification"; +import "vue-toastification/dist/index.css"; + +globalBus.on("setupVue", vue => vue.use(Toast)); + +/** + * Gives a {@link CSSProperties} object that makes an object glow, to bring focus to it. + * Default values are for a "soft" white notif effect. + * @param color The color of the glow effect. + * @param strength The strength of the glow effect - affects its spread. + */ +export function getNotifyStyle(color = "white", strength = "8px") { + return { + transform: "scale(1.05, 1.05)", + borderColor: "rgba(0, 0, 0, 0.125)", + boxShadow: `-4px -4px 4px rgba(0, 0, 0, 0.25) inset, 0 0 ${strength} ${color}`, + zIndex: 1 + }; +} + +/** Utility function to call {@link getNotifyStyle} with "high importance" parameters. */ +export function getHighNotifyStyle() { + return getNotifyStyle("red", "20px"); +} + +/** + * Create a boolean ref that will automatically be set based on the given condition, but also dismissed when hovering over a given element, typically the element where acting upon the notification would take place. + * @param element The element that will dismiss the notification on hover. + * @param shouldNotify A function or ref that determines if the notif should be active currently or not. + */ +export function createDismissableNotify( + element: VueFeature, + shouldNotify: Ref<boolean> | (() => boolean) +): Ref<boolean> { + const processedShouldNotify = convertComputable(shouldNotify) as Ref<boolean>; + const notifying = ref(false); + nextTick(() => { + notifying.value = processedShouldNotify.value; + + watch(trackHover(element), hovering => { + if (!hovering) { + notifying.value = false; + } + }); + watch(processedShouldNotify, shouldNotify => { + notifying.value = shouldNotify; + }); + }); + return notifying; +} diff --git a/src/game/persistence.ts b/src/game/persistence.ts new file mode 100644 index 0000000..9ad0634 --- /dev/null +++ b/src/game/persistence.ts @@ -0,0 +1,316 @@ +import { isArray } from "@vue/shared"; +import { globalBus } from "game/events"; +import type { GenericLayer } from "game/layers"; +import { addingLayers, persistentRefs } from "game/layers"; +import type { DecimalSource } from "util/bignum"; +import Decimal from "util/bignum"; +import { ProxyState } from "util/proxies"; +import type { Ref, WritableComputedRef } from "vue"; +import { computed, isReactive, isRef, ref } from "vue"; +import player from "./player"; +import state from "./state"; + +/** + * A symbol used in {@link Persistent} objects. + * @see {@link Persistent[PersistentState]} + */ +export const PersistentState = Symbol("PersistentState"); +/** + * A symbol used in {@link Persistent} objects. + * @see {@link Persistent[DefaultValue]} + */ +export const DefaultValue = Symbol("DefaultValue"); +/** + * A symbol used in {@link Persistent} objects. + * @see {@link Persistent[StackTrace]} + */ +export const StackTrace = Symbol("StackTrace"); +/** + * A symbol used in {@link Persistent} objects. + * @see {@link Persistent[Deleted]} + */ +export const Deleted = Symbol("Deleted"); +/** + * A symbol used in {@link Persistent} objects. + * @see {@link Persistent[NonPersistent]} + */ +export const NonPersistent = Symbol("NonPersistent"); +/** + * A symbol used in {@link Persistent} objects. + * @see {@link Persistent[SaveDataPath]} + */ +export const SaveDataPath = Symbol("SaveDataPath"); + +/** + * This is a union of things that should be safely stringifiable without needing special processes or knowing what to load them in as. + * - Decimals aren't allowed because we'd need to know to parse them back. + * - DecimalSources are allowed because the string is a valid value for them + */ +export type State = + | string + | number + | boolean + | DecimalSource + | { [key: string]: State } + | { [key: number]: State }; + +/** + * A {@link Ref} that has been augmented with properties to allow it to be saved and loaded within the player save data object. + */ +export type Persistent<T extends State = State> = Ref<T> & { + value: T; + /** A flag that this is a persistent property. Typically a circular reference. */ + [PersistentState]: Ref<T>; + /** The value the ref should be set to in a fresh save, or when updating an old save to the current version. */ + [DefaultValue]: T; + /** The stack trace of where the persistent ref was created. This is used for debugging purposes when a persistent ref is created but not placed in its layer object. */ + [StackTrace]: string; + /** + * This is a flag that can be set once the option func is evaluated, to mark that a persistent ref should _not_ be saved to the player save data object. + * @see {@link deletePersistent} for marking a persistent ref as deleted. + */ + [Deleted]: boolean; + /** + * A non-persistent ref that just reads and writes ot the persistent ref. Used for passing to other features without duplicating the persistent ref in the constructed save data object. + */ + [NonPersistent]: NonPersistent<T>; + /** + * The path this persistent appears in within the save data object. Predominantly used to ensure it's only placed in there one time. + */ + [SaveDataPath]: string[] | undefined; +}; + +export type NonPersistent<T extends State = State> = WritableComputedRef<T> & { [DefaultValue]: T }; + +function getStackTrace() { + return ( + new Error().stack + ?.split("\n") + .slice(3, 5) + .map(line => line.trim()) + .join("\n") ?? "" + ); +} + +function checkNaNAndWrite<T extends State>(persistent: Persistent<T>, value: T) { + // Decimal is smart enough to return false on things that aren't supposed to be numbers + if (Decimal.isNaN(value as DecimalSource)) { + if (!state.hasNaN) { + player.autosave = false; + state.hasNaN = true; + state.NaNPath = persistent[SaveDataPath]; + state.NaNPersistent = persistent as Persistent<DecimalSource>; + } + console.error( + `Attempted to save NaN value to`, + persistent[SaveDataPath]?.join("."), + persistent + ); + throw "Attempted to set NaN value. See above for details"; + } + persistent[PersistentState].value = value; +} + +/** + * Create a persistent ref, which can be saved and loaded. + * All (non-deleted) persistent refs must be included somewhere within the layer object returned by that layer's options func. + * @param defaultValue The value the persistent ref should start at on fresh saves or when reset. + */ +export function persistent<T extends State>(defaultValue: T | Ref<T>): Persistent<T> { + const persistentState: Ref<T> = isRef(defaultValue) + ? defaultValue + : (ref<T>(defaultValue) as Ref<T>); + + if (isRef(defaultValue)) { + defaultValue = defaultValue.value; + } + + const nonPersistent = computed({ + get() { + return persistentState.value; + }, + set(value) { + checkNaNAndWrite(persistent, value); + } + }) as NonPersistent<T>; + nonPersistent[DefaultValue] = defaultValue; + + // We're trying to mock a vue ref, which means the type expects a private [RefSymbol] property that we can't access, but the actual implementation of isRef just checks for `__v_isRef` + const persistent = { + get value() { + return persistentState.value as T; + }, + set value(value: T) { + checkNaNAndWrite(persistent, value); + }, + __v_isRef: true, + [PersistentState]: persistentState, + [DefaultValue]: defaultValue, + [StackTrace]: getStackTrace(), + [Deleted]: false, + [NonPersistent]: nonPersistent, + [SaveDataPath]: undefined + } as unknown as Persistent<T>; + + if (addingLayers.length === 0) { + console.warn( + "Creating a persistent ref outside of a layer. This is not officially supported", + persistent, + "\nCreated at:\n" + persistent[StackTrace] + ); + } else { + persistentRefs[addingLayers[addingLayers.length - 1]].add(persistent); + } + + return persistent; +} + +/** + * Type guard for whether an arbitrary value is a persistent ref + * @param value The value that may or may not be a persistent ref + */ +export function isPersistent(value: unknown): value is Persistent { + return value != null && typeof value === "object" && PersistentState in value; +} + +/** + * Unwraps the non-persistent ref inside of persistent refs, to be passed to other features without duplicating values in the save data object. + * @param persistent The persistent ref to unwrap + */ +export function noPersist<T extends Persistent<S>, S extends State>( + persistent: T +): T[typeof NonPersistent] { + return persistent[NonPersistent]; +} + +/** + * Mark a {@link Persistent} as deleted, so it won't be saved and loaded. + * Since persistent refs must be created during a layer's options func, features can not create persistent refs after evaluating their own options funcs. + * As a result, it must create any persistent refs it _might_ need. + * This function can then be called after the options func is evaluated to mark the persistent ref to not be saved or loaded. + */ +export function deletePersistent(persistent: Persistent) { + if (addingLayers.length === 0) { + console.warn("Deleting a persistent ref outside of a layer. Ignoring...", persistent); + } else { + persistentRefs[addingLayers[addingLayers.length - 1]].delete(persistent); + } + persistent[Deleted] = true; +} + +globalBus.on("addLayer", (layer: GenericLayer, saveData: Record<string, unknown>) => { + const features: { type: typeof Symbol }[] = []; + const handleObject = (obj: Record<string, unknown>, path: string[] = []): boolean => { + let foundPersistent = false; + Object.keys(obj).forEach(key => { + let value = obj[key]; + if (value != null && typeof value === "object") { + if (ProxyState in value) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + value = (value as any)[ProxyState] as object; + } + if (isPersistent(value)) { + foundPersistent = true; + if (value[Deleted]) { + console.warn( + "Deleted persistent ref present in returned object. Ignoring...", + value, + "\nCreated at:\n" + value[StackTrace] + ); + return; + } + persistentRefs[layer.id].delete(value); + + // Handle SaveDataPath + const newPath = [layer.id, ...path, key]; + if ( + value[SaveDataPath] != undefined && + JSON.stringify(newPath) !== JSON.stringify(value[SaveDataPath]) + ) { + console.error( + `Persistent ref is being saved to \`${newPath.join( + "." + )}\` when it's already present at \`${value[SaveDataPath].join( + "." + )}\`. This can cause unexpected behavior when loading saves between updates.`, + value + ); + } + value[SaveDataPath] = newPath; + + // Construct save path if it doesn't exist + const persistentState = path.reduce<Record<string, unknown>>((acc, curr) => { + if (!(curr in acc)) { + acc[curr] = {}; + } + return acc[curr] as Record<string, unknown>; + }, saveData); + + // Cache currently saved value + const savedValue = persistentState[key]; + // Add ref to save data + persistentState[key] = value[PersistentState]; + // Load previously saved value + if (isReactive(persistentState)) { + if (savedValue != null) { + persistentState[key] = savedValue; + } else { + persistentState[key] = value[DefaultValue]; + } + } else { + if (savedValue != null) { + (persistentState[key] as Ref<unknown>).value = savedValue; + } else { + (persistentState[key] as Ref<unknown>).value = value[DefaultValue]; + } + } + } else if ( + !(value instanceof Decimal) && + !isRef(value) && + // eslint-disable-next-line @typescript-eslint/no-explicit-any + !features.includes(value as { type: typeof Symbol }) + ) { + if (typeof (value as { type: typeof Symbol }).type === "symbol") { + features.push(value as { type: typeof Symbol }); + } + + // Continue traversing + const foundPersistentInChild = handleObject(value as Record<string, unknown>, [ + ...path, + key + ]); + + // Show warning for persistent values inside arrays + // TODO handle arrays better + if (foundPersistentInChild) { + if (isArray(value) && !isArray(obj)) { + console.warn( + "Found array that contains persistent values when adding layer. Keep in mind changing the order of elements in the array will mess with existing player saves.", + ProxyState in obj + ? (obj as Record<PropertyKey, unknown>)[ProxyState] + : obj, + key + ); + } else { + foundPersistent = true; + } + } + } + } + }); + return foundPersistent; + }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + handleObject((layer as any)[ProxyState]); + persistentRefs[layer.id].forEach(persistent => { + if (persistent[Deleted]) { + return; + } + console.error( + `Created persistent ref in ${layer.id} without registering it to the layer! Make sure to include everything persistent in the returned object`, + persistent, + "\nCreated at:\n" + persistent[StackTrace] + ); + }); + persistentRefs[layer.id].clear(); +}); diff --git a/src/game/player.ts b/src/game/player.ts new file mode 100644 index 0000000..5d1142e --- /dev/null +++ b/src/game/player.ts @@ -0,0 +1,75 @@ +import type { Ref } from "vue"; +import { reactive, unref } from "vue"; + +/** The player save data object. */ +export interface Player { + /** The ID of this save. */ + id: string; + /** A multiplier for time passing. Set to 0 when the game is paused. */ + devSpeed: number | null; + /** The display name of this save. */ + name: string; + /** The open tabs. */ + tabs: Array<string>; + /** The current time this save was last opened at, in ms since the unix epoch. */ + time: number; + /** Whether or not to automatically save every couple of seconds and on tab close. */ + autosave: boolean; + /** Whether or not to apply offline time when loading this save. */ + offlineProd: boolean; + /** How much offline time has been accumulated and not yet processed. */ + offlineTime: number | null; + /** How long, in ms, this game has been played. */ + timePlayed: number; + /** Whether or not to continue playing after {@link data/projEntry.hasWon} is true. */ + keepGoing: boolean; + /** The ID of this project, to make sure saves aren't imported into the wrong project. */ + modID: string; + /** The version of the project this save was created by. Used for upgrading saves for new versions. */ + modVersion: string; + /** A dictionary of layer save data. */ + layers: Record<string, LayerData<unknown>>; +} + +/** A layer's save data. Automatically unwraps refs. */ +export type LayerData<T> = { + [P in keyof T]?: T[P] extends (infer U)[] + ? Record<string, LayerData<U>> + : T[P] extends Record<string, never> + ? never + : T[P] extends Ref<infer S> + ? S + : T[P] extends object + ? LayerData<T[P]> + : T[P]; +}; + +const player = reactive<Player>({ + id: "", + devSpeed: null, + name: "", + tabs: [], + time: -1, + autosave: true, + offlineProd: true, + offlineTime: null, + timePlayed: 0, + keepGoing: false, + modID: "", + modVersion: "", + layers: {} +}); + +export default window.player = player; + +/** Convert a player save data object into a JSON string. Unwraps refs. */ +export function stringifySave(player: Player): string { + return JSON.stringify(player, (key, value) => unref(value)); +} + +declare global { + /** Augment the window object so the player can be accessed from the console. */ + interface Window { + player: Player; + } +} diff --git a/src/game/requirements.tsx b/src/game/requirements.tsx new file mode 100644 index 0000000..9412e22 --- /dev/null +++ b/src/game/requirements.tsx @@ -0,0 +1,326 @@ +import { isArray } from "@vue/shared"; +import { CoercableComponent, isVisible, jsx, setDefault, Visibility } from "features/feature"; +import { displayResource, Resource } from "features/resources/resource"; +import Decimal, { DecimalSource } from "lib/break_eternity"; +import { + Computable, + convertComputable, + processComputable, + ProcessedComputable +} from "util/computed"; +import { createLazyProxy } from "util/proxies"; +import { joinJSX, renderJSX } from "util/vue"; +import { computed, unref } from "vue"; +import Formula, { + calculateCost, + calculateMaxAffordable, + GenericFormula, + InvertibleFormula +} from "./formulas"; +import { DefaultValue, Persistent } from "./persistence"; + +/** + * An object that can be used to describe a requirement to perform some purchase or other action. + * @see {@link createCostRequirement} + */ +export interface Requirement { + /** + * The display for this specific requirement. This is used for displays multiple requirements condensed. Required if {@link visibility} can be {@link Visibility.Visible}. + */ + partialDisplay?: (amount?: DecimalSource) => JSX.Element; + /** + * The display for this specific requirement. Required if {@link visibility} can be {@link Visibility.Visible}. + */ + display?: (amount?: DecimalSource) => JSX.Element; + /** + * Whether or not this requirement should be displayed in Vue Features. {@link displayRequirements} will respect this property. + */ + visibility: ProcessedComputable<Visibility.Visible | Visibility.None | boolean>; + /** + * Whether or not this requirement has been met. + */ + requirementMet: ProcessedComputable<DecimalSource | boolean>; + /** + * Whether or not this requirement will need to affect the game state when whatever is using this requirement gets triggered. + */ + requiresPay: ProcessedComputable<boolean>; + /** + * Whether or not this requirement can have multiple levels of requirements that can be met at once. Requirement is assumed to not have multiple levels if this property not present. + */ + canMaximize?: ProcessedComputable<boolean>; + /** + * Perform any effects to the game state that should happen when the requirement gets triggered. + * @param amount The amount of levels of requirements to pay for. + */ + pay?: (amount?: DecimalSource) => void; +} + +/** + * Utility type for accepting 1 or more {@link Requirement}s. + */ +export type Requirements = Requirement | Requirement[]; + +/** An object that configures a {@link Requirement} based on a resource cost. */ +export interface CostRequirementOptions { + /** + * The resource that will be checked for meeting the {@link cost}. + */ + resource: Resource; + /** + * The amount of {@link resource} that must be met for this requirement. You can pass a formula, in which case maximizing will work out of the box (assuming its invertible and, for more accurate calculations, its integral is invertible). If you don't pass a formula then you can still support maximizing by passing a custom {@link pay} function. + */ + cost: Computable<DecimalSource> | GenericFormula; + /** + * Pass-through to {@link Requirement.visibility}. + */ + visibility?: Computable<Visibility.Visible | Visibility.None | boolean>; + /** + * Pass-through to {@link Requirement.requiresPay}. If not set to false, the default {@link pay} function will remove {@link cost} from {@link resource}. + */ + requiresPay?: Computable<boolean>; + /** + * When calculating multiple levels to be handled at once, whether it should consider resources used for each level as spent. Setting this to false causes calculations to be faster with larger numbers and supports more math functions. + * @see {Formula} + */ + spendResources?: Computable<boolean>; + /** + * Pass-through to {@link Requirement.pay}. May be required for maximizing support. + * @see {@link cost} for restrictions on maximizing support. + */ + pay?: (amount?: DecimalSource) => void; +} + +export type CostRequirement = Requirement & CostRequirementOptions; + +/** + * Lazily creates a requirement with the given options, that is based on meeting an amount of a resource. + * @param optionsFunc Cost requirement options. + */ +export function createCostRequirement<T extends CostRequirementOptions>( + optionsFunc: () => T +): CostRequirement { + return createLazyProxy(() => { + const req = optionsFunc() as T & Partial<Requirement>; + + req.partialDisplay = amount => ( + <span + style={ + unref(req.requirementMet as ProcessedComputable<boolean>) + ? "" + : "color: var(--danger)" + } + > + {displayResource( + req.resource, + req.cost instanceof Formula + ? calculateCost( + req.cost, + amount ?? 1, + unref( + req.spendResources as ProcessedComputable<boolean> | undefined + ) ?? true + ) + : unref(req.cost as ProcessedComputable<DecimalSource>) + )}{" "} + {req.resource.displayName} + </span> + ); + req.display = amount => ( + <div> + {unref(req.requiresPay as ProcessedComputable<boolean>) ? "Costs: " : "Requires: "} + {displayResource( + req.resource, + req.cost instanceof Formula + ? calculateCost( + req.cost, + amount ?? 1, + unref( + req.spendResources as ProcessedComputable<boolean> | undefined + ) ?? true + ) + : unref(req.cost as ProcessedComputable<DecimalSource>) + )}{" "} + {req.resource.displayName} + </div> + ); + + processComputable(req as T, "visibility"); + setDefault(req, "visibility", Visibility.Visible); + processComputable(req as T, "cost"); + processComputable(req as T, "requiresPay"); + processComputable(req as T, "spendResources"); + setDefault(req, "requiresPay", true); + setDefault(req, "pay", function (amount?: DecimalSource) { + const cost = + req.cost instanceof Formula + ? calculateCost( + req.cost, + amount ?? 1, + unref(req.spendResources as ProcessedComputable<boolean> | undefined) ?? + true + ) + : unref(req.cost as ProcessedComputable<DecimalSource>); + req.resource.value = Decimal.sub(req.resource.value, cost).max(0); + }); + + req.canMaximize = req.cost instanceof Formula && req.cost.isInvertible(); + + if (req.canMaximize) { + req.requirementMet = calculateMaxAffordable( + req.cost as InvertibleFormula, + req.resource, + unref(req.spendResources as ProcessedComputable<boolean> | undefined) ?? true + ); + } else { + req.requirementMet = computed(() => { + if (req.cost instanceof Formula) { + return Decimal.gte(req.resource.value, req.cost.evaluate()); + } else { + return Decimal.gte( + req.resource.value, + unref(req.cost as ProcessedComputable<DecimalSource>) + ); + } + }); + } + + return req as CostRequirement; + }); +} + +/** + * Utility function for creating a requirement that a specified vue feature is visible + * @param feature The feature to check the visibility of + */ +export function createVisibilityRequirement(feature: { + visibility: ProcessedComputable<Visibility | boolean>; +}): Requirement { + return createLazyProxy(() => ({ + requirementMet: computed(() => isVisible(feature.visibility)), + visibility: Visibility.None, + requiresPay: false + })); +} + +/** + * Creates a requirement based on a true/false value + * @param requirement The boolean requirement to use + * @param display How to display this requirement to the user + */ +export function createBooleanRequirement( + requirement: Computable<boolean>, + display?: CoercableComponent +): Requirement { + return createLazyProxy(() => ({ + requirementMet: convertComputable(requirement), + partialDisplay: display == null ? undefined : jsx(() => renderJSX(display)), + display: display == null ? undefined : jsx(() => <>Req: {renderJSX(display)}</>), + visibility: display == null ? Visibility.None : Visibility.Visible, + requiresPay: false + })); +} + +/** + * Utility for checking if 1+ requirements are all met + * @param requirements The 1+ requirements to check + */ +export function requirementsMet(requirements: Requirements): boolean { + if (isArray(requirements)) { + return requirements.every(requirementsMet); + } + const reqsMet = unref(requirements.requirementMet); + return typeof reqsMet === "boolean" ? reqsMet : Decimal.gt(reqsMet, 0); +} + +/** + * Calculates the maximum number of levels that could be acquired with the current requirement states. True/false requirements will be counted as Infinity or 0. + * @param requirements The 1+ requirements to check + */ +export function maxRequirementsMet(requirements: Requirements): DecimalSource { + if (isArray(requirements)) { + return requirements.map(maxRequirementsMet).reduce(Decimal.min); + } + const reqsMet = unref(requirements.requirementMet); + if (typeof reqsMet === "boolean") { + return reqsMet ? Infinity : 0; + } else if (Decimal.gt(reqsMet, 1) && unref(requirements.canMaximize) !== true) { + return 1; + } + return reqsMet; +} + +/** + * Utility function for display 1+ requirements compactly. + * @param requirements The 1+ requirements to display + * @param amount The amount of levels earned to be displayed + */ +export function displayRequirements(requirements: Requirements, amount: DecimalSource = 1) { + if (isArray(requirements)) { + requirements = requirements.filter(r => isVisible(r.visibility)); + if (requirements.length === 1) { + requirements = requirements[0]; + } + } + if (isArray(requirements)) { + requirements = requirements.filter(r => "partialDisplay" in r); + const withCosts = requirements.filter(r => unref(r.requiresPay)); + const withoutCosts = requirements.filter(r => !unref(r.requiresPay)); + return ( + <> + {withCosts.length > 0 ? ( + <div> + Costs:{" "} + {joinJSX( + withCosts.map(r => r.partialDisplay!(amount)), + <>, </> + )} + </div> + ) : null} + {withoutCosts.length > 0 ? ( + <div> + Requires:{" "} + {joinJSX( + withoutCosts.map(r => r.partialDisplay!(amount)), + <>, </> + )} + </div> + ) : null} + </> + ); + } + return requirements.display?.() ?? <></>; +} + +/** + * Utility function for paying the costs for 1+ requirements + * @param requirements The 1+ requirements to pay + * @param amount How many levels to pay for + */ +export function payRequirements(requirements: Requirements, amount: DecimalSource = 1) { + if (isArray(requirements)) { + requirements.filter(r => unref(r.requiresPay)).forEach(r => r.pay?.(amount)); + } else if (unref(requirements.requiresPay)) { + requirements.pay?.(amount); + } +} + +export function payByDivision(this: CostRequirement, amount?: DecimalSource) { + const cost = + this.cost instanceof Formula + ? calculateCost( + this.cost, + amount ?? 1, + unref(this.spendResources as ProcessedComputable<boolean> | undefined) ?? true + ) + : unref(this.cost as ProcessedComputable<DecimalSource>); + this.resource.value = Decimal.div(this.resource.value, cost); +} + +export function payByReset(overrideDefaultValue?: DecimalSource) { + return function (this: CostRequirement) { + this.resource.value = + overrideDefaultValue ?? + (this.resource as Resource & Persistent<DecimalSource>)[DefaultValue] ?? + 0; + }; +} diff --git a/src/game/settings.ts b/src/game/settings.ts new file mode 100644 index 0000000..0748d68 --- /dev/null +++ b/src/game/settings.ts @@ -0,0 +1,123 @@ +import projInfo from "data/projInfo.json"; +import { Themes } from "data/themes"; +import type { CoercableComponent } from "features/feature"; +import { globalBus } from "game/events"; +import LZString from "lz-string"; +import { hardReset } from "util/save"; +import { reactive, watch } from "vue"; + +/** The player's settings object. */ +export interface Settings { + /** The ID of the active save. */ + active: string; + /** The IDs of all created saves. */ + saves: string[]; + /** Whether or not to show the current ticks per second in the lower left corner of the page. */ + showTPS: boolean; + /** The current theme to display the game in. */ + theme: Themes; + /** Whether or not to cap the project at 20 ticks per second. */ + unthrottled: boolean; + /** Whether to align modifiers to the unit. */ + alignUnits: boolean; +} + +const state = reactive<Partial<Settings>>({ + active: "", + saves: [], + showTPS: true, + theme: Themes.Nordic, + unthrottled: false, + alignUnits: false +}); + +watch( + state, + state => { + const stringifiedSettings = LZString.compressToUTF16(JSON.stringify(state)); + localStorage.setItem(projInfo.id, stringifiedSettings); + }, + { deep: true } +); + +declare global { + /** + * Augment the window object so the settings, and hard resetting the settings, can be accessed from the console. + */ + interface Window { + settings: Settings; + hardResetSettings: VoidFunction; + } +} +/** + * The player settings object. Stores data that persists across all saves. + * Automatically saved to localStorage whenever changed. + */ +export default window.settings = state as Settings; +/** A function that erases all player settings, including all saves. */ +export const hardResetSettings = (window.hardResetSettings = () => { + const settings = { + active: "", + saves: [], + showTPS: true, + theme: Themes.Nordic, + alignUnits: false + }; + globalBus.emit("loadSettings", settings); + Object.assign(state, settings); + hardReset(); +}); + +/** + * Loads the player settings from localStorage. + * Calls the {@link GlobalEvents.loadSettings} event for custom properties to be included. + * Custom properties should be added by the file they relate to, so they won't be included if the file is tree shaken away. + * Custom properties should also register the field to modify said setting using {@link registerSettingField}. + */ +export function loadSettings(): void { + try { + let item: string | null = localStorage.getItem(projInfo.id); + if (item != null && item !== "") { + if (item[0] === "{") { + // plaintext. No processing needed + } else if (item[0] === "e") { + // Assumed to be base64, which starts with e + item = decodeURIComponent(escape(atob(item))); + } else if (item[0] === "ᯡ") { + // Assumed to be lz, which starts with ᯡ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + item = LZString.decompressFromUTF16(item)!; + } else { + console.warn("Unable to determine settings encoding", item); + return; + } + const settings = JSON.parse(item); + if (typeof settings === "object") { + Object.assign(state, settings); + } + } + globalBus.emit("loadSettings", state); + // eslint-disable-next-line no-empty + } catch {} +} + +/** A list of fields to append to the settings modal. */ +export const settingFields: CoercableComponent[] = reactive([]); +/** Register a field to be displayed in the settings modal. */ +export function registerSettingField(component: CoercableComponent) { + settingFields.push(component); +} + +/** A list of components to show in the info modal. */ +export const infoComponents: CoercableComponent[] = reactive([]); +/** Register a component to be displayed in the info modal. */ +export function registerInfoComponent(component: CoercableComponent) { + infoComponents.push(component); +} + +/** A list of components to add to the root of the page. */ +export const gameComponents: CoercableComponent[] = reactive([]); +/** Register a component to be displayed at the root of the page. */ +export function registerGameComponent(component: CoercableComponent) { + gameComponents.push(component); +} diff --git a/src/game/state.ts b/src/game/state.ts new file mode 100644 index 0000000..db71c7b --- /dev/null +++ b/src/game/state.ts @@ -0,0 +1,28 @@ +import type { DecimalSource } from "util/bignum"; +import { shallowReactive } from "vue"; +import type { Persistent } from "./persistence"; + +/** An object of global data that is not persistent. */ +export interface Transient { + /** A list of the duration, in ms, of the last 10 game ticks. Used for calculating TPS. */ + lastTenTicks: number[]; + /** Whether or not a NaN value has been detected and undealt with. */ + hasNaN: boolean; + /** The location within the player save data object of the NaN value. */ + NaNPath?: string[]; + /** The ref that was being set to NaN. */ + NaNPersistent?: Persistent<DecimalSource>; +} + +declare global { + /** Augment the window object so the transient state can be accessed from the console. */ + interface Window { + state: Transient; + } +} +/** The global transient state object. */ +export default window.state = shallowReactive<Transient>({ + lastTenTicks: [], + hasNaN: false, + NaNPath: [] +}); diff --git a/src/lib/break_eternity.ts b/src/lib/break_eternity.ts new file mode 100644 index 0000000..8d39f22 --- /dev/null +++ b/src/lib/break_eternity.ts @@ -0,0 +1,2991 @@ +/* eslint-disable @typescript-eslint/no-this-alias */ +/* eslint-disable @typescript-eslint/no-loss-of-precision */ +import { LRUCache } from "../lib/lru-cache"; + +export type CompareResult = -1 | 0 | 1; + +const MAX_SIGNIFICANT_DIGITS = 17; //Maximum number of digits of precision to assume in Number + +const EXP_LIMIT = 9e15; //If we're ABOVE this value, increase a layer. (9e15 is close to the largest integer that can fit in a Number.) + +const LAYER_DOWN: number = Math.log10(9e15); + +const FIRST_NEG_LAYER = 1 / 9e15; //At layer 0, smaller non-zero numbers than this become layer 1 numbers with negative mag. After that the pattern continues as normal. + +const NUMBER_EXP_MAX = 308; //The largest exponent that can appear in a Number, though not all mantissas are valid here. + +const NUMBER_EXP_MIN = -324; //The smallest exponent that can appear in a Number, though not all mantissas are valid here. + +const MAX_ES_IN_A_ROW = 5; //For default toString behaviour, when to swap from eee... to (e^n) syntax. + +const DEFAULT_FROM_STRING_CACHE_SIZE = (1 << 10) - 1; // The default size of the LRU cache used to cache Decimal.fromString. + +const IGNORE_COMMAS = true; +const COMMAS_ARE_DECIMAL_POINTS = false; + +const powerOf10 = (function () { + // We need this lookup table because Math.pow(10, exponent) + // when exponent's absolute value is large is slightly inaccurate. + // You can fix it with the power of math... or just make a lookup table. + // Faster AND simpler + const powersOf10: number[] = []; + + for (let i = NUMBER_EXP_MIN + 1; i <= NUMBER_EXP_MAX; i++) { + powersOf10.push(Number("1e" + i)); + } + + const indexOf0InPowersOf10 = 323; + return function (power: number) { + return powersOf10[power + indexOf0InPowersOf10]; + }; +})(); + +//tetration/slog to real height stuff +//background info and tables of values for critical functions taken here: https://github.com/Patashu/break_eternity.js/issues/22 +const critical_headers = [2, Math.E, 3, 4, 5, 6, 7, 8, 9, 10]; +const critical_tetr_values = [ + [ + // Base 2 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) + 1, 1.0891180521811202527, 1.1789767925673958433, 1.2701455431742086633, + 1.3632090180450091941, 1.4587818160364217007, 1.5575237916251418333, 1.6601571006859253673, + 1.7674858188369780435, 1.8804192098842727359, 2 + ], + [ + // Base E (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) + 1, //0.0 + 1.1121114330934078681, //0.1 + 1.2310389249316089299, //0.2 + 1.3583836963111376089, //0.3 + 1.4960519303993531879, //0.4 + 1.646354233751194581, //0.5 + 1.8121385357018724464, //0.6 + 1.9969713246183068478, //0.7 + 2.205389554552754433, //0.8 + 2.4432574483385252544, //0.9 + Math.E //1.0 + ], + [ + // Base 3 + 1, 1.1187738849693603, 1.2464963939368214, 1.38527004705667, 1.5376664685821402, + 1.7068895236551784, 1.897001227148399, 2.1132403089001035, 2.362480153784171, + 2.6539010333870774, 3 + ], + [ + // Base 4 + 1, 1.1367350847096405, 1.2889510672956703, 1.4606478703324786, 1.6570295196661111, + 1.8850062585672889, 2.1539465047453485, 2.476829779693097, 2.872061932789197, + 3.3664204535587183, 4 + ], + [ + // Base 5 + 1, 1.1494592900767588, 1.319708228183931, 1.5166291280087583, 1.748171114438024, + 2.0253263297298045, 2.3636668498288547, 2.7858359149579424, 3.3257226212448145, + 4.035730287722532, 5 + ], + [ + // Base 6 + 1, 1.159225940787673, 1.343712473580932, 1.5611293155111927, 1.8221199554561318, + 2.14183924486326, 2.542468319282638, 3.0574682501653316, 3.7390572020926873, + 4.6719550537360774, 6 + ], + [ + // Base 7 + 1, 1.1670905356972596, 1.3632807444991446, 1.5979222279405536, 1.8842640123816674, + 2.2416069644878687, 2.69893426559423, 3.3012632110403577, 4.121250340630164, + 5.281493033448316, 7 + ], + [ + // Base 8 + 1, 1.1736630594087796, 1.379783782386201, 1.6292821855668218, 1.9378971836180754, + 2.3289975651071977, 2.8384347394720835, 3.5232708454565906, 4.478242031114584, + 5.868592169644505, 8 + ], + [ + // Base 9 + 1, 1.1793017514670474, 1.394054150657457, 1.65664127441059, 1.985170999970283, + 2.4069682290577457, 2.9647310119960752, 3.7278665320924946, 4.814462547283592, + 6.436522247411611, 9 + ], + [ + // Base 10 (using http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html ) + 1, 1.1840100246247336579, 1.4061375836156954169, 1.6802272208863963918, + 2.026757028388618927, 2.477005606344964758, 3.0805252717554819987, 3.9191964192627283911, + 5.135152840833186423, 6.9899611795347148455, 10 + ] +]; +const critical_slog_values = [ + [ + // Base 2 + -1, -0.9194161097107025, -0.8335625019330468, -0.7425599821143978, -0.6466611521029437, + -0.5462617907227869, -0.4419033816638769, -0.3342645487554494, -0.224140440909962, + -0.11241087890006762, 0 + ], + [ + // Base E + -1, //0.0 + -0.90603157029014, //0.1 + -0.80786507256596, //0.2 + -0.7064666939634, //0.3 + -0.60294836853664, //0.4 + -0.49849837513117, //0.5 + -0.39430303318768, //0.6 + -0.29147201034755, //0.7 + -0.19097820800866, //0.8 + -0.09361896280296, //0.9 + 0 //1.0 + ], + [ + // Base 3 + -1, -0.9021579584316141, -0.8005762598234203, -0.6964780623319391, -0.5911906810998454, + -0.486050182576545, -0.3823089430815083, -0.28106046722897615, -0.1831906535795894, + -0.08935809204418144, 0 + ], + [ + // Base 4 + -1, -0.8917227442365535, -0.781258746326964, -0.6705130326902455, -0.5612813129406509, + -0.4551067709033134, -0.35319256652135966, -0.2563741554088552, -0.1651412821106526, + -0.0796919581982668, 0 + ], + [ + // Base 5 + -1, -0.8843387974366064, -0.7678744063886243, -0.6529563724510552, -0.5415870994657841, + -0.4352842206588936, -0.33504449124791424, -0.24138853420685147, -0.15445285440944467, + -0.07409659641336663, 0 + ], + [ + // Base 6 + -1, -0.8786709358426346, -0.7577735191184886, -0.6399546189952064, -0.527284921869926, + -0.4211627631006314, -0.3223479611761232, -0.23107655627789858, -0.1472057700818259, + -0.07035171210706326, 0 + ], + [ + // Base 7 + -1, -0.8740862815291583, -0.7497032990976209, -0.6297119746181752, -0.5161838335958787, + -0.41036238255751956, -0.31277212146489963, -0.2233976621705518, -0.1418697367979619, + -0.06762117662323441, 0 + ], + [ + // Base 8 + -1, -0.8702632331800649, -0.7430366914122081, -0.6213373075161548, -0.5072025698095242, + -0.40171437727184167, -0.30517930701410456, -0.21736343968190863, -0.137710238299109, + -0.06550774483471955, 0 + ], + [ + // Base 9 + -1, -0.8670016295947213, -0.7373984232432306, -0.6143173985094293, -0.49973884395492807, + -0.394584953527678, -0.2989649949848695, -0.21245647317021688, -0.13434688362382652, + -0.0638072667348083, 0 + ], + [ + // Base 10 + -1, -0.8641642839543857, -0.732534623168535, -0.6083127477059322, -0.4934049257184696, + -0.3885773075899922, -0.29376029055315767, -0.2083678561173622, -0.13155653399373268, + -0.062401588652553186, 0 + ] +]; + +let D = function D(value: DecimalSource): Readonly<Decimal> { + return Decimal.fromValue_noAlloc(value); +}; + +let FC = function (sign: number, layer: number, mag: number) { + return Decimal.fromComponents(sign, layer, mag); +}; + +let FC_NN = function FC_NN(sign: number, layer: number, mag: number) { + return Decimal.fromComponents_noNormalize(sign, layer, mag); +}; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +let ME = function ME(mantissa: number, exponent: number) { + return Decimal.fromMantissaExponent(mantissa, exponent); +}; + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +let ME_NN = function ME_NN(mantissa: number, exponent: number) { + return Decimal.fromMantissaExponent_noNormalize(mantissa, exponent); +}; + +const decimalPlaces = function decimalPlaces(value: number, places: number): number { + const len = places + 1; + const numDigits = Math.ceil(Math.log10(Math.abs(value))); + const rounded = + Math.round(value * Math.pow(10, len - numDigits)) * Math.pow(10, numDigits - len); + return parseFloat(rounded.toFixed(Math.max(len - numDigits, 0))); +}; + +const f_maglog10 = function (n: number) { + return Math.sign(n) * Math.log10(Math.abs(n)); +}; + +//from HyperCalc source code +const f_gamma = function (n: number) { + if (!isFinite(n)) { + return n; + } + if (n < -50) { + if (n === Math.trunc(n)) { + return Number.NEGATIVE_INFINITY; + } + return 0; + } + + let scal1 = 1; + while (n < 10) { + scal1 = scal1 * n; + ++n; + } + + n -= 1; + let l = 0.9189385332046727; //0.5*Math.log(2*Math.PI) + l = l + (n + 0.5) * Math.log(n); + l = l - n; + const n2 = n * n; + let np = n; + l = l + 1 / (12 * np); + np = np * n2; + l = l + 1 / (360 * np); + np = np * n2; + l = l + 1 / (1260 * np); + np = np * n2; + l = l + 1 / (1680 * np); + np = np * n2; + l = l + 1 / (1188 * np); + np = np * n2; + l = l + 691 / (360360 * np); + np = np * n2; + l = l + 7 / (1092 * np); + np = np * n2; + l = l + 3617 / (122400 * np); + + return Math.exp(l) / scal1; +}; + +const _twopi = 6.2831853071795864769252842; // 2*pi +const _EXPN1 = 0.36787944117144232159553; // exp(-1) +const OMEGA = 0.56714329040978387299997; // W(1, 0) +//from https://math.stackexchange.com/a/465183 +// The evaluation can become inaccurate very close to the branch point +const f_lambertw = function (z: number, tol = 1e-10): number { + let w; + let wn; + + if (!Number.isFinite(z)) { + return z; + } + if (z === 0) { + return z; + } + if (z === 1) { + return OMEGA; + } + + if (z < 10) { + w = 0; + } else { + w = Math.log(z) - Math.log(Math.log(z)); + } + + for (let i = 0; i < 100; ++i) { + wn = (z * Math.exp(-w) + w * w) / (w + 1); + if (Math.abs(wn - w) < tol * Math.abs(wn)) { + return wn; + } else { + w = wn; + } + } + + throw Error(`Iteration failed to converge: ${z.toString()}`); + //return Number.NaN; +}; + +//from https://github.com/scipy/scipy/blob/8dba340293fe20e62e173bdf2c10ae208286692f/scipy/special/lambertw.pxd +// The evaluation can become inaccurate very close to the branch point +// at ``-1/e``. In some corner cases, `lambertw` might currently +// fail to converge, or can end up on the wrong branch. +function d_lambertw(z: Decimal, tol = 1e-10): Decimal { + let w; + let ew, wewz, wn; + + if (!Number.isFinite(z.mag)) { + return z; + } + if (z.eq(Decimal.dZero)) { + return z; + } + if (z.eq(Decimal.dOne)) { + //Split out this case because the asymptotic series blows up + return Decimal.fromNumber(OMEGA); + } + + //Get an initial guess for Halley's method + w = Decimal.ln(z); + + //Halley's method; see 5.9 in [1] + + for (let i = 0; i < 100; ++i) { + ew = w.neg().exp(); + wewz = w.sub(z.mul(ew)); + wn = w.sub(wewz.div(w.add(1).sub(w.add(2).mul(wewz).div(Decimal.mul(2, w).add(2))))); + if (Decimal.abs(wn.sub(w)).lt(Decimal.abs(wn).mul(tol))) { + return wn; + } else { + w = wn; + } + } + + throw Error(`Iteration failed to converge: ${z.toString()}`); + //return Decimal.dNaN; +} + +export type DecimalSource = Decimal | number | string; + +/** + * The Decimal's value is simply mantissa * 10^exponent. + */ +export default class Decimal { + public static dZero: Decimal; + public static dOne: Decimal; + public static dNegOne: Decimal; + public static dTwo: Decimal; + public static dTen: Decimal; + public static dNaN: Decimal; + public static dInf: Decimal; + public static dNegInf: Decimal; + public static dNumberMax: Decimal; + public static dNumberMin: Decimal; + + private static fromStringCache = new LRUCache<string, Decimal>(DEFAULT_FROM_STRING_CACHE_SIZE); + + public sign = 0; + public mag = 0; + public layer = 0; + + constructor(value?: DecimalSource) { + if (value instanceof Decimal) { + this.fromDecimal(value); + } else if (typeof value === "number") { + this.fromNumber(value); + } else if (typeof value === "string") { + this.fromString(value); + } + } + + get m(): number { + if (this.sign === 0) { + return 0; + } else if (this.layer === 0) { + const exp = Math.floor(Math.log10(this.mag)); + //handle special case 5e-324 + let man; + if (this.mag === 5e-324) { + man = 5; + } else { + man = this.mag / powerOf10(exp); + } + return this.sign * man; + } else if (this.layer === 1) { + const residue = this.mag - Math.floor(this.mag); + return this.sign * Math.pow(10, residue); + } else { + //mantissa stops being relevant past 1e9e15 / ee15.954 + return this.sign; + } + } + + set m(value: number) { + if (this.layer <= 2) { + this.fromMantissaExponent(value, this.e); + } else { + //don't even pretend mantissa is meaningful + this.sign = Math.sign(value); + if (this.sign === 0) { + this.layer = 0; + this.exponent = 0; + } + } + } + + get e(): number { + if (this.sign === 0) { + return 0; + } else if (this.layer === 0) { + return Math.floor(Math.log10(this.mag)); + } else if (this.layer === 1) { + return Math.floor(this.mag); + } else if (this.layer === 2) { + return Math.floor(Math.sign(this.mag) * Math.pow(10, Math.abs(this.mag))); + } else { + return this.mag * Number.POSITIVE_INFINITY; + } + } + set e(value: number) { + this.fromMantissaExponent(this.m, value); + } + + get s(): number { + return this.sign; + } + set s(value: number) { + if (value === 0) { + this.sign = 0; + this.layer = 0; + this.mag = 0; + } else { + this.sign = value; + } + } + + // Object.defineProperty(Decimal.prototype, "mantissa", { + get mantissa(): number { + return this.m; + } + + set mantissa(value: number) { + this.m = value; + } + + get exponent(): number { + return this.e; + } + set exponent(value: number) { + this.e = value; + } + + public static fromComponents(sign: number, layer: number, mag: number): Decimal { + return new Decimal().fromComponents(sign, layer, mag); + } + + public static fromComponents_noNormalize(sign: number, layer: number, mag: number): Decimal { + return new Decimal().fromComponents_noNormalize(sign, layer, mag); + } + + public static fromMantissaExponent(mantissa: number, exponent: number): Decimal { + return new Decimal().fromMantissaExponent(mantissa, exponent); + } + + public static fromMantissaExponent_noNormalize(mantissa: number, exponent: number): Decimal { + return new Decimal().fromMantissaExponent_noNormalize(mantissa, exponent); + } + + public static fromDecimal(value: Decimal): Decimal { + return new Decimal().fromDecimal(value); + } + + public static fromNumber(value: number): Decimal { + return new Decimal().fromNumber(value); + } + + public static fromString(value: string): Decimal { + return new Decimal().fromString(value); + } + + public static fromValue(value: DecimalSource): Decimal { + return new Decimal().fromValue(value); + } + + /** + * Converts a DecimalSource to a Decimal, without constructing a new Decimal + * if the provided value is already a Decimal. + * + * As the return value could be the provided value itself, this function + * returns a read-only Decimal to prevent accidental mutations of the value. + * Use `new Decimal(value)` to explicitly create a writeable copy if mutation + * is required. + */ + public static fromValue_noAlloc(value: DecimalSource): Readonly<Decimal> { + if (value instanceof Decimal) { + return value; + } else if (typeof value === "string") { + const cached = Decimal.fromStringCache.get(value); + if (cached !== undefined) { + return cached; + } + return Decimal.fromString(value); + } else if (typeof value === "number") { + return Decimal.fromNumber(value); + } else { + // This should never happen... but some users like Prestige Tree Rewritten + // pass undefined values in as DecimalSources, so we should handle this + // case to not break them. + return Decimal.dZero; + } + } + + public static abs(value: DecimalSource): Decimal { + return D(value).abs(); + } + + public static neg(value: DecimalSource): Decimal { + return D(value).neg(); + } + + public static negate(value: DecimalSource): Decimal { + return D(value).neg(); + } + + public static negated(value: DecimalSource): Decimal { + return D(value).neg(); + } + + public static sign(value: DecimalSource): number { + return D(value).sign; + } + + public static sgn(value: DecimalSource): number { + return D(value).sign; + } + + public static round(value: DecimalSource): Decimal { + return D(value).round(); + } + + public static floor(value: DecimalSource): Decimal { + return D(value).floor(); + } + + public static ceil(value: DecimalSource): Decimal { + return D(value).ceil(); + } + + public static trunc(value: DecimalSource): Decimal { + return D(value).trunc(); + } + + public static add(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).add(other); + } + + public static plus(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).add(other); + } + + public static sub(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).sub(other); + } + + public static subtract(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).sub(other); + } + + public static minus(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).sub(other); + } + + public static mul(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).mul(other); + } + + public static multiply(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).mul(other); + } + + public static times(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).mul(other); + } + + public static div(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).div(other); + } + + public static divide(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).div(other); + } + + public static recip(value: DecimalSource): Decimal { + return D(value).recip(); + } + + public static reciprocal(value: DecimalSource): Decimal { + return D(value).recip(); + } + + public static reciprocate(value: DecimalSource): Decimal { + return D(value).reciprocate(); + } + + public static cmp(value: DecimalSource, other: DecimalSource): CompareResult { + return D(value).cmp(other); + } + + public static cmpabs(value: DecimalSource, other: DecimalSource): CompareResult { + return D(value).cmpabs(other); + } + + public static compare(value: DecimalSource, other: DecimalSource): CompareResult { + return D(value).cmp(other); + } + + public static isNaN(value: DecimalSource): boolean { + value = D(value); + return isNaN(value.sign) || isNaN(value.layer) || isNaN(value.mag); + } + + public static isFinite(value: DecimalSource): boolean { + value = D(value); + return isFinite(value.sign) && isFinite(value.layer) && isFinite(value.mag); + } + + public static eq(value: DecimalSource, other: DecimalSource): boolean { + return D(value).eq(other); + } + + public static equals(value: DecimalSource, other: DecimalSource): boolean { + return D(value).eq(other); + } + + public static neq(value: DecimalSource, other: DecimalSource): boolean { + return D(value).neq(other); + } + + public static notEquals(value: DecimalSource, other: DecimalSource): boolean { + return D(value).notEquals(other); + } + + public static lt(value: DecimalSource, other: DecimalSource): boolean { + return D(value).lt(other); + } + + public static lte(value: DecimalSource, other: DecimalSource): boolean { + return D(value).lte(other); + } + + public static gt(value: DecimalSource, other: DecimalSource): boolean { + return D(value).gt(other); + } + + public static gte(value: DecimalSource, other: DecimalSource): boolean { + return D(value).gte(other); + } + + public static max(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).max(other); + } + + public static min(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).min(other); + } + + public static minabs(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).minabs(other); + } + + public static maxabs(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).maxabs(other); + } + + public static clamp(value: DecimalSource, min: DecimalSource, max: DecimalSource): Decimal { + return D(value).clamp(min, max); + } + + public static clampMin(value: DecimalSource, min: DecimalSource): Decimal { + return D(value).clampMin(min); + } + + public static clampMax(value: DecimalSource, max: DecimalSource): Decimal { + return D(value).clampMax(max); + } + + public static cmp_tolerance( + value: DecimalSource, + other: DecimalSource, + tolerance: number + ): CompareResult { + return D(value).cmp_tolerance(other, tolerance); + } + + public static compare_tolerance( + value: DecimalSource, + other: DecimalSource, + tolerance: number + ): CompareResult { + return D(value).cmp_tolerance(other, tolerance); + } + + public static eq_tolerance( + value: DecimalSource, + other: DecimalSource, + tolerance?: number + ): boolean { + return D(value).eq_tolerance(other, tolerance); + } + + public static equals_tolerance( + value: DecimalSource, + other: DecimalSource, + tolerance?: number + ): boolean { + return D(value).eq_tolerance(other, tolerance); + } + + public static neq_tolerance( + value: DecimalSource, + other: DecimalSource, + tolerance: number + ): boolean { + return D(value).neq_tolerance(other, tolerance); + } + + public static notEquals_tolerance( + value: DecimalSource, + other: DecimalSource, + tolerance: number + ): boolean { + return D(value).notEquals_tolerance(other, tolerance); + } + + public static lt_tolerance( + value: DecimalSource, + other: DecimalSource, + tolerance: number + ): boolean { + return D(value).lt_tolerance(other, tolerance); + } + + public static lte_tolerance( + value: DecimalSource, + other: DecimalSource, + tolerance: number + ): boolean { + return D(value).lte_tolerance(other, tolerance); + } + + public static gt_tolerance( + value: DecimalSource, + other: DecimalSource, + tolerance: number + ): boolean { + return D(value).gt_tolerance(other, tolerance); + } + + public static gte_tolerance( + value: DecimalSource, + other: DecimalSource, + tolerance: number + ): boolean { + return D(value).gte_tolerance(other, tolerance); + } + + public static pLog10(value: DecimalSource): Decimal { + return D(value).pLog10(); + } + + public static absLog10(value: DecimalSource): Decimal { + return D(value).absLog10(); + } + + public static log10(value: DecimalSource): Decimal { + return D(value).log10(); + } + + public static log(value: DecimalSource, base: DecimalSource): Decimal { + return D(value).log(base); + } + + public static log2(value: DecimalSource): Decimal { + return D(value).log2(); + } + + public static ln(value: DecimalSource): Decimal { + return D(value).ln(); + } + + public static logarithm(value: DecimalSource, base: DecimalSource): Decimal { + return D(value).logarithm(base); + } + + public static pow(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).pow(other); + } + + public static pow10(value: DecimalSource): Decimal { + return D(value).pow10(); + } + + public static pow_base(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).pow_base(other); + } + + public static root(value: DecimalSource, other: DecimalSource): Decimal { + return D(value).root(other); + } + + public static factorial(value: DecimalSource, _other?: never): Decimal { + return D(value).factorial(); + } + + public static gamma(value: DecimalSource, _other?: never): Decimal { + return D(value).gamma(); + } + + public static lngamma(value: DecimalSource, _other?: never): Decimal { + return D(value).lngamma(); + } + + public static exp(value: DecimalSource): Decimal { + return D(value).exp(); + } + + public static sqr(value: DecimalSource): Decimal { + return D(value).sqr(); + } + + public static sqrt(value: DecimalSource): Decimal { + return D(value).sqrt(); + } + + public static cube(value: DecimalSource): Decimal { + return D(value).cube(); + } + + public static cbrt(value: DecimalSource): Decimal { + return D(value).cbrt(); + } + + public static tetrate( + value: DecimalSource, + height = 2, + payload: DecimalSource = FC_NN(1, 0, 1) + ): Decimal { + return D(value).tetrate(height, payload); + } + + public static iteratedexp(value: DecimalSource, height = 2, payload = FC_NN(1, 0, 1)): Decimal { + return D(value).iteratedexp(height, payload); + } + + public static iteratedlog(value: DecimalSource, base: DecimalSource = 10, times = 1): Decimal { + return D(value).iteratedlog(base, times); + } + + public static layeradd10(value: DecimalSource, diff: DecimalSource): Decimal { + return D(value).layeradd10(diff); + } + + public static layeradd(value: DecimalSource, diff: number, base: DecimalSource = 10): Decimal { + return D(value).layeradd(diff, base); + } + + public static slog(value: DecimalSource, base = 10): Decimal { + return D(value).slog(base); + } + + public static lambertw(value: DecimalSource): Decimal { + return D(value).lambertw(); + } + + public static ssqrt(value: DecimalSource): Decimal { + return D(value).ssqrt(); + } + + public static pentate( + value: DecimalSource, + height = 2, + payload: DecimalSource = FC_NN(1, 0, 1) + ): Decimal { + return D(value).pentate(height, payload); + } + + public static sin(value: DecimalSource): Decimal { + return D(value).sin(); + } + + public static cos(value: DecimalSource): Decimal { + return D(value).cos(); + } + + public static tan(value: DecimalSource): Decimal { + return D(value).tan(); + } + + public static asin(value: DecimalSource): Decimal { + return D(value).asin(); + } + + public static acos(value: DecimalSource): Decimal { + return D(value).acos(); + } + + public static atan(value: DecimalSource): Decimal { + return D(value).atan(); + } + + public static sinh(value: DecimalSource): Decimal { + return D(value).sinh(); + } + + public static cosh(value: DecimalSource): Decimal { + return D(value).cosh(); + } + + public static tanh(value: DecimalSource): Decimal { + return D(value).tanh(); + } + + public static asinh(value: DecimalSource): Decimal { + return D(value).asinh(); + } + + public static acosh(value: DecimalSource): Decimal { + return D(value).acosh(); + } + + public static atanh(value: DecimalSource): Decimal { + return D(value).atanh(); + } + + /** + * If you're willing to spend 'resourcesAvailable' and want to buy something + * with exponentially increasing cost each purchase (start at priceStart, + * multiply by priceRatio, already own currentOwned), how much of it can you buy? + * Adapted from Trimps source code. + */ + + public static affordGeometricSeries( + resourcesAvailable: DecimalSource, + priceStart: DecimalSource, + priceRatio: DecimalSource, + currentOwned: DecimalSource + ): Decimal { + return this.affordGeometricSeries_core( + D(resourcesAvailable), + D(priceStart), + D(priceRatio), + currentOwned + ); + } + /** + * How much resource would it cost to buy (numItems) items if you already have currentOwned, + * the initial price is priceStart and it multiplies by priceRatio each purchase? + */ + + public static sumGeometricSeries( + numItems: DecimalSource, + priceStart: DecimalSource, + priceRatio: DecimalSource, + currentOwned: DecimalSource + ): Decimal { + return this.sumGeometricSeries_core(numItems, D(priceStart), D(priceRatio), currentOwned); + } + /** + * If you're willing to spend 'resourcesAvailable' and want to buy something with additively + * increasing cost each purchase (start at priceStart, add by priceAdd, already own currentOwned), + * how much of it can you buy? + */ + + public static affordArithmeticSeries( + resourcesAvailable: DecimalSource, + priceStart: DecimalSource, + priceAdd: DecimalSource, + currentOwned: DecimalSource + ): Decimal { + return this.affordArithmeticSeries_core( + D(resourcesAvailable), + D(priceStart), + D(priceAdd), + D(currentOwned) + ); + } + /** + * How much resource would it cost to buy (numItems) items if you already have currentOwned, + * the initial price is priceStart and it adds priceAdd each purchase? + * Adapted from http://www.mathwords.com/a/arithmetic_series.htm + */ + + public static sumArithmeticSeries( + numItems: DecimalSource, + priceStart: DecimalSource, + priceAdd: DecimalSource, + currentOwned: DecimalSource + ): Decimal { + return this.sumArithmeticSeries_core( + D(numItems), + D(priceStart), + D(priceAdd), + D(currentOwned) + ); + } + /** + * When comparing two purchases that cost (resource) and increase your resource/sec by (deltaRpS), + * the lowest efficiency score is the better one to purchase. + * From Frozen Cookies: + * http://cookieclicker.wikia.com/wiki/Frozen_Cookies_(JavaScript_Add-on)#Efficiency.3F_What.27s_that.3F + */ + + public static efficiencyOfPurchase( + cost: DecimalSource, + currentRpS: DecimalSource, + deltaRpS: DecimalSource + ): Decimal { + return this.efficiencyOfPurchase_core(D(cost), D(currentRpS), D(deltaRpS)); + } + + public static randomDecimalForTesting(maxLayers: number): Decimal { + // NOTE: This doesn't follow any kind of sane random distribution, so use this for testing purposes only. + //5% of the time, return 0 + if (Math.random() * 20 < 1) { + return FC_NN(0, 0, 0); + } + + const randomsign = Math.random() > 0.5 ? 1 : -1; + + //5% of the time, return 1 or -1 + if (Math.random() * 20 < 1) { + return FC_NN(randomsign, 0, 1); + } + + //pick a random layer + const layer = Math.floor(Math.random() * (maxLayers + 1)); + + let randomexp = layer === 0 ? Math.random() * 616 - 308 : Math.random() * 16; + //10% of the time, make it a simple power of 10 + if (Math.random() > 0.9) { + randomexp = Math.trunc(randomexp); + } + let randommag = Math.pow(10, randomexp); + //10% of the time, trunc mag + if (Math.random() > 0.9) { + randommag = Math.trunc(randommag); + } + return FC(randomsign, layer, randommag); + } + + public static affordGeometricSeries_core( + resourcesAvailable: Decimal, + priceStart: Decimal, + priceRatio: Decimal, + currentOwned: DecimalSource + ): Decimal { + const actualStart = priceStart.mul(priceRatio.pow(currentOwned)); + return Decimal.floor( + resourcesAvailable + .div(actualStart) + .mul(priceRatio.sub(1)) + .add(1) + .log10() + .div(priceRatio.log10()) + ); + } + + public static sumGeometricSeries_core( + numItems: DecimalSource, + priceStart: Decimal, + priceRatio: Decimal, + currentOwned: DecimalSource + ): Decimal { + return priceStart + .mul(priceRatio.pow(currentOwned)) + .mul(Decimal.sub(1, priceRatio.pow(numItems))) + .div(Decimal.sub(1, priceRatio)); + } + + public static affordArithmeticSeries_core( + resourcesAvailable: Decimal, + priceStart: Decimal, + priceAdd: Decimal, + currentOwned: Decimal + ): Decimal { + // n = (-(a-d/2) + sqrt((a-d/2)^2+2dS))/d + // where a is actualStart, d is priceAdd and S is resourcesAvailable + // then floor it and you're done! + const actualStart = priceStart.add(currentOwned.mul(priceAdd)); + const b = actualStart.sub(priceAdd.div(2)); + const b2 = b.pow(2); + return b + .neg() + .add(b2.add(priceAdd.mul(resourcesAvailable).mul(2)).sqrt()) + .div(priceAdd) + .floor(); + } + + public static sumArithmeticSeries_core( + numItems: Decimal, + priceStart: Decimal, + priceAdd: Decimal, + currentOwned: Decimal + ): Decimal { + const actualStart = priceStart.add(currentOwned.mul(priceAdd)); // (n/2)*(2*a+(n-1)*d) + + return numItems.div(2).mul(actualStart.mul(2).plus(numItems.sub(1).mul(priceAdd))); + } + + public static efficiencyOfPurchase_core( + cost: Decimal, + currentRpS: Decimal, + deltaRpS: Decimal + ): Decimal { + return cost.div(currentRpS).add(cost.div(deltaRpS)); + } + + public normalize(): this { + /* + PSEUDOCODE: + Whenever we are partially 0 (sign is 0 or mag and layer is 0), make it fully 0. + Whenever we are at or hit layer 0, extract sign from negative mag. + If layer === 0 and mag < FIRST_NEG_LAYER (1/9e15), shift to 'first negative layer' (add layer, log10 mag). + While abs(mag) > EXP_LIMIT (9e15), layer += 1, mag = maglog10(mag). + While abs(mag) < LAYER_DOWN (15.954) and layer > 0, layer -= 1, mag = pow(10, mag). + + When we're done, all of the following should be true OR one of the numbers is not IsFinite OR layer is not IsInteger (error state): + Any 0 is totally zero (0, 0, 0). + Anything layer 0 has mag 0 OR mag > 1/9e15 and < 9e15. + Anything layer 1 or higher has abs(mag) >= 15.954 and < 9e15. + We will assume in calculations that all Decimals are either erroneous or satisfy these criteria. (Otherwise: Garbage in, garbage out.) + */ + if (this.sign === 0 || (this.mag === 0 && this.layer === 0)) { + this.sign = 0; + this.mag = 0; + this.layer = 0; + return this; + } + + if (this.layer === 0 && this.mag < 0) { + //extract sign from negative mag at layer 0 + this.mag = -this.mag; + this.sign = -this.sign; + } + + //Handle shifting from layer 0 to negative layers. + if (this.layer === 0 && this.mag < FIRST_NEG_LAYER) { + this.layer += 1; + this.mag = Math.log10(this.mag); + return this; + } + + let absmag = Math.abs(this.mag); + let signmag = Math.sign(this.mag); + + if (absmag >= EXP_LIMIT) { + this.layer += 1; + this.mag = signmag * Math.log10(absmag); + return this; + } else { + while (absmag < LAYER_DOWN && this.layer > 0) { + this.layer -= 1; + if (this.layer === 0) { + this.mag = Math.pow(10, this.mag); + } else { + this.mag = signmag * Math.pow(10, absmag); + absmag = Math.abs(this.mag); + signmag = Math.sign(this.mag); + } + } + if (this.layer === 0) { + if (this.mag < 0) { + //extract sign from negative mag at layer 0 + this.mag = -this.mag; + this.sign = -this.sign; + } else if (this.mag === 0) { + //excessive rounding can give us all zeroes + this.sign = 0; + } + } + } + + return this; + } + + public fromComponents(sign: number, layer: number, mag: number): this { + this.sign = sign; + this.layer = layer; + this.mag = mag; + + this.normalize(); + return this; + } + + public fromComponents_noNormalize(sign: number, layer: number, mag: number): this { + this.sign = sign; + this.layer = layer; + this.mag = mag; + return this; + } + + public fromMantissaExponent(mantissa: number, exponent: number): this { + this.layer = 1; + this.sign = Math.sign(mantissa); + mantissa = Math.abs(mantissa); + this.mag = exponent + Math.log10(mantissa); + + this.normalize(); + return this; + } + + public fromMantissaExponent_noNormalize(mantissa: number, exponent: number): this { + //The idea of 'normalizing' a break_infinity.js style Decimal doesn't really apply. So just do the same thing. + this.fromMantissaExponent(mantissa, exponent); + return this; + } + + public fromDecimal(value: Decimal): this { + this.sign = value.sign; + this.layer = value.layer; + this.mag = value.mag; + return this; + } + + public fromNumber(value: number): this { + this.mag = Math.abs(value); + this.sign = Math.sign(value); + this.layer = 0; + this.normalize(); + return this; + } + + public fromString(value: string): Decimal { + const originalValue = value; + const cached = Decimal.fromStringCache.get(originalValue); + if (cached !== undefined) { + return this.fromDecimal(cached); + } + if (IGNORE_COMMAS) { + value = value.replace(",", ""); + } else if (COMMAS_ARE_DECIMAL_POINTS) { + value = value.replace(",", "."); + } + + //Handle x^^^y format. + const pentationparts = value.split("^^^"); + if (pentationparts.length === 2) { + const base = parseFloat(pentationparts[0]); + const height = parseFloat(pentationparts[1]); + const heightparts = pentationparts[1].split(";"); + let payload = 1; + if (heightparts.length === 2) { + payload = parseFloat(heightparts[1]); + if (!isFinite(payload)) { + payload = 1; + } + } + if (isFinite(base) && isFinite(height)) { + const result = Decimal.pentate(base, height, payload); + this.sign = result.sign; + this.layer = result.layer; + this.mag = result.mag; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } + + //Handle x^^y format. + const tetrationparts = value.split("^^"); + if (tetrationparts.length === 2) { + const base = parseFloat(tetrationparts[0]); + const height = parseFloat(tetrationparts[1]); + const heightparts = tetrationparts[1].split(";"); + let payload = 1; + if (heightparts.length === 2) { + payload = parseFloat(heightparts[1]); + if (!isFinite(payload)) { + payload = 1; + } + } + if (isFinite(base) && isFinite(height)) { + const result = Decimal.tetrate(base, height, payload); + this.sign = result.sign; + this.layer = result.layer; + this.mag = result.mag; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } + + //Handle x^y format. + const powparts = value.split("^"); + if (powparts.length === 2) { + const base = parseFloat(powparts[0]); + const exponent = parseFloat(powparts[1]); + if (isFinite(base) && isFinite(exponent)) { + const result = Decimal.pow(base, exponent); + this.sign = result.sign; + this.layer = result.layer; + this.mag = result.mag; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } + + //Handle various cases involving it being a Big Number. + value = value.trim().toLowerCase(); + + //handle X PT Y format. + let base; + let height; + let ptparts = value.split("pt"); + if (ptparts.length === 2) { + base = 10; + height = parseFloat(ptparts[0]); + ptparts[1] = ptparts[1].replace("(", ""); + ptparts[1] = ptparts[1].replace(")", ""); + let payload = parseFloat(ptparts[1]); + if (!isFinite(payload)) { + payload = 1; + } + if (isFinite(base) && isFinite(height)) { + const result = Decimal.tetrate(base, height, payload); + this.sign = result.sign; + this.layer = result.layer; + this.mag = result.mag; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } + + //handle XpY format (it's the same thing just with p). + ptparts = value.split("p"); + if (ptparts.length === 2) { + base = 10; + height = parseFloat(ptparts[0]); + ptparts[1] = ptparts[1].replace("(", ""); + ptparts[1] = ptparts[1].replace(")", ""); + let payload = parseFloat(ptparts[1]); + if (!isFinite(payload)) { + payload = 1; + } + if (isFinite(base) && isFinite(height)) { + const result = Decimal.tetrate(base, height, payload); + this.sign = result.sign; + this.layer = result.layer; + this.mag = result.mag; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } + + const parts = value.split("e"); + const ecount = parts.length - 1; + + //Handle numbers that are exactly floats (0 or 1 es). + if (ecount === 0) { + const numberAttempt = parseFloat(value); + if (isFinite(numberAttempt)) { + this.fromNumber(numberAttempt); + if (Decimal.fromStringCache.size >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } else if (ecount === 1) { + //Very small numbers ("2e-3000" and so on) may look like valid floats but round to 0. + const numberAttempt = parseFloat(value); + if (isFinite(numberAttempt) && numberAttempt !== 0) { + this.fromNumber(numberAttempt); + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } + + //Handle new (e^N)X format. + const newparts = value.split("e^"); + if (newparts.length === 2) { + this.sign = 1; + if (newparts[0].charAt(0) == "-") { + this.sign = -1; + } + let layerstring = ""; + for (let i = 0; i < newparts[1].length; ++i) { + const chrcode = newparts[1].charCodeAt(i); + if ((chrcode >= 43 && chrcode <= 57) || chrcode === 101) { + //is "0" to "9" or "+" or "-" or "." or "e" (or "," or "/") + layerstring += newparts[1].charAt(i); + } //we found the end of the layer count + else { + this.layer = parseFloat(layerstring); + this.mag = parseFloat(newparts[1].substr(i + 1)); + this.normalize(); + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + } + } + + if (ecount < 1) { + this.sign = 0; + this.layer = 0; + this.mag = 0; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + const mantissa = parseFloat(parts[0]); + if (mantissa === 0) { + this.sign = 0; + this.layer = 0; + this.mag = 0; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + let exponent = parseFloat(parts[parts.length - 1]); + //handle numbers like AeBeC and AeeeeBeC + if (ecount >= 2) { + const me = parseFloat(parts[parts.length - 2]); + if (isFinite(me)) { + exponent *= Math.sign(me); + exponent += f_maglog10(me); + } + } + + //Handle numbers written like eee... (N es) X + if (!isFinite(mantissa)) { + this.sign = parts[0] === "-" ? -1 : 1; + this.layer = ecount; + this.mag = exponent; + } + //Handle numbers written like XeY + else if (ecount === 1) { + this.sign = Math.sign(mantissa); + this.layer = 1; + //Example: 2e10 is equal to 10^log10(2e10) which is equal to 10^(10+log10(2)) + this.mag = exponent + Math.log10(Math.abs(mantissa)); + } + //Handle numbers written like Xeee... (N es) Y + else { + this.sign = Math.sign(mantissa); + this.layer = ecount; + if (ecount === 2) { + const result = Decimal.mul(FC(1, 2, exponent), D(mantissa)); + this.sign = result.sign; + this.layer = result.layer; + this.mag = result.mag; + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } else { + //at eee and above, mantissa is too small to be recognizable! + this.mag = exponent; + } + } + + this.normalize(); + if (Decimal.fromStringCache.maxSize >= 1) { + Decimal.fromStringCache.set(originalValue, Decimal.fromDecimal(this)); + } + return this; + } + + public fromValue(value: DecimalSource): Decimal { + if (value instanceof Decimal) { + return this.fromDecimal(value); + } + + if (typeof value === "number") { + return this.fromNumber(value); + } + + if (typeof value === "string") { + return this.fromString(value); + } + + this.sign = 0; + this.layer = 0; + this.mag = 0; + return this; + } + + public toNumber(): number { + if (!Number.isFinite(this.layer)) { + return Number.NaN; + } + if (this.layer === 0) { + return this.sign * this.mag; + } else if (this.layer === 1) { + return this.sign * Math.pow(10, this.mag); + } //overflow for any normalized Decimal + else { + return this.mag > 0 + ? this.sign > 0 + ? Number.POSITIVE_INFINITY + : Number.NEGATIVE_INFINITY + : 0; + } + } + + public mantissaWithDecimalPlaces(places: number): number { + // https://stackoverflow.com/a/37425022 + if (isNaN(this.m)) { + return Number.NaN; + } + + if (this.m === 0) { + return 0; + } + + return decimalPlaces(this.m, places); + } + + public magnitudeWithDecimalPlaces(places: number): number { + // https://stackoverflow.com/a/37425022 + if (isNaN(this.mag)) { + return Number.NaN; + } + + if (this.mag === 0) { + return 0; + } + + return decimalPlaces(this.mag, places); + } + + public toString(): string { + if (isNaN(this.layer) || isNaN(this.sign) || isNaN(this.mag)) { + return "NaN"; + } + if (this.mag === Number.POSITIVE_INFINITY || this.layer === Number.POSITIVE_INFINITY) { + return this.sign === 1 ? "Infinity" : "-Infinity"; + } + + if (this.layer === 0) { + if ((this.mag < 1e21 && this.mag > 1e-7) || this.mag === 0) { + return (this.sign * this.mag).toString(); + } + return this.m + "e" + this.e; + } else if (this.layer === 1) { + return this.m + "e" + this.e; + } else { + //layer 2+ + if (this.layer <= MAX_ES_IN_A_ROW) { + return (this.sign === -1 ? "-" : "") + "e".repeat(this.layer) + this.mag; + } else { + return (this.sign === -1 ? "-" : "") + "(e^" + this.layer + ")" + this.mag; + } + } + } + + public toExponential(places: number): string { + if (this.layer === 0) { + return (this.sign * this.mag).toExponential(places); + } + return this.toStringWithDecimalPlaces(places); + } + + public toFixed(places: number): string { + if (this.layer === 0) { + return (this.sign * this.mag).toFixed(places); + } + return this.toStringWithDecimalPlaces(places); + } + + public toPrecision(places: number): string { + if (this.e <= -7) { + return this.toExponential(places - 1); + } + + if (places > this.e) { + return this.toFixed(places - this.exponent - 1); + } + + return this.toExponential(places - 1); + } + + public valueOf(): string { + return this.toString(); + } + + public toJSON(): string { + return this.toString(); + } + + public toStringWithDecimalPlaces(places: number): string { + if (this.layer === 0) { + if ((this.mag < 1e21 && this.mag > 1e-7) || this.mag === 0) { + return (this.sign * this.mag).toFixed(places); + } + return decimalPlaces(this.m, places) + "e" + decimalPlaces(this.e, places); + } else if (this.layer === 1) { + return decimalPlaces(this.m, places) + "e" + decimalPlaces(this.e, places); + } else { + //layer 2+ + if (this.layer <= MAX_ES_IN_A_ROW) { + return ( + (this.sign === -1 ? "-" : "") + + "e".repeat(this.layer) + + decimalPlaces(this.mag, places) + ); + } else { + return ( + (this.sign === -1 ? "-" : "") + + "(e^" + + this.layer + + ")" + + decimalPlaces(this.mag, places) + ); + } + } + } + + public abs(): Decimal { + return FC_NN(this.sign === 0 ? 0 : 1, this.layer, this.mag); + } + + public neg(): Decimal { + return FC_NN(-this.sign, this.layer, this.mag); + } + + public negate(): Decimal { + return this.neg(); + } + + public negated(): Decimal { + return this.neg(); + } + + // public sign () { + // return this.sign; + // } + + public sgn(): number { + return this.sign; + } + + public round(): this | Decimal { + if (this.mag < 0) { + return Decimal.dZero; + } + if (this.layer === 0) { + return FC(this.sign, 0, Math.round(this.mag)); + } + return this; + } + + public floor(): this | Decimal { + if (this.mag < 0) { + return Decimal.dZero; + } + if (this.layer === 0) { + return FC(this.sign, 0, Math.floor(this.mag)); + } + return this; + } + + public ceil(): this | Decimal { + if (this.mag < 0) { + return Decimal.dZero; + } + if (this.layer === 0) { + return FC(this.sign, 0, Math.ceil(this.mag)); + } + return this; + } + + public trunc(): this | Decimal { + if (this.mag < 0) { + return Decimal.dZero; + } + if (this.layer === 0) { + return FC(this.sign, 0, Math.trunc(this.mag)); + } + return this; + } + + public add(value: DecimalSource): this | Decimal { + const decimal = D(value); + + //inf/nan check + if (!Number.isFinite(this.layer)) { + return this; + } + if (!Number.isFinite(decimal.layer)) { + return decimal; + } + + //Special case - if one of the numbers is 0, return the other number. + if (this.sign === 0) { + return decimal; + } + if (decimal.sign === 0) { + return this; + } + + //Special case - Adding a number to its negation produces 0, no matter how large. + if ( + this.sign === -decimal.sign && + this.layer === decimal.layer && + this.mag === decimal.mag + ) { + return FC_NN(0, 0, 0); + } + + let a; + let b; + + //Special case: If one of the numbers is layer 2 or higher, just take the bigger number. + if (this.layer >= 2 || decimal.layer >= 2) { + return this.maxabs(decimal); + } + + if (Decimal.cmpabs(this, decimal) > 0) { + a = this; + b = decimal; + } else { + a = decimal; + b = this; + } + + if (a.layer === 0 && b.layer === 0) { + return Decimal.fromNumber(a.sign * a.mag + b.sign * b.mag); + } + + const layera = a.layer * Math.sign(a.mag); + const layerb = b.layer * Math.sign(b.mag); + + //If one of the numbers is 2+ layers higher than the other, just take the bigger number. + if (layera - layerb >= 2) { + return a; + } + + if (layera === 0 && layerb === -1) { + if (Math.abs(b.mag - Math.log10(a.mag)) > MAX_SIGNIFICANT_DIGITS) { + return a; + } else { + const magdiff = Math.pow(10, Math.log10(a.mag) - b.mag); + const mantissa = b.sign + a.sign * magdiff; + return FC(Math.sign(mantissa), 1, b.mag + Math.log10(Math.abs(mantissa))); + } + } + + if (layera === 1 && layerb === 0) { + if (Math.abs(a.mag - Math.log10(b.mag)) > MAX_SIGNIFICANT_DIGITS) { + return a; + } else { + const magdiff = Math.pow(10, a.mag - Math.log10(b.mag)); + const mantissa = b.sign + a.sign * magdiff; + return FC( + Math.sign(mantissa), + 1, + Math.log10(b.mag) + Math.log10(Math.abs(mantissa)) + ); + } + } + + if (Math.abs(a.mag - b.mag) > MAX_SIGNIFICANT_DIGITS) { + return a; + } else { + const magdiff = Math.pow(10, a.mag - b.mag); + const mantissa = b.sign + a.sign * magdiff; + return FC(Math.sign(mantissa), 1, b.mag + Math.log10(Math.abs(mantissa))); + } + + throw Error("Bad arguments to add: " + this + ", " + value); + } + + public plus(value: DecimalSource): Decimal { + return this.add(value); + } + + public sub(value: DecimalSource): Decimal { + return this.add(D(value).neg()); + } + + public subtract(value: DecimalSource): Decimal { + return this.sub(value); + } + + public minus(value: DecimalSource): Decimal { + return this.sub(value); + } + + public mul(value: DecimalSource): Decimal { + const decimal = D(value); + + //inf/nan check + if (!Number.isFinite(this.layer)) { + return this; + } + if (!Number.isFinite(decimal.layer)) { + return decimal; + } + + //Special case - if one of the numbers is 0, return 0. + if (this.sign === 0 || decimal.sign === 0) { + return FC_NN(0, 0, 0); + } + + //Special case - Multiplying a number by its own reciprocal yields +/- 1, no matter how large. + if (this.layer === decimal.layer && this.mag === -decimal.mag) { + return FC_NN(this.sign * decimal.sign, 0, 1); + } + + let a; + let b; + + //Which number is bigger in terms of its multiplicative distance from 1? + if ( + this.layer > decimal.layer || + (this.layer == decimal.layer && Math.abs(this.mag) > Math.abs(decimal.mag)) + ) { + a = this; + b = decimal; + } else { + a = decimal; + b = this; + } + + if (a.layer === 0 && b.layer === 0) { + return Decimal.fromNumber(a.sign * b.sign * a.mag * b.mag); + } + + //Special case: If one of the numbers is layer 3 or higher or one of the numbers is 2+ layers bigger than the other, just take the bigger number. + if (a.layer >= 3 || a.layer - b.layer >= 2) { + return FC(a.sign * b.sign, a.layer, a.mag); + } + + if (a.layer === 1 && b.layer === 0) { + return FC(a.sign * b.sign, 1, a.mag + Math.log10(b.mag)); + } + + if (a.layer === 1 && b.layer === 1) { + return FC(a.sign * b.sign, 1, a.mag + b.mag); + } + + if (a.layer === 2 && b.layer === 1) { + const newmag = FC(Math.sign(a.mag), a.layer - 1, Math.abs(a.mag)).add( + FC(Math.sign(b.mag), b.layer - 1, Math.abs(b.mag)) + ); + return FC(a.sign * b.sign, newmag.layer + 1, newmag.sign * newmag.mag); + } + + if (a.layer === 2 && b.layer === 2) { + const newmag = FC(Math.sign(a.mag), a.layer - 1, Math.abs(a.mag)).add( + FC(Math.sign(b.mag), b.layer - 1, Math.abs(b.mag)) + ); + return FC(a.sign * b.sign, newmag.layer + 1, newmag.sign * newmag.mag); + } + + throw Error("Bad arguments to mul: " + this + ", " + value); + } + + public multiply(value: DecimalSource): Decimal { + return this.mul(value); + } + + public times(value: DecimalSource): Decimal { + return this.mul(value); + } + + public div(value: DecimalSource): Decimal { + const decimal = D(value); + return this.mul(decimal.recip()); + } + + public divide(value: DecimalSource): Decimal { + return this.div(value); + } + + public divideBy(value: DecimalSource): Decimal { + return this.div(value); + } + + public dividedBy(value: DecimalSource): Decimal { + return this.div(value); + } + + public recip(): Decimal { + if (this.mag === 0) { + return Decimal.dNaN; + } else if (this.layer === 0) { + return FC(this.sign, 0, 1 / this.mag); + } else { + return FC(this.sign, this.layer, -this.mag); + } + } + + public reciprocal(): Decimal { + return this.recip(); + } + + public reciprocate(): Decimal { + return this.recip(); + } + + /** + * -1 for less than value, 0 for equals value, 1 for greater than value + */ + public cmp(value: DecimalSource): CompareResult { + const decimal = D(value); + if (this.sign > decimal.sign) { + return 1; + } + if (this.sign < decimal.sign) { + return -1; + } + return (this.sign * this.cmpabs(value)) as CompareResult; + } + + public cmpabs(value: DecimalSource): CompareResult { + const decimal = D(value); + const layera = this.mag > 0 ? this.layer : -this.layer; + const layerb = decimal.mag > 0 ? decimal.layer : -decimal.layer; + if (layera > layerb) { + return 1; + } + if (layera < layerb) { + return -1; + } + if (this.mag > decimal.mag) { + return 1; + } + if (this.mag < decimal.mag) { + return -1; + } + return 0; + } + + public compare(value: DecimalSource): CompareResult { + return this.cmp(value); + } + + public isNan(): boolean { + return isNaN(this.sign) || isNaN(this.layer) || isNaN(this.mag); + } + + public isFinite(): boolean { + return isFinite(this.sign) && isFinite(this.layer) && isFinite(this.mag); + } + + public eq(value: DecimalSource): boolean { + const decimal = D(value); + return ( + this.sign === decimal.sign && this.layer === decimal.layer && this.mag === decimal.mag + ); + } + + public equals(value: DecimalSource): boolean { + return this.eq(value); + } + + public neq(value: DecimalSource): boolean { + return !this.eq(value); + } + + public notEquals(value: DecimalSource): boolean { + return this.neq(value); + } + + public lt(value: DecimalSource): boolean { + return this.cmp(value) === -1; + } + + public lte(value: DecimalSource): boolean { + return !this.gt(value); + } + + public gt(value: DecimalSource): boolean { + return this.cmp(value) === 1; + } + + public gte(value: DecimalSource): boolean { + return !this.lt(value); + } + + public max(value: DecimalSource): Decimal { + const decimal = D(value); + return this.lt(decimal) ? decimal : this; + } + + public min(value: DecimalSource): Decimal { + const decimal = D(value); + return this.gt(decimal) ? decimal : this; + } + + public maxabs(value: DecimalSource): Decimal { + const decimal = D(value); + return this.cmpabs(decimal) < 0 ? decimal : this; + } + + public minabs(value: DecimalSource): Decimal { + const decimal = D(value); + return this.cmpabs(decimal) > 0 ? decimal : this; + } + + public clamp(min: DecimalSource, max: DecimalSource): Decimal { + return this.max(min).min(max); + } + + public clampMin(min: DecimalSource): Decimal { + return this.max(min); + } + + public clampMax(max: DecimalSource): Decimal { + return this.min(max); + } + + public cmp_tolerance(value: DecimalSource, tolerance: number): CompareResult { + const decimal = D(value); + return this.eq_tolerance(decimal, tolerance) ? 0 : this.cmp(decimal); + } + + public compare_tolerance(value: DecimalSource, tolerance: number): CompareResult { + return this.cmp_tolerance(value, tolerance); + } + + /** + * Tolerance is a relative tolerance, multiplied by the greater of the magnitudes of the two arguments. + * For example, if you put in 1e-9, then any number closer to the + * larger number than (larger number)*1e-9 will be considered equal. + */ + public eq_tolerance(value: DecimalSource, tolerance?: number): boolean { + const decimal = D(value); // https://stackoverflow.com/a/33024979 + if (tolerance == null) { + tolerance = 1e-7; + } + //Numbers that are too far away are never close. + if (this.sign !== decimal.sign) { + return false; + } + if (Math.abs(this.layer - decimal.layer) > 1) { + return false; + } + // return abs(a-b) <= tolerance * max(abs(a), abs(b)) + let magA = this.mag; + let magB = decimal.mag; + if (this.layer > decimal.layer) { + magB = f_maglog10(magB); + } + if (this.layer < decimal.layer) { + magA = f_maglog10(magA); + } + return Math.abs(magA - magB) <= tolerance * Math.max(Math.abs(magA), Math.abs(magB)); + } + + public equals_tolerance(value: DecimalSource, tolerance: number): boolean { + return this.eq_tolerance(value, tolerance); + } + + public neq_tolerance(value: DecimalSource, tolerance: number): boolean { + return !this.eq_tolerance(value, tolerance); + } + + public notEquals_tolerance(value: DecimalSource, tolerance: number): boolean { + return this.neq_tolerance(value, tolerance); + } + + public lt_tolerance(value: DecimalSource, tolerance: number): boolean { + const decimal = D(value); + return !this.eq_tolerance(decimal, tolerance) && this.lt(decimal); + } + + public lte_tolerance(value: DecimalSource, tolerance: number): boolean { + const decimal = D(value); + return this.eq_tolerance(decimal, tolerance) || this.lt(decimal); + } + + public gt_tolerance(value: DecimalSource, tolerance: number): boolean { + const decimal = D(value); + return !this.eq_tolerance(decimal, tolerance) && this.gt(decimal); + } + + public gte_tolerance(value: DecimalSource, tolerance: number): boolean { + const decimal = D(value); + return this.eq_tolerance(decimal, tolerance) || this.gt(decimal); + } + + public pLog10(): Decimal { + if (this.lt(Decimal.dZero)) { + return Decimal.dZero; + } + return this.log10(); + } + + public absLog10(): Decimal { + if (this.sign === 0) { + return Decimal.dNaN; + } else if (this.layer > 0) { + return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); + } else { + return FC(1, 0, Math.log10(this.mag)); + } + } + + public log10(): Decimal { + if (this.sign <= 0) { + return Decimal.dNaN; + } else if (this.layer > 0) { + return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); + } else { + return FC(this.sign, 0, Math.log10(this.mag)); + } + } + + public log(base: DecimalSource): Decimal { + base = D(base); + if (this.sign <= 0) { + return Decimal.dNaN; + } + if (base.sign <= 0) { + return Decimal.dNaN; + } + if (base.sign === 1 && base.layer === 0 && base.mag === 1) { + return Decimal.dNaN; + } else if (this.layer === 0 && base.layer === 0) { + return FC(this.sign, 0, Math.log(this.mag) / Math.log(base.mag)); + } + + return Decimal.div(this.log10(), base.log10()); + } + + public log2(): Decimal { + if (this.sign <= 0) { + return Decimal.dNaN; + } else if (this.layer === 0) { + return FC(this.sign, 0, Math.log2(this.mag)); + } else if (this.layer === 1) { + return FC(Math.sign(this.mag), 0, Math.abs(this.mag) * 3.321928094887362); //log2(10) + } else if (this.layer === 2) { + return FC(Math.sign(this.mag), 1, Math.abs(this.mag) + 0.5213902276543247); //-log10(log10(2)) + } else { + return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); + } + } + + public ln(): Decimal { + if (this.sign <= 0) { + return Decimal.dNaN; + } else if (this.layer === 0) { + return FC(this.sign, 0, Math.log(this.mag)); + } else if (this.layer === 1) { + return FC(Math.sign(this.mag), 0, Math.abs(this.mag) * 2.302585092994046); //ln(10) + } else if (this.layer === 2) { + return FC(Math.sign(this.mag), 1, Math.abs(this.mag) + 0.36221568869946325); //log10(log10(e)) + } else { + return FC(Math.sign(this.mag), this.layer - 1, Math.abs(this.mag)); + } + } + + public logarithm(base: DecimalSource): Decimal { + return this.log(base); + } + + public pow(value: DecimalSource): Decimal { + const decimal = D(value); + const a = this; + const b = decimal; + + //special case: if a is 0, then return 0 (UNLESS b is 0, then return 1) + if (a.sign === 0) { + return b.eq(0) ? FC_NN(1, 0, 1) : a; + } + //special case: if a is 1, then return 1 + if (a.sign === 1 && a.layer === 0 && a.mag === 1) { + return a; + } + //special case: if b is 0, then return 1 + if (b.sign === 0) { + return FC_NN(1, 0, 1); + } + //special case: if b is 1, then return a + if (b.sign === 1 && b.layer === 0 && b.mag === 1) { + return a; + } + + const result = a.absLog10().mul(b).pow10(); + + if (this.sign === -1) { + if (Math.abs(b.toNumber() % 2) % 2 === 1) { + return result.neg(); + } else if (Math.abs(b.toNumber() % 2) % 2 === 0) { + return result; + } + return Decimal.dNaN; + } + + return result; + } + + public pow10(): Decimal { + /* + There are four cases we need to consider: + 1) positive sign, positive mag (e15, ee15): +1 layer (e.g. 10^15 becomes e15, 10^e15 becomes ee15) + 2) negative sign, positive mag (-e15, -ee15): +1 layer but sign and mag sign are flipped (e.g. 10^-15 becomes e-15, 10^-e15 becomes ee-15) + 3) positive sign, negative mag (e-15, ee-15): layer 0 case would have been handled in the Math.pow check, so just return 1 + 4) negative sign, negative mag (-e-15, -ee-15): layer 0 case would have been handled in the Math.pow check, so just return 1 + */ + + if (!Number.isFinite(this.layer) || !Number.isFinite(this.mag)) { + return Decimal.dNaN; + } + + let a: Decimal = this; + + //handle layer 0 case - if no precision is lost just use Math.pow, else promote one layer + if (a.layer === 0) { + const newmag = Math.pow(10, a.sign * a.mag); + if (Number.isFinite(newmag) && Math.abs(newmag) >= 0.1) { + return FC(1, 0, newmag); + } else { + if (a.sign === 0) { + return Decimal.dOne; + } else { + a = FC_NN(a.sign, a.layer + 1, Math.log10(a.mag)); + } + } + } + + //handle all 4 layer 1+ cases individually + if (a.sign > 0 && a.mag >= 0) { + return FC(a.sign, a.layer + 1, a.mag); + } + if (a.sign < 0 && a.mag >= 0) { + return FC(-a.sign, a.layer + 1, -a.mag); + } + //both the negative mag cases are identical: one +/- rounding error + return Decimal.dOne; + } + + public pow_base(value: DecimalSource): Decimal { + return D(value).pow(this); + } + + public root(value: DecimalSource): Decimal { + const decimal = D(value); + return this.pow(decimal.recip()); + } + + public factorial(): Decimal { + if (this.mag < 0) { + return this.add(1).gamma(); + } else if (this.layer === 0) { + return this.add(1).gamma(); + } else if (this.layer === 1) { + return Decimal.exp(Decimal.mul(this, Decimal.ln(this).sub(1))); + } else { + return Decimal.exp(this); + } + } + + //from HyperCalc source code + public gamma(): Decimal { + if (this.mag < 0) { + return this.recip(); + } else if (this.layer === 0) { + if (this.lt(FC_NN(1, 0, 24))) { + return Decimal.fromNumber(f_gamma(this.sign * this.mag)); + } + + const t = this.mag - 1; + let l = 0.9189385332046727; //0.5*Math.log(2*Math.PI) + l = l + (t + 0.5) * Math.log(t); + l = l - t; + const n2 = t * t; + let np = t; + let lm = 12 * np; + let adj = 1 / lm; + let l2 = l + adj; + if (l2 === l) { + return Decimal.exp(l); + } + + l = l2; + np = np * n2; + lm = 360 * np; + adj = 1 / lm; + l2 = l - adj; + if (l2 === l) { + return Decimal.exp(l); + } + + l = l2; + np = np * n2; + lm = 1260 * np; + let lt = 1 / lm; + l = l + lt; + np = np * n2; + lm = 1680 * np; + lt = 1 / lm; + l = l - lt; + return Decimal.exp(l); + } else if (this.layer === 1) { + return Decimal.exp(Decimal.mul(this, Decimal.ln(this).sub(1))); + } else { + return Decimal.exp(this); + } + } + + public lngamma(): Decimal { + return this.gamma().ln(); + } + + public exp(): Decimal { + if (this.mag < 0) { + return Decimal.dOne; + } + if (this.layer === 0 && this.mag <= 709.7) { + return Decimal.fromNumber(Math.exp(this.sign * this.mag)); + } else if (this.layer === 0) { + return FC(1, 1, this.sign * Math.log10(Math.E) * this.mag); + } else if (this.layer === 1) { + return FC(1, 2, this.sign * (Math.log10(0.4342944819032518) + this.mag)); + } else { + return FC(1, this.layer + 1, this.sign * this.mag); + } + } + + public sqr(): Decimal { + return this.pow(2); + } + + public sqrt(): Decimal { + if (this.layer === 0) { + return Decimal.fromNumber(Math.sqrt(this.sign * this.mag)); + } else if (this.layer === 1) { + return FC(1, 2, Math.log10(this.mag) - 0.3010299956639812); + } else { + const result = Decimal.div(FC_NN(this.sign, this.layer - 1, this.mag), FC_NN(1, 0, 2)); + result.layer += 1; + result.normalize(); + return result; + } + } + + public cube(): Decimal { + return this.pow(3); + } + + public cbrt(): Decimal { + return this.pow(1 / 3); + } + + //Tetration/tetrate: The result of exponentiating 'this' to 'this' 'height' times in a row. https://en.wikipedia.org/wiki/Tetration + //If payload != 1, then this is 'iterated exponentiation', the result of exping (payload) to base (this) (height) times. https://andydude.github.io/tetration/archives/tetration2/ident.html + //Works with negative and positive real heights. + public tetrate(height = 2, payload: DecimalSource = FC_NN(1, 0, 1)): Decimal { + //x^^1 == x + if (height === 1) { + return Decimal.pow(this, payload); + } + //x^^0 == 1 + if (height === 0) { + return new Decimal(payload); + } + //1^^x == 1 + if (this.eq(Decimal.dOne)) { + return Decimal.dOne; + } + //-1^^x == -1 + if (this.eq(-1)) { + return Decimal.pow(this, payload); + } + + if (height === Number.POSITIVE_INFINITY) { + const this_num = this.toNumber(); + //within the convergence range? + if (this_num <= 1.44466786100976613366 && this_num >= 0.06598803584531253708) { + //hotfix for the very edge of the number range not being handled properly + if (this_num > 1.444667861009099) { + return Decimal.fromNumber(Math.E); + } + //Formula for infinite height power tower. + const negln = Decimal.ln(this).neg(); + return negln.lambertw().div(negln); + } else if (this_num > 1.44466786100976613366) { + //explodes to infinity + // TODO: replace this with Decimal.dInf + return Decimal.fromNumber(Number.POSITIVE_INFINITY); + } else { + //0.06598803584531253708 > this_num >= 0: never converges + //this_num < 0: quickly becomes a complex number + return Decimal.dNaN; + } + } + + //0^^x oscillates if we define 0^0 == 1 (which in javascript land we do), since then 0^^1 is 0, 0^^2 is 1, 0^^3 is 0, etc. payload is ignored + //using the linear approximation for height (TODO: don't know a better way to calculate it ATM, but it wouldn't surprise me if it's just NaN) + if (this.eq(Decimal.dZero)) { + let result = Math.abs((height + 1) % 2); + if (result > 1) { + result = 2 - result; + } + return Decimal.fromNumber(result); + } + + if (height < 0) { + return Decimal.iteratedlog(payload, this, -height); + } + + payload = D(payload); + const oldheight = height; + height = Math.trunc(height); + const fracheight = oldheight - height; + + if (this.gt(Decimal.dZero) && this.lte(1.44466786100976613366)) { + //similar to 0^^n, flip-flops between two values, converging slowly (or if it's below 0.06598803584531253708, never. so once again, the fractional part at the end will be a linear approximation (TODO: again pending knowledge of how to approximate better, although tbh I think it should in reality just be NaN) + height = Math.min(10000, height); + for (let i = 0; i < height; ++i) { + const old_payload: Decimal = payload; + payload = this.pow(payload); + //stop early if we converge + if (old_payload.eq(payload)) { + return payload; + } + } + if (fracheight != 0) { + const next_payload = this.pow(payload); + return payload.mul(1 - fracheight).add(next_payload.mul(fracheight)); + } + return payload; + } + //TODO: base < 0, but it's hard for me to reason about (probably all non-integer heights are NaN automatically?) + + if (fracheight !== 0) { + if (payload.eq(Decimal.dOne)) { + //TODO: for bases above 10, revert to old linear approximation until I can think of something better + if (this.gt(10)) { + payload = this.pow(fracheight); + } else { + payload = Decimal.fromNumber( + Decimal.tetrate_critical(this.toNumber(), fracheight) + ); + //TODO: until the critical section grid can handle numbers below 2, scale them to the base + //TODO: maybe once the critical section grid has very large bases, this math can be appropriate for them too? I'll think about it + if (this.lt(2)) { + payload = payload.sub(1).mul(this.minus(1)).plus(1); + } + } + } else { + if (this.eq(10)) { + payload = payload.layeradd10(fracheight); + } else { + payload = payload.layeradd(fracheight, this); + } + } + } + + for (let i = 0; i < height; ++i) { + payload = this.pow(payload); + //bail if we're NaN + if (!isFinite(payload.layer) || !isFinite(payload.mag)) { + return payload.normalize(); + } + //shortcut + if (payload.layer - this.layer > 3) { + return FC_NN(payload.sign, payload.layer + (height - i - 1), payload.mag); + } + //give up after 10000 iterations if nothing is happening + if (i > 10000) { + return payload; + } + } + return payload; + } + + //iteratedexp/iterated exponentiation: - all cases handled in tetrate, so just call it + public iteratedexp(height = 2, payload = FC_NN(1, 0, 1)): Decimal { + return this.tetrate(height, payload); + } + + //iterated log/repeated log: The result of applying log(base) 'times' times in a row. Approximately equal to subtracting (times) from the number's slog representation. Equivalent to tetrating to a negative height. + //Works with negative and positive real heights. + public iteratedlog(base: DecimalSource = 10, times = 1): Decimal { + if (times < 0) { + return Decimal.tetrate(base, -times, this); + } + + base = D(base); + let result = Decimal.fromDecimal(this); + const fulltimes = times; + times = Math.trunc(times); + const fraction = fulltimes - times; + if (result.layer - base.layer > 3) { + const layerloss = Math.min(times, result.layer - base.layer - 3); + times -= layerloss; + result.layer -= layerloss; + } + + for (let i = 0; i < times; ++i) { + result = result.log(base); + //bail if we're NaN + if (!isFinite(result.layer) || !isFinite(result.mag)) { + return result.normalize(); + } + //give up after 10000 iterations if nothing is happening + if (i > 10000) { + return result; + } + } + + //handle fractional part + if (fraction > 0 && fraction < 1) { + if (base.eq(10)) { + result = result.layeradd10(-fraction); + } else { + result = result.layeradd(-fraction, base); + } + } + + return result; + } + + //Super-logarithm, one of tetration's inverses, tells you what size power tower you'd have to tetrate base to to get number. By definition, will never be higher than 1.8e308 in break_eternity.js, since a power tower 1.8e308 numbers tall is the largest representable number. + // https://en.wikipedia.org/wiki/Super-logarithm + // NEW: Accept a number of iterations, and use binary search to, after making an initial guess, hone in on the true value, assuming tetration as the ground truth. + public slog(base: DecimalSource = 10, iterations = 100): Decimal { + let step_size = 0.001; + let has_changed_directions_once = false; + let previously_rose = false; + let result = this.slog_internal(base).toNumber(); + for (let i = 1; i < iterations; ++i) { + const new_decimal = new Decimal(base).tetrate(result); + const currently_rose = new_decimal.gt(this); + if (i > 1) { + if (previously_rose != currently_rose) { + has_changed_directions_once = true; + } + } + previously_rose = currently_rose; + if (has_changed_directions_once) { + step_size /= 2; + } else { + step_size *= 2; + } + step_size = Math.abs(step_size) * (currently_rose ? -1 : 1); + result += step_size; + if (step_size === 0) { + break; + } + } + return Decimal.fromNumber(result); + } + + public slog_internal(base: DecimalSource = 10): Decimal { + base = D(base); + + //special cases: + //slog base 0 or lower is NaN + if (base.lte(Decimal.dZero)) { + return Decimal.dNaN; + } + //slog base 1 is NaN + if (base.eq(Decimal.dOne)) { + return Decimal.dNaN; + } + //need to handle these small, wobbling bases specially + if (base.lt(Decimal.dOne)) { + if (this.eq(Decimal.dOne)) { + return Decimal.dZero; + } + if (this.eq(Decimal.dZero)) { + return Decimal.dNegOne; + } + //0 < this < 1: ambiguous (happens multiple times) + //this < 0: impossible (as far as I can tell) + //this > 1: partially complex (http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html base 0.25 for proof) + return Decimal.dNaN; + } + //slog_n(0) is -1 + if (this.mag < 0 || this.eq(Decimal.dZero)) { + return Decimal.dNegOne; + } + + let result = 0; + let copy = Decimal.fromDecimal(this); + if (copy.layer - base.layer > 3) { + const layerloss = copy.layer - base.layer - 3; + result += layerloss; + copy.layer -= layerloss; + } + + for (let i = 0; i < 100; ++i) { + if (copy.lt(Decimal.dZero)) { + copy = Decimal.pow(base, copy); + result -= 1; + } else if (copy.lte(Decimal.dOne)) { + return Decimal.fromNumber( + result + Decimal.slog_critical(base.toNumber(), copy.toNumber()) + ); + } else { + result += 1; + copy = Decimal.log(copy, base); + } + } + return Decimal.fromNumber(result); + } + + //background info and tables of values for critical functions taken here: https://github.com/Patashu/break_eternity.js/issues/22 + public static slog_critical(base: number, height: number): number { + //TODO: for bases above 10, revert to old linear approximation until I can think of something better + if (base > 10) { + return height - 1; + } + return Decimal.critical_section(base, height, critical_slog_values); + } + + public static tetrate_critical(base: number, height: number): number { + return Decimal.critical_section(base, height, critical_tetr_values); + } + + public static critical_section(base: number, height: number, grid: number[][]): number { + //this part is simple at least, since it's just 0.1 to 0.9 + height *= 10; + if (height < 0) { + height = 0; + } + if (height > 10) { + height = 10; + } + //have to do this complicated song and dance since one of the critical_headers is Math.E, and in the future I'd like 1.5 as well + if (base < 2) { + base = 2; + } + if (base > 10) { + base = 10; + } + let lower = 0; + let upper = 0; + //basically, if we're between bases, we interpolate each bases' relevant values together + //then we interpolate based on what the fractional height is. + //accuracy could be improved by doing a non-linear interpolation (maybe), by adding more bases and heights (definitely) but this is AFAIK the best you can get without running some pari.gp or mathematica program to calculate exact values + //however, do note http://myweb.astate.edu/wpaulsen/tetcalc/tetcalc.html can do it for arbitrary heights but not for arbitrary bases (2, e, 10 present) + for (let i = 0; i < critical_headers.length; ++i) { + if (critical_headers[i] == base) { + // exact match + lower = grid[i][Math.floor(height)]; + upper = grid[i][Math.ceil(height)]; + break; + } else if (critical_headers[i] < base && critical_headers[i + 1] > base) { + // interpolate between this and the next + const basefrac = + (base - critical_headers[i]) / (critical_headers[i + 1] - critical_headers[i]); + lower = + grid[i][Math.floor(height)] * (1 - basefrac) + + grid[i + 1][Math.floor(height)] * basefrac; + upper = + grid[i][Math.ceil(height)] * (1 - basefrac) + + grid[i + 1][Math.ceil(height)] * basefrac; + break; + } + } + const frac = height - Math.floor(height); + //improvement - you get more accuracy (especially around 0.9-1.0) by doing log, then frac, then powing the result + //(we could pre-log the lookup table, but then fractional bases would get Weird) + //also, use old linear for slog (values 0 or less in critical section). maybe something else is better but haven't thought about what yet + if (lower <= 0 || upper <= 0) { + return lower * (1 - frac) + upper * frac; + } else { + return Math.pow( + base, + (Math.log(lower) / Math.log(base)) * (1 - frac) + + (Math.log(upper) / Math.log(base)) * frac + ); + } + } + + //Function for adding/removing layers from a Decimal, even fractional layers (e.g. its slog10 representation). + //Moved this over to use the same critical section as tetrate/slog. + public layeradd10(diff: DecimalSource): Decimal { + diff = Decimal.fromValue_noAlloc(diff).toNumber(); + const result = Decimal.fromDecimal(this); + if (diff >= 1) { + //bug fix: if result is very smol (mag < 0, layer > 0) turn it into 0 first + if (result.mag < 0 && result.layer > 0) { + result.sign = 0; + result.mag = 0; + result.layer = 0; + } else if (result.sign === -1 && result.layer == 0) { + //bug fix - for stuff like -3.layeradd10(1) we need to move the sign to the mag + result.sign = 1; + result.mag = -result.mag; + } + const layeradd = Math.trunc(diff); + diff -= layeradd; + result.layer += layeradd; + } + if (diff <= -1) { + const layeradd = Math.trunc(diff); + diff -= layeradd; + result.layer += layeradd; + if (result.layer < 0) { + for (let i = 0; i < 100; ++i) { + result.layer++; + result.mag = Math.log10(result.mag); + if (!isFinite(result.mag)) { + //another bugfix: if we hit -Infinity mag, then we should return negative infinity, not 0. 0.layeradd10(-1) h its this + if (result.sign === 0) { + result.sign = 1; + } + //also this, for 0.layeradd10(-2) + if (result.layer < 0) { + result.layer = 0; + } + return result.normalize(); + } + if (result.layer >= 0) { + break; + } + } + } + } + + while (result.layer < 0) { + result.layer++; + result.mag = Math.log10(result.mag); + } + //bugfix: before we normalize: if we started with 0, we now need to manually fix a layer ourselves! + if (result.sign === 0) { + result.sign = 1; + if (result.mag === 0 && result.layer >= 1) { + result.layer -= 1; + result.mag = 1; + } + } + result.normalize(); + + //layeradd10: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 10 and iterated log base 10. Also equivalent to adding a fractional amount to the number's layer in its break_eternity.js representation. + if (diff !== 0) { + return result.layeradd(diff, 10); //safe, only calls positive height 1 payload tetration, slog and log + } + + return result; + } + + //layeradd: like adding 'diff' to the number's slog(base) representation. Very similar to tetrate base 'base' and iterated log base 'base'. + public layeradd(diff: number, base: DecimalSource): Decimal { + const slogthis = this.slog(base).toNumber(); + const slogdest = slogthis + diff; + if (slogdest >= 0) { + return Decimal.tetrate(base, slogdest); + } else if (!Number.isFinite(slogdest)) { + return Decimal.dNaN; + } else if (slogdest >= -1) { + return Decimal.log(Decimal.tetrate(base, slogdest + 1), base); + } else { + return Decimal.log(Decimal.log(Decimal.tetrate(base, slogdest + 2), base), base); + } + } + + //The Lambert W function, also called the omega function or product logarithm, is the solution W(x) === x*e^x. + // https://en.wikipedia.org/wiki/Lambert_W_function + //Some special values, for testing: https://en.wikipedia.org/wiki/Lambert_W_function#Special_values + public lambertw(): Decimal { + if (this.lt(-0.3678794411710499)) { + throw Error("lambertw is unimplemented for results less than -1, sorry!"); + } else if (this.mag < 0) { + return Decimal.fromNumber(f_lambertw(this.toNumber())); + } else if (this.layer === 0) { + return Decimal.fromNumber(f_lambertw(this.sign * this.mag)); + } else if (this.layer === 1) { + return d_lambertw(this); + } else if (this.layer === 2) { + return d_lambertw(this); + } + if (this.layer >= 3) { + return FC_NN(this.sign, this.layer - 1, this.mag); + } + + throw "Unhandled behavior in lambertw()"; + } + + //The super square-root function - what number, tetrated to height 2, equals this? + //Other sroots are possible to calculate probably through guess and check methods, this one is easy though. + // https://en.wikipedia.org/wiki/Tetration#Super-root + public ssqrt(): Decimal { + if (this.sign == 1 && this.layer >= 3) { + return FC_NN(this.sign, this.layer - 1, this.mag); + } + const lnx = this.ln(); + return lnx.div(lnx.lambertw()); + } + + //Pentation/pentate: The result of tetrating 'height' times in a row. An absurdly strong operator - Decimal.pentate(2, 4.28) and Decimal.pentate(10, 2.37) are already too huge for break_eternity.js! + // https://en.wikipedia.org/wiki/Pentation + public pentate(height = 2, payload: DecimalSource = FC_NN(1, 0, 1)): Decimal { + payload = D(payload); + const oldheight = height; + height = Math.trunc(height); + const fracheight = oldheight - height; + + //I have no idea if this is a meaningful approximation for pentation to continuous heights, but it is monotonic and continuous. + if (fracheight !== 0) { + if (payload.eq(Decimal.dOne)) { + ++height; + payload = Decimal.fromNumber(fracheight); + } else { + if (this.eq(10)) { + payload = payload.layeradd10(fracheight); + } else { + payload = payload.layeradd(fracheight, this); + } + } + } + + for (let i = 0; i < height; ++i) { + payload = this.tetrate(payload.toNumber()); + //bail if we're NaN + if (!isFinite(payload.layer) || !isFinite(payload.mag)) { + return payload.normalize(); + } + //give up after 10 iterations if nothing is happening + if (i > 10) { + return payload; + } + } + + return payload; + } + + // trig functions! + public sin(): this | Decimal { + if (this.mag < 0) { + return this; + } + if (this.layer === 0) { + return Decimal.fromNumber(Math.sin(this.sign * this.mag)); + } + return FC_NN(0, 0, 0); + } + + public cos(): Decimal { + if (this.mag < 0) { + return Decimal.dOne; + } + if (this.layer === 0) { + return Decimal.fromNumber(Math.cos(this.sign * this.mag)); + } + return FC_NN(0, 0, 0); + } + + public tan(): this | Decimal { + if (this.mag < 0) { + return this; + } + if (this.layer === 0) { + return Decimal.fromNumber(Math.tan(this.sign * this.mag)); + } + return FC_NN(0, 0, 0); + } + + public asin(): this | Decimal { + if (this.mag < 0) { + return this; + } + if (this.layer === 0) { + return Decimal.fromNumber(Math.asin(this.sign * this.mag)); + } + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } + + public acos(): Decimal { + if (this.mag < 0) { + return Decimal.fromNumber(Math.acos(this.toNumber())); + } + if (this.layer === 0) { + return Decimal.fromNumber(Math.acos(this.sign * this.mag)); + } + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } + + public atan(): this | Decimal { + if (this.mag < 0) { + return this; + } + if (this.layer === 0) { + return Decimal.fromNumber(Math.atan(this.sign * this.mag)); + } + return Decimal.fromNumber(Math.atan(this.sign * 1.8e308)); + } + + public sinh(): Decimal { + return this.exp().sub(this.negate().exp()).div(2); + } + + public cosh(): Decimal { + return this.exp().add(this.negate().exp()).div(2); + } + + public tanh(): Decimal { + return this.sinh().div(this.cosh()); + } + + public asinh(): Decimal { + return Decimal.ln(this.add(this.sqr().add(1).sqrt())); + } + + public acosh(): Decimal { + return Decimal.ln(this.add(this.sqr().sub(1).sqrt())); + } + + public atanh(): Decimal { + if (this.abs().gte(1)) { + return FC_NN(Number.NaN, Number.NaN, Number.NaN); + } + + return Decimal.ln(this.add(1).div(Decimal.fromNumber(1).sub(this))).div(2); + } + + /** + * Joke function from Realm Grinder + */ + public ascensionPenalty(ascensions: DecimalSource): Decimal { + if (ascensions === 0) { + return this; + } + + return this.root(Decimal.pow(10, ascensions)); + } + + /** + * Joke function from Cookie Clicker. It's 'egg' + */ + public egg(): Decimal { + return this.add(9); + } + + public lessThanOrEqualTo(other: DecimalSource): boolean { + return this.cmp(other) < 1; + } + + public lessThan(other: DecimalSource): boolean { + return this.cmp(other) < 0; + } + + public greaterThanOrEqualTo(other: DecimalSource): boolean { + return this.cmp(other) > -1; + } + + public greaterThan(other: DecimalSource): boolean { + return this.cmp(other) > 0; + } + + // return Decimal; +} + +// Assign these after the Decimal is assigned because vitest had issues otherwise +// If we can figure out why, we can make these readonly properties instead +Decimal.dZero = FC_NN(0, 0, 0); +Decimal.dOne = FC_NN(1, 0, 1); +Decimal.dNegOne = FC_NN(-1, 0, 1); +Decimal.dTwo = FC_NN(1, 0, 2); +Decimal.dTen = FC_NN(1, 0, 10); +Decimal.dNaN = FC_NN(Number.NaN, Number.NaN, Number.NaN); +Decimal.dInf = FC_NN(1, Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY); +Decimal.dNegInf = FC_NN(-1, Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY); +Decimal.dNumberMax = FC(1, 0, Number.MAX_VALUE); +Decimal.dNumberMin = FC(1, 0, Number.MIN_VALUE); + +// return Decimal; + +// Optimise Decimal aliases. +// We can't do this optimisation before Decimal is assigned. +D = Decimal.fromValue_noAlloc; +FC = Decimal.fromComponents; +FC_NN = Decimal.fromComponents_noNormalize; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +ME = Decimal.fromMantissaExponent; +// eslint-disable-next-line @typescript-eslint/no-unused-vars +ME_NN = Decimal.fromMantissaExponent_noNormalize; diff --git a/src/lib/collapseTransition.d.ts b/src/lib/collapseTransition.d.ts new file mode 100644 index 0000000..ff06672 --- /dev/null +++ b/src/lib/collapseTransition.d.ts @@ -0,0 +1 @@ +declare module '@ivanv/vue-collapse-transition/src/CollapseTransition.vue'; diff --git a/src/lib/lru-cache.ts b/src/lib/lru-cache.ts new file mode 100644 index 0000000..35363ef --- /dev/null +++ b/src/lib/lru-cache.ts @@ -0,0 +1,139 @@ +/** +* A LRU cache intended for caching pure functions. +*/ +export class LRUCache<K, V> { + private map = new Map<K, ListNode<K, V>>(); + // Invariant: Exactly one of the below is true before and after calling a + // LRUCache method: + // - first and last are both undefined, and map.size() is 0. + // - first and last are the same object, and map.size() is 1. + // - first and last are different objects, and map.size() is greater than 1. + private first: ListNode<K, V> | undefined = undefined; + private last: ListNode<K, V> | undefined = undefined; + maxSize: number; + + /** + * @param maxSize The maximum size for this cache. We recommend setting this + * to be one less than a power of 2, as most hashtables - including V8's + * Object hashtable (https://crsrc.org/c/v8/src/objects/ordered-hash-table.cc) + * - uses powers of two for hashtable sizes. It can't exactly be a power of + * two, as a .set() call could temporarily set the size of the map to be + * maxSize + 1. + */ + constructor(maxSize: number) { + this.maxSize = maxSize; + } + + get size(): number { + return this.map.size; + } + + /** + * Gets the specified key from the cache, or undefined if it is not in the + * cache. + * @param key The key to get. + * @returns The cached value, or undefined if key is not in the cache. + */ + get(key: K): V | undefined { + const node = this.map.get(key); + if (node === undefined) { + return undefined; + } + // It is guaranteed that there is at least one item in the cache. + // Therefore, first and last are guaranteed to be a ListNode... + // but if there is only one item, they might be the same. + + // Update the order of the list to make this node the first node in the + // list. + // This isn't needed if this node is already the first node in the list. + if (node !== this.first) { + // As this node is DIFFERENT from the first node, it is guaranteed that + // there are at least two items in the cache. + // However, this node could possibly be the last item. + if (node === this.last) { + // This node IS the last node. + this.last = node.prev; + // From the invariants, there must be at least two items in the cache, + // so node - which is the original "last node" - must have a defined + // previous node. Therefore, this.last - set above - must be defined + // here. + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.last!.next = undefined; + } else { + // This node is somewhere in the middle of the list, so there must be at + // least THREE items in the list, and this node's prev and next must be + // defined here. + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + node.prev!.next = node.next; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + node.next!.prev = node.prev; + } + node.next = this.first; + // From the invariants, there must be at least two items in the cache, so + // this.first must be a valid ListNode. + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.first!.prev = node; + this.first = node; + } + return node.value; + } + + /** + * Sets an entry in the cache. + * + * @param key The key of the entry. + * @param value The value of the entry. + * @throws Error, if the map already contains the key. + */ + set(key: K, value: V): void { + // Ensure that this.maxSize >= 1. + if (this.maxSize < 1) { + return; + } + if (this.map.has(key)) { + throw new Error("Cannot update existing keys in the cache"); + } + const node = new ListNode(key, value); + // Move node to the front of the list. + if (this.first === undefined) { + // If the first is undefined, the last is undefined too. + // Therefore, this cache has no items in it. + this.first = node; + this.last = node; + } else { + // This cache has at least one item in it. + node.next = this.first; + this.first.prev = node; + this.first = node; + } + this.map.set(key, node); + + while (this.map.size > this.maxSize) { + // We are guaranteed that this.maxSize >= 1, + // so this.map.size is guaranteed to be >= 2, + // so this.first and this.last must be different valid ListNodes, + // and this.last.prev must also be a valid ListNode (possibly this.first). + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const last = this.last!; + this.map.delete(last.key); + this.last = last.prev; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + this.last!.next = undefined; + } + } +} + +/** +* A node in a doubly linked list. +*/ +class ListNode<K, V> { + key: K; + value: V; + next: ListNode<K, V> | undefined = undefined; + prev: ListNode<K, V> | undefined = undefined; + + constructor(key: K, value: V) { + this.key = key; + this.value = value; + } +} \ No newline at end of file diff --git a/src/lib/pixi.ts b/src/lib/pixi.ts new file mode 100644 index 0000000..9db8382 --- /dev/null +++ b/src/lib/pixi.ts @@ -0,0 +1,7 @@ +import { Application } from "@pixi/app"; +import { BatchRenderer, Renderer } from "@pixi/core"; +import { TickerPlugin } from "@pixi/ticker"; + +Application.registerPlugin(TickerPlugin); + +Renderer.registerPlugin("batch", BatchRenderer); diff --git a/src/lib/pwa-register.d.ts b/src/lib/pwa-register.d.ts new file mode 100644 index 0000000..ac20d3c --- /dev/null +++ b/src/lib/pwa-register.d.ts @@ -0,0 +1,17 @@ +declare module 'virtual:pwa-register/vue' { + import type { Ref } from 'vue' + + export interface RegisterSWOptions { + immediate?: boolean + onNeedRefresh?: () => void + onOfflineReady?: () => void + onRegistered?: (registration: ServiceWorkerRegistration | undefined) => void + onRegisterError?: (error: any) => void + } + + export function useRegisterSW(options?: RegisterSWOptions): { + needRefresh: Ref<boolean> + offlineReady: Ref<boolean> + updateServiceWorker: (reloadPage?: boolean) => Promise<void> + } + } \ No newline at end of file diff --git a/src/lib/vue-panzoom.d.ts b/src/lib/vue-panzoom.d.ts new file mode 100644 index 0000000..ec2db3e --- /dev/null +++ b/src/lib/vue-panzoom.d.ts @@ -0,0 +1 @@ +declare module 'vue-panzoom'; diff --git a/src/lib/vue-textarea-autosize.d.ts b/src/lib/vue-textarea-autosize.d.ts new file mode 100644 index 0000000..95c04d9 --- /dev/null +++ b/src/lib/vue-textarea-autosize.d.ts @@ -0,0 +1 @@ +declare module 'vue-textarea-autosize'; diff --git a/src/main.css b/src/main.css new file mode 100644 index 0000000..60188bd --- /dev/null +++ b/src/main.css @@ -0,0 +1,68 @@ +:root { + color-scheme: dark; +} + +* { + transition-duration: 0.5s; + font-family: "Roboto Mono", monospace; + font-weight: bold; + margin: auto; + text-size-adjust: none; +} + +*:focus { + outline: none; +} + +body { + overflow: hidden; + transition: none; + text-align: center; +} + +html, body, #app { + min-height: 100%; + height: 100%; +} + +h1, h2, h3, b, input { + display: inline; +} + +button { + color: black; +} + +a, +.button, +.link { + display: block; + color: var(--link); + background: none; + border: none; + cursor: pointer; + text-decoration: none; +} + +a:hover, +.button:hover, +.link:hover { + text-shadow: 5px 0 10px var(--link), + -3px 0 12px var(--link); +} + +.button:disabled { + opacity: .5; + cursor: not-allowed; +} +.button:disabled:hover { + text-shadow: none; +} + +ul { + list-style-type: none; +} + +.Vue-Toastification__toast { + margin: unset; +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..74893b2 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,81 @@ +import "@fontsource/material-icons"; +import App from "App.vue"; +import projInfo from "data/projInfo.json"; +import "game/notifications"; +import { load } from "util/save"; +import { useRegisterSW } from "virtual:pwa-register/vue"; +import type { App as VueApp } from "vue"; +import { createApp, nextTick } from "vue"; +import { useToast } from "vue-toastification"; + +declare global { + /** + * Augment the window object so the vue app and project info can be accessed from the console. + */ + interface Window { + vue: VueApp; + projInfo: typeof projInfo; + } + + /** Fix for typedoc treating import functions as taking AssertOptions instead of GlobOptions. */ + interface AssertOptions { + as: string; + } +} + +document.title = projInfo.title; +window.projInfo = projInfo; +if (projInfo.id === "") { + throw "Project ID is empty! Please select a unique ID for this project in /src/data/projInfo.json"; +} + +requestAnimationFrame(async () => { + console.log( + "%cMade in Profectus%c\nLearn more at www.moddingtree.com", + "font-weight: bold; font-size: 24px; color: #A3BE8C; background: #2E3440; padding: 4px 8px; border-radius: 8px;", + "padding: 4px;" + ); + await load(); + const { globalBus } = await import("./game/events"); + const { startGameLoop } = await import("./game/gameLoop"); + + // Create Vue + const vue = (window.vue = createApp(App)); + globalBus.emit("setupVue", vue); + vue.mount("#app"); + + // Setup PWA update prompt + nextTick(() => { + const toast = useToast(); + const { updateServiceWorker } = useRegisterSW({ + onNeedRefresh() { + toast.info("New content available, click here to update.", { + timeout: false, + closeOnClick: false, + draggable: false, + icon: { + iconClass: "material-icons", + iconChildren: "refresh", + iconTag: "i" + }, + rtl: false, + onClick() { + updateServiceWorker(); + } + }); + }, + onOfflineReady() { + toast.info("App ready to work offline"); + }, + onRegisterError: console.warn, + onRegistered(r) { + if (r) { + // https://stackoverflow.com/questions/65500916/typeerror-failed-to-execute-update-on-serviceworkerregistration-illegal-in + setInterval(() => r.update(), 60 * 60 * 1000); + } + } + }); + }); + + startGameLoop(); +}); diff --git a/src/util/bignum.ts b/src/util/bignum.ts new file mode 100644 index 0000000..d8e3252 --- /dev/null +++ b/src/util/bignum.ts @@ -0,0 +1,46 @@ +// Import Decimal and numberUtils from a different file to globally change which big num library gets used +// This way switching out big number libraries just needs to happen here, not every file that needs big numbers +import type { DecimalSource as RawDecimalSource } from "lib/break_eternity"; +import Decimal, * as numberUtils from "util/break_eternity"; + +export const { + exponentialFormat, + commaFormat, + regularFormat, + format, + formatWhole, + formatTime, + toPlaces, + formatSmall, + invertOOM +} = numberUtils; + +export type DecimalSource = RawDecimalSource; + +declare global { + /** Augment the window object so the big num functions can be accessed from the console. */ + interface Window { + Decimal: typeof Decimal; + exponentialFormat: (num: DecimalSource, precision: number, mantissa: boolean) => string; + commaFormat: (num: DecimalSource, precision: number) => string; + regularFormat: (num: DecimalSource, precision: number) => string; + format: (num: DecimalSource, precision?: number, small?: boolean) => string; + formatWhole: (num: DecimalSource) => string; + formatTime: (s: number) => string; + toPlaces: (x: DecimalSource, precision: number, maxAccepted: DecimalSource) => string; + formatSmall: (x: DecimalSource, precision?: number) => string; + invertOOM: (x: DecimalSource) => Decimal; + } +} +window.Decimal = Decimal; +window.exponentialFormat = exponentialFormat; +window.commaFormat = commaFormat; +window.regularFormat = regularFormat; +window.format = format; +window.formatWhole = formatWhole; +window.formatTime = formatTime; +window.toPlaces = toPlaces; +window.formatSmall = formatSmall; +window.invertOOM = invertOOM; + +export default Decimal; diff --git a/src/util/break_eternity.ts b/src/util/break_eternity.ts new file mode 100644 index 0000000..dd6aed7 --- /dev/null +++ b/src/util/break_eternity.ts @@ -0,0 +1,196 @@ +import projInfo from "data/projInfo.json"; +import type { DecimalSource } from "lib/break_eternity"; +import Decimal from "lib/break_eternity"; + +export default Decimal; + +const decimalOne = new Decimal(1); + +export function exponentialFormat(num: DecimalSource, precision: number, mantissa = true): string { + let e = Decimal.log10(num).floor(); + let m = Decimal.div(num, Decimal.pow(10, e)); + if (m.toStringWithDecimalPlaces(precision) === "10") { + m = decimalOne; + e = e.add(1); + } + const eString = e.gte(1e9) + ? format(e, Math.max(Math.max(precision, 3), projInfo.defaultDecimalsShown)) + : e.gte(10000) + ? commaFormat(e, 0) + : e.toStringWithDecimalPlaces(0); + if (mantissa) { + return m.toStringWithDecimalPlaces(precision) + "e" + eString; + } else { + return "e" + eString; + } +} + +export function commaFormat(num: DecimalSource, precision: number): string { + if (num === null || num === undefined) { + return "NaN"; + } + num = new Decimal(num); + if (num.mag < 0.001) { + return (0).toFixed(precision); + } + const init = num.toStringWithDecimalPlaces(precision); + const portions = init.split("."); + portions[0] = portions[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"); + if (portions.length == 1) return portions[0]; + return portions[0] + "." + portions[1]; +} + +export function regularFormat(num: DecimalSource, precision: number): string { + if (num === null || num === undefined) { + return "NaN"; + } + num = new Decimal(num); + if (num.mag < 0.0001) { + return (0).toFixed(precision); + } + if (num.mag < 0.1 && precision !== 0) { + precision = Math.max( + Math.max(precision, num.log10().negate().ceil().toNumber()), + projInfo.defaultDecimalsShown + ); + } + return num.toStringWithDecimalPlaces(precision); +} + +const eeee1000 = new Decimal("eeee1000"); +const e100000 = new Decimal("e100000"); +const e1000 = new Decimal("e1000"); +const e9 = new Decimal(1e9); +const e6 = new Decimal(1e6); +const e3 = new Decimal(1e3); +const nearOne = new Decimal(0.98); +const thousandth = new Decimal(0.001); +const zero = new Decimal(0); +export function format(num: DecimalSource, precision?: number, small?: boolean): string { + if (precision == null) precision = projInfo.defaultDecimalsShown; + small = small ?? projInfo.defaultShowSmall; + num = new Decimal(num); + if (isNaN(num.sign) || isNaN(num.layer) || isNaN(num.mag)) { + return "NaN"; + } + if (num.sign < 0) { + return "-" + format(num.neg(), precision); + } + if (num.mag === Number.POSITIVE_INFINITY) { + return "Infinity"; + } + if (num.gte(eeee1000)) { + const slog = num.slog(); + if (slog.gte(e6)) { + return "F" + format(slog.floor()); + } else { + return ( + Decimal.pow(10, slog.sub(slog.floor())).toStringWithDecimalPlaces(3) + + "F" + + commaFormat(slog.floor(), 0) + ); + } + } else if (num.gte(e100000)) { + return exponentialFormat(num, 0, false); + } else if (num.gte(e1000)) { + return exponentialFormat(num, 0); + } else if (num.gte(e9)) { + return exponentialFormat(num, precision); + } else if (num.gte(e3)) { + return commaFormat(num, 0); + } else if (num.gte(thousandth) || !small) { + return regularFormat(num, precision); + } else if (num.eq(zero)) { + return (0).toFixed(precision); + } + + num = invertOOM(num); + if (num.lt(e1000)) { + const val = exponentialFormat(num, precision); + return val.replace(/([^(?:e|F)]*)$/, "-$1"); + } else { + return format(num, precision) + "⁻¹"; + } +} + +export function formatWhole(num: DecimalSource): string { + num = new Decimal(num); + if (num.sign < 0) { + return "-" + formatWhole(num.neg()); + } + if (num.gte(e9)) { + return format(num); + } + if (num.lte(nearOne) && !num.eq(zero)) { + return format(num); + } + return format(num, 0); +} + +export function formatTime(seconds: DecimalSource): string { + if (Decimal.lt(seconds, 0)) { + return "-" + formatTime(Decimal.neg(seconds)); + } + if (Decimal.gt(seconds, 2 ** 51)) { + // integer precision limit + return format(Decimal.div(seconds, 31536000)) + "y"; + } + seconds = new Decimal(seconds).toNumber(); + if (seconds < 60) { + return format(seconds) + "s"; + } else if (seconds < 3600) { + return formatWhole(Math.floor(seconds / 60)) + "m " + format(seconds % 60) + "s"; + } else if (seconds < 86400) { + return ( + formatWhole(Math.floor(seconds / 3600)) + + "h " + + formatWhole(Math.floor(seconds / 60) % 60) + + "m " + + formatWhole(seconds % 60) + + "s" + ); + } else if (seconds < 31536000) { + return ( + formatWhole(Math.floor(seconds / 84600) % 365) + + "d " + + formatWhole(Math.floor(seconds / 3600) % 24) + + "h " + + formatWhole(Math.floor(seconds / 60) % 60) + + "m" + ); + } else { + return ( + formatWhole(Math.floor(seconds / 31536000)) + + "y " + + formatWhole(Math.floor(seconds / 84600) % 365) + + "d " + + formatWhole(Math.floor(seconds / 3600) % 24) + + "h" + ); + } +} + +export function toPlaces(x: DecimalSource, precision: number, maxAccepted: DecimalSource): string { + x = new Decimal(x); + let result = x.toStringWithDecimalPlaces(precision); + if (new Decimal(result).gte(maxAccepted)) { + result = Decimal.sub(maxAccepted, Math.pow(0.1, precision)).toStringWithDecimalPlaces( + precision + ); + } + return result; +} + +// Will also display very small numbers +export function formatSmall(x: DecimalSource, precision?: number): string { + return format(x, precision, true); +} + +export function invertOOM(x: DecimalSource): Decimal { + let e = Decimal.log10(x).ceil(); + const m = Decimal.div(x, Decimal.pow(10, e)); + e = e.neg(); + x = new Decimal(10).pow(e).times(m); + + return x; +} diff --git a/src/util/common.ts b/src/util/common.ts new file mode 100644 index 0000000..d7560dd --- /dev/null +++ b/src/util/common.ts @@ -0,0 +1,27 @@ +export type WithRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }; + +export type ArrayElements<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer S> + ? S + : never; + +// Reference: +// https://stackoverflow.com/questions/7225407/convert-camelcasetext-to-sentence-case-text +export function camelToTitle(camel: string): string { + let title = camel.replace(/([A-Z])/g, " $1"); + title = title.charAt(0).toUpperCase() + title.slice(1); + return title; +} + +export function isFunction<T, S extends ReadonlyArray<unknown>, R>( + functionOrValue: ((...args: S) => T) | R +): functionOrValue is (...args: S) => T { + return typeof functionOrValue === "function"; +} + +export enum Direction { + Up = "Up", + Down = "Down", + Left = "Left", + Right = "Right", + Default = "Up" +} diff --git a/src/util/computed.ts b/src/util/computed.ts new file mode 100644 index 0000000..8a9ad62 --- /dev/null +++ b/src/util/computed.ts @@ -0,0 +1,57 @@ +import type { JSXFunction } from "features/feature"; +import { isFunction } from "util/common"; +import type { Ref } from "vue"; +import { computed } from "vue"; + +export const DoNotCache = Symbol("DoNotCache"); + +export type Computable<T> = T | Ref<T> | (() => T); +export type ProcessedComputable<T> = T | Ref<T>; +export type GetComputableType<T> = T extends { [DoNotCache]: true } + ? T + : T extends () => infer S + ? Ref<S> + : undefined extends T + ? undefined + : T; +export type GetComputableTypeWithDefault<T, S> = undefined extends T + ? S + : GetComputableType<NonNullable<T>>; +export type UnwrapComputableType<T> = T extends Ref<infer S> ? S : T extends () => infer S ? S : T; + +export type ComputableKeysOf<T> = Pick< + T, + { + [K in keyof T]: T[K] extends Computable<unknown> ? K : never; + }[keyof T] +>; + +// TODO fix the typing of this function, such that casting isn't necessary and can be used to +// detect if a createX function is validly written +export function processComputable<T, S extends keyof ComputableKeysOf<T>>( + obj: T, + key: S +): asserts obj is T & { [K in S]: ProcessedComputable<UnwrapComputableType<T[S]>> } { + const computable = obj[key]; + if ( + isFunction(computable) && + computable.length === 0 && + !(computable as unknown as JSXFunction)[DoNotCache] + ) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + obj[key] = computed(computable.bind(obj)); + } else if (isFunction(computable)) { + obj[key] = computable.bind(obj) as unknown as T[S]; + (obj[key] as unknown as JSXFunction)[DoNotCache] = true; + } +} + +export function convertComputable<T>(obj: Computable<T>): ProcessedComputable<T> { + if (isFunction(obj) && !(obj as unknown as JSXFunction)[DoNotCache]) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + obj = computed(obj); + } + return obj as ProcessedComputable<T>; +} diff --git a/src/util/proxies.ts b/src/util/proxies.ts new file mode 100644 index 0000000..174378b --- /dev/null +++ b/src/util/proxies.ts @@ -0,0 +1,82 @@ +import type { Persistent } from "game/persistence"; +import { NonPersistent } from "game/persistence"; +import Decimal from "util/bignum"; + +export const ProxyState = Symbol("ProxyState"); +export const ProxyPath = Symbol("ProxyPath"); + +export type ProxiedWithState<T> = NonNullable<T> extends Record<PropertyKey, unknown> + ? NonNullable<T> extends Decimal + ? T + : { + [K in keyof T]: ProxiedWithState<T[K]>; + } & { + [ProxyState]: T; + [ProxyPath]: string[]; + } + : T; + +export type Proxied<T> = NonNullable<T> extends Record<PropertyKey, unknown> + ? NonNullable<T> extends Persistent<infer S> + ? NonPersistent<S> + : NonNullable<T> extends Decimal + ? T + : { + [K in keyof T]: Proxied<T[K]>; + } & { + [ProxyState]: T; + } + : T; + +// Takes a function that returns an object and pretends to be that object +// Note that the object is lazily calculated +export function createLazyProxy<T extends object, S extends T>( + objectFunc: (baseObject: S) => T & S, + baseObject: S = {} as S +): T { + const obj: S & Partial<T> = baseObject; + let calculated = false; + function calculateObj(): T { + if (!calculated) { + Object.assign(obj, objectFunc(obj)); + calculated = true; + } + return obj as S & T; + } + + return new Proxy(obj, { + get(target, key) { + if (key === ProxyState) { + return calculateObj(); + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const val = (calculateObj() as any)[key]; + if (val != null && typeof val === "object" && NonPersistent in val) { + return val[NonPersistent]; + } + return val; + }, + set(target, key, value) { + // TODO give warning about this? It should only be done with caution + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (calculateObj() as any)[key] = value; + return true; + }, + has(target, key) { + if (key === ProxyState) { + return true; + } + return Reflect.has(calculateObj(), key); + }, + ownKeys() { + return Reflect.ownKeys(calculateObj()); + }, + getOwnPropertyDescriptor(target, key) { + if (!calculated) { + Object.assign(obj, objectFunc(obj)); + calculated = true; + } + return Object.getOwnPropertyDescriptor(target, key); + } + }) as S & T; +} diff --git a/src/util/save.ts b/src/util/save.ts new file mode 100644 index 0000000..4137e5b --- /dev/null +++ b/src/util/save.ts @@ -0,0 +1,161 @@ +import projInfo from "data/projInfo.json"; +import { globalBus } from "game/events"; +import type { Player } from "game/player"; +import player, { stringifySave } from "game/player"; +import settings, { loadSettings } from "game/settings"; +import LZString from "lz-string"; +import { ref } from "vue"; + +export function setupInitialStore(player: Partial<Player> = {}): Player { + return Object.assign( + { + id: `${projInfo.id}-0`, + name: "Default Save", + tabs: projInfo.initialTabs.slice(), + time: Date.now(), + autosave: true, + offlineProd: true, + offlineTime: 0, + timePlayed: 0, + keepGoing: false, + modID: projInfo.id, + modVersion: projInfo.versionNumber, + layers: {} + }, + player + ) as Player; +} + +export function save(playerData?: Player): string { + const stringifiedSave = LZString.compressToUTF16(stringifySave(playerData ?? player)); + localStorage.setItem((playerData ?? player).id, stringifiedSave); + return stringifiedSave; +} + +export async function load(): Promise<void> { + // Load global settings + loadSettings(); + + try { + let save = localStorage.getItem(settings.active); + if (save == null) { + await loadSave(newSave()); + return; + } + if (save[0] === "{") { + // plaintext. No processing needed + } else if (save[0] === "e") { + // Assumed to be base64, which starts with e + save = decodeURIComponent(escape(atob(save))); + } else if (save[0] === "ᯡ") { + // Assumed to be lz, which starts with ᯡ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + save = LZString.decompressFromUTF16(save)!; + } else { + throw `Unable to determine save encoding`; + } + const player = JSON.parse(save); + if (player.modID !== projInfo.id) { + await loadSave(newSave()); + return; + } + player.id = settings.active; + await loadSave(player); + } catch (e) { + console.error("Failed to load save. Falling back to new save.\n", e); + await loadSave(newSave()); + } +} + +export function newSave(): Player { + const id = getUniqueID(); + const player = setupInitialStore({ id }); + save(player); + + settings.saves.push(id); + + return player; +} + +export function getUniqueID(): string { + let id, + i = 0; + do { + id = `${projInfo.id}-${i++}`; + } while (localStorage.getItem(id) != null); + return id; +} + +export const loadingSave = ref(false); + +export async function loadSave(playerObj: Partial<Player>): Promise<void> { + console.info("Loading save", playerObj); + loadingSave.value = true; + const { layers, removeLayer, addLayer } = await import("game/layers"); + const { fixOldSave, getInitialLayers } = await import("data/projEntry"); + + for (const layer in layers) { + const l = layers[layer]; + if (l) { + removeLayer(l); + } + } + getInitialLayers(playerObj).forEach(layer => addLayer(layer, playerObj)); + + playerObj = setupInitialStore(playerObj); + if ( + playerObj.offlineProd && + playerObj.time != null && + playerObj.time && + playerObj.devSpeed !== 0 + ) { + if (playerObj.offlineTime == undefined) playerObj.offlineTime = 0; + playerObj.offlineTime += Math.min( + playerObj.offlineTime + (Date.now() - playerObj.time) / 1000, + projInfo.offlineLimit * 3600 + ); + } + playerObj.time = Date.now(); + if (playerObj.modVersion !== projInfo.versionNumber) { + fixOldSave(playerObj.modVersion, playerObj); + playerObj.modVersion = projInfo.versionNumber; + } + + Object.assign(player, playerObj); + settings.active = player.id; + + globalBus.emit("onLoad"); +} + +setInterval(() => { + if (player.autosave) { + save(); + } +}, 1000); +window.onbeforeunload = () => { + if (player.autosave) { + save(); + } +}; + +declare global { + /** + * Augment the window object so the save, hard reset, and deleteLowerSaves functions can be accessed from the console. + */ + interface Window { + save: VoidFunction; + hardReset: VoidFunction; + deleteLowerSaves: VoidFunction; + } +} +window.save = save; +export const hardReset = (window.hardReset = async () => { + await loadSave(newSave()); +}); +export const deleteLowerSaves = (window.deleteLowerSaves = () => { + const index = Object.values(settings.saves).indexOf(player.id) + 1; + Object.values(settings.saves) + .slice(index) + .forEach(id => localStorage.removeItem(id)); + settings.saves = settings.saves.slice(0, index); +}); diff --git a/src/util/vue.tsx b/src/util/vue.tsx new file mode 100644 index 0000000..a3897a5 --- /dev/null +++ b/src/util/vue.tsx @@ -0,0 +1,243 @@ +import Col from "components/layout/Column.vue"; +import Row from "components/layout/Row.vue"; +import type { CoercableComponent, GenericComponent, JSXFunction } from "features/feature"; +import { + Component as ComponentKey, + GatherProps, + isVisible, + jsx, + Visibility +} from "features/feature"; +import type { ProcessedComputable } from "util/computed"; +import { DoNotCache } from "util/computed"; +import type { Component, ComputedRef, DefineComponent, PropType, Ref, ShallowRef } from "vue"; +import { + computed, + defineComponent, + isRef, + onUnmounted, + ref, + shallowRef, + unref, + watchEffect +} from "vue"; + +export function coerceComponent( + component: CoercableComponent, + defaultWrapper = "span" +): DefineComponent { + if (typeof component === "function") { + return defineComponent({ render: component }); + } + if (typeof component === "string") { + if (component.length > 0) { + component = component.trim(); + if (component.charAt(0) !== "<") { + component = `<${defaultWrapper}>${component}</${defaultWrapper}>`; + } + + return defineComponent({ template: component }); + } + return defineComponent({ render: () => ({}) }); + } + return component; +} + +export interface VueFeature { + [ComponentKey]: GenericComponent; + [GatherProps]: () => Record<string, unknown>; +} + +export function render(object: VueFeature | CoercableComponent): JSX.Element | DefineComponent { + if (isCoercableComponent(object)) { + if (typeof object === "function") { + return (object as JSXFunction)(); + } + return coerceComponent(object); + } + const Component = object[ComponentKey]; + return <Component {...object[GatherProps]()} />; +} + +export function renderRow(...objects: (VueFeature | CoercableComponent)[]): JSX.Element { + return <Row>{objects.map(render)}</Row>; +} + +export function renderCol(...objects: (VueFeature | CoercableComponent)[]): JSX.Element { + return <Col>{objects.map(render)}</Col>; +} + +export function renderJSX(object: VueFeature | CoercableComponent): JSX.Element { + if (isCoercableComponent(object)) { + if (typeof object === "function") { + return (object as JSXFunction)(); + } + if (typeof object === "string") { + return <>{object}</>; + } + // TODO why is object typed as never? + const Comp = object as DefineComponent; + return <Comp />; + } + const Component = object[ComponentKey]; + return <Component {...object[GatherProps]()} />; +} + +export function renderRowJSX(...objects: (VueFeature | CoercableComponent)[]): JSX.Element { + return <Row>{objects.map(renderJSX)}</Row>; +} + +export function renderColJSX(...objects: (VueFeature | CoercableComponent)[]): JSX.Element { + return <Col>{objects.map(renderJSX)}</Col>; +} + +export function joinJSX(objects: JSX.Element[], joiner: JSX.Element): JSX.Element { + return objects.reduce((acc, curr) => ( + <> + {acc} + {joiner} + {curr} + </> + )); +} + +export function isCoercableComponent(component: unknown): component is CoercableComponent { + if (typeof component === "string") { + return true; + } else if (typeof component === "object") { + if (component == null) { + return false; + } + return "render" in component || "component" in component; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + } else if (typeof component === "function" && (component as any)[DoNotCache] === true) { + return true; + } + return false; +} + +export function setupHoldToClick( + onClick?: Ref<((e?: MouseEvent | TouchEvent) => void) | undefined>, + onHold?: Ref<VoidFunction | undefined> +): { + start: (e: MouseEvent | TouchEvent) => void; + stop: VoidFunction; + handleHolding: VoidFunction; +} { + const interval = ref<NodeJS.Timer | null>(null); + const event = ref<MouseEvent | TouchEvent | undefined>(undefined); + + function start(e: MouseEvent | TouchEvent) { + if (!interval.value) { + interval.value = setInterval(handleHolding, 250); + } + event.value = e; + } + function stop() { + if (interval.value) { + clearInterval(interval.value); + interval.value = null; + } + } + function handleHolding() { + if (onHold && onHold.value) { + onHold.value(); + } else if (onClick && onClick.value) { + onClick.value(event.value); + } + } + + onUnmounted(stop); + + return { start, stop, handleHolding }; +} + +export function getFirstFeature< + T extends VueFeature & { visibility: ProcessedComputable<Visibility | boolean> } +>( + features: T[], + filter: (feature: T) => boolean +): { + firstFeature: Ref<T | undefined>; + collapsedContent: JSXFunction; + hasCollapsedContent: Ref<boolean>; +} { + const filteredFeatures = computed(() => + features.filter(feature => isVisible(feature.visibility) && filter(feature)) + ); + return { + firstFeature: computed(() => filteredFeatures.value[0]), + collapsedContent: jsx(() => renderCol(...filteredFeatures.value.slice(1))), + hasCollapsedContent: computed(() => filteredFeatures.value.length > 1) + }; +} + +export function computeComponent( + component: Ref<ProcessedComputable<CoercableComponent>>, + defaultWrapper = "div" +): ShallowRef<Component | ""> { + const comp = shallowRef<Component | "">(); + watchEffect(() => { + comp.value = coerceComponent(unwrapRef(component), defaultWrapper); + }); + return comp as ShallowRef<Component | "">; +} +export function computeOptionalComponent( + component: Ref<ProcessedComputable<CoercableComponent | undefined> | undefined>, + defaultWrapper = "div" +): ShallowRef<Component | "" | null> { + const comp = shallowRef<Component | "" | null>(null); + watchEffect(() => { + const currComponent = unwrapRef(component); + comp.value = + currComponent == "" || currComponent == null + ? null + : coerceComponent(currComponent, defaultWrapper); + }); + return comp; +} + +export function wrapRef<T>(ref: Ref<ProcessedComputable<T>>): ComputedRef<T> { + return computed(() => unwrapRef(ref)); +} + +export function unwrapRef<T>(ref: Ref<ProcessedComputable<T>>): T { + return unref<T>(unref(ref)); +} + +export function setRefValue<T>(ref: Ref<T | Ref<T>>, value: T) { + if (isRef(ref.value)) { + ref.value.value = value; + } else { + ref.value = value; + } +} + +export type PropTypes = + | typeof Boolean + | typeof String + | typeof Number + | typeof Function + | typeof Object + | typeof Array; +// TODO Unfortunately, the typescript engine gives up on typing completely when you use this method, +// Even though it has the same typing as when doing it manually +export function processedPropType<T>(...types: PropTypes[]): PropType<ProcessedComputable<T>> { + if (!types.includes(Object)) { + types.push(Object); + } + return types as PropType<ProcessedComputable<T>>; +} + +export function trackHover(element: VueFeature): Ref<boolean> { + const isHovered = ref(false); + + const elementGatherProps = element[GatherProps].bind(element); + element[GatherProps] = () => ({ + ...elementGatherProps(), + onPointerenter: () => (isHovered.value = true), + onPointerleave: () => (isHovered.value = false) + }); + + return isHovered; +} diff --git a/tests/game/formulas.test.ts b/tests/game/formulas.test.ts new file mode 100644 index 0000000..ddc0bee --- /dev/null +++ b/tests/game/formulas.test.ts @@ -0,0 +1,1012 @@ +import { createResource, Resource } from "features/resources/resource"; +import Formula, { + calculateCost, + calculateMaxAffordable, + GenericFormula, + InvertibleFormula, + unrefFormulaSource +} from "game/formulas"; +import Decimal, { DecimalSource } from "util/bignum"; +import { beforeAll, describe, expect, test } from "vitest"; +import { ref } from "vue"; +import "../utils"; + +type FormulaFunctions = keyof GenericFormula & keyof typeof Formula & keyof typeof Decimal; + +const testValues = ["-1e400", 0, 0.25] as const; + +const invertibleZeroParamFunctionNames = [ + "neg", + "recip", + "log10", + "log2", + "ln", + "pow10", + "exp", + "sqr", + "sqrt", + "cube", + "cbrt", + "lambertw", + "ssqrt", + "sin", + "cos", + "tan", + "asin", + "acos", + "atan", + "sinh", + "cosh", + "tanh", + "asinh", + "acosh", + "atanh" +] as const; +const nonInvertibleZeroParamFunctionNames = [ + "abs", + "sign", + "round", + "floor", + "ceil", + "trunc", + "pLog10", + "absLog10", + "factorial", + "gamma", + "lngamma" +] as const; +const integrableZeroParamFunctionNames = [ + "neg", + "recip", + "log10", + "log2", + "ln", + "pow10", + "exp", + "sqr", + "sqrt", + "cube", + "cbrt", + "sin", + "cos", + "tan", + "asin", + "acos", + "atan", + "sinh", + "cosh", + "tanh", + "asinh", + "acosh", + "atanh" +] as const; +const nonIntegrableZeroParamFunctionNames = [ + ...nonInvertibleZeroParamFunctionNames, + "lambertw", + "ssqrt" +] as const; +const invertibleIntegralZeroPramFunctionNames = [ + "recip", + "log10", + "log2", + "ln", + "pow10", + "sqr", + "sqrt", + "cube", + "cbrt" +] as const; +const nonInvertibleIntegralZeroPramFunctionNames = [ + ...nonIntegrableZeroParamFunctionNames, + "neg", + "exp", + "sin", + "cos", + "tan", + "asin", + "acos", + "atan", + "sinh", + "cosh", + "tanh", + "asinh", + "acosh", + "atanh" +] as const; + +const invertibleOneParamFunctionNames = [ + "add", + "sub", + "mul", + "div", + "log", + "pow", + "root", + "slog" +] as const; +const nonInvertibleOneParamFunctionNames = ["layeradd10"] as const; +const integrableOneParamFunctionNames = ["add", "sub", "mul", "div", "log", "pow", "root"] as const; +const nonIntegrableOneParamFunctionNames = [...nonInvertibleOneParamFunctionNames, "slog"] as const; +const invertibleIntegralOneParamFunctionNames = integrableOneParamFunctionNames; +const nonInvertibleIntegralOneParamFunctionNames = nonIntegrableOneParamFunctionNames; + +const invertibleTwoParamFunctionNames = ["tetrate", "layeradd", "iteratedexp"] as const; +const nonInvertibleTwoParamFunctionNames = ["iteratedlog", "pentate"] as const; +const nonIntegrableTwoParamFunctionNames = [ + ...invertibleTwoParamFunctionNames, + ...nonInvertibleZeroParamFunctionNames +]; +const nonInvertibleIntegralTwoParamFunctionNames = nonIntegrableTwoParamFunctionNames; + +describe("Formula Equality Checking", () => { + describe("Equality Checks", () => { + test("Equals", () => Formula.add(1, 1).equals(Formula.add(1, 1))); + test("Not Equals due to inputs", () => Formula.add(1, 1).equals(Formula.add(1, 0))); + test("Not Equals due to functions", () => Formula.add(1, 1).equals(Formula.sub(1, 1))); + test("Not Equals due to hasVariable", () => + Formula.constant(1).equals(Formula.variable(1))); + }); + + describe("Formula aliases", () => { + function testAliases<T extends FormulaFunctions>( + aliases: T[], + args: Parameters<typeof Formula[T]> + ) { + describe(aliases[0], () => { + let formula: GenericFormula; + beforeAll(() => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + formula = Formula[aliases[0]](...args); + }); + + aliases.slice(1).forEach(alias => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + test(alias, () => expect(Formula[alias](...args).equals(formula)).toBe(true)); + }); + }); + } + testAliases(["neg", "negate", "negated"], [1]); + testAliases(["recip", "reciprocal", "reciprocate"], [1]); + testAliases(["sign", "sgn"], [1]); + testAliases(["add", "plus"], [1, 1]); + testAliases(["sub", "subtract", "minus"], [1, 1]); + testAliases(["mul", "multiply", "times"], [1, 1]); + testAliases(["div", "divide"], [1, 1]); + testAliases(["log", "logarithm"], [1, 1]); + }); + + describe("Instance vs Static methods", () => { + let formula: GenericFormula; + beforeAll(() => { + formula = Formula.constant(10); + }); + [...invertibleZeroParamFunctionNames, ...nonInvertibleZeroParamFunctionNames].forEach( + name => { + test(name, () => { + const instanceFormula = formula[name](); + const staticFormula = Formula[name](formula); + expect(instanceFormula.equals(staticFormula)).toBe(true); + }); + } + ); + + [...invertibleOneParamFunctionNames, ...nonInvertibleOneParamFunctionNames].forEach( + name => { + test(name, () => { + const instanceFormula = formula[name](10); + const staticFormula = Formula[name](formula, 10); + expect(instanceFormula.equals(staticFormula)).toBe(true); + }); + } + ); + + [...invertibleTwoParamFunctionNames, ...nonInvertibleTwoParamFunctionNames].forEach( + name => { + test(name, () => { + const instanceFormula = formula[name](1, 1); + const staticFormula = Formula[name](formula, 1, 1); + expect(instanceFormula.equals(staticFormula)).toBe(true); + }); + } + ); + }); +}); + +describe("Creating Formulas", () => { + describe("Constants", () => { + function testConstant( + desc: string, + formulaFunc: () => InvertibleFormula, + expectedValue: DecimalSource = 10 + ) { + describe(desc, () => { + let formula: GenericFormula; + beforeAll(() => { + formula = formulaFunc(); + }); + test("Is not invertible", () => expect(formula.isInvertible()).toBe(false)); + test("Is not integrable", () => expect(formula.isIntegrable()).toBe(false)); + test("Integral is not invertible", () => + expect(formula.isIntegralInvertible()).toBe(false)); + test("Is not marked as having a variable", () => + expect(formula.hasVariable()).toBe(false)); + test("Evaluates correctly", () => + expect(formula.evaluate()).compare_tolerance(expectedValue)); + test("Invert throws", () => expect(() => formula.invert(25)).toThrow()); + test("Integrate throws", () => expect(() => formula.evaluateIntegral()).toThrow()); + test("Invert integral throws", () => + expect(() => formula.invertIntegral(25)).toThrow()); + }); + } + testConstant("number", () => Formula.constant(10)); + testConstant("string", () => Formula.constant("10")); + testConstant("decimal", () => Formula.constant(new Decimal("1e400")), "1e400"); + testConstant("ref", () => Formula.constant(ref(10))); + }); + + function checkFormula<T extends FormulaFunctions>( + functionName: T, + args: Readonly<Parameters<typeof Formula[T]>> + ) { + let formula: GenericFormula; + beforeAll(() => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + formula = Formula[functionName](...args); + }); + // None of these formulas have variables, so they should all behave the same + test("Is not marked as having a variable", () => expect(formula.hasVariable()).toBe(false)); + test("Is not invertible", () => expect(formula.isInvertible()).toBe(false)); + test(`Formula throws if trying to invert`, () => + expect(() => formula.invert(10)).toThrow()); + test("Is not integrable", () => expect(formula.isIntegrable()).toBe(false)); + test("Has a non-invertible integral", () => + expect(formula.isIntegralInvertible()).toBe(false)); + } + + // Utility function that will test all the different + // It's a lot of tests, but I'd rather be exhaustive + function testFormulaCall<T extends FormulaFunctions>( + functionName: T, + args: Readonly<Parameters<typeof Formula[T]>> + ) { + let testName = functionName + "("; + for (let i = 0; i < args.length; i++) { + if (i !== 0) { + testName += ", "; + } + testName += args[i]; + } + testName += ") evaluates correctly"; + test(testName, () => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const formula = Formula[functionName](...args); + + try { + const expectedEvaluation = Decimal[functionName]( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + ...args.map(i => unrefFormulaSource(i)) + ); + if (expectedEvaluation != null) { + expect(formula.evaluate()).compare_tolerance(expectedEvaluation); + } + } catch { + // If this is an invalid Decimal operation, then ignore this test case + } + }); + } + + describe("0-param", () => { + [...invertibleZeroParamFunctionNames, ...nonInvertibleZeroParamFunctionNames].forEach( + names => + describe(names, () => { + checkFormula(names, [0] as const); + testValues.forEach(i => testFormulaCall(names, [i] as const)); + }) + ); + }); + describe("1-param", () => { + ( + [ + ...invertibleOneParamFunctionNames, + ...nonInvertibleOneParamFunctionNames, + "max", + "min", + "maxabs", + "minabs", + "clampMin", + "clampMax" + ] as const + ).forEach(names => + describe(names, () => { + checkFormula(names, [0, 0] as const); + testValues.forEach(i => + testValues.forEach(j => testFormulaCall(names, [i, j] as const)) + ); + }) + ); + }); + describe("2-param", () => { + ( + [ + ...invertibleTwoParamFunctionNames, + ...nonInvertibleTwoParamFunctionNames, + "clamp" + ] as const + ).forEach(names => + describe(names, () => { + checkFormula(names, [0, 0, 0] as const); + testValues.forEach(i => + testValues.forEach(j => + testValues.forEach(k => testFormulaCall(names, [i, j, k] as const)) + ) + ); + }) + ); + }); +}); + +describe("Variables", () => { + let variable: GenericFormula; + let constant: GenericFormula; + beforeAll(() => { + variable = Formula.variable(10); + constant = Formula.constant(10); + }); + + test("Created variable is marked as a variable", () => + expect(variable.hasVariable()).toBe(true)); + test("evaluate() returns variable's value", () => + expect(variable.evaluate()).compare_tolerance(10)); + test("evaluate(variable) overrides variable value", () => + expect(variable.add(10).evaluate(20)).compare_tolerance(30)); + + test("Nested variable is marked as having a variable", () => + expect(variable.add(10).div(3).pow(2).hasVariable()).toBe(true)); + test("Nested non-variable is marked as not having a variable", () => + expect(constant.add(10).div(3).pow(2).hasVariable()).toBe(false)); +}); + +describe("Inverting", () => { + let variable: GenericFormula; + let constant: GenericFormula; + beforeAll(() => { + variable = Formula.variable(10); + constant = Formula.constant(10); + }); + + test("variable.invert() is pass-through", () => + expect(variable.invert(100)).compare_tolerance(100)); + + describe("Invertible Formulas correctly calculate when they contain a variable", () => { + function checkFormula(formula: GenericFormula, expectedBool = true) { + expect(formula.isInvertible()).toBe(expectedBool); + expect(formula.hasVariable()).toBe(expectedBool); + } + invertibleZeroParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var) is marked as invertible and having a variable`, () => + checkFormula(Formula[name](variable))); + }); + }); + invertibleOneParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var, const) is marked as invertible and having a variable`, () => + checkFormula(Formula[name](variable, constant))); + test(`${name}(const, var) is marked as invertible and having a variable`, () => + checkFormula(Formula[name](constant, variable))); + test(`${name}(var, var) is marked as not invertible and not having a variable`, () => + checkFormula(Formula[name](variable, variable), false)); + }); + }); + invertibleTwoParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var, const, const) is marked as invertible and having a variable`, () => + checkFormula(Formula[name](variable, constant, constant))); + test(`${name}(const, var, const) is marked as invertible and having a variable`, () => + checkFormula(Formula[name](constant, variable, constant))); + test(`${name}(const, const, var) is marked as invertible and having a variable`, () => + checkFormula(Formula[name](constant, constant, variable))); + test(`${name}(var, var, const) is marked as not invertible and not having a variable`, () => + checkFormula(Formula[name](variable, variable, constant), false)); + test(`${name}(var, const, var) is marked as not invertible and not having a variable`, () => + checkFormula(Formula[name](variable, constant, variable), false)); + test(`${name}(const, var, var) is marked as not invertible and not having a variable`, () => + checkFormula(Formula[name](constant, variable, variable), false)); + test(`${name}(var, var, var) is marked as not invertible and not having a variable`, () => + checkFormula(Formula[name](variable, variable, variable), false)); + }); + }); + }); + + describe("Non-invertible formulas marked as such", () => { + function checkFormula(formula: GenericFormula) { + expect(formula.isInvertible()).toBe(false); + expect(formula.isIntegrable()).toBe(false); + expect(formula.isIntegralInvertible()).toBe(false); + } + nonInvertibleZeroParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var) is marked as not invertible`, () => + checkFormula(Formula[name](variable))); + }); + }); + nonInvertibleOneParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var, const) is marked as not invertible`, () => + checkFormula(Formula[name](variable, constant))); + test(`${name}(const, var) is marked as not invertible`, () => + checkFormula(Formula[name](constant, variable))); + test(`${name}(var, var) is marked as not invertible`, () => + checkFormula(Formula[name](variable, variable))); + }); + }); + nonInvertibleTwoParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var, const, const) is marked as not invertible`, () => + checkFormula(Formula[name](variable, constant, constant))); + test(`${name}(const, var, const) is marked as not invertible`, () => + checkFormula(Formula[name](constant, variable, constant))); + test(`${name}(const, const, var) is marked as not invertible`, () => + checkFormula(Formula[name](constant, constant, variable))); + test(`${name}(var, var, const) is marked as not invertible`, () => + checkFormula(Formula[name](variable, variable, constant))); + test(`${name}(var, const, var) is marked as not invertible`, () => + checkFormula(Formula[name](variable, constant, variable))); + test(`${name}(const, var, var) is marked as not invertible`, () => + checkFormula(Formula[name](constant, variable, variable))); + test(`${name}(var, var, var) is marked as not invertible`, () => + checkFormula(Formula[name](variable, variable, variable))); + }); + }); + }); + + describe("Inverting calculates the value of the variable", () => { + let variable: GenericFormula; + let constant: GenericFormula; + beforeAll(() => { + variable = Formula.variable(2); + constant = Formula.constant(3); + }); + invertibleOneParamFunctionNames.forEach(name => + describe(name, () => { + test(`${name}(var, const).invert()`, () => { + const formula = Formula[name](variable, constant); + const result = formula.evaluate(); + expect(formula.invert(result)).compare_tolerance(2); + }); + test(`${name}(const, var).invert()`, () => { + const formula = Formula[name](constant, variable); + const result = formula.evaluate(); + expect(formula.invert(result)).compare_tolerance(2); + }); + }) + ); + invertibleTwoParamFunctionNames.forEach(name => + describe(name, () => { + test(`${name}(var, const, const).invert()`, () => { + const formula = Formula[name](variable, constant, constant); + const result = formula.evaluate(); + expect(formula.invert(result)).compare_tolerance(2); + }); + test(`${name}(const, var, const).invert()`, () => { + const formula = Formula[name](constant, variable, constant); + const result = formula.evaluate(); + expect(formula.invert(result)).compare_tolerance(2); + }); + test(`${name}(const, const, var).invert()`, () => { + const formula = Formula[name](constant, constant, variable); + const result = formula.evaluate(); + expect(formula.invert(result)).compare_tolerance(2); + }); + }) + ); + }); + + describe("Inverting pass-throughs", () => { + test("max", () => expect(Formula.max(variable, constant).invert(10)).compare_tolerance(10)); + test("min", () => expect(Formula.min(variable, constant).invert(10)).compare_tolerance(10)); + test("minabs", () => + expect(Formula.minabs(variable, constant).invert(10)).compare_tolerance(10)); + test("maxabs", () => + expect(Formula.maxabs(variable, constant).invert(10)).compare_tolerance(10)); + test("clampMax", () => + expect(Formula.clampMax(variable, constant).invert(10)).compare_tolerance(10)); + test("clampMin", () => + expect(Formula.clampMin(variable, constant).invert(10)).compare_tolerance(10)); + test("clamp", () => + expect(Formula.clamp(variable, constant, constant).invert(10)).compare_tolerance(10)); + }); + + test("Inverting nested formulas", () => { + const formula = Formula.add(variable, constant).times(constant); + expect(formula.invert(100)).compare_tolerance(0); + }); + + test("Inverting with non-invertible sections", () => { + const formula = Formula.add(variable, constant.ceil()); + expect(formula.isInvertible()).toBe(true); + expect(formula.invert(10)).compare_tolerance(7); + }); +}); + +describe("Integrating", () => { + let variable: GenericFormula; + let constant: GenericFormula; + beforeAll(() => { + variable = Formula.variable(10); + constant = Formula.constant(10); + }); + + test("evaluateIntegral() returns variable's value", () => + expect(variable.evaluate()).compare_tolerance(10)); + test("evaluateIntegral(variable) overrides variable value", () => + expect(variable.add(10).evaluateIntegral(20)).compare_tolerance(400)); + + describe("Integrable functions marked as such", () => { + function checkFormula(formula: GenericFormula) { + expect(formula.isIntegrable()).toBe(true); + expect(() => formula.evaluateIntegral()).to.not.throw(); + } + integrableZeroParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var) is marked as integrable`, () => + checkFormula(Formula[name](variable))); + }); + }); + integrableOneParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var, const) is marked as integrable`, () => + checkFormula(Formula[name](variable, constant))); + test(`${name}(const, var) is marked as integrable`, () => + checkFormula(Formula[name](constant, variable))); + test(`${name}(var, var) is marked as not integrable`, () => + expect(Formula[name](variable, variable).isIntegrable()).toBe(false)); + }); + }); + }); + + describe("Non-Integrable functions marked as such", () => { + function checkFormula(formula: GenericFormula) { + expect(formula.isIntegrable()).toBe(false); + } + nonIntegrableZeroParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var) is marked as not integrable`, () => + checkFormula(Formula[name](variable))); + }); + }); + nonIntegrableOneParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var, const) is marked as not integrable`, () => + checkFormula(Formula[name](variable, constant))); + test(`${name}(const, var) is marked as not integrable`, () => + checkFormula(Formula[name](constant, variable))); + test(`${name}(var, var) is marked as not integrable`, () => + checkFormula(Formula[name](variable, variable))); + }); + }); + nonIntegrableTwoParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var, const, const) is marked as not integrable`, () => + checkFormula(Formula[name](variable, constant, constant))); + test(`${name}(const, var, const) is marked as not integrable`, () => + checkFormula(Formula[name](constant, variable, constant))); + test(`${name}(const, const, var) is marked as not integrable`, () => + checkFormula(Formula[name](constant, constant, variable))); + test(`${name}(var, var, const) is marked as not integrable`, () => + checkFormula(Formula[name](variable, variable, constant))); + test(`${name}(var, const, var) is marked as not integrable`, () => + checkFormula(Formula[name](variable, constant, variable))); + test(`${name}(const, var, var) is marked as not integrable`, () => + checkFormula(Formula[name](constant, variable, variable))); + test(`${name}(var, var, var) is marked as not integrable`, () => + checkFormula(Formula[name](variable, variable, variable))); + }); + }); + }); + + // TODO I think these tests will require writing at least one known example for every function + describe.todo("Integrable formulas integrate correctly"); + + test("Integrating nested formulas", () => { + const formula = Formula.add(variable, constant).times(constant); + expect(formula.evaluateIntegral()).compare_tolerance(1500); + }); +}); + +describe("Inverting integrals", () => { + let variable: GenericFormula; + let constant: GenericFormula; + beforeAll(() => { + variable = Formula.variable(10); + constant = Formula.constant(10); + }); + + test("variable.invertIntegral() is pass-through", () => + expect(variable.invertIntegral(20)).compare_tolerance(20)); + + describe("Invertible Integral functions marked as such", () => { + function checkFormula(formula: GenericFormula) { + expect(formula.isIntegralInvertible()).toBe(true); + expect(() => formula.invertIntegral(10)).to.not.throw(); + } + invertibleIntegralZeroPramFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var) is marked as having an invertible integral`, () => + checkFormula(Formula[name](variable))); + }); + }); + invertibleIntegralOneParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var, const) is marked as having an invertible integral`, () => + checkFormula(Formula[name](variable, constant))); + test(`${name}(const, var) is marked as having an invertible integral`, () => + checkFormula(Formula[name](constant, variable))); + test(`${name}(var, var) is marked as not having an invertible integral`, () => { + const formula = Formula[name](variable, variable); + expect(formula.isIntegralInvertible()).toBe(false); + expect(() => formula.invertIntegral(10)).to.throw(); + }); + }); + }); + }); + + describe("Non-Invertible integral functions marked as such", () => { + function checkFormula(formula: GenericFormula) { + expect(formula.isIntegralInvertible()).toBe(false); + } + nonInvertibleIntegralZeroPramFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var) is marked as not having an invertible integral`, () => + checkFormula(Formula[name](variable))); + }); + }); + nonInvertibleIntegralOneParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var, const) is marked as not having an invertible integral`, () => + checkFormula(Formula[name](variable, constant))); + test(`${name}(const, var) is marked as not having an invertible integral`, () => + checkFormula(Formula[name](constant, variable))); + test(`${name}(var, var) is marked as not having an invertible integral`, () => + checkFormula(Formula[name](variable, variable))); + }); + }); + nonInvertibleIntegralTwoParamFunctionNames.forEach(name => { + describe(name, () => { + test(`${name}(var, const, const) is marked as not having an invertible integral`, () => + checkFormula(Formula[name](variable, constant, constant))); + test(`${name}(const, var, const) is marked as not having an invertible integral`, () => + checkFormula(Formula[name](constant, variable, constant))); + test(`${name}(const, const, var) is marked as not having an invertible integral`, () => + checkFormula(Formula[name](constant, constant, variable))); + test(`${name}(var, var, const) is marked as not having an invertible integral`, () => + checkFormula(Formula[name](variable, variable, constant))); + test(`${name}(var, const, var) is marked as not having an invertible integral`, () => + checkFormula(Formula[name](variable, constant, variable))); + test(`${name}(const, var, var) is marked as not having an invertible integral`, () => + checkFormula(Formula[name](constant, variable, variable))); + test(`${name}(var, var, var) is marked as not having an invertible integral`, () => + checkFormula(Formula[name](variable, variable, variable))); + }); + }); + }); + + // TODO I think these tests will require writing at least one known example for every function + describe.todo("Invertible Integral formulas invert correctly"); + + test("Inverting integral of nested formulas", () => { + const formula = Formula.add(variable, constant).times(constant); + expect(formula.invertIntegral(1500)).compare_tolerance(10); + }); + + describe("Inverting integral pass-throughs", () => { + test("max", () => + expect(Formula.max(variable, constant).invertIntegral(10)).compare_tolerance(10)); + test("min", () => + expect(Formula.min(variable, constant).invertIntegral(10)).compare_tolerance(10)); + test("minabs", () => + expect(Formula.minabs(variable, constant).invertIntegral(10)).compare_tolerance(10)); + test("maxabs", () => + expect(Formula.maxabs(variable, constant).invertIntegral(10)).compare_tolerance(10)); + test("clampMax", () => + expect(Formula.clampMax(variable, constant).invertIntegral(10)).compare_tolerance(10)); + test("clampMin", () => + expect(Formula.clampMin(variable, constant).invertIntegral(10)).compare_tolerance(10)); + test("clamp", () => + expect( + Formula.clamp(variable, constant, constant).invertIntegral(10) + ).compare_tolerance(10)); + }); +}); + +describe("Step-wise", () => { + let variable: GenericFormula; + let constant: GenericFormula; + beforeAll(() => { + variable = Formula.variable(10); + constant = Formula.constant(10); + }); + + test("Formula without variable is marked as such", () => { + expect(Formula.step(constant, 10, value => Formula.sqrt(value)).isInvertible()).toBe(false); + expect(Formula.step(constant, 10, value => Formula.sqrt(value)).hasVariable()).toBe(false); + }); + + test("Formula with variable is marked as such", () => { + expect(Formula.step(variable, 10, value => Formula.sqrt(value)).isInvertible()).toBe(true); + expect(Formula.step(variable, 10, value => Formula.sqrt(value)).hasVariable()).toBe(true); + }); + + test("Non-invertible formula modifier marks formula as such", () => { + expect(Formula.step(constant, 10, value => Formula.abs(value)).isInvertible()).toBe(false); + expect(Formula.step(constant, 10, value => Formula.abs(value)).hasVariable()).toBe(false); + }); + + test("Formula never marked integrable", () => { + expect(Formula.step(constant, 10, value => Formula.add(value, 10)).isIntegrable()).toBe( + false + ); + expect(() => + Formula.step(constant, 10, value => Formula.add(value, 10)).evaluateIntegral() + ).toThrow(); + }); + + test("Formula never marked as having an invertible integral", () => { + expect( + Formula.step(constant, 10, value => Formula.add(value, 10)).isIntegralInvertible() + ).toBe(false); + expect(() => + Formula.step(constant, 10, value => Formula.add(value, 10)).invertIntegral(10) + ).toThrow(); + }); + + test("Formula modifiers with variables mark formula as non-invertible", () => { + expect( + Formula.step(constant, 10, value => Formula.add(value, variable)).isInvertible() + ).toBe(false); + expect( + Formula.step(constant, 10, value => Formula.add(value, variable)).hasVariable() + ).toBe(false); + }); + + describe("Pass-through underneath start", () => { + test("Evaluates correctly", () => + expect( + Formula.step(constant, 20, value => Formula.sqrt(value)).evaluate() + ).compare_tolerance(10)); + test("Inverts correctly with variable in input", () => + expect( + Formula.step(variable, 20, value => Formula.sqrt(value)).invert(10) + ).compare_tolerance(10)); + }); + + describe("Evaluates correctly beyond start", () => { + test("Evaluates correctly", () => + expect( + Formula.step(variable, 8, value => Formula.add(value, 2)).evaluate() + ).compare_tolerance(12)); + test("Inverts correctly", () => + expect( + Formula.step(variable, 8, value => Formula.add(value, 2)).invert(12) + ).compare_tolerance(10)); + }); +}); + +describe("Conditionals", () => { + let variable: GenericFormula; + let constant: GenericFormula; + beforeAll(() => { + variable = Formula.variable(10); + constant = Formula.constant(10); + }); + + test("Formula without variable is marked as such", () => { + expect(Formula.if(constant, true, value => Formula.sqrt(value)).isInvertible()).toBe(false); + expect(Formula.if(constant, true, value => Formula.sqrt(value)).hasVariable()).toBe(false); + }); + + test("Formula with variable is marked as such", () => { + expect(Formula.if(variable, true, value => Formula.sqrt(value)).isInvertible()).toBe(true); + expect(Formula.if(variable, true, value => Formula.sqrt(value)).hasVariable()).toBe(true); + }); + + test("Non-invertible formula modifier marks formula as such", () => { + expect(Formula.if(constant, true, value => Formula.abs(value)).isInvertible()).toBe(false); + expect(Formula.if(constant, true, value => Formula.abs(value)).hasVariable()).toBe(false); + }); + + test("Formula never marked integrable", () => { + expect(Formula.if(constant, true, value => Formula.add(value, 10)).isIntegrable()).toBe( + false + ); + expect(() => + Formula.if(constant, true, value => Formula.add(value, 10)).evaluateIntegral() + ).toThrow(); + }); + + test("Formula never marked as having an invertible integral", () => { + expect( + Formula.if(constant, true, value => Formula.add(value, 10)).isIntegralInvertible() + ).toBe(false); + expect(() => + Formula.if(constant, true, value => Formula.add(value, 10)).invertIntegral(10) + ).toThrow(); + }); + + test("Formula modifiers with variables mark formula as non-invertible", () => { + expect( + Formula.if(constant, true, value => Formula.add(value, variable)).isInvertible() + ).toBe(false); + expect( + Formula.if(constant, true, value => Formula.add(value, variable)).hasVariable() + ).toBe(false); + }); + + describe("Pass-through with condition false", () => { + test("Evaluates correctly", () => + expect( + Formula.if(constant, false, value => Formula.sqrt(value)).evaluate() + ).compare_tolerance(10)); + test("Inverts correctly with variable in input", () => + expect( + Formula.if(variable, false, value => Formula.sqrt(value)).invert(10) + ).compare_tolerance(10)); + }); + + describe("Evaluates correctly with condition true", () => { + test("Evaluates correctly", () => + expect( + Formula.if(variable, true, value => Formula.add(value, 2)).evaluate() + ).compare_tolerance(12)); + test("Inverts correctly", () => + expect( + Formula.if(variable, true, value => Formula.add(value, 2)).invert(12) + ).compare_tolerance(10)); + }); +}); + +describe("Custom Formulas", () => { + describe("Formula with evaluate", () => { + test("Zero input evaluates correctly", () => + expect(new Formula({ inputs: [], evaluate: () => 10 }).evaluate()).compare_tolerance( + 10 + )); + test("One input evaluates correctly", () => + expect( + new Formula({ inputs: [1], evaluate: value => value }).evaluate() + ).compare_tolerance(1)); + test("Two inputs evaluates correctly", () => + expect( + new Formula({ inputs: [1, 2], evaluate: (v1, v2) => v1 }).evaluate() + ).compare_tolerance(1)); + }); + + describe("Formula with invert", () => { + test("Zero input inverts correctly", () => + expect( + new Formula({ + inputs: [], + evaluate: () => 6, + invert: value => value, + hasVariable: true + }).invert(10) + ).compare_tolerance(10)); + test("One input inverts correctly", () => + expect( + new Formula({ + inputs: [1], + evaluate: () => 10, + invert: (value, v1) => v1, + hasVariable: true + }).invert(10) + ).compare_tolerance(1)); + test("Two inputs inverts correctly", () => + expect( + new Formula({ + inputs: [1, 2], + evaluate: () => 10, + invert: (value, v1, v2) => v2, + hasVariable: true + }).invert(10) + ).compare_tolerance(2)); + }); + + describe("Formula with integrate", () => { + test("Zero input integrates correctly", () => + expect( + new Formula({ + inputs: [], + evaluate: () => 10, + integrate: () => 20 + }).evaluateIntegral() + ).compare_tolerance(20)); + test("One input integrates correctly", () => + expect( + new Formula({ + inputs: [1], + evaluate: () => 10, + integrate: (val, v1) => val ?? 20 + }).evaluateIntegral() + ).compare_tolerance(20)); + test("Two inputs integrates correctly", () => + expect( + new Formula({ + inputs: [1, 2], + evaluate: (v1, v2) => 10, + integrate: (v1, v2) => 3 + }).evaluateIntegral() + ).compare_tolerance(3)); + }); + + describe("Formula with invertIntegral", () => { + test("Zero input inverts integral correctly", () => + expect( + new Formula({ + inputs: [], + evaluate: () => 10, + invertIntegral: () => 1, + hasVariable: true + }).invertIntegral(8) + ).compare_tolerance(1)); + test("One input inverts integral correctly", () => + expect( + new Formula({ + inputs: [1], + evaluate: () => 10, + invertIntegral: (val, v1) => 1, + hasVariable: true + }).invertIntegral(8) + ).compare_tolerance(1)); + test("Two inputs inverts integral correctly", () => + expect( + new Formula({ + inputs: [1, 2], + evaluate: (v1, v2) => 10, + invertIntegral: (v1, v2) => 1, + hasVariable: true + }).invertIntegral(8) + ).compare_tolerance(1)); + }); +}); + +describe("Buy Max", () => { + let resource: Resource; + beforeAll(() => { + resource = createResource(ref(10)); + }); + describe("With spending", () => { + test("Throws on formula with non-invertible integral", () => { + const maxAffordable = calculateMaxAffordable(Formula.neg(10), resource, false); + expect(() => maxAffordable.value).toThrow(); + }); + // https://www.desmos.com/calculator/5vgletdc1p + test("Calculates max affordable and cost correctly", () => { + const variable = Formula.variable(10); + const formula = Formula.pow(1.05, variable); + const maxAffordable = calculateMaxAffordable(formula, resource, false); + expect(maxAffordable.value).compare_tolerance(47); + expect(calculateCost(formula, maxAffordable.value, false)).compare_tolerance( + Decimal.pow(1.05, 47) + ); + }); + }); + describe("Without spending", () => { + test("Throws on non-invertible formula", () => { + const maxAffordable = calculateMaxAffordable(Formula.abs(10), resource); + expect(() => maxAffordable.value).toThrow(); + }); + // https://www.desmos.com/calculator/5vgletdc1p + test("Calculates max affordable and cost correctly", () => { + const variable = Formula.variable(10); + const formula = Formula.pow(1.05, variable); + const maxAffordable = calculateMaxAffordable(formula, resource); + expect(maxAffordable.value).compare_tolerance(7); + expect(calculateCost(formula, maxAffordable.value)).compare_tolerance(7.35); + }); + }); +}); diff --git a/tests/game/requirements.test.ts b/tests/game/requirements.test.ts new file mode 100644 index 0000000..fa9ae5e --- /dev/null +++ b/tests/game/requirements.test.ts @@ -0,0 +1,182 @@ +import { Visibility } from "features/feature"; +import { createResource, Resource } from "features/resources/resource"; +import Formula from "game/formulas"; +import { + createBooleanRequirement, + createCostRequirement, + createVisibilityRequirement, + maxRequirementsMet, + payRequirements, + Requirement, + requirementsMet +} from "game/requirements"; +import { beforeAll, describe, expect, test } from "vitest"; +import { isRef, ref, unref } from "vue"; +import "../utils"; + +describe("Creating cost requirement", () => { + describe("Minimal requirement", () => { + let resource: Resource; + let requirement: Requirement; + beforeAll(() => { + resource = createResource(ref(10)); + requirement = createCostRequirement(() => ({ + resource, + cost: 10 + })); + }); + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + test("resource pass-through", () => expect((requirement as any).resource).toBe(resource)); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + test("cost pass-through", () => expect((requirement as any).cost).toBe(10)); + + test("partialDisplay exists", () => + expect(typeof requirement.partialDisplay).toBe("function")); + test("display exists", () => expect(typeof requirement.display).toBe("function")); + test("pay exists", () => expect(typeof requirement.pay).toBe("function")); + test("requirementMet exists", () => { + expect(requirement.requirementMet).not.toBeNull(); + expect(isRef(requirement.requirementMet)).toBe(true); + }); + test("is visible", () => expect(requirement.visibility).toBe(Visibility.Visible)); + test("requires pay", () => expect(requirement.requiresPay).toBe(true)); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + test("spends resources", () => expect((requirement as any).spendResources).toBe(true)); + test("cannot maximize", () => expect(unref(requirement.canMaximize)).toBe(false)); + }); + + describe("Fully customized", () => { + let resource: Resource; + let requirement: Requirement; + beforeAll(() => { + resource = createResource(ref(10)); + requirement = createCostRequirement(() => ({ + resource, + cost: 10, + visibility: Visibility.None, + requiresPay: false, + maximize: true, + spendResources: false, + // eslint-disable-next-line @typescript-eslint/no-empty-function + pay() {} + })); + }); + + test("pay is empty function", () => + requirement.pay != null && + typeof requirement.pay === "function" && + requirement.pay.length === 1); + test("is not visible", () => expect(requirement.visibility).toBe(Visibility.None)); + test("does not require pay", () => expect(requirement.requiresPay).toBe(false)); + test("does not spend resources", () => + // eslint-disable-next-line @typescript-eslint/no-explicit-any + expect((requirement as any).spendResources).toBe(false)); + test("can maximize", () => expect(unref(requirement.canMaximize)).toBe(true)); + }); + + test("Requirement met when meeting the cost", () => { + const resource = createResource(ref(10)); + const requirement = createCostRequirement(() => ({ + resource, + cost: 10 + })); + expect(unref(requirement.requirementMet)).toBe(true); + }); + + test("Requirement not met when not meeting the cost", () => { + const resource = createResource(ref(10)); + const requirement = createCostRequirement(() => ({ + resource, + cost: 100 + })); + expect(unref(requirement.requirementMet)).toBe(false); + }); +}); + +describe("Creating visibility requirement", () => { + test("Requirement met when visible", () => { + const requirement = createVisibilityRequirement({ visibility: Visibility.Visible }); + expect(unref(requirement.requirementMet)).toBe(true); + }); + + test("Requirement not met when not visible", () => { + let requirement = createVisibilityRequirement({ visibility: Visibility.None }); + expect(unref(requirement.requirementMet)).toBe(false); + requirement = createVisibilityRequirement({ visibility: Visibility.Hidden }); + expect(unref(requirement.requirementMet)).toBe(false); + }); +}); + +describe("Creating boolean requirement", () => { + test("Requirement met when true", () => { + const requirement = createBooleanRequirement(ref(true)); + expect(unref(requirement.requirementMet)).toBe(true); + }); + + test("Requirement not met when false", () => { + const requirement = createBooleanRequirement(ref(false)); + expect(unref(requirement.requirementMet)).toBe(false); + }); +}); + +describe("Checking all requirements met", () => { + let metRequirement: Requirement; + let unmetRequirement: Requirement; + beforeAll(() => { + metRequirement = createBooleanRequirement(true); + unmetRequirement = createBooleanRequirement(false); + }); + + test("Returns true if no requirements", () => { + expect(requirementsMet([])).toBe(true); + }); + + test("Returns true if all requirements met", () => { + expect(requirementsMet([metRequirement, metRequirement])).toBe(true); + }); + + test("Returns false if any requirements unmet", () => { + expect(requirementsMet([metRequirement, unmetRequirement])).toBe(false); + }); +}); + +describe("Checking maximum levels of requirements met", () => { + test("Returns 0 if any requirement is not met", () => { + const requirements = [ + createBooleanRequirement(false), + createBooleanRequirement(true), + createCostRequirement(() => ({ + resource: createResource(ref(10)), + cost: Formula.variable(0) + })) + ]; + expect(maxRequirementsMet(requirements)).compare_tolerance(0); + }); + + test("Returns correct number of requirements met", () => { + const requirements = [ + createBooleanRequirement(true), + createCostRequirement(() => ({ + resource: createResource(ref(10)), + cost: Formula.variable(0) + })) + ]; + expect(maxRequirementsMet(requirements)).compare_tolerance(10); + }); +}); + +test("Paying requirements", () => { + const resource = createResource(ref(100)); + const noPayment = createCostRequirement(() => ({ + resource, + cost: 10, + requiresPay: false + })); + const payment = createCostRequirement(() => ({ + resource, + cost: 10 + })); + payRequirements([noPayment, payment]); + expect(resource.value).compare_tolerance(90); +}); diff --git a/tests/util/common.test.ts b/tests/util/common.test.ts new file mode 100644 index 0000000..619810f --- /dev/null +++ b/tests/util/common.test.ts @@ -0,0 +1,27 @@ +import { camelToTitle, isFunction } from "util/common"; +import { describe, expect, test, vi } from "vitest"; + +describe("camelToTitle", () => { + test("Capitalizes first letter in single word", () => + expect(camelToTitle("test")).toBe("Test")); + + test("Converts three word camel case string to title case", () => + expect(camelToTitle("camelCaseTest")).toBe("Camel Case Test")); +}); + +describe("isFunction", () => { + test("Given function returns true", () => expect(isFunction(vi.fn())).toBe(true)); + + // Go through all primitives and basic types + test("Given a non-function returns false", () => { + expect(isFunction("test")).toBe(false); + expect(isFunction(10)).toBe(false); + expect(isFunction(BigInt(10))).toBe(false); + expect(isFunction(true)).toBe(false); + expect(isFunction(undefined)).toBe(false); + expect(isFunction(Symbol())).toBe(false); + expect(isFunction(null)).toBe(false); + expect(isFunction({})).toBe(false); + expect(isFunction([])).toBe(false); + }); +}); diff --git a/tests/utils.ts b/tests/utils.ts new file mode 100644 index 0000000..0e58e19 --- /dev/null +++ b/tests/utils.ts @@ -0,0 +1,40 @@ +import Decimal, { DecimalSource, format } from "util/bignum"; +import { expect } from "vitest"; + +interface CustomMatchers<R = unknown> { + compare_tolerance(expected: DecimalSource): R; +} + +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace Vi { + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface Assertion extends CustomMatchers {} + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface AsymmetricMatchersContaining extends CustomMatchers {} + } +} + +expect.extend({ + compare_tolerance(received: DecimalSource, expected: DecimalSource) { + const { isNot } = this; + let pass = false; + if (!Decimal.isFinite(expected)) { + pass = !Decimal.isFinite(received); + } else if (Decimal.isNaN(expected)) { + pass = Decimal.isNaN(received); + } else { + pass = Decimal.eq_tolerance(received, expected); + } + return { + // do not alter your "pass" based on isNot. Vitest does it for you + pass, + message: () => + `Expected ${received} to${ + (isNot as boolean) ? " not" : "" + } be close to ${expected}`, + expected: format(expected), + actual: format(received) + }; + } +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..280a1e1 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,50 @@ +{ + "compilerOptions": { + "noErrorTruncation": true, + "target": "esnext", + "module": "esnext", + "strict": true, + "checkJs": false, + "jsx": "preserve", + "importHelpers": true, + "moduleResolution": "node", + "resolveJsonModule": true, + "experimentalDecorators": true, + "allowJs": true, + "skipLibCheck": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "sourceMap": true, + "baseUrl": "src", + "types": [ + "vite/client", + "node" + ], + "lib": [ + "esnext", + "dom", + "dom.iterable", + "scripthost" + ] + }, + "include": [ + "src/**/*.ts", + "src/**/*.tsx", + "src/**/*.vue", + "tests/**/*.ts", + "tests/**/*.tsx" + ], + "exclude": [ + "node_modules" + ], + "typedocOptions": { + "entryPoints": ["src"], + "entryPointStrategy": "expand", + "cleanOutputDir": true, + "name": "Profectus", + "includeVersion": true, + "categorizeByGroup": false, + "readme": "none", + "out": "../docs/api" + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..f3ce360 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,61 @@ +import vue from "@vitejs/plugin-vue"; +import vueJsx from "@vitejs/plugin-vue-jsx"; +import { defineConfig } from "vite"; +import { VitePWA } from "vite-plugin-pwa"; +import tsconfigPaths from "vite-tsconfig-paths"; +import projInfo from "./src/data/projInfo.json"; + +// https://vitejs.dev/config/ +export default defineConfig({ + base: "./", + build: { + rollupOptions: { + output: { + manualChunks(id) { + if (id.includes("node_modules")) { + return id.toString().split("node_modules/")[1].split("/")[0].toString(); + } + } + } + } + }, + resolve: { + alias: { + vue: "vue/dist/vue.esm-bundler.js" + } + }, + plugins: [ + vue(), + vueJsx({ + // options are passed on to @vue/babel-plugin-jsx + }), + tsconfigPaths(), + VitePWA({ + includeAssets: ["Logo.svg", "favicon.ico", "robots.txt", "apple-touch-icon.png"], + manifest: { + name: projInfo.title, + short_name: projInfo.title, + description: projInfo.description, + theme_color: "#2E3440", + icons: [ + { + src: "pwa-192x192.png", + sizes: "192x192", + type: "image/png" + }, + { + src: "pwa-512x512.png", + sizes: "512x512", + type: "image/png" + }, + { + src: "pwa-512x512.png", + sizes: "512x512", + type: "image/png", + purpose: "any maskable" + } + ] + } + }) + ] +}); diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..3ab791b --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,9 @@ +import { mergeConfig } from 'vite' +import { defineConfig } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig(viteConfig, defineConfig({ + test: { + environment: "jsdom" + } +}))